Index: runtime/vm/deopt_instructions.cc |
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc |
index fce3e71822c8c033a9f0a82ea4129564842f07f1..b9a6da3a062abb1069b204bc7dfd50bc742fa9c2 100644 |
--- a/runtime/vm/deopt_instructions.cc |
+++ b/runtime/vm/deopt_instructions.cc |
@@ -72,18 +72,14 @@ class DeoptStackSlotInstr : public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kStackSlot; } |
virtual const char* ToCString() const { |
- const char* format = "s%"Pd""; |
- intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, stack_slot_index_); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "s%"Pd"", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* 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); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
*to_addr = *from_addr; |
} |
@@ -105,19 +101,15 @@ class DeoptDoubleStackSlotInstr : public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; } |
virtual const char* ToCString() const { |
- const char* format = "ds%"Pd""; |
- intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, stack_slot_index_); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "ds%"Pd"", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* 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)); |
- 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)); |
@@ -141,19 +133,15 @@ class DeoptInt64StackSlotInstr : public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; } |
virtual const char* ToCString() const { |
- const char* format = "ms%"Pd""; |
- intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, stack_slot_index_); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "ms%"Pd"", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* 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*>( |
deopt_context->GetFromFrameAddressAt(from_index)); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
if (Smi::IsValid64(*from_addr)) { |
*to_addr = reinterpret_cast<intptr_t>( |
@@ -182,19 +170,15 @@ class DeoptFloat32x4StackSlotInstr : public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; } |
virtual const char* ToCString() const { |
- const char* format = "f32x4s%"Pd""; |
- intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, stack_slot_index_); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "f32x4s%"Pd"", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* 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)); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
Isolate::Current()->DeferFloat32x4Materialization( |
*from_addr, reinterpret_cast<RawFloat32x4**>(to_addr)); |
@@ -218,19 +202,15 @@ class DeoptUint32x4StackSlotInstr : public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; } |
virtual const char* ToCString() const { |
- const char* format = "ui32x4s%"Pd""; |
- intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, stack_slot_index_); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "ui32x4s%"Pd"", stack_slot_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* 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)); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
Isolate::Current()->DeferUint32x4Materialization( |
*from_addr, reinterpret_cast<RawUint32x4**>(to_addr)); |
@@ -270,7 +250,7 @@ class DeoptRetAddressInstr : public DeoptInstr { |
"ret oti:%"Pd"(%"Pd")", object_table_index_, deopt_id_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
Function& function = Function::Handle(deopt_context->isolate()); |
function ^= deopt_context->ObjectAt(object_table_index_); |
const Code& code = |
@@ -279,7 +259,6 @@ class DeoptRetAddressInstr : public DeoptInstr { |
uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, |
PcDescriptors::kDeopt); |
ASSERT(continue_at_pc != 0); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
*to_addr = continue_at_pc; |
uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); |
@@ -321,19 +300,14 @@ class DeoptConstantInstr : public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kConstant; } |
virtual const char* ToCString() const { |
- const char* format = "const oti:%"Pd""; |
- intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, object_table_index_); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "const oti:%"Pd"", object_table_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
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(); |
+ *reinterpret_cast<RawObject**>(to_addr) = obj.raw(); |
} |
private: |
@@ -356,10 +330,8 @@ class DeoptRegisterInstr: public DeoptInstr { |
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; |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ *to_addr = deopt_context->RegisterValue(reg_); |
} |
private: |
@@ -382,9 +354,8 @@ class DeoptFpuRegisterInstr: public DeoptInstr { |
return Assembler::FpuRegisterName(reg_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
double value = deopt_context->FpuRegisterValue(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)); |
@@ -406,17 +377,12 @@ class DeoptInt64FpuRegisterInstr: public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; } |
virtual const char* ToCString() const { |
- const char* format = "%s(m)"; |
- intptr_t len = |
- OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_)); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_)); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "%s(m)", Assembler::FpuRegisterName(reg_)); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
if (Smi::IsValid64(value)) { |
*to_addr = reinterpret_cast<intptr_t>( |
@@ -444,17 +410,12 @@ class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } |
virtual const char* ToCString() const { |
- const char* format = "%s(f32x4)"; |
- intptr_t len = |
- OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_)); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_)); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "%s(f32x4)", Assembler::FpuRegisterName(reg_)); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
Isolate::Current()->DeferFloat32x4Materialization( |
value, reinterpret_cast<RawFloat32x4**>(to_addr)); |
@@ -477,17 +438,12 @@ class DeoptUint32x4FpuRegisterInstr: public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } |
virtual const char* ToCString() const { |
- const char* format = "%s(f32x4)"; |
- intptr_t len = |
- OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_)); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_)); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "%s(f32x4)", Assembler::FpuRegisterName(reg_)); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
*reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
Isolate::Current()->DeferUint32x4Materialization( |
value, reinterpret_cast<RawUint32x4**>(to_addr)); |
@@ -513,14 +469,11 @@ class DeoptPcMarkerInstr : public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
virtual const char* ToCString() const { |
- const char* format = "pcmark oti:%"Pd""; |
- intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, object_table_index_); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "pcmark oti:%"Pd"", object_table_index_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
Function& function = Function::Handle(deopt_context->isolate()); |
function ^= deopt_context->ObjectAt(object_table_index_); |
const Code& code = |
@@ -528,7 +481,6 @@ class DeoptPcMarkerInstr : public DeoptInstr { |
ASSERT(!code.IsNull()); |
intptr_t pc_marker = code.EntryPoint() + |
Assembler::kOffsetOfSavedPCfromEntrypoint; |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
*to_addr = pc_marker; |
// Increment the deoptimization counter. This effectively increments each |
// function occurring in the optimized frame. |
@@ -563,10 +515,8 @@ class DeoptCallerFpInstr : public DeoptInstr { |
return "callerfp"; |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
- intptr_t from = deopt_context->GetCallerFp(); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
- *to_addr = from; |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ *to_addr = deopt_context->GetCallerFp(); |
deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr)); |
} |
@@ -588,10 +538,8 @@ class DeoptCallerPcInstr : public DeoptInstr { |
return "callerpc"; |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
- intptr_t from = deopt_context->GetFromPc(); |
- intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
- *to_addr = from; |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ *to_addr = deopt_context->GetFromPc(); |
} |
private: |
@@ -623,14 +571,11 @@ class DeoptSuffixInstr : public DeoptInstr { |
virtual DeoptInstr::Kind kind() const { return kSuffix; } |
virtual const char* ToCString() const { |
- const char* format = "suffix %"Pd":%"Pd; |
- intptr_t len = OS::SNPrint(NULL, 0, format, info_number_, suffix_length_); |
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(chars, len + 1, format, info_number_, suffix_length_); |
- return chars; |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "suffix %"Pd":%"Pd, info_number_, suffix_length_); |
} |
- void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
// The deoptimization info is uncompressed by translating away suffixes |
// before executing the instructions. |
UNREACHABLE(); |
@@ -652,6 +597,66 @@ class DeoptSuffixInstr : public DeoptInstr { |
}; |
+// Write reference to a materialized object with the given index into the |
+// stack slot. |
+class DeoptMaterializedObjectRefInstr : public DeoptInstr { |
+ public: |
+ explicit DeoptMaterializedObjectRefInstr(intptr_t index) |
+ : index_(index) { |
+ ASSERT(index >= 0); |
+ } |
+ |
+ virtual intptr_t from_index() const { return index_; } |
+ virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } |
+ |
+ virtual const char* ToCString() const { |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "mat ref #%"Pd"", index_); |
+ } |
+ |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
+ Isolate::Current()->DeferMaterializedObjectRef( |
+ index_, to_addr); |
+ } |
+ |
+ private: |
+ intptr_t index_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); |
+}; |
+ |
+ |
+// Materialize object with the given number of fields. |
+// Arguments for materialization (class and field-value pairs) are pushed |
+// to the expression stack of the bottom-most frame. |
+class DeoptMaterializeObjectInstr : public DeoptInstr { |
+ public: |
+ explicit DeoptMaterializeObjectInstr(intptr_t field_count) |
+ : field_count_(field_count) { |
+ ASSERT(field_count >= 0); |
+ } |
+ |
+ virtual intptr_t from_index() const { return field_count_; } |
+ virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } |
+ |
+ virtual const char* ToCString() const { |
+ return Isolate::Current()->current_zone()->PrintToString( |
+ "mat obj len:%"Pd"", field_count_); |
+ } |
+ |
+ void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
+ // This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
+ UNREACHABLE(); |
+ } |
+ |
+ private: |
+ intptr_t field_count_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); |
+}; |
+ |
+ |
intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) { |
*info_number = DeoptSuffixInstr::InfoNumber::decode(from_index); |
return DeoptSuffixInstr::SuffixLength::decode(from_index); |
@@ -700,6 +705,9 @@ DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { |
case kCallerFp: return new DeoptCallerFpInstr(); |
case kCallerPc: return new DeoptCallerPcInstr(); |
case kSuffix: return new DeoptSuffixInstr(from_index); |
+ case kMaterializedObjectRef: |
+ return new DeoptMaterializedObjectRefInstr(from_index); |
+ case kMaterializeObject: return new DeoptMaterializeObjectInstr(from_index); |
} |
UNREACHABLE(); |
return NULL; |
@@ -743,7 +751,9 @@ DeoptInfoBuilder::DeoptInfoBuilder(const intptr_t num_args) |
object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())), |
num_args_(num_args), |
trie_root_(new TrieNode()), |
- current_info_number_(0) { |
+ current_info_number_(0), |
+ frame_start_(-1), |
+ materializations_() { |
} |
@@ -778,7 +788,7 @@ void DeoptInfoBuilder::AddReturnAddress(const Function& function, |
(code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0)); |
#endif |
const intptr_t object_table_index = FindOrAddObjectInTable(function); |
- ASSERT(to_index == instructions_.length()); |
+ ASSERT(to_index == FrameSize()); |
instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id)); |
} |
@@ -787,7 +797,7 @@ void DeoptInfoBuilder::AddPcMarker(const Function& function, |
intptr_t to_index) { |
// Function object was already added by AddReturnAddress, find it. |
intptr_t from_index = FindOrAddObjectInTable(function); |
- ASSERT(to_index == instructions_.length()); |
+ ASSERT(to_index == FrameSize()); |
instructions_.Add(new DeoptPcMarkerInstr(from_index)); |
} |
@@ -833,35 +843,102 @@ void DeoptInfoBuilder::AddCopy(Value* value, |
ASSERT(value->definition()->representation() == kUnboxedUint32x4); |
deopt_instr = new DeoptUint32x4StackSlotInstr(from_index); |
} |
+ } else if (from_loc.IsInvalid() && |
+ value->definition()->IsMaterializeObject()) { |
+ const intptr_t index = FindMaterialization( |
+ value->definition()->AsMaterializeObject()); |
+ ASSERT(index >= 0); |
+ deopt_instr = new DeoptMaterializedObjectRefInstr(index); |
} else { |
UNREACHABLE(); |
} |
- ASSERT(to_index == instructions_.length()); |
+ ASSERT(to_index == FrameSize()); |
ASSERT(deopt_instr != NULL); |
instructions_.Add(deopt_instr); |
} |
void DeoptInfoBuilder::AddCallerFp(intptr_t to_index) { |
- ASSERT(to_index == instructions_.length()); |
+ ASSERT(to_index == FrameSize()); |
instructions_.Add(new DeoptCallerFpInstr()); |
} |
void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) { |
- ASSERT(to_index == instructions_.length()); |
+ ASSERT(to_index == FrameSize()); |
instructions_.Add(new DeoptCallerPcInstr()); |
} |
+void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t to_index) { |
+ ASSERT(to_index == FrameSize()); |
+ intptr_t object_table_index = FindOrAddObjectInTable(obj); |
+ instructions_.Add(new DeoptConstantInstr(object_table_index)); |
+} |
+ |
+ |
+void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { |
+ const intptr_t index = FindMaterialization(mat); |
+ if (index >= 0) { |
+ return; // Already added. |
+ } |
+ materializations_.Add(mat); |
+ |
+ // Count initialized fields and emit kMaterializeObject instruction. |
+ // There is no need to write nulls into fields because object is null |
+ // initialized by default. |
+ intptr_t non_null_fields = 0; |
+ for (intptr_t i = 0; i < mat->InputCount(); i++) { |
+ if (!mat->InputAt(i)->BindsToConstantNull()) { |
+ non_null_fields++; |
+ } |
+ } |
+ |
+ instructions_.Add(new DeoptMaterializeObjectInstr(non_null_fields)); |
+} |
+ |
+ |
+intptr_t DeoptInfoBuilder::EmitMaterializationArguments() { |
+ intptr_t slot_idx = 1; // Return address is emitted at 0. |
+ for (intptr_t i = 0; i < materializations_.length(); i++) { |
+ MaterializeObjectInstr* mat = materializations_[i]; |
+ AddConstant(mat->cls(), slot_idx++); // Class of the instance to allocate. |
+ for (intptr_t i = 0; i < mat->InputCount(); i++) { |
+ if (!mat->InputAt(i)->BindsToConstantNull()) { |
+ // Emit field-value pair. |
+ AddConstant(mat->FieldAt(i), slot_idx++); |
+ AddCopy(mat->InputAt(i), mat->LocationAt(i), slot_idx++); |
+ } |
+ } |
+ } |
+ return slot_idx; |
+} |
+ |
+ |
+intptr_t DeoptInfoBuilder::FindMaterialization( |
+ MaterializeObjectInstr* mat) const { |
+ for (intptr_t i = 0; i < materializations_.length(); i++) { |
+ if (materializations_[i] == mat) { |
+ return i; |
+ } |
+ } |
+ return -1; |
+} |
+ |
+ |
RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() { |
+ // TODO(vegorov): enable compression of deoptimization info containing object |
+ // materialization instructions. |
+ const bool disable_compression = |
+ (instructions_[0]->kind() == DeoptInstr::kMaterializeObject); |
+ |
intptr_t length = instructions_.length(); |
// Count the number of instructions that are a shared suffix of some deopt |
// info already written. |
TrieNode* suffix = trie_root_; |
intptr_t suffix_length = 0; |
- if (FLAG_compress_deopt_info) { |
+ if (FLAG_compress_deopt_info && !disable_compression) { |
for (intptr_t i = length - 1; i >= 0; --i) { |
TrieNode* node = suffix->FindChild(*instructions_[i]); |
if (node == NULL) break; |
@@ -894,6 +971,9 @@ RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() { |
} |
instructions_.Clear(); |
+ materializations_.Clear(); |
+ frame_start_ = -1; |
+ |
++current_info_number_; |
return deopt_info.raw(); |
} |