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.
4
5#include "src/v8.h"
6
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"
13
14namespace v8 {
15namespace internal {
16
17#ifdef VERIFY_HEAP
18
19void Object::ObjectVerify() {
20  if (IsSmi()) {
21    Smi::cast(this)->SmiVerify();
22  } else {
23    HeapObject::cast(this)->HeapObjectVerify();
24  }
25}
26
27
28void Object::VerifyPointer(Object* p) {
29  if (p->IsHeapObject()) {
30    HeapObject::VerifyHeapPointer(p);
31  } else {
32    CHECK(p->IsSmi());
33  }
34}
35
36
37void Smi::SmiVerify() {
38  CHECK(IsSmi());
39}
40
41
42void HeapObject::HeapObjectVerify() {
43  InstanceType instance_type = map()->instance_type();
44
45  if (instance_type < FIRST_NONSTRING_TYPE) {
46    String::cast(this)->StringVerify();
47    return;
48  }
49
50  switch (instance_type) {
51    case SYMBOL_TYPE:
52      Symbol::cast(this)->SymbolVerify();
53      break;
54    case MAP_TYPE:
55      Map::cast(this)->MapVerify();
56      break;
57    case HEAP_NUMBER_TYPE:
58    case MUTABLE_HEAP_NUMBER_TYPE:
59      HeapNumber::cast(this)->HeapNumberVerify();
60      break;
61    case FIXED_ARRAY_TYPE:
62      FixedArray::cast(this)->FixedArrayVerify();
63      break;
64    case FIXED_DOUBLE_ARRAY_TYPE:
65      FixedDoubleArray::cast(this)->FixedDoubleArrayVerify();
66      break;
67    case CONSTANT_POOL_ARRAY_TYPE:
68      ConstantPoolArray::cast(this)->ConstantPoolArrayVerify();
69      break;
70    case BYTE_ARRAY_TYPE:
71      ByteArray::cast(this)->ByteArrayVerify();
72      break;
73    case FREE_SPACE_TYPE:
74      FreeSpace::cast(this)->FreeSpaceVerify();
75      break;
76
77#define VERIFY_TYPED_ARRAY(Type, type, TYPE, ctype, size)                      \
78    case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
79      External##Type##Array::cast(this)->External##Type##ArrayVerify();        \
80      break;                                                                   \
81    case FIXED_##TYPE##_ARRAY_TYPE:                                            \
82      Fixed##Type##Array::cast(this)->FixedTypedArrayVerify();                 \
83      break;
84
85    TYPED_ARRAYS(VERIFY_TYPED_ARRAY)
86#undef VERIFY_TYPED_ARRAY
87
88    case CODE_TYPE:
89      Code::cast(this)->CodeVerify();
90      break;
91    case ODDBALL_TYPE:
92      Oddball::cast(this)->OddballVerify();
93      break;
94    case JS_OBJECT_TYPE:
95    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
96      JSObject::cast(this)->JSObjectVerify();
97      break;
98    case JS_GENERATOR_OBJECT_TYPE:
99      JSGeneratorObject::cast(this)->JSGeneratorObjectVerify();
100      break;
101    case JS_MODULE_TYPE:
102      JSModule::cast(this)->JSModuleVerify();
103      break;
104    case JS_VALUE_TYPE:
105      JSValue::cast(this)->JSValueVerify();
106      break;
107    case JS_DATE_TYPE:
108      JSDate::cast(this)->JSDateVerify();
109      break;
110    case JS_FUNCTION_TYPE:
111      JSFunction::cast(this)->JSFunctionVerify();
112      break;
113    case JS_GLOBAL_PROXY_TYPE:
114      JSGlobalProxy::cast(this)->JSGlobalProxyVerify();
115      break;
116    case JS_GLOBAL_OBJECT_TYPE:
117      JSGlobalObject::cast(this)->JSGlobalObjectVerify();
118      break;
119    case JS_BUILTINS_OBJECT_TYPE:
120      JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
121      break;
122    case CELL_TYPE:
123      Cell::cast(this)->CellVerify();
124      break;
125    case PROPERTY_CELL_TYPE:
126      PropertyCell::cast(this)->PropertyCellVerify();
127      break;
128    case JS_ARRAY_TYPE:
129      JSArray::cast(this)->JSArrayVerify();
130      break;
131    case JS_SET_TYPE:
132      JSSet::cast(this)->JSSetVerify();
133      break;
134    case JS_MAP_TYPE:
135      JSMap::cast(this)->JSMapVerify();
136      break;
137    case JS_SET_ITERATOR_TYPE:
138      JSSetIterator::cast(this)->JSSetIteratorVerify();
139      break;
140    case JS_MAP_ITERATOR_TYPE:
141      JSMapIterator::cast(this)->JSMapIteratorVerify();
142      break;
143    case JS_WEAK_MAP_TYPE:
144      JSWeakMap::cast(this)->JSWeakMapVerify();
145      break;
146    case JS_WEAK_SET_TYPE:
147      JSWeakSet::cast(this)->JSWeakSetVerify();
148      break;
149    case JS_REGEXP_TYPE:
150      JSRegExp::cast(this)->JSRegExpVerify();
151      break;
152    case FILLER_TYPE:
153      break;
154    case JS_PROXY_TYPE:
155      JSProxy::cast(this)->JSProxyVerify();
156      break;
157    case JS_FUNCTION_PROXY_TYPE:
158      JSFunctionProxy::cast(this)->JSFunctionProxyVerify();
159      break;
160    case FOREIGN_TYPE:
161      Foreign::cast(this)->ForeignVerify();
162      break;
163    case SHARED_FUNCTION_INFO_TYPE:
164      SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
165      break;
166    case JS_MESSAGE_OBJECT_TYPE:
167      JSMessageObject::cast(this)->JSMessageObjectVerify();
168      break;
169    case JS_ARRAY_BUFFER_TYPE:
170      JSArrayBuffer::cast(this)->JSArrayBufferVerify();
171      break;
172    case JS_TYPED_ARRAY_TYPE:
173      JSTypedArray::cast(this)->JSTypedArrayVerify();
174      break;
175    case JS_DATA_VIEW_TYPE:
176      JSDataView::cast(this)->JSDataViewVerify();
177      break;
178
179#define MAKE_STRUCT_CASE(NAME, Name, name) \
180  case NAME##_TYPE:                        \
181    Name::cast(this)->Name##Verify();      \
182    break;
183    STRUCT_LIST(MAKE_STRUCT_CASE)
184#undef MAKE_STRUCT_CASE
185
186    default:
187      UNREACHABLE();
188      break;
189  }
190}
191
192
193void HeapObject::VerifyHeapPointer(Object* p) {
194  CHECK(p->IsHeapObject());
195  HeapObject* ho = HeapObject::cast(p);
196  CHECK(ho->GetHeap()->Contains(ho));
197}
198
199
200void Symbol::SymbolVerify() {
201  CHECK(IsSymbol());
202  CHECK(HasHashCode());
203  CHECK_GT(Hash(), 0);
204  CHECK(name()->IsUndefined() || name()->IsString());
205  CHECK(flags()->IsSmi());
206}
207
208
209void HeapNumber::HeapNumberVerify() {
210  CHECK(IsHeapNumber() || IsMutableHeapNumber());
211}
212
213
214void ByteArray::ByteArrayVerify() {
215  CHECK(IsByteArray());
216}
217
218
219void FreeSpace::FreeSpaceVerify() {
220  CHECK(IsFreeSpace());
221}
222
223
224#define EXTERNAL_ARRAY_VERIFY(Type, type, TYPE, ctype, size)                  \
225  void External##Type##Array::External##Type##ArrayVerify() {                 \
226    CHECK(IsExternal##Type##Array());                                         \
227  }
228
229TYPED_ARRAYS(EXTERNAL_ARRAY_VERIFY)
230#undef EXTERNAL_ARRAY_VERIFY
231
232
233template <class Traits>
234void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
235  CHECK(IsHeapObject() &&
236        HeapObject::cast(this)->map()->instance_type() ==
237            Traits::kInstanceType);
238}
239
240
241bool JSObject::ElementsAreSafeToExamine() {
242  // If a GC was caused while constructing this object, the elements
243  // pointer may point to a one pointer filler map.
244  return reinterpret_cast<Map*>(elements()) !=
245      GetHeap()->one_pointer_filler_map();
246}
247
248
249void JSObject::JSObjectVerify() {
250  VerifyHeapPointer(properties());
251  VerifyHeapPointer(elements());
252
253  if (GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS) {
254    CHECK(this->elements()->IsFixedArray());
255    CHECK_GE(this->elements()->length(), 2);
256  }
257
258  if (HasFastProperties()) {
259    CHECK_EQ(map()->unused_property_fields(),
260             (map()->inobject_properties() + properties()->length() -
261              map()->NextFreePropertyIndex()));
262    DescriptorArray* descriptors = map()->instance_descriptors();
263    for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
264      if (descriptors->GetDetails(i).type() == FIELD) {
265        Representation r = descriptors->GetDetails(i).representation();
266        FieldIndex index = FieldIndex::ForDescriptor(map(), i);
267        Object* value = RawFastPropertyAt(index);
268        if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber());
269        if (value->IsUninitialized()) continue;
270        if (r.IsSmi()) DCHECK(value->IsSmi());
271        if (r.IsHeapObject()) DCHECK(value->IsHeapObject());
272        HeapType* field_type = descriptors->GetFieldType(i);
273        if (r.IsNone()) {
274          CHECK(field_type->Is(HeapType::None()));
275        } else if (!HeapType::Any()->Is(field_type)) {
276          CHECK(!field_type->NowStable() || field_type->NowContains(value));
277        }
278      }
279    }
280  }
281
282  // If a GC was caused while constructing this object, the elements
283  // pointer may point to a one pointer filler map.
284  if (ElementsAreSafeToExamine()) {
285    CHECK_EQ((map()->has_fast_smi_or_object_elements() ||
286              (elements() == GetHeap()->empty_fixed_array())),
287             (elements()->map() == GetHeap()->fixed_array_map() ||
288              elements()->map() == GetHeap()->fixed_cow_array_map()));
289    CHECK(map()->has_fast_object_elements() == HasFastObjectElements());
290  }
291}
292
293
294void Map::MapVerify() {
295  Heap* heap = GetHeap();
296  CHECK(!heap->InNewSpace(this));
297  CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
298  CHECK(instance_size() == kVariableSizeSentinel ||
299         (kPointerSize <= instance_size() &&
300          instance_size() < heap->Capacity()));
301  VerifyHeapPointer(prototype());
302  VerifyHeapPointer(instance_descriptors());
303  SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates());
304  if (HasTransitionArray()) {
305    SLOW_DCHECK(transitions()->IsSortedNoDuplicates());
306    SLOW_DCHECK(transitions()->IsConsistentWithBackPointers(this));
307  }
308}
309
310
311void Map::DictionaryMapVerify() {
312  MapVerify();
313  CHECK(is_dictionary_map());
314  CHECK(instance_descriptors()->IsEmpty());
315  CHECK_EQ(0, pre_allocated_property_fields());
316  CHECK_EQ(0, unused_property_fields());
317  CHECK_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
318      visitor_id());
319}
320
321
322void Map::VerifyOmittedMapChecks() {
323  if (!FLAG_omit_map_checks_for_leaf_maps) return;
324  if (!is_stable() ||
325      is_deprecated() ||
326      HasTransitionArray() ||
327      is_dictionary_map()) {
328    CHECK_EQ(0, dependent_code()->number_of_entries(
329        DependentCode::kPrototypeCheckGroup));
330  }
331}
332
333
334void CodeCache::CodeCacheVerify() {
335  VerifyHeapPointer(default_cache());
336  VerifyHeapPointer(normal_type_cache());
337  CHECK(default_cache()->IsFixedArray());
338  CHECK(normal_type_cache()->IsUndefined()
339         || normal_type_cache()->IsCodeCacheHashTable());
340}
341
342
343void PolymorphicCodeCache::PolymorphicCodeCacheVerify() {
344  VerifyHeapPointer(cache());
345  CHECK(cache()->IsUndefined() || cache()->IsPolymorphicCodeCacheHashTable());
346}
347
348
349void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
350  VerifyObjectField(kStorage1Offset);
351  VerifyObjectField(kStorage2Offset);
352  VerifyObjectField(kStorage3Offset);
353}
354
355
356void AliasedArgumentsEntry::AliasedArgumentsEntryVerify() {
357  VerifySmiField(kAliasedContextSlot);
358}
359
360
361void FixedArray::FixedArrayVerify() {
362  for (int i = 0; i < length(); i++) {
363    Object* e = get(i);
364    VerifyPointer(e);
365  }
366}
367
368
369void FixedDoubleArray::FixedDoubleArrayVerify() {
370  for (int i = 0; i < length(); i++) {
371    if (!is_the_hole(i)) {
372      double value = get_scalar(i);
373      CHECK(!std::isnan(value) ||
374            (bit_cast<uint64_t>(value) ==
375             bit_cast<uint64_t>(canonical_not_the_hole_nan_as_double())) ||
376            ((bit_cast<uint64_t>(value) & Double::kSignMask) != 0));
377    }
378  }
379}
380
381
382void ConstantPoolArray::ConstantPoolArrayVerify() {
383  CHECK(IsConstantPoolArray());
384  ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR);
385  while (!code_iter.is_finished()) {
386    Address code_entry = get_code_ptr_entry(code_iter.next_index());
387    VerifyPointer(Code::GetCodeFromTargetAddress(code_entry));
388  }
389  ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR);
390  while (!heap_iter.is_finished()) {
391    VerifyObjectField(OffsetOfElementAt(heap_iter.next_index()));
392  }
393}
394
395
396void JSGeneratorObject::JSGeneratorObjectVerify() {
397  // In an expression like "new g()", there can be a point where a generator
398  // object is allocated but its fields are all undefined, as it hasn't yet been
399  // initialized by the generator.  Hence these weak checks.
400  VerifyObjectField(kFunctionOffset);
401  VerifyObjectField(kContextOffset);
402  VerifyObjectField(kReceiverOffset);
403  VerifyObjectField(kOperandStackOffset);
404  VerifyObjectField(kContinuationOffset);
405  VerifyObjectField(kStackHandlerIndexOffset);
406}
407
408
409void JSModule::JSModuleVerify() {
410  VerifyObjectField(kContextOffset);
411  VerifyObjectField(kScopeInfoOffset);
412  CHECK(context()->IsUndefined() ||
413        Context::cast(context())->IsModuleContext());
414}
415
416
417void JSValue::JSValueVerify() {
418  Object* v = value();
419  if (v->IsHeapObject()) {
420    VerifyHeapPointer(v);
421  }
422}
423
424
425void JSDate::JSDateVerify() {
426  if (value()->IsHeapObject()) {
427    VerifyHeapPointer(value());
428  }
429  CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber());
430  CHECK(year()->IsUndefined() || year()->IsSmi() || year()->IsNaN());
431  CHECK(month()->IsUndefined() || month()->IsSmi() || month()->IsNaN());
432  CHECK(day()->IsUndefined() || day()->IsSmi() || day()->IsNaN());
433  CHECK(weekday()->IsUndefined() || weekday()->IsSmi() || weekday()->IsNaN());
434  CHECK(hour()->IsUndefined() || hour()->IsSmi() || hour()->IsNaN());
435  CHECK(min()->IsUndefined() || min()->IsSmi() || min()->IsNaN());
436  CHECK(sec()->IsUndefined() || sec()->IsSmi() || sec()->IsNaN());
437  CHECK(cache_stamp()->IsUndefined() ||
438        cache_stamp()->IsSmi() ||
439        cache_stamp()->IsNaN());
440
441  if (month()->IsSmi()) {
442    int month = Smi::cast(this->month())->value();
443    CHECK(0 <= month && month <= 11);
444  }
445  if (day()->IsSmi()) {
446    int day = Smi::cast(this->day())->value();
447    CHECK(1 <= day && day <= 31);
448  }
449  if (hour()->IsSmi()) {
450    int hour = Smi::cast(this->hour())->value();
451    CHECK(0 <= hour && hour <= 23);
452  }
453  if (min()->IsSmi()) {
454    int min = Smi::cast(this->min())->value();
455    CHECK(0 <= min && min <= 59);
456  }
457  if (sec()->IsSmi()) {
458    int sec = Smi::cast(this->sec())->value();
459    CHECK(0 <= sec && sec <= 59);
460  }
461  if (weekday()->IsSmi()) {
462    int weekday = Smi::cast(this->weekday())->value();
463    CHECK(0 <= weekday && weekday <= 6);
464  }
465  if (cache_stamp()->IsSmi()) {
466    CHECK(Smi::cast(cache_stamp())->value() <=
467          Smi::cast(GetIsolate()->date_cache()->stamp())->value());
468  }
469}
470
471
472void JSMessageObject::JSMessageObjectVerify() {
473  CHECK(IsJSMessageObject());
474  CHECK(type()->IsString());
475  CHECK(arguments()->IsJSArray());
476  VerifyObjectField(kStartPositionOffset);
477  VerifyObjectField(kEndPositionOffset);
478  VerifyObjectField(kArgumentsOffset);
479  VerifyObjectField(kScriptOffset);
480  VerifyObjectField(kStackFramesOffset);
481}
482
483
484void String::StringVerify() {
485  CHECK(IsString());
486  CHECK(length() >= 0 && length() <= Smi::kMaxValue);
487  if (IsInternalizedString()) {
488    CHECK(!GetHeap()->InNewSpace(this));
489  }
490  if (IsConsString()) {
491    ConsString::cast(this)->ConsStringVerify();
492  } else if (IsSlicedString()) {
493    SlicedString::cast(this)->SlicedStringVerify();
494  }
495}
496
497
498void ConsString::ConsStringVerify() {
499  CHECK(this->first()->IsString());
500  CHECK(this->second() == GetHeap()->empty_string() ||
501        this->second()->IsString());
502  CHECK(this->length() >= ConsString::kMinLength);
503  CHECK(this->length() == this->first()->length() + this->second()->length());
504  if (this->IsFlat()) {
505    // A flat cons can only be created by String::SlowTryFlatten.
506    // Afterwards, the first part may be externalized.
507    CHECK(this->first()->IsSeqString() || this->first()->IsExternalString());
508  }
509}
510
511
512void SlicedString::SlicedStringVerify() {
513  CHECK(!this->parent()->IsConsString());
514  CHECK(!this->parent()->IsSlicedString());
515  CHECK(this->length() >= SlicedString::kMinLength);
516}
517
518
519void JSFunction::JSFunctionVerify() {
520  CHECK(IsJSFunction());
521  VerifyObjectField(kPrototypeOrInitialMapOffset);
522  VerifyObjectField(kNextFunctionLinkOffset);
523  CHECK(code()->IsCode());
524  CHECK(next_function_link() == NULL ||
525        next_function_link()->IsUndefined() ||
526        next_function_link()->IsJSFunction());
527}
528
529
530void SharedFunctionInfo::SharedFunctionInfoVerify() {
531  CHECK(IsSharedFunctionInfo());
532  VerifyObjectField(kNameOffset);
533  VerifyObjectField(kCodeOffset);
534  VerifyObjectField(kOptimizedCodeMapOffset);
535  VerifyObjectField(kFeedbackVectorOffset);
536  VerifyObjectField(kScopeInfoOffset);
537  VerifyObjectField(kInstanceClassNameOffset);
538  VerifyObjectField(kFunctionDataOffset);
539  VerifyObjectField(kScriptOffset);
540  VerifyObjectField(kDebugInfoOffset);
541}
542
543
544void JSGlobalProxy::JSGlobalProxyVerify() {
545  CHECK(IsJSGlobalProxy());
546  JSObjectVerify();
547  VerifyObjectField(JSGlobalProxy::kNativeContextOffset);
548  // Make sure that this object has no properties, elements.
549  CHECK_EQ(0, properties()->length());
550  CHECK(HasFastSmiElements());
551  CHECK_EQ(0, FixedArray::cast(elements())->length());
552}
553
554
555void JSGlobalObject::JSGlobalObjectVerify() {
556  CHECK(IsJSGlobalObject());
557  JSObjectVerify();
558  for (int i = GlobalObject::kBuiltinsOffset;
559       i < JSGlobalObject::kSize;
560       i += kPointerSize) {
561    VerifyObjectField(i);
562  }
563}
564
565
566void JSBuiltinsObject::JSBuiltinsObjectVerify() {
567  CHECK(IsJSBuiltinsObject());
568  JSObjectVerify();
569  for (int i = GlobalObject::kBuiltinsOffset;
570       i < JSBuiltinsObject::kSize;
571       i += kPointerSize) {
572    VerifyObjectField(i);
573  }
574}
575
576
577void Oddball::OddballVerify() {
578  CHECK(IsOddball());
579  Heap* heap = GetHeap();
580  VerifyHeapPointer(to_string());
581  Object* number = to_number();
582  if (number->IsHeapObject()) {
583    CHECK(number == heap->nan_value());
584  } else {
585    CHECK(number->IsSmi());
586    int value = Smi::cast(number)->value();
587    // Hidden oddballs have negative smis.
588    const int kLeastHiddenOddballNumber = -5;
589    CHECK_LE(value, 1);
590    CHECK(value >= kLeastHiddenOddballNumber);
591  }
592  if (map() == heap->undefined_map()) {
593    CHECK(this == heap->undefined_value());
594  } else if (map() == heap->the_hole_map()) {
595    CHECK(this == heap->the_hole_value());
596  } else if (map() == heap->null_map()) {
597    CHECK(this == heap->null_value());
598  } else if (map() == heap->boolean_map()) {
599    CHECK(this == heap->true_value() ||
600          this == heap->false_value());
601  } else if (map() == heap->uninitialized_map()) {
602    CHECK(this == heap->uninitialized_value());
603  } else if (map() == heap->no_interceptor_result_sentinel_map()) {
604    CHECK(this == heap->no_interceptor_result_sentinel());
605  } else if (map() == heap->arguments_marker_map()) {
606    CHECK(this == heap->arguments_marker());
607  } else if (map() == heap->termination_exception_map()) {
608    CHECK(this == heap->termination_exception());
609  } else if (map() == heap->exception_map()) {
610    CHECK(this == heap->exception());
611  } else {
612    UNREACHABLE();
613  }
614}
615
616
617void Cell::CellVerify() {
618  CHECK(IsCell());
619  VerifyObjectField(kValueOffset);
620}
621
622
623void PropertyCell::PropertyCellVerify() {
624  CHECK(IsPropertyCell());
625  VerifyObjectField(kValueOffset);
626  VerifyObjectField(kTypeOffset);
627}
628
629
630void Code::CodeVerify() {
631  CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
632                  kCodeAlignment));
633  relocation_info()->ObjectVerify();
634  Address last_gc_pc = NULL;
635  Isolate* isolate = GetIsolate();
636  for (RelocIterator it(this); !it.done(); it.next()) {
637    it.rinfo()->Verify(isolate);
638    // Ensure that GC will not iterate twice over the same pointer.
639    if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
640      CHECK(it.rinfo()->pc() != last_gc_pc);
641      last_gc_pc = it.rinfo()->pc();
642    }
643  }
644  CHECK(raw_type_feedback_info() == Smi::FromInt(0) ||
645        raw_type_feedback_info()->IsSmi() == IsCodeStubOrIC());
646}
647
648
649void Code::VerifyEmbeddedObjectsDependency() {
650  if (!CanContainWeakObjects()) return;
651  DisallowHeapAllocation no_gc;
652  Isolate* isolate = GetIsolate();
653  HandleScope scope(isolate);
654  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
655  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
656    Object* obj = it.rinfo()->target_object();
657    if (IsWeakObject(obj)) {
658      if (obj->IsMap()) {
659        Map* map = Map::cast(obj);
660        DependentCode::DependencyGroup group = is_optimized_code() ?
661            DependentCode::kWeakCodeGroup : DependentCode::kWeakICGroup;
662        CHECK(map->dependent_code()->Contains(group, this));
663      } else if (obj->IsJSObject()) {
664        Object* raw_table = GetIsolate()->heap()->weak_object_to_code_table();
665        WeakHashTable* table = WeakHashTable::cast(raw_table);
666        Handle<Object> key_obj(obj, isolate);
667        CHECK(DependentCode::cast(table->Lookup(key_obj))->Contains(
668            DependentCode::kWeakCodeGroup, this));
669      }
670    }
671  }
672}
673
674
675void JSArray::JSArrayVerify() {
676  JSObjectVerify();
677  CHECK(length()->IsNumber() || length()->IsUndefined());
678  // If a GC was caused while constructing this array, the elements
679  // pointer may point to a one pointer filler map.
680  if (ElementsAreSafeToExamine()) {
681    CHECK(elements()->IsUndefined() ||
682          elements()->IsFixedArray() ||
683          elements()->IsFixedDoubleArray());
684  }
685}
686
687
688void JSSet::JSSetVerify() {
689  CHECK(IsJSSet());
690  JSObjectVerify();
691  VerifyHeapPointer(table());
692  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
693  // TODO(arv): Verify OrderedHashTable too.
694}
695
696
697void JSMap::JSMapVerify() {
698  CHECK(IsJSMap());
699  JSObjectVerify();
700  VerifyHeapPointer(table());
701  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
702  // TODO(arv): Verify OrderedHashTable too.
703}
704
705
706void JSSetIterator::JSSetIteratorVerify() {
707  CHECK(IsJSSetIterator());
708  JSObjectVerify();
709  VerifyHeapPointer(table());
710  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
711  CHECK(index()->IsSmi() || index()->IsUndefined());
712  CHECK(kind()->IsSmi() || kind()->IsUndefined());
713}
714
715
716void JSMapIterator::JSMapIteratorVerify() {
717  CHECK(IsJSMapIterator());
718  JSObjectVerify();
719  VerifyHeapPointer(table());
720  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
721  CHECK(index()->IsSmi() || index()->IsUndefined());
722  CHECK(kind()->IsSmi() || kind()->IsUndefined());
723}
724
725
726void JSWeakMap::JSWeakMapVerify() {
727  CHECK(IsJSWeakMap());
728  JSObjectVerify();
729  VerifyHeapPointer(table());
730  CHECK(table()->IsHashTable() || table()->IsUndefined());
731}
732
733
734void JSWeakSet::JSWeakSetVerify() {
735  CHECK(IsJSWeakSet());
736  JSObjectVerify();
737  VerifyHeapPointer(table());
738  CHECK(table()->IsHashTable() || table()->IsUndefined());
739}
740
741
742void JSRegExp::JSRegExpVerify() {
743  JSObjectVerify();
744  CHECK(data()->IsUndefined() || data()->IsFixedArray());
745  switch (TypeTag()) {
746    case JSRegExp::ATOM: {
747      FixedArray* arr = FixedArray::cast(data());
748      CHECK(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
749      break;
750    }
751    case JSRegExp::IRREGEXP: {
752      bool is_native = RegExpImpl::UsesNativeRegExp();
753
754      FixedArray* arr = FixedArray::cast(data());
755      Object* one_byte_data = arr->get(JSRegExp::kIrregexpLatin1CodeIndex);
756      // Smi : Not compiled yet (-1) or code prepared for flushing.
757      // JSObject: Compilation error.
758      // Code/ByteArray: Compiled code.
759      CHECK(
760          one_byte_data->IsSmi() ||
761          (is_native ? one_byte_data->IsCode() : one_byte_data->IsByteArray()));
762      Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex);
763      CHECK(uc16_data->IsSmi() ||
764             (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray()));
765
766      Object* one_byte_saved =
767          arr->get(JSRegExp::kIrregexpLatin1CodeSavedIndex);
768      CHECK(one_byte_saved->IsSmi() || one_byte_saved->IsString() ||
769            one_byte_saved->IsCode());
770      Object* uc16_saved = arr->get(JSRegExp::kIrregexpUC16CodeSavedIndex);
771      CHECK(uc16_saved->IsSmi() || uc16_saved->IsString() ||
772             uc16_saved->IsCode());
773
774      CHECK(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi());
775      CHECK(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi());
776      break;
777    }
778    default:
779      CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag());
780      CHECK(data()->IsUndefined());
781      break;
782  }
783}
784
785
786void JSProxy::JSProxyVerify() {
787  CHECK(IsJSProxy());
788  VerifyPointer(handler());
789  CHECK(hash()->IsSmi() || hash()->IsUndefined());
790}
791
792
793void JSFunctionProxy::JSFunctionProxyVerify() {
794  CHECK(IsJSFunctionProxy());
795  JSProxyVerify();
796  VerifyPointer(call_trap());
797  VerifyPointer(construct_trap());
798}
799
800
801void JSArrayBuffer::JSArrayBufferVerify() {
802  CHECK(IsJSArrayBuffer());
803  JSObjectVerify();
804  VerifyPointer(byte_length());
805  CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
806        || byte_length()->IsUndefined());
807}
808
809
810void JSArrayBufferView::JSArrayBufferViewVerify() {
811  CHECK(IsJSArrayBufferView());
812  JSObjectVerify();
813  VerifyPointer(buffer());
814  CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined()
815        || buffer() == Smi::FromInt(0));
816
817  VerifyPointer(byte_offset());
818  CHECK(byte_offset()->IsSmi() || byte_offset()->IsHeapNumber()
819        || byte_offset()->IsUndefined());
820
821  VerifyPointer(byte_length());
822  CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
823        || byte_length()->IsUndefined());
824}
825
826
827void JSTypedArray::JSTypedArrayVerify() {
828  CHECK(IsJSTypedArray());
829  JSArrayBufferViewVerify();
830  VerifyPointer(length());
831  CHECK(length()->IsSmi() || length()->IsHeapNumber()
832        || length()->IsUndefined());
833
834  VerifyPointer(elements());
835}
836
837
838void JSDataView::JSDataViewVerify() {
839  CHECK(IsJSDataView());
840  JSArrayBufferViewVerify();
841}
842
843
844void Foreign::ForeignVerify() {
845  CHECK(IsForeign());
846}
847
848
849void Box::BoxVerify() {
850  CHECK(IsBox());
851  value()->ObjectVerify();
852}
853
854
855void AccessorInfo::AccessorInfoVerify() {
856  VerifyPointer(name());
857  VerifyPointer(flag());
858  VerifyPointer(expected_receiver_type());
859}
860
861
862void ExecutableAccessorInfo::ExecutableAccessorInfoVerify() {
863  CHECK(IsExecutableAccessorInfo());
864  AccessorInfoVerify();
865  VerifyPointer(getter());
866  VerifyPointer(setter());
867  VerifyPointer(data());
868}
869
870
871void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorVerify() {
872  CHECK(IsDeclaredAccessorDescriptor());
873  VerifyPointer(serialized_data());
874}
875
876
877void DeclaredAccessorInfo::DeclaredAccessorInfoVerify() {
878  CHECK(IsDeclaredAccessorInfo());
879  AccessorInfoVerify();
880  VerifyPointer(descriptor());
881}
882
883
884void AccessorPair::AccessorPairVerify() {
885  CHECK(IsAccessorPair());
886  VerifyPointer(getter());
887  VerifyPointer(setter());
888}
889
890
891void AccessCheckInfo::AccessCheckInfoVerify() {
892  CHECK(IsAccessCheckInfo());
893  VerifyPointer(named_callback());
894  VerifyPointer(indexed_callback());
895  VerifyPointer(data());
896}
897
898
899void InterceptorInfo::InterceptorInfoVerify() {
900  CHECK(IsInterceptorInfo());
901  VerifyPointer(getter());
902  VerifyPointer(setter());
903  VerifyPointer(query());
904  VerifyPointer(deleter());
905  VerifyPointer(enumerator());
906  VerifyPointer(data());
907}
908
909
910void CallHandlerInfo::CallHandlerInfoVerify() {
911  CHECK(IsCallHandlerInfo());
912  VerifyPointer(callback());
913  VerifyPointer(data());
914}
915
916
917void TemplateInfo::TemplateInfoVerify() {
918  VerifyPointer(tag());
919  VerifyPointer(property_list());
920  VerifyPointer(property_accessors());
921}
922
923
924void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
925  CHECK(IsFunctionTemplateInfo());
926  TemplateInfoVerify();
927  VerifyPointer(serial_number());
928  VerifyPointer(call_code());
929  VerifyPointer(prototype_template());
930  VerifyPointer(parent_template());
931  VerifyPointer(named_property_handler());
932  VerifyPointer(indexed_property_handler());
933  VerifyPointer(instance_template());
934  VerifyPointer(signature());
935  VerifyPointer(access_check_info());
936}
937
938
939void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
940  CHECK(IsObjectTemplateInfo());
941  TemplateInfoVerify();
942  VerifyPointer(constructor());
943  VerifyPointer(internal_field_count());
944}
945
946
947void SignatureInfo::SignatureInfoVerify() {
948  CHECK(IsSignatureInfo());
949  VerifyPointer(receiver());
950  VerifyPointer(args());
951}
952
953
954void TypeSwitchInfo::TypeSwitchInfoVerify() {
955  CHECK(IsTypeSwitchInfo());
956  VerifyPointer(types());
957}
958
959
960void AllocationSite::AllocationSiteVerify() {
961  CHECK(IsAllocationSite());
962}
963
964
965void AllocationMemento::AllocationMementoVerify() {
966  CHECK(IsAllocationMemento());
967  VerifyHeapPointer(allocation_site());
968  CHECK(!IsValid() || GetAllocationSite()->IsAllocationSite());
969}
970
971
972void Script::ScriptVerify() {
973  CHECK(IsScript());
974  VerifyPointer(source());
975  VerifyPointer(name());
976  line_offset()->SmiVerify();
977  column_offset()->SmiVerify();
978  VerifyPointer(wrapper());
979  type()->SmiVerify();
980  VerifyPointer(line_ends());
981  VerifyPointer(id());
982}
983
984
985void JSFunctionResultCache::JSFunctionResultCacheVerify() {
986  JSFunction::cast(get(kFactoryIndex))->ObjectVerify();
987
988  int size = Smi::cast(get(kCacheSizeIndex))->value();
989  CHECK(kEntriesIndex <= size);
990  CHECK(size <= length());
991  CHECK_EQ(0, size % kEntrySize);
992
993  int finger = Smi::cast(get(kFingerIndex))->value();
994  CHECK(kEntriesIndex <= finger);
995  CHECK((finger < size) || (finger == kEntriesIndex && finger == size));
996  CHECK_EQ(0, finger % kEntrySize);
997
998  if (FLAG_enable_slow_asserts) {
999    for (int i = kEntriesIndex; i < size; i++) {
1000      CHECK(!get(i)->IsTheHole());
1001      get(i)->ObjectVerify();
1002    }
1003    for (int i = size; i < length(); i++) {
1004      CHECK(get(i)->IsTheHole());
1005      get(i)->ObjectVerify();
1006    }
1007  }
1008}
1009
1010
1011void NormalizedMapCache::NormalizedMapCacheVerify() {
1012  FixedArray::cast(this)->FixedArrayVerify();
1013  if (FLAG_enable_slow_asserts) {
1014    for (int i = 0; i < length(); i++) {
1015      Object* e = FixedArray::get(i);
1016      if (e->IsMap()) {
1017        Map::cast(e)->DictionaryMapVerify();
1018      } else {
1019        CHECK(e->IsUndefined());
1020      }
1021    }
1022  }
1023}
1024
1025
1026void DebugInfo::DebugInfoVerify() {
1027  CHECK(IsDebugInfo());
1028  VerifyPointer(shared());
1029  VerifyPointer(original_code());
1030  VerifyPointer(code());
1031  VerifyPointer(break_points());
1032}
1033
1034
1035void BreakPointInfo::BreakPointInfoVerify() {
1036  CHECK(IsBreakPointInfo());
1037  code_position()->SmiVerify();
1038  source_position()->SmiVerify();
1039  statement_position()->SmiVerify();
1040  VerifyPointer(break_point_objects());
1041}
1042#endif  // VERIFY_HEAP
1043
1044#ifdef DEBUG
1045
1046void JSObject::IncrementSpillStatistics(SpillInformation* info) {
1047  info->number_of_objects_++;
1048  // Named properties
1049  if (HasFastProperties()) {
1050    info->number_of_objects_with_fast_properties_++;
1051    info->number_of_fast_used_fields_   += map()->NextFreePropertyIndex();
1052    info->number_of_fast_unused_fields_ += map()->unused_property_fields();
1053  } else {
1054    NameDictionary* dict = property_dictionary();
1055    info->number_of_slow_used_properties_ += dict->NumberOfElements();
1056    info->number_of_slow_unused_properties_ +=
1057        dict->Capacity() - dict->NumberOfElements();
1058  }
1059  // Indexed properties
1060  switch (GetElementsKind()) {
1061    case FAST_HOLEY_SMI_ELEMENTS:
1062    case FAST_SMI_ELEMENTS:
1063    case FAST_HOLEY_DOUBLE_ELEMENTS:
1064    case FAST_DOUBLE_ELEMENTS:
1065    case FAST_HOLEY_ELEMENTS:
1066    case FAST_ELEMENTS: {
1067      info->number_of_objects_with_fast_elements_++;
1068      int holes = 0;
1069      FixedArray* e = FixedArray::cast(elements());
1070      int len = e->length();
1071      Heap* heap = GetHeap();
1072      for (int i = 0; i < len; i++) {
1073        if (e->get(i) == heap->the_hole_value()) holes++;
1074      }
1075      info->number_of_fast_used_elements_   += len - holes;
1076      info->number_of_fast_unused_elements_ += holes;
1077      break;
1078    }
1079
1080#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
1081    case EXTERNAL_##TYPE##_ELEMENTS:                                          \
1082    case TYPE##_ELEMENTS:
1083
1084    TYPED_ARRAYS(TYPED_ARRAY_CASE)
1085#undef TYPED_ARRAY_CASE
1086    { info->number_of_objects_with_fast_elements_++;
1087      FixedArrayBase* e = FixedArrayBase::cast(elements());
1088      info->number_of_fast_used_elements_ += e->length();
1089      break;
1090    }
1091    case DICTIONARY_ELEMENTS: {
1092      SeededNumberDictionary* dict = element_dictionary();
1093      info->number_of_slow_used_elements_ += dict->NumberOfElements();
1094      info->number_of_slow_unused_elements_ +=
1095          dict->Capacity() - dict->NumberOfElements();
1096      break;
1097    }
1098    case SLOPPY_ARGUMENTS_ELEMENTS:
1099      break;
1100  }
1101}
1102
1103
1104void JSObject::SpillInformation::Clear() {
1105  number_of_objects_ = 0;
1106  number_of_objects_with_fast_properties_ = 0;
1107  number_of_objects_with_fast_elements_ = 0;
1108  number_of_fast_used_fields_ = 0;
1109  number_of_fast_unused_fields_ = 0;
1110  number_of_slow_used_properties_ = 0;
1111  number_of_slow_unused_properties_ = 0;
1112  number_of_fast_used_elements_ = 0;
1113  number_of_fast_unused_elements_ = 0;
1114  number_of_slow_used_elements_ = 0;
1115  number_of_slow_unused_elements_ = 0;
1116}
1117
1118
1119void JSObject::SpillInformation::Print() {
1120  PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);
1121
1122  PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
1123         number_of_objects_with_fast_properties_,
1124         number_of_fast_used_fields_, number_of_fast_unused_fields_);
1125
1126  PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
1127         number_of_objects_ - number_of_objects_with_fast_properties_,
1128         number_of_slow_used_properties_, number_of_slow_unused_properties_);
1129
1130  PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
1131         number_of_objects_with_fast_elements_,
1132         number_of_fast_used_elements_, number_of_fast_unused_elements_);
1133
1134  PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
1135         number_of_objects_ - number_of_objects_with_fast_elements_,
1136         number_of_slow_used_elements_, number_of_slow_unused_elements_);
1137
1138  PrintF("\n");
1139}
1140
1141
1142bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) {
1143  if (valid_entries == -1) valid_entries = number_of_descriptors();
1144  Name* current_key = NULL;
1145  uint32_t current = 0;
1146  for (int i = 0; i < number_of_descriptors(); i++) {
1147    Name* key = GetSortedKey(i);
1148    if (key == current_key) {
1149      OFStream os(stdout);
1150      PrintDescriptors(os);
1151      return false;
1152    }
1153    current_key = key;
1154    uint32_t hash = GetSortedKey(i)->Hash();
1155    if (hash < current) {
1156      OFStream os(stdout);
1157      PrintDescriptors(os);
1158      return false;
1159    }
1160    current = hash;
1161  }
1162  return true;
1163}
1164
1165
1166bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
1167  DCHECK(valid_entries == -1);
1168  Name* current_key = NULL;
1169  uint32_t current = 0;
1170  for (int i = 0; i < number_of_transitions(); i++) {
1171    Name* key = GetSortedKey(i);
1172    if (key == current_key) {
1173      OFStream os(stdout);
1174      PrintTransitions(os);
1175      return false;
1176    }
1177    current_key = key;
1178    uint32_t hash = GetSortedKey(i)->Hash();
1179    if (hash < current) {
1180      OFStream os(stdout);
1181      PrintTransitions(os);
1182      return false;
1183    }
1184    current = hash;
1185  }
1186  return true;
1187}
1188
1189
1190static bool CheckOneBackPointer(Map* current_map, Object* target) {
1191  return !target->IsMap() || Map::cast(target)->GetBackPointer() == current_map;
1192}
1193
1194
1195bool TransitionArray::IsConsistentWithBackPointers(Map* current_map) {
1196  for (int i = 0; i < number_of_transitions(); ++i) {
1197    if (!CheckOneBackPointer(current_map, GetTarget(i))) return false;
1198  }
1199  return true;
1200}
1201
1202
1203#endif  // DEBUG
1204
1205} }  // namespace v8::internal
1206