| 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 } | 105 } |
| 106 | 106 |
| 107 private: | 107 private: |
| 108 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 108 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 109 | 109 |
| 110 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); | 110 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); |
| 111 }; | 111 }; |
| 112 | 112 |
| 113 | 113 |
| 114 // Deoptimization instruction creating return address using function and | 114 // Deoptimization instruction creating return address using function and |
| 115 // deopt-id stored at 'object_table_index'. | 115 // deopt-id stored at 'object_table_index'. Uses the deopt-after |
| 116 class DeoptRetAddrInstr : public DeoptInstr { | 116 // continuation point. |
| 117 class DeoptRetAddrAfterInstr : public DeoptInstr { |
| 117 public: | 118 public: |
| 118 explicit DeoptRetAddrInstr(intptr_t object_table_index) | 119 explicit DeoptRetAddrAfterInstr(intptr_t object_table_index) |
| 119 : object_table_index_(object_table_index) { | 120 : object_table_index_(object_table_index) { |
| 120 ASSERT(object_table_index >= 0); | 121 ASSERT(object_table_index >= 0); |
| 121 } | 122 } |
| 122 | 123 |
| 123 virtual intptr_t from_index() const { return object_table_index_; } | 124 virtual intptr_t from_index() const { return object_table_index_; } |
| 124 virtual DeoptInstr::Kind kind() const { return kSetRetAddress; } | 125 virtual DeoptInstr::Kind kind() const { return kSetRetAfterAddress; } |
| 125 | 126 |
| 126 virtual const char* ToCString() const { | 127 virtual const char* ToCString() const { |
| 127 intptr_t len = OS::SNPrint(NULL, 0, "ret oti:%d", object_table_index_); | 128 intptr_t len = OS::SNPrint(NULL, 0, "ret aft oti:%d", object_table_index_); |
| 128 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 129 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
| 129 OS::SNPrint(chars, len + 1, "ret oti:%d", object_table_index_); | 130 OS::SNPrint(chars, len + 1, "ret aft oti:%d", object_table_index_); |
| 130 return chars; | 131 return chars; |
| 131 } | 132 } |
| 132 | 133 |
| 133 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 134 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 134 Function& function = Function::Handle(deopt_context->isolate()); | 135 Function& function = Function::Handle(deopt_context->isolate()); |
| 135 function ^= deopt_context->ObjectAt(object_table_index_); | 136 function ^= deopt_context->ObjectAt(object_table_index_); |
| 136 Smi& deopt_id_as_smi = Smi::Handle(deopt_context->isolate()); | 137 Smi& deopt_id_as_smi = Smi::Handle(deopt_context->isolate()); |
| 137 deopt_id_as_smi ^= deopt_context->ObjectAt(object_table_index_ + 1); | 138 deopt_id_as_smi ^= deopt_context->ObjectAt(object_table_index_ + 1); |
| 138 const Code& code = | 139 const Code& code = |
| 139 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | 140 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
| 140 uword continue_at_pc = | 141 uword continue_at_pc = |
| 142 code.GetDeoptAfterPcAtDeoptId(deopt_id_as_smi.Value()); |
| 143 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 144 *to_addr = continue_at_pc; |
| 145 } |
| 146 |
| 147 private: |
| 148 const intptr_t object_table_index_; |
| 149 |
| 150 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrAfterInstr); |
| 151 }; |
| 152 |
| 153 |
| 154 // Deoptimization instruction creating return address using function and |
| 155 // deopt-id stored at 'object_table_index'. Uses the deopt-before |
| 156 // continuation point. |
| 157 class DeoptRetAddrBeforeInstr : public DeoptInstr { |
| 158 public: |
| 159 explicit DeoptRetAddrBeforeInstr(intptr_t object_table_index) |
| 160 : object_table_index_(object_table_index) { |
| 161 ASSERT(object_table_index >= 0); |
| 162 } |
| 163 |
| 164 virtual intptr_t from_index() const { return object_table_index_; } |
| 165 virtual DeoptInstr::Kind kind() const { return kSetRetBeforeAddress; } |
| 166 |
| 167 virtual const char* ToCString() const { |
| 168 intptr_t len = OS::SNPrint(NULL, 0, "ret bef oti:%d", object_table_index_); |
| 169 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
| 170 OS::SNPrint(chars, len + 1, "ret bef oti:%d", object_table_index_); |
| 171 return chars; |
| 172 } |
| 173 |
| 174 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 175 Function& function = Function::Handle(deopt_context->isolate()); |
| 176 function ^= deopt_context->ObjectAt(object_table_index_); |
| 177 Smi& deopt_id_as_smi = Smi::Handle(deopt_context->isolate()); |
| 178 deopt_id_as_smi ^= deopt_context->ObjectAt(object_table_index_ + 1); |
| 179 const Code& code = |
| 180 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
| 181 uword continue_at_pc = |
| 141 code.GetDeoptBeforePcAtDeoptId(deopt_id_as_smi.Value()); | 182 code.GetDeoptBeforePcAtDeoptId(deopt_id_as_smi.Value()); |
| 142 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | 183 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 143 *to_addr = continue_at_pc; | 184 *to_addr = continue_at_pc; |
| 144 } | 185 } |
| 145 | 186 |
| 146 private: | 187 private: |
| 147 const intptr_t object_table_index_; | 188 const intptr_t object_table_index_; |
| 148 | 189 |
| 149 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrInstr); | 190 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrBeforeInstr); |
| 150 }; | 191 }; |
| 151 | 192 |
| 152 | 193 |
| 153 // Deoptimization instruction moving a constant stored at 'object_table_index'. | 194 // Deoptimization instruction moving a constant stored at 'object_table_index'. |
| 154 class DeoptConstantInstr : public DeoptInstr { | 195 class DeoptConstantInstr : public DeoptInstr { |
| 155 public: | 196 public: |
| 156 explicit DeoptConstantInstr(intptr_t object_table_index) | 197 explicit DeoptConstantInstr(intptr_t object_table_index) |
| 157 : object_table_index_(object_table_index) { | 198 : object_table_index_(object_table_index) { |
| 158 ASSERT(object_table_index >= 0); | 199 ASSERT(object_table_index >= 0); |
| 159 } | 200 } |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 private: | 360 private: |
| 320 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 361 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
| 321 }; | 362 }; |
| 322 | 363 |
| 323 | 364 |
| 324 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { | 365 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { |
| 325 Kind kind = static_cast<Kind>(kind_as_int); | 366 Kind kind = static_cast<Kind>(kind_as_int); |
| 326 switch (kind) { | 367 switch (kind) { |
| 327 case kCopyStackSlot: return new DeoptStackSlotInstr(from_index); | 368 case kCopyStackSlot: return new DeoptStackSlotInstr(from_index); |
| 328 case kCopyDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); | 369 case kCopyDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); |
| 329 case kSetRetAddress: return new DeoptRetAddrInstr(from_index); | 370 case kSetRetAfterAddress: return new DeoptRetAddrAfterInstr(from_index); |
| 371 case kSetRetBeforeAddress: return new DeoptRetAddrBeforeInstr(from_index); |
| 330 case kCopyConstant: return new DeoptConstantInstr(from_index); | 372 case kCopyConstant: return new DeoptConstantInstr(from_index); |
| 331 case kCopyRegister: return new DeoptRegisterInstr(from_index); | 373 case kCopyRegister: return new DeoptRegisterInstr(from_index); |
| 332 case kCopyXmmRegister: return new DeoptXmmRegisterInstr(from_index); | 374 case kCopyXmmRegister: return new DeoptXmmRegisterInstr(from_index); |
| 333 case kSetPcMarker: return new DeoptPcMarkerInstr(from_index); | 375 case kSetPcMarker: return new DeoptPcMarkerInstr(from_index); |
| 334 case kSetCallerFp: return new DeoptCallerFpInstr(); | 376 case kSetCallerFp: return new DeoptCallerFpInstr(); |
| 335 case kSetCallerPc: return new DeoptCallerPcInstr(); | 377 case kSetCallerPc: return new DeoptCallerPcInstr(); |
| 336 } | 378 } |
| 337 UNREACHABLE(); | 379 UNREACHABLE(); |
| 338 return NULL; | 380 return NULL; |
| 339 } | 381 } |
| 340 | 382 |
| 341 | 383 |
| 342 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | 384 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { |
| 343 for (intptr_t i = 0; i < object_table_.Length(); i++) { | 385 for (intptr_t i = 0; i < object_table_.Length(); i++) { |
| 344 if (object_table_.At(i) == obj.raw()) { | 386 if (object_table_.At(i) == obj.raw()) { |
| 345 return i; | 387 return i; |
| 346 } | 388 } |
| 347 } | 389 } |
| 348 // Add object. | 390 // Add object. |
| 349 const intptr_t result = object_table_.Length(); | 391 const intptr_t result = object_table_.Length(); |
| 350 object_table_.Add(obj); | 392 object_table_.Add(obj); |
| 351 return result; | 393 return result; |
| 352 } | 394 } |
| 353 | 395 |
| 354 | 396 |
| 355 // Will be neeeded for inlined functions, currently trivial. | 397 void DeoptInfoBuilder::AddReturnAddressBefore(const Function& function, |
| 356 void DeoptInfoBuilder::AddReturnAddress(const Function& function, | 398 intptr_t deopt_id, |
| 357 intptr_t deopt_id, | 399 intptr_t to_index) { |
| 358 intptr_t to_index) { | |
| 359 const intptr_t object_table_index = object_table_.Length(); | 400 const intptr_t object_table_index = object_table_.Length(); |
| 360 object_table_.Add(function); | 401 object_table_.Add(function); |
| 361 object_table_.Add(Smi::ZoneHandle(Smi::New(deopt_id))); | 402 object_table_.Add(Smi::ZoneHandle(Smi::New(deopt_id))); |
| 362 ASSERT(to_index == instructions_.length()); | 403 ASSERT(to_index == instructions_.length()); |
| 363 instructions_.Add(new DeoptRetAddrInstr(object_table_index)); | 404 instructions_.Add(new DeoptRetAddrBeforeInstr(object_table_index)); |
| 405 } |
| 406 |
| 407 |
| 408 void DeoptInfoBuilder::AddReturnAddressAfter(const Function& function, |
| 409 intptr_t deopt_id, |
| 410 intptr_t to_index) { |
| 411 const intptr_t object_table_index = object_table_.Length(); |
| 412 object_table_.Add(function); |
| 413 object_table_.Add(Smi::ZoneHandle(Smi::New(deopt_id))); |
| 414 ASSERT(to_index == instructions_.length()); |
| 415 instructions_.Add(new DeoptRetAddrAfterInstr(object_table_index)); |
| 364 } | 416 } |
| 365 | 417 |
| 366 | 418 |
| 367 void DeoptInfoBuilder::AddPcMarker(const Function& function, | 419 void DeoptInfoBuilder::AddPcMarker(const Function& function, |
| 368 intptr_t to_index) { | 420 intptr_t to_index) { |
| 369 // Function object was already added by AddReturnAddress, find it. | 421 // Function object was already added by AddReturnAddress, find it. |
| 370 intptr_t from_index = FindOrAddObjectInTable(function); | 422 intptr_t from_index = FindOrAddObjectInTable(function); |
| 371 ASSERT(to_index == instructions_.length()); | 423 ASSERT(to_index == instructions_.length()); |
| 372 instructions_.Add(new DeoptPcMarkerInstr(from_index)); | 424 instructions_.Add(new DeoptPcMarkerInstr(from_index)); |
| 373 } | 425 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 const intptr_t len = instructions_.length(); | 472 const intptr_t len = instructions_.length(); |
| 421 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(len)); | 473 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(len)); |
| 422 for (intptr_t i = 0; i < len; i++) { | 474 for (intptr_t i = 0; i < len; i++) { |
| 423 DeoptInstr* instr = instructions_[i]; | 475 DeoptInstr* instr = instructions_[i]; |
| 424 deopt_info.SetAt(i, instr->kind(), instr->from_index()); | 476 deopt_info.SetAt(i, instr->kind(), instr->from_index()); |
| 425 } | 477 } |
| 426 return deopt_info.raw(); | 478 return deopt_info.raw(); |
| 427 } | 479 } |
| 428 | 480 |
| 429 } // namespace dart | 481 } // namespace dart |
| OLD | NEW |