Index: runtime/vm/deopt_instructions.cc |
=================================================================== |
--- runtime/vm/deopt_instructions.cc (revision 27970) |
+++ runtime/vm/deopt_instructions.cc (working copy) |
@@ -18,58 +18,133 @@ |
DECLARE_FLAG(bool, trace_deoptimization); |
DECLARE_FLAG(bool, trace_deoptimization_verbose); |
-DeoptimizationContext::DeoptimizationContext(intptr_t* to_frame_start, |
- intptr_t to_frame_size, |
- const Array& object_table, |
- intptr_t num_args, |
- DeoptReasonId deopt_reason) |
- : object_table_(object_table), |
- to_frame_(to_frame_start), |
- to_frame_size_(to_frame_size), |
+DeoptContext::DeoptContext(const Array& object_table, |
+ intptr_t num_args, |
+ DeoptReasonId deopt_reason) |
+ : object_table_(object_table.raw()), |
+ to_frame_(NULL), |
+ to_frame_size_(0), |
from_frame_(NULL), |
from_frame_size_(0), |
- registers_copy_(NULL), |
- fpu_registers_copy_(NULL), |
+ cpu_registers_(NULL), |
+ fpu_registers_(NULL), |
num_args_(num_args), |
deopt_reason_(deopt_reason), |
- isolate_(Isolate::Current()) { |
- from_frame_ = isolate_->deopt_frame_copy(); |
- from_frame_size_ = isolate_->deopt_frame_copy_size(); |
- registers_copy_ = isolate_->deopt_cpu_registers_copy(); |
- fpu_registers_copy_ = isolate_->deopt_fpu_registers_copy(); |
- // The deoptimized frame is filled starting just below the sp of its caller |
- // down to kDartFrameFixedSize words below its own sp. |
- // The chain of frame pointers is recreated from the fp of the caller. |
+ isolate_(Isolate::Current()), |
+ deferred_boxes_(NULL), |
+ deferred_object_refs_(NULL), |
+ deferred_objects_count_(0), |
+ deferred_objects_(NULL) { |
+} |
+ |
+ |
+DeoptContext::~DeoptContext() { |
+ // Delete all deferred objects. |
+ for (intptr_t i = 0; i < deferred_objects_count_; i++) { |
+ delete deferred_objects_[i]; |
+ } |
+ delete[] deferred_objects_; |
+ deferred_objects_ = NULL; |
+ deferred_objects_count_ = 0; |
+} |
+ |
+ |
+void DeoptContext::SetToFrame(intptr_t* start, |
+ intptr_t size) { |
+ ASSERT(start != NULL); |
+ ASSERT(size >= 0); |
+ ASSERT(to_frame_ == NULL); |
+ to_frame_ = start; |
+ to_frame_size_ = size; |
+} |
+ |
+ |
+void DeoptContext::SetFromFrame(intptr_t* start, |
+ intptr_t size) { |
+ ASSERT(start != NULL); |
+ ASSERT(size >= 0); |
+ ASSERT(from_frame_ == NULL); |
+ from_frame_ = start; |
+ from_frame_size_ = size; |
caller_fp_ = GetFromFp(); |
} |
-intptr_t DeoptimizationContext::GetFromFp() const { |
+void DeoptContext::SetSavedRegisters(fpu_register_t* fpu_registers, |
+ intptr_t* cpu_registers) { |
+ ASSERT(cpu_registers_ == NULL && fpu_registers_ == NULL); |
+ cpu_registers_ = cpu_registers; |
+ fpu_registers_ = fpu_registers; |
+} |
+ |
+ |
+void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
+ visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_table_)); |
+} |
+ |
+ |
+intptr_t DeoptContext::GetFromFp() const { |
return from_frame_[from_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp]; |
} |
-intptr_t DeoptimizationContext::GetFromPp() const { |
+intptr_t DeoptContext::GetFromPp() const { |
return from_frame_[from_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp + |
StackFrame::SavedCallerPpSlotFromFp()]; |
} |
-intptr_t DeoptimizationContext::GetFromPc() const { |
+intptr_t DeoptContext::GetFromPc() const { |
return from_frame_[from_frame_size_ - num_args_ + kSavedPcSlotFromSp]; |
} |
-intptr_t DeoptimizationContext::GetCallerFp() const { |
+intptr_t DeoptContext::GetCallerFp() const { |
return caller_fp_; |
} |
-void DeoptimizationContext::SetCallerFp(intptr_t caller_fp) { |
+void DeoptContext::SetCallerFp(intptr_t caller_fp) { |
caller_fp_ = caller_fp; |
} |
+static void FillDeferredSlots(DeferredSlot** slot_list) { |
+ DeferredSlot* slot = *slot_list; |
+ *slot_list = NULL; |
+ |
+ while (slot != NULL) { |
+ DeferredSlot* current = slot; |
+ slot = slot->next(); |
+ |
+ current->Materialize(); |
+ |
+ delete current; |
+ } |
+} |
+ |
+ |
+// Materializes all deferred objects. Returns the total number of |
+// artificial arguments used during deoptimization. |
+intptr_t DeoptContext::MaterializeDeferredObjects() { |
+ // First materialize all unboxed "primitive" values (doubles, mints, simd) |
+ // then materialize objects. The order is important: objects might be |
+ // referencing boxes allocated on the first step. At the same time |
+ // objects can't be referencing other deferred objects because storing |
+ // an object into a field is always conservatively treated as escaping by |
+ // allocation sinking and load forwarding. |
+ FillDeferredSlots(&deferred_boxes_); |
+ FillDeferredSlots(&deferred_object_refs_); |
+ |
+ // Compute total number of artificial arguments used during deoptimization. |
+ intptr_t deopt_arguments = 0; |
+ for (intptr_t i = 0; i < DeferredObjectsCount(); i++) { |
+ deopt_arguments += GetDeferredObject(i)->ArgumentCount(); |
+ } |
+ return deopt_arguments; |
+} |
+ |
+ |
// Deoptimization instruction moving value from optimized frame at |
// 'from_index' to specified slots in the unoptimized frame. |
// 'from_index' represents the slot index of the frame (0 being first argument) |
@@ -90,7 +165,7 @@ |
"s%" Pd "", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
intptr_t from_index = |
deopt_context->from_frame_size() - stack_slot_index_ - 1; |
intptr_t* from_addr = deopt_context->GetFromFrameAddressAt(from_index); |
@@ -119,13 +194,13 @@ |
"ds%" Pd "", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
intptr_t from_index = |
deopt_context->from_frame_size() - stack_slot_index_ - 1; |
double* from_addr = reinterpret_cast<double*>( |
deopt_context->GetFromFrameAddressAt(from_index)); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
- Isolate::Current()->DeferDoubleMaterialization( |
+ deopt_context->DeferDoubleMaterialization( |
*from_addr, reinterpret_cast<RawDouble**>(to_addr)); |
} |
@@ -151,7 +226,7 @@ |
"ms%" Pd "", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
intptr_t from_index = |
deopt_context->from_frame_size() - stack_slot_index_ - 1; |
int64_t* from_addr = reinterpret_cast<int64_t*>( |
@@ -161,7 +236,7 @@ |
*to_addr = reinterpret_cast<intptr_t>( |
Smi::New(static_cast<intptr_t>(*from_addr))); |
} else { |
- Isolate::Current()->DeferMintMaterialization( |
+ deopt_context->DeferMintMaterialization( |
*from_addr, reinterpret_cast<RawMint**>(to_addr)); |
} |
} |
@@ -188,13 +263,13 @@ |
"f32x4s%" Pd "", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
intptr_t from_index = |
deopt_context->from_frame_size() - stack_slot_index_ - 1; |
simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( |
deopt_context->GetFromFrameAddressAt(from_index)); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
- Isolate::Current()->DeferFloat32x4Materialization( |
+ deopt_context->DeferFloat32x4Materialization( |
*from_addr, reinterpret_cast<RawFloat32x4**>(to_addr)); |
} |
@@ -220,13 +295,13 @@ |
"ui32x4s%" Pd "", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
intptr_t from_index = |
deopt_context->from_frame_size() - stack_slot_index_ - 1; |
simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( |
deopt_context->GetFromFrameAddressAt(from_index)); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
- Isolate::Current()->DeferUint32x4Materialization( |
+ deopt_context->DeferUint32x4Materialization( |
*from_addr, reinterpret_cast<RawUint32x4**>(to_addr)); |
} |
@@ -264,7 +339,7 @@ |
"ret oti:%" Pd "(%" Pd ")", object_table_index_, deopt_id_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
Function& function = Function::Handle(deopt_context->isolate()); |
function ^= deopt_context->ObjectAt(object_table_index_); |
const Code& code = |
@@ -318,7 +393,7 @@ |
"const oti:%" Pd "", object_table_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
const Object& obj = Object::Handle( |
deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); |
*reinterpret_cast<RawObject**>(to_addr) = obj.raw(); |
@@ -344,7 +419,7 @@ |
return Assembler::RegisterName(reg_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
*to_addr = deopt_context->RegisterValue(reg_); |
} |
@@ -368,10 +443,10 @@ |
return Assembler::FpuRegisterName(reg_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
double value = deopt_context->FpuRegisterValue(reg_); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
- Isolate::Current()->DeferDoubleMaterialization( |
+ deopt_context->DeferDoubleMaterialization( |
value, reinterpret_cast<RawDouble**>(to_addr)); |
} |
@@ -395,14 +470,14 @@ |
"%s(m)", Assembler::FpuRegisterName(reg_)); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
if (Smi::IsValid64(value)) { |
*to_addr = reinterpret_cast<intptr_t>( |
Smi::New(static_cast<intptr_t>(value))); |
} else { |
- Isolate::Current()->DeferMintMaterialization( |
+ deopt_context->DeferMintMaterialization( |
value, reinterpret_cast<RawMint**>(to_addr)); |
} |
} |
@@ -428,10 +503,10 @@ |
"%s(f32x4)", Assembler::FpuRegisterName(reg_)); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
- Isolate::Current()->DeferFloat32x4Materialization( |
+ deopt_context->DeferFloat32x4Materialization( |
value, reinterpret_cast<RawFloat32x4**>(to_addr)); |
} |
@@ -456,10 +531,10 @@ |
"%s(f32x4)", Assembler::FpuRegisterName(reg_)); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
- Isolate::Current()->DeferUint32x4Materialization( |
+ deopt_context->DeferUint32x4Materialization( |
value, reinterpret_cast<RawUint32x4**>(to_addr)); |
} |
@@ -487,7 +562,7 @@ |
"pcmark oti:%" Pd "", object_table_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
Function& function = Function::Handle(deopt_context->isolate()); |
function ^= deopt_context->ObjectAt(object_table_index_); |
if (function.IsNull()) { |
@@ -539,7 +614,7 @@ |
"pp oti:%" Pd "", object_table_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
Function& function = Function::Handle(deopt_context->isolate()); |
function ^= deopt_context->ObjectAt(object_table_index_); |
const Code& code = |
@@ -568,7 +643,7 @@ |
return "callerfp"; |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
*to_addr = deopt_context->GetCallerFp(); |
deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( |
to_addr - (kSavedCallerFpSlotFromFp * kWordSize))); |
@@ -591,7 +666,7 @@ |
return "callerpp"; |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
*to_addr = deopt_context->GetFromPp(); |
} |
@@ -613,7 +688,7 @@ |
return "callerpc"; |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
*to_addr = deopt_context->GetFromPc(); |
} |
@@ -650,7 +725,7 @@ |
"suffix %" Pd ":%" Pd, info_number_, suffix_length_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
// The deoptimization info is uncompressed by translating away suffixes |
// before executing the instructions. |
UNREACHABLE(); |
@@ -689,9 +764,9 @@ |
"mat ref #%" Pd "", index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
- Isolate::Current()->DeferMaterializedObjectRef( |
+ deopt_context->DeferMaterializedObjectRef( |
index_, to_addr); |
} |
@@ -720,7 +795,7 @@ |
"mat obj len:%" Pd "", field_count_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ void Execute(DeoptContext* deopt_context, intptr_t* to_addr) { |
// This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
UNREACHABLE(); |
} |