Now that we understand some techniques on how we can use the end commands to access selected areas on the RAM. We can go on and talk about how to write the end code that handles object construction. Now, beginning with the big picture, here is an example of some client class that seeks to create a point object. And as usual we do it as we do in Java and C# using a two stage process. First of all we declare a object variable, p1. And later on we may or may not call a constructor and assign this object to the variable that we previously declared, p1. And here is the point class that actually services this request. In other words we have a constructor which is a subroutine within the point class. And when we evoke the new method or the new subroutine within the client class we actually cause the code or the constructor to start running. So what we have here is a typical caller-callee kind of relationship. And you should bear in mind that as far as the compiler is concerned. What we have here is two completely separate and stand-alone compilation units. So we are facing the challenge of, first of all, compiling the client class. And then separately, compiling the point class, and not necessarily in this order. Right, so how do we do it? Well that's what this unit is all about. Let us begin with the client class. And as usual everything that we do in the high level is going to be reflected in some way on the low level. And in this course we are always fond of exploring both layers simultaneously. So this will be no exception. When we do var Point p1, the compiler will end up generating code that essentially maps the p1 variable on some location in the stack which is going to be initialized to 0. And then later on, when we actually call the constructor, the compiled code that will start running will end up creating the object proper on the heap. And the same code will also, well not necessarily the same code but the two classes running together. Will end up taking the base address of the newly created object and storing it in what we assigned previously the p1 variable. Now the 6012 address is completely arbitrary. I made it up, and I assume that this is the place in the RAM that the compiler ended up storing this particular object. So that's what happens in a very sort of high-level view of operation. And with that, let us now delve into compiling this particular method call which happens to be, sorry, a constructor call. And in order to do this, we'll look at the slightly more interesting code in which we declare and create actually two object variables, p1 and p2. As well as one primitive variable d. And here is the compiled code that the compiler will generate from this particular high level source code. So first of all, what will the compiler do with these two variable declarations? Now, actually, the compiler deals with every statement kind of one at a time. So it's a little bit misleading that I wrote the two statements together here, but I'm doing it just to save space and minimize clutter. Whenever the compiler encounters a variable declaration, it generates no code whatsoever. The only thing that the compiler does is it updates the relevant symbol table. And because we are now compiling code that resides in a certain subroutine, we'll end up updating the symbol table of the subroutine. And recording that what we have here are the two point variables, p1 and p2, as well as one primitive variable, d. Moving along, we now want to compile the statement, calling point of view and assigning the result to p1. How should we do it? Now look at this high level method call here. Point.new (2,3). What do we have here? Well, what we have is just a call to some subroutine. So we can handle it just like we handle any subroutine call in the VM language. We can push the two arguments, two and three, and call point.new to execute its magic, whatever magic it may be. So we are calling the subroutine for its effect, so to speak. However, because new is a constructor there's a certain contract, or a big time assumption which lurks in the background. And in particular, the calling code, this code that we are now writing, assumes that when the constructor will execute, whenever it will happen. When the constructor will execute it will end up allocating some space on the RAM for the newly constructed object. And it will also take the base address of this space on the RAM and it will return it to the caller. It will return it to me. I'm the caller, right? So with that in mind, it makes perfect sense to pop the topmost value of the stack into p1. Why? Because that's exactly what we want right? We want p1 to point at the base address of the newly constructed object. So if this contract will be respected by the constructor we'll have exactly what we wanted as we see in this REM diagram. What about p2? It's exactly the same story and therefore, I'm not going to repeat it. So, that's how the compiler handles calls to create new objects from the caller's perspective. Now let me kind of recap and say a few words about the resulting impact. First of all when we declare the variables, when the compiler generates code to declare the variables. Well, we know that it generates no code. It just creates the symbol table, or modifies the symbol table. Well, essentially it ends up mapping these three variables on the RAM and initializing them to 0. I'm repeating what I said before for closure. And only when We call the constructors and only when the constructors will actually go to work only then during runtime are we going to actually create the objects on the RAM and assign their base addresses to the previously allocated variables. So, object construction is a two-stage affair that happens both during compile time and during runtime. And it's important to understand it and that's why I took the trouble to repeat this slide as well. All right, so now we know how to generate code to handle object construction from the caller's perspective, and we can move on to talk about the callee. So the challenge now is how to handle the compilation of constructors. Well, let's think about it. First of all, a constructor is typically designed to do at least two things. First of all, arrange some space on the RAM for the new object. And second of all, no less important, a constructor typically assigns certain values to the fields of the newly constructed object. That's what typically happens, right? When you say new Point 2,3 you expect the x property of the point to be set to 2 and the y property be set to 3. So the constructor is responsible for doing these initialization tasks. All right, with that in mind the constructor must have access to the object's fields. How can we do it? How can we access the object fields? Well, we talked about it in the previous unit. We can access the object fields by accessing the, this virtual segment. Don't forget we are writing VM code. We have to do everything from the VM code perspective. So we can manipulate this segment and this will end up manipulating the current object. The object that the constructor just created. And in order to access this segment, we first have to anchor it properly on the right address in the RAM using the pointer segment. Nothing is new here because we discussed it in the previous unit, but now we will see how it comes to play in the actual task of developing a compiler. All right, so here is the call to the constructor that I repeat here just for context. I don't have to repeat it because it belongs to a different class, right? We already took care of this class. And now we're taking care of the point class. But I wanted to show it once again for perspective. Because these things don't happen in a vacuum. So, how do we compile this point class? Well, we begin by compiling the three statements, class Point {, field int x, y; static int pointCount; and this is not really the subject of this unit, because in this unit, we're talking about compiling constructors only. But I will comment that when the compiler handles these three high level commands, it generates no code whatsoever. The only thing that it does is create the class level symbol table. And that's it. And then at a certain point the compiler will get to a point where it has to generate code for the constructor, so the first thing that we see is the constructor signature, so to speak, or the constructor declaration. And how does the compiler handle it? Well, once again it will generate no code whatsoever. The only thing that it will do with this statement is that with this declaration is that it will create the subroutine symbol table. The subroutine happens to be the constructor. And record in it that all we have so far are two variables, x and ay, and both of them are argument kind of variables. Well now comes an interesting and important stage in code generation. The compiler knows that it generates code for a constructor and it knows that the constructor has to create some space on the RAM for the newly constructed object. So the first question we should ask is how does the compiler know how much space is needed? Well the compiler can consult the class level symbol table and realize that objects of this particular class, of the point class, require two words only, x and y. All right? Because we have a 16-bit machine. Everything is 16-bit. In a more complex language like Java we may need more words. In the case if we have more complex integer types or flow types or floating point. But here just by looking at the symbol table we know that we need to secure a memory block that contains two words right? Now the question is how do we find such a free memory block on the RAM. Well, at this stage the operating system comes to the rescue. And the operating system, which we have seen here and there during the course supplies all sorts of very important functionality. And one part of this functionality is a function called alloc, comes from the word allocate. If you provide alloc with a certain argument like five, then alloc will go to work and it will find a memory block on the RAM which has two important properties. First of all it is five words long. And second of all it's free. Now no one needs it and therefore the constructor can safely use it. Now, the implementation of alloc is very clever and elegant and we will look into it and implement it in the last module of this course, when we actually build the operating system. But for now, we are going to use it as a black box obstruction. So everything that I said is written here in this comment. And the compiler now is going to use the operating system to create this space on the RAM. How do we do it? We push two, because we need two words, and we call memory alloc, for its effect. And we know that memory alloc is going to return the base address of the newly created object. With that in mind it makes perfect sense to pop this value that was returned by alloc into pointer zero. Why? Because if we do this, we are going to align this virtual segment on the object that we currently, that we have just constructed on the RAM. And I do this because I know as a compiler writer, I know that with very high likelihood the next commands in the constructor will want to access the fields of the newly created object and if they will not want to do it then so be it. So I'm not going to use this segment. But if I will need to use the dis-segment, I took care of it. It is readily available and now I can use it safely. In particular, indeed if you look back at the high level code, you see that the next two statements that we have to handle are exactly what I just described. These are statements that seek to access the x and y properties or the x and y fields of the new object. Well, now that this segment has been properly aligned I can happily do just that. So I generate code that pushes argument 0, why argument 0? Because I look it up in the symbol table and I see that ax stands for argument zero so I push it on the stack and then I unload it or pop it into this zero and then I do the same with the ay and y. And by doing this I'm going to manipulate this zero and this one and because I took care to anchor them correctly, I'm going to manipulate the right area on the RAM. All right, moving along, I have to handle let the pointCount = PointCount + 1, and this is not terribly interesting because I'm not manipulating any objects here, so I'm not going to belabor on it. And finally, and that's very important, according to the rules of the game every Jack constructor must end with a return this statement and indeed we see that we have a return this statement in this constructor as well. So how do we compile it? Easy, right? This is already anchored on the right endless, so all we have to do. Is push pointer zero on the stack, because pointer zero contains the base address of this and return this address to the caller, and that's the end of the compile code of this particular constructor. But as you can imagine, this code would be very similar for many other constructors as well in principle of course. Now, what do we do with this return address? Well, let us remind our self where we started. Where we started with some caller issuing a call to the constructors code so I'm returning the value to this location in the high level code and it may look it will be more clear if we think about the compiled callers code after the caller is the caller code point dot new it sort of sits back. And waits for the constructor to do its job. And it knows that when the constructor will terminate its processing, the topmost value on the stack will be the return value. The base address of the object that was just constructed. And therefore it makes perfect sense, I'm sorry. And therefore, it makes perfect sense to pop this top most value onto p1. And this will create, once again, the desired setup of an object that we discussed all along. So that's it, that's how we handle constructors and so we have mastered the art and the science of generating code both for the constructor calling as well as for the constructor execution itself. And now that we have done that, we can go on and talk about object manipulation.