Reviewers: rossberg,

Message:
PTAL

Description:
[strong] class objects created in strong mode are frozen

BUG=v8:3956

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

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

Affected files (+96, -1 lines):
  M src/compiler/ast-graph-builder.cc
  M src/full-codegen.cc
  A test/mjsunit/strong/class-object-frozen.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 46fd17bb8bc482fbeb0b1422d763fdeadf131d63..99510e3abc8aa69cea2ab7d8d459072640fcea96 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -1640,6 +1640,14 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1);
   NewNode(op, environment()->Pop());  // prototype
   NewNode(op, environment()->Pop());  // literal
+  if (is_strong(language_mode())) {
+ // TODO(conradw): It would be more efficient to define the properties with
+    // the right attributes the first time round.
+    literal =
+ NewNode(javascript()->CallRuntime(Runtime::kObjectFreeze, 1), literal);
+    // Freezing the class object should never deopt.
+    PrepareFrameState(literal, BailoutId::None());
+  }

   // Assign to class variable.
   if (expr->scope() != NULL) {
@@ -1652,7 +1660,6 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
     BuildVariableAssignment(var, literal, Token::INIT_CONST, feedback,
                             BailoutId::None(), states);
   }
-
   ast_context()->ProduceValue(literal);
 }

Index: src/full-codegen.cc
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 636698122617ee491f72ea7862c2bc08547d4c36..a97ea22134af4e9ea52765b1471b51d74921e791 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -1204,6 +1204,13 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) { // Verify that compilation exactly consumed the number of store ic slots
     // that the ClassLiteral node had to offer.
     DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
+
+    if (is_strong(language_mode())) {
+ // TODO(conradw): It would be more efficient to define the properties with
+      // the right attributes the first time round.
+      __ Push(result_register());
+      __ CallRuntime(Runtime::kObjectFreeze, 1);
+    }
   }

   context()->Plug(result_register());
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
new file mode 100644
index 0000000000000000000000000000000000000000..eda3a8cbd346044f6c3a9e29115e5b3e1c598dee
--- /dev/null
+++ b/test/mjsunit/strong/class-object-frozen.js
@@ -0,0 +1,81 @@
+// 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
+
+"use strict";
+
+function getClass() {
+  class Foo {
+    static get bar() { return 0 }
+  }
+  return Foo;
+}
+
+function getClassExpr() {
+  return (class { static get bar() { return 0 } });
+}
+
+function getClassStrong() {
+  "use strong";
+  class Foo {
+    static get bar() { return 0 }
+  }
+  return Foo;
+}
+
+function getClassExprStrong() {
+  "use strong";
+  return (class { static get bar() { return 0 } });
+}
+
+function addProperty(o) {
+  o.baz = 1;
+}
+
+function convertPropertyToData(o) {
+  assertTrue(o.hasOwnProperty("bar"));
+  Object.defineProperty(o, "bar", { value: 1 });
+  print(o.bar);
+}
+
+assertDoesNotThrow(function(){addProperty(getClass())});
+assertDoesNotThrow(function(){convertPropertyToData(getClass())});
+assertDoesNotThrow(function(){addProperty(getClassExpr())});
+assertDoesNotThrow(function(){convertPropertyToData(getClassExpr())});
+
+assertThrows(function(){addProperty(getClassStrong())}, TypeError);
+assertThrows(function(){convertPropertyToData(getClassStrong())}, TypeError);
+assertThrows(function(){addProperty(getClassExprStrong())}, TypeError);
+assertThrows(function(){convertPropertyToData(getClassExprStrong())},
+             TypeError);
+
+// Check strong classes don't freeze their parents.
+(function() {
+  "use strong";
+  let parent = getClass();
+
+  class Foo extends parent {
+    static get bar() { return 0 }
+  }
+
+  assertThrows(function(){addProperty(Foo)}, TypeError);
+  assertThrows(function(){convertPropertyToData(Foo)}, TypeError);
+  assertDoesNotThrow(function(){addProperty(parent)});
+  assertDoesNotThrow(function(){convertPropertyToData(parent)});
+})();
+
+// Check strong classes don't freeze their children.
+(function() {
+  let parent = getClassStrong();
+
+  class Foo extends parent {
+    static get bar() { return 0 }
+  }
+
+  assertThrows(function(){addProperty(parent)}, TypeError);
+  assertThrows(function(){convertPropertyToData(parent)}, TypeError);
+  assertDoesNotThrow(function(){addProperty(Foo)});
+  assertDoesNotThrow(function(){convertPropertyToData(Foo)});
+})();


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