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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
%def field(helper=""):
/*
* General field read / write (iget-* iput-* sget-* sput-*).
*/
.extern $helper
mov r0, rPC @ arg0: Instruction* inst
mov r1, rINST @ arg1: uint16_t inst_data
add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf
mov r3, rSELF @ arg3: Thread* self
PREFETCH_INST 2 @ prefetch next opcode
bl $helper
cmp r0, #0
beq MterpPossibleException
ADVANCE 2
GET_INST_OPCODE ip @ extract opcode from rINST
GOTO_OPCODE ip @ jump to next instruction
%def op_check_cast():
/*
* Check to see if a cast from one class to another is allowed.
*/
/* check-cast vAA, class@BBBB */
EXPORT_PC
FETCH r0, 1 @ r0<- BBBB
mov r1, rINST, lsr #8 @ r1<- AA
VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
bl MterpCheckCast @ (index, &obj, method, self)
PREFETCH_INST 2
cmp r0, #0
bne MterpPossibleException
ADVANCE 2
GET_INST_OPCODE ip @ extract opcode from rINST
GOTO_OPCODE ip @ jump to next instruction
%def op_iget(is_object=False, is_wide=False, load="ldr", helper="MterpIGetU32"):
@ Fast-path which gets the field offset from thread-local cache.
add r0, rSELF, #THREAD_INTERPRETER_CACHE_OFFSET @ cache address
ubfx r1, rPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 @ entry index
add r0, r0, r1, lsl #3 @ entry address within the cache
ldrd r0, r1, [r0] @ entry key (pc) and value (offset)
mov r2, rINST, lsr #12 @ B
GET_VREG r2, r2 @ object we're operating on
cmp r0, rPC
% slow_path_label = add_helper(lambda: field(helper))
bne ${slow_path_label} @ cache miss
cmp r2, #0
beq common_errNullObject @ null object
% if is_wide:
ldrd r0, r1, [r1, r2] @ r0,r1 <- obj.field
% else:
${load} r0, [r2, r1] @ r0 <- obj.field
% #endif
% if is_object:
UNPOISON_HEAP_REF r0
#if defined(USE_READ_BARRIER)
# if defined(USE_BAKER_READ_BARRIER)
ldr ip, [rSELF, #THREAD_IS_GC_MARKING_OFFSET]
cmp ip, #0
bne .L_${opcode}_mark @ GC is active
.L_${opcode}_marked:
# else
bl artReadBarrierMark @ r0 <- artReadBarrierMark(r0)
# endif
#endif
% #endif
ubfx r2, rINST, #8, #4 @ A
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
% if is_object:
SET_VREG_OBJECT r0, r2 @ fp[A]<- r0
% elif is_wide:
SET_VREG_WIDE r0, r1, r2 @ fp[A]<- r0, r1
% else:
SET_VREG r0, r2 @ fp[A]<- r0
% #endif
GET_INST_OPCODE ip @ extract opcode from rINST
GOTO_OPCODE ip @ jump to next instruction
% if is_object:
#if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER)
.L_${opcode}_mark:
bl artReadBarrierMark @ r0 <- artReadBarrierMark(r0)
b .L_${opcode}_marked
#endif
% #endif
%def op_iget_boolean():
% op_iget(load="ldrb", helper="MterpIGetU8")
%def op_iget_byte():
% op_iget(load="ldrsb", helper="MterpIGetI8")
%def op_iget_char():
% op_iget(load="ldrh", helper="MterpIGetU16")
%def op_iget_object():
% op_iget(is_object=True, helper="MterpIGetObj")
%def op_iget_short():
% op_iget(load="ldrsh", helper="MterpIGetI16")
%def op_iget_wide():
% op_iget(is_wide=True, helper="MterpIGetU64")
%def op_instance_of():
/*
* Check to see if an object reference is an instance of a class.
*
* Most common situation is a non-null object, being compared against
* an already-resolved class.
*/
/* instance-of vA, vB, class@CCCC */
EXPORT_PC
FETCH r0, 1 @ r0<- CCCC
mov r1, rINST, lsr #12 @ r1<- B
VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
bl MterpInstanceOf @ (index, &obj, method, self)
ldr r1, [rSELF, #THREAD_EXCEPTION_OFFSET]
ubfx r9, rINST, #8, #4 @ r9<- A
PREFETCH_INST 2
cmp r1, #0 @ exception pending?
bne MterpException
ADVANCE 2 @ advance rPC
SET_VREG r0, r9 @ vA<- r0
GET_INST_OPCODE ip @ extract opcode from rINST
GOTO_OPCODE ip @ jump to next instruction
%def op_iput(helper="MterpIPutU32"):
% field(helper=helper)
%def op_iput_boolean():
% op_iput(helper="MterpIPutU8")
%def op_iput_byte():
% op_iput(helper="MterpIPutI8")
%def op_iput_char():
% op_iput(helper="MterpIPutU16")
%def op_iput_object():
% op_iput(helper="MterpIPutObj")
%def op_iput_short():
% op_iput(helper="MterpIPutI16")
%def op_iput_wide():
% op_iput(helper="MterpIPutU64")
%def op_new_instance():
/*
* Create a new instance of a class.
*/
/* new-instance vAA, class@BBBB */
EXPORT_PC
add r0, rFP, #OFF_FP_SHADOWFRAME
mov r1, rSELF
mov r2, rINST
bl MterpNewInstance @ (shadow_frame, self, inst_data)
cmp r0, #0
beq MterpPossibleException
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
GET_INST_OPCODE ip @ extract opcode from rINST
GOTO_OPCODE ip @ jump to next instruction
%def op_sget(helper="MterpSGetU32"):
% field(helper=helper)
%def op_sget_boolean():
% op_sget(helper="MterpSGetU8")
%def op_sget_byte():
% op_sget(helper="MterpSGetI8")
%def op_sget_char():
% op_sget(helper="MterpSGetU16")
%def op_sget_object():
% op_sget(helper="MterpSGetObj")
%def op_sget_short():
% op_sget(helper="MterpSGetI16")
%def op_sget_wide():
% op_sget(helper="MterpSGetU64")
%def op_sput(helper="MterpSPutU32"):
% field(helper=helper)
%def op_sput_boolean():
% op_sput(helper="MterpSPutU8")
%def op_sput_byte():
% op_sput(helper="MterpSPutI8")
%def op_sput_char():
% op_sput(helper="MterpSPutU16")
%def op_sput_object():
% op_sput(helper="MterpSPutObj")
%def op_sput_short():
% op_sput(helper="MterpSPutI16")
%def op_sput_wide():
% op_sput(helper="MterpSPutU64")
|