OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/deopt_instructions.h" | 5 #include "vm/deopt_instructions.h" |
6 | 6 |
7 #include "vm/assembler_macros.h" | 7 #include "vm/assembler_macros.h" |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 #include "vm/locations.h" | 9 #include "vm/locations.h" |
10 #include "vm/parser.h" | 10 #include "vm/parser.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
54 // 'from_index' represents the slot index of the frame (0 being first argument) | 54 // 'from_index' represents the slot index of the frame (0 being first argument) |
55 // and accounts for saved return address, frame pointer and pc marker. | 55 // and accounts for saved return address, frame pointer and pc marker. |
56 class DeoptStackSlotInstr : public DeoptInstr { | 56 class DeoptStackSlotInstr : public DeoptInstr { |
57 public: | 57 public: |
58 explicit DeoptStackSlotInstr(intptr_t from_index) | 58 explicit DeoptStackSlotInstr(intptr_t from_index) |
59 : stack_slot_index_(from_index) { | 59 : stack_slot_index_(from_index) { |
60 ASSERT(stack_slot_index_ >= 0); | 60 ASSERT(stack_slot_index_ >= 0); |
61 } | 61 } |
62 | 62 |
63 virtual intptr_t from_index() const { return stack_slot_index_; } | 63 virtual intptr_t from_index() const { return stack_slot_index_; } |
64 virtual DeoptInstr::Kind kind() const { return kCopyStackSlot; } | 64 virtual DeoptInstr::Kind kind() const { return kStackSlot; } |
65 | 65 |
66 virtual const char* ToCString() const { | 66 virtual const char* ToCString() const { |
67 const char* format = "s%"Pd""; | 67 const char* format = "s%"Pd""; |
68 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); | 68 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); |
69 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 69 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
70 OS::SNPrint(chars, len + 1, format, stack_slot_index_); | 70 OS::SNPrint(chars, len + 1, format, stack_slot_index_); |
71 return chars; | 71 return chars; |
72 } | 72 } |
73 | 73 |
74 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 74 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
(...skipping 12 matching lines...) Expand all Loading... | |
87 | 87 |
88 | 88 |
89 class DeoptDoubleStackSlotInstr : public DeoptInstr { | 89 class DeoptDoubleStackSlotInstr : public DeoptInstr { |
90 public: | 90 public: |
91 explicit DeoptDoubleStackSlotInstr(intptr_t from_index) | 91 explicit DeoptDoubleStackSlotInstr(intptr_t from_index) |
92 : stack_slot_index_(from_index) { | 92 : stack_slot_index_(from_index) { |
93 ASSERT(stack_slot_index_ >= 0); | 93 ASSERT(stack_slot_index_ >= 0); |
94 } | 94 } |
95 | 95 |
96 virtual intptr_t from_index() const { return stack_slot_index_; } | 96 virtual intptr_t from_index() const { return stack_slot_index_; } |
97 virtual DeoptInstr::Kind kind() const { return kCopyDoubleStackSlot; } | 97 virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; } |
98 | 98 |
99 virtual const char* ToCString() const { | 99 virtual const char* ToCString() const { |
100 const char* format = "ds%"Pd""; | 100 const char* format = "ds%"Pd""; |
101 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); | 101 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); |
102 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 102 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
103 OS::SNPrint(chars, len + 1, format, stack_slot_index_); | 103 OS::SNPrint(chars, len + 1, format, stack_slot_index_); |
104 return chars; | 104 return chars; |
105 } | 105 } |
106 | 106 |
107 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 107 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
(...skipping 15 matching lines...) Expand all Loading... | |
123 | 123 |
124 | 124 |
125 class DeoptInt64StackSlotInstr : public DeoptInstr { | 125 class DeoptInt64StackSlotInstr : public DeoptInstr { |
126 public: | 126 public: |
127 explicit DeoptInt64StackSlotInstr(intptr_t from_index) | 127 explicit DeoptInt64StackSlotInstr(intptr_t from_index) |
128 : stack_slot_index_(from_index) { | 128 : stack_slot_index_(from_index) { |
129 ASSERT(stack_slot_index_ >= 0); | 129 ASSERT(stack_slot_index_ >= 0); |
130 } | 130 } |
131 | 131 |
132 virtual intptr_t from_index() const { return stack_slot_index_; } | 132 virtual intptr_t from_index() const { return stack_slot_index_; } |
133 virtual DeoptInstr::Kind kind() const { return kCopyInt64StackSlot; } | 133 virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; } |
134 | 134 |
135 virtual const char* ToCString() const { | 135 virtual const char* ToCString() const { |
136 const char* format = "ms%"Pd""; | 136 const char* format = "ms%"Pd""; |
137 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); | 137 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); |
138 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 138 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
139 OS::SNPrint(chars, len + 1, format, stack_slot_index_); | 139 OS::SNPrint(chars, len + 1, format, stack_slot_index_); |
140 return chars; | 140 return chars; |
141 } | 141 } |
142 | 142 |
143 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 143 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
(...skipping 15 matching lines...) Expand all Loading... | |
159 private: | 159 private: |
160 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 160 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
161 | 161 |
162 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr); | 162 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr); |
163 }; | 163 }; |
164 | 164 |
165 | 165 |
166 // Deoptimization instruction creating return address using function and | 166 // Deoptimization instruction creating return address using function and |
167 // deopt-id stored at 'object_table_index'. Uses the deopt-after | 167 // deopt-id stored at 'object_table_index'. Uses the deopt-after |
168 // continuation point. | 168 // continuation point. |
169 class DeoptRetAddrAfterInstr : public DeoptInstr { | 169 class DeoptRetAfterAddressInstr : public DeoptInstr { |
170 public: | 170 public: |
171 DeoptRetAddrAfterInstr(intptr_t object_table_index, intptr_t deopt_id) | 171 DeoptRetAfterAddressInstr(intptr_t object_table_index, intptr_t deopt_id) |
172 : object_table_index_(object_table_index), deopt_id_(deopt_id) { | 172 : object_table_index_(object_table_index), deopt_id_(deopt_id) { |
173 ASSERT(object_table_index >= 0); | 173 ASSERT(object_table_index >= 0); |
174 ASSERT(deopt_id >= 0); | 174 ASSERT(deopt_id >= 0); |
175 } | 175 } |
176 | 176 |
177 explicit DeoptRetAddrAfterInstr(intptr_t from_index) | 177 explicit DeoptRetAfterAddressInstr(intptr_t from_index) |
178 : object_table_index_(ObjectTableIndex::decode(from_index)), | 178 : object_table_index_(ObjectTableIndex::decode(from_index)), |
179 deopt_id_(DeoptId::decode(from_index)) { | 179 deopt_id_(DeoptId::decode(from_index)) { |
180 } | 180 } |
181 | 181 |
182 virtual intptr_t from_index() const { | 182 virtual intptr_t from_index() const { |
183 return ObjectTableIndex::encode(object_table_index_) | | 183 return ObjectTableIndex::encode(object_table_index_) | |
184 DeoptId::encode(deopt_id_); | 184 DeoptId::encode(deopt_id_); |
185 } | 185 } |
186 virtual DeoptInstr::Kind kind() const { return kSetRetAfterAddress; } | 186 virtual DeoptInstr::Kind kind() const { return kRetAfterAddress; } |
187 | 187 |
188 virtual const char* ToCString() const { | 188 virtual const char* ToCString() const { |
189 const char* format = "ret aft oti:%"Pd"(%"Pd")"; | 189 const char* format = "ret aft oti:%"Pd"(%"Pd")"; |
190 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_); | 190 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_); |
191 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 191 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
192 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_); | 192 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_); |
193 return chars; | 193 return chars; |
194 } | 194 } |
195 | 195 |
196 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 196 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
197 Function& function = Function::Handle(deopt_context->isolate()); | 197 Function& function = Function::Handle(deopt_context->isolate()); |
198 function ^= deopt_context->ObjectAt(object_table_index_); | 198 function ^= deopt_context->ObjectAt(object_table_index_); |
199 const Code& code = | 199 const Code& code = |
200 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | 200 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
201 uword continue_at_pc = code.GetDeoptAfterPcAtDeoptId(deopt_id_); | 201 uword continue_at_pc = code.GetDeoptAfterPcAtDeoptId(deopt_id_); |
202 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | 202 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
203 *to_addr = continue_at_pc; | 203 *to_addr = continue_at_pc; |
204 } | 204 } |
205 | 205 |
206 private: | 206 private: |
207 static const intptr_t kFieldWidth = kBitsPerWord / 2; | 207 static const intptr_t kFieldWidth = kBitsPerWord / 2; |
208 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { }; | 208 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { }; |
209 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; | 209 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; |
210 | 210 |
211 const intptr_t object_table_index_; | 211 const intptr_t object_table_index_; |
212 const intptr_t deopt_id_; | 212 const intptr_t deopt_id_; |
213 | 213 |
214 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrAfterInstr); | 214 DISALLOW_COPY_AND_ASSIGN(DeoptRetAfterAddressInstr); |
215 }; | 215 }; |
216 | 216 |
217 | 217 |
218 // Deoptimization instruction creating return address using function and | 218 // Deoptimization instruction creating return address using function and |
219 // deopt-id stored at 'object_table_index'. Uses the deopt-before | 219 // deopt-id stored at 'object_table_index'. Uses the deopt-before |
220 // continuation point. | 220 // continuation point. |
221 class DeoptRetAddrBeforeInstr : public DeoptInstr { | 221 class DeoptRetBeforeAddressInstr : public DeoptInstr { |
222 public: | 222 public: |
223 DeoptRetAddrBeforeInstr(intptr_t object_table_index, intptr_t deopt_id) | 223 DeoptRetBeforeAddressInstr(intptr_t object_table_index, intptr_t deopt_id) |
224 : object_table_index_(object_table_index), deopt_id_(deopt_id) { | 224 : object_table_index_(object_table_index), deopt_id_(deopt_id) { |
225 ASSERT(object_table_index >= 0); | 225 ASSERT(object_table_index >= 0); |
226 ASSERT(deopt_id_ >= 0); | 226 ASSERT(deopt_id >= 0); |
227 } | 227 } |
228 | 228 |
229 explicit DeoptRetAddrBeforeInstr(intptr_t from_index) | 229 explicit DeoptRetBeforeAddressInstr(intptr_t from_index) |
230 : object_table_index_(ObjectTableIndex::decode(from_index)), | 230 : object_table_index_(ObjectTableIndex::decode(from_index)), |
231 deopt_id_(DeoptId::decode(from_index)) { | 231 deopt_id_(DeoptId::decode(from_index)) { |
232 } | 232 } |
233 | 233 |
234 virtual intptr_t from_index() const { | 234 virtual intptr_t from_index() const { |
235 return ObjectTableIndex::encode(object_table_index_) | | 235 return ObjectTableIndex::encode(object_table_index_) | |
236 DeoptId::encode(deopt_id_); | 236 DeoptId::encode(deopt_id_); |
237 } | 237 } |
238 virtual DeoptInstr::Kind kind() const { return kSetRetBeforeAddress; } | 238 virtual DeoptInstr::Kind kind() const { return kRetBeforeAddress; } |
239 | 239 |
240 virtual const char* ToCString() const { | 240 virtual const char* ToCString() const { |
241 const char* format = "ret bef oti:%"Pd"(%"Pd")"; | 241 const char* format = "ret bef oti:%"Pd"(%"Pd")"; |
242 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_); | 242 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_); |
243 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 243 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
244 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_); | 244 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_); |
245 return chars; | 245 return chars; |
246 } | 246 } |
247 | 247 |
248 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 248 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
249 Function& function = Function::Handle(deopt_context->isolate()); | 249 Function& function = Function::Handle(deopt_context->isolate()); |
250 function ^= deopt_context->ObjectAt(object_table_index_); | 250 function ^= deopt_context->ObjectAt(object_table_index_); |
251 const Code& code = | 251 const Code& code = |
252 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | 252 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
253 uword continue_at_pc = code.GetDeoptBeforePcAtDeoptId(deopt_id_); | 253 uword continue_at_pc = code.GetDeoptBeforePcAtDeoptId(deopt_id_); |
254 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | 254 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
255 *to_addr = continue_at_pc; | 255 *to_addr = continue_at_pc; |
256 } | 256 } |
257 | 257 |
258 private: | 258 private: |
259 static const intptr_t kFieldWidth = kBitsPerWord / 2; | 259 static const intptr_t kFieldWidth = kBitsPerWord / 2; |
260 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { }; | 260 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { }; |
261 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; | 261 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; |
262 | 262 |
263 const intptr_t object_table_index_; | 263 const intptr_t object_table_index_; |
264 const intptr_t deopt_id_; | 264 const intptr_t deopt_id_; |
265 | 265 |
266 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrBeforeInstr); | 266 DISALLOW_COPY_AND_ASSIGN(DeoptRetBeforeAddressInstr); |
267 }; | 267 }; |
268 | 268 |
269 | 269 |
270 // Deoptimization instruction moving a constant stored at 'object_table_index'. | 270 // Deoptimization instruction moving a constant stored at 'object_table_index'. |
271 class DeoptConstantInstr : public DeoptInstr { | 271 class DeoptConstantInstr : public DeoptInstr { |
272 public: | 272 public: |
273 explicit DeoptConstantInstr(intptr_t object_table_index) | 273 explicit DeoptConstantInstr(intptr_t object_table_index) |
274 : object_table_index_(object_table_index) { | 274 : object_table_index_(object_table_index) { |
275 ASSERT(object_table_index >= 0); | 275 ASSERT(object_table_index >= 0); |
276 } | 276 } |
277 | 277 |
278 virtual intptr_t from_index() const { return object_table_index_; } | 278 virtual intptr_t from_index() const { return object_table_index_; } |
279 virtual DeoptInstr::Kind kind() const { return kCopyConstant; } | 279 virtual DeoptInstr::Kind kind() const { return kConstant; } |
280 | 280 |
281 virtual const char* ToCString() const { | 281 virtual const char* ToCString() const { |
282 const char* format = "const oti:%"Pd""; | 282 const char* format = "const oti:%"Pd""; |
283 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); | 283 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); |
284 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 284 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
285 OS::SNPrint(chars, len + 1, format, object_table_index_); | 285 OS::SNPrint(chars, len + 1, format, object_table_index_); |
286 return chars; | 286 return chars; |
287 } | 287 } |
288 | 288 |
289 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 289 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
(...skipping 11 matching lines...) Expand all Loading... | |
301 }; | 301 }; |
302 | 302 |
303 | 303 |
304 // Deoptimization instruction moving a CPU register. | 304 // Deoptimization instruction moving a CPU register. |
305 class DeoptRegisterInstr: public DeoptInstr { | 305 class DeoptRegisterInstr: public DeoptInstr { |
306 public: | 306 public: |
307 explicit DeoptRegisterInstr(intptr_t reg_as_int) | 307 explicit DeoptRegisterInstr(intptr_t reg_as_int) |
308 : reg_(static_cast<Register>(reg_as_int)) {} | 308 : reg_(static_cast<Register>(reg_as_int)) {} |
309 | 309 |
310 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 310 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
311 virtual DeoptInstr::Kind kind() const { return kCopyRegister; } | 311 virtual DeoptInstr::Kind kind() const { return kRegister; } |
312 | 312 |
313 virtual const char* ToCString() const { | 313 virtual const char* ToCString() const { |
314 return Assembler::RegisterName(reg_); | 314 return Assembler::RegisterName(reg_); |
315 } | 315 } |
316 | 316 |
317 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 317 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
318 intptr_t value = deopt_context->RegisterValue(reg_); | 318 intptr_t value = deopt_context->RegisterValue(reg_); |
319 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | 319 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
320 *to_addr = value; | 320 *to_addr = value; |
321 } | 321 } |
322 | 322 |
323 private: | 323 private: |
324 const Register reg_; | 324 const Register reg_; |
325 | 325 |
326 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); | 326 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); |
327 }; | 327 }; |
328 | 328 |
329 | 329 |
330 // Deoptimization instruction moving an XMM register. | 330 // Deoptimization instruction moving an XMM register. |
331 class DeoptXmmRegisterInstr: public DeoptInstr { | 331 class DeoptXmmRegisterInstr: public DeoptInstr { |
332 public: | 332 public: |
333 explicit DeoptXmmRegisterInstr(intptr_t reg_as_int) | 333 explicit DeoptXmmRegisterInstr(intptr_t reg_as_int) |
334 : reg_(static_cast<XmmRegister>(reg_as_int)) {} | 334 : reg_(static_cast<XmmRegister>(reg_as_int)) {} |
335 | 335 |
336 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 336 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
337 virtual DeoptInstr::Kind kind() const { return kCopyXmmRegister; } | 337 virtual DeoptInstr::Kind kind() const { return kXmmRegister; } |
338 | 338 |
339 virtual const char* ToCString() const { | 339 virtual const char* ToCString() const { |
340 return Assembler::XmmRegisterName(reg_); | 340 return Assembler::XmmRegisterName(reg_); |
341 } | 341 } |
342 | 342 |
343 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 343 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
344 double value = deopt_context->XmmRegisterValue(reg_); | 344 double value = deopt_context->XmmRegisterValue(reg_); |
345 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | 345 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
346 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 346 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
347 Isolate::Current()->DeferDoubleMaterialization( | 347 Isolate::Current()->DeferDoubleMaterialization( |
348 value, reinterpret_cast<RawDouble**>(to_addr)); | 348 value, reinterpret_cast<RawDouble**>(to_addr)); |
349 } | 349 } |
350 | 350 |
351 private: | 351 private: |
352 const XmmRegister reg_; | 352 const XmmRegister reg_; |
353 | 353 |
354 DISALLOW_COPY_AND_ASSIGN(DeoptXmmRegisterInstr); | 354 DISALLOW_COPY_AND_ASSIGN(DeoptXmmRegisterInstr); |
355 }; | 355 }; |
356 | 356 |
357 | 357 |
358 class DeoptInt64XmmRegisterInstr: public DeoptInstr { | 358 class DeoptInt64XmmRegisterInstr: public DeoptInstr { |
359 public: | 359 public: |
360 explicit DeoptInt64XmmRegisterInstr(intptr_t reg_as_int) | 360 explicit DeoptInt64XmmRegisterInstr(intptr_t reg_as_int) |
361 : reg_(static_cast<XmmRegister>(reg_as_int)) {} | 361 : reg_(static_cast<XmmRegister>(reg_as_int)) {} |
362 | 362 |
363 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 363 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
364 virtual DeoptInstr::Kind kind() const { return kCopyInt64XmmRegister; } | 364 virtual DeoptInstr::Kind kind() const { return kInt64XmmRegister; } |
365 | 365 |
366 virtual const char* ToCString() const { | 366 virtual const char* ToCString() const { |
367 const char* format = "%s(m)"; | 367 const char* format = "%s(m)"; |
368 intptr_t len = | 368 intptr_t len = |
369 OS::SNPrint(NULL, 0, format, Assembler::XmmRegisterName(reg_)); | 369 OS::SNPrint(NULL, 0, format, Assembler::XmmRegisterName(reg_)); |
370 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 370 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
371 OS::SNPrint(chars, len + 1, format, Assembler::XmmRegisterName(reg_)); | 371 OS::SNPrint(chars, len + 1, format, Assembler::XmmRegisterName(reg_)); |
372 return chars; | 372 return chars; |
373 } | 373 } |
374 | 374 |
(...skipping 20 matching lines...) Expand all Loading... | |
395 // Deoptimization instruction creating a PC marker for the code of | 395 // Deoptimization instruction creating a PC marker for the code of |
396 // function at 'object_table_index'. | 396 // function at 'object_table_index'. |
397 class DeoptPcMarkerInstr : public DeoptInstr { | 397 class DeoptPcMarkerInstr : public DeoptInstr { |
398 public: | 398 public: |
399 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 399 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
400 : object_table_index_(object_table_index) { | 400 : object_table_index_(object_table_index) { |
401 ASSERT(object_table_index >= 0); | 401 ASSERT(object_table_index >= 0); |
402 } | 402 } |
403 | 403 |
404 virtual intptr_t from_index() const { return object_table_index_; } | 404 virtual intptr_t from_index() const { return object_table_index_; } |
405 virtual DeoptInstr::Kind kind() const { return kSetPcMarker; } | 405 virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
406 | 406 |
407 virtual const char* ToCString() const { | 407 virtual const char* ToCString() const { |
408 const char* format = "pcmark oti:%"Pd""; | 408 const char* format = "pcmark oti:%"Pd""; |
409 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); | 409 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); |
410 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 410 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
411 OS::SNPrint(chars, len + 1, format, object_table_index_); | 411 OS::SNPrint(chars, len + 1, format, object_table_index_); |
412 return chars; | 412 return chars; |
413 } | 413 } |
414 | 414 |
415 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 415 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
(...skipping 20 matching lines...) Expand all Loading... | |
436 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); | 436 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); |
437 }; | 437 }; |
438 | 438 |
439 | 439 |
440 // Deoptimization instruction copying the caller saved FP from optimized frame. | 440 // Deoptimization instruction copying the caller saved FP from optimized frame. |
441 class DeoptCallerFpInstr : public DeoptInstr { | 441 class DeoptCallerFpInstr : public DeoptInstr { |
442 public: | 442 public: |
443 DeoptCallerFpInstr() {} | 443 DeoptCallerFpInstr() {} |
444 | 444 |
445 virtual intptr_t from_index() const { return 0; } | 445 virtual intptr_t from_index() const { return 0; } |
446 virtual DeoptInstr::Kind kind() const { return kSetCallerFp; } | 446 virtual DeoptInstr::Kind kind() const { return kCallerFp; } |
447 | 447 |
448 virtual const char* ToCString() const { | 448 virtual const char* ToCString() const { |
449 return "callerfp"; | 449 return "callerfp"; |
450 } | 450 } |
451 | 451 |
452 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 452 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
453 intptr_t from = deopt_context->GetCallerFp(); | 453 intptr_t from = deopt_context->GetCallerFp(); |
454 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | 454 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
455 *to_addr = from; | 455 *to_addr = from; |
456 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr)); | 456 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr)); |
457 } | 457 } |
458 | 458 |
459 private: | 459 private: |
460 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 460 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
461 }; | 461 }; |
462 | 462 |
463 | 463 |
464 // Deoptimization instruction copying the caller return address from optimized | 464 // Deoptimization instruction copying the caller return address from optimized |
465 // frame. | 465 // frame. |
466 class DeoptCallerPcInstr : public DeoptInstr { | 466 class DeoptCallerPcInstr : public DeoptInstr { |
467 public: | 467 public: |
468 DeoptCallerPcInstr() {} | 468 DeoptCallerPcInstr() {} |
469 | 469 |
470 virtual intptr_t from_index() const { return 0; } | 470 virtual intptr_t from_index() const { return 0; } |
471 virtual DeoptInstr::Kind kind() const { return kSetCallerPc; } | 471 virtual DeoptInstr::Kind kind() const { return kCallerPc; } |
472 | 472 |
473 virtual const char* ToCString() const { | 473 virtual const char* ToCString() const { |
474 return "callerpc"; | 474 return "callerpc"; |
475 } | 475 } |
476 | 476 |
477 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 477 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
478 intptr_t from = deopt_context->GetFromPc(); | 478 intptr_t from = deopt_context->GetFromPc(); |
479 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | 479 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
480 *to_addr = from; | 480 *to_addr = from; |
481 } | 481 } |
482 | 482 |
483 private: | 483 private: |
484 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 484 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
485 }; | 485 }; |
486 | 486 |
487 | 487 |
488 class DeoptSuffixInstr : public DeoptInstr { | |
srdjan
2012/10/08 16:37:58
Add brief comment about the class.
| |
489 public: | |
490 DeoptSuffixInstr(intptr_t info_number, intptr_t suffix_length) | |
491 : info_number_(info_number), suffix_length_(suffix_length) { | |
492 ASSERT(info_number >= 0); | |
493 ASSERT(suffix_length >= 0); | |
494 } | |
495 | |
496 explicit DeoptSuffixInstr(intptr_t from_index) | |
497 : info_number_(InfoNumber::decode(from_index)), | |
498 suffix_length_(SuffixLength::decode(from_index)) { | |
499 } | |
500 | |
501 virtual intptr_t from_index() const { | |
502 return InfoNumber::encode(info_number_) | | |
503 SuffixLength::encode(suffix_length_); | |
504 } | |
505 virtual DeoptInstr::Kind kind() const { return kSuffix; } | |
506 | |
507 virtual const char* ToCString() const { | |
508 const char* format = "suffix %"Pd":%"Pd; | |
509 intptr_t len = OS::SNPrint(NULL, 0, format, info_number_, suffix_length_); | |
510 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
511 OS::SNPrint(chars, len + 1, format, info_number_, suffix_length_); | |
512 return chars; | |
513 } | |
514 | |
515 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | |
516 UNREACHABLE(); | |
Kevin Millikin (Google)
2012/10/05 14:31:55
Notice. The strategy is to 'uncompress' the entry
| |
517 } | |
518 | |
519 private: | |
520 friend class DeoptInstr; | |
521 | |
522 static const intptr_t kFieldWidth = kBitsPerWord / 2; | |
523 class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { }; | |
524 class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; | |
525 | |
526 const intptr_t info_number_; | |
527 const intptr_t suffix_length_; | |
528 | |
529 DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr); | |
530 }; | |
531 | |
532 | |
533 intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) { | |
534 *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index); | |
535 return DeoptSuffixInstr::SuffixLength::decode(from_index); | |
536 } | |
537 | |
538 | |
488 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { | 539 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { |
489 Kind kind = static_cast<Kind>(kind_as_int); | 540 Kind kind = static_cast<Kind>(kind_as_int); |
490 switch (kind) { | 541 switch (kind) { |
491 case kCopyStackSlot: return new DeoptStackSlotInstr(from_index); | 542 case kStackSlot: return new DeoptStackSlotInstr(from_index); |
492 case kCopyDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); | 543 case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); |
493 case kCopyInt64StackSlot: return new DeoptInt64StackSlotInstr(from_index); | 544 case kInt64StackSlot: return new DeoptInt64StackSlotInstr(from_index); |
494 case kSetRetAfterAddress: return new DeoptRetAddrAfterInstr(from_index); | 545 case kRetAfterAddress: return new DeoptRetAfterAddressInstr(from_index); |
495 case kSetRetBeforeAddress: return new DeoptRetAddrBeforeInstr(from_index); | 546 case kRetBeforeAddress: return new DeoptRetBeforeAddressInstr(from_index); |
496 case kCopyConstant: return new DeoptConstantInstr(from_index); | 547 case kConstant: return new DeoptConstantInstr(from_index); |
497 case kCopyRegister: return new DeoptRegisterInstr(from_index); | 548 case kRegister: return new DeoptRegisterInstr(from_index); |
498 case kCopyXmmRegister: return new DeoptXmmRegisterInstr(from_index); | 549 case kXmmRegister: return new DeoptXmmRegisterInstr(from_index); |
499 case kCopyInt64XmmRegister: | 550 case kInt64XmmRegister: return new DeoptInt64XmmRegisterInstr(from_index); |
500 return new DeoptInt64XmmRegisterInstr(from_index); | 551 case kPcMarker: return new DeoptPcMarkerInstr(from_index); |
501 case kSetPcMarker: return new DeoptPcMarkerInstr(from_index); | 552 case kCallerFp: return new DeoptCallerFpInstr(); |
502 case kSetCallerFp: return new DeoptCallerFpInstr(); | 553 case kCallerPc: return new DeoptCallerPcInstr(); |
503 case kSetCallerPc: return new DeoptCallerPcInstr(); | 554 case kSuffix: return new DeoptSuffixInstr(from_index); |
504 } | 555 } |
505 UNREACHABLE(); | 556 UNREACHABLE(); |
506 return NULL; | 557 return NULL; |
507 } | 558 } |
508 | 559 |
509 | 560 |
561 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { | |
562 public: | |
563 // Construct the root node representing the implicit "shared" terminator | |
564 // at the end of each deopt info. | |
565 TrieNode() : instruction_(NULL), info_number_(-1), children_(16) { } | |
566 | |
567 // Construct a node representing a written instruction. | |
568 TrieNode(DeoptInstr* instruction, intptr_t info_number) | |
569 : instruction_(instruction), info_number_(info_number), children_(4) { } | |
570 | |
571 intptr_t info_number() const { return info_number_; } | |
572 | |
573 void AddChild(TrieNode* child) { | |
574 if (child != NULL) children_.Add(child); | |
srdjan
2012/10/08 16:37:58
When can you call this with child==NULL ?
| |
575 } | |
576 | |
577 TrieNode* FindChild(const DeoptInstr& instruction) { | |
578 for (intptr_t i = 0; i < children_.length(); ++i) { | |
579 TrieNode* child = children_[i]; | |
580 if (child->instruction_->Equals(instruction)) return child; | |
581 } | |
582 return NULL; | |
583 } | |
584 | |
585 private: | |
586 const DeoptInstr* instruction_; // Istruction that was written. | |
srdjan
2012/10/08 16:37:58
s/Istruction/Instruction/
| |
587 const intptr_t info_number_; // Index of the deopt info it was written to. | |
588 | |
589 GrowableArray<TrieNode*> children_; | |
590 }; | |
591 | |
592 | |
593 DeoptInfoBuilder::DeoptInfoBuilder(const intptr_t num_args) | |
594 : instructions_(), | |
595 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())), | |
596 num_args_(num_args), | |
597 trie_root_(new TrieNode()), | |
598 current_info_number_(0) { | |
599 } | |
600 | |
601 | |
510 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | 602 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { |
511 for (intptr_t i = 0; i < object_table_.Length(); i++) { | 603 for (intptr_t i = 0; i < object_table_.Length(); i++) { |
512 if (object_table_.At(i) == obj.raw()) { | 604 if (object_table_.At(i) == obj.raw()) { |
513 return i; | 605 return i; |
514 } | 606 } |
515 } | 607 } |
516 // Add object. | 608 // Add object. |
517 const intptr_t result = object_table_.Length(); | 609 const intptr_t result = object_table_.Length(); |
518 object_table_.Add(obj); | 610 object_table_.Add(obj); |
519 return result; | 611 return result; |
520 } | 612 } |
521 | 613 |
522 | 614 |
523 void DeoptInfoBuilder::AddReturnAddressBefore(const Function& function, | 615 void DeoptInfoBuilder::AddReturnAddressBefore(const Function& function, |
524 intptr_t deopt_id, | 616 intptr_t deopt_id, |
525 intptr_t to_index) { | 617 intptr_t to_index) { |
526 const intptr_t object_table_index = FindOrAddObjectInTable(function); | 618 const intptr_t object_table_index = FindOrAddObjectInTable(function); |
527 ASSERT(to_index == instructions_.length()); | 619 ASSERT(to_index == instructions_.length()); |
528 instructions_.Add(new DeoptRetAddrBeforeInstr(object_table_index, deopt_id)); | 620 instructions_.Add(new DeoptRetBeforeAddressInstr(object_table_index, |
621 deopt_id)); | |
529 } | 622 } |
530 | 623 |
531 | 624 |
532 void DeoptInfoBuilder::AddReturnAddressAfter(const Function& function, | 625 void DeoptInfoBuilder::AddReturnAddressAfter(const Function& function, |
533 intptr_t deopt_id, | 626 intptr_t deopt_id, |
534 intptr_t to_index) { | 627 intptr_t to_index) { |
535 const intptr_t object_table_index = FindOrAddObjectInTable(function); | 628 const intptr_t object_table_index = FindOrAddObjectInTable(function); |
536 ASSERT(to_index == instructions_.length()); | 629 ASSERT(to_index == instructions_.length()); |
537 instructions_.Add(new DeoptRetAddrAfterInstr(object_table_index, deopt_id)); | 630 instructions_.Add(new DeoptRetAfterAddressInstr(object_table_index, |
631 deopt_id)); | |
538 } | 632 } |
539 | 633 |
540 | 634 |
541 void DeoptInfoBuilder::AddPcMarker(const Function& function, | 635 void DeoptInfoBuilder::AddPcMarker(const Function& function, |
542 intptr_t to_index) { | 636 intptr_t to_index) { |
543 // Function object was already added by AddReturnAddress, find it. | 637 // Function object was already added by AddReturnAddress, find it. |
544 intptr_t from_index = FindOrAddObjectInTable(function); | 638 intptr_t from_index = FindOrAddObjectInTable(function); |
545 ASSERT(to_index == instructions_.length()); | 639 ASSERT(to_index == instructions_.length()); |
546 instructions_.Add(new DeoptPcMarkerInstr(from_index)); | 640 instructions_.Add(new DeoptPcMarkerInstr(from_index)); |
547 } | 641 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
593 instructions_.Add(new DeoptCallerFpInstr()); | 687 instructions_.Add(new DeoptCallerFpInstr()); |
594 } | 688 } |
595 | 689 |
596 | 690 |
597 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) { | 691 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) { |
598 ASSERT(to_index == instructions_.length()); | 692 ASSERT(to_index == instructions_.length()); |
599 instructions_.Add(new DeoptCallerPcInstr()); | 693 instructions_.Add(new DeoptCallerPcInstr()); |
600 } | 694 } |
601 | 695 |
602 | 696 |
603 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() const { | 697 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() { |
604 const intptr_t len = instructions_.length(); | 698 intptr_t length = instructions_.length(); |
605 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(len)); | 699 |
606 for (intptr_t i = 0; i < len; i++) { | 700 // Count the number of instructions that are a shared suffix of some deopt |
701 // info already written. | |
702 TrieNode* suffix = trie_root_; | |
703 intptr_t suffix_length = 0; | |
704 for (intptr_t i = length - 1; i >= 0; --i) { | |
705 TrieNode* node = suffix->FindChild(*instructions_[i]); | |
706 if (node == NULL) break; | |
707 suffix = node; | |
708 ++suffix_length; | |
709 } | |
710 | |
711 // Allocate space for the translation. If the shared suffix is longer | |
712 // than one instruction, we replace it with a single suffix instruction. | |
713 if (suffix_length > 1) length -= (suffix_length - 1); | |
714 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(length)); | |
715 | |
716 // Write the unshared instructions and build their sub-tree. | |
717 TrieNode* node = NULL; | |
718 intptr_t write_count = (suffix_length > 1) ? length - 1 : length; | |
719 for (intptr_t i = 0; i < write_count; ++i) { | |
607 DeoptInstr* instr = instructions_[i]; | 720 DeoptInstr* instr = instructions_[i]; |
608 deopt_info.SetAt(i, instr->kind(), instr->from_index()); | 721 deopt_info.SetAt(i, instr->kind(), instr->from_index()); |
722 TrieNode* child = node; | |
723 node = new TrieNode(instr, current_info_number_); | |
724 node->AddChild(child); | |
609 } | 725 } |
726 suffix->AddChild(node); | |
727 | |
728 if (suffix_length > 1) { | |
729 DeoptInstr* instr = | |
730 new DeoptSuffixInstr(suffix->info_number(), suffix_length); | |
731 deopt_info.SetAt(length - 1, instr->kind(), instr->from_index()); | |
732 } | |
733 | |
734 instructions_.Clear(); | |
735 ++current_info_number_; | |
610 return deopt_info.raw(); | 736 return deopt_info.raw(); |
611 } | 737 } |
612 | 738 |
613 | 739 |
614 intptr_t DeoptTable::SizeFor(intptr_t length) { | 740 intptr_t DeoptTable::SizeFor(intptr_t length) { |
615 return length * kEntrySize; | 741 return length * kEntrySize; |
616 } | 742 } |
617 | 743 |
618 void DeoptTable::SetEntry(const Array& table, | 744 void DeoptTable::SetEntry(const Array& table, |
619 intptr_t index, | 745 intptr_t index, |
(...skipping 19 matching lines...) Expand all Loading... | |
639 Smi* offset, | 765 Smi* offset, |
640 DeoptInfo* info, | 766 DeoptInfo* info, |
641 Smi* reason) { | 767 Smi* reason) { |
642 intptr_t i = index * kEntrySize; | 768 intptr_t i = index * kEntrySize; |
643 *offset ^= table.At(i); | 769 *offset ^= table.At(i); |
644 *info ^= table.At(i + 1); | 770 *info ^= table.At(i + 1); |
645 *reason ^= table.At(i + 2); | 771 *reason ^= table.At(i + 2); |
646 } | 772 } |
647 | 773 |
648 } // namespace dart | 774 } // namespace dart |
OLD | NEW |