[generators] Remove full-codegen implementation of yield*.

The recently introduced desugaring of yield* renders this code dead.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#33762}
This commit is contained in:
neis 2016-02-05 00:53:39 -08:00 committed by Commit bot
parent 3c71bd1846
commit 9096aef4c1
11 changed files with 18 additions and 904 deletions

View File

@ -2596,26 +2596,6 @@ class Yield final : public Expression {
void set_generator_object(Expression* e) { generator_object_ = e; }
void set_expression(Expression* e) { expression_ = e; }
// Type feedback information.
bool HasFeedbackSlots() const { return yield_kind() == kDelegating; }
void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache) override {
if (HasFeedbackSlots()) {
yield_first_feedback_slot_ = spec->AddKeyedLoadICSlot();
keyed_load_feedback_slot_ = spec->AddLoadICSlot();
done_feedback_slot_ = spec->AddLoadICSlot();
}
}
FeedbackVectorSlot KeyedLoadFeedbackSlot() {
DCHECK(!HasFeedbackSlots() || !yield_first_feedback_slot_.IsInvalid());
return yield_first_feedback_slot_;
}
FeedbackVectorSlot DoneFeedbackSlot() { return keyed_load_feedback_slot_; }
FeedbackVectorSlot ValueFeedbackSlot() { return done_feedback_slot_; }
protected:
Yield(Zone* zone, Expression* generator_object, Expression* expression,
Kind yield_kind, int pos)
@ -2628,9 +2608,6 @@ class Yield final : public Expression {
Expression* generator_object_;
Expression* expression_;
Kind yield_kind_;
FeedbackVectorSlot yield_first_feedback_slot_;
FeedbackVectorSlot keyed_load_feedback_slot_;
FeedbackVectorSlot done_feedback_slot_;
};

View File

