EmitKeyedCallWithLoadIC(expr, property->key());
}
}
+ } else if (call_type == Call::SUPER_CALL) {
+ SuperReference* super_ref = callee->AsSuperReference();
+ DCHECK(super_ref != NULL);
+ __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ Push(r0);
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+ __ Push(result_register());
+ VisitForStackValue(super_ref->this_var());
+ EmitCall(expr, CallICState::METHOD);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
EmitKeyedCallWithLoadIC(expr, property->key());
}
}
+ } else if (call_type == Call::SUPER_CALL) {
+ SuperReference* super_ref = callee->AsSuperReference();
+ DCHECK(super_ref != NULL);
+ __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ Push(x0);
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+ __ Push(result_register());
+ VisitForStackValue(super_ref->this_var());
+ EmitCall(expr, CallICState::METHOD);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
}
}
+ if (expression()->AsSuperReference() != NULL) return SUPER_CALL;
+
Property* property = expression()->AsProperty();
return property != NULL ? PROPERTY_CALL : OTHER_CALL;
}
GLOBAL_CALL,
LOOKUP_SLOT_CALL,
PROPERTY_CALL,
+ SUPER_CALL,
OTHER_CALL
};
Call* NewCall(Expression* expression,
ZoneList<Expression*>* arguments,
int pos) {
- SuperReference* super_ref = expression->AsSuperReference();
- Call* call;
- if (super_ref != NULL) {
- Literal* constructor =
- NewStringLiteral(ast_value_factory_->constructor_string(), pos);
- Property* superConstructor = NewProperty(super_ref, constructor, pos);
- call = new (zone_) Call(zone_, superConstructor, arguments, pos, id_gen_);
- } else {
- call = new (zone_) Call(zone_, expression, arguments, pos, id_gen_);
- }
+ Call* call = new (zone_) Call(zone_, expression, arguments, pos, id_gen_);
VISIT_AND_RETURN(Call, call)
}
flags = CALL_AS_METHOD;
break;
}
+ case Call::SUPER_CALL: {
+ // todo(dslomov): implement super calls in turbofan.
+ UNIMPLEMENTED();
+ break;
+ }
case Call::POSSIBLY_EVAL_CALL:
possibly_eval = true;
// Fall through.
EmitKeyedCallWithLoadIC(expr, property->key());
}
}
+ } else if (call_type == Call::SUPER_CALL) {
+ SuperReference* super_ref = callee->AsSuperReference();
+ DCHECK(super_ref != NULL);
+ __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+ __ push(result_register());
+ VisitForStackValue(super_ref->this_var());
+ EmitCall(expr, CallICState::METHOD);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
EmitKeyedCallWithLoadIC(expr, property->key());
}
}
+ } else if (call_type == Call::SUPER_CALL) {
+ SuperReference* super_ref = callee->AsSuperReference();
+ DCHECK(super_ref != NULL);
+ __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+ __ Push(result_register());
+ VisitForStackValue(super_ref->this_var());
+ EmitCall(expr, CallICState::METHOD);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
(function TestSuperCall() {
function Subclass(base, constructor) {
- var homeObject = { __proto__ : base.prototype };
- var result = constructor.toMethod(homeObject);
- homeObject.constructor = result;
- result.prototype = homeObject;
- return result;
+ var homeObject = {
+ __proto__: base.prototype,
+ constructor: constructor
+ };
+ constructor.__proto__ = base;
+ constructor.prototype = homeObject;
+ // not doing toMethod: home object is not required for
+ // super constructor calls.
+ return constructor;
}
var baseCalled = 0;
var d = new Derived2("base", "derived");
assertEquals("base", d.fromBase);
assertEquals("derived", d.fromDerived);
+
+ function ImplicitSubclassOfFunction() {
+ super();
+ this.x = 123;
+ }
+
+ var o = new ImplicitSubclassOfFunction();
+ assertEquals(123, o.x);
+
+ var calls = 0;
+ function G() {
+ calls++;
+ }
+ function F() {
+ super();
+ }
+ F.__proto__ = G;
+ new F();
+ assertEquals(1, calls);
+ F.__proto__ = function() {};
+ new F();
+ assertEquals(1, calls);
+}());
+
+
+(function TestSuperCallErrorCases() {
+ function T() {
+ super();
+ }
+ T.__proto__ = null;
+ // Spec says ReferenceError here, but for other IsCallable failures
+ // we throw TypeError.
+ // Filed https://bugs.ecmascript.org/show_bug.cgi?id=3282
+ assertThrows(function() { new T(); }, TypeError);
}());