Chromium Code Reviews| Index: src/compiler/ast-graph-builder.cc |
| diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc |
| index c7b2c93b2b6836f16c251e393fa4a589d341e9d0..38f2514bd816b199c587d4d13dcee76d02b5f822 100644 |
| --- a/src/compiler/ast-graph-builder.cc |
| +++ b/src/compiler/ast-graph-builder.cc |
| @@ -1351,7 +1351,9 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| test_value.Else(); |
| { |
| // Bind value and do loop body. |
| - VisitForInAssignment(stmt->each(), value, stmt->AssignmentId()); |
| + VisitForInAssignment(stmt->each(), value, |
| + ResolveFeedbackSlot(stmt->EachFeedbackSlot()), |
|
Michael Starzinger
2015/06/15 14:20:11
nit: Please pull into local variable for consisten
mvstanton
2015/06/21 13:37:35
Done.
|
| + stmt->AssignmentId()); |
| VisitIterationBody(stmt, &for_loop); |
| } |
| test_value.End(); |
| @@ -1571,6 +1573,7 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { |
| environment()->Push(proto); |
| // Create nodes to store method values into the literal. |
| + int store_slot_index = 0; |
| for (int i = 0; i < expr->properties()->length(); i++) { |
| ObjectLiteral::Property* property = expr->properties()->at(i); |
| environment()->Push(property->is_static() ? literal : proto); |
| @@ -1593,7 +1596,9 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { |
| Node* value = environment()->Pop(); |
| Node* key = environment()->Pop(); |
| Node* receiver = environment()->Pop(); |
| - BuildSetHomeObject(value, receiver, property->value()); |
| + ResolvedFeedbackSlot slot = ResolveFeedbackSlot( |
| + expr->SlotForHomeObject(property->value(), &store_slot_index)); |
| + BuildSetHomeObject(value, receiver, property->value(), slot); |
| switch (property->kind()) { |
| case ObjectLiteral::Property::CONSTANT: |
| @@ -1633,8 +1638,12 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { |
| DCHECK_NOT_NULL(expr->class_variable_proxy()); |
| Variable* var = expr->class_variable_proxy()->var(); |
| FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| - BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None(), |
| - states); |
| + ResolvedFeedbackSlot slot = |
| + ResolveFeedbackSlot(FLAG_vector_stores |
| + ? expr->GetNthSlot(store_slot_index++) |
| + : FeedbackVectorICSlot::Invalid()); |
| + BuildVariableAssignment(var, literal, Token::INIT_CONST, slot, |
| + BailoutId::None(), states); |
| } |
| ast_context()->ProduceValue(literal); |
| @@ -1712,6 +1721,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| // Create nodes to store computed values into the literal. |
| int property_index = 0; |
| + int store_slot_index = 0; |
| AccessorTable accessor_table(zone()); |
| for (; property_index < expr->properties()->length(); property_index++) { |
| ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| @@ -1734,11 +1744,17 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| FrameStateBeforeAndAfter states(this, property->value()->id()); |
| Node* value = environment()->Pop(); |
| Handle<Name> name = key->AsPropertyName(); |
| - Node* store = |
| - BuildNamedStore(literal, name, value, TypeFeedbackId::None()); |
| + ResolvedFeedbackSlot slot = |
| + FLAG_vector_stores |
| + ? ResolveFeedbackSlot(expr->GetNthSlot(store_slot_index++)) |
| + : ResolvedFeedbackSlot(); |
| + Node* store = BuildNamedStore(literal, name, value, slot, |
| + TypeFeedbackId::None()); |
| states.AddToNode(store, key->id(), |
| OutputFrameStateCombine::Ignore()); |
| - BuildSetHomeObject(value, literal, property->value()); |
| + ResolvedFeedbackSlot home_slot = ResolveFeedbackSlot( |
| + expr->SlotForHomeObject(property->value(), &store_slot_index)); |
| + BuildSetHomeObject(value, literal, property->value(), home_slot); |
| } else { |
| VisitForEffect(property->value()); |
| } |
| @@ -1757,7 +1773,9 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| Node* set_property = NewNode(op, receiver, key, value, language); |
| // SetProperty should not lazy deopt on an object literal. |
| PrepareFrameState(set_property, BailoutId::None()); |
| - BuildSetHomeObject(value, receiver, property->value()); |
| + ResolvedFeedbackSlot home_slot = ResolveFeedbackSlot( |
| + expr->SlotForHomeObject(property->value(), &store_slot_index)); |
| + BuildSetHomeObject(value, receiver, property->value(), home_slot); |
| } |
| break; |
| } |
| @@ -1793,9 +1811,15 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| it != accessor_table.end(); ++it) { |
| VisitForValue(it->first); |
| VisitForValueOrNull(it->second->getter); |
| - BuildSetHomeObject(environment()->Top(), literal, it->second->getter); |
| + ResolvedFeedbackSlot slot_getter = ResolveFeedbackSlot( |
| + expr->SlotForHomeObject(it->second->getter, &store_slot_index)); |
| + BuildSetHomeObject(environment()->Top(), literal, it->second->getter, |
| + slot_getter); |
| VisitForValueOrNull(it->second->setter); |
| - BuildSetHomeObject(environment()->Top(), literal, it->second->setter); |
| + ResolvedFeedbackSlot slot_setter = ResolveFeedbackSlot( |
| + expr->SlotForHomeObject(it->second->getter, &store_slot_index)); |
| + BuildSetHomeObject(environment()->Top(), literal, it->second->setter, |
| + slot_setter); |
| Node* setter = environment()->Pop(); |
| Node* getter = environment()->Pop(); |
| Node* name = environment()->Pop(); |
| @@ -1840,8 +1864,9 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| Node* value = environment()->Pop(); |
| Node* key = environment()->Pop(); |
| Node* receiver = environment()->Pop(); |
| - BuildSetHomeObject(value, receiver, property->value()); |
| - |
| + ResolvedFeedbackSlot slot = ResolveFeedbackSlot( |
| + expr->SlotForHomeObject(property->value(), &store_slot_index)); |
| + BuildSetHomeObject(value, receiver, property->value(), slot); |
| switch (property->kind()) { |
| case ObjectLiteral::Property::CONSTANT: |
| case ObjectLiteral::Property::COMPUTED: |
| @@ -1882,6 +1907,10 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| NewNode(op, literal); |
| } |
| + // Verify that compilation exactly consumed the number of store ic slots that |
| + // the ObjectLiteral node had to offer. |
| + DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count()); |
| + |
| ast_context()->ProduceValue(environment()->Pop()); |
| } |
| @@ -1919,8 +1948,11 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| FrameStateBeforeAndAfter states(this, subexpr->id()); |
| Node* value = environment()->Pop(); |
| Node* index = jsgraph()->Constant(array_index); |
| + // TODO(mvstanton): this should be a runtime call. We can't use an |
| + // IC unless we have it in full code as well. |
|
Michael Starzinger
2015/06/15 14:20:11
As discussed offline: It's not the responsibility
mvstanton
2015/06/21 13:37:35
Done.
|
| Node* store = |
| - BuildKeyedStore(literal, index, value, TypeFeedbackId::None()); |
| + BuildKeyedStore(literal, index, value, ResolvedFeedbackSlot(), |
| + TypeFeedbackId::None()); |
| states.AddToNode(store, expr->GetIdForElement(array_index), |
| OutputFrameStateCombine::Ignore()); |
| } |
| @@ -1964,6 +1996,7 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value, |
| + const ResolvedFeedbackSlot& slot, |
| BailoutId bailout_id) { |
| DCHECK(expr->IsValidReferenceExpression()); |
| @@ -1976,7 +2009,8 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value, |
| case VARIABLE: { |
| Variable* var = expr->AsVariableProxy()->var(); |
| FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| - BuildVariableAssignment(var, value, Token::ASSIGN, bailout_id, states); |
| + BuildVariableAssignment(var, value, Token::ASSIGN, slot, bailout_id, |
| + states); |
| break; |
| } |
| case NAMED_PROPERTY: { |
| @@ -1987,7 +2021,7 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value, |
| value = environment()->Pop(); |
| Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| Node* store = |
| - BuildNamedStore(object, name, value, TypeFeedbackId::None()); |
| + BuildNamedStore(object, name, value, slot, TypeFeedbackId::None()); |
| states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore()); |
| break; |
| } |
| @@ -1999,7 +2033,8 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value, |
| Node* key = environment()->Pop(); |
| Node* object = environment()->Pop(); |
| value = environment()->Pop(); |
| - Node* store = BuildKeyedStore(object, key, value, TypeFeedbackId::None()); |
| + Node* store = |
| + BuildKeyedStore(object, key, value, slot, TypeFeedbackId::None()); |
| states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore()); |
| break; |
| } |
| @@ -2161,18 +2196,19 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
| FrameStateBeforeAndAfter store_states(this, before_store_id); |
| // Store the value. |
| Node* value = environment()->Pop(); |
| + ResolvedFeedbackSlot slot = ResolveFeedbackSlot(expr->AssignmentSlot()); |
| switch (assign_type) { |
| case VARIABLE: { |
| Variable* variable = expr->target()->AsVariableProxy()->var(); |
| - BuildVariableAssignment(variable, value, expr->op(), expr->id(), |
| + BuildVariableAssignment(variable, value, expr->op(), slot, expr->id(), |
| store_states, ast_context()->GetStateCombine()); |
| break; |
| } |
| case NAMED_PROPERTY: { |
| Node* object = environment()->Pop(); |
| Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| - Node* store = |
| - BuildNamedStore(object, name, value, expr->AssignmentFeedbackId()); |
| + Node* store = BuildNamedStore(object, name, value, slot, |
| + expr->AssignmentFeedbackId()); |
| store_states.AddToNode(store, expr->id(), |
| ast_context()->GetStateCombine()); |
| break; |
| @@ -2180,8 +2216,8 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
| case KEYED_PROPERTY: { |
| Node* key = environment()->Pop(); |
| Node* object = environment()->Pop(); |
| - Node* store = |
| - BuildKeyedStore(object, key, value, expr->AssignmentFeedbackId()); |
| + Node* store = BuildKeyedStore(object, key, value, slot, |
| + expr->AssignmentFeedbackId()); |
| store_states.AddToNode(store, expr->id(), |
| ast_context()->GetStateCombine()); |
| break; |
| @@ -2649,20 +2685,21 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| } |
| // Store the value. |
| + ResolvedFeedbackSlot slot = ResolveFeedbackSlot(expr->CountSlot()); |
| switch (assign_type) { |
| case VARIABLE: { |
| Variable* variable = expr->expression()->AsVariableProxy()->var(); |
| environment()->Push(value); |
| - BuildVariableAssignment(variable, value, expr->op(), expr->AssignmentId(), |
| - store_states); |
| + BuildVariableAssignment(variable, value, expr->op(), slot, |
| + expr->AssignmentId(), store_states); |
| environment()->Pop(); |
| break; |
| } |
| case NAMED_PROPERTY: { |
| Node* object = environment()->Pop(); |
| Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| - Node* store = |
| - BuildNamedStore(object, name, value, expr->CountStoreFeedbackId()); |
| + Node* store = BuildNamedStore(object, name, value, slot, |
| + expr->CountStoreFeedbackId()); |
| environment()->Push(value); |
| store_states.AddToNode(store, expr->AssignmentId(), |
| OutputFrameStateCombine::Ignore()); |
| @@ -2672,8 +2709,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| case KEYED_PROPERTY: { |
| Node* key = environment()->Pop(); |
| Node* object = environment()->Pop(); |
| - Node* store = |
| - BuildKeyedStore(object, key, value, expr->CountStoreFeedbackId()); |
| + Node* store = BuildKeyedStore(object, key, value, slot, |
| + expr->CountStoreFeedbackId()); |
| environment()->Push(value); |
| store_states.AddToNode(store, expr->AssignmentId(), |
| OutputFrameStateCombine::Ignore()); |
| @@ -3105,8 +3142,9 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { |
| DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); |
| // This should never lazy deopt, so it is fine to send invalid bailout id. |
| FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| - BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None(), |
| - states); |
| + ResolvedFeedbackSlot slot; |
| + BuildVariableAssignment(arguments, object, Token::ASSIGN, slot, |
| + BailoutId::None(), states); |
| return object; |
| } |
| @@ -3124,7 +3162,8 @@ Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) { |
| DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); |
| // This should never lazy deopt, so it is fine to send invalid bailout id. |
| FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| - BuildVariableAssignment(rest, object, Token::ASSIGN, BailoutId::None(), |
| + ResolvedFeedbackSlot slot; |
| + BuildVariableAssignment(rest, object, Token::ASSIGN, slot, BailoutId::None(), |
| states); |
| return object; |
| @@ -3136,8 +3175,9 @@ Node* AstGraphBuilder::BuildThisFunctionVar(Variable* this_function_var) { |
| Node* this_function = GetFunctionClosure(); |
| FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| + ResolvedFeedbackSlot slot; |
| BuildVariableAssignment(this_function_var, this_function, Token::INIT_CONST, |
| - BailoutId::None(), states); |
| + slot, BailoutId::None(), states); |
| return this_function; |
| } |
| @@ -3321,7 +3361,8 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, |
| Node* AstGraphBuilder::BuildVariableAssignment( |
| - Variable* variable, Node* value, Token::Value op, BailoutId bailout_id, |
| + Variable* variable, Node* value, Token::Value op, |
| + const ResolvedFeedbackSlot& slot, BailoutId bailout_id, |
| FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) { |
| Node* the_hole = jsgraph()->TheHoleConstant(); |
| VariableMode mode = variable->mode(); |
| @@ -3331,7 +3372,7 @@ Node* AstGraphBuilder::BuildVariableAssignment( |
| Node* global = BuildLoadGlobalObject(); |
| Handle<Name> name = variable->name(); |
| Node* store = |
| - BuildNamedStore(global, name, value, TypeFeedbackId::None()); |
| + BuildNamedStore(global, name, value, slot, TypeFeedbackId::None()); |
| states.AddToNode(store, bailout_id, combine); |
| return store; |
| } |
| @@ -3464,16 +3505,19 @@ Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name, |
| Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value, |
| + const ResolvedFeedbackSlot& feedback, |
| TypeFeedbackId id) { |
| - const Operator* op = javascript()->StoreProperty(language_mode()); |
| + const Operator* op = javascript()->StoreProperty(language_mode(), feedback); |
| return Record(js_type_feedback_, NewNode(op, object, key, value), id); |
| } |
| Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name, |
| - Node* value, TypeFeedbackId id) { |
| + Node* value, |
| + const ResolvedFeedbackSlot& feedback, |
| + TypeFeedbackId id) { |
| const Operator* op = |
| - javascript()->StoreNamed(language_mode(), MakeUnique(name)); |
| + javascript()->StoreNamed(language_mode(), feedback, MakeUnique(name)); |
| return Record(js_type_feedback_, NewNode(op, object, value), id); |
| } |
| @@ -3612,12 +3656,13 @@ Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) { |
| Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object, |
| - Expression* expr) { |
| + Expression* expr, |
| + const ResolvedFeedbackSlot& slot) { |
| if (!FunctionLiteral::NeedsHomeObject(expr)) return value; |
| Handle<Name> name = isolate()->factory()->home_object_symbol(); |
| FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| Node* store = |
| - BuildNamedStore(value, name, home_object, TypeFeedbackId::None()); |
| + BuildNamedStore(value, name, home_object, slot, TypeFeedbackId::None()); |
| states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore()); |
| return store; |
| } |