@ -1979,112 +1979,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
break;
}
case Yield::kDelegating: {
VisitForStackValue(expr->generator_object());
// Initial stack layout is as follows:
// [sp + 1 * kPointerSize] iter
// [sp + 0 * kPointerSize] g
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
Register load_receiver = LoadDescriptor::ReceiverRegister();
Register load_name = LoadDescriptor::NameRegister();
// Initial send value is undefined.
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
__ b(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
__ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
__ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
__ Push(load_name, r3, r0); // "throw", iter, except
__ jmp(&l_call);
// try { received = %yield result }
// Shuffle the received result above a try handler and yield it without
// re-boxing.
__ bind(&l_try);
__ pop(r0); // result
int handler_index = NewHandlerTableEntry();
EnterTryBlock(handler_index, &l_catch);
const int try_block_size = TryCatch::kElementCount * kPointerSize;
__ push(r0); // result
__ jmp(&l_suspend);
__ bind(&l_continuation);
__ RecordGeneratorContinuation();
__ jmp(&l_resume);
__ bind(&l_suspend);
const int generator_object_depth = kPointerSize + try_block_size;
__ ldr(r0, MemOperand(sp, generator_object_depth));
__ push(r0); // g
__ Push(Smi::FromInt(handler_index)); // handler-index
DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ mov(r1, Operand(Smi::FromInt(l_continuation.pos())));
__ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset));
__ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset));
__ mov(r1, cp);
__ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2,
kLRHasBeenSaved, kDontSaveFPRegs);
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ pop(r0); // result
EmitReturnSequence();
__ bind(&l_resume); // received in r0
ExitTryBlock(handler_index);
// receiver = iter; f = 'next'; arg = received;
__ bind(&l_next);
__ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
__ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
__ Push(load_name, r3, r0); // "next", iter, received
// result = receiver[f](arg);
__ bind(&l_call);
__ ldr(load_receiver, MemOperand(sp, kPointerSize));
__ ldr(load_name, MemOperand(sp, 2 * kPointerSize));
__ mov(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
CallIC(ic, TypeFeedbackId::None());
__ mov(r1, r0);
__ str(r1, MemOperand(sp, 2 * kPointerSize));
SetCallPosition(expr);
__ mov(r0, Operand(1));
__ Call(
isolate()->builtins()->Call(ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The function is still on the stack; drop it.
// if (!result.done) goto l_try;
__ bind(&l_loop);
__ Move(load_receiver, r0);
__ push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
__ mov(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // r0=result.done
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
__ b(ne, &l_try);
// result.value
__ pop(load_receiver); // result
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
__ mov(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // r0=result.value
context()->DropAndPlug(2, r0); // drop iter and g
break;
}
case Yield::kDelegating:
UNREACHABLE();
}
}

View File

@ -4385,116 +4385,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
break;
}
case Yield::kDelegating: {
VisitForStackValue(expr->generator_object());
// Initial stack layout is as follows:
// [sp + 1 * kPointerSize] iter
// [sp + 0 * kPointerSize] g
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
Register load_receiver = LoadDescriptor::ReceiverRegister();
Register load_name = LoadDescriptor::NameRegister();
// Initial send value is undefined.
__ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
__ B(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ Bind(&l_catch);
__ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
__ Peek(x3, 1 * kPointerSize); // iter
__ Push(load_name, x3, x0); // "throw", iter, except
__ B(&l_call);
// try { received = %yield result }
// Shuffle the received result above a try handler and yield it without
// re-boxing.
__ Bind(&l_try);
__ Pop(x0); // result
int handler_index = NewHandlerTableEntry();
EnterTryBlock(handler_index, &l_catch);
const int try_block_size = TryCatch::kElementCount * kPointerSize;
__ Push(x0); // result
__ B(&l_suspend);
// TODO(jbramley): This label is bound here because the following code
// looks at its pos(). Is it possible to do something more efficient here,
// perhaps using Adr?
__ Bind(&l_continuation);
__ RecordGeneratorContinuation();
__ B(&l_resume);
__ Bind(&l_suspend);
const int generator_object_depth = kPointerSize + try_block_size;
__ Peek(x0, generator_object_depth);
__ Push(x0); // g
__ Push(Smi::FromInt(handler_index)); // handler-index
DCHECK((l_continuation.pos() > 0) && Smi::IsValid(l_continuation.pos()));
__ Mov(x1, Smi::FromInt(l_continuation.pos()));
__ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset));
__ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset));
__ Mov(x1, cp);
__ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2,
kLRHasBeenSaved, kDontSaveFPRegs);
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ Pop(x0); // result
EmitReturnSequence();
__ Bind(&l_resume); // received in x0
ExitTryBlock(handler_index);
// receiver = iter; f = 'next'; arg = received;
__ Bind(&l_next);
__ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
__ Peek(x3, 1 * kPointerSize); // iter
__ Push(load_name, x3, x0); // "next", iter, received
// result = receiver[f](arg);
__ Bind(&l_call);
__ Peek(load_receiver, 1 * kPointerSize);
__ Peek(load_name, 2 * kPointerSize);
__ Mov(LoadDescriptor::SlotRegister(),
SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
CallIC(ic, TypeFeedbackId::None());
__ Mov(x1, x0);
__ Poke(x1, 2 * kPointerSize);
SetCallPosition(expr);
__ Mov(x0, 1);
__ Call(
isolate()->builtins()->Call(ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The function is still on the stack; drop it.
// if (!result.done) goto l_try;
__ Bind(&l_loop);
__ Move(load_receiver, x0);
__ Push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
__ Mov(LoadDescriptor::SlotRegister(),
SmiFromSlot(expr->DoneFeedbackSlot()));
CallLoadIC(NOT_INSIDE_TYPEOF); // x0=result.done
// The ToBooleanStub argument (result.done) is in x0.
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
__ B(ne, &l_try);
// result.value
__ Pop(load_receiver); // result
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
__ Mov(LoadDescriptor::SlotRegister(),
SmiFromSlot(expr->ValueFeedbackSlot()));
CallLoadIC(NOT_INSIDE_TYPEOF); // x0=result.value
context()->DropAndPlug(2, x0); // drop iter and g
break;
}
case Yield::kDelegating:
UNREACHABLE();
}
}

View File

