Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: src/interpreter/bytecode-generator.cc

Issue 2411873004: [ignition] Eliminate hole checks where statically possible for loads and stores (Closed)
Patch Set: Move logic to scope analysis time Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698