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" |
11 | 11 |
12 namespace dart { | 12 namespace dart { |
13 | 13 |
14 DeoptimizationContext::DeoptimizationContext(intptr_t* to_frame_start, | 14 DeoptimizationContext::DeoptimizationContext(intptr_t* to_frame_start, |
15 intptr_t to_frame_size, | 15 intptr_t to_frame_size, |
16 const Array& object_table, | 16 const Array& object_table, |
17 intptr_t num_args) | 17 intptr_t num_args) |
18 : object_table_(object_table), | 18 : object_table_(object_table), |
19 to_frame_(to_frame_start), | 19 to_frame_(to_frame_start), |
20 to_frame_size_(to_frame_size), | 20 to_frame_size_(to_frame_size), |
21 from_frame_(NULL), | 21 from_frame_(NULL), |
22 from_frame_size_(0), | 22 from_frame_size_(0), |
23 registers_copy_(NULL), | 23 registers_copy_(NULL), |
| 24 xmm_registers_copy_(NULL), |
24 num_args_(num_args), | 25 num_args_(num_args), |
25 isolate_(Isolate::Current()) { | 26 isolate_(Isolate::Current()) { |
26 from_frame_ = isolate_->deopt_frame_copy(); | 27 from_frame_ = isolate_->deopt_frame_copy(); |
27 from_frame_size_ = isolate_->deopt_frame_copy_size(); | 28 from_frame_size_ = isolate_->deopt_frame_copy_size(); |
28 registers_copy_ = isolate_->deopt_registers_copy(); | 29 registers_copy_ = isolate_->deopt_cpu_registers_copy(); |
| 30 xmm_registers_copy_ = isolate_->deopt_xmm_registers_copy(); |
29 } | 31 } |
30 | 32 |
31 | 33 |
32 intptr_t* DeoptimizationContext::GetFromFpAddress() const { | 34 intptr_t* DeoptimizationContext::GetFromFpAddress() const { |
33 return &from_frame_[from_frame_size_ - 1 - num_args_ - 1]; | 35 return &from_frame_[from_frame_size_ - 1 - num_args_ - 1]; |
34 } | 36 } |
35 | 37 |
36 | 38 |
37 intptr_t* DeoptimizationContext::GetFromPcAddress() const { | 39 intptr_t* DeoptimizationContext::GetFromPcAddress() const { |
38 return &from_frame_[from_frame_size_ - 1 - num_args_]; | 40 return &from_frame_[from_frame_size_ - 1 - num_args_]; |
(...skipping 28 matching lines...) Expand all Loading... |
67 *to_addr = *from_addr; | 69 *to_addr = *from_addr; |
68 } | 70 } |
69 | 71 |
70 private: | 72 private: |
71 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 73 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
72 | 74 |
73 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); | 75 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); |
74 }; | 76 }; |
75 | 77 |
76 | 78 |
| 79 class DeoptDoubleStackSlotInstr : public DeoptInstr { |
| 80 public: |
| 81 explicit DeoptDoubleStackSlotInstr(intptr_t from_index) |
| 82 : stack_slot_index_(from_index) { |
| 83 ASSERT(stack_slot_index_ >= 0); |
| 84 } |
| 85 |
| 86 virtual intptr_t from_index() const { return stack_slot_index_; } |
| 87 virtual DeoptInstr::Kind kind() const { return kCopyDoubleStackSlot; } |
| 88 |
| 89 virtual const char* ToCString() const { |
| 90 intptr_t len = OS::SNPrint(NULL, 0, "ds%d", stack_slot_index_); |
| 91 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
| 92 OS::SNPrint(chars, len + 1, "ds%d", stack_slot_index_); |
| 93 return chars; |
| 94 } |
| 95 |
| 96 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 97 intptr_t from_index = |
| 98 deopt_context->from_frame_size() - stack_slot_index_ - 1; |
| 99 double* from_addr = reinterpret_cast<double*>( |
| 100 deopt_context->GetFromFrameAddressAt(from_index)); |
| 101 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 102 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 103 Isolate::Current()->DeferDoubleMaterialization( |
| 104 *from_addr, reinterpret_cast<RawDouble**>(to_addr)); |
| 105 } |
| 106 |
| 107 private: |
| 108 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 109 |
| 110 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); |
| 111 }; |
| 112 |
| 113 |
77 // Deoptimization instruction creating return address using function and | 114 // Deoptimization instruction creating return address using function and |
78 // deopt-id stored at 'object_table_index'. | 115 // deopt-id stored at 'object_table_index'. |
79 class DeoptRetAddrInstr : public DeoptInstr { | 116 class DeoptRetAddrInstr : public DeoptInstr { |
80 public: | 117 public: |
81 explicit DeoptRetAddrInstr(intptr_t object_table_index) | 118 explicit DeoptRetAddrInstr(intptr_t object_table_index) |
82 : object_table_index_(object_table_index) { | 119 : object_table_index_(object_table_index) { |
83 ASSERT(object_table_index >= 0); | 120 ASSERT(object_table_index >= 0); |
84 } | 121 } |
85 | 122 |
86 virtual intptr_t from_index() const { return object_table_index_; } | 123 virtual intptr_t from_index() const { return object_table_index_; } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 *to_addr = obj.raw(); | 175 *to_addr = obj.raw(); |
139 } | 176 } |
140 | 177 |
141 private: | 178 private: |
142 const intptr_t object_table_index_; | 179 const intptr_t object_table_index_; |
143 | 180 |
144 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 181 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
145 }; | 182 }; |
146 | 183 |
147 | 184 |
148 // Deoptimization instruction moving a register. | 185 // Deoptimization instruction moving a CPU register. |
149 class DeoptRegisterInstr: public DeoptInstr { | 186 class DeoptRegisterInstr: public DeoptInstr { |
150 public: | 187 public: |
151 explicit DeoptRegisterInstr(intptr_t reg_as_int) | 188 explicit DeoptRegisterInstr(intptr_t reg_as_int) |
152 : reg_(static_cast<Register>(reg_as_int)) {} | 189 : reg_(static_cast<Register>(reg_as_int)) {} |
153 | 190 |
154 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 191 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
155 virtual DeoptInstr::Kind kind() const { return kCopyRegister; } | 192 virtual DeoptInstr::Kind kind() const { return kCopyRegister; } |
156 | 193 |
157 virtual const char* ToCString() const { | 194 virtual const char* ToCString() const { |
158 return Assembler::RegisterName(reg_); | 195 return Assembler::RegisterName(reg_); |
159 } | 196 } |
160 | 197 |
161 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 198 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
162 intptr_t value = deopt_context->RegisterValue(reg_); | 199 intptr_t value = deopt_context->RegisterValue(reg_); |
163 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | 200 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
164 *to_addr = value; | 201 *to_addr = value; |
165 } | 202 } |
166 | 203 |
167 private: | 204 private: |
168 const Register reg_; | 205 const Register reg_; |
169 | 206 |
170 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); | 207 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); |
171 }; | 208 }; |
172 | 209 |
173 | 210 |
| 211 // Deoptimization instruction moving an XMM register. |
| 212 class DeoptXmmRegisterInstr: public DeoptInstr { |
| 213 public: |
| 214 explicit DeoptXmmRegisterInstr(intptr_t reg_as_int) |
| 215 : reg_(static_cast<XmmRegister>(reg_as_int)) {} |
| 216 |
| 217 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
| 218 virtual DeoptInstr::Kind kind() const { return kCopyXmmRegister; } |
| 219 |
| 220 virtual const char* ToCString() const { |
| 221 return Assembler::XmmRegisterName(reg_); |
| 222 } |
| 223 |
| 224 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 225 double value = deopt_context->XmmRegisterValue(reg_); |
| 226 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 227 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 228 Isolate::Current()->DeferDoubleMaterialization( |
| 229 value, reinterpret_cast<RawDouble**>(to_addr)); |
| 230 } |
| 231 |
| 232 private: |
| 233 const XmmRegister reg_; |
| 234 |
| 235 DISALLOW_COPY_AND_ASSIGN(DeoptXmmRegisterInstr); |
| 236 }; |
| 237 |
| 238 |
174 // Deoptimization instruction creating a PC marker for the code of | 239 // Deoptimization instruction creating a PC marker for the code of |
175 // function at 'object_table_index'. | 240 // function at 'object_table_index'. |
176 class DeoptPcMarkerInstr : public DeoptInstr { | 241 class DeoptPcMarkerInstr : public DeoptInstr { |
177 public: | 242 public: |
178 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 243 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
179 : object_table_index_(object_table_index) { | 244 : object_table_index_(object_table_index) { |
180 ASSERT(object_table_index >= 0); | 245 ASSERT(object_table_index >= 0); |
181 } | 246 } |
182 | 247 |
183 virtual intptr_t from_index() const { return object_table_index_; } | 248 virtual intptr_t from_index() const { return object_table_index_; } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 | 317 |
253 private: | 318 private: |
254 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 319 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
255 }; | 320 }; |
256 | 321 |
257 | 322 |
258 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { | 323 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { |
259 Kind kind = static_cast<Kind>(kind_as_int); | 324 Kind kind = static_cast<Kind>(kind_as_int); |
260 switch (kind) { | 325 switch (kind) { |
261 case kCopyStackSlot: return new DeoptStackSlotInstr(from_index); | 326 case kCopyStackSlot: return new DeoptStackSlotInstr(from_index); |
| 327 case kCopyDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); |
262 case kSetRetAddress: return new DeoptRetAddrInstr(from_index); | 328 case kSetRetAddress: return new DeoptRetAddrInstr(from_index); |
263 case kCopyConstant: return new DeoptConstantInstr(from_index); | 329 case kCopyConstant: return new DeoptConstantInstr(from_index); |
264 case kCopyRegister: return new DeoptRegisterInstr(from_index); | 330 case kCopyRegister: return new DeoptRegisterInstr(from_index); |
| 331 case kCopyXmmRegister: return new DeoptXmmRegisterInstr(from_index); |
265 case kSetPcMarker: return new DeoptPcMarkerInstr(from_index); | 332 case kSetPcMarker: return new DeoptPcMarkerInstr(from_index); |
266 case kSetCallerFp: return new DeoptCallerFpInstr(); | 333 case kSetCallerFp: return new DeoptCallerFpInstr(); |
267 case kSetCallerPc: return new DeoptCallerPcInstr(); | 334 case kSetCallerPc: return new DeoptCallerPcInstr(); |
268 } | 335 } |
269 UNREACHABLE(); | 336 UNREACHABLE(); |
270 return NULL; | 337 return NULL; |
271 } | 338 } |
272 | 339 |
273 | 340 |
274 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | 341 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 | 374 |
308 void DeoptInfoBuilder::AddCopy(const Location& from_loc, | 375 void DeoptInfoBuilder::AddCopy(const Location& from_loc, |
309 const Value& from_value, | 376 const Value& from_value, |
310 const intptr_t to_index) { | 377 const intptr_t to_index) { |
311 DeoptInstr* deopt_instr = NULL; | 378 DeoptInstr* deopt_instr = NULL; |
312 if (from_loc.IsConstant()) { | 379 if (from_loc.IsConstant()) { |
313 intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant()); | 380 intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant()); |
314 deopt_instr = new DeoptConstantInstr(object_table_index); | 381 deopt_instr = new DeoptConstantInstr(object_table_index); |
315 } else if (from_loc.IsRegister()) { | 382 } else if (from_loc.IsRegister()) { |
316 deopt_instr = new DeoptRegisterInstr(from_loc.reg()); | 383 deopt_instr = new DeoptRegisterInstr(from_loc.reg()); |
| 384 } else if (from_loc.IsXmmRegister()) { |
| 385 deopt_instr = new DeoptXmmRegisterInstr(from_loc.xmm_reg()); |
317 } else if (from_loc.IsStackSlot()) { | 386 } else if (from_loc.IsStackSlot()) { |
318 intptr_t from_index = (from_loc.stack_index() < 0) ? | 387 intptr_t from_index = (from_loc.stack_index() < 0) ? |
319 from_loc.stack_index() + num_args_ : | 388 from_loc.stack_index() + num_args_ : |
320 from_loc.stack_index() + num_args_ - | 389 from_loc.stack_index() + num_args_ - |
321 ParsedFunction::kFirstLocalSlotIndex + 1; | 390 ParsedFunction::kFirstLocalSlotIndex + 1; |
322 deopt_instr = new DeoptStackSlotInstr(from_index); | 391 deopt_instr = new DeoptStackSlotInstr(from_index); |
| 392 } else if (from_loc.IsDoubleStackSlot()) { |
| 393 intptr_t from_index = (from_loc.stack_index() < 0) ? |
| 394 from_loc.stack_index() + num_args_ : |
| 395 from_loc.stack_index() + num_args_ - |
| 396 ParsedFunction::kFirstLocalSlotIndex + 1; |
| 397 deopt_instr = new DeoptDoubleStackSlotInstr(from_index); |
323 } else { | 398 } else { |
324 UNREACHABLE(); | 399 UNREACHABLE(); |
325 } | 400 } |
326 ASSERT(to_index == instructions_.length()); | 401 ASSERT(to_index == instructions_.length()); |
327 instructions_.Add(deopt_instr); | 402 instructions_.Add(deopt_instr); |
328 } | 403 } |
329 | 404 |
330 | 405 |
331 void DeoptInfoBuilder::AddCallerFp(intptr_t to_index) { | 406 void DeoptInfoBuilder::AddCallerFp(intptr_t to_index) { |
332 ASSERT(to_index == instructions_.length()); | 407 ASSERT(to_index == instructions_.length()); |
(...skipping 11 matching lines...) Expand all Loading... |
344 const intptr_t len = instructions_.length(); | 419 const intptr_t len = instructions_.length(); |
345 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(len)); | 420 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(len)); |
346 for (intptr_t i = 0; i < len; i++) { | 421 for (intptr_t i = 0; i < len; i++) { |
347 DeoptInstr* instr = instructions_[i]; | 422 DeoptInstr* instr = instructions_[i]; |
348 deopt_info.SetAt(i, instr->kind(), instr->from_index()); | 423 deopt_info.SetAt(i, instr->kind(), instr->from_index()); |
349 } | 424 } |
350 return deopt_info.raw(); | 425 return deopt_info.raw(); |
351 } | 426 } |
352 | 427 |
353 } // namespace dart | 428 } // namespace dart |
OLD | NEW |