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.