[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:
parent
3c71bd1846
commit
9096aef4c1
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user