@ -1892,115 +1892,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
break;
}
case Yield::kDelegating: {
VisitForStackValue(expr->generator_object());
// Initial stack layout is as follows:
// [sp + 1 * kPointerSize] iter
// [sp + 0 * kPointerSize] g
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
Register load_receiver = LoadDescriptor::ReceiverRegister();
Register load_name = LoadDescriptor::NameRegister();
// Initial send value is undefined.
__ mov(eax, isolate()->factory()->undefined_value());
__ jmp(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
__ mov(load_name, isolate()->factory()->throw_string()); // "throw"
__ push(load_name); // "throw"
__ push(Operand(esp, 2 * kPointerSize)); // iter
__ push(eax); // exception
__ jmp(&l_call);
// try { received = %yield result }
// Shuffle the received result above a try handler and yield it without
// re-boxing.
__ bind(&l_try);
__ pop(eax); // result
int handler_index = NewHandlerTableEntry();
EnterTryBlock(handler_index, &l_catch);
const int try_block_size = TryCatch::kElementCount * kPointerSize;
__ push(eax); // result
__ jmp(&l_suspend);
__ bind(&l_continuation);
__ RecordGeneratorContinuation();
__ jmp(&l_resume);
__ bind(&l_suspend);
const int generator_object_depth = kPointerSize + try_block_size;
__ mov(eax, Operand(esp, generator_object_depth));
__ push(eax); // g
__ push(Immediate(Smi::FromInt(handler_index))); // handler-index
DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
Immediate(Smi::FromInt(l_continuation.pos())));
__ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
__ mov(ecx, esi);
__ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
kDontSaveFPRegs);
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
__ mov(context_register(),
Operand(ebp, StandardFrameConstants::kContextOffset));
__ pop(eax); // result
EmitReturnSequence();
__ bind(&l_resume); // received in eax
ExitTryBlock(handler_index);
// receiver = iter; f = iter.next; arg = received;
__ bind(&l_next);
__ mov(load_name, isolate()->factory()->next_string());
__ push(load_name); // "next"
__ push(Operand(esp, 2 * kPointerSize)); // iter
__ push(eax); // received
// result = receiver[f](arg);
__ bind(&l_call);
__ mov(load_receiver, Operand(esp, kPointerSize));
__ mov(LoadDescriptor::SlotRegister(),
Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
CallIC(ic, TypeFeedbackId::None());
__ mov(edi, eax);
__ mov(Operand(esp, 2 * kPointerSize), edi);
SetCallPosition(expr);
__ Set(eax, 1);
__ Call(
isolate()->builtins()->Call(ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The function is still on the stack; drop it.
// if (!result.done) goto l_try;
__ bind(&l_loop);
__ push(eax); // save result
__ Move(load_receiver, eax); // result
__ mov(load_name,
isolate()->factory()->done_string()); // "done"
__ mov(LoadDescriptor::SlotRegister(),
Immediate(SmiFromSlot(expr->DoneFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // result.done in eax
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
__ j(not_equal, &l_try);
// result.value
__ pop(load_receiver); // result
__ mov(load_name,
isolate()->factory()->value_string()); // "value"
__ mov(LoadDescriptor::SlotRegister(),
Immediate(SmiFromSlot(expr->ValueFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // result.value in eax
context()->DropAndPlug(2, eax); // drop iter and g
break;
}
case Yield::kDelegating:
UNREACHABLE();
}
}

View File

@ -1976,116 +1976,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
break;
}
case Yield::kDelegating: {
VisitForStackValue(expr->generator_object());
// Initial stack layout is as follows:
// [sp + 1 * kPointerSize] iter
// [sp + 0 * kPointerSize] g
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call;
Register load_receiver = LoadDescriptor::ReceiverRegister();
Register load_name = LoadDescriptor::NameRegister();
// Initial send value is undefined.
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
__ Branch(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
__ mov(a0, v0);
__ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
__ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter
__ Push(load_name, a3, a0); // "throw", iter, except
__ jmp(&l_call);
// try { received = %yield result }
// Shuffle the received result above a try handler and yield it without
// re-boxing.
__ bind(&l_try);
__ pop(a0); // result
int handler_index = NewHandlerTableEntry();
EnterTryBlock(handler_index, &l_catch);
const int try_block_size = TryCatch::kElementCount * kPointerSize;
__ push(a0); // result
__ jmp(&l_suspend);
__ bind(&l_continuation);
__ RecordGeneratorContinuation();
__ mov(a0, v0);
__ jmp(&l_resume);
__ bind(&l_suspend);
const int generator_object_depth = kPointerSize + try_block_size;
__ lw(a0, MemOperand(sp, generator_object_depth));
__ push(a0); // g
__ Push(Smi::FromInt(handler_index)); // handler-index
DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ li(a1, Operand(Smi::FromInt(l_continuation.pos())));
__ sw(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset));
__ sw(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset));
__ mov(a1, cp);
__ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2,
kRAHasBeenSaved, kDontSaveFPRegs);
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ pop(v0); // result
EmitReturnSequence();
__ mov(a0, v0);
__ bind(&l_resume); // received in a0
ExitTryBlock(handler_index);
// receiver = iter; f = 'next'; arg = received;
__ bind(&l_next);
__ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
__ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter
__ Push(load_name, a3, a0); // "next", iter, received
// result = receiver[f](arg);
__ bind(&l_call);
__ lw(load_receiver, MemOperand(sp, kPointerSize));
__ lw(load_name, MemOperand(sp, 2 * kPointerSize));
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
CallIC(ic, TypeFeedbackId::None());
__ mov(a0, v0);
__ mov(a1, a0);
__ sw(a1, MemOperand(sp, 2 * kPointerSize));
SetCallPosition(expr);
__ li(a0, Operand(1));
__ Call(
isolate()->builtins()->Call(ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The function is still on the stack; drop it.
// if (!result.done) goto l_try;
__ Move(load_receiver, v0);
__ push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // v0=result.done
__ mov(a0, v0);
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(&l_try, ne, result_register(), Operand(at));
// result.value
__ pop(load_receiver); // result
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // v0=result.value
context()->DropAndPlug(2, v0); // drop iter and g
break;
}
case Yield::kDelegating:
UNREACHABLE();
}
}

View File

@ -1977,115 +1977,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
break;
}
case Yield::kDelegating: {
VisitForStackValue(expr->generator_object());
// Initial stack layout is as follows:
// [sp + 1 * kPointerSize] iter
// [sp + 0 * kPointerSize] g
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call;
Register load_receiver = LoadDescriptor::ReceiverRegister();
Register load_name = LoadDescriptor::NameRegister();
// Initial send value is undefined.
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
__ Branch(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
__ mov(a0, v0);
__ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw"
__ ld(a3, MemOperand(sp, 1 * kPointerSize)); // iter
__ Push(a2, a3, a0); // "throw", iter, except
__ jmp(&l_call);
// try { received = %yield result }
// Shuffle the received result above a try handler and yield it without
// re-boxing.
__ bind(&l_try);
__ pop(a0); // result
int handler_index = NewHandlerTableEntry();
EnterTryBlock(handler_index, &l_catch);
const int try_block_size = TryCatch::kElementCount * kPointerSize;
__ push(a0); // result
__ jmp(&l_suspend);
__ bind(&l_continuation);
__ RecordGeneratorContinuation();
__ mov(a0, v0);
__ jmp(&l_resume);
__ bind(&l_suspend);
const int generator_object_depth = kPointerSize + try_block_size;
__ ld(a0, MemOperand(sp, generator_object_depth));
__ push(a0); // g
__ Push(Smi::FromInt(handler_index)); // handler-index
DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ li(a1, Operand(Smi::FromInt(l_continuation.pos())));
__ sd(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset));
__ sd(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset));
__ mov(a1, cp);
__ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2,
kRAHasBeenSaved, kDontSaveFPRegs);
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
__ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ pop(v0); // result
EmitReturnSequence();
__ mov(a0, v0);
__ bind(&l_resume); // received in a0
ExitTryBlock(handler_index);
// receiver = iter; f = 'next'; arg = received;
__ bind(&l_next);
__ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
__ ld(a3, MemOperand(sp, 1 * kPointerSize)); // iter
__ Push(load_name, a3, a0); // "next", iter, received
// result = receiver[f](arg);
__ bind(&l_call);
__ ld(load_receiver, MemOperand(sp, kPointerSize));
__ ld(load_name, MemOperand(sp, 2 * kPointerSize));
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
CallIC(ic, TypeFeedbackId::None());
__ mov(a0, v0);
__ mov(a1, a0);
__ sd(a1, MemOperand(sp, 2 * kPointerSize));
SetCallPosition(expr);
__ li(a0, Operand(1));
__ Call(
isolate()->builtins()->Call(ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
__ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The function is still on the stack; drop it.
// if (!result.done) goto l_try;
__ Move(load_receiver, v0);
__ push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // v0=result.done
__ mov(a0, v0);
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(&l_try, ne, result_register(), Operand(at));
// result.value
__ pop(load_receiver); // result
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // v0=result.value
context()->DropAndPlug(2, v0); // drop iter and g
break;
}
case Yield::kDelegating:
UNREACHABLE();
}
}

