Chromium Code Reviews| Index: runtime/vm/intermediate_language_ia32.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_ia32.cc (revision 33158) |
| +++ runtime/vm/intermediate_language_ia32.cc (working copy) |
| @@ -24,6 +24,7 @@ |
| DECLARE_FLAG(bool, propagate_ic_data); |
| DECLARE_FLAG(bool, use_osr); |
| DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| +DECLARE_FLAG(bool, use_slow_path); |
| // Generic summary for call instructions that have all arguments pushed |
| // on the stack and return the result in a fixed register EAX. |
| @@ -2255,6 +2256,16 @@ |
| LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const { |
| + if (opt) { |
| + const intptr_t kNumInputs = 0; |
| + const intptr_t kNumTemps = 3; |
| + LocationSummary* locs = new LocationSummary( |
| + kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| + locs->set_temp(0, Location::RegisterLocation(EAX)); |
| + locs->set_temp(1, Location::RegisterLocation(ECX)); |
| + locs->set_temp(2, Location::RegisterLocation(EBX)); |
| + locs->set_out(Location::RegisterLocation(EAX)); |
|
regis
2014/02/28 18:07:01
Don't you miss a return locs here?
Florian Schneider
2014/03/03 11:42:58
Thanks. Yes of course. That should improve the cod
|
| + } |
| const intptr_t kNumInputs = 0; |
| const intptr_t kNumTemps = 1; |
| LocationSummary* locs = |
| @@ -2265,7 +2276,105 @@ |
| } |
| +class AllocateContextSlowPath : public SlowPathCode { |
| + public: |
| + explicit AllocateContextSlowPath(AllocateContextInstr* instruction) |
| + : instruction_(instruction) { } |
| + |
| + virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| + __ Comment("AllocateContextSlowPath"); |
| + __ Bind(entry_label()); |
| + |
| + LocationSummary* locs = instruction_->locs(); |
| + locs->live_registers()->Remove(locs->out()); |
| + |
| + compiler->SaveLiveRegisters(locs); |
| + |
| + __ movl(EDX, Immediate(instruction_->num_context_variables())); |
| + const ExternalLabel label("alloc_context", |
| + StubCode::AllocateContextEntryPoint()); |
| + compiler->GenerateCall(instruction_->token_pos(), |
| + &label, |
| + PcDescriptors::kOther, |
| + locs); |
| + ASSERT(instruction_->locs()->out().reg() == EAX); |
| + compiler->RestoreLiveRegisters(instruction_->locs()); |
| + __ jmp(exit_label()); |
| + } |
| + |
| + private: |
| + AllocateContextInstr* instruction_; |
| +}; |
| + |
| + |
| + |
| void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| + if (compiler->is_optimizing()) { |
| + // Try allocate the object. |
| + AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| + compiler->AddSlowPathCode(slow_path); |
| + intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| + __ movl(EBX, Immediate(instance_size)); |
|
regis
2014/02/28 18:07:01
If you were using temp 2 instead of EBX directly,
Florian Schneider
2014/03/03 11:42:58
Done. Changed to temp0, temp1, result, etc.
|
| + Isolate* isolate = Isolate::Current(); |
| + Heap* heap = isolate->heap(); |
| + __ movl(EAX, Address::Absolute(heap->TopAddress())); |
|
regis
2014/02/28 18:07:01
ditto
Florian Schneider
2014/03/03 11:42:58
Done.
|
| + __ addl(EBX, EAX); |
|
regis
2014/02/28 18:07:01
ditto
Florian Schneider
2014/03/03 11:42:58
Done.
|
| + // Check if the allocation fits into the remaining space. |
| + // EAX: potential new object. |
| + // EBX: potential next object start. |
| + __ cmpl(EBX, Address::Absolute(heap->EndAddress())); |
| + if (FLAG_use_slow_path) { |
| + __ jmp(slow_path->entry_label()); |
| + } else { |
| + __ j(ABOVE_EQUAL, slow_path->entry_label()); |
| + } |
| + |
| + // Successfully allocated the object, now update top to point to |
| + // next object start and initialize the object. |
| + // EAX: new object. |
| + // EBX: next object start. |
| + // EDX: number of context variables. |
| + __ movl(Address::Absolute(heap->TopAddress()), EBX); |
| + __ addl(EAX, Immediate(kHeapObjectTag)); |
| + __ UpdateAllocationStatsWithSize(kContextCid, instance_size, kNoRegister); |
| + |
| + // Calculate the size tag and write tags. |
| + intptr_t size_tag = (instance_size > RawObject::SizeTag::kMaxSizeTag) |
| + ? 0 : instance_size << (RawObject::kSizeTagBit - kObjectAlignmentLog2); |
| + |
| + intptr_t tags = size_tag | RawObject::ClassIdTag::encode(kContextCid); |
| + __ movl(FieldAddress(EAX, Context::tags_offset()), Immediate(tags)); |
| + |
| + // Setup up number of context variables field. |
| + // EAX: new object. |
| + __ movl(FieldAddress(EAX, Context::num_variables_offset()), |
| + Immediate(num_context_variables())); |
| + |
| + // Setup isolate field. |
| + __ movl(FieldAddress(EAX, Context::isolate_offset()), |
| + Immediate(reinterpret_cast<int32_t>(isolate))); |
| + |
| + // Setup the parent field. |
| + const Immediate& raw_null = |
| + Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| + __ movl(FieldAddress(EAX, Context::parent_offset()), raw_null); |
| + |
| + // Initialize the context variables. |
| + // EAX: new object. |
| + if (num_context_variables() > 0) { |
| + Label loop; |
| + __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); |
| + __ movl(ECX, Immediate(num_context_variables())); |
| + __ Bind(&loop); |
| + __ decl(ECX); |
| + __ movl(Address(EBX, ECX, TIMES_4, 0), raw_null); |
| + __ j(NOT_ZERO, &loop, Assembler::kNearJump); |
| + } |
| + // EAX: new object. |
| + __ Bind(slow_path->exit_label()); |
| + return; |
| + } |
| + |
| ASSERT(locs()->temp(0).reg() == EDX); |
| ASSERT(locs()->out().reg() == EAX); |