I am not clear about was static and stack allocation are? Is static allocation static and stack allocation dynamic? Then where does heap allocation belong?
How is activation record related to this? I thought activation record is a conceptual thing like activation tree, and does not have any physical existence.
What does the following target machine code mean?
static allocation:
ST callee. staticArea , #here + 20
BR callee. codeArea
stack allocation :
LD SP , #stackStart
code for the first procedure
HALT
ADD SP , SP , #caller. recordSize
ST *SP , #here + 16
BR callee. codeArea
BR *O (SP) // return to caller
SUB SP , SP , #caller. recordSize // decrement stack pointer
Related
I want to ask a question which is confusing to me ,
when I write int x = 0 ; which is a local variable
I know it will be stored in the stack by using stack pointer , but how computer remember that this variable x is stored to this address ?
is that a compiler role or linker role or what happen exactly .
I am trying to implement a custom physical allocation for which I need to modify the allocPhysPages() function in the System class. There is this section of code in that function
AddrRange m5opRange(0xffff0000, 0x100000000);
if (m5opRange.contains(next_return_addr)) {
warn("Reached m5ops MMIO region\n");
return_addr = 0xffffffff;
pagePtr_arr[chiplet_id] = 0xffffffff >> PageShift;
}
My question is can I comment out this section of code which checks if the allocated physical address is in the MMIO region or not. I don't want to take care of the MMIO region to reduce the complexity. If I comment this out then would it lead to any kind of failure during simulation?
Note: allocPhysPages() is located in src/sim/system.cc
Reading some Apple code, I stumbled upon the following C chunk
alloca(sizeof(CMTimeRange) * 3)
is this the same thing as allocation stack memory via
CMTimeRange *p = CMTimeRange[3] ?
Is there any implications on performance? The need to free the memory?
If you really only want to allocate 3 elements of something on the stack the use of alloca makes no sense at all. It only makes sense if you have a variable length that depends on some dynamic parameter at runtime, or if you do an unknown number of such allocations in the same function.
alloca is not a standard function and differs from platform to platform. The C standard has prefered to introduce VLA, variable length arrays as a replacement.
is this the same thing as allocation stack memory via...
I would think not quite. Declaring a local variable causes the memory to be reserved when the stack frame is entered (by subtracting the size of variable from the stack pointer and adjusting for alignment).
It looks like alloca(3) works by adjusting the stack pointer at the moment it is encountered. Note the "Bugs" section of the man page.
alloca() is machine and compiler dependent; its use is discouraged.
alloca() is slightly unsafe because it cannot ensure that the pointer returned points to a valid and usable block of memory. The allocation made may exceed the bounds of the stack, or even go further into other objects in memory, and alloca() cannot determine such an error. Avoid alloca() with large unbounded allocations.
These two points together add up to the following in my opinion:
DO NOT USE ALLOCA
Assuming as Joachim points out you mean CMTimeRange someVariableName[3]...
Both will allocate memory on the stack.
I'm guessing alloca() will have to add extra code after your function prologue to do the allocation... The function prologue is code that the compiler automatically generates for you to create room on the stack. The upshot is that your function may be slightly larger once compiled but not by much... a few extra instructions to modify the stack pointer and possibly stack frame. I guess a compiler could optimize the call out if it wasn't in a conditional branch, or just even lift it outside of a conditional branch though?
I experimented on my MQX compiler with no optimisations... it's not objective-c, just C, also a different platform, but hopefully that's a good enough approximation and does show a difference in emitted code. I used two simple functions with a large array on the stack to make sure stack space had to be used (variable couldn't exist solely in registers).
Obviously it is not advisable to put large arrays on the stack... this is just for demo purposes.
unsigned int TEST1(unsigned int stuff)
{
unsigned int a1[100]; // Make sure it must go on stack
unsigned int a2[100]; // Make sure it must go on stack
a1[0] = 0xdead;
a2[0] = stuff + 10;
return a2[0];
}
unsigned int TEST2(unsigned int stuff)
{
unsigned int a1[100]; // Make sure it must go on stack
unsigned int *a2 = alloca(sizeof(unsigned int)*100);
a1[0] = 0xdead;
a2[0] = stuff + 10;
return a2[0];
}
The following assembler was generated:
TEST1:
Both arrays a1 and a2 are put on the stack in the function prologue...
0: 1cfcb6c8 push %fp
4: 230a3700 mov %fp,%sp
8: 24993901 sub3 %sp,%sp,100 # Both arrays put on stack
c: 7108 mov_s %r1,%r0
e: 1b38bf98 0000dead st 0xdead,[%fp,0xffff_fce0] ; 0xdead
16: e00a add_s %r0,%r0,10
18: 1b9cb018 st %r0,[%fp,0xffff_fe70]
1c: 240a36c0 mov %sp,%fp
20: 1404341b pop %fp
24: 7ee0 j_s [%blink]
TEST2:
Only array a1 is put on the stack in the proglogue... Extra lines of code have to be generated to deal with the alloca.
0: 1cfcb6c8 push %fp
4: 230a3700 mov %fp,%sp
8: 24593c9c sub3 %sp,%sp,50 # Only one array put on stack
c: 240a07c0 mov %r4,%blink
10: 220a0000 mov %r2,%r0
14: 218a0406 mov %r1,0x190 # Extra for alloca()
18: 2402305c sub %sp,%sp,%r1 # Extra for alloca()
1c: 08020000r bl _stkchk # Extra for alloca()
20: 738b mov_s %r3,%sp # Extra, r3 to access write via pointer
22: 1b9cbf98 0000dead st 0xdead,[%fp,0xffff_fe70] ; 0xdead
2a: 22400280 add %r0,%r2,10
2e: a300 st_s %r0,[%r3] # r3 to access write via pointer
30: 270a3100 mov %blink,%r4
34: 240a36c0 mov %sp,%fp
38: 1404341b pop %fp
3c: 7ee0 j_s [%blink]
Also you alloca() memory will be accessed through pointers (unless there are clever compiler optimisations for this... I don't know) so causes actual memory access. Automatic variables might be optimized to being just register accesses, which is better... the compiler can figure out using register colouring what automatic variables are best left in registers and if they ever need to be on the stack.
I had a quick search through C99 standard (C11 is about... my reference is out of date a little). Could not see a reference to alloca so maybe not a standard-defined function. A possible disadvantage?
While programming (for example, in C), a lot of variables are kept in the stack.
A stack is a FIFO data structure, and we can pop only the top value of the stack.
let's say I have 100 variables stored in the stack, and I want to get the value of the one of them, which is not in the top of the stack.
How do I get it? Do the operating system pop all the variables which are newer in the stack until getting the wanted variable, then push all of them back inside?
Or is there a different way the operating system can approach a variable inside the stack?
Thanks
The stack, as used in languages like C, is not a typical LIFO. It's called a stack because it is used in a way similar to a LIFO: When a procedure is called, a new frame is pushed onto the stack. The frame typically contains local variables and bookkeeping information like where to return to. Similarly, when a procedure returns, its frame is popped off the stack.
There's nothing magical about this. The compiler (not the operating system) allocates a register to be used as a stack pointer - let's call it SP. By convention, SP points to the memory location of the next free stack word:
+----------------+ (high address)
| argument 0 |
+----------------+
| argument 1 |
+----------------+
| return address |
+----------------+
| local 0 |
+----------------+
| local 1 |
+----------------+ +----+
| free slot | <-------------- | SP |
+----------------+ (low address) +----+
To push a value onto the stack, we do something like this (in pseudo-assembly):
STORE [SP], 42 ; store the value 42 at the address where SP points
SUB SP, 1 ; move down (the stack grows down!) to the next stack location
Where the notation [SP] is read as "the contents of the memory cell to which SP points". Some architectures, notably x86, provide a push instruction that does both the storing and subtraction. To pop (and discard) the n top values on the stack, we just add n to SP*.
Now, suppose we want to access the local 0 field above. Easy enough if our CPU has a base+offset addressing mode! Assume SP points to the free slot as in the picture above.
LOAD R0, [SP+2] ; load "local 0" into register R0
Notice how we didn't need to pop local 0 off the stack first, because we can reference any field using its offset from the stack pointer.
Depending on the compiler and machine architecture, there may be another register pointing to the area between locals and arguments (or thereabouts). This register, typically called a frame pointer, remains fixed as the stack pointer moves around.
I want to stress the fact that normally, the operating system isn't involved in stack manipulation at all. The kernel allocates the initial stack, and possibly monitors its growth, but leaves the pushing and popping of values to the user program.
*For simplicity, I've assumed that the machine word size is 1 byte, which is why we subtract 1 from SP. On a 32-bit machine, pushing a word onto the stack means subtracting (at least) four bytes.
I. The operating system doesn't do anything directly with your variables.
II. Don't think of the stack as a physical stack (the reason for this is overly simple: it isn't one). The elements of the stack can be accessed directly, and the compiler generates code that does so. Google "stack pointer relative addressing".
I have to following question.
Given is the function:
show(int a, int b)
{
int v1;
int v2;
}
a and b are parameters. v1 en v2 are local variables. Draw a stack in which its is clear where a, b, v1 , v2, the old frame pointer en the return adress are. Also show where the high and low stack addresses are.
I hope i have been clear enough.
Edit:
What i have now is:
v2 <-- SP
v1
prevLV <-- LV
Ra
a
b
Drawing a definitive picture is hard as it depends on the implementation of the JVM, but what you have now is VERY unlikely to be correct.
Because Java doesn't distinguish args from temps (see the iload, etc.. bytecodes), they're going to need to appear side by side in memory, or someone's going to have to copy them from the caller pending stack to the callee at frame construction time (which tends to be expensive).