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
This commit is contained in:
parent
1aed997ad6
commit
1080d2aade
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -4376,6 +4376,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) {
|
||||
Handle<Object> object = args.at<Object>(0);
|
||||
if (object->IsJSObject()) {
|
||||
Handle<JSObject> js_object(Handle<JSObject>::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> object = args.at<Object>(0);
|
||||
if (object->IsJSObject()) {
|
||||
Handle<JSObject> js_object(Handle<JSObject>::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) {
|
||||
if (is_observed && obj->IsJSObject() &&
|
||||
!JSObject::cast(obj)->HasExternalArrayElements()) {
|
||||
// Go to dictionary mode, so that we don't skip map checks.
|
||||
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);
|
||||
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();
|
||||
if (maybe->IsFailure()) return maybe;
|
||||
ASSERT(!JSObject::cast(obj)->HasFastElements());
|
||||
}
|
||||
}
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
@ -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);
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user