Chromium Code Reviews| Index: runtime/vm/deopt_instructions.cc |
| diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc |
| index c461d935fe6520961fd85e378d1340410a48e0e5..395a842d2755a09ef5c2090a1482e30bee57f3db 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,37 @@ class DeoptFpuRegisterInstr: public DeoptInstr { |
| }; |
| -class DeoptInt64FpuRegisterInstr: public DeoptInstr { |
| +static int64_t CombineLoAndHi(int32_t* lo, int32_t* hi) { |
|
srdjan
2014/04/30 18:46:01
Use utils.h LowHighTo64Bits
Cutch
2014/05/21 17:00:03
Done.
|
| + ASSERT(lo != NULL); |
| + ASSERT(hi != NULL); |
| + uint64_t lo64 = *reinterpret_cast<uint32_t*>(lo); |
| + uint64_t hi64 = *reinterpret_cast<uint32_t*>(hi); |
| + uint64_t value = (hi64 << 32) | lo64; |
| + return *reinterpret_cast<int64_t*>(&value); |
| +} |
| + |
| +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)) {} |
|
srdjan
2014/04/30 18:46:01
Assert int values are valid registers
Cutch
2014/05/21 17:00:03
I have added asserts to the DeoptContext so that a
|
| - 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_); |
| + int32_t lo_value = deopt_context->RegisterValue(lo_reg_); |
| + int32_t hi_value = deopt_context->RegisterValue(hi_reg_); |
| + int64_t value = CombineLoAndHi(&lo_value, &hi_value); |
| *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| if (Smi::IsValid64(value)) { |
| *dest_addr = reinterpret_cast<intptr_t>( |
| @@ -744,10 +762,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 = CombineLoAndHi(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) { |
|
srdjan
2014/04/30 18:46:01
ASSERT reg_as_int is a valid value.
Cutch
2014/05/21 17:00:03
As above, all accesses to registers in the deopt c
|
| + // 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 = CombineLoAndHi(®_value, &slot_value); |
| + } else { |
| + value = CombineLoAndHi(&slot_value, ®_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 +1325,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 +1478,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 +1508,33 @@ 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: |
|
srdjan
2014/04/30 18:46:01
Say R: Register, S: Stack-slot
Cutch
2014/05/21 17:00:03
Done.
|
| + // 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( |