| Index: src/compiler/ast-graph-builder.cc
|
| diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
|
| index d5ee9c5f894bf93bea19cf76bd6515bacac28f88..22ef8518249f825d5abf93fc5518c535b61af302 100644
|
| --- a/src/compiler/ast-graph-builder.cc
|
| +++ b/src/compiler/ast-graph-builder.cc
|
| @@ -1365,7 +1365,9 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
| test_value.Else();
|
| {
|
| // Bind value and do loop body.
|
| - VisitForInAssignment(stmt->each(), value, stmt->AssignmentId());
|
| + ResolvedFeedbackSlot slot =
|
| + ResolveFeedbackSlot(stmt->EachFeedbackSlot());
|
| + VisitForInAssignment(stmt->each(), value, slot, stmt->AssignmentId());
|
| VisitIterationBody(stmt, &for_loop);
|
| }
|
| test_value.End();
|
| @@ -1586,6 +1588,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);
|
| @@ -1608,7 +1611,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:
|
| @@ -1648,8 +1653,11 @@ 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);
|
| @@ -1727,6 +1735,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);
|
| @@ -1749,11 +1758,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());
|
| }
|
| @@ -1772,7 +1787,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;
|
| }
|
| @@ -1808,9 +1825,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();
|
| @@ -1855,8 +1878,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:
|
| @@ -1897,6 +1921,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());
|
| }
|
|
|
| @@ -1935,7 +1963,8 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
| Node* value = environment()->Pop();
|
| Node* index = jsgraph()->Constant(array_index);
|
| Node* store =
|
| - BuildKeyedStore(literal, index, value, TypeFeedbackId::None());
|
| + BuildKeyedStore(literal, index, value, ResolvedFeedbackSlot(),
|
| + TypeFeedbackId::None());
|
| states.AddToNode(store, expr->GetIdForElement(array_index),
|
| OutputFrameStateCombine::Ignore());
|
| }
|
| @@ -1979,6 +2008,7 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
|
|
|
|
| void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
|
| + const ResolvedFeedbackSlot& slot,
|
| BailoutId bailout_id) {
|
| DCHECK(expr->IsValidReferenceExpression());
|
|
|
| @@ -1991,7 +2021,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: {
|
| @@ -2002,7 +2033,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;
|
| }
|
| @@ -2014,7 +2045,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;
|
| }
|
| @@ -2176,18 +2208,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;
|
| @@ -2195,8 +2228,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;
|
| @@ -2647,20 +2680,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());
|
| @@ -2670,8 +2704,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());
|
| @@ -3112,8 +3146,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;
|
| }
|
| @@ -3131,7 +3166,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;
|
| @@ -3143,8 +3179,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;
|
| }
|
|
|
| @@ -3329,7 +3366,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();
|
| @@ -3339,7 +3377,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;
|
| }
|
| @@ -3472,16 +3510,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(), MakeUnique(name), feedback);
|
| return Record(js_type_feedback_, NewNode(op, object, value), id);
|
| }
|
|
|
| @@ -3626,12 +3667,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;
|
| }
|
|
|