Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index cfc45caefe82a366f30f0a3b856ebe44c6bee757..82c9a7cf55797384a0354820bade802f7b7c71df 100644 |
--- a/src/interpreter/bytecode-generator.cc |
+++ b/src/interpreter/bytecode-generator.cc |
@@ -706,8 +706,11 @@ void BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) { |
// Emit an implicit return instruction in case control flow can fall off the |
// end of the function without an explicit return being present on all paths. |
if (builder()->RequiresImplicitReturn()) { |
+ // Do a hard return as execution_control is the top level and will not |
+ // issue a deferred return command. |
+ DCHECK(execution_control() == &control); |
builder()->LoadUndefined(); |
- BuildReturn(); |
+ BuildHardReturn(); |
Dan Ehrenberg
2017/02/09 06:40:00
Why is this a hard return? I would expect implicit
caitp
2017/02/09 12:53:07
This change is just too shrink bytecode a bit.
Th
Dan Ehrenberg
2017/02/09 13:23:36
I thought this would be reached in a case like "as
rmcilroy
2017/02/09 13:33:49
I didn't realize this was only a to optimize bytec
caitp
2017/02/09 13:38:47
My understanding is that this is needed to ensure
|
} |
DCHECK(!builder()->RequiresImplicitReturn()); |
} |
@@ -1058,6 +1061,14 @@ void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
builder()->SetStatementPosition(stmt); |
VisitForAccumulatorValue(stmt->expression()); |
+ |
+ if (stmt->is_hard_return()) { |
+ // TODO(caitp): remove hard_return handling and ReturnStatement AST node |
+ // flags once BytecodeGenerator performs all implicit control flow for |
+ // async functions. |
+ return BuildHardReturn(); |
+ } |
+ |
execution_control()->ReturnAccumulator(); |
} |
@@ -1991,6 +2002,30 @@ void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( |
} |
void BytecodeGenerator::BuildReturn() { |
+ if (IsAsyncFunction(info()->literal()->kind())) { |
+ RegisterAllocationScope register_scope(this); |
+ RegisterList args = register_allocator()->NewRegisterList(3); |
+ Register receiver = args[0]; |
+ Register promise = args[1]; |
+ Register return_value = args[2]; |
+ builder()->StoreAccumulatorInRegister(return_value); |
+ |
+ Variable* var_promise = scope()->promise_var(); |
+ DCHECK_NOT_NULL(var_promise); |
+ BuildVariableLoad(var_promise, FeedbackSlot::Invalid(), |
+ HoleCheckMode::kElided); |
+ builder() |
+ ->StoreAccumulatorInRegister(promise) |
+ .LoadUndefined() |
+ .StoreAccumulatorInRegister(receiver) |
+ .CallJSRuntime(Context::PROMISE_RESOLVE_INDEX, args) |
+ .LoadAccumulatorWithRegister(promise); |
+ } |
+ |
+ BuildHardReturn(); |
+} |
+ |
+void BytecodeGenerator::BuildHardReturn() { |
if (FLAG_trace) { |
RegisterAllocationScope register_scope(this); |
Register result = register_allocator()->NewRegister(); |