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

Unified Diff: src/hydrogen.cc

Issue 23537024: Let BuildStore/BuildLoad distinguish between keyed/named load/stores. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 7 years, 3 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
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index bd9b0d69967ecec4e3e3b2a99afee473d81b30ce..3cbe1cb392751a97f5568d110a9c2140cbe7f73a 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -4896,109 +4896,51 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
}
-void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
- Property* prop = expr->target()->AsProperty();
- ASSERT(prop != NULL);
- CHECK_ALIVE(VisitForValue(prop->obj()));
+static bool ComputeReceiverTypes(Expression* expr,
+ HValue* receiver,
+ SmallMapList** t) {
+ SmallMapList* types = expr->GetReceiverTypes();
+ *t = types;
+ bool monomorphic = expr->IsMonomorphic();
+ if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
+ Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
+ types->FilterForPossibleTransitions(root_map);
+ monomorphic = types->length() == 1;
+ }
+ return monomorphic && CanInlinePropertyAccess(*types->first());
+}
- if (prop->key()->IsPropertyName()) {
- // Named store.
- CHECK_ALIVE(VisitForValue(expr->value()));
- HValue* value = environment()->ExpressionStackAt(0);
- HValue* object = environment()->ExpressionStackAt(1);
- if (expr->IsUninitialized()) {
- Add<HDeoptimize>("Insufficient type feedback for property assignment",
- Deoptimizer::SOFT);
- }
- return BuildStoreNamed(
- expr, expr->id(), expr->AssignmentId(), prop, object, value);
- } else {
+void HOptimizedGraphBuilder::BuildStore(Expression* expr,
+ Property* prop,
+ BailoutId ast_id,
+ BailoutId return_id,
+ bool is_uninitialized) {
+ HValue* value = environment()->ExpressionStackAt(0);
+
+ if (!prop->key()->IsPropertyName()) {
// Keyed store.
- CHECK_ALIVE(VisitForValue(prop->key()));
- CHECK_ALIVE(VisitForValue(expr->value()));
- HValue* value = environment()->ExpressionStackAt(0);
HValue* key = environment()->ExpressionStackAt(1);
HValue* object = environment()->ExpressionStackAt(2);
bool has_side_effects = false;
- HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(),
+ HandleKeyedElementAccess(object, key, value, expr, return_id,
expr->position(),
true, // is_store
&has_side_effects);
Drop(3);
Push(value);
- Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
+ Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
return ast_context()->ReturnValue(Pop());
}
-}
-
-
-// Because not every expression has a position and there is not common
-// superclass of Assignment and CountOperation, we cannot just pass the
-// owning expression instead of position and ast_id separately.
-void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
- Variable* var,
- HValue* value,
- int position,
- BailoutId ast_id) {
- LookupResult lookup(isolate());
- GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
- if (type == kUseCell) {
- Handle<GlobalObject> global(current_info()->global_object());
- Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
- if (cell->type()->IsConstant()) {
- IfBuilder builder(this);
- HValue* constant = Add<HConstant>(cell->type()->AsConstant());
- if (cell->type()->AsConstant()->IsNumber()) {
- builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ);
- } else {
- builder.If<HCompareObjectEqAndBranch>(value, constant);
- }
- builder.Then();
- builder.Else();
- Add<HDeoptimize>("Constant global variable assignment",
- Deoptimizer::EAGER);
- builder.End();
- }
- HInstruction* instr =
- Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
- instr->set_position(position);
- if (instr->HasObservableSideEffects()) {
- Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
- }
- } else {
- HGlobalObject* global_object = Add<HGlobalObject>();
- HStoreGlobalGeneric* instr =
- Add<HStoreGlobalGeneric>(global_object, var->name(),
- value, function_strict_mode_flag());
- instr->set_position(position);
- ASSERT(instr->HasObservableSideEffects());
- Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
- }
-}
+ // Named store.
+ HValue* object = environment()->ExpressionStackAt(1);
-static bool ComputeReceiverTypes(Expression* expr,
- HValue* receiver,
- SmallMapList** t) {
- SmallMapList* types = expr->GetReceiverTypes();
- *t = types;
- bool monomorphic = expr->IsMonomorphic();
- if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
- Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
- types->FilterForPossibleTransitions(root_map);
- monomorphic = types->length() == 1;
+ if (is_uninitialized) {
+ Add<HDeoptimize>("Insufficient type feedback for property assignment",
+ Deoptimizer::SOFT);
}
- return monomorphic && CanInlinePropertyAccess(*types->first());
-}
-
-void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
- BailoutId id,
- BailoutId assignment_id,
- Property* prop,
- HValue* object,
- HValue* value) {
Literal* key = prop->key()->AsLiteral();
Handle<String> name = Handle<String>::cast(key->value());
ASSERT(!name.is_null());
@@ -5015,7 +4957,7 @@ void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
if (LookupSetter(map, name, &setter, &holder)) {
AddCheckConstantFunction(holder, object, map);
if (FLAG_inline_accessors &&
- TryInlineSetter(setter, id, assignment_id, value)) {
+ TryInlineSetter(setter, ast_id, return_id, value)) {
return;
}
Drop(2);
@@ -5032,7 +4974,7 @@ void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
} else if (types != NULL && types->length() > 1) {
Drop(2);
return HandlePolymorphicStoreNamedField(
- expr->position(), id, object, value, types, name);
+ expr->position(), ast_id, object, value, types, name);
} else {
Drop(2);
instr = BuildStoreNamedGeneric(object, name, value);
@@ -5042,13 +4984,71 @@ void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
instr->set_position(expr->position());
AddInstruction(instr);
if (instr->HasObservableSideEffects()) {
- Add<HSimulate>(id, REMOVABLE_SIMULATE);
+ Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
}
if (!ast_context()->IsEffect()) Drop(1);
return ast_context()->ReturnValue(value);
}
+void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
+ Property* prop = expr->target()->AsProperty();
+ ASSERT(prop != NULL);
+ CHECK_ALIVE(VisitForValue(prop->obj()));
+ if (!prop->key()->IsPropertyName()) {
+ CHECK_ALIVE(VisitForValue(prop->key()));
+ }
+ CHECK_ALIVE(VisitForValue(expr->value()));
+ BuildStore(expr, prop, expr->id(),
+ expr->AssignmentId(), expr->IsUninitialized());
+}
+
+
+// Because not every expression has a position and there is not common
+// superclass of Assignment and CountOperation, we cannot just pass the
+// owning expression instead of position and ast_id separately.
+void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
+ Variable* var,
+ HValue* value,
+ int position,
+ BailoutId ast_id) {
+ LookupResult lookup(isolate());
+ GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
+ if (type == kUseCell) {
+ Handle<GlobalObject> global(current_info()->global_object());
+ Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
+ if (cell->type()->IsConstant()) {
+ IfBuilder builder(this);
+ HValue* constant = Add<HConstant>(cell->type()->AsConstant());
+ if (cell->type()->AsConstant()->IsNumber()) {
+ builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ);
+ } else {
+ builder.If<HCompareObjectEqAndBranch>(value, constant);
+ }
+ builder.Then();
+ builder.Else();
+ Add<HDeoptimize>("Constant global variable assignment",
+ Deoptimizer::EAGER);
+ builder.End();
+ }
+ HInstruction* instr =
+ Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
+ instr->set_position(position);
+ if (instr->HasObservableSideEffects()) {
+ Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
+ }
+ } else {
+ HGlobalObject* global_object = Add<HGlobalObject>();
+ HStoreGlobalGeneric* instr =
+ Add<HStoreGlobalGeneric>(global_object, var->name(),
+ value, function_strict_mode_flag());
+ instr->set_position(position);
+ ASSERT(instr->HasObservableSideEffects());
+ Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
+ }
+}
+
+
void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
Expression* target = expr->target();
VariableProxy* proxy = target->AsVariableProxy();
@@ -5130,62 +5130,30 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
return ast_context()->ReturnValue(Pop());
} else if (prop != NULL) {
- if (prop->key()->IsPropertyName()) {
- // Named property.
- CHECK_ALIVE(VisitForValue(prop->obj()));
- HValue* object = Top();
- CHECK_ALIVE(PushLoad(prop, object, expr->position()));
-
- CHECK_ALIVE(VisitForValue(expr->value()));
- HValue* right = Pop();
- HValue* left = Pop();
-
- HInstruction* instr = BuildBinaryOperation(operation, left, right);
- PushAndAdd(instr);
- if (instr->HasObservableSideEffects()) {
- Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
- }
-
- return BuildStoreNamed(
- expr, expr->id(), expr->AssignmentId(), prop, object, instr);
- } else {
- // Keyed property.
- CHECK_ALIVE(VisitForValue(prop->obj()));
+ CHECK_ALIVE(VisitForValue(prop->obj()));
+ HValue* object = Top();
+ HValue* key = NULL;
+ if ((!prop->IsStringLength() &&
+ !prop->IsFunctionPrototype() &&
+ !prop->key()->IsPropertyName()) ||
+ prop->IsStringAccess()) {
CHECK_ALIVE(VisitForValue(prop->key()));
- HValue* obj = environment()->ExpressionStackAt(1);
- HValue* key = environment()->ExpressionStackAt(0);
-
- bool has_side_effects = false;
- HValue* load = HandleKeyedElementAccess(
- obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition,
- false, // is_store
- &has_side_effects);
- Push(load);
- if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
-
- CHECK_ALIVE(VisitForValue(expr->value()));
- HValue* right = Pop();
- HValue* left = Pop();
-
- HInstruction* instr = BuildBinaryOperation(operation, left, right);
- PushAndAdd(instr);
- if (instr->HasObservableSideEffects()) {
- Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
- }
+ key = Top();
+ }
- HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
- RelocInfo::kNoPosition,
- true, // is_store
- &has_side_effects);
+ CHECK_ALIVE(PushLoad(prop, object, key, expr->position()));
- // Drop the simulated receiver, key, and value. Return the value.
- Drop(3);
- Push(instr);
- ASSERT(has_side_effects); // Stores always have side effects.
- Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
- return ast_context()->ReturnValue(Pop());
- }
+ CHECK_ALIVE(VisitForValue(expr->value()));
+ HValue* right = Pop();
+ HValue* left = Pop();
+ HInstruction* instr = BuildBinaryOperation(operation, left, right);
+ PushAndAdd(instr);
+ if (instr->HasObservableSideEffects()) {
+ Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
+ }
+ BuildStore(expr, prop, expr->id(),
+ expr->AssignmentId(), expr->IsUninitialized());
} else {
return Bailout(kInvalidLhsInCompoundAssignment);
}
@@ -5840,9 +5808,11 @@ bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
void HOptimizedGraphBuilder::PushLoad(Property* expr,
HValue* object,
+ HValue* key,
int position) {
ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
Push(object);
+ if (key != NULL) Push(key);
BuildLoad(expr, position, expr->LoadId());
}
@@ -5858,7 +5828,6 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr,
AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
instr = BuildLoadStringLength(string, checkstring);
} else if (expr->IsStringAccess()) {
- CHECK_ALIVE(VisitForValue(expr->key()));
HValue* index = Pop();
HValue* string = Pop();
HValue* context = environment()->context();
@@ -5902,8 +5871,6 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr,
}
} else {
- CHECK_ALIVE(VisitForValue(expr->key()));
-
HValue* key = Pop();
HValue* obj = Pop();
@@ -5936,6 +5903,13 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
if (TryArgumentsAccess(expr)) return;
CHECK_ALIVE(VisitForValue(expr->obj()));
+ if ((!expr->IsStringLength() &&
+ !expr->IsFunctionPrototype() &&
+ !expr->key()->IsPropertyName()) ||
+ expr->IsStringAccess()) {
+ CHECK_ALIVE(VisitForValue(expr->key()));
+ }
+
BuildLoad(expr, expr->position(), expr->id());
}
@@ -7478,16 +7452,18 @@ HInstruction* HOptimizedGraphBuilder::BuildIncrement(
}
-void HOptimizedGraphBuilder::BuildStoreInEffect(Expression* expr,
- Property* prop,
- BailoutId ast_id,
- BailoutId return_id,
- HValue* object,
- HValue* value) {
+void HOptimizedGraphBuilder::BuildStoreForEffect(Expression* expr,
+ Property* prop,
+ BailoutId ast_id,
+ BailoutId return_id,
+ HValue* object,
+ HValue* key,
+ HValue* value) {
EffectContext for_effect(this);
Push(object);
+ if (key != NULL) Push(key);
Push(value);
- BuildStoreNamed(expr, ast_id, return_id, prop, object, value);
+ BuildStore(expr, prop, ast_id, return_id);
}
@@ -7567,69 +7543,42 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
return Bailout(kLookupVariableInCountOperation);
}
- } else {
- // Argument of the count operation is a property.
- ASSERT(prop != NULL);
+ Drop(returns_original_input ? 2 : 1);
+ return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
+ }
- if (prop->key()->IsPropertyName()) {
- // Named property.
- if (returns_original_input) Push(graph()->GetConstantUndefined());
+ // Argument of the count operation is a property.
+ ASSERT(prop != NULL);
+ if (returns_original_input) Push(graph()->GetConstantUndefined());
- CHECK_ALIVE(VisitForValue(prop->obj()));
- HValue* object = Top();
- CHECK_ALIVE(PushLoad(prop, object, expr->position()));
+ CHECK_ALIVE(VisitForValue(prop->obj()));
+ HValue* object = Top();
- after = BuildIncrement(returns_original_input, expr);
+ HValue* key = NULL;
+ if ((!prop->IsStringLength() &&
+ !prop->IsFunctionPrototype() &&
+ !prop->key()->IsPropertyName()) ||
+ prop->IsStringAccess()) {
+ CHECK_ALIVE(VisitForValue(prop->key()));
+ key = Top();
+ }
- if (returns_original_input) {
- HValue* result = Pop();
- HValue* object = Pop();
- environment()->SetExpressionStackAt(0, result);
- CHECK_ALIVE(BuildStoreInEffect(
- expr, prop, expr->id(), expr->AssignmentId(), object, after));
- return ast_context()->ReturnValue(Pop());
- }
+ CHECK_ALIVE(PushLoad(prop, object, key, expr->position()));
- return BuildStoreNamed(
- expr, expr->id(), expr->AssignmentId(), prop, object, after);
- } else {
- // Keyed property.
- if (returns_original_input) Push(graph()->GetConstantUndefined());
+ after = BuildIncrement(returns_original_input, expr);
- CHECK_ALIVE(VisitForValue(prop->obj()));
- CHECK_ALIVE(VisitForValue(prop->key()));
- HValue* obj = environment()->ExpressionStackAt(1);
- HValue* key = environment()->ExpressionStackAt(0);
-
- bool has_side_effects = false;
- HValue* load = HandleKeyedElementAccess(
- obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition,
- false, // is_store
- &has_side_effects);
- Push(load);
- if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
-
- after = BuildIncrement(returns_original_input, expr);
- input = environment()->ExpressionStackAt(0);
-
- HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(),
- RelocInfo::kNoPosition,
- true, // is_store
- &has_side_effects);
-
- // Drop the key and the original value from the bailout environment.
- // Overwrite the receiver with the result of the operation, and the
- // placeholder with the original value if necessary.
- Drop(2);
- environment()->SetExpressionStackAt(0, after);
- if (returns_original_input) environment()->SetExpressionStackAt(1, input);
- ASSERT(has_side_effects); // Stores always have side effects.
- Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
- }
+ if (returns_original_input) {
+ input = Pop();
+ // Drop object and key to push it again in the effect context below.
+ Drop(key == NULL ? 1 : 2);
+ environment()->SetExpressionStackAt(0, input);
+ CHECK_ALIVE(BuildStoreForEffect(
+ expr, prop, expr->id(), expr->AssignmentId(), object, key, after));
+ return ast_context()->ReturnValue(Pop());
}
- Drop(returns_original_input ? 2 : 1);
- return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
+ environment()->SetExpressionStackAt(0, after);
+ return BuildStore(expr, prop, expr->id(), expr->AssignmentId());
}
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698