Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index fc5a4a4fa67c5a470aefee9b7dfe4b2d7600301e..3ac33039220292b6d165ef69d811fdfdfc17a470 100644 |
--- a/src/interpreter/bytecode-generator.cc |
+++ b/src/interpreter/bytecode-generator.cc |
@@ -829,8 +829,8 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
case VariableLocation::MODULE: |
if (variable->IsExport() && variable->binding_needs_init()) { |
builder()->LoadTheHole(); |
- VisitVariableAssignment(variable, Token::INIT, |
- FeedbackVectorSlot::Invalid()); |
+ BuildVariableAssignment(variable, Token::INIT, |
+ FeedbackVectorSlot::Invalid(), decl->proxy()); |
} |
// Nothing to do for imports. |
break; |
@@ -849,8 +849,8 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
case VariableLocation::PARAMETER: |
case VariableLocation::LOCAL: { |
VisitForAccumulatorValue(decl->fun()); |
- VisitVariableAssignment(variable, Token::INIT, |
- FeedbackVectorSlot::Invalid()); |
+ BuildVariableAssignment(variable, Token::INIT, |
+ FeedbackVectorSlot::Invalid(), decl->proxy()); |
break; |
} |
case VariableLocation::CONTEXT: { |
@@ -874,8 +874,8 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
DCHECK_EQ(variable->mode(), LET); |
DCHECK(variable->IsExport()); |
VisitForAccumulatorValue(decl->fun()); |
- VisitVariableAssignment(variable, Token::INIT, |
- FeedbackVectorSlot::Invalid()); |
+ BuildVariableAssignment(variable, Token::INIT, |
+ FeedbackVectorSlot::Invalid(), decl->proxy()); |
break; |
} |
} |
@@ -894,7 +894,7 @@ void BytecodeGenerator::VisitModuleNamespaceImports() { |
.CallRuntime(Runtime::kGetModuleNamespace, module_request); |
Variable* var = scope()->LookupLocal(entry->local_name); |
DCHECK_NOT_NULL(var); |
- VisitVariableAssignment(var, Token::INIT, FeedbackVectorSlot::Invalid()); |
+ BuildVariableAssignment(var, Token::INIT, FeedbackVectorSlot::Invalid()); |
} |
} |
@@ -1147,8 +1147,8 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
LhsKind assign_type = Property::GetAssignType(property); |
switch (assign_type) { |
case VARIABLE: { |
- Variable* variable = expr->AsVariableProxy()->var(); |
- VisitVariableAssignment(variable, Token::ASSIGN, slot); |
+ VariableProxy* proxy = expr->AsVariableProxy(); |
+ BuildVariableAssignment(proxy->var(), Token::ASSIGN, slot, proxy); |
break; |
} |
case NAMED_PROPERTY: { |
@@ -1395,11 +1395,11 @@ void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { |
builder()->CallRuntime(Runtime::kToFastProperties, literal); |
// Assign to class variable. |
if (expr->class_variable_proxy() != nullptr) { |
- Variable* var = expr->class_variable_proxy()->var(); |
+ VariableProxy* proxy = expr->class_variable_proxy(); |
FeedbackVectorSlot slot = expr->NeedsProxySlot() |
? expr->ProxySlot() |
: FeedbackVectorSlot::Invalid(); |
- VisitVariableAssignment(var, Token::INIT, slot); |
+ BuildVariableAssignment(proxy->var(), Token::INIT, slot, proxy); |
} |
} |
@@ -1773,18 +1773,19 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
builder()->SetExpressionPosition(proxy); |
- VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
+ BuildVariableLoad(proxy); |
} |
-void BytecodeGenerator::BuildHoleCheckForVariableLoad(Variable* variable) { |
- if (variable->binding_needs_init()) { |
- BuildThrowIfHole(variable->name()); |
+void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableProxy* proxy) { |
+ if (proxy->needs_hole_check()) { |
+ BuildThrowIfHole(proxy->name()); |
} |
} |
-void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
- FeedbackVectorSlot slot, |
+void BytecodeGenerator::BuildVariableLoad(VariableProxy* proxy, |
TypeofMode typeof_mode) { |
+ Variable* variable = proxy->var(); |
+ FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); |
switch (variable->location()) { |
case VariableLocation::LOCAL: { |
Register source(Register(variable->index())); |
@@ -1792,7 +1793,7 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
// VisitForRegisterScope, in order to avoid register aliasing if |
// subsequent expressions assign to the same variable. |
builder()->LoadAccumulatorWithRegister(source); |
- BuildHoleCheckForVariableLoad(variable); |
+ BuildHoleCheckForVariableLoad(proxy); |
break; |
} |
case VariableLocation::PARAMETER: { |
@@ -1803,7 +1804,7 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
// VisitForRegisterScope, in order to avoid register aliasing if |
// subsequent expressions assign to the same variable. |
builder()->LoadAccumulatorWithRegister(source); |
- BuildHoleCheckForVariableLoad(variable); |
+ BuildHoleCheckForVariableLoad(proxy); |
break; |
} |
case VariableLocation::UNALLOCATED: { |
@@ -1822,7 +1823,7 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
} |
builder()->LoadContextSlot(context_reg, variable->index(), depth); |
- BuildHoleCheckForVariableLoad(variable); |
+ BuildHoleCheckForVariableLoad(proxy); |
break; |
} |
case VariableLocation::LOOKUP: { |
@@ -1833,7 +1834,7 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
execution_context()->ContextChainDepth(local_variable->scope()); |
builder()->LoadLookupContextSlot(variable->name(), typeof_mode, |
local_variable->index(), depth); |
- BuildHoleCheckForVariableLoad(variable); |
+ BuildHoleCheckForVariableLoad(proxy); |
break; |
} |
case DYNAMIC_GLOBAL: { |
@@ -1868,16 +1869,16 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
.StoreAccumulatorInRegister(args[1]) |
.CallRuntime(Runtime::kLoadModuleImport, args); |
} |
- BuildHoleCheckForVariableLoad(variable); |
+ BuildHoleCheckForVariableLoad(proxy); |
break; |
} |
} |
} |
-void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( |
- Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
+void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( |
+ VariableProxy* proxy, TypeofMode typeof_mode) { |
ValueResultScope accumulator_result(this); |
- VisitVariableLoad(variable, slot, typeof_mode); |
+ BuildVariableLoad(proxy, typeof_mode); |
} |
void BytecodeGenerator::BuildReturn() { |
@@ -1946,15 +1947,16 @@ void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, |
} |
} |
-void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
+void BytecodeGenerator::BuildVariableAssignment(Variable* variable, |
Token::Value op, |
- FeedbackVectorSlot slot) { |
+ FeedbackVectorSlot slot, |
+ VariableProxy* proxy) { |
+ DCHECK_IMPLIES(proxy != nullptr, variable == proxy->var()); |
+ DCHECK_IMPLIES(proxy == nullptr, !variable->binding_needs_init()); |
+ bool hole_check_required = proxy != nullptr && proxy->needs_hole_check(); |
VariableMode mode = variable->mode(); |
RegisterAllocationScope assignment_register_scope(this); |
BytecodeLabel end_label; |
- bool hole_check_required = |
- variable->binding_needs_init() && |
- (op != Token::INIT || (mode == CONST && variable->is_this())); |
switch (variable->location()) { |
case VariableLocation::PARAMETER: |
case VariableLocation::LOCAL: { |
@@ -2108,7 +2110,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
switch (assign_type) { |
case VARIABLE: { |
VariableProxy* proxy = expr->target()->AsVariableProxy(); |
- VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
+ BuildVariableLoad(proxy); |
builder()->StoreAccumulatorInRegister(old_value); |
break; |
} |
@@ -2157,10 +2159,10 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
FeedbackVectorSlot slot = expr->AssignmentSlot(); |
switch (assign_type) { |
case VARIABLE: { |
- // TODO(oth): The VisitVariableAssignment() call is hard to reason about. |
+ // TODO(oth): The BuildVariableAssignment() call is hard to reason about. |
// Is the value in the accumulator safe? Yes, but scary. |
- Variable* variable = expr->target()->AsVariableProxy()->var(); |
- VisitVariableAssignment(variable, expr->op(), slot); |
+ VariableProxy* proxy = expr->target()->AsVariableProxy(); |
+ BuildVariableAssignment(proxy->var(), expr->op(), slot, proxy); |
break; |
} |
case NAMED_PROPERTY: |
@@ -2386,8 +2388,7 @@ void BytecodeGenerator::VisitCall(Call* expr) { |
builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
// Load callee as a global variable. |
VariableProxy* proxy = callee_expr->AsVariableProxy(); |
- VisitVariableLoadForAccumulatorValue(proxy->var(), |
- proxy->VariableFeedbackSlot()); |
+ BuildVariableLoadForAccumulatorValue(proxy); |
builder()->StoreAccumulatorInRegister(callee); |
break; |
} |
@@ -2553,8 +2554,7 @@ void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { |
// Typeof does not throw a reference error on global variables, hence we |
// perform a non-contextual load in case the operand is a variable proxy. |
VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
- VisitVariableLoadForAccumulatorValue( |
- proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); |
+ BuildVariableLoadForAccumulatorValue(proxy, INSIDE_TYPEOF); |
} else { |
VisitForAccumulatorValue(expr->expression()); |
} |
@@ -2678,8 +2678,7 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { |
switch (assign_type) { |
case VARIABLE: { |
VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
- VisitVariableLoadForAccumulatorValue(proxy->var(), |
- proxy->VariableFeedbackSlot()); |
+ BuildVariableLoadForAccumulatorValue(proxy); |
break; |
} |
case NAMED_PROPERTY: { |
@@ -2742,8 +2741,8 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { |
FeedbackVectorSlot feedback_slot = expr->CountSlot(); |
switch (assign_type) { |
case VARIABLE: { |
- Variable* variable = expr->expression()->AsVariableProxy()->var(); |
- VisitVariableAssignment(variable, expr->op(), feedback_slot); |
+ VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
+ BuildVariableAssignment(proxy->var(), expr->op(), feedback_slot, proxy); |
break; |
} |
case NAMED_PROPERTY: { |
@@ -3035,7 +3034,7 @@ void BytecodeGenerator::VisitArgumentsObject(Variable* variable) { |
? CreateArgumentsType::kUnmappedArguments |
: CreateArgumentsType::kMappedArguments; |
builder()->CreateArguments(type); |
- VisitVariableAssignment(variable, Token::ASSIGN, |
+ BuildVariableAssignment(variable, Token::ASSIGN, |
FeedbackVectorSlot::Invalid()); |
} |
@@ -3046,7 +3045,7 @@ void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) { |
// variable. |
builder()->CreateArguments(CreateArgumentsType::kRestParameter); |
DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); |
- VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid()); |
+ BuildVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid()); |
} |
void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { |
@@ -3054,7 +3053,7 @@ void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { |
// Store the closure we were called with in the given variable. |
builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
- VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
+ BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
} |
void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { |
@@ -3062,7 +3061,7 @@ void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { |
// Store the new target we were called with in the given variable. |
builder()->LoadAccumulatorWithRegister(Register::new_target()); |
- VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
+ BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
// TODO(mstarzinger): The <new.target> register is not set by the deoptimizer |
// and we need to make sure {BytecodeRegisterOptimizer} flushes its state |