From e7027442dcbdbff6d891ffc87ec4ffbf246f721f Mon Sep 17 00:00:00 2001 From: mbrandy Date: Tue, 1 Sep 2015 09:18:09 -0700 Subject: [PATCH] PPC: Crankshaft is now able to compile top level code even if there is a ScriptContext. Port 29ebcc32052d486cbc1933ac4738aa5cb68aa851 Original commit message: This CL introduces HPrologue instruction which does the context allocation work and supports deoptimization. R=ishell@chromium.org, jyan@ca.ibm.com, dstence@us.ibm.com, joransiu@ca.ibm.com BUG= Review URL: https://codereview.chromium.org/1324023002 Cr-Commit-Position: refs/heads/master@{#30516} --- src/full-codegen/ppc/full-codegen-ppc.cc | 17 ++++++++++++----- src/ppc/lithium-codegen-ppc.cc | 32 +++++++++++++++++++------------- src/ppc/lithium-ppc.cc | 7 ++++++- src/ppc/lithium-ppc.h | 7 +++++++ 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/full-codegen/ppc/full-codegen-ppc.cc b/src/full-codegen/ppc/full-codegen-ppc.cc index abd41c4..4af5bc4 100644 --- a/src/full-codegen/ppc/full-codegen-ppc.cc +++ b/src/full-codegen/ppc/full-codegen-ppc.cc @@ -186,7 +186,7 @@ void FullCodeGenerator::Generate() { } } - bool function_in_register = true; + bool function_in_register_r4 = true; // Possibly allocate a local context. if (info->scope()->num_heap_slots() > 0) { @@ -207,7 +207,7 @@ void FullCodeGenerator::Generate() { __ push(r4); __ CallRuntime(Runtime::kNewFunctionContext, 1); } - function_in_register = false; + function_in_register_r4 = false; // Context is returned in r3. It replaces the context passed to us. // It's saved in the stack and kept live in cp. __ mr(cp, r3); @@ -240,14 +240,19 @@ void FullCodeGenerator::Generate() { } } + PrepareForBailoutForId(BailoutId::Prologue(), NO_REGISTERS); + // Function register is trashed in case we bailout here. But since that + // could happen only when we allocate a context the value of + // |function_in_register_r4| is correct. + // Possibly set up a local binding to the this function which is used in // derived constructors with super calls. Variable* this_function_var = scope()->this_function_var(); if (this_function_var != nullptr) { Comment cmnt(masm_, "[ This function"); - if (!function_in_register) { + if (!function_in_register_r4) { __ LoadP(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); - // The write barrier clobbers register again, keep is marked as such. + // The write barrier clobbers register again, keep it marked as such. } SetVar(this_function_var, r4, r3, r5); } @@ -271,6 +276,7 @@ void FullCodeGenerator::Generate() { __ LoadP(r4, MemOperand(r5, StandardFrameConstants::kMarkerOffset)); __ CmpSmiLiteral(r4, Smi::FromInt(StackFrame::CONSTRUCT), r0); Label non_construct_frame, done; + function_in_register_r4 = false; __ bne(&non_construct_frame); __ LoadP(r3, MemOperand( @@ -298,6 +304,7 @@ void FullCodeGenerator::Generate() { __ LoadSmiLiteral(r4, Smi::FromInt(rest_index)); __ LoadSmiLiteral(r3, Smi::FromInt(language_mode())); __ Push(r6, r5, r4, r3); + function_in_register_r4 = false; RestParamAccessStub stub(isolate()); __ CallStub(&stub); @@ -309,7 +316,7 @@ void FullCodeGenerator::Generate() { if (arguments != NULL) { // Function uses arguments object. Comment cmnt(masm_, "[ Allocate arguments object"); - if (!function_in_register) { + if (!function_in_register_r4) { // Load this again, if it's used by the local context below. __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); } else { diff --git a/src/ppc/lithium-codegen-ppc.cc b/src/ppc/lithium-codegen-ppc.cc index c870c20..9abe91e 100644 --- a/src/ppc/lithium-codegen-ppc.cc +++ b/src/ppc/lithium-codegen-ppc.cc @@ -176,16 +176,27 @@ bool LCodeGen::GeneratePrologue() { if (info()->saves_caller_doubles()) { SaveCallerDoubles(); } + return !is_aborted(); +} + + +void LCodeGen::DoPrologue(LPrologue* instr) { + Comment(";;; Prologue begin"); // Possibly allocate a local context. - int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; - if (heap_slots > 0) { + if (info()->scope()->num_heap_slots() > 0) { Comment(";;; Allocate local context"); bool need_write_barrier = true; // Argument to NewContext is the function, which is in r4. - DCHECK(!info()->scope()->is_script_scope()); - if (heap_slots <= FastNewContextStub::kMaximumSlots) { - FastNewContextStub stub(isolate(), heap_slots); + int slots = info()->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; + Safepoint::DeoptMode deopt_mode = Safepoint::kNoLazyDeopt; + if (info()->scope()->is_script_scope()) { + __ push(r4); + __ Push(info()->scope()->GetScopeInfo(info()->isolate())); + __ CallRuntime(Runtime::kNewScriptContext, 2); + deopt_mode = Safepoint::kLazyDeopt; + } else if (slots <= FastNewContextStub::kMaximumSlots) { + FastNewContextStub stub(isolate(), slots); __ CallStub(&stub); // Result of FastNewContextStub is always in new space. need_write_barrier = false; @@ -193,7 +204,8 @@ bool LCodeGen::GeneratePrologue() { __ push(r4); __ CallRuntime(Runtime::kNewFunctionContext, 1); } - RecordSafepoint(Safepoint::kNoLazyDeopt); + RecordSafepoint(deopt_mode); + // Context is returned in both r3 and cp. It replaces the context // passed to us. It's saved in the stack and kept live in cp. __ mr(cp, r3); @@ -226,13 +238,7 @@ bool LCodeGen::GeneratePrologue() { Comment(";;; End allocate local context"); } - // Trace the call. - if (FLAG_trace && info()->IsOptimizing()) { - // We have not executed any compiled code yet, so cp still holds the - // incoming context. - __ CallRuntime(Runtime::kTraceEnter, 0); - } - return !is_aborted(); + Comment(";;; Prologue end"); } diff --git a/src/ppc/lithium-ppc.cc b/src/ppc/lithium-ppc.cc index fb58784..e727090 100644 --- a/src/ppc/lithium-ppc.cc +++ b/src/ppc/lithium-ppc.cc @@ -928,7 +928,7 @@ void LChunkBuilder::AddInstruction(LInstruction* instr, } chunk_->AddInstruction(instr, current_block_); - if (instr->IsCall()) { + if (instr->IsCall() || instr->IsPrologue()) { HValue* hydrogen_value_for_lazy_bailout = hydrogen_val; if (hydrogen_val->HasObservableSideEffects()) { HSimulate* sim = HSimulate::cast(hydrogen_val->next()); @@ -942,6 +942,11 @@ void LChunkBuilder::AddInstruction(LInstruction* instr, } +LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) { + return new (zone()) LPrologue(); +} + + LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { return new (zone()) LGoto(instr->FirstSuccessor()); } diff --git a/src/ppc/lithium-ppc.h b/src/ppc/lithium-ppc.h index a34e19c..0bc99ce 100644 --- a/src/ppc/lithium-ppc.h +++ b/src/ppc/lithium-ppc.h @@ -131,6 +131,7 @@ class LCodeGen; V(OsrEntry) \ V(Parameter) \ V(Power) \ + V(Prologue) \ V(PushArgument) \ V(RegExpLiteral) \ V(Return) \ @@ -384,6 +385,12 @@ class LGoto final : public LTemplateInstruction<0, 0, 0> { }; +class LPrologue final : public LTemplateInstruction<0, 0, 0> { + public: + DECLARE_CONCRETE_INSTRUCTION(Prologue, "prologue") +}; + + class LLazyBailout final : public LTemplateInstruction<0, 0, 0> { public: LLazyBailout() : gap_instructions_size_(0) {} -- 2.7.4