/
CompiledBlock.class.st
135 lines (109 loc) · 3.59 KB
/
CompiledBlock.class.st
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"
Specific version of compiled code for block's.
CompiledBlock are used only in the recent BlockClosure implementation by Eliot Miranda and Clement Bera, also known as FullBlockClosure. This new representation makes possible heavier runtime optimisations while simplifying a lot of code, both image-side and VM-side.
In addition the execution mechanics, a compiled block have an extra optional literal. The last literal is the compiled code referring to the compiled block.
"
Class {
#name : #CompiledBlock,
#superclass : #CompiledCode,
#type : #compiledMethod,
#category : #'Kernel-Methods'
}
{ #category : #scanning }
CompiledBlock >> hasMethodReturn [
"Answer whether the receiver has a method-return ('^') in its code."
^ (InstructionStream on: self) scanFor: [:byte |
self encoderClass methodReturnBytecodes includes: byte]
]
{ #category : #comparing }
CompiledBlock >> hash [
"CompiledMethod>>#= compares code, i.e. same literals and same bytecode.
So we look at the header, methodClass and some bytes between initialPC and endPC,
but /not/ the selector because the equal method does not compare selectors.
Note that we must override ByteArray>hash which looks at all bytes of the receiver.
Using bytes from the pointer part of a COmpiledmethod can lead to a variable hash
if and when when the GC moves literals in the receiver."
| initialPC endPC hash |
initialPC := self initialPC.
endPC := self endPC.
hash := self species hash + self header + initialPC + endPC.
"sample approximately 20 bytes"
initialPC to: endPC by: (endPC - initialPC // 20 max: 1) do:
[:i| hash := hash + (self at: i)].
^hash
"(CompiledMethod>>#hash) hash"
]
{ #category : #testing }
CompiledBlock >> isTestMethod [
^ false
]
{ #category : #accessing }
CompiledBlock >> method [
"answer the compiled method that I am installed in, or nil if none."
^self outerCode method
]
{ #category : #accessing }
CompiledBlock >> methodClass [
"answer the compiled method that I am installed in, or nil if none."
^self outerCode methodClass
]
{ #category : #accessing }
CompiledBlock >> methodNode [
^ self outerCode methodNode
]
{ #category : #accessing }
CompiledBlock >> numberOfReservedLiterals [
^ 1
]
{ #category : #accessing }
CompiledBlock >> outerCode [
"answer the compiled code that I am installed in, or nil if none."
^self literalAt: self numLiterals
]
{ #category : #accessing }
CompiledBlock >> outerCode: aCompiledCode [
^self literalAt: self numLiterals put: aCompiledCode
]
{ #category : #accessing }
CompiledBlock >> penultimateLiteral [
^ nil
]
{ #category : #accessing }
CompiledBlock >> pragmas [
^ #()
]
{ #category : #accessing }
CompiledBlock >> primitive [
^ 0
]
{ #category : #printing }
CompiledBlock >> printOn: s [
s << 'compiledBlock'
]
{ #category : #compatibility }
CompiledBlock >> properties [
^ nil->nil
]
{ #category : #comparing }
CompiledBlock >> sameLiteralsAs: method [
"Compare my literals to those of method. This is needed to compare compiled methods."
| numLits literal1 literal2 |
(numLits := self numLiterals) ~= method numLiterals
ifTrue: [ ^ false ].
"The last literal requires special checking instead of using #literalEqual:"
1 to: numLits - 1 do: [ :index |
literal1 := self literalAt: index.
literal2 := method literalAt: index.
(literal1 == literal2 or: [ literal1 literalEqual: literal2 ])
ifFalse: [ ^ false ] ].
"we can't do = on outer code or it will recursively call this code"
^ true
]
{ #category : #accessing }
CompiledBlock >> selector [
^ self outerCode selector
]
{ #category : #accessing }
CompiledBlock >> sourceCode [
^ self outerCode sourceCode
]