Reviewers: rossberg, Benedikt Meurer,

Message:
PTAL

Description:
[strong] weak classes can't inherit from strong ones

Prerequisite for sealing strong class instances.

Depends on https://codereview.chromium.org/1314203002/

BUG=v8:3956
LOG=N

Please review this at https://codereview.chromium.org/1316333002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+43, -52 lines):
  M src/compiler/ast-graph-builder.cc
  M src/full-codegen/full-codegen.cc
  M src/messages.h
  M src/runtime/runtime.h
  M src/runtime/runtime-classes.cc
  M test/mjsunit/strong/class-object-frozen.js
  A test/mjsunit/strong/class-weak-extend.js
  M test/mjsunit/strong/literals.js


Index: src/compiler/ast-graph-builder.cc
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 10abec7b8824741217a09e39e69e8e35b4a9224c..3eebbbcf677dd78b52c8cfae82aa8474c86d1515 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -1564,10 +1564,7 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
   Node* name = environment()->Pop();
   Node* start = jsgraph()->Constant(expr->start_position());
   Node* end = jsgraph()->Constant(expr->end_position());
-  const Operator* opc = javascript()->CallRuntime(
-      is_strong(language_mode()) ? Runtime::kDefineClassStrong
-                                 : Runtime::kDefineClass,
-      5);
+ const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass, 5);
   Node* literal = NewNode(opc, name, extends, constructor, start, end);
   PrepareFrameState(literal, expr->CreateLiteralId(),
                     OutputFrameStateCombine::Push());
Index: src/full-codegen/full-codegen.cc
diff --git a/src/full-codegen/full-codegen.cc b/src/full-codegen/full-codegen.cc index fa2f921d016786a56b276f854f99360db42db684..5ef9d0a0b935eb2f163cb43f4bd1785010135320 100644
--- a/src/full-codegen/full-codegen.cc
+++ b/src/full-codegen/full-codegen.cc
@@ -1297,9 +1297,7 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
     __ Push(Smi::FromInt(lit->start_position()));
     __ Push(Smi::FromInt(lit->end_position()));

-    __ CallRuntime(is_strong(language_mode()) ? Runtime::kDefineClassStrong
-                                              : Runtime::kDefineClass,
-                   5);
+    __ CallRuntime(Runtime::kDefineClass, 5);
     PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG);

     int store_slot_index = 0;
Index: src/messages.h
diff --git a/src/messages.h b/src/messages.h
index 409353dc5c1bf87f6aae2a82073e6f47946c8810..4ed94780d1b3fd841b45bdfc9ba8aa1553aa8c98 100644
--- a/src/messages.h
+++ b/src/messages.h
@@ -225,6 +225,7 @@ class CallSite {
"to be non-writable is deprecated") \ T(StrongSetProto, \ "On strong object %, redefining the internal prototype is deprecated") \ + T(StrongWeakExtend, "Non-strong class % cannot extend a strong object") \ T(SymbolKeyFor, "% is not a symbol") \ T(SymbolToNumber, "Cannot convert a Symbol value to a number") \ T(SymbolToString, "Cannot convert a Symbol value to a string") \
Index: src/runtime/runtime-classes.cc
diff --git a/src/runtime/runtime-classes.cc b/src/runtime/runtime-classes.cc
index bc273eec307279c02024b674b0ac1843e8d72a73..f76ee81f2d1079580164b0163960712bfe1051f0 100644
--- a/src/runtime/runtime-classes.cc
+++ b/src/runtime/runtime-classes.cc
@@ -138,6 +138,18 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name,
       isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
   if (constructor->map()->is_strong()) {
     map->set_is_strong();
+    // Strong class is not permitted to extend null.
+    if (super_class->IsNull()) {
+ THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kStrongExtendNull),
+                      Object);
+    }
+  } else {
+    if (Handle<HeapObject>::cast(super_class)->map()->is_strong()) {
+      // Weak class is not permitted to extend strong class.
+      THROW_NEW_ERROR(isolate,
+ NewTypeError(MessageTemplate::kStrongWeakExtend, name),
+                      Object);
+    }
   }
   Map::SetPrototype(map, prototype_parent);
   map->SetConstructor(*constructor);
@@ -212,28 +224,6 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
 }


