1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "disassembler.h"
31#include "disasm.h"
32#include "jsregexp.h"
33#include "macro-assembler.h"
34#include "objects-visiting.h"
35
36namespace v8 {
37namespace internal {
38
39#ifdef VERIFY_HEAP
40
41void MaybeObject::Verify() {
42  Object* this_as_object;
43  if (ToObject(&this_as_object)) {
44    if (this_as_object->IsSmi()) {
45      Smi::cast(this_as_object)->SmiVerify();
46    } else {
47      HeapObject::cast(this_as_object)->HeapObjectVerify();
48    }
49  } else {
50    Failure::cast(this)->FailureVerify();
51  }
52}
53
54
55void Object::VerifyPointer(Object* p) {
56  if (p->IsHeapObject()) {
57    HeapObject::VerifyHeapPointer(p);
58  } else {
59    CHECK(p->IsSmi());
60  }
61}
62
63
64void Smi::SmiVerify() {
65  CHECK(IsSmi());
66}
67
68
69void Failure::FailureVerify() {
70  CHECK(IsFailure());
71}
72
73
74void HeapObject::HeapObjectVerify() {
75  InstanceType instance_type = map()->instance_type();
76
77  if (instance_type < FIRST_NONSTRING_TYPE) {
78    String::cast(this)->StringVerify();
79    return;
80  }
81
82  switch (instance_type) {
83    case SYMBOL_TYPE:
84      Symbol::cast(this)->SymbolVerify();
85      break;
86    case MAP_TYPE:
87      Map::cast(this)->MapVerify();
88      break;
89    case HEAP_NUMBER_TYPE:
90      HeapNumber::cast(this)->HeapNumberVerify();
91      break;
92    case FIXED_ARRAY_TYPE:
93      FixedArray::cast(this)->FixedArrayVerify();
94      break;
95    case FIXED_DOUBLE_ARRAY_TYPE:
96      FixedDoubleArray::cast(this)->FixedDoubleArrayVerify();
97      break;
98    case CONSTANT_POOL_ARRAY_TYPE:
99      ConstantPoolArray::cast(this)->ConstantPoolArrayVerify();
100      break;
101    case BYTE_ARRAY_TYPE:
102      ByteArray::cast(this)->ByteArrayVerify();
103      break;
104    case FREE_SPACE_TYPE:
105      FreeSpace::cast(this)->FreeSpaceVerify();
106      break;
107    case EXTERNAL_PIXEL_ARRAY_TYPE:
108      ExternalPixelArray::cast(this)->ExternalPixelArrayVerify();
109      break;
110    case EXTERNAL_BYTE_ARRAY_TYPE:
111      ExternalByteArray::cast(this)->ExternalByteArrayVerify();
112      break;
113    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
114      ExternalUnsignedByteArray::cast(this)->ExternalUnsignedByteArrayVerify();
115      break;
116    case EXTERNAL_SHORT_ARRAY_TYPE:
117      ExternalShortArray::cast(this)->ExternalShortArrayVerify();
118      break;
119    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
120      ExternalUnsignedShortArray::cast(this)->
121          ExternalUnsignedShortArrayVerify();
122      break;
123    case EXTERNAL_INT_ARRAY_TYPE:
124      ExternalIntArray::cast(this)->ExternalIntArrayVerify();
125      break;
126    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
127      ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayVerify();
128      break;
129    case EXTERNAL_FLOAT_ARRAY_TYPE:
130      ExternalFloatArray::cast(this)->ExternalFloatArrayVerify();
131      break;
132    case EXTERNAL_DOUBLE_ARRAY_TYPE:
133      ExternalDoubleArray::cast(this)->ExternalDoubleArrayVerify();
134      break;
135    case CODE_TYPE:
136      Code::cast(this)->CodeVerify();
137      break;
138    case ODDBALL_TYPE:
139      Oddball::cast(this)->OddballVerify();
140      break;
141    case JS_OBJECT_TYPE:
142    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
143      JSObject::cast(this)->JSObjectVerify();
144      break;
145    case JS_GENERATOR_OBJECT_TYPE:
146      JSGeneratorObject::cast(this)->JSGeneratorObjectVerify();
147      break;
148    case JS_MODULE_TYPE:
149      JSModule::cast(this)->JSModuleVerify();
150      break;
151    case JS_VALUE_TYPE:
152      JSValue::cast(this)->JSValueVerify();
153      break;
154    case JS_DATE_TYPE:
155      JSDate::cast(this)->JSDateVerify();
156      break;
157    case JS_FUNCTION_TYPE:
158      JSFunction::cast(this)->JSFunctionVerify();
159      break;
160    case JS_GLOBAL_PROXY_TYPE:
161      JSGlobalProxy::cast(this)->JSGlobalProxyVerify();
162      break;
163    case JS_GLOBAL_OBJECT_TYPE:
164      JSGlobalObject::cast(this)->JSGlobalObjectVerify();
165      break;
166    case JS_BUILTINS_OBJECT_TYPE:
167      JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
168      break;
169    case CELL_TYPE:
170      Cell::cast(this)->CellVerify();
171      break;
172    case PROPERTY_CELL_TYPE:
173      PropertyCell::cast(this)->PropertyCellVerify();
174      break;
175    case JS_ARRAY_TYPE:
176      JSArray::cast(this)->JSArrayVerify();
177      break;
178    case JS_SET_TYPE:
179      JSSet::cast(this)->JSSetVerify();
180      break;
181    case JS_MAP_TYPE:
182      JSMap::cast(this)->JSMapVerify();
183      break;
184    case JS_WEAK_MAP_TYPE:
185      JSWeakMap::cast(this)->JSWeakMapVerify();
186      break;
187    case JS_WEAK_SET_TYPE:
188      JSWeakSet::cast(this)->JSWeakSetVerify();
189      break;
190    case JS_REGEXP_TYPE:
191      JSRegExp::cast(this)->JSRegExpVerify();
192      break;
193    case FILLER_TYPE:
194      break;
195    case JS_PROXY_TYPE:
196      JSProxy::cast(this)->JSProxyVerify();
197      break;
198    case JS_FUNCTION_PROXY_TYPE:
199      JSFunctionProxy::cast(this)->JSFunctionProxyVerify();
200      break;
201    case FOREIGN_TYPE:
202      Foreign::cast(this)->ForeignVerify();
203      break;
204    case SHARED_FUNCTION_INFO_TYPE:
205      SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
206      break;
207    case JS_MESSAGE_OBJECT_TYPE:
208      JSMessageObject::cast(this)->JSMessageObjectVerify();
209      break;
210    case JS_ARRAY_BUFFER_TYPE:
211      JSArrayBuffer::cast(this)->JSArrayBufferVerify();
212      break;
213    case JS_TYPED_ARRAY_TYPE:
214      JSTypedArray::cast(this)->JSTypedArrayVerify();
215      break;
216    case JS_DATA_VIEW_TYPE:
217      JSDataView::cast(this)->JSDataViewVerify();
218      break;
219
220#define MAKE_STRUCT_CASE(NAME, Name, name) \
221  case NAME##_TYPE:                        \
222    Name::cast(this)->Name##Verify();      \
223    break;
224    STRUCT_LIST(MAKE_STRUCT_CASE)
225#undef MAKE_STRUCT_CASE
226
227    default:
228      UNREACHABLE();
229      break;
230  }
231}
232
233
234void HeapObject::VerifyHeapPointer(Object* p) {
235  CHECK(p->IsHeapObject());
236  HeapObject* ho = HeapObject::cast(p);
237  CHECK(ho->GetHeap()->Contains(ho));
238}
239
240
241void Symbol::SymbolVerify() {
242  CHECK(IsSymbol());
243  CHECK(HasHashCode());
244  CHECK_GT(Hash(), 0);
245  CHECK(name()->IsUndefined() || name()->IsString());
246  CHECK(flags()->IsSmi());
247}
248
249
250void HeapNumber::HeapNumberVerify() {
251  CHECK(IsHeapNumber());
252}
253
254
255void ByteArray::ByteArrayVerify() {
256  CHECK(IsByteArray());
257}
258
259
260void FreeSpace::FreeSpaceVerify() {
261  CHECK(IsFreeSpace());
262}
263
264
265void ExternalPixelArray::ExternalPixelArrayVerify() {
266  CHECK(IsExternalPixelArray());
267}
268
269
270void ExternalByteArray::ExternalByteArrayVerify() {
271  CHECK(IsExternalByteArray());
272}
273
274
275void ExternalUnsignedByteArray::ExternalUnsignedByteArrayVerify() {
276  CHECK(IsExternalUnsignedByteArray());
277}
278
279
280void ExternalShortArray::ExternalShortArrayVerify() {
281  CHECK(IsExternalShortArray());
282}
283
284
285void ExternalUnsignedShortArray::ExternalUnsignedShortArrayVerify() {
286  CHECK(IsExternalUnsignedShortArray());
287}
288
289
290void ExternalIntArray::ExternalIntArrayVerify() {
291  CHECK(IsExternalIntArray());
292}
293
294
295void ExternalUnsignedIntArray::ExternalUnsignedIntArrayVerify() {
296  CHECK(IsExternalUnsignedIntArray());
297}
298
299
300void ExternalFloatArray::ExternalFloatArrayVerify() {
301  CHECK(IsExternalFloatArray());
302}
303
304
305void ExternalDoubleArray::ExternalDoubleArrayVerify() {
306  CHECK(IsExternalDoubleArray());
307}
308
309
310bool JSObject::ElementsAreSafeToExamine() {
311  return (FLAG_use_gvn && FLAG_use_allocation_folding) ||
312      reinterpret_cast<Map*>(elements()) !=
313      GetHeap()->one_pointer_filler_map();
314}
315
316
317void JSObject::JSObjectVerify() {
318  VerifyHeapPointer(properties());
319  VerifyHeapPointer(elements());
320
321  if (GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS) {
322    CHECK(this->elements()->IsFixedArray());
323    CHECK_GE(this->elements()->length(), 2);
324  }
325
326  if (HasFastProperties()) {
327    CHECK_EQ(map()->unused_property_fields(),
328             (map()->inobject_properties() + properties()->length() -
329              map()->NextFreePropertyIndex()));
330    DescriptorArray* descriptors = map()->instance_descriptors();
331    for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
332      if (descriptors->GetDetails(i).type() == FIELD) {
333        Representation r = descriptors->GetDetails(i).representation();
334        int field = descriptors->GetFieldIndex(i);
335        Object* value = RawFastPropertyAt(field);
336        if (r.IsDouble()) ASSERT(value->IsHeapNumber());
337        if (value->IsUninitialized()) continue;
338        if (r.IsSmi()) ASSERT(value->IsSmi());
339        if (r.IsHeapObject()) ASSERT(value->IsHeapObject());
340      }
341    }
342  }
343
344  // If a GC was caused while constructing this object, the elements
345  // pointer may point to a one pointer filler map.
346  if (ElementsAreSafeToExamine()) {
347    CHECK_EQ((map()->has_fast_smi_or_object_elements() ||
348              (elements() == GetHeap()->empty_fixed_array())),
349             (elements()->map() == GetHeap()->fixed_array_map() ||
350              elements()->map() == GetHeap()->fixed_cow_array_map()));
351    CHECK(map()->has_fast_object_elements() == HasFastObjectElements());
352  }
353}
354
355
356void Map::MapVerify() {
357  Heap* heap = GetHeap();
358  CHECK(!heap->InNewSpace(this));
359  CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
360  CHECK(instance_size() == kVariableSizeSentinel ||
361         (kPointerSize <= instance_size() &&
362          instance_size() < heap->Capacity()));
363  VerifyHeapPointer(prototype());
364  VerifyHeapPointer(instance_descriptors());
365  SLOW_ASSERT(instance_descriptors()->IsSortedNoDuplicates());
366  if (HasTransitionArray()) {
367    SLOW_ASSERT(transitions()->IsSortedNoDuplicates());
368    SLOW_ASSERT(transitions()->IsConsistentWithBackPointers(this));
369  }
370}
371
372
373void Map::SharedMapVerify() {
374  MapVerify();
375  CHECK(is_shared());
376  CHECK(instance_descriptors()->IsEmpty());
377  CHECK_EQ(0, pre_allocated_property_fields());
378  CHECK_EQ(0, unused_property_fields());
379  CHECK_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
380      visitor_id());
381}
382
383
384void Map::VerifyOmittedMapChecks() {
385  if (!FLAG_omit_map_checks_for_leaf_maps) return;
386  if (!is_stable() ||
387      is_deprecated() ||
388      HasTransitionArray() ||
389      is_dictionary_map()) {
390    CHECK_EQ(0, dependent_code()->number_of_entries(
391        DependentCode::kPrototypeCheckGroup));
392  }
393}
394
395
396void CodeCache::CodeCacheVerify() {
397  VerifyHeapPointer(default_cache());
398  VerifyHeapPointer(normal_type_cache());
399  CHECK(default_cache()->IsFixedArray());
400  CHECK(normal_type_cache()->IsUndefined()
401         || normal_type_cache()->IsCodeCacheHashTable());
402}
403
404
405void PolymorphicCodeCache::PolymorphicCodeCacheVerify() {
406  VerifyHeapPointer(cache());
407  CHECK(cache()->IsUndefined() || cache()->IsPolymorphicCodeCacheHashTable());
408}
409
410
411void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
412  VerifyObjectField(kStorage1Offset);
413  VerifyObjectField(kStorage2Offset);
414  VerifyHeapPointer(type_feedback_cells());
415}
416
417
418void AliasedArgumentsEntry::AliasedArgumentsEntryVerify() {
419  VerifySmiField(kAliasedContextSlot);
420}
421
422
423void FixedArray::FixedArrayVerify() {
424  for (int i = 0; i < length(); i++) {
425    Object* e = get(i);
426    if (e->IsHeapObject()) {
427      VerifyHeapPointer(e);
428    } else {
429      e->Verify();
430    }
431  }
432}
433
434
435void FixedDoubleArray::FixedDoubleArrayVerify() {
436  for (int i = 0; i < length(); i++) {
437    if (!is_the_hole(i)) {
438      double value = get_scalar(i);
439      CHECK(!std::isnan(value) ||
440             (BitCast<uint64_t>(value) ==
441              BitCast<uint64_t>(canonical_not_the_hole_nan_as_double())) ||
442             ((BitCast<uint64_t>(value) & Double::kSignMask) != 0));
443    }
444  }
445}
446
447
448void ConstantPoolArray::ConstantPoolArrayVerify() {
449  CHECK(IsConstantPoolArray());
450}
451
452
453void JSGeneratorObject::JSGeneratorObjectVerify() {
454  // In an expression like "new g()", there can be a point where a generator
455  // object is allocated but its fields are all undefined, as it hasn't yet been
456  // initialized by the generator.  Hence these weak checks.
457  VerifyObjectField(kFunctionOffset);
458  VerifyObjectField(kContextOffset);
459  VerifyObjectField(kReceiverOffset);
460  VerifyObjectField(kOperandStackOffset);
461  VerifyObjectField(kContinuationOffset);
462  VerifyObjectField(kStackHandlerIndexOffset);
463}
464
465
466void JSModule::JSModuleVerify() {
467  VerifyObjectField(kContextOffset);
468  VerifyObjectField(kScopeInfoOffset);
469  CHECK(context()->IsUndefined() ||
470        Context::cast(context())->IsModuleContext());
471}
472
473
474void JSValue::JSValueVerify() {
475  Object* v = value();
476  if (v->IsHeapObject()) {
477    VerifyHeapPointer(v);
478  }
479}
480
481
482void JSDate::JSDateVerify() {
483  if (value()->IsHeapObject()) {
484    VerifyHeapPointer(value());
485  }
486  CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber());
487  CHECK(year()->IsUndefined() || year()->IsSmi() || year()->IsNaN());
488  CHECK(month()->IsUndefined() || month()->IsSmi() || month()->IsNaN());
489  CHECK(day()->IsUndefined() || day()->IsSmi() || day()->IsNaN());
490  CHECK(weekday()->IsUndefined() || weekday()->IsSmi() || weekday()->IsNaN());
491  CHECK(hour()->IsUndefined() || hour()->IsSmi() || hour()->IsNaN());
492  CHECK(min()->IsUndefined() || min()->IsSmi() || min()->IsNaN());
493  CHECK(sec()->IsUndefined() || sec()->IsSmi() || sec()->IsNaN());
494  CHECK(cache_stamp()->IsUndefined() ||
495        cache_stamp()->IsSmi() ||
496        cache_stamp()->IsNaN());
497
498  if (month()->IsSmi()) {
499    int month = Smi::cast(this->month())->value();
500    CHECK(0 <= month && month <= 11);
501  }
502  if (day()->IsSmi()) {
503    int day = Smi::cast(this->day())->value();
504    CHECK(1 <= day && day <= 31);
505  }
506  if (hour()->IsSmi()) {
507    int hour = Smi::cast(this->hour())->value();
508    CHECK(0 <= hour && hour <= 23);
509  }
510  if (min()->IsSmi()) {
511    int min = Smi::cast(this->min())->value();
512    CHECK(0 <= min && min <= 59);
513  }
514  if (sec()->IsSmi()) {
515    int sec = Smi::cast(this->sec())->value();
516    CHECK(0 <= sec && sec <= 59);
517  }
518  if (weekday()->IsSmi()) {
519    int weekday = Smi::cast(this->weekday())->value();
520    CHECK(0 <= weekday && weekday <= 6);
521  }
522  if (cache_stamp()->IsSmi()) {
523    CHECK(Smi::cast(cache_stamp())->value() <=
524          Smi::cast(GetIsolate()->date_cache()->stamp())->value());
525  }
526}
527
528
529void JSMessageObject::JSMessageObjectVerify() {
530  CHECK(IsJSMessageObject());
531  CHECK(type()->IsString());
532  CHECK(arguments()->IsJSArray());
533  VerifyObjectField(kStartPositionOffset);
534  VerifyObjectField(kEndPositionOffset);
535  VerifyObjectField(kArgumentsOffset);
536  VerifyObjectField(kScriptOffset);
537  VerifyObjectField(kStackTraceOffset);
538  VerifyObjectField(kStackFramesOffset);
539}
540
541
542void String::StringVerify() {
543  CHECK(IsString());
544  CHECK(length() >= 0 && length() <= Smi::kMaxValue);
545  if (IsInternalizedString()) {
546    CHECK(!GetHeap()->InNewSpace(this));
547  }
548  if (IsConsString()) {
549    ConsString::cast(this)->ConsStringVerify();
550  } else if (IsSlicedString()) {
551    SlicedString::cast(this)->SlicedStringVerify();
552  }
553}
554
555
556void ConsString::ConsStringVerify() {
557  CHECK(this->first()->IsString());
558  CHECK(this->second() == GetHeap()->empty_string() ||
559        this->second()->IsString());
560  CHECK(this->length() >= ConsString::kMinLength);
561  if (this->IsFlat()) {
562    // A flat cons can only be created by String::SlowTryFlatten.
563    // Afterwards, the first part may be externalized.
564    CHECK(this->first()->IsSeqString() || this->first()->IsExternalString());
565  }
566}
567
568
569void SlicedString::SlicedStringVerify() {
570  CHECK(!this->parent()->IsConsString());
571  CHECK(!this->parent()->IsSlicedString());
572  CHECK(this->length() >= SlicedString::kMinLength);
573}
574
575
576void JSFunction::JSFunctionVerify() {
577  CHECK(IsJSFunction());
578  VerifyObjectField(kPrototypeOrInitialMapOffset);
579  VerifyObjectField(kNextFunctionLinkOffset);
580  CHECK(code()->IsCode());
581  CHECK(next_function_link() == NULL ||
582        next_function_link()->IsUndefined() ||
583        next_function_link()->IsJSFunction());
584}
585
586
587void SharedFunctionInfo::SharedFunctionInfoVerify() {
588  CHECK(IsSharedFunctionInfo());
589  VerifyObjectField(kNameOffset);
590  VerifyObjectField(kCodeOffset);
591  VerifyObjectField(kOptimizedCodeMapOffset);
592  VerifyObjectField(kScopeInfoOffset);
593  VerifyObjectField(kInstanceClassNameOffset);
594  VerifyObjectField(kFunctionDataOffset);
595  VerifyObjectField(kScriptOffset);
596  VerifyObjectField(kDebugInfoOffset);
597}
598
599
600void JSGlobalProxy::JSGlobalProxyVerify() {
601  CHECK(IsJSGlobalProxy());
602  JSObjectVerify();
603  VerifyObjectField(JSGlobalProxy::kNativeContextOffset);
604  // Make sure that this object has no properties, elements.
605  CHECK_EQ(0, properties()->length());
606  CHECK(HasFastObjectElements());
607  CHECK_EQ(0, FixedArray::cast(elements())->length());
608}
609
610
611void JSGlobalObject::JSGlobalObjectVerify() {
612  CHECK(IsJSGlobalObject());
613  JSObjectVerify();
614  for (int i = GlobalObject::kBuiltinsOffset;
615       i < JSGlobalObject::kSize;
616       i += kPointerSize) {
617    VerifyObjectField(i);
618  }
619}
620
621
622void JSBuiltinsObject::JSBuiltinsObjectVerify() {
623  CHECK(IsJSBuiltinsObject());
624  JSObjectVerify();
625  for (int i = GlobalObject::kBuiltinsOffset;
626       i < JSBuiltinsObject::kSize;
627       i += kPointerSize) {
628    VerifyObjectField(i);
629  }
630}
631
632
633void Oddball::OddballVerify() {
634  CHECK(IsOddball());
635  VerifyHeapPointer(to_string());
636  Object* number = to_number();
637  if (number->IsHeapObject()) {
638    CHECK(number == HeapObject::cast(number)->GetHeap()->nan_value());
639  } else {
640    CHECK(number->IsSmi());
641    int value = Smi::cast(number)->value();
642    // Hidden oddballs have negative smis.
643    const int kLeastHiddenOddballNumber = -4;
644    CHECK_LE(value, 1);
645    CHECK(value >= kLeastHiddenOddballNumber);
646  }
647}
648
649
650void Cell::CellVerify() {
651  CHECK(IsCell());
652  VerifyObjectField(kValueOffset);
653}
654
655
656void PropertyCell::PropertyCellVerify() {
657  CHECK(IsPropertyCell());
658  VerifyObjectField(kValueOffset);
659  VerifyObjectField(kTypeOffset);
660}
661
662
663void Code::CodeVerify() {
664  CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
665                  kCodeAlignment));
666  relocation_info()->Verify();
667  Address last_gc_pc = NULL;
668  for (RelocIterator it(this); !it.done(); it.next()) {
669    it.rinfo()->Verify();
670    // Ensure that GC will not iterate twice over the same pointer.
671    if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
672      CHECK(it.rinfo()->pc() != last_gc_pc);
673      last_gc_pc = it.rinfo()->pc();
674    }
675  }
676}
677
678
679void Code::VerifyEmbeddedObjectsDependency() {
680  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
681  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
682    Object* obj = it.rinfo()->target_object();
683    if (IsWeakEmbeddedObject(kind(), obj)) {
684      if (obj->IsMap()) {
685        Map* map = Map::cast(obj);
686        CHECK(map->dependent_code()->Contains(
687            DependentCode::kWeaklyEmbeddedGroup, this));
688      } else if (obj->IsJSObject()) {
689        Object* raw_table = GetIsolate()->heap()->weak_object_to_code_table();
690        WeakHashTable* table = WeakHashTable::cast(raw_table);
691        CHECK(DependentCode::cast(table->Lookup(obj))->Contains(
692            DependentCode::kWeaklyEmbeddedGroup, this));
693      }
694    }
695  }
696}
697
698
699void JSArray::JSArrayVerify() {
700  JSObjectVerify();
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());
708  }
709}
710
711
712void JSSet::JSSetVerify() {
713  CHECK(IsJSSet());
714  JSObjectVerify();
715  VerifyHeapPointer(table());
716  CHECK(table()->IsHashTable() || table()->IsUndefined());
717}
718
719
720void JSMap::JSMapVerify() {
721  CHECK(IsJSMap());
722  JSObjectVerify();
723  VerifyHeapPointer(table());
724  CHECK(table()->IsHashTable() || table()->IsUndefined());
725}
726
727
728void JSWeakMap::JSWeakMapVerify() {
729  CHECK(IsJSWeakMap());
730  JSObjectVerify();
731  VerifyHeapPointer(table());
732  CHECK(table()->IsHashTable() || table()->IsUndefined());
733}
734
735
736void JSWeakSet::JSWeakSetVerify() {
737  CHECK(IsJSWeakSet());
738  JSObjectVerify();
739  VerifyHeapPointer(table());
740  CHECK(table()->IsHashTable() || table()->IsUndefined());
741}
742
743
744void JSRegExp::JSRegExpVerify() {
745  JSObjectVerify();
746  CHECK(data()->IsUndefined() || data()->IsFixedArray());
747  switch (TypeTag()) {
748    case JSRegExp::ATOM: {
749      FixedArray* arr = FixedArray::cast(data());
750      CHECK(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
751      break;
752    }
753    case JSRegExp::IRREGEXP: {
754      bool is_native = RegExpImpl::UsesNativeRegExp();
755
756      FixedArray* arr = FixedArray::cast(data());
757      Object* ascii_data = arr->get(JSRegExp::kIrregexpASCIICodeIndex);
758      // Smi : Not compiled yet (-1) or code prepared for flushing.
759      // JSObject: Compilation error.
760      // Code/ByteArray: Compiled code.
761      CHECK(ascii_data->IsSmi() ||
762             (is_native ? ascii_data->IsCode() : ascii_data->IsByteArray()));
763      Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex);
764      CHECK(uc16_data->IsSmi() ||
765             (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray()));
766
767      Object* ascii_saved = arr->get(JSRegExp::kIrregexpASCIICodeSavedIndex);
768      CHECK(ascii_saved->IsSmi() || ascii_saved->IsString() ||
769             ascii_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
816  VerifyPointer(byte_offset());
817  CHECK(byte_offset()->IsSmi() || byte_offset()->IsHeapNumber()
818        || byte_offset()->IsUndefined());
819
820  VerifyPointer(byte_length());
821  CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
822        || byte_length()->IsUndefined());
823}
824
825
826void JSTypedArray::JSTypedArrayVerify() {
827  CHECK(IsJSTypedArray());
828  JSArrayBufferViewVerify();
829  VerifyPointer(length());
830  CHECK(length()->IsSmi() || length()->IsHeapNumber()
831        || length()->IsUndefined());
832
833  VerifyPointer(elements());
834}
835
836
837void JSDataView::JSDataViewVerify() {
838  CHECK(IsJSDataView());
839  JSArrayBufferViewVerify();
840}
841
842
843void Foreign::ForeignVerify() {
844  CHECK(IsForeign());
845}
846
847
848void Box::BoxVerify() {
849  CHECK(IsBox());
850  value()->Verify();
851}
852
853
854void AccessorInfo::AccessorInfoVerify() {
855  VerifyPointer(name());
856  VerifyPointer(flag());
857  VerifyPointer(expected_receiver_type());
858}
859
860
861void ExecutableAccessorInfo::ExecutableAccessorInfoVerify() {
862  CHECK(IsExecutableAccessorInfo());
863  AccessorInfoVerify();
864  VerifyPointer(getter());
865  VerifyPointer(setter());
866  VerifyPointer(data());
867}
868
869
870void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorVerify() {
871  CHECK(IsDeclaredAccessorDescriptor());
872  VerifyPointer(serialized_data());
873}
874
875
876void DeclaredAccessorInfo::DeclaredAccessorInfoVerify() {
877  CHECK(IsDeclaredAccessorInfo());
878  AccessorInfoVerify();
879  VerifyPointer(descriptor());
880}
881
882
883void AccessorPair::AccessorPairVerify() {
884  CHECK(IsAccessorPair());
885  VerifyPointer(getter());
886  VerifyPointer(setter());
887  VerifySmiField(kAccessFlagsOffset);
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(data());
979  VerifyPointer(wrapper());
980  type()->SmiVerify();
981  VerifyPointer(line_ends());
982  VerifyPointer(id());
983}
984
985
986void JSFunctionResultCache::JSFunctionResultCacheVerify() {
987  JSFunction::cast(get(kFactoryIndex))->Verify();
988
989  int size = Smi::cast(get(kCacheSizeIndex))->value();
990  CHECK(kEntriesIndex <= size);
991  CHECK(size <= length());
992  CHECK_EQ(0, size % kEntrySize);
993
994  int finger = Smi::cast(get(kFingerIndex))->value();
995  CHECK(kEntriesIndex <= finger);
996  CHECK((finger < size) || (finger == kEntriesIndex && finger == size));
997  CHECK_EQ(0, finger % kEntrySize);
998
999  if (FLAG_enable_slow_asserts) {
1000    for (int i = kEntriesIndex; i < size; i++) {
1001      CHECK(!get(i)->IsTheHole());
1002      get(i)->Verify();
1003    }
1004    for (int i = size; i < length(); i++) {
1005      CHECK(get(i)->IsTheHole());
1006      get(i)->Verify();
1007    }
1008  }
1009}
1010
1011
1012void NormalizedMapCache::NormalizedMapCacheVerify() {
1013  FixedArray::cast(this)->Verify();
1014  if (FLAG_enable_slow_asserts) {
1015    for (int i = 0; i < length(); i++) {
1016      Object* e = get(i);
1017      if (e->IsMap()) {
1018        Map::cast(e)->SharedMapVerify();
1019      } else {
1020        CHECK(e->IsUndefined());
1021      }
1022    }
1023  }
1024}
1025
1026
1027#ifdef ENABLE_DEBUGGER_SUPPORT
1028void DebugInfo::DebugInfoVerify() {
1029  CHECK(IsDebugInfo());
1030  VerifyPointer(shared());
1031  VerifyPointer(original_code());
1032  VerifyPointer(code());
1033  VerifyPointer(break_points());
1034}
1035
1036
1037void BreakPointInfo::BreakPointInfoVerify() {
1038  CHECK(IsBreakPointInfo());
1039  code_position()->SmiVerify();
1040  source_position()->SmiVerify();
1041  statement_position()->SmiVerify();
1042  VerifyPointer(break_point_objects());
1043}
1044#endif  // ENABLE_DEBUGGER_SUPPORT
1045#endif  // VERIFY_HEAP
1046
1047#ifdef DEBUG
1048
1049void JSObject::IncrementSpillStatistics(SpillInformation* info) {
1050  info->number_of_objects_++;
1051  // Named properties
1052  if (HasFastProperties()) {
1053    info->number_of_objects_with_fast_properties_++;
1054    info->number_of_fast_used_fields_   += map()->NextFreePropertyIndex();
1055    info->number_of_fast_unused_fields_ += map()->unused_property_fields();
1056  } else {
1057    NameDictionary* dict = property_dictionary();
1058    info->number_of_slow_used_properties_ += dict->NumberOfElements();
1059    info->number_of_slow_unused_properties_ +=
1060        dict->Capacity() - dict->NumberOfElements();
1061  }
1062  // Indexed properties
1063  switch (GetElementsKind()) {
1064    case FAST_HOLEY_SMI_ELEMENTS:
1065    case FAST_SMI_ELEMENTS:
1066    case FAST_HOLEY_DOUBLE_ELEMENTS:
1067    case FAST_DOUBLE_ELEMENTS:
1068    case FAST_HOLEY_ELEMENTS:
1069    case FAST_ELEMENTS: {
1070      info->number_of_objects_with_fast_elements_++;
1071      int holes = 0;
1072      FixedArray* e = FixedArray::cast(elements());
1073      int len = e->length();
1074      Heap* heap = GetHeap();
1075      for (int i = 0; i < len; i++) {
1076        if (e->get(i) == heap->the_hole_value()) holes++;
1077      }
1078      info->number_of_fast_used_elements_   += len - holes;
1079      info->number_of_fast_unused_elements_ += holes;
1080      break;
1081    }
1082    case EXTERNAL_BYTE_ELEMENTS:
1083    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
1084    case EXTERNAL_SHORT_ELEMENTS:
1085    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
1086    case EXTERNAL_INT_ELEMENTS:
1087    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
1088    case EXTERNAL_FLOAT_ELEMENTS:
1089    case EXTERNAL_DOUBLE_ELEMENTS:
1090    case EXTERNAL_PIXEL_ELEMENTS: {
1091      info->number_of_objects_with_fast_elements_++;
1092      ExternalPixelArray* e = ExternalPixelArray::cast(elements());
1093      info->number_of_fast_used_elements_ += e->length();
1094      break;
1095    }
1096    case DICTIONARY_ELEMENTS: {
1097      SeededNumberDictionary* dict = element_dictionary();
1098      info->number_of_slow_used_elements_ += dict->NumberOfElements();
1099      info->number_of_slow_unused_elements_ +=
1100          dict->Capacity() - dict->NumberOfElements();
1101      break;
1102    }
1103    case NON_STRICT_ARGUMENTS_ELEMENTS:
1104      break;
1105  }
1106}
1107
1108
1109void JSObject::SpillInformation::Clear() {
1110  number_of_objects_ = 0;
1111  number_of_objects_with_fast_properties_ = 0;
1112  number_of_objects_with_fast_elements_ = 0;
1113  number_of_fast_used_fields_ = 0;
1114  number_of_fast_unused_fields_ = 0;
1115  number_of_slow_used_properties_ = 0;
1116  number_of_slow_unused_properties_ = 0;
1117  number_of_fast_used_elements_ = 0;
1118  number_of_fast_unused_elements_ = 0;
1119  number_of_slow_used_elements_ = 0;
1120  number_of_slow_unused_elements_ = 0;
1121}
1122
1123
1124void JSObject::SpillInformation::Print() {
1125  PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);
1126
1127  PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
1128         number_of_objects_with_fast_properties_,
1129         number_of_fast_used_fields_, number_of_fast_unused_fields_);
1130
1131  PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
1132         number_of_objects_ - number_of_objects_with_fast_properties_,
1133         number_of_slow_used_properties_, number_of_slow_unused_properties_);
1134
1135  PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
1136         number_of_objects_with_fast_elements_,
1137         number_of_fast_used_elements_, number_of_fast_unused_elements_);
1138
1139  PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
1140         number_of_objects_ - number_of_objects_with_fast_elements_,
1141         number_of_slow_used_elements_, number_of_slow_unused_elements_);
1142
1143  PrintF("\n");
1144}
1145
1146
1147bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) {
1148  if (valid_entries == -1) valid_entries = number_of_descriptors();
1149  Name* current_key = NULL;
1150  uint32_t current = 0;
1151  for (int i = 0; i < number_of_descriptors(); i++) {
1152    Name* key = GetSortedKey(i);
1153    if (key == current_key) {
1154      PrintDescriptors();
1155      return false;
1156    }
1157    current_key = key;
1158    uint32_t hash = GetSortedKey(i)->Hash();
1159    if (hash < current) {
1160      PrintDescriptors();
1161      return false;
1162    }
1163    current = hash;
1164  }
1165  return true;
1166}
1167
1168
1169bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
1170  ASSERT(valid_entries == -1);
1171  Name* current_key = NULL;
1172  uint32_t current = 0;
1173  for (int i = 0; i < number_of_transitions(); i++) {
1174    Name* key = GetSortedKey(i);
1175    if (key == current_key) {
1176      PrintTransitions();
1177      return false;
1178    }
1179    current_key = key;
1180    uint32_t hash = GetSortedKey(i)->Hash();
1181    if (hash < current) {
1182      PrintTransitions();
1183      return false;
1184    }
1185    current = hash;
1186  }
1187  return true;
1188}
1189
1190
1191static bool CheckOneBackPointer(Map* current_map, Object* target) {
1192  return !target->IsMap() || Map::cast(target)->GetBackPointer() == current_map;
1193}
1194
1195
1196bool TransitionArray::IsConsistentWithBackPointers(Map* current_map) {
1197  for (int i = 0; i < number_of_transitions(); ++i) {
1198    if (!CheckOneBackPointer(current_map, GetTarget(i))) return false;
1199  }
1200  return true;
1201}
1202
1203
1204#endif  // DEBUG
1205
1206} }  // namespace v8::internal
1207