Index: src/crankshaft/lithium.cc |
diff --git a/src/crankshaft/lithium.cc b/src/crankshaft/lithium.cc |
index 3dff459a54a695676091d66cc161d76b48c6b650..d34b04f5da022ccaa582777c14db0fbb18f051cd 100644 |
--- a/src/crankshaft/lithium.cc |
+++ b/src/crankshaft/lithium.cc |
@@ -338,7 +338,6 @@ void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { |
} |
} |
- |
LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { |
return LConstantOperand::Create(constant->id(), zone()); |
} |
@@ -508,6 +507,57 @@ void LChunkBuilderBase::Retry(BailoutReason reason) { |
status_ = ABORTED; |
} |
+void LChunkBuilderBase::CreateLazyBailoutForCall(HBasicBlock* current_block, |
+ LInstruction* instr, |
+ HInstruction* hydrogen_val) { |
+ if (!instr->IsCall()) return; |
+ |
+ HEnvironment* hydrogen_env = current_block->last_environment(); |
+ HValue* hydrogen_value_for_lazy_bailout = hydrogen_val; |
+ DCHECK_NOT_NULL(hydrogen_env); |
+ if (instr->IsSyntacticTailCall()) { |
+ // If it was a syntactic tail call we need to drop the current frame and |
+ // all the frames on top of it that are either an arguments adaptor frame |
+ // or a tail caller frame. |
+ hydrogen_env = hydrogen_env->outer(); |
+ while (hydrogen_env != nullptr && |
+ (hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR || |
+ hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) { |
+ hydrogen_env = hydrogen_env->outer(); |
+ } |
+ if (hydrogen_env != nullptr) { |
+ if (hydrogen_env->frame_type() == JS_FUNCTION) { |
+ // In case an outer frame is a function frame we have to replay |
+ // environment manually because |
+ // 1) it does not contain a result of inlined function yet, |
+ // 2) we can't find the proper simulate that corresponds to the point |
+ // after inlined call to do a ReplayEnvironment() on. |
+ // So we push return value on top of outer environment. |
+ // As for JS_GETTER/JS_SETTER/JS_CONSTRUCT nothing has to be done here, |
+ // the deoptimizer ensures that the result of the callee is correctly |
+ // propagated to result register during deoptimization. |
+ hydrogen_env = hydrogen_env->Copy(); |
+ hydrogen_env->Push(hydrogen_val); |
+ } |
+ } else { |
+ // Although we don't need this lazy bailout for normal execution |
+ // (because when we tail call from the outermost function we should pop |
+ // its frame) we still need it when debugger is on. |
+ hydrogen_env = current_block->last_environment(); |
+ } |
+ } else { |
+ if (hydrogen_val->HasObservableSideEffects()) { |
+ HSimulate* sim = HSimulate::cast(hydrogen_val->next()); |
+ sim->ReplayEnvironment(hydrogen_env); |
+ hydrogen_value_for_lazy_bailout = sim; |
+ } |
+ } |
+ LInstruction* bailout = LChunkBuilderBase::AssignEnvironment( |
+ new (zone()) LLazyBailout(), hydrogen_env); |
+ bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); |
+ chunk_->AddInstruction(bailout, current_block); |
+} |
+ |
LInstruction* LChunkBuilderBase::AssignEnvironment(LInstruction* instr, |
HEnvironment* hydrogen_env) { |
int argument_index_accumulator = 0; |