Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
| 6 | 6 |
| 7 #include "src/ast/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/builtins/builtins-constructor.h" | 9 #include "src/builtins/builtins-constructor.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 699 // since we skip some obviously dead code. Hence the generated bytecode may | 699 // since we skip some obviously dead code. Hence the generated bytecode may |
| 700 // contain jumps to unbound labels (resume points that will never be used). | 700 // contain jumps to unbound labels (resume points that will never be used). |
| 701 // We bind these now. | 701 // We bind these now. |
| 702 for (auto& label : generator_resume_points_) { | 702 for (auto& label : generator_resume_points_) { |
| 703 if (!label.is_bound()) builder()->Bind(&label); | 703 if (!label.is_bound()) builder()->Bind(&label); |
| 704 } | 704 } |
| 705 | 705 |
| 706 // Emit an implicit return instruction in case control flow can fall off the | 706 // Emit an implicit return instruction in case control flow can fall off the |
| 707 // end of the function without an explicit return being present on all paths. | 707 // end of the function without an explicit return being present on all paths. |
| 708 if (builder()->RequiresImplicitReturn()) { | 708 if (builder()->RequiresImplicitReturn()) { |
| 709 // Do a hard return as execution_control is the top level and will not | |
| 710 // issue a deferred return command. | |
| 711 DCHECK(execution_control() == &control); | |
| 709 builder()->LoadUndefined(); | 712 builder()->LoadUndefined(); |
| 710 BuildReturn(); | 713 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
| |
| 711 } | 714 } |
| 712 DCHECK(!builder()->RequiresImplicitReturn()); | 715 DCHECK(!builder()->RequiresImplicitReturn()); |
| 713 } | 716 } |
| 714 | 717 |
| 715 void BytecodeGenerator::GenerateBytecodeBody() { | 718 void BytecodeGenerator::GenerateBytecodeBody() { |
| 716 // Build the arguments object if it is used. | 719 // Build the arguments object if it is used. |
| 717 VisitArgumentsObject(scope()->arguments()); | 720 VisitArgumentsObject(scope()->arguments()); |
| 718 | 721 |
| 719 // Build rest arguments array if it is used. | 722 // Build rest arguments array if it is used. |
| 720 Variable* rest_parameter = scope()->rest_parameter(); | 723 Variable* rest_parameter = scope()->rest_parameter(); |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1051 } | 1054 } |
| 1052 | 1055 |
| 1053 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 1056 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
| 1054 builder()->SetStatementPosition(stmt); | 1057 builder()->SetStatementPosition(stmt); |
| 1055 execution_control()->Break(stmt->target()); | 1058 execution_control()->Break(stmt->target()); |
| 1056 } | 1059 } |
| 1057 | 1060 |
| 1058 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 1061 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
| 1059 builder()->SetStatementPosition(stmt); | 1062 builder()->SetStatementPosition(stmt); |
| 1060 VisitForAccumulatorValue(stmt->expression()); | 1063 VisitForAccumulatorValue(stmt->expression()); |
| 1064 | |
| 1065 if (stmt->is_hard_return()) { | |
| 1066 // TODO(caitp): remove hard_return handling and ReturnStatement AST node | |
| 1067 // flags once BytecodeGenerator performs all implicit control flow for | |
| 1068 // async functions. | |
| 1069 return BuildHardReturn(); | |
| 1070 } | |
| 1071 | |
| 1061 execution_control()->ReturnAccumulator(); | 1072 execution_control()->ReturnAccumulator(); |
| 1062 } | 1073 } |
| 1063 | 1074 |
| 1064 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 1075 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
| 1065 builder()->SetStatementPosition(stmt); | 1076 builder()->SetStatementPosition(stmt); |
| 1066 VisitForAccumulatorValue(stmt->expression()); | 1077 VisitForAccumulatorValue(stmt->expression()); |
| 1067 BuildNewLocalWithContext(stmt->scope()); | 1078 BuildNewLocalWithContext(stmt->scope()); |
| 1068 VisitInScope(stmt->statement(), stmt->scope()); | 1079 VisitInScope(stmt->statement(), stmt->scope()); |
| 1069 } | 1080 } |
| 1070 | 1081 |
| (...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1984 } | 1995 } |
| 1985 | 1996 |
| 1986 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( | 1997 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( |
| 1987 Variable* variable, FeedbackSlot slot, HoleCheckMode hole_check_mode, | 1998 Variable* variable, FeedbackSlot slot, HoleCheckMode hole_check_mode, |
| 1988 TypeofMode typeof_mode) { | 1999 TypeofMode typeof_mode) { |
| 1989 ValueResultScope accumulator_result(this); | 2000 ValueResultScope accumulator_result(this); |
| 1990 BuildVariableLoad(variable, slot, hole_check_mode, typeof_mode); | 2001 BuildVariableLoad(variable, slot, hole_check_mode, typeof_mode); |
| 1991 } | 2002 } |
| 1992 | 2003 |
| 1993 void BytecodeGenerator::BuildReturn() { | 2004 void BytecodeGenerator::BuildReturn() { |
| 2005 if (IsAsyncFunction(info()->literal()->kind())) { | |
| 2006 RegisterAllocationScope register_scope(this); | |
| 2007 RegisterList args = register_allocator()->NewRegisterList(3); | |
| 2008 Register receiver = args[0]; | |
| 2009 Register promise = args[1]; | |
| 2010 Register return_value = args[2]; | |
| 2011 builder()->StoreAccumulatorInRegister(return_value); | |
| 2012 | |
| 2013 Variable* var_promise = scope()->promise_var(); | |
| 2014 DCHECK_NOT_NULL(var_promise); | |
| 2015 BuildVariableLoad(var_promise, FeedbackSlot::Invalid(), | |
| 2016 HoleCheckMode::kElided); | |
| 2017 builder() | |
| 2018 ->StoreAccumulatorInRegister(promise) | |
| 2019 .LoadUndefined() | |
| 2020 .StoreAccumulatorInRegister(receiver) | |
| 2021 .CallJSRuntime(Context::PROMISE_RESOLVE_INDEX, args) | |
| 2022 .LoadAccumulatorWithRegister(promise); | |
| 2023 } | |
| 2024 | |
| 2025 BuildHardReturn(); | |
| 2026 } | |
| 2027 | |
| 2028 void BytecodeGenerator::BuildHardReturn() { | |
| 1994 if (FLAG_trace) { | 2029 if (FLAG_trace) { |
| 1995 RegisterAllocationScope register_scope(this); | 2030 RegisterAllocationScope register_scope(this); |
| 1996 Register result = register_allocator()->NewRegister(); | 2031 Register result = register_allocator()->NewRegister(); |
| 1997 // Runtime returns {result} value, preserving accumulator. | 2032 // Runtime returns {result} value, preserving accumulator. |
| 1998 builder()->StoreAccumulatorInRegister(result).CallRuntime( | 2033 builder()->StoreAccumulatorInRegister(result).CallRuntime( |
| 1999 Runtime::kTraceExit, result); | 2034 Runtime::kTraceExit, result); |
| 2000 } | 2035 } |
| 2001 builder()->Return(); | 2036 builder()->Return(); |
| 2002 } | 2037 } |
| 2003 | 2038 |
| (...skipping 1377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3381 } | 3416 } |
| 3382 | 3417 |
| 3383 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3418 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
| 3384 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3419 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 3385 : Runtime::kStoreKeyedToSuper_Sloppy; | 3420 : Runtime::kStoreKeyedToSuper_Sloppy; |
| 3386 } | 3421 } |
| 3387 | 3422 |
| 3388 } // namespace interpreter | 3423 } // namespace interpreter |
| 3389 } // namespace internal | 3424 } // namespace internal |
| 3390 } // namespace v8 | 3425 } // namespace v8 |
| OLD | NEW |