break;
}
- case Yield::DELEGATING: {
- VisitForStackValue(expr->generator_object());
-
- // Initial stack layout is as follows:
- // [sp + 1 * kPointerSize] iter
- // [sp + 0 * kPointerSize] g
-
- Label l_catch, l_try, l_resume, l_send, l_call, l_loop;
- // Initial send value is undefined.
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
- __ b(&l_send);
-
- // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; }
- __ bind(&l_catch);
- handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
- __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
- __ push(r3); // iter
- __ push(r0); // exception
- __ mov(r0, r3); // iter
- __ push(r0); // push LoadIC state
- __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw"
- Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(throw_ic); // iter.throw in r0
- __ add(sp, sp, Operand(kPointerSize)); // drop LoadIC state
- __ jmp(&l_call);
-
- // try { received = yield result.value }
- __ bind(&l_try);
- __ pop(r0); // result.value
- __ PushTryHandler(StackHandler::CATCH, expr->index());
- const int handler_size = StackHandlerConstants::kSize;
- __ push(r0); // result.value
- __ ldr(r3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g
- __ push(r3); // g
- __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
- __ ldr(context_register(),
- MemOperand(fp, StandardFrameConstants::kContextOffset));
- __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
- __ b(ne, &l_resume);
- EmitReturnIteratorResult(false);
- __ bind(&l_resume); // received in r0
- __ PopTryHandler();
-
- // receiver = iter; f = iter.send; arg = received;
- __ bind(&l_send);
- __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
- __ push(r3); // iter
- __ push(r0); // received
- __ mov(r0, r3); // iter
- __ push(r0); // push LoadIC state
- __ LoadRoot(r2, Heap::ksend_stringRootIndex); // "send"
- Handle<Code> send_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(send_ic); // iter.send in r0
- __ add(sp, sp, Operand(kPointerSize)); // drop LoadIC state
-
- // result = f.call(receiver, arg);
- __ bind(&l_call);
- Label l_call_runtime;
- __ JumpIfSmi(r0, &l_call_runtime);
- __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
- __ b(ne, &l_call_runtime);
- __ mov(r1, r0);
- ParameterCount count(1);
- __ InvokeFunction(r1, count, CALL_FUNCTION,
- NullCallWrapper(), CALL_AS_METHOD);
- __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- __ jmp(&l_loop);
- __ bind(&l_call_runtime);
- __ push(r0);
- __ CallRuntime(Runtime::kCall, 3);
-
- // val = result.value; if (!result.done) goto l_try;
- __ bind(&l_loop);
- // result.value
- __ push(r0); // save result
- __ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value"
- Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(value_ic); // result.value in r0
- __ pop(r1); // result
- __ push(r0); // result.value
- __ mov(r0, r1); // result
- __ push(r0); // push LoadIC state
- __ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done"
- Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(done_ic); // result.done in r0
- __ add(sp, sp, Operand(kPointerSize)); // drop LoadIC state
- ToBooleanStub stub(r0);
- __ CallStub(&stub);
- __ cmp(r0, Operand(0));
- __ b(eq, &l_try);
-
- // result.value
- __ pop(r0); // result.value
- context()->DropAndPlug(2, r0); // drop iter and g
- break;
- }
+ case Yield::DELEGATING:
+ UNIMPLEMENTED();
}
}
Kind yield_kind() const { return yield_kind_; }
virtual int position() const { return pos_; }
- // Delegating yield surrounds the "yield" in a "try/catch". This index
- // locates the catch handler in the handler table, and is equivalent to
- // TryCatchStatement::index().
- int index() const {
- ASSERT(yield_kind() == DELEGATING);
- return index_;
- }
- void set_index(int index) {
- ASSERT(yield_kind() == DELEGATING);
- index_ = index;
- }
-
protected:
Yield(Isolate* isolate,
Expression* generator_object,
generator_object_(generator_object),
expression_(expression),
yield_kind_(yield_kind),
- index_(-1),
pos_(pos) { }
private:
Expression* generator_object_;
Expression* expression_;
Kind yield_kind_;
- int index_;
int pos_;
};
V(minus_infinity_string, "-Infinity") \
V(hidden_stack_trace_string, "v8::hidden_stack_trace") \
V(query_colon_string, "(?:)") \
- V(Generator_string, "Generator") \
- V(send_string, "send") \
- V(throw_string, "throw") \
- V(done_string, "done") \
- V(value_string, "value")
+ V(Generator_string, "Generator")
// Forward declarations.
class GCTracer;
break;
}
- case Yield::DELEGATING: {
- VisitForStackValue(expr->generator_object());
-
- // Initial stack layout is as follows:
- // [sp + 1 * kPointerSize] iter
- // [sp + 0 * kPointerSize] g
-
- Label l_catch, l_try, l_resume, l_send, l_call, l_loop;
- // Initial send value is undefined.
- __ mov(eax, isolate()->factory()->undefined_value());
- __ jmp(&l_send);
-
- // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; }
- __ bind(&l_catch);
- handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
- __ mov(edx, Operand(esp, 1 * kPointerSize)); // iter
- __ push(edx); // iter
- __ push(eax); // exception
- __ mov(ecx, isolate()->factory()->throw_string()); // "throw"
- Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(throw_ic); // iter.throw in eax
- __ jmp(&l_call);
-
- // try { received = yield result.value }
- __ bind(&l_try);
- __ pop(eax); // result.value
- __ PushTryHandler(StackHandler::CATCH, expr->index());
- const int handler_size = StackHandlerConstants::kSize;
- __ push(eax); // result.value
- __ push(Operand(esp, (0 + 1) * kPointerSize + handler_size)); // g
- __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
- __ mov(context_register(),
- Operand(ebp, StandardFrameConstants::kContextOffset));
- __ CompareRoot(eax, Heap::kTheHoleValueRootIndex);
- __ j(not_equal, &l_resume);
- EmitReturnIteratorResult(false);
- __ bind(&l_resume); // received in eax
- __ PopTryHandler();
-
- // receiver = iter; f = iter.send; arg = received;
- __ bind(&l_send);
- __ mov(edx, Operand(esp, 1 * kPointerSize)); // iter
- __ push(edx); // iter
- __ push(eax); // received
- __ mov(ecx, isolate()->factory()->send_string()); // "send"
- Handle<Code> send_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(send_ic); // iter.send in eax
-
- // result = f.call(receiver, arg);
- __ bind(&l_call);
- Label l_call_runtime;
- __ JumpIfSmi(eax, &l_call_runtime);
- __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
- __ j(not_equal, &l_call_runtime);
- __ mov(edi, eax);
- ParameterCount count(1);
- __ InvokeFunction(edi, count, CALL_FUNCTION,
- NullCallWrapper(), CALL_AS_METHOD);
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- __ jmp(&l_loop);
- __ bind(&l_call_runtime);
- __ push(eax);
- __ CallRuntime(Runtime::kCall, 3);
-
- // val = result.value; if (!result.done) goto l_try;
- __ bind(&l_loop);
- // result.value
- __ push(eax); // save result
- __ mov(edx, eax); // result
- __ mov(ecx, isolate()->factory()->value_string()); // "value"
- Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(value_ic); // result.value in eax
- __ pop(ebx); // result
- __ push(eax); // result.value
- __ mov(edx, ebx); // result
- __ mov(ecx, isolate()->factory()->done_string()); // "done"
- Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(done_ic); // result.done in eax
- ToBooleanStub stub(eax);
- __ push(eax);
- __ CallStub(&stub);
- __ test(eax, eax);
- __ j(zero, &l_try);
-
- // result.value
- __ pop(eax); // result.value
- context()->DropAndPlug(2, eax); // drop iter and g
- break;
- }
+ case Yield::DELEGATING:
+ UNIMPLEMENTED();
}
}
Expression* generator_object = factory()->NewVariableProxy(
current_function_state_->generator_object_variable());
Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
- Yield* yield =
- factory()->NewYield(generator_object, expression, kind, position);
- if (kind == Yield::DELEGATING) {
- yield->set_index(current_function_state_->NextHandlerIndex());
- }
- return yield;
+ return factory()->NewYield(generator_object, expression, kind, position);
}
break;
}
- case Yield::DELEGATING: {
- VisitForStackValue(expr->generator_object());
-
- // Initial stack layout is as follows:
- // [sp + 1 * kPointerSize] iter
- // [sp + 0 * kPointerSize] g
-
- Label l_catch, l_try, l_resume, l_send, l_call, l_loop;
- // Initial send value is undefined.
- __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
- __ jmp(&l_send);
-
- // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; }
- __ bind(&l_catch);
- handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
- __ movq(rcx, Operand(rsp, 1 * kPointerSize)); // iter
- __ push(rcx); // iter
- __ push(rax); // exception
- __ movq(rax, rcx); // iter
- __ LoadRoot(rcx, Heap::kthrow_stringRootIndex); // "throw"
- Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(throw_ic); // iter.throw in rax
- __ jmp(&l_call);
-
- // try { received = yield result.value }
- __ bind(&l_try);
- __ pop(rax); // result.value
- __ PushTryHandler(StackHandler::CATCH, expr->index());
- const int handler_size = StackHandlerConstants::kSize;
- __ push(rax); // result.value
- __ push(Operand(rsp, (0 + 1) * kPointerSize + handler_size)); // g
- __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
- __ movq(context_register(),
- Operand(rbp, StandardFrameConstants::kContextOffset));
- __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
- __ j(not_equal, &l_resume);
- EmitReturnIteratorResult(false);
- __ bind(&l_resume); // received in rax
- __ PopTryHandler();
-
- // receiver = iter; f = iter.send; arg = received;
- __ bind(&l_send);
- __ movq(rcx, Operand(rsp, 1 * kPointerSize)); // iter
- __ push(rcx); // iter
- __ push(rax); // received
- __ movq(rax, rcx); // iter
- __ LoadRoot(rcx, Heap::ksend_stringRootIndex); // "send"
- Handle<Code> send_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(send_ic); // iter.send in rax
-
- // result = f.call(receiver, arg);
- __ bind(&l_call);
- Label l_call_runtime;
- __ JumpIfSmi(rax, &l_call_runtime);
- __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
- __ j(not_equal, &l_call_runtime);
- __ movq(rdi, rax);
- ParameterCount count(1);
- __ InvokeFunction(rdi, count, CALL_FUNCTION,
- NullCallWrapper(), CALL_AS_METHOD);
- __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
- __ jmp(&l_loop);
- __ bind(&l_call_runtime);
- __ push(rax);
- __ CallRuntime(Runtime::kCall, 3);
-
- // val = result.value; if (!result.done) goto l_try;
- __ bind(&l_loop);
- // result.value
- __ push(rax); // save result
- __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value"
- Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(value_ic); // result.value in rax
- __ pop(rbx); // result
- __ push(rax); // result.value
- __ movq(rax, rbx); // result
- __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
- Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(done_ic); // result.done in rax
- ToBooleanStub stub(rax);
- __ push(rax);
- __ CallStub(&stub);
- __ testq(rax, rax);
- __ j(zero, &l_try);
-
- // result.value
- __ pop(rax); // result.value
- context()->DropAndPlug(2, rax); // drop iter and g
- break;
- }
+ case Yield::DELEGATING:
+ UNIMPLEMENTED();
}
}
"foo",
[2, "1foo3", 5, "4foo6", "foofoo"]);
-// Delegating yield
-TestGenerator(
- function* g26() {
- function* g() { var x = yield 1; yield 2; yield x; return 3; }
- yield* g();
- },
- [1, 2, undefined, undefined],
- "foo",
- [1, 2, "foo", undefined]);
-
function TestTryCatch() {
function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; }
function Sentinel() {}
assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
assertThrows(function() { iter.next(); }, Error);
- // ***
iter = g();
assertIteratorResult(1, false, iter.next());
assertIteratorResult(2, false, iter.next());
assertIteratorResult(3, false, iter.next());
assertIteratorResult(undefined, true, iter.next());
assertThrows(function() { iter.next(); }, Error);
-
- // same as *** above with delegate
- iter = (function* () { yield* g(); })();
- assertIteratorResult(1, false, iter.next());
- assertIteratorResult(2, false, iter.next());
- var exn = new Sentinel;
- assertIteratorResult(exn, false, iter.throw(exn));
- assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
- assertThrows(function() { iter.next(); }, Error);
}
TestTryCatch();
assertThrows(function() { iter.next(); }, Sentinel);
assertThrows(function() { iter.next(); }, Error);
- // ***
iter = g();
assertIteratorResult(1, false, iter.next());
assertIteratorResult(2, false, iter.next());
assertIteratorResult(4, false, iter.next());
assertIteratorResult(undefined, true, iter.next());
assertThrows(function() { iter.next(); }, Error);
-
- // same as *** above with delegate
- iter = (function* () { yield* g(); })();
- assertIteratorResult(1, false, iter.next());
- assertIteratorResult(2, false, iter.next());
- assertIteratorResult(3, false, iter.throw(new Sentinel));
- assertThrows(function() { iter.throw(new Sentinel2); }, Sentinel2);
- assertThrows(function() { iter.next(); }, Error);
}
TestTryFinally();
assertIteratorResult(undefined, true, iter.next());
assertThrows(function() { iter.next(); }, Error);
- // ***
iter = g();
assertIteratorResult(1, false, iter.next());
assertIteratorResult(2, false, iter.next());
assertThrows(function() { iter.next(); }, Sentinel2);
assertThrows(function() { iter.next(); }, Error);
- // same as *** above with delegate
- iter = (function* () { yield* g(); })();
- assertIteratorResult(1, false, iter.next());
- assertIteratorResult(2, false, iter.next());
- var exn = new Sentinel;
- assertIteratorResult(exn, false, iter.throw(exn));
- assertIteratorResult(4, false, iter.throw(new Sentinel2));
- assertThrows(function() { iter.next(); }, Sentinel2);
- assertThrows(function() { iter.next(); }, Error);
-
// That's probably enough.
}
TestNestedTry();