| 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 |