Index: src/objects-debug.cc |
diff --git a/src/objects-debug.cc b/src/objects-debug.cc |
index fff4f3091c05f9e9c05af37a0abbd1d4d79aa0c7..13342ca36a405b187a862c54dca11a972d085f9e 100644 |
--- a/src/objects-debug.cc |
+++ b/src/objects-debug.cc |
@@ -100,14 +100,12 @@ |
break; |
case JS_OBJECT_TYPE: |
case JS_ERROR_TYPE: |
+ case JS_ARGUMENTS_TYPE: |
case JS_API_OBJECT_TYPE: |
case JS_SPECIAL_API_OBJECT_TYPE: |
case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
case JS_PROMISE_TYPE: |
JSObject::cast(this)->JSObjectVerify(); |
- break; |
- case JS_ARGUMENTS_TYPE: |
- JSArgumentsObject::cast(this)->JSArgumentsObjectVerify(); |
break; |
case JS_GENERATOR_OBJECT_TYPE: |
JSGeneratorObject::cast(this)->JSGeneratorObjectVerify(); |
@@ -248,9 +246,9 @@ |
template <class Traits> |
void FixedTypedArray<Traits>::FixedTypedArrayVerify() { |
- CHECK(IsHeapObject()); |
- CHECK(HeapObject::cast(this)->map()->instance_type() == |
- Traits::kInstanceType); |
+ CHECK(IsHeapObject() && |
+ HeapObject::cast(this)->map()->instance_type() == |
+ Traits::kInstanceType); |
if (base_pointer() == this) { |
CHECK(external_pointer() == |
ExternalReference::fixed_typed_array_base_data_offset().address()); |
@@ -267,166 +265,76 @@ |
GetHeap()->one_pointer_filler_map(); |
} |
-namespace { |
- |
-void VerifyFastProperties(JSReceiver* receiver) { |
- // TODO(cbruni): JSProxy support for slow properties |
- if (!receiver->IsJSObject()) return; |
- Isolate* isolate = receiver->GetIsolate(); |
- Map* map = receiver->map(); |
- CHECK(!map->is_dictionary_map()); |
- JSObject* obj = JSObject::cast(receiver); |
- int actual_unused_property_fields = map->GetInObjectProperties() + |
- obj->properties()->length() - |
- map->NextFreePropertyIndex(); |
- if (map->unused_property_fields() != actual_unused_property_fields) { |
- // This could actually happen in the middle of StoreTransitionStub |
- // when the new extended backing store is already set into the object and |
- // the allocation of the MutableHeapNumber triggers GC (in this case map |
- // is not updated yet). |
- CHECK_EQ(map->unused_property_fields(), |
- actual_unused_property_fields - JSObject::kFieldsAdded); |
- } |
- DescriptorArray* descriptors = map->instance_descriptors(); |
- for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
- if (descriptors->GetDetails(i).type() != DATA) continue; |
- Representation r = descriptors->GetDetails(i).representation(); |
- FieldIndex index = FieldIndex::ForDescriptor(map, i); |
- if (obj->IsUnboxedDoubleField(index)) { |
- DCHECK(r.IsDouble()); |
- continue; |
- } |
- Object* value = obj->RawFastPropertyAt(index); |
- if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber()); |
- if (value->IsUninitialized(isolate)) continue; |
- if (r.IsSmi()) DCHECK(value->IsSmi()); |
- if (r.IsHeapObject()) DCHECK(value->IsHeapObject()); |
- FieldType* field_type = descriptors->GetFieldType(i); |
- bool type_is_none = field_type->IsNone(); |
- bool type_is_any = field_type->IsAny(); |
- if (r.IsNone()) { |
- CHECK(type_is_none); |
- } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) { |
- // If allocation folding is off then GC could happen during inner |
- // object literal creation and we will end up having and undefined |
- // value that does not match the field type. |
- CHECK(!field_type->NowStable() || field_type->NowContains(value) || |
- (!FLAG_use_allocation_folding && value->IsUndefined(isolate))); |
- } |
- } |
-} |
- |
-template <typename T> |
-void VerifyDictionary(T* dict) { |
- CHECK(dict->IsFixedArray()); |
- CHECK(dict->IsDictionary()); |
- int capacity = dict->Capacity(); |
- int nof = dict->NumberOfElements(); |
- int nod = dict->NumberOfDeletedElements(); |
- CHECK_LE(capacity, dict->length()); |
- CHECK_LE(nof, capacity); |
- CHECK_LE(0, nof + nod); |
- CHECK_LE(nof + nod, capacity); |
-} |
- |
-void VerifySlowProperties(JSReceiver* obj) { |
- Map* map = obj->map(); |
- CHECK(map->is_dictionary_map()); |
- CHECK_EQ(0, map->NumberOfOwnDescriptors()); |
- CHECK_EQ(0, map->unused_property_fields()); |
- CHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength()); |
- CHECK(obj->properties()->IsDictionary()); |
- // Kept in-object properties for sow-mode object need to be zapped: |
- int nof_in_object_properties = map->GetInObjectProperties(); |
- if (nof_in_object_properties > 0) { |
- JSObject* js_object = JSObject::cast(obj); |
- Smi* zap_value = Smi::FromInt(0); |
- for (int i = 0; i < nof_in_object_properties; i++) { |
- FieldIndex index = FieldIndex::ForLoadByFieldIndex(map, i); |
- Object* field = js_object->RawFastPropertyAt(index); |
- CHECK_EQ(field, zap_value); |
- } |
- } |
- if (obj->IsJSGlobalObject()) { |
- VerifyDictionary(JSObject::cast(obj)->global_dictionary()); |
- } else { |
- VerifyDictionary(obj->property_dictionary()); |
- } |
-} |
- |
-void VerifyProperties(JSReceiver* obj) { |
- obj->VerifyHeapPointer(obj->properties()); |
- if (obj->HasFastProperties()) { |
- VerifyFastProperties(obj); |
- } else { |
- VerifySlowProperties(obj); |
- } |
-} |
- |
-void VerifyElements(JSObject* obj) { |
- obj->VerifyHeapPointer(obj->elements()); |
+ |
+void JSObject::JSObjectVerify() { |
+ VerifyHeapPointer(properties()); |
+ VerifyHeapPointer(elements()); |
+ |
+ if (HasSloppyArgumentsElements()) { |
+ CHECK(this->elements()->IsFixedArray()); |
+ CHECK_GE(this->elements()->length(), 2); |
+ } |
+ |
+ if (HasFastProperties()) { |
+ int actual_unused_property_fields = map()->GetInObjectProperties() + |
+ properties()->length() - |
+ map()->NextFreePropertyIndex(); |
+ if (map()->unused_property_fields() != actual_unused_property_fields) { |
+ // This could actually happen in the middle of StoreTransitionStub |
+ // when the new extended backing store is already set into the object and |
+ // the allocation of the MutableHeapNumber triggers GC (in this case map |
+ // is not updated yet). |
+ CHECK_EQ(map()->unused_property_fields(), |
+ actual_unused_property_fields - JSObject::kFieldsAdded); |
+ } |
+ DescriptorArray* descriptors = map()->instance_descriptors(); |
+ Isolate* isolate = GetIsolate(); |
+ for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) { |
+ if (descriptors->GetDetails(i).type() == DATA) { |
+ Representation r = descriptors->GetDetails(i).representation(); |
+ FieldIndex index = FieldIndex::ForDescriptor(map(), i); |
+ if (IsUnboxedDoubleField(index)) { |
+ DCHECK(r.IsDouble()); |
+ continue; |
+ } |
+ Object* value = RawFastPropertyAt(index); |
+ if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber()); |
+ if (value->IsUninitialized(isolate)) continue; |
+ if (r.IsSmi()) DCHECK(value->IsSmi()); |
+ if (r.IsHeapObject()) DCHECK(value->IsHeapObject()); |
+ FieldType* field_type = descriptors->GetFieldType(i); |
+ bool type_is_none = field_type->IsNone(); |
+ bool type_is_any = field_type->IsAny(); |
+ if (r.IsNone()) { |
+ CHECK(type_is_none); |
+ } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) { |
+ // If allocation folding is off then GC could happen during inner |
+ // object literal creation and we will end up having and undefined |
+ // value that does not match the field type. |
+ CHECK(!field_type->NowStable() || field_type->NowContains(value) || |
+ (!FLAG_use_allocation_folding && value->IsUndefined(isolate))); |
+ } |
+ } |
+ } |
+ } |
+ |
// If a GC was caused while constructing this object, the elements |
// pointer may point to a one pointer filler map. |
- if (!obj->ElementsAreSafeToExamine()) return; |
- Map* map = obj->map(); |
- Heap* heap = obj->GetHeap(); |
- FixedArrayBase* elements = obj->elements(); |
- CHECK_EQ((map->has_fast_smi_or_object_elements() || |
- (elements == heap->empty_fixed_array()) || |
- obj->HasFastStringWrapperElements()), |
- (elements->map() == heap->fixed_array_map() || |
- elements->map() == heap->fixed_cow_array_map())); |
- CHECK_EQ(map->has_fast_object_elements(), obj->HasFastObjectElements()); |
- |
- ElementsKind kind = obj->GetElementsKind(); |
- if (IsFastSmiOrObjectElementsKind(kind)) { |
- CHECK(elements->map() == heap->fixed_array_map() || |
- elements->map() == heap->fixed_cow_array_map()); |
- } else if (IsFastDoubleElementsKind(kind)) { |
- CHECK(elements->IsFixedDoubleArray() || |
- elements == heap->empty_fixed_array()); |
- } else if (kind == DICTIONARY_ELEMENTS) { |
- CHECK(elements->IsSeededNumberDictionary()); |
- VerifyDictionary(SeededNumberDictionary::cast(elements)); |
- return; |
- } else { |
- CHECK(kind > DICTIONARY_ELEMENTS); |
- } |
- CHECK(!IsSloppyArgumentsElements(kind) || |
- (elements->IsFixedArray() && elements->length() >= 2)); |
- |
- if (IsFastPackedElementsKind(kind)) { |
- uint32_t length = elements->length(); |
- if (obj->IsJSArray()) { |
- Object* number = JSArray::cast(obj)->length(); |
- if (number->IsSmi()) { |
- length = Min(length, static_cast<uint32_t>(Smi::cast(number)->value())); |
- } |
- } |
- if (kind == FAST_DOUBLE_ELEMENTS) { |
- for (uint32_t i = 0; i < length; i++) { |
- CHECK(!FixedDoubleArray::cast(elements)->is_the_hole(i)); |
- } |
- } else { |
- for (uint32_t i = 0; i < length; i++) { |
- CHECK_NE(FixedArray::cast(elements)->get(i), heap->the_hole_value()); |
- } |
- } |
- } |
-} |
- |
-} // namespace |
- |
-void JSObject::JSObjectVerify() { |
- VerifyProperties(this); |
- VerifyElements(this); |
-} |
+ if (ElementsAreSafeToExamine()) { |
+ CHECK_EQ((map()->has_fast_smi_or_object_elements() || |
+ (elements() == GetHeap()->empty_fixed_array()) || |
+ HasFastStringWrapperElements()), |
+ (elements()->map() == GetHeap()->fixed_array_map() || |
+ elements()->map() == GetHeap()->fixed_cow_array_map())); |
+ CHECK(map()->has_fast_object_elements() == HasFastObjectElements()); |
+ } |
+} |
+ |
void Map::MapVerify() { |
Heap* heap = GetHeap(); |
CHECK(!heap->InNewSpace(this)); |
- CHECK_LE(FIRST_TYPE, instance_type()); |
- CHECK_LE(instance_type(), LAST_TYPE); |
+ CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE); |
CHECK(instance_size() == kVariableSizeSentinel || |
(kPointerSize <= instance_size() && |
instance_size() < heap->Capacity())); |
@@ -449,7 +357,6 @@ |
CHECK(instance_descriptors()->IsEmpty()); |
CHECK_EQ(0, unused_property_fields()); |
CHECK_EQ(Heap::GetStaticVisitorIdForMap(this), visitor_id()); |
- CHECK_EQ(kInvalidEnumCacheSentinel, EnumLength()); |
} |
@@ -519,59 +426,6 @@ |
VerifyObjectField(kReceiverOffset); |
VerifyObjectField(kOperandStackOffset); |
VerifyObjectField(kContinuationOffset); |
- JSObjectVerify(); |
-} |
- |
-namespace { |
- |
-void VerifyArgumentsParameterMap(FixedArray* elements) { |
- Isolate* isolate = elements->GetIsolate(); |
- CHECK(elements->IsFixedArray()); |
- CHECK_GE(elements->length(), 2); |
- HeapObject* context = HeapObject::cast(elements->get(0)); |
- HeapObject* arguments = HeapObject::cast(elements->get(1)); |
- // TODO(cbruni): fix arguments creation to be atomic. |
- CHECK_IMPLIES(context->IsUndefined(isolate), arguments->IsUndefined(isolate)); |
- CHECK(context->IsUndefined(isolate) || context->IsContext()); |
- CHECK(arguments->IsUndefined(isolate) || arguments->IsFixedArray()); |
-} |
- |
-} // namespace |
- |
-void JSArgumentsObject::JSArgumentsObjectVerify() { |
- VerifyObjectField(kLengthOffset); |
- JSObjectVerify(); |
- Isolate* isolate = GetIsolate(); |
- |
- if (isolate->bootstrapper()->IsActive()) return; |
- Context* context = isolate->context(); |
- Object* constructor = map()->GetConstructor(); |
- if (constructor->IsJSFunction()) { |
- context = JSFunction::cast(constructor)->context(); |
- } |
- // TODO(cbruni): replace with NULL check once all hydrogren stubs manage to |
- // set up the contexts properly. |
- if (isolate->context()->IsSmi()) return; |
- Context* native_context = context->native_context(); |
- if (map() == native_context->sloppy_arguments_map()) { |
- // Sloppy arguments without aliased arguments has a normal elements backing |
- // store which is already verified by JSObjectVerify() above. |
- } else if (map() == native_context->fast_aliased_arguments_map()) { |
- CHECK(HasFastArgumentsElements()); |
- FixedArray* elements = FixedArray::cast(this->elements()); |
- VerifyArgumentsParameterMap(FixedArray::cast(elements)); |
- CHECK_EQ(elements->map(), isolate->heap()->sloppy_arguments_elements_map()); |
- } else if (map() == native_context->slow_aliased_arguments_map()) { |
- CHECK(HasSlowArgumentsElements()); |
- FixedArray* elements = FixedArray::cast(this->elements()); |
- VerifyArgumentsParameterMap(elements); |
- VerifyDictionary(SeededNumberDictionary::cast(elements->get(1))); |
- CHECK_EQ(elements->map(), isolate->heap()->sloppy_arguments_elements_map()); |
- } else if (map() == native_context->strict_arguments_map()) { |
- CHECK(HasFastElements()); |
- } else { |
- // TODO(cbruni): follow up on normalized argument maps. |
- } |
} |
@@ -580,12 +434,10 @@ |
if (v->IsHeapObject()) { |
VerifyHeapPointer(v); |
} |
- JSObjectVerify(); |
} |
void JSDate::JSDateVerify() { |
- JSObjectVerify(); |
if (value()->IsHeapObject()) { |
VerifyHeapPointer(value()); |
} |
@@ -635,7 +487,6 @@ |
void JSMessageObject::JSMessageObjectVerify() { |
- JSObjectVerify(); |
CHECK(IsJSMessageObject()); |
VerifyObjectField(kStartPositionOffset); |
VerifyObjectField(kEndPositionOffset); |
@@ -694,7 +545,6 @@ |
void JSFunction::JSFunctionVerify() { |
CHECK(IsJSFunction()); |
- JSObjectVerify(); |
VerifyObjectField(kPrototypeOrInitialMapOffset); |
VerifyObjectField(kNextFunctionLinkOffset); |
CHECK(code()->IsCode()); |
@@ -741,7 +591,6 @@ |
elements()->length() == 0) { |
return; |
} |
- CHECK(!HasFastProperties()); |
JSObjectVerify(); |
} |
@@ -845,7 +694,7 @@ |
} else if (obj->IsJSObject()) { |
if (isolate->heap()->InNewSpace(obj)) { |
ArrayList* list = |
- isolate->heap()->weak_new_space_object_to_code_list(); |
+ GetIsolate()->heap()->weak_new_space_object_to_code_list(); |
bool found = false; |
for (int i = 0; i < list->Length(); i += 2) { |
WeakCell* obj_cell = WeakCell::cast(list->Get(i)); |
@@ -859,7 +708,7 @@ |
} else { |
Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate); |
DependentCode* dep = |
- isolate->heap()->LookupWeakObjectToCodeDependency(key_obj); |
+ GetIsolate()->heap()->LookupWeakObjectToCodeDependency(key_obj); |
dep->Contains(DependentCode::kWeakCodeGroup, cell); |
} |
} |
@@ -869,22 +718,17 @@ |
void JSArray::JSArrayVerify() { |
- CHECK(IsJSArray()); |
JSObjectVerify(); |
Isolate* isolate = GetIsolate(); |
- // Allow undefined for not fully initialized JSArrays |
- if (length()->IsUndefined(isolate)) { |
- CHECK_EQ(FixedArray::cast(elements()), |
- isolate->heap()->empty_fixed_array()); |
- return; |
- } |
- CHECK(length()->IsNumber()); |
+ CHECK(length()->IsNumber() || length()->IsUndefined(isolate)); |
// If a GC was caused while constructing this array, the elements |
// pointer may point to a one pointer filler map. |
if (ElementsAreSafeToExamine()) { |
- CHECK(elements()->IsFixedArray() || elements()->IsFixedDoubleArray()); |
- } |
-} |
+ CHECK(elements()->IsUndefined(isolate) || elements()->IsFixedArray() || |
+ elements()->IsFixedDoubleArray()); |
+ } |
+} |
+ |
void JSSet::JSSetVerify() { |
CHECK(IsJSSet()); |
@@ -1452,8 +1296,7 @@ |
while (!old_it.done()) { |
RelocInfo* rinfo = old_it.rinfo(); |
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
- CHECK(!target->is_handler()); |
- CHECK(!target->is_inline_cache_stub()); |
+ CHECK(!target->is_handler() && !target->is_inline_cache_stub()); |
if (target == stack_check) break; |
old_it.next(); |
} |
@@ -1461,8 +1304,7 @@ |
while (!new_it.done()) { |
RelocInfo* rinfo = new_it.rinfo(); |
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
- CHECK(!target->is_handler()); |
- CHECK(!target->is_inline_cache_stub()); |
+ CHECK(!target->is_handler() && !target->is_inline_cache_stub()); |
if (target == stack_check) break; |
new_it.next(); |
} |