| 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/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
| 9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
| 10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 VisitStatements(stmt->statements()); | 696 VisitStatements(stmt->statements()); |
| 697 if (stmt->labels() != nullptr) block_builder.EndBlock(); | 697 if (stmt->labels() != nullptr) block_builder.EndBlock(); |
| 698 } | 698 } |
| 699 | 699 |
| 700 | 700 |
| 701 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { | 701 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
| 702 Variable* variable = decl->proxy()->var(); | 702 Variable* variable = decl->proxy()->var(); |
| 703 VariableMode mode = decl->mode(); | 703 VariableMode mode = decl->mode(); |
| 704 // Const and let variables are initialized with the hole so that we can | 704 // Const and let variables are initialized with the hole so that we can |
| 705 // check that they are only assigned once. | 705 // check that they are only assigned once. |
| 706 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; | 706 bool hole_init = mode == CONST || mode == LET; |
| 707 switch (variable->location()) { | 707 switch (variable->location()) { |
| 708 case VariableLocation::GLOBAL: | 708 case VariableLocation::GLOBAL: |
| 709 case VariableLocation::UNALLOCATED: { | 709 case VariableLocation::UNALLOCATED: { |
| 710 Handle<Oddball> value = variable->binding_needs_init() | 710 Handle<Oddball> value = variable->binding_needs_init() |
| 711 ? isolate()->factory()->the_hole_value() | 711 ? isolate()->factory()->the_hole_value() |
| 712 : isolate()->factory()->undefined_value(); | 712 : isolate()->factory()->undefined_value(); |
| 713 globals()->push_back(variable->name()); | 713 globals()->push_back(variable->name()); |
| 714 globals()->push_back(value); | 714 globals()->push_back(value); |
| 715 break; | 715 break; |
| 716 } | 716 } |
| (...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1786 } | 1786 } |
| 1787 | 1787 |
| 1788 | 1788 |
| 1789 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1789 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
| 1790 builder()->SetExpressionPosition(proxy); | 1790 builder()->SetExpressionPosition(proxy); |
| 1791 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1791 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
| 1792 } | 1792 } |
| 1793 | 1793 |
| 1794 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, | 1794 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, |
| 1795 Handle<String> name) { | 1795 Handle<String> name) { |
| 1796 if (mode == CONST_LEGACY) { | 1796 if (mode == LET || mode == CONST) { |
| 1797 BytecodeLabel end_label; | |
| 1798 builder()->JumpIfNotHole(&end_label).LoadUndefined().Bind(&end_label); | |
| 1799 } else if (mode == LET || mode == CONST) { | |
| 1800 BuildThrowIfHole(name); | 1797 BuildThrowIfHole(name); |
| 1801 } | 1798 } |
| 1802 } | 1799 } |
| 1803 | 1800 |
| 1804 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1801 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
| 1805 FeedbackVectorSlot slot, | 1802 FeedbackVectorSlot slot, |
| 1806 TypeofMode typeof_mode) { | 1803 TypeofMode typeof_mode) { |
| 1807 VariableMode mode = variable->mode(); | 1804 VariableMode mode = variable->mode(); |
| 1808 switch (variable->location()) { | 1805 switch (variable->location()) { |
| 1809 case VariableLocation::LOCAL: { | 1806 case VariableLocation::LOCAL: { |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1973 } | 1970 } |
| 1974 } | 1971 } |
| 1975 | 1972 |
| 1976 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1973 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
| 1977 Token::Value op, | 1974 Token::Value op, |
| 1978 FeedbackVectorSlot slot) { | 1975 FeedbackVectorSlot slot) { |
| 1979 VariableMode mode = variable->mode(); | 1976 VariableMode mode = variable->mode(); |
| 1980 RegisterAllocationScope assignment_register_scope(this); | 1977 RegisterAllocationScope assignment_register_scope(this); |
| 1981 BytecodeLabel end_label; | 1978 BytecodeLabel end_label; |
| 1982 bool hole_check_required = | 1979 bool hole_check_required = |
| 1983 (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) || | 1980 (mode == LET && op != Token::INIT) || |
| 1984 (mode == CONST && op != Token::INIT) || | 1981 (mode == CONST && op != Token::INIT) || |
| 1985 (mode == CONST && op == Token::INIT && variable->is_this()); | 1982 (mode == CONST && op == Token::INIT && variable->is_this()); |
| 1986 switch (variable->location()) { | 1983 switch (variable->location()) { |
| 1987 case VariableLocation::PARAMETER: | 1984 case VariableLocation::PARAMETER: |
| 1988 case VariableLocation::LOCAL: { | 1985 case VariableLocation::LOCAL: { |
| 1989 Register destination; | 1986 Register destination; |
| 1990 if (VariableLocation::PARAMETER == variable->location()) { | 1987 if (VariableLocation::PARAMETER == variable->location()) { |
| 1991 destination = Register(builder()->Parameter(variable->index() + 1)); | 1988 destination = Register(builder()->Parameter(variable->index() + 1)); |
| 1992 } else { | 1989 } else { |
| 1993 destination = Register(variable->index()); | 1990 destination = Register(variable->index()); |
| 1994 } | 1991 } |
| 1995 | 1992 |
| 1993 if (mode == CONST_LEGACY && op != Token::INIT) { |
| 1994 if (is_strict(language_mode())) { |
| 1995 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), |
| 1996 0); |
| 1997 } |
| 1998 // Non-initializing assignments to legacy constants are ignored |
| 1999 // in sloppy mode. Break here to avoid storing into variable. |
| 2000 break; |
| 2001 } |
| 2002 |
| 1996 if (hole_check_required) { | 2003 if (hole_check_required) { |
| 1997 // Load destination to check for hole. | 2004 // Load destination to check for hole. |
| 1998 Register value_temp = register_allocator()->NewRegister(); | 2005 Register value_temp = register_allocator()->NewRegister(); |
| 1999 builder() | 2006 builder() |
| 2000 ->StoreAccumulatorInRegister(value_temp) | 2007 ->StoreAccumulatorInRegister(value_temp) |
| 2001 .LoadAccumulatorWithRegister(destination); | 2008 .LoadAccumulatorWithRegister(destination); |
| 2002 | 2009 |
| 2003 if (mode == CONST_LEGACY && op == Token::INIT) { | 2010 BuildHoleCheckForVariableAssignment(variable, op); |
| 2004 // Perform an intialization check for legacy constants. | 2011 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2005 builder() | |
| 2006 ->JumpIfNotHole(&end_label) | |
| 2007 .MoveRegister(value_temp, destination) | |
| 2008 .Bind(&end_label) | |
| 2009 .LoadAccumulatorWithRegister(value_temp); | |
| 2010 // Break here because the value should not be stored unconditionally. | |
| 2011 break; | |
| 2012 } else if (mode == CONST_LEGACY && op != Token::INIT) { | |
| 2013 if (is_strict(language_mode())) { | |
| 2014 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), | |
| 2015 0); | |
| 2016 } else { | |
| 2017 // Ensure accumulator is in the correct state. | |
| 2018 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 2019 } | |
| 2020 // Non-initializing assignments to legacy constants are ignored | |
| 2021 // in sloppy mode. Break here to avoid storing into variable. | |
| 2022 break; | |
| 2023 } else { | |
| 2024 BuildHoleCheckForVariableAssignment(variable, op); | |
| 2025 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 2026 } | |
| 2027 } | 2012 } |
| 2028 | |
| 2029 builder()->StoreAccumulatorInRegister(destination); | 2013 builder()->StoreAccumulatorInRegister(destination); |
| 2030 break; | 2014 break; |
| 2031 } | 2015 } |
| 2032 case VariableLocation::GLOBAL: | 2016 case VariableLocation::GLOBAL: |
| 2033 case VariableLocation::UNALLOCATED: { | 2017 case VariableLocation::UNALLOCATED: { |
| 2034 builder()->StoreGlobal(variable->name(), feedback_index(slot), | 2018 builder()->StoreGlobal(variable->name(), feedback_index(slot), |
| 2035 language_mode()); | 2019 language_mode()); |
| 2036 break; | 2020 break; |
| 2037 } | 2021 } |
| 2038 case VariableLocation::CONTEXT: { | 2022 case VariableLocation::CONTEXT: { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2055 .LoadAccumulatorWithRegister(execution_context()->reg()) | 2039 .LoadAccumulatorWithRegister(execution_context()->reg()) |
| 2056 .StoreAccumulatorInRegister(context_reg); | 2040 .StoreAccumulatorInRegister(context_reg); |
| 2057 for (int i = 0; i < depth; ++i) { | 2041 for (int i = 0; i < depth; ++i) { |
| 2058 builder() | 2042 builder() |
| 2059 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) | 2043 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) |
| 2060 .StoreAccumulatorInRegister(context_reg); | 2044 .StoreAccumulatorInRegister(context_reg); |
| 2061 } | 2045 } |
| 2062 builder()->LoadAccumulatorWithRegister(value_temp); | 2046 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2063 } | 2047 } |
| 2064 | 2048 |
| 2049 if (mode == CONST_LEGACY && op != Token::INIT) { |
| 2050 if (is_strict(language_mode())) { |
| 2051 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), |
| 2052 0); |
| 2053 } |
| 2054 // Non-initializing assignments to legacy constants are ignored |
| 2055 // in sloppy mode. Break here to avoid storing into variable. |
| 2056 break; |
| 2057 } |
| 2058 |
| 2065 if (hole_check_required) { | 2059 if (hole_check_required) { |
| 2066 // Load destination to check for hole. | 2060 // Load destination to check for hole. |
| 2067 Register value_temp = register_allocator()->NewRegister(); | 2061 Register value_temp = register_allocator()->NewRegister(); |
| 2068 builder() | 2062 builder() |
| 2069 ->StoreAccumulatorInRegister(value_temp) | 2063 ->StoreAccumulatorInRegister(value_temp) |
| 2070 .LoadContextSlot(context_reg, variable->index()); | 2064 .LoadContextSlot(context_reg, variable->index()); |
| 2071 | 2065 |
| 2072 if (mode == CONST_LEGACY && op == Token::INIT) { | 2066 BuildHoleCheckForVariableAssignment(variable, op); |
| 2073 // Perform an intialization check for legacy constants. | 2067 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2074 builder() | |
| 2075 ->JumpIfNotHole(&end_label) | |
| 2076 .LoadAccumulatorWithRegister(value_temp) | |
| 2077 .StoreContextSlot(context_reg, variable->index()) | |
| 2078 .Bind(&end_label); | |
| 2079 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 2080 // Break here because the value should not be stored unconditionally. | |
| 2081 // The above code performs the store conditionally. | |
| 2082 break; | |
| 2083 } else if (mode == CONST_LEGACY && op != Token::INIT) { | |
| 2084 if (is_strict(language_mode())) { | |
| 2085 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), | |
| 2086 0); | |
| 2087 } else { | |
| 2088 // Ensure accumulator is in the correct state. | |
| 2089 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 2090 } | |
| 2091 // Non-initializing assignments to legacy constants are ignored | |
| 2092 // in sloppy mode. Break here to avoid storing into variable. | |
| 2093 break; | |
| 2094 } else { | |
| 2095 BuildHoleCheckForVariableAssignment(variable, op); | |
| 2096 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 2097 } | |
| 2098 } | 2068 } |
| 2099 | 2069 |
| 2100 builder()->StoreContextSlot(context_reg, variable->index()); | 2070 builder()->StoreContextSlot(context_reg, variable->index()); |
| 2101 break; | 2071 break; |
| 2102 } | 2072 } |
| 2103 case VariableLocation::LOOKUP: { | 2073 case VariableLocation::LOOKUP: { |
| 2104 if (mode == CONST_LEGACY && op == Token::INIT) { | 2074 DCHECK_NE(CONST_LEGACY, variable->mode()); |
| 2105 register_allocator()->PrepareForConsecutiveAllocations(3); | 2075 builder()->StoreLookupSlot(variable->name(), language_mode()); |
| 2106 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 2107 Register context = register_allocator()->NextConsecutiveRegister(); | |
| 2108 Register name = register_allocator()->NextConsecutiveRegister(); | |
| 2109 | |
| 2110 // InitializeLegacyConstLookupSlot runtime call returns the 'value' | |
| 2111 // passed to it. So, accumulator will have its original contents when | |
| 2112 // runtime call returns. | |
| 2113 builder() | |
| 2114 ->StoreAccumulatorInRegister(value) | |
| 2115 .MoveRegister(execution_context()->reg(), context) | |
| 2116 .LoadLiteral(variable->name()) | |
| 2117 .StoreAccumulatorInRegister(name) | |
| 2118 .CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, value, 3); | |
| 2119 } else { | |
| 2120 builder()->StoreLookupSlot(variable->name(), language_mode()); | |
| 2121 } | |
| 2122 break; | 2076 break; |
| 2123 } | 2077 } |
| 2124 } | 2078 } |
| 2125 } | 2079 } |
| 2126 | 2080 |
| 2127 | 2081 |
| 2128 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 2082 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 2129 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); | 2083 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
| 2130 Register object, key, home_object, value; | 2084 Register object, key, home_object, value; |
| 2131 Handle<String> name; | 2085 Handle<String> name; |
| (...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3274 } | 3228 } |
| 3275 | 3229 |
| 3276 | 3230 |
| 3277 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3231 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3278 return info()->shared_info()->feedback_vector()->GetIndex(slot); | 3232 return info()->shared_info()->feedback_vector()->GetIndex(slot); |
| 3279 } | 3233 } |
| 3280 | 3234 |
| 3281 } // namespace interpreter | 3235 } // namespace interpreter |
| 3282 } // namespace internal | 3236 } // namespace internal |
| 3283 } // namespace v8 | 3237 } // namespace v8 |
| OLD | NEW |