Commit 9640015e authored by zhengxing.li's avatar zhengxing.li Committed by Commit bot

X87: [crankshaft] Fixing ES6 tail call elimination.

  port acbb968d (r34920)

  original commit message:
  In case when F inlined normal call to G which tail calls H we should not write translation for G for the tail call site.
  Otherwise we will see G in a stack trace inside H.

  This CL also enables all existing tests related to ES6 tail call elimination and adds more combinations.

BUG=

Review URL: https://codereview.chromium.org/1819273003

Cr-Commit-Position: refs/heads/master@{#34972}
parent 236d7005
......@@ -595,12 +595,7 @@ LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr,
LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
HEnvironment* hydrogen_env = current_block_->last_environment();
int argument_index_accumulator = 0;
ZoneList<HValue*> objects_to_materialize(0, zone());
instr->set_environment(CreateEnvironment(hydrogen_env,
&argument_index_accumulator,
&objects_to_materialize));
return instr;
return LChunkBuilderBase::AssignEnvironment(instr, hydrogen_env);
}
......@@ -925,15 +920,39 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
chunk_->AddInstruction(instr, current_block_);
if (instr->IsCall()) {
HEnvironment* hydrogen_env = current_block_->last_environment();
HValue* hydrogen_value_for_lazy_bailout = hydrogen_val;
if (hydrogen_val->HasObservableSideEffects()) {
HSimulate* sim = HSimulate::cast(hydrogen_val->next());
sim->ReplayEnvironment(current_block_->last_environment());
hydrogen_value_for_lazy_bailout = sim;
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
// Push return value on top of outer environment.
hydrogen_env = hydrogen_env->Copy();
hydrogen_env->Push(hydrogen_val);
}
} else {
if (hydrogen_val->HasObservableSideEffects()) {
HSimulate* sim = HSimulate::cast(hydrogen_val->next());
sim->ReplayEnvironment(hydrogen_env);
hydrogen_value_for_lazy_bailout = sim;
}
}
if (hydrogen_env != nullptr) {
// The |hydrogen_env| can be null at this point only if we are generating
// a syntactic tail call from the outermost function but in this case
// it would be a real tail call which will pop function's frame and
// therefore this lazy bailout can be skipped.
LInstruction* bailout = LChunkBuilderBase::AssignEnvironment(
new (zone()) LLazyBailout(), hydrogen_env);
bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
chunk_->AddInstruction(bailout, current_block_);
}
LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
chunk_->AddInstruction(bailout, current_block_);
}
}
......@@ -1116,6 +1135,9 @@ LInstruction* LChunkBuilder::DoCallWithDescriptor(
LCallWithDescriptor* result = new(zone()) LCallWithDescriptor(
descriptor, ops, zone());
if (instr->syntactic_tail_call_mode() == TailCallMode::kAllow) {
result->MarkAsSyntacticTailCall();
}
return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
}
......@@ -1124,6 +1146,9 @@ LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* context = UseFixed(instr->context(), esi);
LOperand* function = UseFixed(instr->function(), edi);
LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
if (instr->syntactic_tail_call_mode() == TailCallMode::kAllow) {
result->MarkAsSyntacticTailCall();
}
return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
}
......
......@@ -226,6 +226,13 @@ class LInstruction : public ZoneObject {
void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
bool IsCall() const { return IsCallBits::decode(bit_field_); }
void MarkAsSyntacticTailCall() {
bit_field_ = IsSyntacticTailCallBits::update(bit_field_, true);
}
bool IsSyntacticTailCall() const {
return IsSyntacticTailCallBits::decode(bit_field_);
}
// Interface to the register allocator and iterators.
bool ClobbersTemps() const { return IsCall(); }
bool ClobbersRegisters() const { return IsCall(); }
......@@ -264,6 +271,8 @@ class LInstruction : public ZoneObject {
virtual LOperand* TempAt(int i) = 0;
class IsCallBits: public BitField<bool, 0, 1> {};
class IsSyntacticTailCallBits : public BitField<bool, IsCallBits::kNext, 1> {
};
LEnvironment* environment_;
SetOncePointer<LPointerMap> pointer_map_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment