Index: src/compiler/ast-graph-builder.cc |
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc |
index a200c701935333f40953e1728b4835205054b48d..d53d2c347a6a24f8d16c066af1f49c2557f6d8d3 100644 |
--- a/src/compiler/ast-graph-builder.cc |
+++ b/src/compiler/ast-graph-builder.cc |
@@ -563,8 +563,10 @@ void AstGraphBuilder::CreateGraphBody(bool stack_check) { |
Variable* rest_parameter = scope->rest_parameter(&rest_index); |
BuildRestArgumentsArray(rest_parameter, rest_index); |
- if (scope->this_function_var() != nullptr || |
- scope->new_target_var() != nullptr) { |
+ // Build .this_function var if it is used. |
+ BuildThisFunctionVar(scope->this_function_var()); |
+ |
+ if (scope->new_target_var() != nullptr) { |
SetStackOverflow(); |
} |
@@ -630,22 +632,6 @@ void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() { |
} |
-// Left-hand side can only be a property, a global or a variable slot. |
-enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
- |
- |
-// Determine the left-hand side kind of an assignment. |
-static LhsKind DetermineLhsKind(Expression* expr) { |
- Property* property = expr->AsProperty(); |
- DCHECK(expr->IsValidReferenceExpression()); |
- LhsKind lhs_kind = |
- (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) |
- ? NAMED_PROPERTY |
- : KEYED_PROPERTY; |
- return lhs_kind; |
-} |
- |
- |
// Gets the bailout id just before reading a variable proxy, but only for |
// unallocated variables. |
static BailoutId BeforeId(VariableProxy* proxy) { |
@@ -1971,7 +1957,7 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value, |
// Left-hand side can only be a property, a global or a variable slot. |
Property* property = expr->AsProperty(); |
- LhsKind assign_type = DetermineLhsKind(expr); |
+ LhsKind assign_type = Property::GetAssignType(property); |
// Evaluate LHS expression and store the value. |
switch (assign_type) { |
@@ -2005,6 +1991,35 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value, |
states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore()); |
break; |
} |
+ case NAMED_SUPER_PROPERTY: { |
+ environment()->Push(value); |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->this_var()); |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->home_object()); |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
+ Node* home_object = environment()->Pop(); |
+ Node* receiver = environment()->Pop(); |
+ value = environment()->Pop(); |
+ Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
+ Node* store = BuildNamedSuperStore(receiver, home_object, name, value, |
+ TypeFeedbackId::None()); |
+ states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore()); |
+ break; |
+ } |
+ case KEYED_SUPER_PROPERTY: { |
+ environment()->Push(value); |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->this_var()); |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->home_object()); |
+ VisitForValue(property->key()); |
+ FrameStateBeforeAndAfter states(this, property->key()->id()); |
+ Node* key = environment()->Pop(); |
+ Node* home_object = environment()->Pop(); |
+ Node* receiver = environment()->Pop(); |
+ value = environment()->Pop(); |
+ Node* store = BuildKeyedSuperStore(receiver, home_object, key, value, |
+ TypeFeedbackId::None()); |
+ states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore()); |
+ break; |
+ } |
} |
} |
@@ -2014,7 +2029,7 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
// Left-hand side can only be a property, a global or a variable slot. |
Property* property = expr->target()->AsProperty(); |
- LhsKind assign_type = DetermineLhsKind(expr->target()); |
+ LhsKind assign_type = Property::GetAssignType(property); |
bool needs_frame_state_before = true; |
// Evaluate LHS expression. |
@@ -2031,11 +2046,19 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
case NAMED_PROPERTY: |
VisitForValue(property->obj()); |
break; |
- case KEYED_PROPERTY: { |
+ case KEYED_PROPERTY: |
VisitForValue(property->obj()); |
VisitForValue(property->key()); |
break; |
- } |
+ case NAMED_SUPER_PROPERTY: |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->this_var()); |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->home_object()); |
+ break; |
+ case KEYED_SUPER_PROPERTY: |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->this_var()); |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->home_object()); |
+ VisitForValue(property->key()); |
+ break; |
} |
BailoutId before_store_id = BailoutId::None(); |
@@ -2076,6 +2099,30 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
OutputFrameStateCombine::Push()); |
break; |
} |
+ case NAMED_SUPER_PROPERTY: { |
+ Node* home_object = environment()->Top(); |
+ Node* receiver = environment()->Peek(1); |
+ Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
+ VectorSlotPair pair = |
+ CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
+ old_value = BuildNamedSuperLoad(receiver, home_object, name, pair); |
+ states.AddToNode(old_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
+ break; |
+ } |
+ case KEYED_SUPER_PROPERTY: { |
+ Node* key = environment()->Top(); |
+ Node* home_object = environment()->Peek(1); |
+ Node* receiver = environment()->Peek(2); |
+ VectorSlotPair pair = |
+ CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
+ FrameStateBeforeAndAfter states(this, property->key()->id()); |
+ old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair); |
+ states.AddToNode(old_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
+ break; |
+ } |
} |
environment()->Push(old_value); |
VisitForValue(expr->value()); |
@@ -2127,6 +2174,26 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
ast_context()->GetStateCombine()); |
break; |
} |
+ case NAMED_SUPER_PROPERTY: { |
+ Node* home_object = environment()->Pop(); |
+ Node* receiver = environment()->Pop(); |
+ Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
+ Node* store = BuildNamedSuperStore(receiver, home_object, name, value, |
+ expr->AssignmentFeedbackId()); |
+ store_states.AddToNode(store, expr->id(), |
+ ast_context()->GetStateCombine()); |
+ break; |
+ } |
+ case KEYED_SUPER_PROPERTY: { |
+ Node* key = environment()->Pop(); |
+ Node* home_object = environment()->Pop(); |
+ Node* receiver = environment()->Pop(); |
+ Node* store = BuildKeyedSuperStore(receiver, home_object, key, value, |
+ expr->AssignmentFeedbackId()); |
+ store_states.AddToNode(store, expr->id(), |
+ ast_context()->GetStateCombine()); |
+ break; |
+ } |
} |
ast_context()->ProduceValue(value); |
@@ -2150,22 +2217,55 @@ void AstGraphBuilder::VisitThrow(Throw* expr) { |
void AstGraphBuilder::VisitProperty(Property* expr) { |
Node* value; |
brucedawson
2015/06/08 17:24:50
It is not clear that 'value' will always be initia
|
+ LhsKind property_kind = Property::GetAssignType(expr); |
VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot()); |
- if (expr->key()->IsPropertyName()) { |
- VisitForValue(expr->obj()); |
- FrameStateBeforeAndAfter states(this, expr->obj()->id()); |
- Node* object = environment()->Pop(); |
- Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName(); |
- value = BuildNamedLoad(object, name, pair); |
- states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
- } else { |
- VisitForValue(expr->obj()); |
- VisitForValue(expr->key()); |
- FrameStateBeforeAndAfter states(this, expr->key()->id()); |
- Node* key = environment()->Pop(); |
- Node* object = environment()->Pop(); |
- value = BuildKeyedLoad(object, key, pair); |
- states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
+ switch (property_kind) { |
+ case VARIABLE: |
+ UNREACHABLE(); |
+ value = nullptr; |
brucedawson
2015/06/08 17:24:50
i.e.; move this assignment to the variable declara
|
+ break; |
+ case NAMED_PROPERTY: { |
+ VisitForValue(expr->obj()); |
+ FrameStateBeforeAndAfter states(this, expr->obj()->id()); |
+ Node* object = environment()->Pop(); |
+ Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName(); |
+ value = BuildNamedLoad(object, name, pair); |
+ states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
+ break; |
+ } |
+ case KEYED_PROPERTY: { |
+ VisitForValue(expr->obj()); |
+ VisitForValue(expr->key()); |
+ FrameStateBeforeAndAfter states(this, expr->key()->id()); |
+ Node* key = environment()->Pop(); |
+ Node* object = environment()->Pop(); |
+ value = BuildKeyedLoad(object, key, pair); |
+ states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
+ break; |
+ } |
+ case NAMED_SUPER_PROPERTY: { |
+ VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var()); |
+ VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object()); |
+ FrameStateBeforeAndAfter states(this, expr->obj()->id()); |
+ Node* home_object = environment()->Pop(); |
+ Node* receiver = environment()->Pop(); |
+ Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName(); |
+ value = BuildNamedSuperLoad(receiver, home_object, name, pair); |
+ states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
+ break; |
+ } |
+ case KEYED_SUPER_PROPERTY: { |
+ VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var()); |
+ VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object()); |
+ VisitForValue(expr->key()); |
+ FrameStateBeforeAndAfter states(this, expr->key()->id()); |
+ Node* key = environment()->Pop(); |
+ Node* home_object = environment()->Pop(); |
+ Node* receiver = environment()->Pop(); |
+ value = BuildKeyedSuperLoad(receiver, home_object, key, pair); |
+ states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
+ break; |
+ } |
} |
ast_context()->ProduceValue(value); |
} |
@@ -2208,29 +2308,58 @@ void AstGraphBuilder::VisitCall(Call* expr) { |
} |
case Call::PROPERTY_CALL: { |
Property* property = callee->AsProperty(); |
- VisitForValue(property->obj()); |
- Node* object = environment()->Top(); |
VectorSlotPair pair = |
CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
- if (property->key()->IsPropertyName()) { |
- FrameStateBeforeAndAfter states(this, property->obj()->id()); |
- Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
- callee_value = BuildNamedLoad(object, name, pair); |
- states.AddToNode(callee_value, property->LoadId(), |
- OutputFrameStateCombine::Push()); |
+ if (!property->IsSuperAccess()) { |
Michael Starzinger
2015/06/05 13:28:19
Could this be modeled as a switch over the LhsKind
arv (Not doing code reviews)
2015/06/05 13:50:26
I tried it but reverted back to the ifs. I found t
Michael Starzinger
2015/06/05 13:53:23
Acknowledged. OK, then let's leave it as it is.
|
+ VisitForValue(property->obj()); |
+ Node* object = environment()->Top(); |
+ |
+ if (property->key()->IsPropertyName()) { |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
+ Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
+ callee_value = BuildNamedLoad(object, name, pair); |
+ states.AddToNode(callee_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
+ } else { |
+ VisitForValue(property->key()); |
+ FrameStateBeforeAndAfter states(this, property->key()->id()); |
+ Node* key = environment()->Pop(); |
+ callee_value = BuildKeyedLoad(object, key, pair); |
+ states.AddToNode(callee_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
+ } |
+ receiver_value = environment()->Pop(); |
+ // Note that a PROPERTY_CALL requires the receiver to be wrapped into an |
+ // object for sloppy callees. This could also be modeled explicitly |
+ // here, |
+ // thereby obsoleting the need for a flag to the call operator. |
+ flags = CALL_AS_METHOD; |
+ |
} else { |
- VisitForValue(property->key()); |
- FrameStateBeforeAndAfter states(this, property->key()->id()); |
- Node* key = environment()->Pop(); |
- callee_value = BuildKeyedLoad(object, key, pair); |
- states.AddToNode(callee_value, property->LoadId(), |
- OutputFrameStateCombine::Push()); |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->this_var()); |
+ VisitForValue( |
+ property->obj()->AsSuperPropertyReference()->home_object()); |
+ Node* home_object = environment()->Pop(); |
+ receiver_value = environment()->Pop(); |
+ if (property->key()->IsPropertyName()) { |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
+ Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
+ callee_value = |
+ BuildNamedSuperLoad(receiver_value, home_object, name, pair); |
+ states.AddToNode(callee_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
+ |
+ } else { |
+ VisitForValue(property->key()); |
+ FrameStateBeforeAndAfter states(this, property->key()->id()); |
+ Node* key = environment()->Pop(); |
+ callee_value = |
+ BuildKeyedSuperLoad(receiver_value, home_object, key, pair); |
+ states.AddToNode(callee_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
+ } |
} |
- receiver_value = environment()->Pop(); |
- // Note that a PROPERTY_CALL requires the receiver to be wrapped into an |
- // object for sloppy callees. This could also be modeled explicitly here, |
- // thereby obsoleting the need for a flag to the call operator. |
- flags = CALL_AS_METHOD; |
+ |
break; |
} |
case Call::SUPER_CALL: |
@@ -2400,7 +2529,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { |
// Left-hand side can only be a property, a global or a variable slot. |
Property* property = expr->expression()->AsProperty(); |
- LhsKind assign_type = DetermineLhsKind(expr->expression()); |
+ LhsKind assign_type = Property::GetAssignType(property); |
// Reserve space for result of postfix operation. |
bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect(); |
@@ -2447,6 +2576,37 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { |
stack_depth = 2; |
break; |
} |
+ case NAMED_SUPER_PROPERTY: { |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->this_var()); |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->home_object()); |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
+ Node* home_object = environment()->Top(); |
+ Node* receiver = environment()->Peek(1); |
+ Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
+ VectorSlotPair pair = |
+ CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
+ old_value = BuildNamedSuperLoad(receiver, home_object, name, pair); |
+ states.AddToNode(old_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
+ stack_depth = 2; |
+ break; |
+ } |
+ case KEYED_SUPER_PROPERTY: { |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->this_var()); |
+ VisitForValue(property->obj()->AsSuperPropertyReference()->home_object()); |
+ VisitForValue(property->key()); |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
+ Node* key = environment()->Top(); |
+ Node* home_object = environment()->Peek(1); |
+ Node* receiver = environment()->Peek(2); |
+ VectorSlotPair pair = |
+ CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
+ old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair); |
+ states.AddToNode(old_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
+ stack_depth = 3; |
+ break; |
+ } |
} |
// Convert old value into a number. |
@@ -2506,6 +2666,30 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { |
environment()->Pop(); |
break; |
} |
+ case NAMED_SUPER_PROPERTY: { |
+ Node* home_object = environment()->Pop(); |
+ Node* receiver = environment()->Pop(); |
+ Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
+ Node* store = BuildNamedSuperStore(receiver, home_object, name, value, |
+ expr->CountStoreFeedbackId()); |
+ environment()->Push(value); |
+ store_states.AddToNode(store, expr->AssignmentId(), |
+ OutputFrameStateCombine::Ignore()); |
+ environment()->Pop(); |
+ break; |
+ } |
+ case KEYED_SUPER_PROPERTY: { |
+ Node* key = environment()->Pop(); |
+ Node* home_object = environment()->Pop(); |
+ Node* receiver = environment()->Pop(); |
+ Node* store = BuildKeyedSuperStore(receiver, home_object, key, value, |
+ expr->CountStoreFeedbackId()); |
+ environment()->Push(value); |
+ store_states.AddToNode(store, expr->AssignmentId(), |
+ OutputFrameStateCombine::Ignore()); |
+ environment()->Pop(); |
+ break; |
+ } |
} |
// Restore old value for postfix expressions. |
@@ -2931,6 +3115,17 @@ Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) { |
} |
+Node* AstGraphBuilder::BuildThisFunctionVar(Variable* this_function_var) { |
+ if (this_function_var == nullptr) return nullptr; |
+ |
+ Node* this_function = GetFunctionClosure(); |
+ FrameStateBeforeAndAfter states(this, BailoutId::None()); |
+ BuildVariableAssignment(this_function_var, this_function, Token::INIT_CONST, |
+ BailoutId::None(), states); |
+ return this_function; |
+} |
+ |
+ |
Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole, |
Node* not_hole) { |
Node* the_hole = jsgraph()->TheHoleConstant(); |
@@ -3257,6 +3452,51 @@ Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name, |
} |
+Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object, |
+ Handle<Name> name, |
+ const VectorSlotPair& feedback) { |
+ Node* name_node = jsgraph()->Constant(name); |
+ const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper, 3); |
+ Node* value = NewNode(op, receiver, home_object, name_node); |
+ return Record(js_type_feedback_, value, feedback.slot()); |
Michael Starzinger
2015/06/05 13:28:19
Just for clarification: My understanding is that w
arv (Not doing code reviews)
2015/06/05 13:50:26
I think that is right. At some point we probably w
Michael Starzinger
2015/06/05 13:53:23
Acknowledged.
|
+} |
+ |
+ |
+Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object, |
+ Node* key, |
+ const VectorSlotPair& feedback) { |
+ const Operator* op = |
+ javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper, 3); |
+ Node* value = NewNode(op, receiver, home_object, key); |
+ return Record(js_type_feedback_, value, feedback.slot()); |
+} |
+ |
+ |
+Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object, |
+ Node* key, Node* value, |
+ TypeFeedbackId id) { |
+ Runtime::FunctionId function_id = is_strict(language_mode()) |
+ ? Runtime::kStoreKeyedToSuper_Strict |
+ : Runtime::kStoreKeyedToSuper_Sloppy; |
+ const Operator* op = javascript()->CallRuntime(function_id, 4); |
+ Node* result = NewNode(op, receiver, home_object, key, value); |
+ return Record(js_type_feedback_, result, id); |
+} |
+ |
+ |
+Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object, |
+ Handle<Name> name, Node* value, |
+ TypeFeedbackId id) { |
+ Node* name_node = jsgraph()->Constant(name); |
+ Runtime::FunctionId function_id = is_strict(language_mode()) |
+ ? Runtime::kStoreToSuper_Strict |
+ : Runtime::kStoreToSuper_Sloppy; |
+ const Operator* op = javascript()->CallRuntime(function_id, 4); |
+ Node* result = NewNode(op, receiver, home_object, name_node, value); |
+ return Record(js_type_feedback_, result, id); |
+} |
+ |
+ |
Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) { |
return NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object, |
jsgraph()->IntPtrConstant(offset - kHeapObjectTag)); |