| Index: runtime/vm/deopt_instructions.cc
|
| ===================================================================
|
| --- runtime/vm/deopt_instructions.cc (revision 10463)
|
| +++ runtime/vm/deopt_instructions.cc (working copy)
|
| @@ -4,16 +4,44 @@
|
|
|
| #include "vm/deopt_instructions.h"
|
|
|
| +#include "vm/assembler_macros.h"
|
| #include "vm/intermediate_language.h"
|
| #include "vm/locations.h"
|
| #include "vm/parser.h"
|
|
|
| namespace dart {
|
|
|
| +DeoptimizationContext::DeoptimizationContext(intptr_t* to_frame_start,
|
| + intptr_t to_frame_size,
|
| + const Array& object_table,
|
| + intptr_t num_args)
|
| + : object_table_(object_table),
|
| + to_frame_(to_frame_start),
|
| + to_frame_size_(to_frame_size),
|
| + from_frame_(NULL),
|
| + from_frame_size_(0),
|
| + 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();
|
| +}
|
| +
|
| +
|
| +intptr_t* DeoptimizationContext::GetFromFpAddress() const {
|
| + return &from_frame_[from_frame_size_ - 1 - num_args_ - 1];
|
| +}
|
| +
|
| +
|
| +intptr_t* DeoptimizationContext::GetFromPcAddress() const {
|
| + return &from_frame_[from_frame_size_ - 1 - num_args_];
|
| +}
|
| +
|
| // Deoptimization instruction moving value from optimized frame at
|
| // 'from_index' to specified slots in the unoptimized frame.
|
| -// 'from_index' represents the local count >= 0, first
|
| -// argument being 0.
|
| +// 'from_index' represents the slot index of the frame (0 being first argument)
|
| +// and accounts for saved return address, frame pointer and pc marker.
|
| class DeoptStackSlotInstr : public DeoptInstr {
|
| public:
|
| explicit DeoptStackSlotInstr(intptr_t from_index)
|
| @@ -31,6 +59,14 @@
|
| return chars;
|
| }
|
|
|
| + void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
|
| + intptr_t from_index =
|
| + deopt_context->from_frame_size() - stack_slot_index_ - 1;
|
| + intptr_t* from_addr = deopt_context->GetFromFrameAddressAt(from_index);
|
| + intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
|
| + *to_addr = *from_addr;
|
| + }
|
| +
|
| private:
|
| const intptr_t stack_slot_index_; // First argument is 0, always >= 0.
|
|
|
| @@ -57,6 +93,18 @@
|
| return chars;
|
| }
|
|
|
| + void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
|
| + Function& function = Function::Handle(deopt_context->isolate());
|
| + function ^= deopt_context->ObjectAt(object_table_index_);
|
| + Smi& deopt_id_as_smi = Smi::Handle(deopt_context->isolate());
|
| + deopt_id_as_smi ^= deopt_context->ObjectAt(object_table_index_ + 1);
|
| + const Code& code =
|
| + Code::Handle(deopt_context->isolate(), function.unoptimized_code());
|
| + uword continue_at_pc = code.GetDeoptPcAtDeoptId(deopt_id_as_smi.Value());
|
| + intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
|
| + *to_addr = continue_at_pc;
|
| + }
|
| +
|
| private:
|
| const intptr_t object_table_index_;
|
|
|
| @@ -82,6 +130,14 @@
|
| return chars;
|
| }
|
|
|
| + void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
|
| + const Object& obj = Object::Handle(
|
| + deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_));
|
| + RawObject** to_addr = reinterpret_cast<RawObject**>(
|
| + deopt_context->GetToFrameAddressAt(to_index));
|
| + *to_addr = obj.raw();
|
| + }
|
| +
|
| private:
|
| const intptr_t object_table_index_;
|
|
|
| @@ -102,6 +158,12 @@
|
| return Assembler::RegisterName(reg_);
|
| }
|
|
|
| + void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
|
| + intptr_t value = deopt_context->RegisterValue(reg_);
|
| + intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
|
| + *to_addr = value;
|
| + }
|
| +
|
| private:
|
| const Register reg_;
|
|
|
| @@ -128,6 +190,17 @@
|
| return chars;
|
| }
|
|
|
| + void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
|
| + Function& function = Function::Handle(deopt_context->isolate());
|
| + function ^= deopt_context->ObjectAt(object_table_index_);
|
| + const Code& code =
|
| + Code::Handle(deopt_context->isolate(), function.unoptimized_code());
|
| + intptr_t pc_marker = code.EntryPoint() +
|
| + AssemblerMacros::kOffsetOfSavedPCfromEntrypoint;
|
| + intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
|
| + *to_addr = pc_marker;
|
| + }
|
| +
|
| private:
|
| intptr_t object_table_index_;
|
|
|
| @@ -143,14 +216,22 @@
|
| virtual intptr_t from_index() const { return 0; }
|
| virtual DeoptInstr::Kind kind() const { return kSetCallerFp; }
|
|
|
| - virtual const char* ToCString() const { return "callerfp"; }
|
| + virtual const char* ToCString() const {
|
| + return "callerfp";
|
| + }
|
|
|
| + void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
|
| + intptr_t* from_addr = deopt_context->GetFromFpAddress();
|
| + intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
|
| + *to_addr = *from_addr;
|
| + }
|
| +
|
| private:
|
| DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr);
|
| };
|
|
|
|
|
| -// Deoptimization instruction copying the caller return address from optimzied
|
| +// Deoptimization instruction copying the caller return address from optimized
|
| // frame.
|
| class DeoptCallerPcInstr : public DeoptInstr {
|
| public:
|
| @@ -159,8 +240,16 @@
|
| virtual intptr_t from_index() const { return 0; }
|
| virtual DeoptInstr::Kind kind() const { return kSetCallerPc; }
|
|
|
| - virtual const char* ToCString() const { return "callerpc"; }
|
| + virtual const char* ToCString() const {
|
| + return "callerpc";
|
| + }
|
|
|
| + void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
|
| + intptr_t* from_addr = deopt_context->GetFromPcAddress();
|
| + intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
|
| + *to_addr = *from_addr;
|
| + }
|
| +
|
| private:
|
| DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr);
|
| };
|
| @@ -226,7 +315,11 @@
|
| } else if (from_loc.IsRegister()) {
|
| deopt_instr = new DeoptRegisterInstr(from_loc.reg());
|
| } else if (from_loc.IsStackSlot()) {
|
| - deopt_instr = new DeoptStackSlotInstr(from_loc.stack_index() + num_args_);
|
| + 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.IsInvalid()) {
|
| ASSERT(from_value.IsConstant());
|
| const Object& obj = from_value.AsConstant()->value();
|
|
|