From 2af164f4d9810f1f51f2f7a62c9cae5d59c3ce14 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Tue, 30 Jul 2013 16:33:58 +0000 Subject: [PATCH] Mark maps as unstable if their instances potentially transition away. 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 | 26 +++++++--- src/objects.cc | 4 +- src/objects.h | 3 ++ test/mjsunit/regress/regress-omit-checks.js | 55 +++++++++++++++++++++ 4 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 test/mjsunit/regress/regress-omit-checks.js diff --git a/src/objects-inl.h b/src/objects-inl.h index 3189d84030..a7c9921f74 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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; } diff --git a/src/objects.cc b/src/objects.cc index 7839faaddf..03e0120b0e 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -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; } diff --git a/src/objects.h b/src/objects.h index 36611ee077..d67fcf3182 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5188,6 +5188,7 @@ class Map: public HeapObject { class IsObserved: public BitField {}; class Deprecated: public BitField {}; class IsFrozen: public BitField {}; + class IsUnstable: public BitField {}; // 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 index 0000000000..e5d5074988 --- /dev/null +++ b/test/mjsunit/regress/regress-omit-checks.js @@ -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);