| 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 = 2;
|
| + LocationSummary* locs = new LocationSummary(
|
| + kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
|
| + locs->set_temp(0, Location::RegisterLocation(ECX));
|
| + locs->set_temp(1, Location::RegisterLocation(EBX));
|
| + locs->set_out(Location::RegisterLocation(EAX));
|
| + return locs;
|
| + }
|
| const intptr_t kNumInputs = 0;
|
| const intptr_t kNumTemps = 1;
|
| LocationSummary* locs =
|
| @@ -2265,7 +2276,108 @@
|
| }
|
|
|
|
|
| +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()) {
|
| + Register temp0 = locs()->temp(0).reg();
|
| + Register temp1 = locs()->temp(1).reg();
|
| + Register result = locs()->out().reg();
|
| + // Try allocate the object.
|
| + AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this);
|
| + compiler->AddSlowPathCode(slow_path);
|
| + intptr_t instance_size = Context::InstanceSize(num_context_variables());
|
| + __ movl(temp1, Immediate(instance_size));
|
| + Isolate* isolate = Isolate::Current();
|
| + Heap* heap = isolate->heap();
|
| + __ movl(result, Address::Absolute(heap->TopAddress()));
|
| + __ addl(temp1, result);
|
| + // Check if the allocation fits into the remaining space.
|
| + // EAX: potential new object.
|
| + // EBX: potential next object start.
|
| + __ cmpl(temp1, 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()), temp1);
|
| + __ addl(result, 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(result, Context::tags_offset()), Immediate(tags));
|
| +
|
| + // Setup up number of context variables field.
|
| + // EAX: new object.
|
| + __ movl(FieldAddress(result, Context::num_variables_offset()),
|
| + Immediate(num_context_variables()));
|
| +
|
| + // Setup isolate field.
|
| + __ movl(FieldAddress(result, 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(result, Context::parent_offset()), raw_null);
|
| +
|
| + // Initialize the context variables.
|
| + // EAX: new object.
|
| + if (num_context_variables() > 0) {
|
| + Label loop;
|
| + __ leal(temp1, FieldAddress(result, Context::variable_offset(0)));
|
| + __ movl(temp0, Immediate(num_context_variables()));
|
| + __ Bind(&loop);
|
| + __ decl(temp0);
|
| + __ movl(Address(temp1, temp0, 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);
|
|
|
|
|