-RUNTIME_FUNCTION(Runtime_DefineClassStrong) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 5);
-  CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
-  CONVERT_SMI_ARG_CHECKED(start_position, 3);
-  CONVERT_SMI_ARG_CHECKED(end_position, 4);
-
-  if (super_class->IsNull()) {
-    THROW_NEW_ERROR_RETURN_FAILURE(
-        isolate, NewTypeError(MessageTemplate::kStrongExtendNull));
-  }
-
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, DefineClass(isolate, name, super_class, constructor,
-                                   start_position, end_position));
-  return *result;
-}
-
-
 RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 3);
Index: src/runtime/runtime.h
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index 4ae9b8846ad5054d42de92b5c9eed94e55ec43e2..d6a98c96a7752f3731eeee4737a084f1d55e0a6e 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -84,7 +84,6 @@ namespace internal {
   F(ToMethod, 2, 1)                           \
   F(HomeObjectSymbol, 0, 1)                   \
   F(DefineClass, 5, 1)                        \
-  F(DefineClassStrong, 5, 1)                  \
   F(FinalizeClassDefinition, 2, 1)            \
   F(DefineClassMethod, 3, 1)                  \
   F(ClassGetSourceCode, 1, 1)                 \
Index: test/mjsunit/strong/class-object-frozen.js
diff --git a/test/mjsunit/strong/class-object-frozen.js b/test/mjsunit/strong/class-object-frozen.js index 2c442c0d5168258986211dd297b7ac05907b459f..49426d8bb29fd20bb74d5adb39457bf129857f8a 100644
--- a/test/mjsunit/strong/class-object-frozen.js
+++ b/test/mjsunit/strong/class-object-frozen.js
@@ -79,20 +79,3 @@ testStrongClass(getClassExprStrong);
   assertDoesNotThrow(function(){addProperty(parent)});
   assertDoesNotThrow(function(){convertPropertyToData(parent)});
 })();
-
-// Check strong classes don't freeze their children.
-(function() {
-  let parent = getClassStrong();
-
-  let classFunc = function() {
-    class Foo extends parent {
-      static get bar() { return 0 }
-      get bar() { return 0 }
-    }
-    return Foo;
-  }
-
-  assertThrows(function(){addProperty(parent)}, TypeError);
-  assertThrows(function(){convertPropertyToData(parent)}, TypeError);
-  testWeakClass(classFunc);
-})();
Index: test/mjsunit/strong/class-weak-extend.js
diff --git a/test/mjsunit/strong/class-weak-extend.js b/test/mjsunit/strong/class-weak-extend.js
new file mode 100644
index 0000000000000000000000000000000000000000..e4faf6f88506984e11387267397fed744c681400
--- /dev/null
+++ b/test/mjsunit/strong/class-weak-extend.js
@@ -0,0 +1,28 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode --allow-natives-syntax
+
+function getStrongClass() {
+  "use strong";
+  return (class {});
+}
+
+function weakClass() {
+  "use strict";
+  class Weak extends getStrongClass() {}
+}
+
+function strongClass() {
+  "use strong";
+  class Strong extends getStrongClass() {}
+}
+
+assertThrows(weakClass, TypeError);
+%OptimizeFunctionOnNextCall(weakClass);
+assertThrows(weakClass, TypeError);
+
+assertDoesNotThrow(strongClass);
+%OptimizeFunctionOnNextCall(strongClass);
+assertDoesNotThrow(strongClass);
Index: test/mjsunit/strong/literals.js
diff --git a/test/mjsunit/strong/literals.js b/test/mjsunit/strong/literals.js index 28123c218ee1d7675f36164758378d7c25940c7c..347ea1ccacbd567296ab0952f110826df03032e1 100644
--- a/test/mjsunit/strong/literals.js
+++ b/test/mjsunit/strong/literals.js
@@ -285,24 +285,19 @@ let GeneratorPrototype = (function*(){}).__proto__;
   class D extends C {};
   class E extends Object {};
   // class F extends null {};
-  const S = (() => {'use strong'; return class {}})();
-  class G extends S {};
   assertWeakClass(C);
   assertWeakClass(D);
   assertWeakClass(E);
   // assertWeakClass(F);
-  assertWeakClass(G);
   assertWeakClass(class {});
   assertWeakClass(class extends Object {});
   // assertWeakClass(class extends null {});
   assertWeakClass(class extends C {});
-  assertWeakClass(class extends S {});
   assertWeakClass(class extends class {} {});
   assertWeakClass(class C {});
   assertWeakClass(class D extends Object {});
   // assertWeakClass(class D extends null {});
   assertWeakClass(class D extends C {});
-  assertWeakClass(class D extends S {});
   assertWeakClass(class D extends class {} {});
 })();



--
--
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