 So, what we are going to assume at this point of time is that I have four kind of instructions, one is all in return and all it is final stop and action is the statements which are not the procedure of function type of statement. So, these are like the findings of Boolean flow and so on. And we do not like to worry about this, but important part is we are going to be the all in return. So, if you look at static allocation, now what we have to do is allocation and the allocation is going to occur as part of the procedure called and it is going to be part of the return sequence. That is why it is hard to manipulate all the addresses. So, let us assume two functions, one is C, another is function P and C is going to remove P by having a false statement and then P will return control which will go back to the beginning of action 2. And action 1 and action 2 are some pieces of code which do not concern any procedure invocation and that is going to be some state type code. So, what we also have is that we have activation report corresponding to C, we have activation report corresponding to P and we have assuming that this takes 60 bytes, this takes 4 bytes, this takes 3 bytes and this takes 4 bytes and this takes 5 array as well. And the other way around is, I have a function C. This gives me a function C and that is what I am calling Now, what we have to understand here is that when I now say that I am trying to make a call to P, how do I manipulate the data in this and when I say I return then where I should jump and the code is going to be in this sequence. So let us make certain assumptions and as I said at this point of time I am first feeling the standard allocation. So all statement is going to be in this case sequence of actually two instructions I am manipulating my return addresses. I have to move instruction to save the return address. So for example, what I need to do is when I say call P, I need to go to the activation of P and fill in the return address. Now what is the return address? Return address is going to be from the beginning of this. So when I call P the code goes here when the code comes back it is not at the same point but the instruction which is next to call. So this is what we do that move instruction save the return address and then a go-to is going to transfer control to the target code. That means when I say call P first thing that will happen is that this return address has to be saved here and then I will say that jump to beginning of wherever the code is. This is the data area and this is the code area so that is where I can control the jump and when I say that return then I am going to jump back to this address and resume execution from that point on. This is what jump this is what jump to the procedure is. So what is the call instruction now? It is a sequence of two instructions. The first instruction is I am moving and I am saying move whatever is the current location and then I say jump to the call code area. Now we have to understand what this 20 means. So we have put here some number 20. What does this 20 mean? Or I am getting this number 20. So I made certain assumptions here and the assumption here is that each of code is going to take 4 bytes a word and each address is also going to take 4 bytes. That means if I start counting how many words this instruction will take? This instruction will take one word for the software, one word for this address and one word for this address. And similarly this will take 4 bytes and this will take 4 bytes. So total if you count I will take 40 bytes here. So whatever is my current address where move is going then the jump return address has to be instruction which is next to this which is going to be current address plus code. That is how I am counting here. So this is what we do and then we say that call static area and the static area of the call code are constants because I am talking about static allocation. I am not doing any static allocation at this point of time. So they refer to address and therefore if I look at this this is where I have to fill in the return address. So what this move instruction is doing is saying that slope this address into the call static area and call static area is obviously the address of the activation report of the first number. So let me straight away go to the code and really put certain number. So let's assume that each action is going to take 40 bytes and start address of the code address of C and P is 100 and 200. And activation reports are statically going to be allocated in the locations which are 100 and 360 code. So since I am doing everything as static allocation these numbers are known to me as compiler. So how will my code look? Code will look something like this. That I have this code corresponding to C, code corresponding to P, data area of C and data area of P and data area of C. So what do I do now? So if you look at this instruction which says move 142 360 code. So what this is saying is that whatever is my current address plus 40 that gives me 140, I am going to store that into 360 code which is the activation report of P. So I am going to store this address which is really the return address so that when this activation returns control, control will jump to 1 code. And then at this location I will say now jump to 200 and what is the 200? 200 is the code area of the procedure and when return happens, what will return say? Return is saying go to the address which is stored in 360 code and what is 360 code? 360 code is the first address of the activation of P. So now when I say go to 360 code I already stored 140 here that means I will jump back to 140 and we will resume execution from here. So let us go back to this point. So basically what we are saying is that the call is static area and the call is code area are the constants which refer to address of activation of the first address of the procedure code area and the data area. And then we say here plus 20 is the move instruction which is the return address and address of the instruction which follows the code thing. And a return from procedure is implemented by this saying go to the indirect call is static area. Everyone knows this for the star operation. Star operation is basically saying jump to the location whose address is stored in this particular location. So this is how my overall code is going to look. So this is how I fill in all my return addresses and this is how I implement them. Of course I have not put instructions here so we discussed also instructions for how to save machine status. So for example what I will do here is that actually when I say move this this is only saving the return address so after this I will also have to have instructions for the activation record which we discussed instructions for setting up all the access leaks which we discussed yesterday. And we will also have to have instructions for having the allocation of local variables which are ongoing. Is this part clear? What we are doing here? So static area is static allocation is fairly straightforward. I know all the addresses at compile time. I only have the layout of activations and once I fix all these addresses at compile time I can start to implement this. You can also see that what it also means is that when I am talking about all these addresses starting from 100 what this means is 100 is the base address which is relocated to the address and when actually code gets loaded in memory and gets executed all addresses will be changed with respect to this base. So when I say 140 this is with respect to base and if this base changes to some other location then obviously this will also change. But that normally through base register OS is going to take care of the execution. Any questions on this? Is this part clear? Yes, no. What do you understand about the stateful registers? So what I need to also do is that I say that I have this call here. So I have implemented call through two instructions. One is that storing the written address and then jumping to the code area. So basically call is a sequence of several more instructions. So one is to create access links one is to save the state other registers. That means I also have to have a sequence of instructions here which will say move register R1 to certain local area move register R2 to certain local area and so on. Now I have to decide which registers to save. So suppose I have eight registers and I want to save that in the activation here. So I also have to have these instructions before I jump to 200 and start executing it. I will have instruction here which will say that save all these into the temporary locations which are part of this activation. And similarly when I say go to this before this go to I will also have to have instructions which will say that move all the data which I saved here back into the registers. So I will have to save the machine status and we will have to restore the machines. So this too will be done by calling or calling? Shall we go back to what we did in the order? All right. This we discussed earlier. Shall we move forward? Now let us come to the stack allocation. So this is what I do in static allocation now let us come to stack allocation. What is going to happen in stack allocation is that I will have some port area. So this is all the port of the main program and of all the functions and procedures. And I also have now what I can assume is that even for the main programs my stack suppose may start from here and this is the static data or the global data. And this is how my stack will start. So first thing I need to remember here is that what is my stack pointer? Now normally what we do is normally two pointers are maintained but let us work with one pointer for the timing and that one pointer is the stack pointer and the stack pointer is to begin with maybe here and then I say that activation is on top of stack pointer since I know the size of activation record or in this case global data I can always find out with respect to the stack pointer where is the offset. So I also need to therefore remember that what is the location for which I will start loading my stack. So what we do here is that pollution of activation record is not known until the runtime until your program is executing I will not know where in memory this activation record is going to come because depending upon the call sequence this activation will be anywhere because also remember that we are not dealing with recursion and so on. So pollution is going to be stored in a register so I will have some location where I will say that what is my stack pointer and that value has to be stored there. And at runtime then I have to manipulate this stack pointer so what will happen is that I will say initially this may be my stack pointer then I load data here now with respect to the stack pointer I can find out all the variables here and now when a new activation comes then I have to increment my stack pointer by saying that stack pointer plus size of this activation becomes the new value of the stack pointer and a new activation comes here. So this is how my stack pointer which keeps manipulating I only have to initialize it once. So this is what we do that before I even start executing my first function I say that some start address from where the stack will start start loading is stored in this register which is SP or stack pointer. And this is really the fault instruction so what we do is that every time our portion activation I manipulate my stack pointer to say that stack pointer is implemented by size of the activation and when I return the reverse action has to take place where I will say that the stack pointer gets decremented by the size of the activation. So now what happens here is I will say that all sequences now implements stack pointer say return address and transfers them control. So this is the new thing earlier I was saving the in static allocation I was just saving the return address and I was transferring control but now I also have to increment my stack pointer. So following my instructions look I will say that at two stack pointer the caller recalls us. So assumption here is that the stack pointer is at the bottom of the caller activation. And then I say move here plus 16 into the location which is 0.32 by stack pointer that means into the location once I have implemented this this is where the first location of the activation is and that is where I store my return address. So same strategy as I was using earlier that return address is always in the first location in this. In this case since I do not know the absolute address I refer to that location by ST. But here now instead of 20 actually in 16. So how did I get this number 16? Again same assumption that each opcode in each address is taking 4 bytes but in this case since this is a register argument I need only 4 bytes for this opcode 4 bytes for this address 4 bytes for this opcode and 2 bytes for this address that gives me 16. I do not have to count now bytes for the register that is the register argument. So this is now my call stack sequence and what we need my return sequence return sequence is just saying that go to whatever is 0.32 by stack pointer with an offset of 0 so this is a standard thing what we say here is that we may remove this 0 what we may just keep it but basically this is saying that if in just in case my return address is somewhere else then I can use z that value here but basically this is saying that whatever is location 0.32 by stack pointer that is where my control has to go but ok and obviously then you have to subtract from stack pointer whatever is there call of size of the activation ok. So how will my code now look let us go back to the quick sort program we discussed yesterday so in quick sort I have this sort program then I have a Q sort so sort was the main program then I had Q sort as exchange in partition so we can make certain assumptions here that the size of activation records are if I say sort partition and quick sort they are given by numbers s size p size and this can be different because for each activation I know how many bytes I need to create that activation I may not know the location because of allocation stack allocation but at least I know the sizes so these sizes are known to be a compile time and first part of each of these activations is going to hold the return address for me that is what I am going to return reserve for the return address and we also assume that the code area in the code area the procedures they start at 100 and stack starts at 600 but all these information I know is going to be available to me as a compile time what I will not know is that in which order I am going to push the activations and therefore it has to be generated as part of my policy so how will my code look so let's say that code looks something like this that in the main program for sort I will make a quick sort so there will be some action here non-pussy reelection then I have a call to queue and then I have another non-pussy reelection and in P which is partition I just take some actions and return and in case of quick sort I have some action then I have a recursive call to P then some more action so in this I have a call to P and I have two recursive calls to so when I call quick sort I will first make a call to partition and then I make two recursive calls to queue that I can only just set up return as this is pushed as part of the activation so this is how my thread looks but when I go to the machine kind of code let's understand what this is going to be so first thing we say is that since my stack starts from 600 I push that value into the stack spoke 600 into the stack point now who returns is what the 600 is Who is going to decide this number 600, whether this is 500, 600 or 1,000? It's not to us. Since I'm generating relocatable code, I know that this is the total process space which has been given to me and I decided that for this program it's sufficient that I know I have done code generation, I know how much code and data area is there and I can start loading my stack from certain location. Actual address of 600 will be mapped on to, depending on the page table will be mapped on to some other address. So this is the total area which has been given to my program and I'm generating code only from this one. So I move 600 to stack point and then I have this action and then I say that add, now since this is going to make a call, I'm saying that add size of s to stack point. And then I say move here plus 16 into the location which is 0.2 by stack pointer. So I move 152 which is 136 plus 16 which is here. That is where the control will come and then I say jump to location 300. And 300 is this location where I make call to. So where will this return address get stored? So return address will get stored into, this is what my code area is. So let's say that this is my code area, then stack pointer started pointing to the first location here. And then this is where I store value of, what is the value? This is where my return address is. But look at the code corresponding to this part. So what happens here? In this part, I'm saying that now I'm going to make call to, first time I'm going to make a call to p. So what I do is I say that take size of q and push that into the stack pointer. So I'm now going to say that this is the activation corresponding. And then the next activation has to be pushed here. So again, your SP has to be incremented. So SP will go here. So this is I increment by the size of the caller. And then I say move 344 into the location which is 0.2 by stack pointer. And what is 344? 344 is 328 plus 16. That is where the components come back. And then I say now jump to location 200. And 200 is the code area corresponding to p. And what does this do? This always says whenever a return happens, a return happens by looking at whatever is my current stack pointer and the address which is stored in the location at an offset of 0, which means the first location of my activation jump to that. So whatever address I store there. And every time this address could be different depending upon the call sequence. But doesn't matter about the addresses. I'm only jumping making any direct jump saying that whatever is the address which is stored in this location, jump to that location. And every time you will see that in this case, I am storing 344 here. In this case, I am storing 390. So when I now make a recursive call here, I'm going to say that increment now this by 2 size once again. Move 396 which is 380 plus 16 into the stack pointer and then jump to 300. So 300 is now a recursive call coming to the beginning of this process. And once the control comes back, control will come back to this location which will say that now subtract this part and then continue execution from here. When I come to 424, then again I am going to add 2 size to sp. And then I say move to 48 which is 432 plus 16. I store this location. Jump to 300 which is a recursive call. And when the control comes back, I come here. And finally, I jump return from this procedure. And what is the value which is stored here? That value must have been initialized at this location. So there's a code I need to generate. And you can see that this code, this is the code really now which is managing R runtime. So irrespective of what my call sequence is and what is the value which is going to be returned by partition, this code is going to remain the same. Only thing that will happen is that if you look at the section 5 and section 6, they are going to determine whether I am going to make a recursive call here or I am going to just fall through and not execute this recursion and straight away jump to this. So it will say that if partition returns the value which is smaller than the mount or is equal to one more promise, then I won't make a recursive call but I will just return. But that is irrespective of whatever the code is. This code will look something like this. So many times people confuse between what the stack pointer makes, stack pointer is pointing to. So what we need to remember is that stack pointer always points to from where the stack starts and activation is on top of stack pointer. Now normally for efficiency reasons, what we may do is that if I look at some activation record my estimator here and I may have an additional pointer here which sometimes you will find that it is called a frame pointer and then I can access data within this activation either with respect to stack pointer or with respect to frame pointer. And what is the difference between stack pointer and frame pointer? If I say f p minus f p, what will it be? It will be the sign of activation. Then why do I need another pointer? The advantage sometimes is that if this activation record becomes large, then some data could be accessed very quickly by looking at an offset with respect to f p and some data which can be accessed very quickly by looking at an offset with respect to f p. And I want to keep offset as small as possible. So now it should also give you a hint. If you go back now to what I did in my activation record, the data which is frequently accessed is either going to be here or is going to be here. So for example, if you notice that I have this local data and so this is where I set machine status in the middle. Now when do I need machine status? Machine status I need only when the call returns, not during the execution of the function. But any data I need during the execution of the function is kept close to one of the pointers and the reason is that this data is accessed much more frequently therefore I should be able to access this function as compared to this data. So if this activation becomes large, then I want all frequently accessed data to be close to one of the pointers. And what is the advantage? That I will be able to access the data with a very small offset. That means not only I will save few bytes of i memory, but I will also have a faster access. Sir, I don't understand that there is one option. Do you remember the sentry language program? Yes. So if you remember the sentry language programming and when you say that I have this instruction it says jump to a location or access a location and the offset is small which I can fit, say offset is up to 8 bytes. Then I will take only 3 bits to fit into it. Now if offset becomes very large, then I may need to make additional bytes to put that offset there. If this is small then it can be part of the same instruction and it will actually save a byte for it. And normally these small offsets are kept in the disk and these instructions are much faster. So just go back and look at the difference between small offset and large offset. It stores the whole instruction in fewer bytes and therefore becomes much faster to access. That's the difference. Something which hardware provides. And what we try to do all the time is that we try to exploit whatever hardware gives me which will have a code which is much faster. So I will be now confident about how to generate a code generation for Procedure. So now you can see that what I am showing you is complete code for 3 address code for or actually in this case happens to be almost the machine code for Procedure. So Procedure handling therefore is, the reason I treated Procedure handling separately from straight line code and so on was that you need to worry about initializing all the data into activations and all the consequences and filling in all the addresses. But you can see that all this is done by compile. So compile only makes sure that I generate enough code so that it can execute. I don't depend upon, so this also is part of my run time system but I don't depend upon OS or anyone to generate this code or fill in these addresses. So now we have seen everything. We started with straight line code and we have all the way up to Procedure's instructions. And we see how to pass parameters. We know how to create access links. We also know how to create. Links to the control structure that means either lexical scoping and dynamic scoping and how to manage my run time system. So what is the next thing in code generation? One thing we have not still touched on that is how do I generate code for dynamic data systems. So far we have not talked about when I say that give me some locations of memory how do I manage the deep space here. This is my stack space but he will go from here and I need to have code for that. Again, this is the area which is provided to me by OS and I have to manipulate this area. I must have enough code to manipulate this. So this is all part of the pipeline. So that is the next thing that we want to look at what I want to do in my dynamic scoping system. How do I manage this? Any questions up to what we have done for Procedure's? Before I move on. Is Procedure part clear? So this storage is usually going to be taken from D which is coming as this part and it will start from this end. And this is what we want to see part of it we saw yesterday. So we are going to allocate the data is going to be retained until this is going to be reallocated. And allocation can either be explicit or implicit. So when I say that if you look at languages where I say that explicit allocation I will have this small like new, I will have this small like this pose and if you look at all different languages like C++ whenever or Java when you say that I create an object at that point of time this gets allocated or in C and say malloc and so on. So I have explicit calls. But then there are languages which are really working at the level of which are list like languages. They will say that whenever I construct the data I don't have to really make a thought it is going to automatically reallocate and automatically reallocate. So there is an issue like garbage collection which comes here which is not part of this class of languages. So people also work on saying how can I do garbage collection in C? So you may leave certain pointers which are just hanging which are not being used in C also and you may end up missing space. So some people have also tried to build the garbage collector with C. But we will only touch upon it and not go into details. So let's see what are the kind of things which may have problems you may face while managing my data stuff. So take critically a list like this. So this list has some data and then it has pointers and the last pointer is 0.0 and then I have a pointer which is 0.2 type of the list. And the calls typically I may have is that I may create now on you. Now in malloc coming what happens is that you can say that give me enough space for creating this kind of data structure. Here I am saying that create now a record and it will determine from the record layout how much space to be given here. And then I can say p hat e is going to be k and p hat intro is going to be i. So these are the typical calls of initializations which are same in all languages. Now what I may do is that I may create unreachable sets. So what I may do is I may decide that I want to dispose of this pointer or initialize this pointer to null. Now as soon as I initialize this pointer to null and there is no pointing to this part of the list what will happen? This cell and this cell becomes inaccessible. And now as far as user is concerned user space is concerned I still have this cell allocated but this is not accessible so actually I am wasting space. Now many people have this notion saying that today memory is not a problem I have 4 gb of virtual address space and therefore I can just keep on doing malloc and not have a worry about disposing it off or releasing it or freeing it if you just want to be precise on c syntax. That is a very dangerous thing to do because over the time what will happen is if you have a large program running imagine operating system running and operating system is continuously doing malloc or various processes and never releases memory. What will happen? Typically you will run out of whatever space is available. So you can create unreachable cells which are not accessible so if I say head up next is assigned and this assigned is nil and these 2 cells are still in memory then they are not part of the free space but they can also be not allocated to any other program. And I may also create dangling references so I may just say that dispose of this or when I say free this particular cell what will happen? This point where it is pointing to some arbitrary location this is a dangling point to know which is equally dangerous. And in fact if I just dispose it off normally I have created a dangling reference I have also created a garbage. So now there are languages which will manage your storage so that even if you create dangling references and garbage over the period they will clean up the space for you. But their language is like C and this class of languages it will not do any such thing and you will learn how to do it. So explicitly programmer has to manage part of it but therefore what we need to manage is that where do I store this and how do I manage my E? As compiler I cannot implement I cannot enforce programmer discipline but as compiler I need to make sure that whatever is provided I can efficiently implement that. So first thing is explicit allocation of fixed size blocks I gave you a glimpse of this yesterday but basically what we are doing is that we are saying that blocks are kept in a list so I am talking about a fixed size block so this is saying that for some small number I can say if I say allocate 400 bytes I will say don't worry I will give you always 1 k size of block. So what we can do is allocation in the very little overheads and what is that all I am saying is that I have an available list where I have a link list of available blocks to me and then these are the part which has been allocated and now if I say I want to free this particular cell I want to be allocate this cell this becomes now part of the available list and this part still remains allocated. So you can see that overhead of managing a fixed size block is very small I just need to have a link list of available blocks and then I can just do allocation in the allocation allocation in the allocation only means that I need to either put it in the list or I remove it from the list. So this is hardly any overhead this really does not put too much of pressure on us and continuing on this so blocks are going to be drawn from continuous area of storage that means as far as this block is concerned this is still going to be continuous in the video I will not say that this block of 1K will take 256 bytes from here and the remaining 784 bytes from somewhere else that kind of thing will not happen the blocks are drawn from continuous area of storage and the area of each block is used as part of it obviously is pointed to the next block and then I have this pointer available which points to the first available block in this and allocation means removing a block from the available list and the allocation means putting the block back into the available list now compile the routine now remember that what I am doing here I am writing part of the program which is going to manage my heap that is also a program I have to make all the declarations there now when I allocate space when I say that I have this link list what is the type of data I declare for this link list I need to declare that so imagine writing a C program which manages this link list or imagine writing a program in any high level language what is the type of the record I declare I declare I don't know whether I am going to store there it will allow me to write the address in any way in talking of C right suppose I have much more strongly typed language than that like Ada or Cosplay or LL not for me to do that so normally what we do is as far as runtime system is concerned or the heap manager is concerned it actually we don't know what is the type of this so I can just use varying pre-calls right and see this is union type and every language for which you have varying pre-calls the type is not fixed and when I actually allocate it goes to the program, program is going to determine what type of data they are going to store there so as far as heap manager is concerned heap manager doesn't care what is the type of this there is just a variant type of structure which is called now interesting situation comes when you have a variable size of it again you have to worry about best fit or first fit so storage can become fragmented over the time and situation may come when program allocates some blocks and then we locate some of them we have this fragmentation going on that I allocated somewhere and then this becomes free and now if I say that I want a block of say size which is larger than all of these then I am stuck because I am a continuous block so I also need to refragment so fragmentation is of low consequences is block size fixed then it doesn't matter if I am fixizing block I just maintain a link list doesn't matter where the next pointer is that is not an issue fragmentation becomes very important when it is variable size so now I also have to see that how do I if I find that suppose I have a free space here and I have free space here and how do I merge the two spaces if they are consecutive to each other then merger is straight forward but if they are not consecutive to each other then what I need to do is I need to move this so assuming that this green part is the allocated space I need to move this here I need to move this here and what was movement involved so what was movement so suppose this is a task in front of you that I have these so I assume that the smallest unit is a byte and I want to make sure that this data remember that once I move it here and I move it here movement just does not mean that this is the base address it means something else that I may have pointer here I may have a location which is actually pointing to some other location so what I need to know is that if it is pointing to say location x and that x moves now everything which is pointing to x should now start pointing to the new location where x is going to be so I must know what my pointers are that means when I say that I have some allocated space within this allocated space what my pointers are and what are not my pointers so I need to worry about when I say defragmentation has anyone done ever defragmentation on a hard disk do you run this program for defragmentation on hard disk yes what happens is there is a pictorial differentiation which comes in so on so how do you think a hard disk defragmentation will manage so suppose I am working on your system or this is your file system then all the file pointers must be correct so all i nodes structure should not be destroyed and so on so somebody knows in some table where all my i node addresses are and when I move this particular block into another block then the i node table must go back and change all the information so similar thing we will do here and we shortly conclude so block cannot be allocated even if space is available because I may need larger space and because of fragmentation defragmentation so allocation of first fit method is that search the first few block which is of size greater than this so best fit method is I am looking for a block which is of size just greater than this first fit method is that I start looking at this and there will be another method which will say that look at the largest block or there will be another method which is saying that after allocation the remaining block should not be available in size and so on so you can think of various strategies here and then allocation means that I look at some block which is of size greater than this and then subdivide this into two parts S and F minus S and time overhead obviously there is now time overhead of searching for a feed block so earlier in the fixed size allocation there was no overhead only overhead was that there was one pointer that was saying that pointer points in the available list and I just change that pointer to the next block and everything was done but here I have an overhead of finding out the available block and when block is reallocated what is done I check whether this is next to a feed block and if it is next to a feed block then I just combine it but if it is not next to a feed block then I have to go to defragmentation so implicit reallocation is it requires now so when I say implicit reallocation implicit reallocation is equivalent to either garbage collection or over the time or defragmentation now this requires some cooperation between the user program and the runtime system and what kind of operation is required now I need to know two things I need to know what are the blocks which have no longer use how do I find out the block which has no longer use so think about it but shortly I am going to ask you this question once again and this by implementing by fixing the format of the storage block that means I just cannot say that I get a block and I put some data here user program has to make sure or my runtime system has to make sure that the data which is put here has certain structure and what that structure may be it may now have a structure saying that I will have user information but I will also say that what are the pointers to other blocks and user information here it may have some entries which actually are pointing to some other blocks there are some pointers now I want to keep all these pointers separate so that when I start defragmenting when I start reallocating I need to worry about what these pointers are pointing to because if I don't have this information I will not be able to manage then I also have certain markers which will say that whether this block is in use or not and I also have a reference that how many other blocks are pointing to this particular block so I need a lot more information than just user information if I want to manage all these reallocations so I will have information like block size so this will say that if I know the first address then I know the boundary area think from the point of view of the hardware in what happens there I will just say that you have certain memory locations and each memory location will be better but if I know that this is the pointer to the first location and I immediately know the size then I can find out what is the size of this particular block and by having this extra information saying that how many blocks whether it is in use or not how many blocks are pointing to this and what are the blocks it is pointing to that is the one which helps me doing allocation which helps me doing reallocation and defragmentation now once I have this information suppose I have this information this is how I have laid it out reallocate can you think of a strategy now that how will I reallocate suppose that I have all these blocks somewhere in my heap which are lined and I just need to know only one thing that is the first block in use if I know the first block in use that will have a pointer to everything so what I can do is I can mark that all my blocks are not in use and then I can say that this is in use so I change the marker to that and say that this is in use and then I say whatever it is pointing to I go to those blocks and mark them also as use and if I continue this traversal then I will mark all the blocks as used and whatever is not used whereas the marker has not been marked that is now can we reallocate so one way to look at this is that somebody actually gave a very nice pictorial representation of any way to take a structure so I mean here I mean if you assume that every pointer is every link is just a pipe so you go to the first block and pour some color into this color liquid into this and it is flowing over all these pointers and wherever it does not reach so whatever block is colored that is in use whatever is not colored that is no longer in use and here look at this so that means we have lost pointer to all those locations and therefore there is no need to keep all this information so recognizing block boundaries so now let us look at all each of these and the first thing we say is that if block is of size fix block is a fixed size block then the position information can be used otherwise each size information will come into block boundaries because that is how I will say that this is where my block ends in case of link list I do this was the fixed size and where the block is in use so reference may occur to a pointer to a sequence of pointers there may be multiple pointers and compiler need to know position of all the pointers in the storage and pointers can be capital fix location in user area does not have any pointers so basically this part this is where I am saying that I am keeping all the pointers here so basically in this user information I know that what are my locations which are pointing to something else which are pointers say I mean otherwise I cannot differentiate between a bit pattern whether this is the address or this is the integer value or other data structure so I need to explicitly know what my pointers are so that when I start moving other blocks then I will know that these are the locations which need to be changed so this is where I say that whether block is in use and what is the reference count it keeps track of number of blocks which point directly to this present block so every time some pointer is disposed in one of those blocks then I need to come back here and change my reference count here and whenever this reference count becomes 0 then I know that this is not being pointed to by any other block and is ready to be disposed of and if one drops to 0 then block can be reallocated and maintaining reference count is going to be possible because every time I do an assignment like this it says q is a sign q then what is happening here that whatever q was pointing to so q is a pointer it was pointing to it will no longer point to that so not only wherever q occurred all those have to be reallocated or the reference counts of the blocks which are pointed to by q they have to be decremented by one but here we say that since q is assigned to p then I now know that p will start pointing to everything which was being pointed to so basically you will have to manage reference count of everything which has been pointed to by p and q whenever you do this assignment okay and reference counts are used when pointers do not appear inside if pointers appear inside the elements that reference count does not mean anything but if pointers do not appear inside you then reference count is the one which can immediately tell you whether something is being used in this so what are the marking techniques are used so marking technique is now basically automatic reallocation of a block so what we have to do is now suppose your program is executing and you say that I want to find out whether certain blocks are reachable or not then if two processes are running simultaneously this can become nightmare because I am continuously allocating and reallocating and other process is trying to find out other thread is trying to find out whether certain block is in use or not so this cannot go on the first thing that happens is that you have to suspend execution of the user program and one of you has done list programming or have done programming in using some kind of interactive development environment of a language where garbage collection happens automatically then you notice that you are editing your program, your program is executing and suddenly everything stops and then for one minute you are just waiting nothing happens so basically it is the garbage collector which is running in the background and your process has been one which has been suspended you cannot simultaneously modify your pointers and say find out what are the pointers in use so suspend execution of the user program and then whatever pointers are frozen pointers then you determine what are the blocks which are directly in use and this is the approach which requires knowledge of all the pointers but we have seen this structure where all the pointers are going to be kept separately now go through the heap where you start marking all the blocks which are unused and once you have done that then follow pointers which mark the block is used and that is reachable so first block will always be reachable I mark that as used and then re-arrocate a block which is still marked unused so I start with the first block the first use block and say that take pointers from here and continue marking and compaction is then move all the use blocks to the end of heap and point us all the pointers will now happen since I know the locations of all the pointers now and what it is pointing to then movement will now become easier I will not have to worry about user area but I need to only look at the pointers that is how I do my compaction so if you know your layout of the space that what my pointers are then I can do it otherwise I will not do it so this is where we close up our discussion on 4th management of heap and we now get into the actual 4th generation which is looking at the final machine and that means