View File

@ -1938,112 +1938,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
break;
}
case Yield::kDelegating: {
VisitForStackValue(expr->generator_object());
// Initial stack layout is as follows:
// [sp + 1 * kPointerSize] iter
// [sp + 0 * kPointerSize] g
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call;
Register load_receiver = LoadDescriptor::ReceiverRegister();
Register load_name = LoadDescriptor::NameRegister();
// Initial send value is undefined.
__ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
__ b(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
__ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
__ LoadP(r6, MemOperand(sp, 1 * kPointerSize)); // iter
__ Push(load_name, r6, r3); // "throw", iter, except
__ b(&l_call);
// try { received = %yield result }
// Shuffle the received result above a try handler and yield it without
// re-boxing.
__ bind(&l_try);
__ pop(r3); // result
int handler_index = NewHandlerTableEntry();
EnterTryBlock(handler_index, &l_catch);
const int try_block_size = TryCatch::kElementCount * kPointerSize;
__ push(r3); // result
__ b(&l_suspend);
__ bind(&l_continuation);
__ RecordGeneratorContinuation();
__ b(&l_resume);
__ bind(&l_suspend);
const int generator_object_depth = kPointerSize + try_block_size;
__ LoadP(r3, MemOperand(sp, generator_object_depth));
__ push(r3); // g
__ Push(Smi::FromInt(handler_index)); // handler-index
DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ LoadSmiLiteral(r4, Smi::FromInt(l_continuation.pos()));
__ StoreP(r4, FieldMemOperand(r3, JSGeneratorObject::kContinuationOffset),
r0);
__ StoreP(cp, FieldMemOperand(r3, JSGeneratorObject::kContextOffset), r0);
__ mr(r4, cp);
__ RecordWriteField(r3, JSGeneratorObject::kContextOffset, r4, r5,
kLRHasBeenSaved, kDontSaveFPRegs);
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ pop(r3); // result
EmitReturnSequence();
__ bind(&l_resume); // received in r3
ExitTryBlock(handler_index);
// receiver = iter; f = 'next'; arg = received;
__ bind(&l_next);
__ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
__ LoadP(r6, MemOperand(sp, 1 * kPointerSize)); // iter
__ Push(load_name, r6, r3); // "next", iter, received
// result = receiver[f](arg);
__ bind(&l_call);
__ LoadP(load_receiver, MemOperand(sp, kPointerSize));
__ LoadP(load_name, MemOperand(sp, 2 * kPointerSize));
__ mov(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
CallIC(ic, TypeFeedbackId::None());
__ mr(r4, r3);
__ StoreP(r4, MemOperand(sp, 2 * kPointerSize));
SetCallPosition(expr);
__ li(r3, Operand(1));
__ Call(
isolate()->builtins()->Call(ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The function is still on the stack; drop it.
// if (!result.done) goto l_try;
__ Move(load_receiver, r3);
__ push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
__ mov(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // r0=result.done
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
__ bne(&l_try);
// result.value
__ pop(load_receiver); // result
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
__ mov(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // r3=result.value
context()->DropAndPlug(2, r3); // drop iter and g
break;
}
case Yield::kDelegating:
UNREACHABLE();
}
}

View File

@ -1915,114 +1915,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
break;
}
case Yield::kDelegating: {
VisitForStackValue(expr->generator_object());
// Initial stack layout is as follows:
// [sp + 1 * kPointerSize] iter
// [sp + 0 * kPointerSize] g
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
Register load_receiver = LoadDescriptor::ReceiverRegister();
Register load_name = LoadDescriptor::NameRegister();
// Initial send value is undefined.
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
__ jmp(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
__ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
__ Push(load_name);
__ Push(Operand(rsp, 2 * kPointerSize)); // iter
__ Push(rax); // exception
__ jmp(&l_call);
// try { received = %yield result }
// Shuffle the received result above a try handler and yield it without
// re-boxing.
__ bind(&l_try);
__ Pop(rax); // result
int handler_index = NewHandlerTableEntry();
EnterTryBlock(handler_index, &l_catch);
const int try_block_size = TryCatch::kElementCount * kPointerSize;
__ Push(rax); // result
__ jmp(&l_suspend);
__ bind(&l_continuation);
__ RecordGeneratorContinuation();
__ jmp(&l_resume);
__ bind(&l_suspend);
const int generator_object_depth = kPointerSize + try_block_size;
__ movp(rax, Operand(rsp, generator_object_depth));
__ Push(rax); // g
__ Push(Smi::FromInt(handler_index)); // handler-index
DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
Smi::FromInt(l_continuation.pos()));
__ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
__ movp(rcx, rsi);
__ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
kDontSaveFPRegs);
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
__ movp(context_register(),
Operand(rbp, StandardFrameConstants::kContextOffset));
__ Pop(rax); // result
EmitReturnSequence();
__ bind(&l_resume); // received in rax
ExitTryBlock(handler_index);
// receiver = iter; f = 'next'; arg = received;
__ bind(&l_next);
__ LoadRoot(load_name, Heap::knext_stringRootIndex);
__ Push(load_name); // "next"
__ Push(Operand(rsp, 2 * kPointerSize)); // iter
__ Push(rax); // received
// result = receiver[f](arg);
__ bind(&l_call);
__ movp(load_receiver, Operand(rsp, kPointerSize));
__ Move(LoadDescriptor::SlotRegister(),
SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
CallIC(ic, TypeFeedbackId::None());
__ movp(rdi, rax);
__ movp(Operand(rsp, 2 * kPointerSize), rdi);
SetCallPosition(expr);
__ Set(rax, 1);
__ Call(
isolate()->builtins()->Call(ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
__ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The function is still on the stack; drop it.
// if (!result.done) goto l_try;
__ bind(&l_loop);
__ Move(load_receiver, rax);
__ Push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
__ Move(LoadDescriptor::SlotRegister(),
SmiFromSlot(expr->DoneFeedbackSlot()));
CallLoadIC(NOT_INSIDE_TYPEOF); // rax=result.done
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
__ j(not_equal, &l_try);
// result.value
__ Pop(load_receiver); // result
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
__ Move(LoadDescriptor::SlotRegister(),
SmiFromSlot(expr->ValueFeedbackSlot()));
CallLoadIC(NOT_INSIDE_TYPEOF); // result.value in rax
context()->DropAndPlug(2, rax); // drop iter and g
break;
}
case Yield::kDelegating:
UNREACHABLE();
}
}

View File

@ -1884,115 +1884,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
break;
}
case Yield::kDelegating: {
VisitForStackValue(expr->generator_object());
// Initial stack layout is as follows:
// [sp + 1 * kPointerSize] iter
// [sp + 0 * kPointerSize] g
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
Register load_receiver = LoadDescriptor::ReceiverRegister();
Register load_name = LoadDescriptor::NameRegister();
// Initial send value is undefined.
__ mov(eax, isolate()->factory()->undefined_value());
__ jmp(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
__ mov(load_name, isolate()->factory()->throw_string()); // "throw"
__ push(load_name); // "throw"
__ push(Operand(esp, 2 * kPointerSize)); // iter
__ push(eax); // exception
__ jmp(&l_call);
// try { received = %yield result }
// Shuffle the received result above a try handler and yield it without
// re-boxing.
__ bind(&l_try);
__ pop(eax); // result
int handler_index = NewHandlerTableEntry();
EnterTryBlock(handler_index, &l_catch);
const int try_block_size = TryCatch::kElementCount * kPointerSize;
__ push(eax); // result
__ jmp(&l_suspend);
__ bind(&l_continuation);
__ RecordGeneratorContinuation();
__ jmp(&l_resume);
__ bind(&l_suspend);
const int generator_object_depth = kPointerSize + try_block_size;
__ mov(eax, Operand(esp, generator_object_depth));
__ push(eax); // g
__ push(Immediate(Smi::FromInt(handler_index))); // handler-index
DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
Immediate(Smi::FromInt(l_continuation.pos())));
__ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
__ mov(ecx, esi);
__ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
kDontSaveFPRegs);
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
__ mov(context_register(),
Operand(ebp, StandardFrameConstants::kContextOffset));
__ pop(eax); // result
EmitReturnSequence();
__ bind(&l_resume); // received in eax
ExitTryBlock(handler_index);
// receiver = iter; f = iter.next; arg = received;
__ bind(&l_next);
__ mov(load_name, isolate()->factory()->next_string());
__ push(load_name); // "next"
__ push(Operand(esp, 2 * kPointerSize)); // iter
__ push(eax); // received
// result = receiver[f](arg);
__ bind(&l_call);
__ mov(load_receiver, Operand(esp, kPointerSize));
__ mov(LoadDescriptor::SlotRegister(),
Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
CallIC(ic, TypeFeedbackId::None());
__ mov(edi, eax);
__ mov(Operand(esp, 2 * kPointerSize), edi);
SetCallPosition(expr);
__ Set(eax, 1);
__ Call(
isolate()->builtins()->Call(ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The function is still on the stack; drop it.
// if (!result.done) goto l_try;
__ bind(&l_loop);
__ push(eax); // save result
__ Move(load_receiver, eax); // result
__ mov(load_name,
isolate()->factory()->done_string()); // "done"
__ mov(LoadDescriptor::SlotRegister(),
Immediate(SmiFromSlot(expr->DoneFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // result.done in eax
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
__ j(not_equal, &l_try);
// result.value
__ pop(load_receiver); // result
__ mov(load_name,
isolate()->factory()->value_string()); // "value"
__ mov(LoadDescriptor::SlotRegister(),
Immediate(SmiFromSlot(expr->ValueFeedbackSlot())));
CallLoadIC(NOT_INSIDE_TYPEOF); // result.value in eax
context()->DropAndPlug(2, eax); // drop iter and g
break;
}
case Yield::kDelegating:
UNREACHABLE();
}
}

View File

@ -36,7 +36,7 @@ RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) {
HandleScope handle_scope(isolate);
DCHECK(args.length() == 1 || args.length() == 2);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0);
JavaScriptFrameIterator stack_iterator(isolate);
@ -55,18 +55,6 @@ RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) {
DCHECK_GE(operands_count, 1 + args.length());
operands_count -= 1 + args.length();
// Second argument indicates that we need to patch the handler table because
// a delegating yield introduced a try-catch statement at expression level,
// hence the operand count was off when we statically computed it.
// TODO(mstarzinger): This special case disappears with do-expressions.
if (args.length() == 2) {
CONVERT_SMI_ARG_CHECKED(handler_index, 1);
Handle<Code> code(frame->unchecked_code());
Handle<HandlerTable> table(HandlerTable::cast(code->handler_table()));
int handler_depth = operands_count - TryBlockConstant::kElementCount;
table->SetRangeDepth(handler_index, handler_depth);
}
if (operands_count == 0) {
// Although it's semantically harmless to call this function with an
// operands_count of zero, it is also unnecessary.

View File

@ -251,7 +251,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_GENERATOR(F) \
F(CreateJSGeneratorObject, 0, 1) \
F(SuspendJSGeneratorObject, -1, 1) \
F(SuspendJSGeneratorObject, 1, 1) \
F(ResumeJSGeneratorObject, 3, 1) \
F(GeneratorClose, 1, 1) \
F(GeneratorGetFunction, 1, 1) \