Index: runtime/vm/deopt_instructions.cc |
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc |
index eabb177c95f60576fbb42bb9479d9865ed65f536..95d250032d329fb87249b1290e03e7f65968e210 100644 |
--- a/runtime/vm/deopt_instructions.cc |
+++ b/runtime/vm/deopt_instructions.cc |
@@ -21,11 +21,13 @@ DeoptimizationContext::DeoptimizationContext(intptr_t* to_frame_start, |
from_frame_(NULL), |
from_frame_size_(0), |
registers_copy_(NULL), |
+ xmm_registers_copy_(NULL), |
num_args_(num_args), |
isolate_(Isolate::Current()) { |
from_frame_ = isolate_->deopt_frame_copy(); |
from_frame_size_ = isolate_->deopt_frame_copy_size(); |
- registers_copy_ = isolate_->deopt_registers_copy(); |
+ registers_copy_ = isolate_->deopt_cpu_registers_copy(); |
+ xmm_registers_copy_ = isolate_->deopt_xmm_registers_copy(); |
} |
@@ -74,6 +76,41 @@ class DeoptStackSlotInstr : public DeoptInstr { |
}; |
+class DeoptDoubleStackSlotInstr : public DeoptInstr { |
+ public: |
+ explicit DeoptDoubleStackSlotInstr(intptr_t from_index) |
+ : stack_slot_index_(from_index) { |
+ ASSERT(stack_slot_index_ >= 0); |
+ } |
+ |
+ virtual intptr_t from_index() const { return stack_slot_index_; } |
+ virtual DeoptInstr::Kind kind() const { return kCopyDoubleStackSlot; } |
+ |
+ virtual const char* ToCString() const { |
+ intptr_t len = OS::SNPrint(NULL, 0, "ds%d", stack_slot_index_); |
+ char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
+ OS::SNPrint(chars, len + 1, "ds%d", stack_slot_index_); |
+ return chars; |
+ } |
+ |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ intptr_t from_index = |
+ deopt_context->from_frame_size() - stack_slot_index_ - 1; |
+ double* from_addr = reinterpret_cast<double*>( |
+ deopt_context->GetFromFrameAddressAt(from_index)); |
+ intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
+ *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
+ Isolate::Current()->DeferDoubleMaterialization( |
+ *from_addr, reinterpret_cast<RawDouble**>(to_addr)); |
+ } |
+ |
+ private: |
+ const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); |
+}; |
+ |
+ |
// Deoptimization instruction creating return address using function and |
// deopt-id stored at 'object_table_index'. |
class DeoptRetAddrInstr : public DeoptInstr { |
@@ -145,7 +182,7 @@ class DeoptConstantInstr : public DeoptInstr { |
}; |
-// Deoptimization instruction moving a register. |
+// Deoptimization instruction moving a CPU register. |
class DeoptRegisterInstr: public DeoptInstr { |
public: |
explicit DeoptRegisterInstr(intptr_t reg_as_int) |
@@ -171,6 +208,34 @@ class DeoptRegisterInstr: public DeoptInstr { |
}; |
+// Deoptimization instruction moving an XMM register. |
+class DeoptXmmRegisterInstr: public DeoptInstr { |
+ public: |
+ explicit DeoptXmmRegisterInstr(intptr_t reg_as_int) |
+ : reg_(static_cast<XmmRegister>(reg_as_int)) {} |
+ |
+ virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
+ virtual DeoptInstr::Kind kind() const { return kCopyXmmRegister; } |
+ |
+ virtual const char* ToCString() const { |
+ return Assembler::XmmRegisterName(reg_); |
+ } |
+ |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ double value = deopt_context->XmmRegisterValue(reg_); |
+ intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
+ *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
+ Isolate::Current()->DeferDoubleMaterialization( |
+ value, reinterpret_cast<RawDouble**>(to_addr)); |
+ } |
+ |
+ private: |
+ const XmmRegister reg_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DeoptXmmRegisterInstr); |
+}; |
+ |
+ |
// Deoptimization instruction creating a PC marker for the code of |
// function at 'object_table_index'. |
class DeoptPcMarkerInstr : public DeoptInstr { |
@@ -259,9 +324,11 @@ DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { |
Kind kind = static_cast<Kind>(kind_as_int); |
switch (kind) { |
case kCopyStackSlot: return new DeoptStackSlotInstr(from_index); |
+ case kCopyDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); |
case kSetRetAddress: return new DeoptRetAddrInstr(from_index); |
case kCopyConstant: return new DeoptConstantInstr(from_index); |
case kCopyRegister: return new DeoptRegisterInstr(from_index); |
+ case kCopyXmmRegister: return new DeoptXmmRegisterInstr(from_index); |
case kSetPcMarker: return new DeoptPcMarkerInstr(from_index); |
case kSetCallerFp: return new DeoptCallerFpInstr(); |
case kSetCallerPc: return new DeoptCallerPcInstr(); |
@@ -314,12 +381,20 @@ void DeoptInfoBuilder::AddCopy(const Location& from_loc, |
deopt_instr = new DeoptConstantInstr(object_table_index); |
} else if (from_loc.IsRegister()) { |
deopt_instr = new DeoptRegisterInstr(from_loc.reg()); |
+ } else if (from_loc.IsXmmRegister()) { |
+ deopt_instr = new DeoptXmmRegisterInstr(from_loc.xmm_reg()); |
} else if (from_loc.IsStackSlot()) { |
intptr_t from_index = (from_loc.stack_index() < 0) ? |
from_loc.stack_index() + num_args_ : |
from_loc.stack_index() + num_args_ - |
ParsedFunction::kFirstLocalSlotIndex + 1; |
deopt_instr = new DeoptStackSlotInstr(from_index); |
+ } else if (from_loc.IsDoubleStackSlot()) { |
+ intptr_t from_index = (from_loc.stack_index() < 0) ? |
+ from_loc.stack_index() + num_args_ : |
+ from_loc.stack_index() + num_args_ - |
+ ParsedFunction::kFirstLocalSlotIndex + 1; |
+ deopt_instr = new DeoptDoubleStackSlotInstr(from_index); |
} else { |
UNREACHABLE(); |
} |