[interpreter] Don't assume generator functions do an initial yield.

Async functions are implemented via special generator functions; special in the
sense that they generally do not immediately yield.  However, our generators
implementation still assumed that every generator function initially yields
(concretely: before doing the state dispatch in a loop header).  This CL fixes
that.

R=littledan@chromium.org, rmcilroy@chromium.org
BUG=chromium:638019

Review-Url: https://codereview.chromium.org/2253033002
Cr-Commit-Position: refs/heads/master@{#38684}
This commit is contained in:
neis 2016-08-17 08:03:19 -07:00 committed by Commit bot
parent 1031a79f60
commit 7fe4d930c9
3 changed files with 29 additions and 13 deletions

View File

@ -876,7 +876,10 @@ void BytecodeGenerator::VisitGeneratorPrologue() {
BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(),
generator_resume_points_);
builder()->Bind(&regular_call);
builder()
->Bind(&regular_call)
.LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
.StoreAccumulatorInRegister(generator_state_);
// This is a regular call. Fall through to the ordinary function prologue,
// after which we will run into the generator object creation and other extra
// code inserted by the parser.

View File

@ -15,7 +15,7 @@ snippet: "
"
frame size: 11
parameter count: 1
bytecode array length: 197
bytecode array length: 201
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(20),
@ -23,10 +23,12 @@ bytecodes: [
B(Star), R(1),
B(LdaZero),
B(TestEqualStrict), R(1),
B(JumpIfTrue), U8(53),
B(JumpIfTrue), U8(57),
B(LdaSmi), U8(76),
B(Star), R(2),
B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1),
B(LdaSmi), U8(-2),
B(Star), R(1),
B(CreateFunctionContext), U8(2),
B(PushContext), R(0),
B(Ldar), R(this),
@ -108,7 +110,7 @@ bytecodes: [
constant pool: [
]
handlers: [
[35, 134, 140],
[39, 138, 144],
]
---
@ -118,7 +120,7 @@ snippet: "
"
frame size: 11
parameter count: 1
bytecode array length: 290
bytecode array length: 294
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(26),
@ -126,13 +128,15 @@ bytecodes: [
B(Star), R(1),
B(LdaZero),
B(TestEqualStrict), R(1),
B(JumpIfTrue), U8(59),
B(JumpIfTrue), U8(63),
B(LdaSmi), U8(1),
B(TestEqualStrict), R(1),
B(JumpIfTrueConstant), U8(0),
B(LdaSmi), U8(76),
B(Star), R(2),
B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1),
B(LdaSmi), U8(-2),
B(Star), R(1),
B(CreateFunctionContext), U8(2),
B(PushContext), R(0),
B(Ldar), R(this),
@ -254,7 +258,7 @@ constant pool: [
kInstanceTypeDontCare,
]
handlers: [
[41, 218, 224],
[45, 222, 228],
]
---
@ -264,7 +268,7 @@ snippet: "
"
frame size: 18
parameter count: 1
bytecode array length: 752
bytecode array length: 756
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(26),
@ -272,13 +276,15 @@ bytecodes: [
B(Star), R(4),
B(LdaZero),
B(TestEqualStrict), R(4),
B(JumpIfTrue), U8(59),
B(JumpIfTrue), U8(63),
B(LdaSmi), U8(1),
B(TestEqualStrict), R(4),
B(JumpIfTrueConstant), U8(3),
B(LdaSmi), U8(76),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kAbort), R(5), U8(1),
B(LdaSmi), U8(-2),
B(Star), R(4),
B(CreateFunctionContext), U8(9),
B(PushContext), R(0),
B(Ldar), R(this),
@ -594,9 +600,9 @@ constant pool: [
kInstanceTypeDontCare,
]
handlers: [
[41, 671, 677],
[139, 426, 432],
[142, 380, 382],
[528, 540, 542],
[45, 675, 681],
[143, 430, 436],
[146, 384, 386],
[532, 544, 546],
]

View File

@ -369,3 +369,10 @@ assertEqualsAsync(
"20", () => (async(foo, { a = "0" }) => foo + a)("2", { a: undefined }));
assertThrows(() => eval("async({ foo = 1 })"), SyntaxError);
assertThrows(() => eval("async(a, { foo = 1 })"), SyntaxError);
// https://bugs.chromium.org/p/chromium/issues/detail?id=628984
async function gaga() {
let i = 1;
while (i-- > 0) { await 42 }
}
assertDoesNotThrow(gaga);