Index: runtime/vm/deopt_instructions.cc |
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc |
index c461d935fe6520961fd85e378d1340410a48e0e5..0c9a7ec4ef6d3d1d3a6efd9cf34a60698834bfe0 100644 |
--- a/runtime/vm/deopt_instructions.cc |
+++ b/runtime/vm/deopt_instructions.cc |
@@ -189,6 +189,7 @@ static bool IsObjectInstruction(DeoptInstr::Kind kind) { |
case DeoptInstr::kStackSlot: |
case DeoptInstr::kDoubleStackSlot: |
case DeoptInstr::kInt64StackSlot: |
+ case DeoptInstr::kInt64StackSlotPair: |
case DeoptInstr::kFloat32x4StackSlot: |
case DeoptInstr::kInt32x4StackSlot: |
case DeoptInstr::kFloat64x2StackSlot: |
@@ -199,7 +200,8 @@ static bool IsObjectInstruction(DeoptInstr::Kind kind) { |
case DeoptInstr::kRegister: |
case DeoptInstr::kFpuRegister: |
- case DeoptInstr::kInt64FpuRegister: |
+ case DeoptInstr::kInt64RegisterPair: |
+ case DeoptInstr::kInt64StackSlotRegister: |
case DeoptInstr::kFloat32x4FpuRegister: |
case DeoptInstr::kInt32x4FpuRegister: |
case DeoptInstr::kFloat64x2FpuRegister: |
@@ -451,7 +453,7 @@ class DeoptInt64StackSlotInstr : public DeoptInstr { |
virtual const char* ToCString() const { |
return Isolate::Current()->current_zone()->PrintToString( |
- "ms%" Pd "", stack_slot_index_); |
+ "int64 stack slot:%" Pd "", stack_slot_index_); |
} |
void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
@@ -719,21 +721,28 @@ class DeoptFpuRegisterInstr: public DeoptInstr { |
}; |
-class DeoptInt64FpuRegisterInstr: public DeoptInstr { |
+class DeoptInt64RegisterPairInstr: public DeoptInstr { |
public: |
- explicit DeoptInt64FpuRegisterInstr(intptr_t reg_as_int) |
- : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
+ DeoptInt64RegisterPairInstr(intptr_t lo_reg_as_int, intptr_t hi_reg_as_int) |
+ : lo_reg_(static_cast<Register>(lo_reg_as_int)), |
+ hi_reg_(static_cast<Register>(hi_reg_as_int)) {} |
- virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } |
- virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; } |
+ virtual intptr_t source_index() const { |
+ return EncodeRegisters(static_cast<intptr_t>(lo_reg_), |
+ static_cast<intptr_t>(hi_reg_)); |
+ } |
+ virtual DeoptInstr::Kind kind() const { return kInt64RegisterPair; } |
virtual const char* ToCString() const { |
return Isolate::Current()->current_zone()->PrintToString( |
- "%s(m)", Assembler::FpuRegisterName(reg_)); |
+ "int64 register pair: %s,%s", Assembler::RegisterName(hi_reg_), |
+ Assembler::RegisterName(lo_reg_)); |
} |
void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
- int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_); |
+ uint32_t lo_value = deopt_context->RegisterValue(lo_reg_); |
+ int32_t hi_value = deopt_context->RegisterValue(hi_reg_); |
+ int64_t value = Utils::LowHighTo64Bits(lo_value, hi_value); |
*reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
if (Smi::IsValid64(value)) { |
*dest_addr = reinterpret_cast<intptr_t>( |
@@ -744,10 +753,178 @@ class DeoptInt64FpuRegisterInstr: public DeoptInstr { |
} |
} |
+ static const intptr_t kFieldWidth = kBitsPerWord / 2; |
+ class LoRegister : public BitField<intptr_t, 0, kFieldWidth> { }; |
+ class HiRegister : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; |
+ static intptr_t EncodeRegisters(intptr_t lo_reg_as_int, |
+ intptr_t hi_reg_as_int) { |
+ return LoRegister::encode(lo_reg_as_int) | |
+ HiRegister::encode(hi_reg_as_int); |
+ } |
+ |
+ static intptr_t DecodeLoRegister(intptr_t v) { |
+ return LoRegister::decode(v); |
+ } |
+ |
+ static intptr_t DecodeHiRegister(intptr_t v) { |
+ return HiRegister::decode(v); |
+ } |
+ |
private: |
- const FpuRegister reg_; |
+ const Register lo_reg_; |
+ const Register hi_reg_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DeoptInt64RegisterPairInstr); |
+}; |
+ |
+ |
+class DeoptInt64StackSlotPairInstr: public DeoptInstr { |
+ public: |
+ DeoptInt64StackSlotPairInstr(intptr_t lo_slot, intptr_t hi_slot) |
+ : lo_slot_(static_cast<Register>(lo_slot)), |
+ hi_slot_(static_cast<Register>(hi_slot)) {} |
+ |
+ virtual intptr_t source_index() const { |
+ return EncodeSlots(static_cast<intptr_t>(lo_slot_), |
+ static_cast<intptr_t>(hi_slot_)); |
+ } |
+ virtual DeoptInstr::Kind kind() const { return kInt64StackSlotPair; } |
+ |
+ virtual const char* ToCString() const { |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "int64 stack slots: %" Pd", %" Pd "", lo_slot_, hi_slot_); |
+ } |
+ |
+ void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
+ intptr_t lo_source_index = |
+ deopt_context->source_frame_size() - lo_slot_ - 1; |
+ int32_t* lo_source_addr = reinterpret_cast<int32_t*>( |
+ deopt_context->GetSourceFrameAddressAt(lo_source_index)); |
+ intptr_t hi_source_index = |
+ deopt_context->source_frame_size() - hi_slot_ - 1; |
+ int32_t* hi_source_addr = reinterpret_cast<int32_t*>( |
+ deopt_context->GetSourceFrameAddressAt(hi_source_index)); |
+ int64_t value = Utils::LowHighTo64Bits(*lo_source_addr, *hi_source_addr); |
+ *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
+ if (Smi::IsValid64(value)) { |
+ *dest_addr = reinterpret_cast<intptr_t>( |
+ Smi::New(static_cast<intptr_t>(value))); |
+ } else { |
+ deopt_context->DeferMintMaterialization( |
+ value, reinterpret_cast<RawMint**>(dest_addr)); |
+ } |
+ } |
+ |
+ static const intptr_t kFieldWidth = kBitsPerWord / 2; |
+ class LoSlot : public BitField<intptr_t, 0, kFieldWidth> { }; |
+ class HiSlot : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; |
+ static intptr_t EncodeSlots(intptr_t lo_slot, |
+ intptr_t hi_slot) { |
+ return LoSlot::encode(lo_slot) | |
+ HiSlot::encode(hi_slot); |
+ } |
+ |
+ static intptr_t DecodeLoSlot(intptr_t v) { |
+ return LoSlot::decode(v); |
+ } |
+ |
+ static intptr_t DecodeHiSlot(intptr_t v) { |
+ return HiSlot::decode(v); |
+ } |
+ |
+ private: |
+ const intptr_t lo_slot_; |
+ const intptr_t hi_slot_; |
- DISALLOW_COPY_AND_ASSIGN(DeoptInt64FpuRegisterInstr); |
+ DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotPairInstr); |
+}; |
+ |
+ |
+class DeoptInt64StackSlotRegisterInstr : public DeoptInstr { |
+ public: |
+ DeoptInt64StackSlotRegisterInstr(intptr_t source_index, |
+ intptr_t reg_as_int, |
+ bool flip) |
+ : slot_(source_index), |
+ reg_(static_cast<Register>(reg_as_int)), |
+ flip_(flip) { |
+ // when flip_ is false, stack slot is low bits and reg is high bits. |
+ // when flip_ is true, stack slot is high bits and reg is low bits. |
+ } |
+ |
+ virtual intptr_t source_index() const { |
+ return Encode(static_cast<intptr_t>(slot_), |
+ static_cast<intptr_t>(reg_), |
+ flip_ ? 1 : 0); |
+ } |
+ virtual DeoptInstr::Kind kind() const { return kInt64StackSlotRegister; } |
+ |
+ virtual const char* ToCString() const { |
+ if (flip_) { |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "int64 reg: %s, stack slot: %" Pd "", Assembler::RegisterName(reg_), |
+ slot_); |
+ } else { |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "int64 stack slot: %" Pd", reg: %s", slot_, |
+ Assembler::RegisterName(reg_)); |
+ } |
+ } |
+ |
+ void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
+ intptr_t slot_source_index = |
+ deopt_context->source_frame_size() - slot_ - 1; |
+ int32_t* slot_source_addr = reinterpret_cast<int32_t*>( |
+ deopt_context->GetSourceFrameAddressAt(slot_source_index)); |
+ int32_t slot_value = *slot_source_addr; |
+ int32_t reg_value = deopt_context->RegisterValue(reg_); |
+ int64_t value; |
+ if (flip_) { |
+ value = Utils::LowHighTo64Bits(reg_value, slot_value); |
+ } else { |
+ value = Utils::LowHighTo64Bits(slot_value, reg_value); |
+ } |
+ *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
+ if (Smi::IsValid64(value)) { |
+ *dest_addr = reinterpret_cast<intptr_t>( |
+ Smi::New(static_cast<intptr_t>(value))); |
+ } else { |
+ deopt_context->DeferMintMaterialization( |
+ value, reinterpret_cast<RawMint**>(dest_addr)); |
+ } |
+ } |
+ |
+ static const intptr_t kFieldWidth = kBitsPerWord / 2; |
+ class Slot : public BitField<intptr_t, 0, kFieldWidth> { }; |
+ class Reg : public BitField<intptr_t, kFieldWidth, kFieldWidth - 1> { }; |
+ // 1 bit for the flip. |
+ class Flip : public BitField<intptr_t, kFieldWidth * 2 - 1, 1> { }; |
+ |
+ static intptr_t Encode(intptr_t slot, |
+ intptr_t reg_as_int, |
+ bool flip) { |
+ return Slot::encode(slot) | |
+ Reg::encode(reg_as_int) | |
+ Flip::encode(flip ? 1 : 0); |
+ } |
+ |
+ static intptr_t DecodeSlot(intptr_t v) { |
+ return Slot::decode(v); |
+ } |
+ |
+ static intptr_t DecodeReg(intptr_t v) { |
+ return Reg::decode(v); |
+ } |
+ |
+ static bool DecodeFlip(intptr_t v) { |
+ return Flip::decode(v); |
+ } |
+ |
+ private: |
+ const intptr_t slot_; |
+ const Register reg_; |
+ const bool flip_; |
+ DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotRegisterInstr); |
}; |
@@ -1139,7 +1316,28 @@ DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { |
case kConstant: return new DeoptConstantInstr(source_index); |
case kRegister: return new DeoptRegisterInstr(source_index); |
case kFpuRegister: return new DeoptFpuRegisterInstr(source_index); |
- case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(source_index); |
+ case kInt64RegisterPair: { |
+ intptr_t lo_reg_as_int = |
+ DeoptInt64RegisterPairInstr::LoRegister::decode(source_index); |
+ intptr_t hi_reg_as_int = |
+ DeoptInt64RegisterPairInstr::HiRegister::decode(source_index); |
+ return new DeoptInt64RegisterPairInstr(lo_reg_as_int, hi_reg_as_int); |
+ } |
+ case kInt64StackSlotPair: { |
+ intptr_t lo_slot = |
+ DeoptInt64StackSlotPairInstr::LoSlot::decode(source_index); |
+ intptr_t hi_slot = |
+ DeoptInt64StackSlotPairInstr::HiSlot::decode(source_index); |
+ return new DeoptInt64StackSlotPairInstr(lo_slot, hi_slot); |
+ } |
+ case kInt64StackSlotRegister: { |
+ intptr_t slot = |
+ DeoptInt64StackSlotRegisterInstr::Slot::decode(source_index); |
+ intptr_t reg_as_int = |
+ DeoptInt64StackSlotRegisterInstr::Reg::decode(source_index); |
+ bool flip = DeoptInt64StackSlotRegisterInstr::Flip::decode(source_index); |
+ return new DeoptInt64StackSlotRegisterInstr(slot, reg_as_int, flip); |
+ } |
case kFloat32x4FpuRegister: |
return new DeoptFloat32x4FpuRegisterInstr(source_index); |
case kFloat64x2FpuRegister: |
@@ -1271,8 +1469,6 @@ void DeoptInfoBuilder::AddCopy(Value* value, |
} else if (source_loc.IsFpuRegister()) { |
if (value->definition()->representation() == kUnboxedDouble) { |
deopt_instr = new DeoptFpuRegisterInstr(source_loc.fpu_reg()); |
- } else if (value->definition()->representation() == kUnboxedMint) { |
- deopt_instr = new DeoptInt64FpuRegisterInstr(source_loc.fpu_reg()); |
} else if (value->definition()->representation() == kUnboxedFloat32x4) { |
deopt_instr = new DeoptFloat32x4FpuRegisterInstr(source_loc.fpu_reg()); |
} else if (value->definition()->representation() == kUnboxedInt32x4) { |
@@ -1303,6 +1499,34 @@ void DeoptInfoBuilder::AddCopy(Value* value, |
ASSERT(value->definition()->representation() == kUnboxedFloat64x2); |
deopt_instr = new DeoptFloat64x2StackSlotInstr(source_index); |
} |
+ } else if (source_loc.IsPairLocation()) { |
+ ASSERT(value->definition()->representation() == kUnboxedMint); |
+ // There are four cases to consider here: |
+ // (R = Register, S = Stack slot). |
+ // 1) R, R. |
+ // 2) S, S. |
+ // 3) R, S. |
+ // 4) S, R. |
+ PairLocation* pair = source_loc.AsPairLocation(); |
+ if (pair->At(0).IsRegister() && pair->At(1).IsRegister()) { |
+ deopt_instr = new DeoptInt64RegisterPairInstr(pair->At(0).reg(), |
+ pair->At(1).reg()); |
+ } else if (pair->At(0).IsStackSlot() && pair->At(1).IsStackSlot()) { |
+ deopt_instr = new DeoptInt64StackSlotPairInstr( |
+ CalculateStackIndex(pair->At(0)), |
+ CalculateStackIndex(pair->At(1))); |
+ } else if (pair->At(0).IsRegister() && pair->At(1).IsStackSlot()) { |
+ deopt_instr = new DeoptInt64StackSlotRegisterInstr( |
+ CalculateStackIndex(pair->At(1)), |
+ pair->At(0).reg(), |
+ true); |
+ } else { |
+ ASSERT(pair->At(0).IsStackSlot() && pair->At(1).IsRegister()); |
+ deopt_instr = new DeoptInt64StackSlotRegisterInstr( |
+ CalculateStackIndex(pair->At(0)), |
+ pair->At(1).reg(), |
+ false); |
+ } |
} else if (source_loc.IsInvalid() && |
value->definition()->IsMaterializeObject()) { |
const intptr_t index = FindMaterialization( |