Revision: 24825
Author: [email protected]
Date: Thu Oct 23 08:32:23 2014 UTC
Log: Classes: implement 'new super'.
[email protected], [email protected]
BUG=v8:3330
LOG=N
Committed: https://code.google.com/p/v8/source/detail?r=24822
Review URL: https://codereview.chromium.org/665773003
https://code.google.com/p/v8/source/detail?r=24825
Modified:
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/arm64/full-codegen-arm64.cc
/branches/bleeding_edge/src/full-codegen.h
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/test/mjsunit/harmony/super.js
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu Oct 23 08:21:30
2014 UTC
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu Oct 23 08:32:23
2014 UTC
@@ -2962,6 +2962,14 @@
__ Push(r4, r3, r2, r1);
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
}
+
+
+void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference*
super_ref) {
+ DCHECK(super_ref != NULL);
+ __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ Push(r0);
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+}
void FullCodeGenerator::VisitCall(Call* expr) {
@@ -3081,10 +3089,7 @@
}
} 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);
+ EmitLoadSuperConstructor(super_ref);
__ Push(result_register());
VisitForStackValue(super_ref->this_var());
EmitCall(expr, CallICState::METHOD);
@@ -3116,7 +3121,12 @@
// Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored.
- VisitForStackValue(expr->expression());
+ if (expr->expression()->IsSuperReference()) {
+ EmitLoadSuperConstructor(expr->expression()->AsSuperReference());
+ __ Push(result_register());
+ } else {
+ VisitForStackValue(expr->expression());
+ }
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = expr->arguments();
=======================================
--- /branches/bleeding_edge/src/arm64/full-codegen-arm64.cc Thu Oct 23
08:21:30 2014 UTC
+++ /branches/bleeding_edge/src/arm64/full-codegen-arm64.cc Thu Oct 23
08:32:23 2014 UTC
@@ -2626,6 +2626,14 @@
// Do the runtime call.
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
}
+
+
+void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference*
super_ref) {
+ DCHECK(super_ref != NULL);
+ __ ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ Push(x0);
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+}
void FullCodeGenerator::VisitCall(Call* expr) {
@@ -2746,10 +2754,7 @@
}
} 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);
+ EmitLoadSuperConstructor(super_ref);
__ Push(result_register());
VisitForStackValue(super_ref->this_var());
EmitCall(expr, CallICState::METHOD);
@@ -2781,7 +2786,12 @@
// Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored.
- VisitForStackValue(expr->expression());
+ if (expr->expression()->IsSuperReference()) {
+ EmitLoadSuperConstructor(expr->expression()->AsSuperReference());
+ __ Push(result_register());
+ } else {
+ VisitForStackValue(expr->expression());
+ }
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = expr->arguments();
=======================================
--- /branches/bleeding_edge/src/full-codegen.h Thu Oct 23 08:21:30 2014 UTC
+++ /branches/bleeding_edge/src/full-codegen.h Thu Oct 23 08:32:23 2014 UTC
@@ -609,6 +609,8 @@
void EmitLoadHomeObject(SuperReference* expr);
+ void EmitLoadSuperConstructor(SuperReference* expr);
+
void CallIC(Handle<Code> code,
TypeFeedbackId id = TypeFeedbackId::None());
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Oct 23
08:21:30 2014 UTC
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Oct 23
08:32:23 2014 UTC
@@ -2865,6 +2865,13 @@
// Do the runtime call.
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
}
+
+
+void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference*
super_ref) {
+ DCHECK(super_ref != NULL);
+ __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+}
void FullCodeGenerator::VisitCall(Call* expr) {
@@ -2977,9 +2984,7 @@
}
} 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);
+ EmitLoadSuperConstructor(super_ref);
__ push(result_register());
VisitForStackValue(super_ref->this_var());
EmitCall(expr, CallICState::METHOD);
@@ -3010,7 +3015,12 @@
// Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored.
- VisitForStackValue(expr->expression());
+ if (expr->expression()->IsSuperReference()) {
+ EmitLoadSuperConstructor(expr->expression()->AsSuperReference());
+ __ push(result_register());
+ } else {
+ VisitForStackValue(expr->expression());
+ }
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = expr->arguments();
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Oct 23 08:21:30
2014 UTC
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Oct 23 08:32:23
2014 UTC
@@ -2865,6 +2865,13 @@
// Do the runtime call.
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
}
+
+
+void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference*
super_ref) {
+ DCHECK(super_ref != NULL);
+ __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+}
void FullCodeGenerator::VisitCall(Call* expr) {
@@ -2976,9 +2983,7 @@
}
} 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);
+ EmitLoadSuperConstructor(super_ref);
__ Push(result_register());
VisitForStackValue(super_ref->this_var());
EmitCall(expr, CallICState::METHOD);
@@ -3009,7 +3014,12 @@
// Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored.
- VisitForStackValue(expr->expression());
+ if (expr->expression()->IsSuperReference()) {
+ EmitLoadSuperConstructor(expr->expression()->AsSuperReference());
+ __ Push(result_register());
+ } else {
+ VisitForStackValue(expr->expression());
+ }
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = expr->arguments();
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/super.js Thu Oct 23
08:21:30 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/harmony/super.js Thu Oct 23
08:32:23 2014 UTC
@@ -1735,19 +1735,19 @@
}());
+function Subclass(base, constructor) {
+ 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;
+}
+
(function TestSuperCall() {
- function Subclass(base, constructor) {
- 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 derivedCalled = 0;
var derivedDerivedCalled = 0;
@@ -1819,6 +1819,32 @@
}());
+(function TestNewSuper() {
+ var baseCalled = 0;
+ var derivedCalled = 0;
+
+ function Base() {
+ baseCalled++;
+ this.x = 15;
+ }
+
+
+ var Derived = Subclass(Base, function() {
+ baseCalled = 0;
+ var b = new super();
+ assertEquals(1, baseCalled)
+ assertEquals(Base.prototype, b.__proto__);
+ assertEquals(15, b.x);
+ assertEquals(undefined, this.x);
+ derivedCalled++;
+ });
+
+ derivedCalled = 0;
+ new Derived();
+ assertEquals(1, derivedCalled);
+}());
+
+
(function TestSuperCallErrorCases() {
function T() {
super();
@@ -1828,4 +1854,10 @@
// we throw TypeError.
// Filed https://bugs.ecmascript.org/show_bug.cgi?id=3282
assertThrows(function() { new T(); }, TypeError);
+
+ function T1() {
+ var b = new super();
+ }
+ T1.__proto = null;
+ assertThrows(function() { new T1(); }, TypeError);
}());
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.