From: rossberg@chromium.org Date: Fri, 14 Dec 2012 14:19:18 +0000 (+0000) Subject: Object.oberve: assertions to narrow down flaky crashes with array length mutation. X-Git-Tag: upstream/4.7.83~15431 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1080d2aade6881346d5cd2306fdfb5b771d0e208;p=platform%2Fupstream%2Fv8.git Object.oberve: assertions to narrow down flaky crashes with array length mutation. R=mstarzinger@chromium.org BUG=v8:2409 Review URL: https://codereview.chromium.org/11566027 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13221 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/objects-debug.cc b/src/objects-debug.cc index e3226c1..5045e1e 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -311,6 +311,9 @@ void Map::MapVerify() { SLOW_ASSERT(transitions()->IsSortedNoDuplicates()); SLOW_ASSERT(transitions()->IsConsistentWithBackPointers(this)); } + ASSERT(!is_observed() || instance_type() < FIRST_JS_OBJECT_TYPE || + instance_type() > LAST_JS_OBJECT_TYPE || + has_slow_elements_kind() || has_external_array_elements()); } diff --git a/src/objects-inl.h b/src/objects-inl.h index d61d3da..9e6044a 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1416,23 +1416,29 @@ void JSObject::initialize_elements() { MaybeObject* JSObject::ResetElements() { - Object* obj; + if (map()->is_observed()) { + // Maintain invariant that observed elements are always in dictionary mode. + SeededNumberDictionary* dictionary; + MaybeObject* maybe = SeededNumberDictionary::Allocate(0); + if (!maybe->To(&dictionary)) return maybe; + if (map() == GetHeap()->non_strict_arguments_elements_map()) { + FixedArray::cast(elements())->set(1, dictionary); + } else { + set_elements(dictionary); + } + return this; + } + ElementsKind elements_kind = GetInitialFastElementsKind(); if (!FLAG_smi_only_arrays) { elements_kind = FastSmiToObjectElementsKind(elements_kind); } - MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), - elements_kind); - if (!maybe_obj->ToObject(&obj)) return maybe_obj; - set_map(Map::cast(obj)); + MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); + Map* map; + if (!maybe->To(&map)) return maybe; + set_map(map); initialize_elements(); - if (FLAG_harmony_observation && map()->is_observed()) { - // Maintain invariant that observed elements are always in dictionary mode. - // For this to work on arrays, we have to make sure to reset length first. - if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(0)); - maybe_obj = NormalizeElements(); - if (maybe_obj->IsFailure()) return maybe_obj; - } + return this; } @@ -3362,6 +3368,9 @@ bool Map::owns_descriptors() { void Map::set_is_observed(bool is_observed) { + ASSERT(instance_type() < FIRST_JS_OBJECT_TYPE || + instance_type() > LAST_JS_OBJECT_TYPE || + has_slow_elements_kind() || has_external_array_elements()); set_bit_field3(IsObserved::update(bit_field3(), is_observed)); } diff --git a/src/objects.h b/src/objects.h index 13414dc..174f43d 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4764,6 +4764,10 @@ class Map: public HeapObject { inline void set_elements_kind(ElementsKind elements_kind) { ASSERT(elements_kind < kElementsKindCount); ASSERT(kElementsKindCount <= (1 << kElementsKindBitCount)); + ASSERT(!is_observed() || + elements_kind == DICTIONARY_ELEMENTS || + elements_kind == NON_STRICT_ARGUMENTS_ELEMENTS || + IsExternalArrayElementsKind(elements_kind)); set_bit_field2((bit_field2() & ~kElementsKindMask) | (elements_kind << kElementsKindShift)); ASSERT(this->elements_kind() == elements_kind); diff --git a/src/runtime.cc b/src/runtime.cc index badcaab..c44a183 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -4376,6 +4376,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) { Handle object = args.at(0); if (object->IsJSObject()) { Handle js_object(Handle::cast(object)); + ASSERT(!js_object->map()->is_observed()); ElementsKind new_kind = js_object->HasFastHoleyElements() ? FAST_HOLEY_DOUBLE_ELEMENTS : FAST_DOUBLE_ELEMENTS; @@ -4392,6 +4393,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) { Handle object = args.at(0); if (object->IsJSObject()) { Handle js_object(Handle::cast(object)); + ASSERT(!js_object->map()->is_observed()); ElementsKind new_kind = js_object->HasFastHoleyElements() ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; @@ -13487,19 +13489,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) { ASSERT(proto->IsJSGlobalObject()); obj = JSReceiver::cast(proto); } + ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() && + JSObject::cast(obj)->HasFastElements())); if (obj->map()->is_observed() != is_observed) { - MaybeObject* maybe = obj->map()->Copy(); - Map* map; - if (!maybe->To(&map)) return maybe; - map->set_is_observed(is_observed); - obj->set_map(map); if (is_observed && obj->IsJSObject() && !JSObject::cast(obj)->HasExternalArrayElements()) { // Go to dictionary mode, so that we don't skip map checks. - maybe = JSObject::cast(obj)->NormalizeElements(); + MaybeObject* maybe = JSObject::cast(obj)->NormalizeElements(); if (maybe->IsFailure()) return maybe; ASSERT(!JSObject::cast(obj)->HasFastElements()); } + MaybeObject* maybe = obj->map()->Copy(); + Map* map; + if (!maybe->To(&map)) return maybe; + map->set_is_observed(is_observed); + obj->set_map(map); } return isolate->heap()->undefined_value(); } diff --git a/test/mjsunit/harmony/object-observe.js b/test/mjsunit/harmony/object-observe.js index 4e2594f..4820582 100644 --- a/test/mjsunit/harmony/object-observe.js +++ b/test/mjsunit/harmony/object-observe.js @@ -943,11 +943,8 @@ function TestFastElementsLength(polymorphic, optimize, oldSize, newSize) { } } -// TODO(rossberg): Still flaky on buildbots, disable for now... -/* for (var b1 = 0; b1 < 2; ++b1) for (var b2 = 0; b2 < 2; ++b2) for (var n1 = 0; n1 < 3; ++n1) for (var n2 = 0; n2 < 3; ++n2) TestFastElementsLength(b1 != 0, b2 != 0, 20*n1, 20*n2); -*/