Modifications
This commit is contained in:
+50
-13
@@ -36,23 +36,50 @@ which in the example is:
|
||||
REPLACE it with:
|
||||
|
||||
[6] = Fclosure8 Const(1) [],
|
||||
[8] = Fclosure8 Const(0) [],
|
||||
[18] = GetField Atom(atom("prototype")) [6],
|
||||
[8] = Fclosure8 Const(0) [],
|
||||
[] = PutField Atom(file_atom[5]) [8, 18],
|
||||
[] = Nop None [],
|
||||
[] = Nop None [],
|
||||
[] = Nop None [],
|
||||
[] = Nop None [],
|
||||
|
||||
INSTRUCTION BY INSTRUCTION:
|
||||
|
||||
PushConst8 Const(1) + DefineClass [5,4] -> Fclosure8 Const(1), keep dst [6]
|
||||
Fclosure8 Const(0) -> unchanged (the method closure)
|
||||
DefineMethod atom=A [8,7] -> GetField "prototype" [6]
|
||||
then PutField atom=A [8,18]
|
||||
Fclosure8 Const(2) -> deleted
|
||||
SetHomeObject -> deleted
|
||||
PutLoc1 [12] -> deleted
|
||||
Drop [11] -> deleted
|
||||
PushConst8 Const(1) ; DefineClass [5,4]
|
||||
-> Fclosure8 Const(1), which keeps the DefineClass dst [6].
|
||||
|
||||
[18] is any fresh value id.
|
||||
Repeat the DefineMethod line for each method in the class.
|
||||
GetField "prototype" [6]
|
||||
-> emitted once for the whole class, into a fresh value id [18].
|
||||
It is NOT emitted per method: the prototype cannot change
|
||||
between the PutFields below. A class with no methods does not
|
||||
emit it at all.
|
||||
|
||||
Fclosure8 Const(0)
|
||||
-> unchanged. It is the method closure.
|
||||
|
||||
DefineMethod atom=A [8,7]
|
||||
-> PutField atom=A [8, 18], reading the [18] from above.
|
||||
Repeat the Fclosure8/PutField pair for each method.
|
||||
|
||||
Fclosure8 Const(2) ; SetHomeObject ; PutLoc1 [12] ; Drop [11]
|
||||
-> deleted. This is the field-initialiser tail.
|
||||
|
||||
Nop
|
||||
-> padding, described below.
|
||||
|
||||
LENGTH, and why the rewrite is written in place:
|
||||
|
||||
matched = 2 + 2n instructions, plus 4 more if the field-initialiser
|
||||
tail is there (n = the number of methods).
|
||||
emitted = 2 + 2n instructions, or 1 when n is 0.
|
||||
|
||||
So the emission is never longer than what it replaces. It is written
|
||||
straight over the matched range and the slack is padded with Nop,
|
||||
which pops and pushes nothing. Every instruction outside a class
|
||||
build keeps its position, so no other range has to be adjusted.
|
||||
|
||||
In the example: 8 matched, 4 emitted, 4 Nop.
|
||||
|
||||
REMEMBER for step 2 and 3:
|
||||
|
||||
@@ -200,7 +227,17 @@ NOT TOUCHED (passed through unchanged)
|
||||
|
||||
|
||||
====================================================================
|
||||
LEFT BEHIND (removed by a later pass)
|
||||
LEFT BEHIND (an empty function)
|
||||
====================================================================
|
||||
|
||||
FnById(4), the fields function. Nothing references it anymore.
|
||||
FnById(4), the fields function. Step 1 deleted the fclosure8 that
|
||||
built it, and step 2 moved its writes into the constructor, so
|
||||
nothing references it anymore.
|
||||
|
||||
Step 2 empties it:
|
||||
|
||||
code: [],
|
||||
|
||||
It is NOT removed from the function list. A function id is an index
|
||||
into that list, so removing one would renumber every function after
|
||||
it and break every FnById that points past it.
|
||||
|
||||
Reference in New Issue
Block a user