• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/objects.h"
6 
7 #include "src/bootstrapper.h"
8 #include "src/disasm.h"
9 #include "src/disassembler.h"
10 #include "src/field-type.h"
11 #include "src/macro-assembler.h"
12 #include "src/ostreams.h"
13 #include "src/regexp/jsregexp.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 #ifdef VERIFY_HEAP
19 
ObjectVerify()20 void Object::ObjectVerify() {
21   if (IsSmi()) {
22     Smi::cast(this)->SmiVerify();
23   } else {
24     HeapObject::cast(this)->HeapObjectVerify();
25   }
26   CHECK(!IsConstructor() || IsCallable());
27 }
28 
29 
VerifyPointer(Object * p)30 void Object::VerifyPointer(Object* p) {
31   if (p->IsHeapObject()) {
32     HeapObject::VerifyHeapPointer(p);
33   } else {
34     CHECK(p->IsSmi());
35   }
36 }
37 
38 
SmiVerify()39 void Smi::SmiVerify() {
40   CHECK(IsSmi());
41   CHECK(!IsCallable());
42   CHECK(!IsConstructor());
43 }
44 
45 
HeapObjectVerify()46 void HeapObject::HeapObjectVerify() {
47   InstanceType instance_type = map()->instance_type();
48 
49   if (instance_type < FIRST_NONSTRING_TYPE) {
50     String::cast(this)->StringVerify();
51     return;
52   }
53 
54   switch (instance_type) {
55     case SYMBOL_TYPE:
56       Symbol::cast(this)->SymbolVerify();
57       break;
58     case MAP_TYPE:
59       Map::cast(this)->MapVerify();
60       break;
61     case HEAP_NUMBER_TYPE:
62     case MUTABLE_HEAP_NUMBER_TYPE:
63       HeapNumber::cast(this)->HeapNumberVerify();
64       break;
65     case SIMD128_VALUE_TYPE:
66       Simd128Value::cast(this)->Simd128ValueVerify();
67       break;
68     case FIXED_ARRAY_TYPE:
69       FixedArray::cast(this)->FixedArrayVerify();
70       break;
71     case FIXED_DOUBLE_ARRAY_TYPE:
72       FixedDoubleArray::cast(this)->FixedDoubleArrayVerify();
73       break;
74     case BYTE_ARRAY_TYPE:
75       ByteArray::cast(this)->ByteArrayVerify();
76       break;
77     case BYTECODE_ARRAY_TYPE:
78       BytecodeArray::cast(this)->BytecodeArrayVerify();
79       break;
80     case TRANSITION_ARRAY_TYPE:
81       TransitionArray::cast(this)->TransitionArrayVerify();
82       break;
83     case FREE_SPACE_TYPE:
84       FreeSpace::cast(this)->FreeSpaceVerify();
85       break;
86 
87 #define VERIFY_TYPED_ARRAY(Type, type, TYPE, ctype, size)                      \
88     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
89       Fixed##Type##Array::cast(this)->FixedTypedArrayVerify();                 \
90       break;
91 
92     TYPED_ARRAYS(VERIFY_TYPED_ARRAY)
93 #undef VERIFY_TYPED_ARRAY
94 
95     case CODE_TYPE:
96       Code::cast(this)->CodeVerify();
97       break;
98     case ODDBALL_TYPE:
99       Oddball::cast(this)->OddballVerify();
100       break;
101     case JS_OBJECT_TYPE:
102     case JS_ERROR_TYPE:
103     case JS_ARGUMENTS_TYPE:
104     case JS_API_OBJECT_TYPE:
105     case JS_SPECIAL_API_OBJECT_TYPE:
106     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
107     case JS_PROMISE_TYPE:
108       JSObject::cast(this)->JSObjectVerify();
109       break;
110     case JS_GENERATOR_OBJECT_TYPE:
111       JSGeneratorObject::cast(this)->JSGeneratorObjectVerify();
112       break;
113     case JS_MODULE_TYPE:
114       JSModule::cast(this)->JSModuleVerify();
115       break;
116     case JS_VALUE_TYPE:
117       JSValue::cast(this)->JSValueVerify();
118       break;
119     case JS_DATE_TYPE:
120       JSDate::cast(this)->JSDateVerify();
121       break;
122     case JS_BOUND_FUNCTION_TYPE:
123       JSBoundFunction::cast(this)->JSBoundFunctionVerify();
124       break;
125     case JS_FUNCTION_TYPE:
126       JSFunction::cast(this)->JSFunctionVerify();
127       break;
128     case JS_GLOBAL_PROXY_TYPE:
129       JSGlobalProxy::cast(this)->JSGlobalProxyVerify();
130       break;
131     case JS_GLOBAL_OBJECT_TYPE:
132       JSGlobalObject::cast(this)->JSGlobalObjectVerify();
133       break;
134     case CELL_TYPE:
135       Cell::cast(this)->CellVerify();
136       break;
137     case PROPERTY_CELL_TYPE:
138       PropertyCell::cast(this)->PropertyCellVerify();
139       break;
140     case WEAK_CELL_TYPE:
141       WeakCell::cast(this)->WeakCellVerify();
142       break;
143     case JS_ARRAY_TYPE:
144       JSArray::cast(this)->JSArrayVerify();
145       break;
146     case JS_SET_TYPE:
147       JSSet::cast(this)->JSSetVerify();
148       break;
149     case JS_MAP_TYPE:
150       JSMap::cast(this)->JSMapVerify();
151       break;
152     case JS_SET_ITERATOR_TYPE:
153       JSSetIterator::cast(this)->JSSetIteratorVerify();
154       break;
155     case JS_MAP_ITERATOR_TYPE:
156       JSMapIterator::cast(this)->JSMapIteratorVerify();
157       break;
158     case JS_WEAK_MAP_TYPE:
159       JSWeakMap::cast(this)->JSWeakMapVerify();
160       break;
161     case JS_WEAK_SET_TYPE:
162       JSWeakSet::cast(this)->JSWeakSetVerify();
163       break;
164     case JS_REGEXP_TYPE:
165       JSRegExp::cast(this)->JSRegExpVerify();
166       break;
167     case FILLER_TYPE:
168       break;
169     case JS_PROXY_TYPE:
170       JSProxy::cast(this)->JSProxyVerify();
171       break;
172     case FOREIGN_TYPE:
173       Foreign::cast(this)->ForeignVerify();
174       break;
175     case SHARED_FUNCTION_INFO_TYPE:
176       SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
177       break;
178     case JS_MESSAGE_OBJECT_TYPE:
179       JSMessageObject::cast(this)->JSMessageObjectVerify();
180       break;
181     case JS_ARRAY_BUFFER_TYPE:
182       JSArrayBuffer::cast(this)->JSArrayBufferVerify();
183       break;
184     case JS_TYPED_ARRAY_TYPE:
185       JSTypedArray::cast(this)->JSTypedArrayVerify();
186       break;
187     case JS_DATA_VIEW_TYPE:
188       JSDataView::cast(this)->JSDataViewVerify();
189       break;
190 
191 #define MAKE_STRUCT_CASE(NAME, Name, name) \
192   case NAME##_TYPE:                        \
193     Name::cast(this)->Name##Verify();      \
194     break;
195     STRUCT_LIST(MAKE_STRUCT_CASE)
196 #undef MAKE_STRUCT_CASE
197 
198     default:
199       UNREACHABLE();
200       break;
201   }
202 }
203 
204 
VerifyHeapPointer(Object * p)205 void HeapObject::VerifyHeapPointer(Object* p) {
206   CHECK(p->IsHeapObject());
207   HeapObject* ho = HeapObject::cast(p);
208   CHECK(ho->GetHeap()->Contains(ho));
209 }
210 
211 
SymbolVerify()212 void Symbol::SymbolVerify() {
213   CHECK(IsSymbol());
214   CHECK(HasHashCode());
215   CHECK(Hash() > 0u);
216   CHECK(name()->IsUndefined(GetIsolate()) || name()->IsString());
217 }
218 
219 
HeapNumberVerify()220 void HeapNumber::HeapNumberVerify() {
221   CHECK(IsHeapNumber() || IsMutableHeapNumber());
222 }
223 
224 
Simd128ValueVerify()225 void Simd128Value::Simd128ValueVerify() { CHECK(IsSimd128Value()); }
226 
227 
ByteArrayVerify()228 void ByteArray::ByteArrayVerify() {
229   CHECK(IsByteArray());
230 }
231 
232 
BytecodeArrayVerify()233 void BytecodeArray::BytecodeArrayVerify() {
234   // TODO(oth): Walk bytecodes and immediate values to validate sanity.
235   // - All bytecodes are known and well formed.
236   // - Jumps must go to new instructions starts.
237   // - No Illegal bytecodes.
238   // - No consecutive sequences of prefix Wide / ExtraWide.
239   CHECK(IsBytecodeArray());
240   CHECK(constant_pool()->IsFixedArray());
241   VerifyHeapPointer(constant_pool());
242 }
243 
244 
FreeSpaceVerify()245 void FreeSpace::FreeSpaceVerify() {
246   CHECK(IsFreeSpace());
247 }
248 
249 
250 template <class Traits>
FixedTypedArrayVerify()251 void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
252   CHECK(IsHeapObject() &&
253         HeapObject::cast(this)->map()->instance_type() ==
254             Traits::kInstanceType);
255   if (base_pointer() == this) {
256     CHECK(external_pointer() ==
257           ExternalReference::fixed_typed_array_base_data_offset().address());
258   } else {
259     CHECK(base_pointer() == nullptr);
260   }
261 }
262 
263 
ElementsAreSafeToExamine()264 bool JSObject::ElementsAreSafeToExamine() {
265   // If a GC was caused while constructing this object, the elements
266   // pointer may point to a one pointer filler map.
267   return reinterpret_cast<Map*>(elements()) !=
268       GetHeap()->one_pointer_filler_map();
269 }
270 
271 
JSObjectVerify()272 void JSObject::JSObjectVerify() {
273   VerifyHeapPointer(properties());
274   VerifyHeapPointer(elements());
275 
276   if (HasSloppyArgumentsElements()) {
277     CHECK(this->elements()->IsFixedArray());
278     CHECK_GE(this->elements()->length(), 2);
279   }
280 
281   if (HasFastProperties()) {
282     int actual_unused_property_fields = map()->GetInObjectProperties() +
283                                         properties()->length() -
284                                         map()->NextFreePropertyIndex();
285     if (map()->unused_property_fields() != actual_unused_property_fields) {
286       // This could actually happen in the middle of StoreTransitionStub
287       // when the new extended backing store is already set into the object and
288       // the allocation of the MutableHeapNumber triggers GC (in this case map
289       // is not updated yet).
290       CHECK_EQ(map()->unused_property_fields(),
291                actual_unused_property_fields - JSObject::kFieldsAdded);
292     }
293     DescriptorArray* descriptors = map()->instance_descriptors();
294     Isolate* isolate = GetIsolate();
295     for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
296       if (descriptors->GetDetails(i).type() == DATA) {
297         Representation r = descriptors->GetDetails(i).representation();
298         FieldIndex index = FieldIndex::ForDescriptor(map(), i);
299         if (IsUnboxedDoubleField(index)) {
300           DCHECK(r.IsDouble());
301           continue;
302         }
303         Object* value = RawFastPropertyAt(index);
304         if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber());
305         if (value->IsUninitialized(isolate)) continue;
306         if (r.IsSmi()) DCHECK(value->IsSmi());
307         if (r.IsHeapObject()) DCHECK(value->IsHeapObject());
308         FieldType* field_type = descriptors->GetFieldType(i);
309         bool type_is_none = field_type->IsNone();
310         bool type_is_any = field_type->IsAny();
311         if (r.IsNone()) {
312           CHECK(type_is_none);
313         } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) {
314           // If allocation folding is off then GC could happen during inner
315           // object literal creation and we will end up having and undefined
316           // value that does not match the field type.
317           CHECK(!field_type->NowStable() || field_type->NowContains(value) ||
318                 (!FLAG_use_allocation_folding && value->IsUndefined(isolate)));
319         }
320       }
321     }
322   }
323 
324   // If a GC was caused while constructing this object, the elements
325   // pointer may point to a one pointer filler map.
326   if (ElementsAreSafeToExamine()) {
327     CHECK_EQ((map()->has_fast_smi_or_object_elements() ||
328               (elements() == GetHeap()->empty_fixed_array()) ||
329               HasFastStringWrapperElements()),
330              (elements()->map() == GetHeap()->fixed_array_map() ||
331               elements()->map() == GetHeap()->fixed_cow_array_map()));
332     CHECK(map()->has_fast_object_elements() == HasFastObjectElements());
333   }
334 }
335 
336 
MapVerify()337 void Map::MapVerify() {
338   Heap* heap = GetHeap();
339   CHECK(!heap->InNewSpace(this));
340   CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
341   CHECK(instance_size() == kVariableSizeSentinel ||
342          (kPointerSize <= instance_size() &&
343           instance_size() < heap->Capacity()));
344   CHECK(GetBackPointer()->IsUndefined(heap->isolate()) ||
345         !Map::cast(GetBackPointer())->is_stable());
346   VerifyHeapPointer(prototype());
347   VerifyHeapPointer(instance_descriptors());
348   SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates());
349   SLOW_DCHECK(TransitionArray::IsSortedNoDuplicates(this));
350   SLOW_DCHECK(TransitionArray::IsConsistentWithBackPointers(this));
351   // TODO(ishell): turn it back to SLOW_DCHECK.
352   CHECK(!FLAG_unbox_double_fields ||
353         layout_descriptor()->IsConsistentWithMap(this));
354 }
355 
356 
DictionaryMapVerify()357 void Map::DictionaryMapVerify() {
358   MapVerify();
359   CHECK(is_dictionary_map());
360   CHECK(instance_descriptors()->IsEmpty());
361   CHECK_EQ(0, unused_property_fields());
362   CHECK_EQ(Heap::GetStaticVisitorIdForMap(this), visitor_id());
363 }
364 
365 
VerifyOmittedMapChecks()366 void Map::VerifyOmittedMapChecks() {
367   if (!FLAG_omit_map_checks_for_leaf_maps) return;
368   if (!is_stable() ||
369       is_deprecated() ||
370       is_dictionary_map()) {
371     CHECK(dependent_code()->IsEmpty(DependentCode::kPrototypeCheckGroup));
372   }
373 }
374 
375 
TypeFeedbackInfoVerify()376 void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
377   VerifyObjectField(kStorage1Offset);
378   VerifyObjectField(kStorage2Offset);
379   VerifyObjectField(kStorage3Offset);
380 }
381 
382 
AliasedArgumentsEntryVerify()383 void AliasedArgumentsEntry::AliasedArgumentsEntryVerify() {
384   VerifySmiField(kAliasedContextSlot);
385 }
386 
387 
FixedArrayVerify()388 void FixedArray::FixedArrayVerify() {
389   for (int i = 0; i < length(); i++) {
390     Object* e = get(i);
391     VerifyPointer(e);
392   }
393 }
394 
395 
FixedDoubleArrayVerify()396 void FixedDoubleArray::FixedDoubleArrayVerify() {
397   for (int i = 0; i < length(); i++) {
398     if (!is_the_hole(i)) {
399       uint64_t value = get_representation(i);
400       uint64_t unexpected =
401           bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN()) &
402           V8_UINT64_C(0x7FF8000000000000);
403       // Create implementation specific sNaN by inverting relevant bit.
404       unexpected ^= V8_UINT64_C(0x0008000000000000);
405       CHECK((value & V8_UINT64_C(0x7FF8000000000000)) != unexpected ||
406             (value & V8_UINT64_C(0x0007FFFFFFFFFFFF)) == V8_UINT64_C(0));
407     }
408   }
409 }
410 
411 
TransitionArrayVerify()412 void TransitionArray::TransitionArrayVerify() {
413   for (int i = 0; i < length(); i++) {
414     Object* e = get(i);
415     VerifyPointer(e);
416   }
417   CHECK_LE(LengthFor(number_of_transitions()), length());
418   CHECK(next_link()->IsUndefined(GetIsolate()) || next_link()->IsSmi() ||
419         next_link()->IsTransitionArray());
420 }
421 
422 
JSGeneratorObjectVerify()423 void JSGeneratorObject::JSGeneratorObjectVerify() {
424   // In an expression like "new g()", there can be a point where a generator
425   // object is allocated but its fields are all undefined, as it hasn't yet been
426   // initialized by the generator.  Hence these weak checks.
427   VerifyObjectField(kFunctionOffset);
428   VerifyObjectField(kContextOffset);
429   VerifyObjectField(kReceiverOffset);
430   VerifyObjectField(kOperandStackOffset);
431   VerifyObjectField(kContinuationOffset);
432 }
433 
434 
JSModuleVerify()435 void JSModule::JSModuleVerify() {
436   VerifyObjectField(kContextOffset);
437   VerifyObjectField(kScopeInfoOffset);
438   CHECK(context()->IsUndefined(GetIsolate()) ||
439         Context::cast(context())->IsModuleContext());
440 }
441 
442 
JSValueVerify()443 void JSValue::JSValueVerify() {
444   Object* v = value();
445   if (v->IsHeapObject()) {
446     VerifyHeapPointer(v);
447   }
448 }
449 
450 
JSDateVerify()451 void JSDate::JSDateVerify() {
452   if (value()->IsHeapObject()) {
453     VerifyHeapPointer(value());
454   }
455   Isolate* isolate = GetIsolate();
456   CHECK(value()->IsUndefined(isolate) || value()->IsSmi() ||
457         value()->IsHeapNumber());
458   CHECK(year()->IsUndefined(isolate) || year()->IsSmi() || year()->IsNaN());
459   CHECK(month()->IsUndefined(isolate) || month()->IsSmi() || month()->IsNaN());
460   CHECK(day()->IsUndefined(isolate) || day()->IsSmi() || day()->IsNaN());
461   CHECK(weekday()->IsUndefined(isolate) || weekday()->IsSmi() ||
462         weekday()->IsNaN());
463   CHECK(hour()->IsUndefined(isolate) || hour()->IsSmi() || hour()->IsNaN());
464   CHECK(min()->IsUndefined(isolate) || min()->IsSmi() || min()->IsNaN());
465   CHECK(sec()->IsUndefined(isolate) || sec()->IsSmi() || sec()->IsNaN());
466   CHECK(cache_stamp()->IsUndefined(isolate) || cache_stamp()->IsSmi() ||
467         cache_stamp()->IsNaN());
468 
469   if (month()->IsSmi()) {
470     int month = Smi::cast(this->month())->value();
471     CHECK(0 <= month && month <= 11);
472   }
473   if (day()->IsSmi()) {
474     int day = Smi::cast(this->day())->value();
475     CHECK(1 <= day && day <= 31);
476   }
477   if (hour()->IsSmi()) {
478     int hour = Smi::cast(this->hour())->value();
479     CHECK(0 <= hour && hour <= 23);
480   }
481   if (min()->IsSmi()) {
482     int min = Smi::cast(this->min())->value();
483     CHECK(0 <= min && min <= 59);
484   }
485   if (sec()->IsSmi()) {
486     int sec = Smi::cast(this->sec())->value();
487     CHECK(0 <= sec && sec <= 59);
488   }
489   if (weekday()->IsSmi()) {
490     int weekday = Smi::cast(this->weekday())->value();
491     CHECK(0 <= weekday && weekday <= 6);
492   }
493   if (cache_stamp()->IsSmi()) {
494     CHECK(Smi::cast(cache_stamp())->value() <=
495           Smi::cast(isolate->date_cache()->stamp())->value());
496   }
497 }
498 
499 
JSMessageObjectVerify()500 void JSMessageObject::JSMessageObjectVerify() {
501   CHECK(IsJSMessageObject());
502   VerifyObjectField(kStartPositionOffset);
503   VerifyObjectField(kEndPositionOffset);
504   VerifyObjectField(kArgumentsOffset);
505   VerifyObjectField(kScriptOffset);
506   VerifyObjectField(kStackFramesOffset);
507 }
508 
509 
StringVerify()510 void String::StringVerify() {
511   CHECK(IsString());
512   CHECK(length() >= 0 && length() <= Smi::kMaxValue);
513   if (IsInternalizedString()) {
514     CHECK(!GetHeap()->InNewSpace(this));
515   }
516   if (IsConsString()) {
517     ConsString::cast(this)->ConsStringVerify();
518   } else if (IsSlicedString()) {
519     SlicedString::cast(this)->SlicedStringVerify();
520   }
521 }
522 
523 
ConsStringVerify()524 void ConsString::ConsStringVerify() {
525   CHECK(this->first()->IsString());
526   CHECK(this->second() == GetHeap()->empty_string() ||
527         this->second()->IsString());
528   CHECK(this->length() >= ConsString::kMinLength);
529   CHECK(this->length() == this->first()->length() + this->second()->length());
530   if (this->IsFlat()) {
531     // A flat cons can only be created by String::SlowTryFlatten.
532     // Afterwards, the first part may be externalized.
533     CHECK(this->first()->IsSeqString() || this->first()->IsExternalString());
534   }
535 }
536 
537 
SlicedStringVerify()538 void SlicedString::SlicedStringVerify() {
539   CHECK(!this->parent()->IsConsString());
540   CHECK(!this->parent()->IsSlicedString());
541   CHECK(this->length() >= SlicedString::kMinLength);
542 }
543 
544 
JSBoundFunctionVerify()545 void JSBoundFunction::JSBoundFunctionVerify() {
546   CHECK(IsJSBoundFunction());
547   JSObjectVerify();
548   VerifyObjectField(kBoundThisOffset);
549   VerifyObjectField(kBoundTargetFunctionOffset);
550   VerifyObjectField(kBoundArgumentsOffset);
551   CHECK(bound_target_function()->IsCallable());
552   CHECK(IsCallable());
553   CHECK_EQ(IsConstructor(), bound_target_function()->IsConstructor());
554 }
555 
556 
JSFunctionVerify()557 void JSFunction::JSFunctionVerify() {
558   CHECK(IsJSFunction());
559   VerifyObjectField(kPrototypeOrInitialMapOffset);
560   VerifyObjectField(kNextFunctionLinkOffset);
561   CHECK(code()->IsCode());
562   CHECK(next_function_link() == NULL ||
563         next_function_link()->IsUndefined(GetIsolate()) ||
564         next_function_link()->IsJSFunction());
565   CHECK(map()->is_callable());
566 }
567 
568 
SharedFunctionInfoVerify()569 void SharedFunctionInfo::SharedFunctionInfoVerify() {
570   CHECK(IsSharedFunctionInfo());
571   VerifyObjectField(kNameOffset);
572   VerifyObjectField(kCodeOffset);
573   VerifyObjectField(kOptimizedCodeMapOffset);
574   VerifyObjectField(kFeedbackMetadataOffset);
575   VerifyObjectField(kScopeInfoOffset);
576   VerifyObjectField(kInstanceClassNameOffset);
577   CHECK(function_data()->IsUndefined(GetIsolate()) || IsApiFunction() ||
578         HasBytecodeArray());
579   VerifyObjectField(kFunctionDataOffset);
580   VerifyObjectField(kScriptOffset);
581   VerifyObjectField(kDebugInfoOffset);
582   CHECK(function_identifier()->IsUndefined(GetIsolate()) ||
583         HasBuiltinFunctionId() || HasInferredName());
584   VerifyObjectField(kFunctionIdentifierOffset);
585 }
586 
587 
JSGlobalProxyVerify()588 void JSGlobalProxy::JSGlobalProxyVerify() {
589   CHECK(IsJSGlobalProxy());
590   JSObjectVerify();
591   VerifyObjectField(JSGlobalProxy::kNativeContextOffset);
592   // Make sure that this object has no properties, elements.
593   CHECK_EQ(0, properties()->length());
594   CHECK_EQ(0, FixedArray::cast(elements())->length());
595 }
596 
597 
JSGlobalObjectVerify()598 void JSGlobalObject::JSGlobalObjectVerify() {
599   CHECK(IsJSGlobalObject());
600   // Do not check the dummy global object for the builtins.
601   if (GlobalDictionary::cast(properties())->NumberOfElements() == 0 &&
602       elements()->length() == 0) {
603     return;
604   }
605   JSObjectVerify();
606 }
607 
608 
OddballVerify()609 void Oddball::OddballVerify() {
610   CHECK(IsOddball());
611   Heap* heap = GetHeap();
612   VerifyHeapPointer(to_string());
613   Object* number = to_number();
614   if (number->IsHeapObject()) {
615     CHECK(number == heap->nan_value());
616   } else {
617     CHECK(number->IsSmi());
618     int value = Smi::cast(number)->value();
619     // Hidden oddballs have negative smis.
620     const int kLeastHiddenOddballNumber = -7;
621     CHECK_LE(value, 1);
622     CHECK(value >= kLeastHiddenOddballNumber);
623   }
624   if (map() == heap->undefined_map()) {
625     CHECK(this == heap->undefined_value());
626   } else if (map() == heap->the_hole_map()) {
627     CHECK(this == heap->the_hole_value());
628   } else if (map() == heap->null_map()) {
629     CHECK(this == heap->null_value());
630   } else if (map() == heap->boolean_map()) {
631     CHECK(this == heap->true_value() ||
632           this == heap->false_value());
633   } else if (map() == heap->uninitialized_map()) {
634     CHECK(this == heap->uninitialized_value());
635   } else if (map() == heap->no_interceptor_result_sentinel_map()) {
636     CHECK(this == heap->no_interceptor_result_sentinel());
637   } else if (map() == heap->arguments_marker_map()) {
638     CHECK(this == heap->arguments_marker());
639   } else if (map() == heap->termination_exception_map()) {
640     CHECK(this == heap->termination_exception());
641   } else if (map() == heap->exception_map()) {
642     CHECK(this == heap->exception());
643   } else if (map() == heap->optimized_out_map()) {
644     CHECK(this == heap->optimized_out());
645   } else if (map() == heap->stale_register_map()) {
646     CHECK(this == heap->stale_register());
647   } else {
648     UNREACHABLE();
649   }
650 }
651 
652 
CellVerify()653 void Cell::CellVerify() {
654   CHECK(IsCell());
655   VerifyObjectField(kValueOffset);
656 }
657 
658 
PropertyCellVerify()659 void PropertyCell::PropertyCellVerify() {
660   CHECK(IsPropertyCell());
661   VerifyObjectField(kValueOffset);
662 }
663 
664 
WeakCellVerify()665 void WeakCell::WeakCellVerify() {
666   CHECK(IsWeakCell());
667   VerifyObjectField(kValueOffset);
668   VerifyObjectField(kNextOffset);
669 }
670 
671 
CodeVerify()672 void Code::CodeVerify() {
673   CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
674                   kCodeAlignment));
675   relocation_info()->ObjectVerify();
676   Address last_gc_pc = NULL;
677   Isolate* isolate = GetIsolate();
678   for (RelocIterator it(this); !it.done(); it.next()) {
679     it.rinfo()->Verify(isolate);
680     // Ensure that GC will not iterate twice over the same pointer.
681     if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
682       CHECK(it.rinfo()->pc() != last_gc_pc);
683       last_gc_pc = it.rinfo()->pc();
684     }
685   }
686   CHECK(raw_type_feedback_info() == Smi::FromInt(0) ||
687         raw_type_feedback_info()->IsSmi() == IsCodeStubOrIC());
688 }
689 
690 
VerifyEmbeddedObjectsDependency()691 void Code::VerifyEmbeddedObjectsDependency() {
692   if (!CanContainWeakObjects()) return;
693   WeakCell* cell = CachedWeakCell();
694   DisallowHeapAllocation no_gc;
695   Isolate* isolate = GetIsolate();
696   HandleScope scope(isolate);
697   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
698   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
699     Object* obj = it.rinfo()->target_object();
700     if (IsWeakObject(obj)) {
701       if (obj->IsMap()) {
702         Map* map = Map::cast(obj);
703         CHECK(map->dependent_code()->Contains(DependentCode::kWeakCodeGroup,
704                                               cell));
705       } else if (obj->IsJSObject()) {
706         WeakHashTable* table =
707             GetIsolate()->heap()->weak_object_to_code_table();
708         Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate);
709         CHECK(DependentCode::cast(table->Lookup(key_obj))
710                   ->Contains(DependentCode::kWeakCodeGroup, cell));
711       }
712     }
713   }
714 }
715 
716 
JSArrayVerify()717 void JSArray::JSArrayVerify() {
718   JSObjectVerify();
719   Isolate* isolate = GetIsolate();
720   CHECK(length()->IsNumber() || length()->IsUndefined(isolate));
721   // If a GC was caused while constructing this array, the elements
722   // pointer may point to a one pointer filler map.
723   if (ElementsAreSafeToExamine()) {
724     CHECK(elements()->IsUndefined(isolate) || elements()->IsFixedArray() ||
725           elements()->IsFixedDoubleArray());
726   }
727 }
728 
729 
JSSetVerify()730 void JSSet::JSSetVerify() {
731   CHECK(IsJSSet());
732   JSObjectVerify();
733   VerifyHeapPointer(table());
734   CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate()));
735   // TODO(arv): Verify OrderedHashTable too.
736 }
737 
738 
JSMapVerify()739 void JSMap::JSMapVerify() {
740   CHECK(IsJSMap());
741   JSObjectVerify();
742   VerifyHeapPointer(table());
743   CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate()));
744   // TODO(arv): Verify OrderedHashTable too.
745 }
746 
747 
JSSetIteratorVerify()748 void JSSetIterator::JSSetIteratorVerify() {
749   CHECK(IsJSSetIterator());
750   JSObjectVerify();
751   VerifyHeapPointer(table());
752   Isolate* isolate = GetIsolate();
753   CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate));
754   CHECK(index()->IsSmi() || index()->IsUndefined(isolate));
755   CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate));
756 }
757 
758 
JSMapIteratorVerify()759 void JSMapIterator::JSMapIteratorVerify() {
760   CHECK(IsJSMapIterator());
761   JSObjectVerify();
762   VerifyHeapPointer(table());
763   Isolate* isolate = GetIsolate();
764   CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate));
765   CHECK(index()->IsSmi() || index()->IsUndefined(isolate));
766   CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate));
767 }
768 
769 
JSWeakMapVerify()770 void JSWeakMap::JSWeakMapVerify() {
771   CHECK(IsJSWeakMap());
772   JSObjectVerify();
773   VerifyHeapPointer(table());
774   CHECK(table()->IsHashTable() || table()->IsUndefined(GetIsolate()));
775 }
776 
777 
JSWeakSetVerify()778 void JSWeakSet::JSWeakSetVerify() {
779   CHECK(IsJSWeakSet());
780   JSObjectVerify();
781   VerifyHeapPointer(table());
782   CHECK(table()->IsHashTable() || table()->IsUndefined(GetIsolate()));
783 }
784 
785 
JSRegExpVerify()786 void JSRegExp::JSRegExpVerify() {
787   JSObjectVerify();
788   Isolate* isolate = GetIsolate();
789   CHECK(data()->IsUndefined(isolate) || data()->IsFixedArray());
790   switch (TypeTag()) {
791     case JSRegExp::ATOM: {
792       FixedArray* arr = FixedArray::cast(data());
793       CHECK(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
794       break;
795     }
796     case JSRegExp::IRREGEXP: {
797       bool is_native = RegExpImpl::UsesNativeRegExp();
798 
799       FixedArray* arr = FixedArray::cast(data());
800       Object* one_byte_data = arr->get(JSRegExp::kIrregexpLatin1CodeIndex);
801       // Smi : Not compiled yet (-1) or code prepared for flushing.
802       // JSObject: Compilation error.
803       // Code/ByteArray: Compiled code.
804       CHECK(
805           one_byte_data->IsSmi() ||
806           (is_native ? one_byte_data->IsCode() : one_byte_data->IsByteArray()));
807       Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex);
808       CHECK(uc16_data->IsSmi() ||
809              (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray()));
810 
811       Object* one_byte_saved =
812           arr->get(JSRegExp::kIrregexpLatin1CodeSavedIndex);
813       CHECK(one_byte_saved->IsSmi() || one_byte_saved->IsString() ||
814             one_byte_saved->IsCode());
815       Object* uc16_saved = arr->get(JSRegExp::kIrregexpUC16CodeSavedIndex);
816       CHECK(uc16_saved->IsSmi() || uc16_saved->IsString() ||
817              uc16_saved->IsCode());
818 
819       CHECK(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi());
820       CHECK(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi());
821       break;
822     }
823     default:
824       CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag());
825       CHECK(data()->IsUndefined(isolate));
826       break;
827   }
828 }
829 
830 
JSProxyVerify()831 void JSProxy::JSProxyVerify() {
832   CHECK(IsJSProxy());
833   VerifyPointer(target());
834   VerifyPointer(handler());
835   Isolate* isolate = GetIsolate();
836   CHECK_EQ(target()->IsCallable(), map()->is_callable());
837   CHECK_EQ(target()->IsConstructor(), map()->is_constructor());
838   CHECK(hash()->IsSmi() || hash()->IsUndefined(isolate));
839   CHECK(map()->prototype()->IsNull(isolate));
840   // There should be no properties on a Proxy.
841   CHECK_EQ(0, map()->NumberOfOwnDescriptors());
842 }
843 
844 
JSArrayBufferVerify()845 void JSArrayBuffer::JSArrayBufferVerify() {
846   CHECK(IsJSArrayBuffer());
847   JSObjectVerify();
848   VerifyPointer(byte_length());
849   CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber() ||
850         byte_length()->IsUndefined(GetIsolate()));
851 }
852 
853 
JSArrayBufferViewVerify()854 void JSArrayBufferView::JSArrayBufferViewVerify() {
855   CHECK(IsJSArrayBufferView());
856   JSObjectVerify();
857   VerifyPointer(buffer());
858   Isolate* isolate = GetIsolate();
859   CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined(isolate) ||
860         buffer() == Smi::FromInt(0));
861 
862   VerifyPointer(raw_byte_offset());
863   CHECK(raw_byte_offset()->IsSmi() || raw_byte_offset()->IsHeapNumber() ||
864         raw_byte_offset()->IsUndefined(isolate));
865 
866   VerifyPointer(raw_byte_length());
867   CHECK(raw_byte_length()->IsSmi() || raw_byte_length()->IsHeapNumber() ||
868         raw_byte_length()->IsUndefined(isolate));
869 }
870 
871 
JSTypedArrayVerify()872 void JSTypedArray::JSTypedArrayVerify() {
873   CHECK(IsJSTypedArray());
874   JSArrayBufferViewVerify();
875   VerifyPointer(raw_length());
876   CHECK(raw_length()->IsSmi() || raw_length()->IsHeapNumber() ||
877         raw_length()->IsUndefined(GetIsolate()));
878 
879   VerifyPointer(elements());
880 }
881 
882 
JSDataViewVerify()883 void JSDataView::JSDataViewVerify() {
884   CHECK(IsJSDataView());
885   JSArrayBufferViewVerify();
886 }
887 
888 
ForeignVerify()889 void Foreign::ForeignVerify() {
890   CHECK(IsForeign());
891 }
892 
893 
BoxVerify()894 void Box::BoxVerify() {
895   CHECK(IsBox());
896   value()->ObjectVerify();
897 }
898 
899 
PrototypeInfoVerify()900 void PrototypeInfo::PrototypeInfoVerify() {
901   CHECK(IsPrototypeInfo());
902   if (prototype_users()->IsWeakFixedArray()) {
903     WeakFixedArray::cast(prototype_users())->FixedArrayVerify();
904   } else {
905     CHECK(prototype_users()->IsSmi());
906   }
907   CHECK(validity_cell()->IsCell() || validity_cell()->IsSmi());
908 }
909 
910 
911 void SloppyBlockWithEvalContextExtension::
SloppyBlockWithEvalContextExtensionVerify()912     SloppyBlockWithEvalContextExtensionVerify() {
913   CHECK(IsSloppyBlockWithEvalContextExtension());
914   VerifyObjectField(kScopeInfoOffset);
915   VerifyObjectField(kExtensionOffset);
916 }
917 
918 
AccessorInfoVerify()919 void AccessorInfo::AccessorInfoVerify() {
920   CHECK(IsAccessorInfo());
921   VerifyPointer(name());
922   VerifyPointer(expected_receiver_type());
923   VerifyPointer(getter());
924   VerifyPointer(setter());
925   VerifyPointer(js_getter());
926   VerifyPointer(data());
927 }
928 
929 
AccessorPairVerify()930 void AccessorPair::AccessorPairVerify() {
931   CHECK(IsAccessorPair());
932   VerifyPointer(getter());
933   VerifyPointer(setter());
934 }
935 
936 
AccessCheckInfoVerify()937 void AccessCheckInfo::AccessCheckInfoVerify() {
938   CHECK(IsAccessCheckInfo());
939   VerifyPointer(callback());
940   VerifyPointer(named_interceptor());
941   VerifyPointer(indexed_interceptor());
942   VerifyPointer(data());
943 }
944 
945 
InterceptorInfoVerify()946 void InterceptorInfo::InterceptorInfoVerify() {
947   CHECK(IsInterceptorInfo());
948   VerifyPointer(getter());
949   VerifyPointer(setter());
950   VerifyPointer(query());
951   VerifyPointer(deleter());
952   VerifyPointer(enumerator());
953   VerifyPointer(data());
954   VerifySmiField(kFlagsOffset);
955 }
956 
957 
CallHandlerInfoVerify()958 void CallHandlerInfo::CallHandlerInfoVerify() {
959   CHECK(IsCallHandlerInfo());
960   VerifyPointer(callback());
961   VerifyPointer(data());
962 }
963 
964 
TemplateInfoVerify()965 void TemplateInfo::TemplateInfoVerify() {
966   VerifyPointer(tag());
967   VerifyPointer(property_list());
968   VerifyPointer(property_accessors());
969 }
970 
971 
FunctionTemplateInfoVerify()972 void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
973   CHECK(IsFunctionTemplateInfo());
974   TemplateInfoVerify();
975   VerifyPointer(serial_number());
976   VerifyPointer(call_code());
977   VerifyPointer(prototype_template());
978   VerifyPointer(parent_template());
979   VerifyPointer(named_property_handler());
980   VerifyPointer(indexed_property_handler());
981   VerifyPointer(instance_template());
982   VerifyPointer(signature());
983   VerifyPointer(access_check_info());
984 }
985 
986 
ObjectTemplateInfoVerify()987 void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
988   CHECK(IsObjectTemplateInfo());
989   TemplateInfoVerify();
990   VerifyPointer(constructor());
991   VerifyPointer(internal_field_count());
992 }
993 
994 
AllocationSiteVerify()995 void AllocationSite::AllocationSiteVerify() {
996   CHECK(IsAllocationSite());
997 }
998 
999 
AllocationMementoVerify()1000 void AllocationMemento::AllocationMementoVerify() {
1001   CHECK(IsAllocationMemento());
1002   VerifyHeapPointer(allocation_site());
1003   CHECK(!IsValid() || GetAllocationSite()->IsAllocationSite());
1004 }
1005 
1006 
ScriptVerify()1007 void Script::ScriptVerify() {
1008   CHECK(IsScript());
1009   VerifyPointer(source());
1010   VerifyPointer(name());
1011   VerifyPointer(wrapper());
1012   VerifyPointer(line_ends());
1013 }
1014 
1015 
NormalizedMapCacheVerify()1016 void NormalizedMapCache::NormalizedMapCacheVerify() {
1017   FixedArray::cast(this)->FixedArrayVerify();
1018   if (FLAG_enable_slow_asserts) {
1019     Isolate* isolate = GetIsolate();
1020     for (int i = 0; i < length(); i++) {
1021       Object* e = FixedArray::get(i);
1022       if (e->IsMap()) {
1023         Map::cast(e)->DictionaryMapVerify();
1024       } else {
1025         CHECK(e->IsUndefined(isolate));
1026       }
1027     }
1028   }
1029 }
1030 
1031 
DebugInfoVerify()1032 void DebugInfo::DebugInfoVerify() {
1033   CHECK(IsDebugInfo());
1034   VerifyPointer(shared());
1035   VerifyPointer(abstract_code());
1036   VerifyPointer(break_points());
1037 }
1038 
1039 
BreakPointInfoVerify()1040 void BreakPointInfo::BreakPointInfoVerify() {
1041   CHECK(IsBreakPointInfo());
1042   VerifyPointer(break_point_objects());
1043 }
1044 #endif  // VERIFY_HEAP
1045 
1046 #ifdef DEBUG
1047 
IncrementSpillStatistics(SpillInformation * info)1048 void JSObject::IncrementSpillStatistics(SpillInformation* info) {
1049   info->number_of_objects_++;
1050   // Named properties
1051   if (HasFastProperties()) {
1052     info->number_of_objects_with_fast_properties_++;
1053     info->number_of_fast_used_fields_   += map()->NextFreePropertyIndex();
1054     info->number_of_fast_unused_fields_ += map()->unused_property_fields();
1055   } else if (IsJSGlobalObject()) {
1056     GlobalDictionary* dict = global_dictionary();
1057     info->number_of_slow_used_properties_ += dict->NumberOfElements();
1058     info->number_of_slow_unused_properties_ +=
1059         dict->Capacity() - dict->NumberOfElements();
1060   } else {
1061     NameDictionary* dict = property_dictionary();
1062     info->number_of_slow_used_properties_ += dict->NumberOfElements();
1063     info->number_of_slow_unused_properties_ +=
1064         dict->Capacity() - dict->NumberOfElements();
1065   }
1066   // Indexed properties
1067   switch (GetElementsKind()) {
1068     case FAST_HOLEY_SMI_ELEMENTS:
1069     case FAST_SMI_ELEMENTS:
1070     case FAST_HOLEY_DOUBLE_ELEMENTS:
1071     case FAST_DOUBLE_ELEMENTS:
1072     case FAST_HOLEY_ELEMENTS:
1073     case FAST_ELEMENTS:
1074     case FAST_STRING_WRAPPER_ELEMENTS: {
1075       info->number_of_objects_with_fast_elements_++;
1076       int holes = 0;
1077       FixedArray* e = FixedArray::cast(elements());
1078       int len = e->length();
1079       Isolate* isolate = GetIsolate();
1080       for (int i = 0; i < len; i++) {
1081         if (e->get(i)->IsTheHole(isolate)) holes++;
1082       }
1083       info->number_of_fast_used_elements_   += len - holes;
1084       info->number_of_fast_unused_elements_ += holes;
1085       break;
1086     }
1087 
1088 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
1089     case TYPE##_ELEMENTS:
1090 
1091     TYPED_ARRAYS(TYPED_ARRAY_CASE)
1092 #undef TYPED_ARRAY_CASE
1093     { info->number_of_objects_with_fast_elements_++;
1094       FixedArrayBase* e = FixedArrayBase::cast(elements());
1095       info->number_of_fast_used_elements_ += e->length();
1096       break;
1097     }
1098     case DICTIONARY_ELEMENTS:
1099     case SLOW_STRING_WRAPPER_ELEMENTS: {
1100       SeededNumberDictionary* dict = element_dictionary();
1101       info->number_of_slow_used_elements_ += dict->NumberOfElements();
1102       info->number_of_slow_unused_elements_ +=
1103           dict->Capacity() - dict->NumberOfElements();
1104       break;
1105     }
1106     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1107     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
1108     case NO_ELEMENTS:
1109       break;
1110   }
1111 }
1112 
1113 
Clear()1114 void JSObject::SpillInformation::Clear() {
1115   number_of_objects_ = 0;
1116   number_of_objects_with_fast_properties_ = 0;
1117   number_of_objects_with_fast_elements_ = 0;
1118   number_of_fast_used_fields_ = 0;
1119   number_of_fast_unused_fields_ = 0;
1120   number_of_slow_used_properties_ = 0;
1121   number_of_slow_unused_properties_ = 0;
1122   number_of_fast_used_elements_ = 0;
1123   number_of_fast_unused_elements_ = 0;
1124   number_of_slow_used_elements_ = 0;
1125   number_of_slow_unused_elements_ = 0;
1126 }
1127 
1128 
Print()1129 void JSObject::SpillInformation::Print() {
1130   PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);
1131 
1132   PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
1133          number_of_objects_with_fast_properties_,
1134          number_of_fast_used_fields_, number_of_fast_unused_fields_);
1135 
1136   PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
1137          number_of_objects_ - number_of_objects_with_fast_properties_,
1138          number_of_slow_used_properties_, number_of_slow_unused_properties_);
1139 
1140   PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
1141          number_of_objects_with_fast_elements_,
1142          number_of_fast_used_elements_, number_of_fast_unused_elements_);
1143 
1144   PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
1145          number_of_objects_ - number_of_objects_with_fast_elements_,
1146          number_of_slow_used_elements_, number_of_slow_unused_elements_);
1147 
1148   PrintF("\n");
1149 }
1150 
1151 
IsSortedNoDuplicates(int valid_entries)1152 bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) {
1153   if (valid_entries == -1) valid_entries = number_of_descriptors();
1154   Name* current_key = NULL;
1155   uint32_t current = 0;
1156   for (int i = 0; i < number_of_descriptors(); i++) {
1157     Name* key = GetSortedKey(i);
1158     if (key == current_key) {
1159       Print();
1160       return false;
1161     }
1162     current_key = key;
1163     uint32_t hash = GetSortedKey(i)->Hash();
1164     if (hash < current) {
1165       Print();
1166       return false;
1167     }
1168     current = hash;
1169   }
1170   return true;
1171 }
1172 
1173 
IsSortedNoDuplicates(int valid_entries)1174 bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
1175   DCHECK(valid_entries == -1);
1176   Name* prev_key = NULL;
1177   PropertyKind prev_kind = kData;
1178   PropertyAttributes prev_attributes = NONE;
1179   uint32_t prev_hash = 0;
1180   for (int i = 0; i < number_of_transitions(); i++) {
1181     Name* key = GetSortedKey(i);
1182     uint32_t hash = key->Hash();
1183     PropertyKind kind = kData;
1184     PropertyAttributes attributes = NONE;
1185     if (!IsSpecialTransition(key)) {
1186       Map* target = GetTarget(i);
1187       PropertyDetails details = GetTargetDetails(key, target);
1188       kind = details.kind();
1189       attributes = details.attributes();
1190     } else {
1191       // Duplicate entries are not allowed for non-property transitions.
1192       CHECK_NE(prev_key, key);
1193     }
1194 
1195     int cmp = CompareKeys(prev_key, prev_hash, prev_kind, prev_attributes, key,
1196                           hash, kind, attributes);
1197     if (cmp >= 0) {
1198       Print();
1199       return false;
1200     }
1201     prev_key = key;
1202     prev_hash = hash;
1203     prev_attributes = attributes;
1204     prev_kind = kind;
1205   }
1206   return true;
1207 }
1208 
1209 
1210 // static
IsSortedNoDuplicates(Map * map)1211 bool TransitionArray::IsSortedNoDuplicates(Map* map) {
1212   Object* raw_transitions = map->raw_transitions();
1213   if (IsFullTransitionArray(raw_transitions)) {
1214     return TransitionArray::cast(raw_transitions)->IsSortedNoDuplicates();
1215   }
1216   // Simple and non-existent transitions are always sorted.
1217   return true;
1218 }
1219 
1220 
CheckOneBackPointer(Map * current_map,Object * target)1221 static bool CheckOneBackPointer(Map* current_map, Object* target) {
1222   return !target->IsMap() || Map::cast(target)->GetBackPointer() == current_map;
1223 }
1224 
1225 
1226 // static
IsConsistentWithBackPointers(Map * map)1227 bool TransitionArray::IsConsistentWithBackPointers(Map* map) {
1228   Object* transitions = map->raw_transitions();
1229   for (int i = 0; i < TransitionArray::NumberOfTransitions(transitions); ++i) {
1230     Map* target = TransitionArray::GetTarget(transitions, i);
1231     if (!CheckOneBackPointer(map, target)) return false;
1232   }
1233   return true;
1234 }
1235 
1236 
1237 // Estimates if there is a path from the object to a context.
1238 // This function is not precise, and can return false even if
1239 // there is a path to a context.
CanLeak(Object * obj,Heap * heap,bool skip_weak_cell)1240 bool CanLeak(Object* obj, Heap* heap, bool skip_weak_cell) {
1241   if (!obj->IsHeapObject()) return false;
1242   if (obj->IsWeakCell()) {
1243     if (skip_weak_cell) return false;
1244     return CanLeak(WeakCell::cast(obj)->value(), heap, skip_weak_cell);
1245   }
1246   if (obj->IsCell()) {
1247     return CanLeak(Cell::cast(obj)->value(), heap, skip_weak_cell);
1248   }
1249   if (obj->IsPropertyCell()) {
1250     return CanLeak(PropertyCell::cast(obj)->value(), heap, skip_weak_cell);
1251   }
1252   if (obj->IsContext()) return true;
1253   if (obj->IsMap()) {
1254     Map* map = Map::cast(obj);
1255     for (int i = 0; i < Heap::kStrongRootListLength; i++) {
1256       Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i);
1257       if (map == heap->root(root_index)) return false;
1258     }
1259     return true;
1260   }
1261   return CanLeak(HeapObject::cast(obj)->map(), heap, skip_weak_cell);
1262 }
1263 
1264 
VerifyEmbeddedObjects(VerifyMode mode)1265 void Code::VerifyEmbeddedObjects(VerifyMode mode) {
1266   if (kind() == OPTIMIZED_FUNCTION) return;
1267   Heap* heap = GetIsolate()->heap();
1268   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
1269              RelocInfo::ModeMask(RelocInfo::CELL);
1270   bool skip_weak_cell = (mode == kNoContextSpecificPointers) ? false : true;
1271   for (RelocIterator it(this, mask); !it.done(); it.next()) {
1272     Object* target = it.rinfo()->rmode() == RelocInfo::CELL
1273                          ? it.rinfo()->target_cell()
1274                          : it.rinfo()->target_object();
1275     CHECK(!CanLeak(target, heap, skip_weak_cell));
1276   }
1277 }
1278 
1279 
1280 // Verify that the debugger can redirect old code to the new code.
VerifyRecompiledCode(Code * old_code,Code * new_code)1281 void Code::VerifyRecompiledCode(Code* old_code, Code* new_code) {
1282   if (old_code->kind() != FUNCTION) return;
1283   if (new_code->kind() != FUNCTION) return;
1284   Isolate* isolate = old_code->GetIsolate();
1285   // Do not verify during bootstrapping. We may replace code using %SetCode.
1286   if (isolate->bootstrapper()->IsActive()) return;
1287 
1288   static const int mask = RelocInfo::kCodeTargetMask;
1289   RelocIterator old_it(old_code, mask);
1290   RelocIterator new_it(new_code, mask);
1291   Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck);
1292 
1293   while (!old_it.done()) {
1294     RelocInfo* rinfo = old_it.rinfo();
1295     Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1296     CHECK(!target->is_handler() && !target->is_inline_cache_stub());
1297     if (target == stack_check) break;
1298     old_it.next();
1299   }
1300 
1301   while (!new_it.done()) {
1302     RelocInfo* rinfo = new_it.rinfo();
1303     Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1304     CHECK(!target->is_handler() && !target->is_inline_cache_stub());
1305     if (target == stack_check) break;
1306     new_it.next();
1307   }
1308 
1309   // Either both are done because there is no stack check.
1310   // Or we are past the prologue for both.
1311   CHECK_EQ(new_it.done(), old_it.done());
1312 
1313   // After the prologue, each call in the old code has a corresponding call
1314   // in the new code.
1315   while (!old_it.done() && !new_it.done()) {
1316     Code* old_target =
1317         Code::GetCodeFromTargetAddress(old_it.rinfo()->target_address());
1318     Code* new_target =
1319         Code::GetCodeFromTargetAddress(new_it.rinfo()->target_address());
1320     CHECK_EQ(old_target->kind(), new_target->kind());
1321     // Check call target for equality unless it's an IC or an interrupt check.
1322     // In both cases they may be patched to be something else.
1323     if (!old_target->is_handler() && !old_target->is_inline_cache_stub() &&
1324         new_target != isolate->builtins()->builtin(Builtins::kInterruptCheck)) {
1325       CHECK_EQ(old_target, new_target);
1326     }
1327     old_it.next();
1328     new_it.next();
1329   }
1330 
1331   // Both are done at the same time.
1332   CHECK_EQ(new_it.done(), old_it.done());
1333 }
1334 
1335 
1336 #endif  // DEBUG
1337 
1338 }  // namespace internal
1339 }  // namespace v8
1340