1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "src/disasm.h"
8 #include "src/disassembler.h"
9 #include "src/heap/objects-visiting.h"
10 #include "src/jsregexp.h"
11 #include "src/macro-assembler.h"
12 #include "src/ostreams.h"
19 void Object::ObjectVerify() {
21 Smi::cast(this)->SmiVerify();
23 HeapObject::cast(this)->HeapObjectVerify();
28 void Object::VerifyPointer(Object* p) {
29 if (p->IsHeapObject()) {
30 HeapObject::VerifyHeapPointer(p);
37 void Smi::SmiVerify() {
42 void HeapObject::HeapObjectVerify() {
43 InstanceType instance_type = map()->instance_type();
45 if (instance_type < FIRST_NONSTRING_TYPE) {
46 String::cast(this)->StringVerify();
50 switch (instance_type) {
52 Symbol::cast(this)->SymbolVerify();
55 Map::cast(this)->MapVerify();
57 case HEAP_NUMBER_TYPE:
58 case MUTABLE_HEAP_NUMBER_TYPE:
59 HeapNumber::cast(this)->HeapNumberVerify();
62 Float32x4::cast(this)->Float32x4Verify();
65 Float64x2::cast(this)->Float64x2Verify();
68 Int32x4::cast(this)->Int32x4Verify();
70 case FIXED_ARRAY_TYPE:
71 FixedArray::cast(this)->FixedArrayVerify();
73 case FIXED_DOUBLE_ARRAY_TYPE:
74 FixedDoubleArray::cast(this)->FixedDoubleArrayVerify();
76 case CONSTANT_POOL_ARRAY_TYPE:
77 ConstantPoolArray::cast(this)->ConstantPoolArrayVerify();
80 ByteArray::cast(this)->ByteArrayVerify();
83 FreeSpace::cast(this)->FreeSpaceVerify();
86 #define VERIFY_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
87 case EXTERNAL_##TYPE##_ARRAY_TYPE: \
88 External##Type##Array::cast(this)->External##Type##ArrayVerify(); \
90 case FIXED_##TYPE##_ARRAY_TYPE: \
91 Fixed##Type##Array::cast(this)->FixedTypedArrayVerify(); \
94 TYPED_ARRAYS(VERIFY_TYPED_ARRAY)
95 #undef VERIFY_TYPED_ARRAY
98 Code::cast(this)->CodeVerify();
101 Oddball::cast(this)->OddballVerify();
104 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
105 JSObject::cast(this)->JSObjectVerify();
107 case JS_GENERATOR_OBJECT_TYPE:
108 JSGeneratorObject::cast(this)->JSGeneratorObjectVerify();
111 JSModule::cast(this)->JSModuleVerify();
114 JSValue::cast(this)->JSValueVerify();
117 JSDate::cast(this)->JSDateVerify();
119 case JS_FUNCTION_TYPE:
120 JSFunction::cast(this)->JSFunctionVerify();
122 case JS_GLOBAL_PROXY_TYPE:
123 JSGlobalProxy::cast(this)->JSGlobalProxyVerify();
125 case JS_GLOBAL_OBJECT_TYPE:
126 JSGlobalObject::cast(this)->JSGlobalObjectVerify();
128 case JS_BUILTINS_OBJECT_TYPE:
129 JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
132 Cell::cast(this)->CellVerify();
134 case PROPERTY_CELL_TYPE:
135 PropertyCell::cast(this)->PropertyCellVerify();
138 JSArray::cast(this)->JSArrayVerify();
141 JSSet::cast(this)->JSSetVerify();
144 JSMap::cast(this)->JSMapVerify();
146 case JS_SET_ITERATOR_TYPE:
147 JSSetIterator::cast(this)->JSSetIteratorVerify();
149 case JS_MAP_ITERATOR_TYPE:
150 JSMapIterator::cast(this)->JSMapIteratorVerify();
152 case JS_WEAK_MAP_TYPE:
153 JSWeakMap::cast(this)->JSWeakMapVerify();
155 case JS_WEAK_SET_TYPE:
156 JSWeakSet::cast(this)->JSWeakSetVerify();
159 JSRegExp::cast(this)->JSRegExpVerify();
164 JSProxy::cast(this)->JSProxyVerify();
166 case JS_FUNCTION_PROXY_TYPE:
167 JSFunctionProxy::cast(this)->JSFunctionProxyVerify();
170 Foreign::cast(this)->ForeignVerify();
172 case SHARED_FUNCTION_INFO_TYPE:
173 SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
175 case JS_MESSAGE_OBJECT_TYPE:
176 JSMessageObject::cast(this)->JSMessageObjectVerify();
178 case JS_ARRAY_BUFFER_TYPE:
179 JSArrayBuffer::cast(this)->JSArrayBufferVerify();
181 case JS_TYPED_ARRAY_TYPE:
182 JSTypedArray::cast(this)->JSTypedArrayVerify();
184 case JS_DATA_VIEW_TYPE:
185 JSDataView::cast(this)->JSDataViewVerify();
188 #define MAKE_STRUCT_CASE(NAME, Name, name) \
190 Name::cast(this)->Name##Verify(); \
192 STRUCT_LIST(MAKE_STRUCT_CASE)
193 #undef MAKE_STRUCT_CASE
202 void HeapObject::VerifyHeapPointer(Object* p) {
203 CHECK(p->IsHeapObject());
204 HeapObject* ho = HeapObject::cast(p);
205 CHECK(ho->GetHeap()->Contains(ho));
209 void Symbol::SymbolVerify() {
211 CHECK(HasHashCode());
213 CHECK(name()->IsUndefined() || name()->IsString());
214 CHECK(flags()->IsSmi());
218 void HeapNumber::HeapNumberVerify() {
219 CHECK(IsHeapNumber() || IsMutableHeapNumber());
223 void Float32x4::Float32x4Verify() {
224 CHECK(IsFloat32x4());
228 void Float64x2::Float64x2Verify() {
229 CHECK(IsFloat64x2());
233 void Int32x4::Int32x4Verify() {
238 void ByteArray::ByteArrayVerify() {
239 CHECK(IsByteArray());
243 void FreeSpace::FreeSpaceVerify() {
244 CHECK(IsFreeSpace());
248 #define EXTERNAL_ARRAY_VERIFY(Type, type, TYPE, ctype, size) \
249 void External##Type##Array::External##Type##ArrayVerify() { \
250 CHECK(IsExternal##Type##Array()); \
253 TYPED_ARRAYS(EXTERNAL_ARRAY_VERIFY)
254 #undef EXTERNAL_ARRAY_VERIFY
257 template <class Traits>
258 void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
259 CHECK(IsHeapObject() &&
260 HeapObject::cast(this)->map()->instance_type() ==
261 Traits::kInstanceType);
265 bool JSObject::ElementsAreSafeToExamine() {
266 // If a GC was caused while constructing this object, the elements
267 // pointer may point to a one pointer filler map.
268 return reinterpret_cast<Map*>(elements()) !=
269 GetHeap()->one_pointer_filler_map();
273 void JSObject::JSObjectVerify() {
274 VerifyHeapPointer(properties());
275 VerifyHeapPointer(elements());
277 if (GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS) {
278 CHECK(this->elements()->IsFixedArray());
279 CHECK_GE(this->elements()->length(), 2);
282 if (HasFastProperties()) {
283 CHECK_EQ(map()->unused_property_fields(),
284 (map()->inobject_properties() + properties()->length() -
285 map()->NextFreePropertyIndex()));
286 DescriptorArray* descriptors = map()->instance_descriptors();
287 for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
288 if (descriptors->GetDetails(i).type() == FIELD) {
289 Representation r = descriptors->GetDetails(i).representation();
290 FieldIndex index = FieldIndex::ForDescriptor(map(), i);
291 Object* value = RawFastPropertyAt(index);
292 if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber());
293 if (value->IsUninitialized()) continue;
294 if (r.IsSmi()) DCHECK(value->IsSmi());
295 if (r.IsHeapObject()) DCHECK(value->IsHeapObject());
296 HeapType* field_type = descriptors->GetFieldType(i);
298 CHECK(field_type->Is(HeapType::None()));
299 } else if (!HeapType::Any()->Is(field_type)) {
300 CHECK(!field_type->NowStable() || field_type->NowContains(value));
306 // If a GC was caused while constructing this object, the elements
307 // pointer may point to a one pointer filler map.
308 if (ElementsAreSafeToExamine()) {
309 CHECK_EQ((map()->has_fast_smi_or_object_elements() ||
310 (elements() == GetHeap()->empty_fixed_array())),
311 (elements()->map() == GetHeap()->fixed_array_map() ||
312 elements()->map() == GetHeap()->fixed_cow_array_map()));
313 CHECK(map()->has_fast_object_elements() == HasFastObjectElements());
318 void Map::MapVerify() {
319 Heap* heap = GetHeap();
320 CHECK(!heap->InNewSpace(this));
321 CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
322 CHECK(instance_size() == kVariableSizeSentinel ||
323 (kPointerSize <= instance_size() &&
324 instance_size() < heap->Capacity()));
325 VerifyHeapPointer(prototype());
326 VerifyHeapPointer(instance_descriptors());
327 SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates());
328 if (HasTransitionArray()) {
329 SLOW_DCHECK(transitions()->IsSortedNoDuplicates());
330 SLOW_DCHECK(transitions()->IsConsistentWithBackPointers(this));
335 void Map::DictionaryMapVerify() {
337 CHECK(is_dictionary_map());
338 CHECK(instance_descriptors()->IsEmpty());
339 CHECK_EQ(0, pre_allocated_property_fields());
340 CHECK_EQ(0, unused_property_fields());
341 CHECK_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
346 void Map::VerifyOmittedMapChecks() {
347 if (!FLAG_omit_map_checks_for_leaf_maps) return;
350 HasTransitionArray() ||
351 is_dictionary_map()) {
352 CHECK_EQ(0, dependent_code()->number_of_entries(
353 DependentCode::kPrototypeCheckGroup));
358 void CodeCache::CodeCacheVerify() {
359 VerifyHeapPointer(default_cache());
360 VerifyHeapPointer(normal_type_cache());
361 CHECK(default_cache()->IsFixedArray());
362 CHECK(normal_type_cache()->IsUndefined()
363 || normal_type_cache()->IsCodeCacheHashTable());
367 void PolymorphicCodeCache::PolymorphicCodeCacheVerify() {
368 VerifyHeapPointer(cache());
369 CHECK(cache()->IsUndefined() || cache()->IsPolymorphicCodeCacheHashTable());
373 void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
374 VerifyObjectField(kStorage1Offset);
375 VerifyObjectField(kStorage2Offset);
376 VerifyObjectField(kStorage3Offset);
380 void AliasedArgumentsEntry::AliasedArgumentsEntryVerify() {
381 VerifySmiField(kAliasedContextSlot);
385 void FixedArray::FixedArrayVerify() {
386 for (int i = 0; i < length(); i++) {
393 void FixedDoubleArray::FixedDoubleArrayVerify() {
394 for (int i = 0; i < length(); i++) {
395 if (!is_the_hole(i)) {
396 double value = get_scalar(i);
397 CHECK(!std::isnan(value) ||
398 (BitCast<uint64_t>(value) ==
399 BitCast<uint64_t>(canonical_not_the_hole_nan_as_double())) ||
400 ((BitCast<uint64_t>(value) & Double::kSignMask) != 0));
406 void ConstantPoolArray::ConstantPoolArrayVerify() {
407 CHECK(IsConstantPoolArray());
408 ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR);
409 while (!code_iter.is_finished()) {
410 Address code_entry = get_code_ptr_entry(code_iter.next_index());
411 VerifyPointer(Code::GetCodeFromTargetAddress(code_entry));
413 ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR);
414 while (!heap_iter.is_finished()) {
415 VerifyObjectField(OffsetOfElementAt(heap_iter.next_index()));
420 void JSGeneratorObject::JSGeneratorObjectVerify() {
421 // In an expression like "new g()", there can be a point where a generator
422 // object is allocated but its fields are all undefined, as it hasn't yet been
423 // initialized by the generator. Hence these weak checks.
424 VerifyObjectField(kFunctionOffset);
425 VerifyObjectField(kContextOffset);
426 VerifyObjectField(kReceiverOffset);
427 VerifyObjectField(kOperandStackOffset);
428 VerifyObjectField(kContinuationOffset);
429 VerifyObjectField(kStackHandlerIndexOffset);
433 void JSModule::JSModuleVerify() {
434 VerifyObjectField(kContextOffset);
435 VerifyObjectField(kScopeInfoOffset);
436 CHECK(context()->IsUndefined() ||
437 Context::cast(context())->IsModuleContext());
441 void JSValue::JSValueVerify() {
443 if (v->IsHeapObject()) {
444 VerifyHeapPointer(v);
449 void JSDate::JSDateVerify() {
450 if (value()->IsHeapObject()) {
451 VerifyHeapPointer(value());
453 CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber());
454 CHECK(year()->IsUndefined() || year()->IsSmi() || year()->IsNaN());
455 CHECK(month()->IsUndefined() || month()->IsSmi() || month()->IsNaN());
456 CHECK(day()->IsUndefined() || day()->IsSmi() || day()->IsNaN());
457 CHECK(weekday()->IsUndefined() || weekday()->IsSmi() || weekday()->IsNaN());
458 CHECK(hour()->IsUndefined() || hour()->IsSmi() || hour()->IsNaN());
459 CHECK(min()->IsUndefined() || min()->IsSmi() || min()->IsNaN());
460 CHECK(sec()->IsUndefined() || sec()->IsSmi() || sec()->IsNaN());
461 CHECK(cache_stamp()->IsUndefined() ||
462 cache_stamp()->IsSmi() ||
463 cache_stamp()->IsNaN());
465 if (month()->IsSmi()) {
466 int month = Smi::cast(this->month())->value();
467 CHECK(0 <= month && month <= 11);
469 if (day()->IsSmi()) {
470 int day = Smi::cast(this->day())->value();
471 CHECK(1 <= day && day <= 31);
473 if (hour()->IsSmi()) {
474 int hour = Smi::cast(this->hour())->value();
475 CHECK(0 <= hour && hour <= 23);
477 if (min()->IsSmi()) {
478 int min = Smi::cast(this->min())->value();
479 CHECK(0 <= min && min <= 59);
481 if (sec()->IsSmi()) {
482 int sec = Smi::cast(this->sec())->value();
483 CHECK(0 <= sec && sec <= 59);
485 if (weekday()->IsSmi()) {
486 int weekday = Smi::cast(this->weekday())->value();
487 CHECK(0 <= weekday && weekday <= 6);
489 if (cache_stamp()->IsSmi()) {
490 CHECK(Smi::cast(cache_stamp())->value() <=
491 Smi::cast(GetIsolate()->date_cache()->stamp())->value());
496 void JSMessageObject::JSMessageObjectVerify() {
497 CHECK(IsJSMessageObject());
498 CHECK(type()->IsString());
499 CHECK(arguments()->IsJSArray());
500 VerifyObjectField(kStartPositionOffset);
501 VerifyObjectField(kEndPositionOffset);
502 VerifyObjectField(kArgumentsOffset);
503 VerifyObjectField(kScriptOffset);
504 VerifyObjectField(kStackFramesOffset);
508 void String::StringVerify() {
510 CHECK(length() >= 0 && length() <= Smi::kMaxValue);
511 if (IsInternalizedString()) {
512 CHECK(!GetHeap()->InNewSpace(this));
514 if (IsConsString()) {
515 ConsString::cast(this)->ConsStringVerify();
516 } else if (IsSlicedString()) {
517 SlicedString::cast(this)->SlicedStringVerify();
522 void ConsString::ConsStringVerify() {
523 CHECK(this->first()->IsString());
524 CHECK(this->second() == GetHeap()->empty_string() ||
525 this->second()->IsString());
526 CHECK(this->length() >= ConsString::kMinLength);
527 CHECK(this->length() == this->first()->length() + this->second()->length());
528 if (this->IsFlat()) {
529 // A flat cons can only be created by String::SlowTryFlatten.
530 // Afterwards, the first part may be externalized.
531 CHECK(this->first()->IsSeqString() || this->first()->IsExternalString());
536 void SlicedString::SlicedStringVerify() {
537 CHECK(!this->parent()->IsConsString());
538 CHECK(!this->parent()->IsSlicedString());
539 CHECK(this->length() >= SlicedString::kMinLength);
543 void JSFunction::JSFunctionVerify() {
544 CHECK(IsJSFunction());
545 VerifyObjectField(kPrototypeOrInitialMapOffset);
546 VerifyObjectField(kNextFunctionLinkOffset);
547 CHECK(code()->IsCode());
548 CHECK(next_function_link() == NULL ||
549 next_function_link()->IsUndefined() ||
550 next_function_link()->IsJSFunction());
554 void SharedFunctionInfo::SharedFunctionInfoVerify() {
555 CHECK(IsSharedFunctionInfo());
556 VerifyObjectField(kNameOffset);
557 VerifyObjectField(kCodeOffset);
558 VerifyObjectField(kOptimizedCodeMapOffset);
559 VerifyObjectField(kFeedbackVectorOffset);
560 VerifyObjectField(kScopeInfoOffset);
561 VerifyObjectField(kInstanceClassNameOffset);
562 VerifyObjectField(kFunctionDataOffset);
563 VerifyObjectField(kScriptOffset);
564 VerifyObjectField(kDebugInfoOffset);
568 void JSGlobalProxy::JSGlobalProxyVerify() {
569 CHECK(IsJSGlobalProxy());
571 VerifyObjectField(JSGlobalProxy::kNativeContextOffset);
572 // Make sure that this object has no properties, elements.
573 CHECK_EQ(0, properties()->length());
574 CHECK(HasFastSmiElements());
575 CHECK_EQ(0, FixedArray::cast(elements())->length());
579 void JSGlobalObject::JSGlobalObjectVerify() {
580 CHECK(IsJSGlobalObject());
582 for (int i = GlobalObject::kBuiltinsOffset;
583 i < JSGlobalObject::kSize;
585 VerifyObjectField(i);
590 void JSBuiltinsObject::JSBuiltinsObjectVerify() {
591 CHECK(IsJSBuiltinsObject());
593 for (int i = GlobalObject::kBuiltinsOffset;
594 i < JSBuiltinsObject::kSize;
596 VerifyObjectField(i);
601 void Oddball::OddballVerify() {
603 Heap* heap = GetHeap();
604 VerifyHeapPointer(to_string());
605 Object* number = to_number();
606 if (number->IsHeapObject()) {
607 CHECK(number == heap->nan_value());
609 CHECK(number->IsSmi());
610 int value = Smi::cast(number)->value();
611 // Hidden oddballs have negative smis.
612 const int kLeastHiddenOddballNumber = -5;
614 CHECK(value >= kLeastHiddenOddballNumber);
616 if (map() == heap->undefined_map()) {
617 CHECK(this == heap->undefined_value());
618 } else if (map() == heap->the_hole_map()) {
619 CHECK(this == heap->the_hole_value());
620 } else if (map() == heap->null_map()) {
621 CHECK(this == heap->null_value());
622 } else if (map() == heap->boolean_map()) {
623 CHECK(this == heap->true_value() ||
624 this == heap->false_value());
625 } else if (map() == heap->uninitialized_map()) {
626 CHECK(this == heap->uninitialized_value());
627 } else if (map() == heap->no_interceptor_result_sentinel_map()) {
628 CHECK(this == heap->no_interceptor_result_sentinel());
629 } else if (map() == heap->arguments_marker_map()) {
630 CHECK(this == heap->arguments_marker());
631 } else if (map() == heap->termination_exception_map()) {
632 CHECK(this == heap->termination_exception());
633 } else if (map() == heap->exception_map()) {
634 CHECK(this == heap->exception());
641 void Cell::CellVerify() {
643 VerifyObjectField(kValueOffset);
647 void PropertyCell::PropertyCellVerify() {
648 CHECK(IsPropertyCell());
649 VerifyObjectField(kValueOffset);
650 VerifyObjectField(kTypeOffset);
654 void Code::CodeVerify() {
655 CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
657 relocation_info()->ObjectVerify();
658 Address last_gc_pc = NULL;
659 Isolate* isolate = GetIsolate();
660 for (RelocIterator it(this); !it.done(); it.next()) {
661 it.rinfo()->Verify(isolate);
662 // Ensure that GC will not iterate twice over the same pointer.
663 if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
664 CHECK(it.rinfo()->pc() != last_gc_pc);
665 last_gc_pc = it.rinfo()->pc();
668 CHECK(raw_type_feedback_info() == Smi::FromInt(0) ||
669 raw_type_feedback_info()->IsSmi() == IsCodeStubOrIC());
673 void Code::VerifyEmbeddedObjectsDependency() {
674 if (!CanContainWeakObjects()) return;
675 DisallowHeapAllocation no_gc;
676 Isolate* isolate = GetIsolate();
677 HandleScope scope(isolate);
678 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
679 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
680 Object* obj = it.rinfo()->target_object();
681 if (IsWeakObject(obj)) {
683 Map* map = Map::cast(obj);
684 DependentCode::DependencyGroup group = is_optimized_code() ?
685 DependentCode::kWeakCodeGroup : DependentCode::kWeakICGroup;
686 CHECK(map->dependent_code()->Contains(group, this));
687 } else if (obj->IsJSObject()) {
688 Object* raw_table = GetIsolate()->heap()->weak_object_to_code_table();
689 WeakHashTable* table = WeakHashTable::cast(raw_table);
690 Handle<Object> key_obj(obj, isolate);
691 CHECK(DependentCode::cast(table->Lookup(key_obj))->Contains(
692 DependentCode::kWeakCodeGroup, this));
699 void JSArray::JSArrayVerify() {
701 CHECK(length()->IsNumber() || length()->IsUndefined());
702 // If a GC was caused while constructing this array, the elements
703 // pointer may point to a one pointer filler map.
704 if (ElementsAreSafeToExamine()) {
705 CHECK(elements()->IsUndefined() ||
706 elements()->IsFixedArray() ||
707 elements()->IsFixedDoubleArray());
712 void JSSet::JSSetVerify() {
715 VerifyHeapPointer(table());
716 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
717 // TODO(arv): Verify OrderedHashTable too.
721 void JSMap::JSMapVerify() {
724 VerifyHeapPointer(table());
725 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
726 // TODO(arv): Verify OrderedHashTable too.
730 void JSSetIterator::JSSetIteratorVerify() {
731 CHECK(IsJSSetIterator());
733 VerifyHeapPointer(table());
734 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
735 CHECK(index()->IsSmi() || index()->IsUndefined());
736 CHECK(kind()->IsSmi() || kind()->IsUndefined());
740 void JSMapIterator::JSMapIteratorVerify() {
741 CHECK(IsJSMapIterator());
743 VerifyHeapPointer(table());
744 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
745 CHECK(index()->IsSmi() || index()->IsUndefined());
746 CHECK(kind()->IsSmi() || kind()->IsUndefined());
750 void JSWeakMap::JSWeakMapVerify() {
751 CHECK(IsJSWeakMap());
753 VerifyHeapPointer(table());
754 CHECK(table()->IsHashTable() || table()->IsUndefined());
758 void JSWeakSet::JSWeakSetVerify() {
759 CHECK(IsJSWeakSet());
761 VerifyHeapPointer(table());
762 CHECK(table()->IsHashTable() || table()->IsUndefined());
766 void JSRegExp::JSRegExpVerify() {
768 CHECK(data()->IsUndefined() || data()->IsFixedArray());
770 case JSRegExp::ATOM: {
771 FixedArray* arr = FixedArray::cast(data());
772 CHECK(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
775 case JSRegExp::IRREGEXP: {
776 bool is_native = RegExpImpl::UsesNativeRegExp();
778 FixedArray* arr = FixedArray::cast(data());
779 Object* ascii_data = arr->get(JSRegExp::kIrregexpASCIICodeIndex);
780 // Smi : Not compiled yet (-1) or code prepared for flushing.
781 // JSObject: Compilation error.
782 // Code/ByteArray: Compiled code.
783 CHECK(ascii_data->IsSmi() ||
784 (is_native ? ascii_data->IsCode() : ascii_data->IsByteArray()));
785 Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex);
786 CHECK(uc16_data->IsSmi() ||
787 (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray()));
789 Object* ascii_saved = arr->get(JSRegExp::kIrregexpASCIICodeSavedIndex);
790 CHECK(ascii_saved->IsSmi() || ascii_saved->IsString() ||
791 ascii_saved->IsCode());
792 Object* uc16_saved = arr->get(JSRegExp::kIrregexpUC16CodeSavedIndex);
793 CHECK(uc16_saved->IsSmi() || uc16_saved->IsString() ||
794 uc16_saved->IsCode());
796 CHECK(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi());
797 CHECK(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi());
801 CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag());
802 CHECK(data()->IsUndefined());
808 void JSProxy::JSProxyVerify() {
810 VerifyPointer(handler());
811 CHECK(hash()->IsSmi() || hash()->IsUndefined());
815 void JSFunctionProxy::JSFunctionProxyVerify() {
816 CHECK(IsJSFunctionProxy());
818 VerifyPointer(call_trap());
819 VerifyPointer(construct_trap());
823 void JSArrayBuffer::JSArrayBufferVerify() {
824 CHECK(IsJSArrayBuffer());
826 VerifyPointer(byte_length());
827 CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
828 || byte_length()->IsUndefined());
832 void JSArrayBufferView::JSArrayBufferViewVerify() {
833 CHECK(IsJSArrayBufferView());
835 VerifyPointer(buffer());
836 CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined()
837 || buffer() == Smi::FromInt(0));
839 VerifyPointer(byte_offset());
840 CHECK(byte_offset()->IsSmi() || byte_offset()->IsHeapNumber()
841 || byte_offset()->IsUndefined());
843 VerifyPointer(byte_length());
844 CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
845 || byte_length()->IsUndefined());
849 void JSTypedArray::JSTypedArrayVerify() {
850 CHECK(IsJSTypedArray());
851 JSArrayBufferViewVerify();
852 VerifyPointer(length());
853 CHECK(length()->IsSmi() || length()->IsHeapNumber()
854 || length()->IsUndefined());
856 VerifyPointer(elements());
860 void JSDataView::JSDataViewVerify() {
861 CHECK(IsJSDataView());
862 JSArrayBufferViewVerify();
866 void Foreign::ForeignVerify() {
871 void Box::BoxVerify() {
873 value()->ObjectVerify();
877 void AccessorInfo::AccessorInfoVerify() {
878 VerifyPointer(name());
879 VerifyPointer(flag());
880 VerifyPointer(expected_receiver_type());
884 void ExecutableAccessorInfo::ExecutableAccessorInfoVerify() {
885 CHECK(IsExecutableAccessorInfo());
886 AccessorInfoVerify();
887 VerifyPointer(getter());
888 VerifyPointer(setter());
889 VerifyPointer(data());
893 void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorVerify() {
894 CHECK(IsDeclaredAccessorDescriptor());
895 VerifyPointer(serialized_data());
899 void DeclaredAccessorInfo::DeclaredAccessorInfoVerify() {
900 CHECK(IsDeclaredAccessorInfo());
901 AccessorInfoVerify();
902 VerifyPointer(descriptor());
906 void AccessorPair::AccessorPairVerify() {
907 CHECK(IsAccessorPair());
908 VerifyPointer(getter());
909 VerifyPointer(setter());
913 void AccessCheckInfo::AccessCheckInfoVerify() {
914 CHECK(IsAccessCheckInfo());
915 VerifyPointer(named_callback());
916 VerifyPointer(indexed_callback());
917 VerifyPointer(data());
921 void InterceptorInfo::InterceptorInfoVerify() {
922 CHECK(IsInterceptorInfo());
923 VerifyPointer(getter());
924 VerifyPointer(setter());
925 VerifyPointer(query());
926 VerifyPointer(deleter());
927 VerifyPointer(enumerator());
928 VerifyPointer(data());
932 void CallHandlerInfo::CallHandlerInfoVerify() {
933 CHECK(IsCallHandlerInfo());
934 VerifyPointer(callback());
935 VerifyPointer(data());
939 void TemplateInfo::TemplateInfoVerify() {
940 VerifyPointer(tag());
941 VerifyPointer(property_list());
942 VerifyPointer(property_accessors());
946 void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
947 CHECK(IsFunctionTemplateInfo());
948 TemplateInfoVerify();
949 VerifyPointer(serial_number());
950 VerifyPointer(call_code());
951 VerifyPointer(prototype_template());
952 VerifyPointer(parent_template());
953 VerifyPointer(named_property_handler());
954 VerifyPointer(indexed_property_handler());
955 VerifyPointer(instance_template());
956 VerifyPointer(signature());
957 VerifyPointer(access_check_info());
961 void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
962 CHECK(IsObjectTemplateInfo());
963 TemplateInfoVerify();
964 VerifyPointer(constructor());
965 VerifyPointer(internal_field_count());
969 void SignatureInfo::SignatureInfoVerify() {
970 CHECK(IsSignatureInfo());
971 VerifyPointer(receiver());
972 VerifyPointer(args());
976 void TypeSwitchInfo::TypeSwitchInfoVerify() {
977 CHECK(IsTypeSwitchInfo());
978 VerifyPointer(types());
982 void AllocationSite::AllocationSiteVerify() {
983 CHECK(IsAllocationSite());
987 void AllocationMemento::AllocationMementoVerify() {
988 CHECK(IsAllocationMemento());
989 VerifyHeapPointer(allocation_site());
990 CHECK(!IsValid() || GetAllocationSite()->IsAllocationSite());
994 void Script::ScriptVerify() {
996 VerifyPointer(source());
997 VerifyPointer(name());
998 line_offset()->SmiVerify();
999 column_offset()->SmiVerify();
1000 VerifyPointer(wrapper());
1001 type()->SmiVerify();
1002 VerifyPointer(line_ends());
1003 VerifyPointer(id());
1007 void JSFunctionResultCache::JSFunctionResultCacheVerify() {
1008 JSFunction::cast(get(kFactoryIndex))->ObjectVerify();
1010 int size = Smi::cast(get(kCacheSizeIndex))->value();
1011 CHECK(kEntriesIndex <= size);
1012 CHECK(size <= length());
1013 CHECK_EQ(0, size % kEntrySize);
1015 int finger = Smi::cast(get(kFingerIndex))->value();
1016 CHECK(kEntriesIndex <= finger);
1017 CHECK((finger < size) || (finger == kEntriesIndex && finger == size));
1018 CHECK_EQ(0, finger % kEntrySize);
1020 if (FLAG_enable_slow_asserts) {
1021 for (int i = kEntriesIndex; i < size; i++) {
1022 CHECK(!get(i)->IsTheHole());
1023 get(i)->ObjectVerify();
1025 for (int i = size; i < length(); i++) {
1026 CHECK(get(i)->IsTheHole());
1027 get(i)->ObjectVerify();
1033 void NormalizedMapCache::NormalizedMapCacheVerify() {
1034 FixedArray::cast(this)->FixedArrayVerify();
1035 if (FLAG_enable_slow_asserts) {
1036 for (int i = 0; i < length(); i++) {
1037 Object* e = FixedArray::get(i);
1039 Map::cast(e)->DictionaryMapVerify();
1041 CHECK(e->IsUndefined());
1048 void DebugInfo::DebugInfoVerify() {
1049 CHECK(IsDebugInfo());
1050 VerifyPointer(shared());
1051 VerifyPointer(original_code());
1052 VerifyPointer(code());
1053 VerifyPointer(break_points());
1057 void BreakPointInfo::BreakPointInfoVerify() {
1058 CHECK(IsBreakPointInfo());
1059 code_position()->SmiVerify();
1060 source_position()->SmiVerify();
1061 statement_position()->SmiVerify();
1062 VerifyPointer(break_point_objects());
1064 #endif // VERIFY_HEAP
1068 void JSObject::IncrementSpillStatistics(SpillInformation* info) {
1069 info->number_of_objects_++;
1071 if (HasFastProperties()) {
1072 info->number_of_objects_with_fast_properties_++;
1073 info->number_of_fast_used_fields_ += map()->NextFreePropertyIndex();
1074 info->number_of_fast_unused_fields_ += map()->unused_property_fields();
1076 NameDictionary* dict = property_dictionary();
1077 info->number_of_slow_used_properties_ += dict->NumberOfElements();
1078 info->number_of_slow_unused_properties_ +=
1079 dict->Capacity() - dict->NumberOfElements();
1081 // Indexed properties
1082 switch (GetElementsKind()) {
1083 case FAST_HOLEY_SMI_ELEMENTS:
1084 case FAST_SMI_ELEMENTS:
1085 case FAST_HOLEY_DOUBLE_ELEMENTS:
1086 case FAST_DOUBLE_ELEMENTS:
1087 case FAST_HOLEY_ELEMENTS:
1088 case FAST_ELEMENTS: {
1089 info->number_of_objects_with_fast_elements_++;
1091 FixedArray* e = FixedArray::cast(elements());
1092 int len = e->length();
1093 Heap* heap = GetHeap();
1094 for (int i = 0; i < len; i++) {
1095 if (e->get(i) == heap->the_hole_value()) holes++;
1097 info->number_of_fast_used_elements_ += len - holes;
1098 info->number_of_fast_unused_elements_ += holes;
1102 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
1103 case EXTERNAL_##TYPE##_ELEMENTS: \
1104 case TYPE##_ELEMENTS:
1106 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1107 #undef TYPED_ARRAY_CASE
1108 { info->number_of_objects_with_fast_elements_++;
1109 FixedArrayBase* e = FixedArrayBase::cast(elements());
1110 info->number_of_fast_used_elements_ += e->length();
1113 case DICTIONARY_ELEMENTS: {
1114 SeededNumberDictionary* dict = element_dictionary();
1115 info->number_of_slow_used_elements_ += dict->NumberOfElements();
1116 info->number_of_slow_unused_elements_ +=
1117 dict->Capacity() - dict->NumberOfElements();
1120 case SLOPPY_ARGUMENTS_ELEMENTS:
1126 void JSObject::SpillInformation::Clear() {
1127 number_of_objects_ = 0;
1128 number_of_objects_with_fast_properties_ = 0;
1129 number_of_objects_with_fast_elements_ = 0;
1130 number_of_fast_used_fields_ = 0;
1131 number_of_fast_unused_fields_ = 0;
1132 number_of_slow_used_properties_ = 0;
1133 number_of_slow_unused_properties_ = 0;
1134 number_of_fast_used_elements_ = 0;
1135 number_of_fast_unused_elements_ = 0;
1136 number_of_slow_used_elements_ = 0;
1137 number_of_slow_unused_elements_ = 0;
1141 void JSObject::SpillInformation::Print() {
1142 PrintF("\n JSObject Spill Statistics (#%d):\n", number_of_objects_);
1144 PrintF(" - fast properties (#%d): %d (used) %d (unused)\n",
1145 number_of_objects_with_fast_properties_,
1146 number_of_fast_used_fields_, number_of_fast_unused_fields_);
1148 PrintF(" - slow properties (#%d): %d (used) %d (unused)\n",
1149 number_of_objects_ - number_of_objects_with_fast_properties_,
1150 number_of_slow_used_properties_, number_of_slow_unused_properties_);
1152 PrintF(" - fast elements (#%d): %d (used) %d (unused)\n",
1153 number_of_objects_with_fast_elements_,
1154 number_of_fast_used_elements_, number_of_fast_unused_elements_);
1156 PrintF(" - slow elements (#%d): %d (used) %d (unused)\n",
1157 number_of_objects_ - number_of_objects_with_fast_elements_,
1158 number_of_slow_used_elements_, number_of_slow_unused_elements_);
1164 bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) {
1165 if (valid_entries == -1) valid_entries = number_of_descriptors();
1166 Name* current_key = NULL;
1167 uint32_t current = 0;
1168 for (int i = 0; i < number_of_descriptors(); i++) {
1169 Name* key = GetSortedKey(i);
1170 if (key == current_key) {
1171 OFStream os(stdout);
1172 PrintDescriptors(os);
1176 uint32_t hash = GetSortedKey(i)->Hash();
1177 if (hash < current) {
1178 OFStream os(stdout);
1179 PrintDescriptors(os);
1188 bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
1189 DCHECK(valid_entries == -1);
1190 Name* current_key = NULL;
1191 uint32_t current = 0;
1192 for (int i = 0; i < number_of_transitions(); i++) {
1193 Name* key = GetSortedKey(i);
1194 if (key == current_key) {
1195 OFStream os(stdout);
1196 PrintTransitions(os);
1200 uint32_t hash = GetSortedKey(i)->Hash();
1201 if (hash < current) {
1202 OFStream os(stdout);
1203 PrintTransitions(os);
1212 static bool CheckOneBackPointer(Map* current_map, Object* target) {
1213 return !target->IsMap() || Map::cast(target)->GetBackPointer() == current_map;
1217 bool TransitionArray::IsConsistentWithBackPointers(Map* current_map) {
1218 for (int i = 0; i < number_of_transitions(); ++i) {
1219 if (!CheckOneBackPointer(current_map, GetTarget(i))) return false;
1227 } } // namespace v8::internal