Mark maps as unstable if their instances potentially transition away.
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 30 Jul 2013 16:33:58 +0000 (16:33 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 30 Jul 2013 16:33:58 +0000 (16:33 +0000)
Use this as a prerequisite for adding code dependencies.

R=ulan@chromium.org

Review URL: https://chromiumcodereview.appspot.com/21095005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15961 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/objects-inl.h
src/objects.cc
src/objects.h
test/mjsunit/regress/regress-omit-checks.js [new file with mode: 0644]

index 3189d84..a7c9921 100644 (file)
@@ -3563,6 +3563,7 @@ bool Map::is_shared() {
 
 
 void Map::set_dictionary_map(bool value) {
+  if (value) mark_unstable();
   set_bit_field3(DictionaryMap::update(bit_field3(), value));
 }
 
@@ -3626,6 +3627,16 @@ bool Map::is_frozen() {
 }
 
 
+void Map::mark_unstable() {
+  set_bit_field3(IsUnstable::update(bit_field3(), true));
+}
+
+
+bool Map::is_stable() {
+  return !IsUnstable::decode(bit_field3());
+}
+
+
 bool Map::has_code_cache() {
   return code_cache() != GetIsolate()->heap()->empty_fixed_array();
 }
@@ -3657,21 +3668,22 @@ bool Map::CanBeDeprecated() {
 
 
 void Map::NotifyLeafMapLayoutChange() {
-  dependent_code()->DeoptimizeDependentCodeGroup(
-      GetIsolate(),
-      DependentCode::kPrototypeCheckGroup);
+  if (is_stable()) {
+    mark_unstable();
+    dependent_code()->DeoptimizeDependentCodeGroup(
+        GetIsolate(),
+        DependentCode::kPrototypeCheckGroup);
+  }
 }
 
 
 bool Map::CanOmitPrototypeChecks() {
-  return !HasTransitionArray() && !is_dictionary_map() &&
-         FLAG_omit_prototype_checks_for_leaf_maps;
+  return is_stable() && FLAG_omit_prototype_checks_for_leaf_maps;
 }
 
 
 bool Map::CanOmitMapChecks() {
-  return !HasTransitionArray() && !is_dictionary_map() &&
-         FLAG_omit_map_checks_for_leaf_maps;
+  return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
 }
 
 
index 7839faa..03e0120 100644 (file)
@@ -2486,8 +2486,7 @@ void Map::DeprecateTransitionTree() {
   deprecate();
   dependent_code()->DeoptimizeDependentCodeGroup(
       GetIsolate(), DependentCode::kTransitionGroup);
-  dependent_code()->DeoptimizeDependentCodeGroup(
-      GetIsolate(), DependentCode::kPrototypeCheckGroup);
+  NotifyLeafMapLayoutChange();
 }
 
 
@@ -6495,6 +6494,7 @@ MaybeObject* Map::RawCopy(int instance_size) {
   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
   new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
   new_bit_field3 = Deprecated::update(new_bit_field3, false);
+  new_bit_field3 = IsUnstable::update(new_bit_field3, false);
   result->set_bit_field3(new_bit_field3);
   return result;
 }
index 36611ee..d67fcf3 100644 (file)
@@ -5188,6 +5188,7 @@ class Map: public HeapObject {
   class IsObserved:                 public BitField<bool, 26,  1> {};
   class Deprecated:                 public BitField<bool, 27,  1> {};
   class IsFrozen:                   public BitField<bool, 28,  1> {};
+  class IsUnstable:                 public BitField<bool, 29,  1> {};
 
   // Tells whether the object in the prototype property will be used
   // for instances created from this function.  If the prototype
@@ -5492,6 +5493,8 @@ class Map: public HeapObject {
   inline void set_is_observed(bool is_observed);
   inline void freeze();
   inline bool is_frozen();
+  inline void mark_unstable();
+  inline bool is_stable();
   inline void deprecate();
   inline bool is_deprecated();
   inline bool CanBeDeprecated();
diff --git a/test/mjsunit/regress/regress-omit-checks.js b/test/mjsunit/regress/regress-omit-checks.js
new file mode 100644 (file)
index 0000000..e5d5074
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+var a = {x:1};
+var a_deprecate = {x:1};
+a_deprecate.x = 1.5;
+function create() {
+  return {__proto__:a, y:1};
+}
+var b1 = create();
+var b2 = create();
+var b3 = create();
+var b4 = create();
+
+function set(b) {
+  b.x = 5;
+  b.z = 10;
+}
+
+set(b1);
+set(b2);
+%OptimizeFunctionOnNextCall(set);
+set(b3);
+var called = false;
+a.x = 1.5;
+Object.defineProperty(a, "z", {set:function(v) { called = true; }});
+set(b4);
+assertTrue(called);
+assertEquals(undefined, b4.z);