| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/locations.h" | 10 #include "vm/locations.h" |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 } | 183 } |
| 184 | 184 |
| 185 | 185 |
| 186 static bool IsObjectInstruction(DeoptInstr::Kind kind) { | 186 static bool IsObjectInstruction(DeoptInstr::Kind kind) { |
| 187 switch (kind) { | 187 switch (kind) { |
| 188 case DeoptInstr::kConstant: | 188 case DeoptInstr::kConstant: |
| 189 case DeoptInstr::kStackSlot: | 189 case DeoptInstr::kStackSlot: |
| 190 case DeoptInstr::kDoubleStackSlot: | 190 case DeoptInstr::kDoubleStackSlot: |
| 191 case DeoptInstr::kInt64StackSlot: | 191 case DeoptInstr::kInt64StackSlot: |
| 192 case DeoptInstr::kFloat32x4StackSlot: | 192 case DeoptInstr::kFloat32x4StackSlot: |
| 193 case DeoptInstr::kUint32x4StackSlot: | 193 case DeoptInstr::kInt32x4StackSlot: |
| 194 case DeoptInstr::kPp: | 194 case DeoptInstr::kPp: |
| 195 case DeoptInstr::kCallerPp: | 195 case DeoptInstr::kCallerPp: |
| 196 case DeoptInstr::kMaterializedObjectRef: | 196 case DeoptInstr::kMaterializedObjectRef: |
| 197 return true; | 197 return true; |
| 198 | 198 |
| 199 case DeoptInstr::kRegister: | 199 case DeoptInstr::kRegister: |
| 200 case DeoptInstr::kFpuRegister: | 200 case DeoptInstr::kFpuRegister: |
| 201 case DeoptInstr::kInt64FpuRegister: | 201 case DeoptInstr::kInt64FpuRegister: |
| 202 case DeoptInstr::kFloat32x4FpuRegister: | 202 case DeoptInstr::kFloat32x4FpuRegister: |
| 203 case DeoptInstr::kUint32x4FpuRegister: | 203 case DeoptInstr::kInt32x4FpuRegister: |
| 204 // TODO(turnidge): Sometimes we encounter a deopt instruction | 204 // TODO(turnidge): Sometimes we encounter a deopt instruction |
| 205 // with a register source while deoptimizing frames during | 205 // with a register source while deoptimizing frames during |
| 206 // debugging but we haven't saved our register set. This | 206 // debugging but we haven't saved our register set. This |
| 207 // happens specifically when using the VMService to inspect the | 207 // happens specifically when using the VMService to inspect the |
| 208 // stack. In that case, the register values will have been | 208 // stack. In that case, the register values will have been |
| 209 // saved before the StackOverflow runtime call but we do not | 209 // saved before the StackOverflow runtime call but we do not |
| 210 // actually keep track of which registers were saved and | 210 // actually keep track of which registers were saved and |
| 211 // restored. | 211 // restored. |
| 212 // | 212 // |
| 213 // It is possible to save this information at the point of the | 213 // It is possible to save this information at the point of the |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 *source_addr, reinterpret_cast<RawFloat32x4**>(dest_addr)); | 499 *source_addr, reinterpret_cast<RawFloat32x4**>(dest_addr)); |
| 500 } | 500 } |
| 501 | 501 |
| 502 private: | 502 private: |
| 503 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 503 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 504 | 504 |
| 505 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr); | 505 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr); |
| 506 }; | 506 }; |
| 507 | 507 |
| 508 | 508 |
| 509 class DeoptUint32x4StackSlotInstr : public DeoptInstr { | 509 class DeoptInt32x4StackSlotInstr : public DeoptInstr { |
| 510 public: | 510 public: |
| 511 explicit DeoptUint32x4StackSlotInstr(intptr_t source_index) | 511 explicit DeoptInt32x4StackSlotInstr(intptr_t source_index) |
| 512 : stack_slot_index_(source_index) { | 512 : stack_slot_index_(source_index) { |
| 513 ASSERT(stack_slot_index_ >= 0); | 513 ASSERT(stack_slot_index_ >= 0); |
| 514 } | 514 } |
| 515 | 515 |
| 516 virtual intptr_t source_index() const { return stack_slot_index_; } | 516 virtual intptr_t source_index() const { return stack_slot_index_; } |
| 517 virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; } | 517 virtual DeoptInstr::Kind kind() const { return kInt32x4StackSlot; } |
| 518 | 518 |
| 519 virtual const char* ToCString() const { | 519 virtual const char* ToCString() const { |
| 520 return Isolate::Current()->current_zone()->PrintToString( | 520 return Isolate::Current()->current_zone()->PrintToString( |
| 521 "ui32x4s%" Pd "", stack_slot_index_); | 521 "ui32x4s%" Pd "", stack_slot_index_); |
| 522 } | 522 } |
| 523 | 523 |
| 524 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 524 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 525 intptr_t source_index = | 525 intptr_t source_index = |
| 526 deopt_context->source_frame_size() - stack_slot_index_ - 1; | 526 deopt_context->source_frame_size() - stack_slot_index_ - 1; |
| 527 simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>( | 527 simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>( |
| 528 deopt_context->GetSourceFrameAddressAt(source_index)); | 528 deopt_context->GetSourceFrameAddressAt(source_index)); |
| 529 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | 529 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 530 deopt_context->DeferUint32x4Materialization( | 530 deopt_context->DeferInt32x4Materialization( |
| 531 *source_addr, reinterpret_cast<RawUint32x4**>(dest_addr)); | 531 *source_addr, reinterpret_cast<RawInt32x4**>(dest_addr)); |
| 532 } | 532 } |
| 533 | 533 |
| 534 private: | 534 private: |
| 535 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 535 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 536 | 536 |
| 537 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr); | 537 DISALLOW_COPY_AND_ASSIGN(DeoptInt32x4StackSlotInstr); |
| 538 }; | 538 }; |
| 539 | 539 |
| 540 | 540 |
| 541 // Deoptimization instruction creating return address using function and | 541 // Deoptimization instruction creating return address using function and |
| 542 // deopt-id stored at 'object_table_index'. | 542 // deopt-id stored at 'object_table_index'. |
| 543 class DeoptRetAddressInstr : public DeoptInstr { | 543 class DeoptRetAddressInstr : public DeoptInstr { |
| 544 public: | 544 public: |
| 545 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) | 545 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) |
| 546 : object_table_index_(object_table_index), deopt_id_(deopt_id) { | 546 : object_table_index_(object_table_index), deopt_id_(deopt_id) { |
| 547 ASSERT(object_table_index >= 0); | 547 ASSERT(object_table_index >= 0); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 } | 737 } |
| 738 | 738 |
| 739 private: | 739 private: |
| 740 const FpuRegister reg_; | 740 const FpuRegister reg_; |
| 741 | 741 |
| 742 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr); | 742 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr); |
| 743 }; | 743 }; |
| 744 | 744 |
| 745 | 745 |
| 746 // Deoptimization instruction moving an XMM register. | 746 // Deoptimization instruction moving an XMM register. |
| 747 class DeoptUint32x4FpuRegisterInstr: public DeoptInstr { | 747 class DeoptInt32x4FpuRegisterInstr: public DeoptInstr { |
| 748 public: | 748 public: |
| 749 explicit DeoptUint32x4FpuRegisterInstr(intptr_t reg_as_int) | 749 explicit DeoptInt32x4FpuRegisterInstr(intptr_t reg_as_int) |
| 750 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | 750 : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
| 751 | 751 |
| 752 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } | 752 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } |
| 753 virtual DeoptInstr::Kind kind() const { return kUint32x4FpuRegister; } | 753 virtual DeoptInstr::Kind kind() const { return kInt32x4FpuRegister; } |
| 754 | 754 |
| 755 virtual const char* ToCString() const { | 755 virtual const char* ToCString() const { |
| 756 return Isolate::Current()->current_zone()->PrintToString( | 756 return Isolate::Current()->current_zone()->PrintToString( |
| 757 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); | 757 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); |
| 758 } | 758 } |
| 759 | 759 |
| 760 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { | 760 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 761 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); | 761 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); |
| 762 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); | 762 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 763 deopt_context->DeferUint32x4Materialization( | 763 deopt_context->DeferInt32x4Materialization( |
| 764 value, reinterpret_cast<RawUint32x4**>(dest_addr)); | 764 value, reinterpret_cast<RawInt32x4**>(dest_addr)); |
| 765 } | 765 } |
| 766 | 766 |
| 767 private: | 767 private: |
| 768 const FpuRegister reg_; | 768 const FpuRegister reg_; |
| 769 | 769 |
| 770 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4FpuRegisterInstr); | 770 DISALLOW_COPY_AND_ASSIGN(DeoptInt32x4FpuRegisterInstr); |
| 771 }; | 771 }; |
| 772 | 772 |
| 773 | 773 |
| 774 // Deoptimization instruction creating a PC marker for the code of | 774 // Deoptimization instruction creating a PC marker for the code of |
| 775 // function at 'object_table_index'. | 775 // function at 'object_table_index'. |
| 776 class DeoptPcMarkerInstr : public DeoptInstr { | 776 class DeoptPcMarkerInstr : public DeoptInstr { |
| 777 public: | 777 public: |
| 778 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 778 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
| 779 : object_table_index_(object_table_index) { | 779 : object_table_index_(object_table_index) { |
| 780 ASSERT(object_table_index >= 0); | 780 ASSERT(object_table_index >= 0); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 | 1062 |
| 1063 | 1063 |
| 1064 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { | 1064 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { |
| 1065 Kind kind = static_cast<Kind>(kind_as_int); | 1065 Kind kind = static_cast<Kind>(kind_as_int); |
| 1066 switch (kind) { | 1066 switch (kind) { |
| 1067 case kStackSlot: return new DeoptStackSlotInstr(source_index); | 1067 case kStackSlot: return new DeoptStackSlotInstr(source_index); |
| 1068 case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(source_index); | 1068 case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(source_index); |
| 1069 case kInt64StackSlot: return new DeoptInt64StackSlotInstr(source_index); | 1069 case kInt64StackSlot: return new DeoptInt64StackSlotInstr(source_index); |
| 1070 case kFloat32x4StackSlot: | 1070 case kFloat32x4StackSlot: |
| 1071 return new DeoptFloat32x4StackSlotInstr(source_index); | 1071 return new DeoptFloat32x4StackSlotInstr(source_index); |
| 1072 case kUint32x4StackSlot: | 1072 case kInt32x4StackSlot: |
| 1073 return new DeoptUint32x4StackSlotInstr(source_index); | 1073 return new DeoptInt32x4StackSlotInstr(source_index); |
| 1074 case kRetAddress: return new DeoptRetAddressInstr(source_index); | 1074 case kRetAddress: return new DeoptRetAddressInstr(source_index); |
| 1075 case kConstant: return new DeoptConstantInstr(source_index); | 1075 case kConstant: return new DeoptConstantInstr(source_index); |
| 1076 case kRegister: return new DeoptRegisterInstr(source_index); | 1076 case kRegister: return new DeoptRegisterInstr(source_index); |
| 1077 case kFpuRegister: return new DeoptFpuRegisterInstr(source_index); | 1077 case kFpuRegister: return new DeoptFpuRegisterInstr(source_index); |
| 1078 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(source_index); | 1078 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(source_index); |
| 1079 case kFloat32x4FpuRegister: | 1079 case kFloat32x4FpuRegister: |
| 1080 return new DeoptFloat32x4FpuRegisterInstr(source_index); | 1080 return new DeoptFloat32x4FpuRegisterInstr(source_index); |
| 1081 case kUint32x4FpuRegister: | 1081 case kInt32x4FpuRegister: |
| 1082 return new DeoptUint32x4FpuRegisterInstr(source_index); | 1082 return new DeoptInt32x4FpuRegisterInstr(source_index); |
| 1083 case kPcMarker: return new DeoptPcMarkerInstr(source_index); | 1083 case kPcMarker: return new DeoptPcMarkerInstr(source_index); |
| 1084 case kPp: return new DeoptPpInstr(source_index); | 1084 case kPp: return new DeoptPpInstr(source_index); |
| 1085 case kCallerFp: return new DeoptCallerFpInstr(); | 1085 case kCallerFp: return new DeoptCallerFpInstr(); |
| 1086 case kCallerPp: return new DeoptCallerPpInstr(); | 1086 case kCallerPp: return new DeoptCallerPpInstr(); |
| 1087 case kCallerPc: return new DeoptCallerPcInstr(); | 1087 case kCallerPc: return new DeoptCallerPcInstr(); |
| 1088 case kSuffix: return new DeoptSuffixInstr(source_index); | 1088 case kSuffix: return new DeoptSuffixInstr(source_index); |
| 1089 case kMaterializedObjectRef: | 1089 case kMaterializedObjectRef: |
| 1090 return new DeoptMaterializedObjectRefInstr(source_index); | 1090 return new DeoptMaterializedObjectRefInstr(source_index); |
| 1091 case kMaterializeObject: | 1091 case kMaterializeObject: |
| 1092 return new DeoptMaterializeObjectInstr(source_index); | 1092 return new DeoptMaterializeObjectInstr(source_index); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 ASSERT(value->definition()->representation() == kTagged); | 1207 ASSERT(value->definition()->representation() == kTagged); |
| 1208 deopt_instr = new DeoptRegisterInstr(source_loc.reg()); | 1208 deopt_instr = new DeoptRegisterInstr(source_loc.reg()); |
| 1209 } else if (source_loc.IsFpuRegister()) { | 1209 } else if (source_loc.IsFpuRegister()) { |
| 1210 if (value->definition()->representation() == kUnboxedDouble) { | 1210 if (value->definition()->representation() == kUnboxedDouble) { |
| 1211 deopt_instr = new DeoptFpuRegisterInstr(source_loc.fpu_reg()); | 1211 deopt_instr = new DeoptFpuRegisterInstr(source_loc.fpu_reg()); |
| 1212 } else if (value->definition()->representation() == kUnboxedMint) { | 1212 } else if (value->definition()->representation() == kUnboxedMint) { |
| 1213 deopt_instr = new DeoptInt64FpuRegisterInstr(source_loc.fpu_reg()); | 1213 deopt_instr = new DeoptInt64FpuRegisterInstr(source_loc.fpu_reg()); |
| 1214 } else if (value->definition()->representation() == kUnboxedFloat32x4) { | 1214 } else if (value->definition()->representation() == kUnboxedFloat32x4) { |
| 1215 deopt_instr = new DeoptFloat32x4FpuRegisterInstr(source_loc.fpu_reg()); | 1215 deopt_instr = new DeoptFloat32x4FpuRegisterInstr(source_loc.fpu_reg()); |
| 1216 } else { | 1216 } else { |
| 1217 ASSERT(value->definition()->representation() == kUnboxedUint32x4); | 1217 ASSERT(value->definition()->representation() == kUnboxedInt32x4); |
| 1218 deopt_instr = new DeoptUint32x4FpuRegisterInstr(source_loc.fpu_reg()); | 1218 deopt_instr = new DeoptInt32x4FpuRegisterInstr(source_loc.fpu_reg()); |
| 1219 } | 1219 } |
| 1220 } else if (source_loc.IsStackSlot()) { | 1220 } else if (source_loc.IsStackSlot()) { |
| 1221 ASSERT(value->definition()->representation() == kTagged); | 1221 ASSERT(value->definition()->representation() == kTagged); |
| 1222 intptr_t source_index = CalculateStackIndex(source_loc); | 1222 intptr_t source_index = CalculateStackIndex(source_loc); |
| 1223 deopt_instr = new DeoptStackSlotInstr(source_index); | 1223 deopt_instr = new DeoptStackSlotInstr(source_index); |
| 1224 } else if (source_loc.IsDoubleStackSlot()) { | 1224 } else if (source_loc.IsDoubleStackSlot()) { |
| 1225 intptr_t source_index = CalculateStackIndex(source_loc); | 1225 intptr_t source_index = CalculateStackIndex(source_loc); |
| 1226 if (value->definition()->representation() == kUnboxedDouble) { | 1226 if (value->definition()->representation() == kUnboxedDouble) { |
| 1227 deopt_instr = new DeoptDoubleStackSlotInstr(source_index); | 1227 deopt_instr = new DeoptDoubleStackSlotInstr(source_index); |
| 1228 } else { | 1228 } else { |
| 1229 ASSERT(value->definition()->representation() == kUnboxedMint); | 1229 ASSERT(value->definition()->representation() == kUnboxedMint); |
| 1230 deopt_instr = new DeoptInt64StackSlotInstr(source_index); | 1230 deopt_instr = new DeoptInt64StackSlotInstr(source_index); |
| 1231 } | 1231 } |
| 1232 } else if (source_loc.IsQuadStackSlot()) { | 1232 } else if (source_loc.IsQuadStackSlot()) { |
| 1233 intptr_t source_index = CalculateStackIndex(source_loc); | 1233 intptr_t source_index = CalculateStackIndex(source_loc); |
| 1234 if (value->definition()->representation() == kUnboxedFloat32x4) { | 1234 if (value->definition()->representation() == kUnboxedFloat32x4) { |
| 1235 deopt_instr = new DeoptFloat32x4StackSlotInstr(source_index); | 1235 deopt_instr = new DeoptFloat32x4StackSlotInstr(source_index); |
| 1236 } else { | 1236 } else { |
| 1237 ASSERT(value->definition()->representation() == kUnboxedUint32x4); | 1237 ASSERT(value->definition()->representation() == kUnboxedInt32x4); |
| 1238 deopt_instr = new DeoptUint32x4StackSlotInstr(source_index); | 1238 deopt_instr = new DeoptInt32x4StackSlotInstr(source_index); |
| 1239 } | 1239 } |
| 1240 } else if (source_loc.IsInvalid() && | 1240 } else if (source_loc.IsInvalid() && |
| 1241 value->definition()->IsMaterializeObject()) { | 1241 value->definition()->IsMaterializeObject()) { |
| 1242 const intptr_t index = FindMaterialization( | 1242 const intptr_t index = FindMaterialization( |
| 1243 value->definition()->AsMaterializeObject()); | 1243 value->definition()->AsMaterializeObject()); |
| 1244 ASSERT(index >= 0); | 1244 ASSERT(index >= 0); |
| 1245 deopt_instr = new DeoptMaterializedObjectRefInstr(index); | 1245 deopt_instr = new DeoptMaterializedObjectRefInstr(index); |
| 1246 } else { | 1246 } else { |
| 1247 UNREACHABLE(); | 1247 UNREACHABLE(); |
| 1248 } | 1248 } |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1411 Smi* offset, | 1411 Smi* offset, |
| 1412 DeoptInfo* info, | 1412 DeoptInfo* info, |
| 1413 Smi* reason) { | 1413 Smi* reason) { |
| 1414 intptr_t i = index * kEntrySize; | 1414 intptr_t i = index * kEntrySize; |
| 1415 *offset ^= table.At(i); | 1415 *offset ^= table.At(i); |
| 1416 *info ^= table.At(i + 1); | 1416 *info ^= table.At(i + 1); |
| 1417 *reason ^= table.At(i + 2); | 1417 *reason ^= table.At(i + 2); |
| 1418 } | 1418 } |
| 1419 | 1419 |
| 1420 } // namespace dart | 1420 } // namespace dart |
| OLD | NEW |