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.

Reply via email to