break;
}
case Call::SUPER_CALL:
- // TODO(dslomov): Implement super calls.
- callee_value = jsgraph()->UndefinedConstant();
- receiver_value = jsgraph()->UndefinedConstant();
- SetStackOverflow();
- break;
+ return VisitCallSuper(expr);
case Call::POSSIBLY_EVAL_CALL:
possibly_eval = true;
if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
}
+void AstGraphBuilder::VisitCallSuper(Call* expr) {
+ SuperCallReference* super = expr->expression()->AsSuperCallReference();
+ DCHECK_NOT_NULL(super);
+
+ // Prepare the callee to the super call. The super constructor is stored as
+ // the prototype of the constructor we are currently executing.
+ VisitForValue(super->this_function_var());
+ Node* this_function = environment()->Pop();
+ const Operator* op = javascript()->CallRuntime(Runtime::kGetPrototype, 1);
+ Node* super_function = NewNode(op, this_function);
+ // TODO(mstarzinger): This probably needs a proper bailout id.
+ PrepareFrameState(super_function, BailoutId::None());
+ environment()->Push(super_function);
+
+ // Evaluate all arguments to the super call.
+ ZoneList<Expression*>* args = expr->arguments();
+ VisitForValues(args);
+
+ // Original receiver is loaded from the {new.target} variable.
+ VisitForValue(super->new_target_var());
+
+ // Create node to perform the super call.
+ const Operator* call = javascript()->CallConstruct(args->length() + 2);
+ Node* value = ProcessArguments(call, args->length() + 2);
+ PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
+
+ // TODO(mstarzinger): It sure would be nice if this were desugared. Also we
+ // are still missing the hole-check in the assignment below, fix that.
+ FrameStateBeforeAndAfter states(this, BailoutId::None());
+ BuildVariableAssignment(super->this_var()->var(), value, Token::INIT_CONST,
+ VectorSlotPair(), BailoutId::None(), states);
+
+ // TODO(mstarzinger): Remove bailout once lowering is correct.
+ SetStackOverflow();
+
+ ast_context()->ProduceValue(value);
+}
+
+
void AstGraphBuilder::VisitCallNew(CallNew* expr) {
VisitForValue(expr->expression());
ZoneList<Expression*>* args = expr->arguments();
VisitForValues(args);
+ // Original receiver is the same as the callee.
+ environment()->Push(environment()->Peek(args->length()));
+
// Create node to perform the construct call.
- const Operator* call = javascript()->CallConstruct(args->length() + 1);
- Node* value = ProcessArguments(call, args->length() + 1);
+ const Operator* call = javascript()->CallConstruct(args->length() + 2);
+ Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(value);
}
CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
CallDescriptor* desc =
- Linkage::GetStubCallDescriptor(isolate(), zone(), d, arity, flags);
+ Linkage::GetStubCallDescriptor(isolate(), zone(), d, arity - 1, flags);
Node* stub_code = jsgraph()->HeapConstant(stub.GetCode());
- Node* construct = NodeProperties::GetValueInput(node, 0);
+ Node* actual_construct = NodeProperties::GetValueInput(node, 0);
+ Node* original_construct = NodeProperties::GetValueInput(node, arity - 1);
+ node->RemoveInput(arity - 1); // Drop original constructor.
node->InsertInput(zone(), 0, stub_code);
- node->InsertInput(zone(), 1, jsgraph()->Int32Constant(arity - 1));
- node->InsertInput(zone(), 2, construct);
+ node->InsertInput(zone(), 1, jsgraph()->Int32Constant(arity - 2));
+ node->InsertInput(zone(), 2, actual_construct);
+ // TODO(mstarzinger): Pass original constructor in register.
+ CHECK_EQ(actual_construct, original_construct);
node->InsertInput(zone(), 3, jsgraph()->UndefinedConstant());
node->set_op(common()->Call(desc));
}