| 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();
|
| }
|
|
|