objects-debug.cc 45.8 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// 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 16
namespace v8 {
namespace internal {
17

18
#ifdef VERIFY_HEAP
19

20 21 22 23 24 25
void Object::ObjectVerify() {
  if (IsSmi()) {
    Smi::cast(this)->SmiVerify();
  } else {
    HeapObject::cast(this)->HeapObjectVerify();
  }
26
  CHECK(!IsConstructor() || IsCallable());
27 28 29
}


30 31 32 33
void Object::VerifyPointer(Object* p) {
  if (p->IsHeapObject()) {
    HeapObject::VerifyHeapPointer(p);
  } else {
34
    CHECK(p->IsSmi());
35 36 37 38 39
  }
}


void Smi::SmiVerify() {
40
  CHECK(IsSmi());
41
  CHECK(!IsCallable());
42
  CHECK(!IsConstructor());
43 44 45 46 47 48 49 50 51 52 53 54
}


void HeapObject::HeapObjectVerify() {
  InstanceType instance_type = map()->instance_type();

  if (instance_type < FIRST_NONSTRING_TYPE) {
    String::cast(this)->StringVerify();
    return;
  }

  switch (instance_type) {
55 56 57
    case SYMBOL_TYPE:
      Symbol::cast(this)->SymbolVerify();
      break;
58 59 60 61
    case MAP_TYPE:
      Map::cast(this)->MapVerify();
      break;
    case HEAP_NUMBER_TYPE:
62
    case MUTABLE_HEAP_NUMBER_TYPE:
63 64
      HeapNumber::cast(this)->HeapNumberVerify();
      break;
65 66
    case SIMD128_VALUE_TYPE:
      Simd128Value::cast(this)->Simd128ValueVerify();
67
      break;
68 69 70
    case FIXED_ARRAY_TYPE:
      FixedArray::cast(this)->FixedArrayVerify();
      break;
71 72 73
    case FIXED_DOUBLE_ARRAY_TYPE:
      FixedDoubleArray::cast(this)->FixedDoubleArrayVerify();
      break;
74 75 76
    case BYTE_ARRAY_TYPE:
      ByteArray::cast(this)->ByteArrayVerify();
      break;
77 78 79
    case BYTECODE_ARRAY_TYPE:
      BytecodeArray::cast(this)->BytecodeArrayVerify();
      break;
80 81 82
    case TRANSITION_ARRAY_TYPE:
      TransitionArray::cast(this)->TransitionArrayVerify();
      break;
83 84 85
    case FREE_SPACE_TYPE:
      FreeSpace::cast(this)->FreeSpaceVerify();
      break;
86 87 88 89

#define VERIFY_TYPED_ARRAY(Type, type, TYPE, ctype, size)                      \
    case FIXED_##TYPE##_ARRAY_TYPE:                                            \
      Fixed##Type##Array::cast(this)->FixedTypedArrayVerify();                 \
90
      break;
91 92 93 94

    TYPED_ARRAYS(VERIFY_TYPED_ARRAY)
#undef VERIFY_TYPED_ARRAY

95 96 97 98 99 100 101
    case CODE_TYPE:
      Code::cast(this)->CodeVerify();
      break;
    case ODDBALL_TYPE:
      Oddball::cast(this)->OddballVerify();
      break;
    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:
ager@chromium.org's avatar
ager@chromium.org committed
106
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
107
    case JS_PROMISE_TYPE:
108 109
      JSObject::cast(this)->JSObjectVerify();
      break;
110 111 112
    case JS_GENERATOR_OBJECT_TYPE:
      JSGeneratorObject::cast(this)->JSGeneratorObjectVerify();
      break;
113 114 115
    case JS_VALUE_TYPE:
      JSValue::cast(this)->JSValueVerify();
      break;
116 117 118
    case JS_DATE_TYPE:
      JSDate::cast(this)->JSDateVerify();
      break;
119 120 121
    case JS_BOUND_FUNCTION_TYPE:
      JSBoundFunction::cast(this)->JSBoundFunctionVerify();
      break;
122 123 124
    case JS_FUNCTION_TYPE:
      JSFunction::cast(this)->JSFunctionVerify();
      break;
125 126 127
    case JS_GLOBAL_PROXY_TYPE:
      JSGlobalProxy::cast(this)->JSGlobalProxyVerify();
      break;
128 129 130
    case JS_GLOBAL_OBJECT_TYPE:
      JSGlobalObject::cast(this)->JSGlobalObjectVerify();
      break;
131 132 133 134
    case CELL_TYPE:
      Cell::cast(this)->CellVerify();
      break;
    case PROPERTY_CELL_TYPE:
135
      PropertyCell::cast(this)->PropertyCellVerify();
136
      break;
ulan@chromium.org's avatar
ulan@chromium.org committed
137 138 139
    case WEAK_CELL_TYPE:
      WeakCell::cast(this)->WeakCellVerify();
      break;
140 141 142
    case JS_ARRAY_TYPE:
      JSArray::cast(this)->JSArrayVerify();
      break;
143 144 145
    case JS_MODULE_NAMESPACE_TYPE:
      JSModuleNamespace::cast(this)->JSModuleNamespaceVerify();
      break;
146 147 148
    case JS_FIXED_ARRAY_ITERATOR_TYPE:
      JSFixedArrayIterator::cast(this)->JSFixedArrayIteratorVerify();
      break;
149 150 151 152 153 154
    case JS_SET_TYPE:
      JSSet::cast(this)->JSSetVerify();
      break;
    case JS_MAP_TYPE:
      JSMap::cast(this)->JSMapVerify();
      break;
155 156 157 158 159 160
    case JS_SET_ITERATOR_TYPE:
      JSSetIterator::cast(this)->JSSetIteratorVerify();
      break;
    case JS_MAP_ITERATOR_TYPE:
      JSMapIterator::cast(this)->JSMapIteratorVerify();
      break;
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
    case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
    case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
    case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
    case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
    case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
    case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:
      JSArrayIterator::cast(this)->JSArrayIteratorVerify();
      break;

199 200 201
    case JS_STRING_ITERATOR_TYPE:
      JSStringIterator::cast(this)->JSStringIteratorVerify();
      break;
202 203 204
    case JS_WEAK_MAP_TYPE:
      JSWeakMap::cast(this)->JSWeakMapVerify();
      break;
205 206 207
    case JS_WEAK_SET_TYPE:
      JSWeakSet::cast(this)->JSWeakSetVerify();
      break;
208 209 210
    case JS_REGEXP_TYPE:
      JSRegExp::cast(this)->JSRegExpVerify();
      break;
211 212
    case FILLER_TYPE:
      break;
213 214 215
    case JS_PROXY_TYPE:
      JSProxy::cast(this)->JSProxyVerify();
      break;
216 217
    case FOREIGN_TYPE:
      Foreign::cast(this)->ForeignVerify();
218 219 220 221
      break;
    case SHARED_FUNCTION_INFO_TYPE:
      SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
      break;
222 223 224
    case JS_MESSAGE_OBJECT_TYPE:
      JSMessageObject::cast(this)->JSMessageObjectVerify();
      break;
225 226 227
    case JS_ARRAY_BUFFER_TYPE:
      JSArrayBuffer::cast(this)->JSArrayBufferVerify();
      break;
228 229 230
    case JS_TYPED_ARRAY_TYPE:
      JSTypedArray::cast(this)->JSTypedArrayVerify();
      break;
231 232 233
    case JS_DATA_VIEW_TYPE:
      JSDataView::cast(this)->JSDataViewVerify();
      break;
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

#define MAKE_STRUCT_CASE(NAME, Name, name) \
  case NAME##_TYPE:                        \
    Name::cast(this)->Name##Verify();      \
    break;
    STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE

    default:
      UNREACHABLE();
      break;
  }
}


void HeapObject::VerifyHeapPointer(Object* p) {
250
  CHECK(p->IsHeapObject());
251 252
  HeapObject* ho = HeapObject::cast(p);
  CHECK(ho->GetHeap()->Contains(ho));
253 254 255
}


256 257 258
void Symbol::SymbolVerify() {
  CHECK(IsSymbol());
  CHECK(HasHashCode());
259
  CHECK(Hash() > 0u);
260
  CHECK(name()->IsUndefined(GetIsolate()) || name()->IsString());
261 262 263
}


264
void HeapNumber::HeapNumberVerify() {
265
  CHECK(IsHeapNumber() || IsMutableHeapNumber());
266
}
267 268


269
void Simd128Value::Simd128ValueVerify() { CHECK(IsSimd128Value()); }
270 271


272
void ByteArray::ByteArrayVerify() {
273
  CHECK(IsByteArray());
274 275 276
}


277 278
void BytecodeArray::BytecodeArrayVerify() {
  // TODO(oth): Walk bytecodes and immediate values to validate sanity.
279 280 281 282
  // - All bytecodes are known and well formed.
  // - Jumps must go to new instructions starts.
  // - No Illegal bytecodes.
  // - No consecutive sequences of prefix Wide / ExtraWide.
283
  CHECK(IsBytecodeArray());
284 285
  CHECK(constant_pool()->IsFixedArray());
  VerifyHeapPointer(constant_pool());
286 287 288
}


289
void FreeSpace::FreeSpaceVerify() {
290
  CHECK(IsFreeSpace());
291 292 293
}


294 295
template <class Traits>
void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
296 297 298
  CHECK(IsHeapObject() &&
        HeapObject::cast(this)->map()->instance_type() ==
            Traits::kInstanceType);
299 300 301 302 303 304
  if (base_pointer() == this) {
    CHECK(external_pointer() ==
          ExternalReference::fixed_typed_array_base_data_offset().address());
  } else {
    CHECK(base_pointer() == nullptr);
  }
305 306 307
}


308
bool JSObject::ElementsAreSafeToExamine() {
309 310 311
  // If a GC was caused while constructing this object, the elements
  // pointer may point to a one pointer filler map.
  return reinterpret_cast<Map*>(elements()) !=
312 313 314
      GetHeap()->one_pointer_filler_map();
}

315

316 317 318
void JSObject::JSObjectVerify() {
  VerifyHeapPointer(properties());
  VerifyHeapPointer(elements());
319

320 321 322
  if (HasSloppyArgumentsElements()) {
    CHECK(this->elements()->IsFixedArray());
    CHECK_GE(this->elements()->length(), 2);
323 324
  }

325 326 327 328 329 330 331 332 333 334 335
  if (HasFastProperties()) {
    int actual_unused_property_fields = map()->GetInObjectProperties() +
                                        properties()->length() -
                                        map()->NextFreePropertyIndex();
    if (map()->unused_property_fields() != actual_unused_property_fields) {
      // This could actually happen in the middle of StoreTransitionStub
      // when the new extended backing store is already set into the object and
      // the allocation of the MutableHeapNumber triggers GC (in this case map
      // is not updated yet).
      CHECK_EQ(map()->unused_property_fields(),
               actual_unused_property_fields - JSObject::kFieldsAdded);
336
    }
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
    DescriptorArray* descriptors = map()->instance_descriptors();
    Isolate* isolate = GetIsolate();
    for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
      if (descriptors->GetDetails(i).type() == DATA) {
        Representation r = descriptors->GetDetails(i).representation();
        FieldIndex index = FieldIndex::ForDescriptor(map(), i);
        if (IsUnboxedDoubleField(index)) {
          DCHECK(r.IsDouble());
          continue;
        }
        Object* value = RawFastPropertyAt(index);
        if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber());
        if (value->IsUninitialized(isolate)) continue;
        if (r.IsSmi()) DCHECK(value->IsSmi());
        if (r.IsHeapObject()) DCHECK(value->IsHeapObject());
        FieldType* field_type = descriptors->GetFieldType(i);
        bool type_is_none = field_type->IsNone();
        bool type_is_any = field_type->IsAny();
        if (r.IsNone()) {
          CHECK(type_is_none);
        } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) {
          // If allocation folding is off then GC could happen during inner
          // object literal creation and we will end up having and undefined
          // value that does not match the field type.
          CHECK(!field_type->NowStable() || field_type->NowContains(value) ||
                (!FLAG_use_allocation_folding && value->IsUndefined(isolate)));
        }
364 365
      }
    }
366
  }
367

368 369 370 371 372 373 374 375 376 377
  // If a GC was caused while constructing this object, the elements
  // pointer may point to a one pointer filler map.
  if (ElementsAreSafeToExamine()) {
    CHECK_EQ((map()->has_fast_smi_or_object_elements() ||
              (elements() == GetHeap()->empty_fixed_array()) ||
              HasFastStringWrapperElements()),
             (elements()->map() == GetHeap()->fixed_array_map() ||
              elements()->map() == GetHeap()->fixed_cow_array_map()));
    CHECK(map()->has_fast_object_elements() == HasFastObjectElements());
  }
378
}
379

380

381
void Map::MapVerify() {
382 383
  Heap* heap = GetHeap();
  CHECK(!heap->InNewSpace(this));
384
  CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
385
  CHECK(instance_size() == kVariableSizeSentinel ||
386
         (kPointerSize <= instance_size() &&
387
          instance_size() < heap->Capacity()));
388
  CHECK(GetBackPointer()->IsUndefined(heap->isolate()) ||
389
        !Map::cast(GetBackPointer())->is_stable());
390 391
  VerifyHeapPointer(prototype());
  VerifyHeapPointer(instance_descriptors());
392
  SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates());
393 394
  SLOW_DCHECK(TransitionArray::IsSortedNoDuplicates(this));
  SLOW_DCHECK(TransitionArray::IsConsistentWithBackPointers(this));
395 396 397
  // TODO(ishell): turn it back to SLOW_DCHECK.
  CHECK(!FLAG_unbox_double_fields ||
        layout_descriptor()->IsConsistentWithMap(this));
398 399 400
}


401
void Map::DictionaryMapVerify() {
402
  MapVerify();
403
  CHECK(is_dictionary_map());
404 405
  CHECK(instance_descriptors()->IsEmpty());
  CHECK_EQ(0, unused_property_fields());
406
  CHECK_EQ(Heap::GetStaticVisitorIdForMap(this), visitor_id());
407 408 409
}


410 411 412 413 414
void Map::VerifyOmittedMapChecks() {
  if (!FLAG_omit_map_checks_for_leaf_maps) return;
  if (!is_stable() ||
      is_deprecated() ||
      is_dictionary_map()) {
ulan's avatar
ulan committed
415
    CHECK(dependent_code()->IsEmpty(DependentCode::kPrototypeCheckGroup));
416 417 418 419
  }
}


420
void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
421 422
  VerifyObjectField(kStorage1Offset);
  VerifyObjectField(kStorage2Offset);
423
  VerifyObjectField(kStorage3Offset);
424 425 426
}


427 428 429 430 431
void AliasedArgumentsEntry::AliasedArgumentsEntryVerify() {
  VerifySmiField(kAliasedContextSlot);
}


432 433 434
void FixedArray::FixedArrayVerify() {
  for (int i = 0; i < length(); i++) {
    Object* e = get(i);
435
    VerifyPointer(e);
436 437 438 439
  }
}


440 441 442
void FixedDoubleArray::FixedDoubleArrayVerify() {
  for (int i = 0; i < length(); i++) {
    if (!is_the_hole(i)) {
443
      uint64_t value = get_representation(i);
444 445 446 447 448 449
      uint64_t unexpected =
          bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN()) &
          V8_UINT64_C(0x7FF8000000000000);
      // Create implementation specific sNaN by inverting relevant bit.
      unexpected ^= V8_UINT64_C(0x0008000000000000);
      CHECK((value & V8_UINT64_C(0x7FF8000000000000)) != unexpected ||
450
            (value & V8_UINT64_C(0x0007FFFFFFFFFFFF)) == V8_UINT64_C(0));
451 452 453 454 455
    }
  }
}


456 457 458 459 460 461
void TransitionArray::TransitionArrayVerify() {
  for (int i = 0; i < length(); i++) {
    Object* e = get(i);
    VerifyPointer(e);
  }
  CHECK_LE(LengthFor(number_of_transitions()), length());
462
  CHECK(next_link()->IsUndefined(GetIsolate()) || next_link()->IsSmi() ||
463 464 465 466
        next_link()->IsTransitionArray());
}


467 468 469 470 471 472
void JSGeneratorObject::JSGeneratorObjectVerify() {
  // In an expression like "new g()", there can be a point where a generator
  // object is allocated but its fields are all undefined, as it hasn't yet been
  // initialized by the generator.  Hence these weak checks.
  VerifyObjectField(kFunctionOffset);
  VerifyObjectField(kContextOffset);
473
  VerifyObjectField(kReceiverOffset);
474 475 476 477 478
  VerifyObjectField(kOperandStackOffset);
  VerifyObjectField(kContinuationOffset);
}


479 480 481 482 483 484 485 486
void JSValue::JSValueVerify() {
  Object* v = value();
  if (v->IsHeapObject()) {
    VerifyHeapPointer(v);
  }
}


487 488 489 490
void JSDate::JSDateVerify() {
  if (value()->IsHeapObject()) {
    VerifyHeapPointer(value());
  }
491 492 493 494 495 496 497 498 499 500 501 502
  Isolate* isolate = GetIsolate();
  CHECK(value()->IsUndefined(isolate) || value()->IsSmi() ||
        value()->IsHeapNumber());
  CHECK(year()->IsUndefined(isolate) || year()->IsSmi() || year()->IsNaN());
  CHECK(month()->IsUndefined(isolate) || month()->IsSmi() || month()->IsNaN());
  CHECK(day()->IsUndefined(isolate) || day()->IsSmi() || day()->IsNaN());
  CHECK(weekday()->IsUndefined(isolate) || weekday()->IsSmi() ||
        weekday()->IsNaN());
  CHECK(hour()->IsUndefined(isolate) || hour()->IsSmi() || hour()->IsNaN());
  CHECK(min()->IsUndefined(isolate) || min()->IsSmi() || min()->IsNaN());
  CHECK(sec()->IsUndefined(isolate) || sec()->IsSmi() || sec()->IsNaN());
  CHECK(cache_stamp()->IsUndefined(isolate) || cache_stamp()->IsSmi() ||
503 504
        cache_stamp()->IsNaN());

505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
  if (month()->IsSmi()) {
    int month = Smi::cast(this->month())->value();
    CHECK(0 <= month && month <= 11);
  }
  if (day()->IsSmi()) {
    int day = Smi::cast(this->day())->value();
    CHECK(1 <= day && day <= 31);
  }
  if (hour()->IsSmi()) {
    int hour = Smi::cast(this->hour())->value();
    CHECK(0 <= hour && hour <= 23);
  }
  if (min()->IsSmi()) {
    int min = Smi::cast(this->min())->value();
    CHECK(0 <= min && min <= 59);
  }
  if (sec()->IsSmi()) {
    int sec = Smi::cast(this->sec())->value();
    CHECK(0 <= sec && sec <= 59);
  }
  if (weekday()->IsSmi()) {
    int weekday = Smi::cast(this->weekday())->value();
    CHECK(0 <= weekday && weekday <= 6);
528
  }
529 530
  if (cache_stamp()->IsSmi()) {
    CHECK(Smi::cast(cache_stamp())->value() <=
531
          Smi::cast(isolate->date_cache()->stamp())->value());
532
  }
533 534 535
}


536 537 538 539 540 541 542 543 544 545
void JSMessageObject::JSMessageObjectVerify() {
  CHECK(IsJSMessageObject());
  VerifyObjectField(kStartPositionOffset);
  VerifyObjectField(kEndPositionOffset);
  VerifyObjectField(kArgumentsOffset);
  VerifyObjectField(kScriptOffset);
  VerifyObjectField(kStackFramesOffset);
}


546 547 548
void String::StringVerify() {
  CHECK(IsString());
  CHECK(length() >= 0 && length() <= Smi::kMaxValue);
549
  if (IsInternalizedString()) {
550
    CHECK(!GetHeap()->InNewSpace(this));
551
  }
552 553 554 555 556 557 558 559 560 561 562 563
  if (IsConsString()) {
    ConsString::cast(this)->ConsStringVerify();
  } else if (IsSlicedString()) {
    SlicedString::cast(this)->SlicedStringVerify();
  }
}


void ConsString::ConsStringVerify() {
  CHECK(this->first()->IsString());
  CHECK(this->second() == GetHeap()->empty_string() ||
        this->second()->IsString());
564
  CHECK(this->length() >= ConsString::kMinLength);
565
  CHECK(this->length() == this->first()->length() + this->second()->length());
566 567 568 569 570 571 572 573 574 575 576 577
  if (this->IsFlat()) {
    // A flat cons can only be created by String::SlowTryFlatten.
    // Afterwards, the first part may be externalized.
    CHECK(this->first()->IsSeqString() || this->first()->IsExternalString());
  }
}


void SlicedString::SlicedStringVerify() {
  CHECK(!this->parent()->IsConsString());
  CHECK(!this->parent()->IsSlicedString());
  CHECK(this->length() >= SlicedString::kMinLength);
578 579 580
}


581 582
void JSBoundFunction::JSBoundFunctionVerify() {
  CHECK(IsJSBoundFunction());
583
  JSObjectVerify();
584 585 586 587 588 589 590 591 592
  VerifyObjectField(kBoundThisOffset);
  VerifyObjectField(kBoundTargetFunctionOffset);
  VerifyObjectField(kBoundArgumentsOffset);
  CHECK(bound_target_function()->IsCallable());
  CHECK(IsCallable());
  CHECK_EQ(IsConstructor(), bound_target_function()->IsConstructor());
}


593 594 595
void JSFunction::JSFunctionVerify() {
  CHECK(IsJSFunction());
  VerifyObjectField(kPrototypeOrInitialMapOffset);
596
  VerifyObjectField(kNextFunctionLinkOffset);
597
  CHECK(code()->IsCode());
598
  CHECK(next_function_link() == NULL ||
599
        next_function_link()->IsUndefined(GetIsolate()) ||
600
        next_function_link()->IsJSFunction());
601
  CHECK(map()->is_callable());
602 603
}

604

605 606 607 608
void SharedFunctionInfo::SharedFunctionInfoVerify() {
  CHECK(IsSharedFunctionInfo());
  VerifyObjectField(kNameOffset);
  VerifyObjectField(kCodeOffset);
609
  VerifyObjectField(kOptimizedCodeMapOffset);
610
  VerifyObjectField(kFeedbackMetadataOffset);
611
  VerifyObjectField(kScopeInfoOffset);
612
  VerifyObjectField(kOuterScopeInfoOffset);
613
  VerifyObjectField(kInstanceClassNameOffset);
614
  CHECK(function_data()->IsUndefined(GetIsolate()) || IsApiFunction() ||
615
        HasBytecodeArray() || HasAsmWasmData());
616
  VerifyObjectField(kFunctionDataOffset);
617 618
  VerifyObjectField(kScriptOffset);
  VerifyObjectField(kDebugInfoOffset);
619 620 621
  CHECK(function_identifier()->IsUndefined(GetIsolate()) ||
        HasBuiltinFunctionId() || HasInferredName());
  VerifyObjectField(kFunctionIdentifierOffset);
622
}
623 624 625 626 627


void JSGlobalProxy::JSGlobalProxyVerify() {
  CHECK(IsJSGlobalProxy());
  JSObjectVerify();
628
  VerifyObjectField(JSGlobalProxy::kNativeContextOffset);
629
  // Make sure that this object has no properties, elements.
feng@chromium.org's avatar
feng@chromium.org committed
630
  CHECK_EQ(0, properties()->length());
631
  CHECK_EQ(0, FixedArray::cast(elements())->length());
632
}
633 634 635 636


void JSGlobalObject::JSGlobalObjectVerify() {
  CHECK(IsJSGlobalObject());
yangguo's avatar
yangguo committed
637 638 639 640
  // Do not check the dummy global object for the builtins.
  if (GlobalDictionary::cast(properties())->NumberOfElements() == 0 &&
      elements()->length() == 0) {
    return;
641 642 643 644 645 646 647
  }
  JSObjectVerify();
}


void Oddball::OddballVerify() {
  CHECK(IsOddball());
648
  Heap* heap = GetHeap();
649 650 651
  VerifyHeapPointer(to_string());
  Object* number = to_number();
  if (number->IsHeapObject()) {
652 653
    CHECK(number == heap->nan_value() ||
          number == heap->hole_nan_value());
654
  } else {
655
    CHECK(number->IsSmi());
656
    int value = Smi::cast(number)->value();
657
    // Hidden oddballs have negative smis.
658
    const int kLeastHiddenOddballNumber = -7;
659 660
    CHECK_LE(value, 1);
    CHECK(value >= kLeastHiddenOddballNumber);
661
  }
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
  if (map() == heap->undefined_map()) {
    CHECK(this == heap->undefined_value());
  } else if (map() == heap->the_hole_map()) {
    CHECK(this == heap->the_hole_value());
  } else if (map() == heap->null_map()) {
    CHECK(this == heap->null_value());
  } else if (map() == heap->boolean_map()) {
    CHECK(this == heap->true_value() ||
          this == heap->false_value());
  } else if (map() == heap->uninitialized_map()) {
    CHECK(this == heap->uninitialized_value());
  } else if (map() == heap->no_interceptor_result_sentinel_map()) {
    CHECK(this == heap->no_interceptor_result_sentinel());
  } else if (map() == heap->arguments_marker_map()) {
    CHECK(this == heap->arguments_marker());
  } else if (map() == heap->termination_exception_map()) {
    CHECK(this == heap->termination_exception());
679 680
  } else if (map() == heap->exception_map()) {
    CHECK(this == heap->exception());
681 682
  } else if (map() == heap->optimized_out_map()) {
    CHECK(this == heap->optimized_out());
683 684
  } else if (map() == heap->stale_register_map()) {
    CHECK(this == heap->stale_register());
685 686 687
  } else {
    UNREACHABLE();
  }
688 689 690
}


691 692 693 694 695 696
void Cell::CellVerify() {
  CHECK(IsCell());
  VerifyObjectField(kValueOffset);
}


697 698
void PropertyCell::PropertyCellVerify() {
  CHECK(IsPropertyCell());
699 700 701 702
  VerifyObjectField(kValueOffset);
}


ulan@chromium.org's avatar
ulan@chromium.org committed
703 704 705 706 707 708 709
void WeakCell::WeakCellVerify() {
  CHECK(IsWeakCell());
  VerifyObjectField(kValueOffset);
  VerifyObjectField(kNextOffset);
}


710
void Code::CodeVerify() {
711
  CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
712
                  kCodeAlignment));
713
  relocation_info()->ObjectVerify();
714
  Address last_gc_pc = NULL;
715
  Isolate* isolate = GetIsolate();
716
  for (RelocIterator it(this); !it.done(); it.next()) {
717
    it.rinfo()->Verify(isolate);
718
    // Ensure that GC will not iterate twice over the same pointer.
719
    if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
720 721 722
      CHECK(it.rinfo()->pc() != last_gc_pc);
      last_gc_pc = it.rinfo()->pc();
    }
723
  }
724
  CHECK(raw_type_feedback_info() == Smi::kZero ||
725
        raw_type_feedback_info()->IsSmi() == IsCodeStubOrIC());
726 727 728
}


729
void Code::VerifyEmbeddedObjectsDependency() {
730
  if (!CanContainWeakObjects()) return;
ulan's avatar
ulan committed
731
  WeakCell* cell = CachedWeakCell();
732 733 734
  DisallowHeapAllocation no_gc;
  Isolate* isolate = GetIsolate();
  HandleScope scope(isolate);
735 736
  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
737
    Object* obj = it.rinfo()->target_object();
738
    if (IsWeakObject(obj)) {
739 740
      if (obj->IsMap()) {
        Map* map = Map::cast(obj);
741
        CHECK(map->dependent_code()->Contains(DependentCode::kWeakCodeGroup,
ulan's avatar
ulan committed
742
                                              cell));
743
      } else if (obj->IsJSObject()) {
744 745
        if (isolate->heap()->InNewSpace(obj)) {
          ArrayList* list =
746
              GetIsolate()->heap()->weak_new_space_object_to_code_list();
747 748 749 750 751 752 753 754 755 756 757 758 759
          bool found = false;
          for (int i = 0; i < list->Length(); i += 2) {
            WeakCell* obj_cell = WeakCell::cast(list->Get(i));
            if (!obj_cell->cleared() && obj_cell->value() == obj &&
                WeakCell::cast(list->Get(i + 1)) == cell) {
              found = true;
              break;
            }
          }
          CHECK(found);
        } else {
          Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate);
          DependentCode* dep =
760
              GetIsolate()->heap()->LookupWeakObjectToCodeDependency(key_obj);
761 762
          dep->Contains(DependentCode::kWeakCodeGroup, cell);
        }
763 764 765 766 767 768
      }
    }
  }
}


769 770
void JSArray::JSArrayVerify() {
  JSObjectVerify();
771
  Isolate* isolate = GetIsolate();
772
  CHECK(length()->IsNumber() || length()->IsUndefined(isolate));
773 774
  // If a GC was caused while constructing this array, the elements
  // pointer may point to a one pointer filler map.
775
  if (ElementsAreSafeToExamine()) {
776 777
    CHECK(elements()->IsUndefined(isolate) || elements()->IsFixedArray() ||
          elements()->IsFixedDoubleArray());
778
  }
779 780
}

781

782 783 784 785
void JSSet::JSSetVerify() {
  CHECK(IsJSSet());
  JSObjectVerify();
  VerifyHeapPointer(table());
786
  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate()));
787
  // TODO(arv): Verify OrderedHashTable too.
788 789 790 791 792 793 794
}


void JSMap::JSMapVerify() {
  CHECK(IsJSMap());
  JSObjectVerify();
  VerifyHeapPointer(table());
795
  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate()));
796 797 798 799 800 801 802 803
  // TODO(arv): Verify OrderedHashTable too.
}


void JSSetIterator::JSSetIteratorVerify() {
  CHECK(IsJSSetIterator());
  JSObjectVerify();
  VerifyHeapPointer(table());
804 805 806 807
  Isolate* isolate = GetIsolate();
  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate));
  CHECK(index()->IsSmi() || index()->IsUndefined(isolate));
  CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate));
808 809 810 811 812 813 814
}


void JSMapIterator::JSMapIteratorVerify() {
  CHECK(IsJSMapIterator());
  JSObjectVerify();
  VerifyHeapPointer(table());
815 816 817 818
  Isolate* isolate = GetIsolate();
  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate));
  CHECK(index()->IsSmi() || index()->IsUndefined(isolate));
  CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate));
819 820 821
}


822 823 824 825
void JSWeakMap::JSWeakMapVerify() {
  CHECK(IsJSWeakMap());
  JSObjectVerify();
  VerifyHeapPointer(table());
826
  CHECK(table()->IsHashTable() || table()->IsUndefined(GetIsolate()));
827 828
}

829 830 831 832 833 834 835 836 837 838
void JSArrayIterator::JSArrayIteratorVerify() {
  CHECK(IsJSArrayIterator());
  JSObjectVerify();
  CHECK(object()->IsJSReceiver() || object()->IsUndefined(GetIsolate()));

  CHECK_GE(index()->Number(), 0);
  CHECK_LE(index()->Number(), kMaxSafeInteger);
  CHECK(object_map()->IsMap() || object_map()->IsUndefined(GetIsolate()));
}

839 840 841
void JSStringIterator::JSStringIteratorVerify() {
  CHECK(IsJSStringIterator());
  JSObjectVerify();
842
  CHECK(string()->IsString());
843

844 845 846
  CHECK_GE(index(), 0);
  CHECK_LE(index(), String::kMaxLength);
}
847

848 849 850 851
void JSWeakSet::JSWeakSetVerify() {
  CHECK(IsJSWeakSet());
  JSObjectVerify();
  VerifyHeapPointer(table());
852
  CHECK(table()->IsHashTable() || table()->IsUndefined(GetIsolate()));
853 854 855
}


856 857
void JSRegExp::JSRegExpVerify() {
  JSObjectVerify();
858 859
  Isolate* isolate = GetIsolate();
  CHECK(data()->IsUndefined(isolate) || data()->IsFixedArray());
860 861 862
  switch (TypeTag()) {
    case JSRegExp::ATOM: {
      FixedArray* arr = FixedArray::cast(data());
863
      CHECK(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
864
      break;
865
    }
866
    case JSRegExp::IRREGEXP: {
867
      bool is_native = RegExpImpl::UsesNativeRegExp();
868

869
      FixedArray* arr = FixedArray::cast(data());
870
      Object* one_byte_data = arr->get(JSRegExp::kIrregexpLatin1CodeIndex);
871
      // Smi : Not compiled yet (-1) or code prepared for flushing.
872 873
      // JSObject: Compilation error.
      // Code/ByteArray: Compiled code.
874 875 876
      CHECK(
          one_byte_data->IsSmi() ||
          (is_native ? one_byte_data->IsCode() : one_byte_data->IsByteArray()));
877
      Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex);
878
      CHECK(uc16_data->IsSmi() ||
879 880
             (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray()));

881 882 883 884
      Object* one_byte_saved =
          arr->get(JSRegExp::kIrregexpLatin1CodeSavedIndex);
      CHECK(one_byte_saved->IsSmi() || one_byte_saved->IsString() ||
            one_byte_saved->IsCode());
885
      Object* uc16_saved = arr->get(JSRegExp::kIrregexpUC16CodeSavedIndex);
886
      CHECK(uc16_saved->IsSmi() || uc16_saved->IsString() ||
887 888
             uc16_saved->IsCode());

889 890
      CHECK(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi());
      CHECK(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi());
891 892 893
      break;
    }
    default:
894
      CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag());
895
      CHECK(data()->IsUndefined(isolate));
896
      break;
897
  }
898 899
}

900
void JSProxy::JSProxyVerify() {
901
  CHECK(IsJSProxy());
902
  VerifyPointer(target());
903
  VerifyPointer(handler());
904
  Isolate* isolate = GetIsolate();
905 906
  CHECK_EQ(target()->IsCallable(), map()->is_callable());
  CHECK_EQ(target()->IsConstructor(), map()->is_constructor());
907
  CHECK(hash()->IsSmi() || hash()->IsUndefined(isolate));
908
  CHECK(map()->prototype()->IsNull(isolate));
909 910
  // There should be no properties on a Proxy.
  CHECK_EQ(0, map()->NumberOfOwnDescriptors());
911 912
}

913

914 915 916 917
void JSArrayBuffer::JSArrayBufferVerify() {
  CHECK(IsJSArrayBuffer());
  JSObjectVerify();
  VerifyPointer(byte_length());
918 919
  CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber() ||
        byte_length()->IsUndefined(GetIsolate()));
920 921
}

922

923 924
void JSArrayBufferView::JSArrayBufferViewVerify() {
  CHECK(IsJSArrayBufferView());
925 926
  JSObjectVerify();
  VerifyPointer(buffer());
927 928
  Isolate* isolate = GetIsolate();
  CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined(isolate) ||
929
        buffer() == Smi::kZero);
930

931 932
  VerifyPointer(raw_byte_offset());
  CHECK(raw_byte_offset()->IsSmi() || raw_byte_offset()->IsHeapNumber() ||
933
        raw_byte_offset()->IsUndefined(isolate));
934

935 936
  VerifyPointer(raw_byte_length());
  CHECK(raw_byte_length()->IsSmi() || raw_byte_length()->IsHeapNumber() ||
937
        raw_byte_length()->IsUndefined(isolate));
938 939
}

940

941 942 943
void JSTypedArray::JSTypedArrayVerify() {
  CHECK(IsJSTypedArray());
  JSArrayBufferViewVerify();
944
  VerifyPointer(raw_length());
945
  CHECK(raw_length()->IsSmi() || raw_length()->IsUndefined(GetIsolate()));
946 947 948 949
  VerifyPointer(elements());
}


950 951 952 953 954 955
void JSDataView::JSDataViewVerify() {
  CHECK(IsJSDataView());
  JSArrayBufferViewVerify();
}


956
void Foreign::ForeignVerify() {
957
  CHECK(IsForeign());
958 959 960
}


961 962
void Box::BoxVerify() {
  CHECK(IsBox());
963
  value()->ObjectVerify();
964 965
}

966 967 968 969 970 971 972
void PromiseResolveThenableJobInfo::PromiseResolveThenableJobInfoVerify() {
  Isolate* isolate = GetIsolate();
  CHECK(IsPromiseResolveThenableJobInfo());
  CHECK(thenable()->IsJSReceiver());
  CHECK(then()->IsJSReceiver());
  CHECK(resolve()->IsJSFunction());
  CHECK(reject()->IsJSFunction());
973 974
  CHECK(debug_id()->IsNumber() || debug_id()->IsUndefined(isolate));
  CHECK(debug_name()->IsString() || debug_name()->IsUndefined(isolate));
975 976
}

977 978 979 980 981 982
void PromiseReactionJobInfo::PromiseReactionJobInfoVerify() {
  Isolate* isolate = GetIsolate();
  CHECK(IsPromiseReactionJobInfo());
  CHECK(value()->IsObject());
  CHECK(tasks()->IsJSArray() || tasks()->IsCallable());
  CHECK(deferred()->IsJSObject() || deferred()->IsUndefined(isolate));
983 984
  CHECK(debug_id()->IsNumber() || debug_id()->IsUndefined(isolate));
  CHECK(debug_name()->IsString() || debug_name()->IsUndefined(isolate));
985 986 987
  CHECK(context()->IsContext());
}

988 989
void JSModuleNamespace::JSModuleNamespaceVerify() {
  CHECK(IsJSModuleNamespace());
990
  VerifyPointer(module());
991 992
}

993 994 995
void JSFixedArrayIterator::JSFixedArrayIteratorVerify() {
  CHECK(IsJSFixedArrayIterator());

996 997
  VerifyPointer(array());
  VerifyPointer(initial_next());
998 999 1000 1001 1002
  VerifySmiField(kIndexOffset);

  CHECK_LE(index(), array()->length());
}

1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
void ModuleInfoEntry::ModuleInfoEntryVerify() {
  Isolate* isolate = GetIsolate();
  CHECK(IsModuleInfoEntry());

  CHECK(export_name()->IsUndefined(isolate) || export_name()->IsString());
  CHECK(local_name()->IsUndefined(isolate) || local_name()->IsString());
  CHECK(import_name()->IsUndefined(isolate) || import_name()->IsString());

  VerifySmiField(kModuleRequestOffset);
  VerifySmiField(kCellIndexOffset);
  VerifySmiField(kBegPosOffset);
  VerifySmiField(kEndPosOffset);

  CHECK_IMPLIES(import_name()->IsString(), module_request() >= 0);
  CHECK_IMPLIES(export_name()->IsString() && import_name()->IsString(),
                local_name()->IsUndefined(isolate));
}

1021 1022
void Module::ModuleVerify() {
  CHECK(IsModule());
1023 1024 1025 1026 1027

  VerifyPointer(code());
  VerifyPointer(exports());
  VerifyPointer(module_namespace());
  VerifyPointer(requested_modules());
1028
  VerifySmiField(kHashOffset);
1029 1030 1031 1032 1033 1034

  CHECK((!instantiated() && code()->IsSharedFunctionInfo()) ||
        (instantiated() && !evaluated() && code()->IsJSFunction()) ||
        (instantiated() && evaluated() && code()->IsModuleInfo()));

  CHECK(module_namespace()->IsUndefined(GetIsolate()) ||
1035
        module_namespace()->IsJSModuleNamespace());
1036 1037 1038 1039 1040
  if (module_namespace()->IsJSModuleNamespace()) {
    CHECK_EQ(JSModuleNamespace::cast(module_namespace())->module(), this);
  }

  CHECK_EQ(requested_modules()->length(), info()->module_requests()->length());
1041

1042
  CHECK_NE(hash(), 0);
1043
}
1044

1045 1046
void PrototypeInfo::PrototypeInfoVerify() {
  CHECK(IsPrototypeInfo());
1047
  CHECK(weak_cell()->IsWeakCell() || weak_cell()->IsUndefined(GetIsolate()));
1048 1049 1050 1051 1052 1053 1054 1055
  if (prototype_users()->IsWeakFixedArray()) {
    WeakFixedArray::cast(prototype_users())->FixedArrayVerify();
  } else {
    CHECK(prototype_users()->IsSmi());
  }
  CHECK(validity_cell()->IsCell() || validity_cell()->IsSmi());
}

1056 1057 1058 1059 1060 1061 1062
void Tuple3::Tuple3Verify() {
  CHECK(IsTuple3());
  VerifyObjectField(kValue1Offset);
  VerifyObjectField(kValue2Offset);
  VerifyObjectField(kValue3Offset);
}

1063 1064
void ContextExtension::ContextExtensionVerify() {
  CHECK(IsContextExtension());
1065 1066 1067 1068 1069
  VerifyObjectField(kScopeInfoOffset);
  VerifyObjectField(kExtensionOffset);
}


1070 1071 1072 1073
void AccessorInfo::AccessorInfoVerify() {
  CHECK(IsAccessorInfo());
  VerifyPointer(name());
  VerifyPointer(expected_receiver_type());
1074 1075
  VerifyPointer(getter());
  VerifyPointer(setter());
1076
  VerifyPointer(js_getter());
1077 1078 1079 1080
  VerifyPointer(data());
}


1081 1082 1083 1084 1085 1086 1087
void AccessorPair::AccessorPairVerify() {
  CHECK(IsAccessorPair());
  VerifyPointer(getter());
  VerifyPointer(setter());
}


1088 1089
void AccessCheckInfo::AccessCheckInfoVerify() {
  CHECK(IsAccessCheckInfo());
1090
  VerifyPointer(callback());
1091 1092
  VerifyPointer(named_interceptor());
  VerifyPointer(indexed_interceptor());
1093 1094 1095
  VerifyPointer(data());
}

1096

1097 1098 1099 1100 1101 1102 1103 1104
void InterceptorInfo::InterceptorInfoVerify() {
  CHECK(IsInterceptorInfo());
  VerifyPointer(getter());
  VerifyPointer(setter());
  VerifyPointer(query());
  VerifyPointer(deleter());
  VerifyPointer(enumerator());
  VerifyPointer(data());
1105
  VerifySmiField(kFlagsOffset);
1106
}
1107

1108 1109 1110 1111 1112 1113 1114

void CallHandlerInfo::CallHandlerInfoVerify() {
  CHECK(IsCallHandlerInfo());
  VerifyPointer(callback());
  VerifyPointer(data());
}

1115

1116 1117 1118
void TemplateInfo::TemplateInfoVerify() {
  VerifyPointer(tag());
  VerifyPointer(property_list());
1119
  VerifyPointer(property_accessors());
1120 1121
}

1122

1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
  CHECK(IsFunctionTemplateInfo());
  TemplateInfoVerify();
  VerifyPointer(serial_number());
  VerifyPointer(call_code());
  VerifyPointer(prototype_template());
  VerifyPointer(parent_template());
  VerifyPointer(named_property_handler());
  VerifyPointer(indexed_property_handler());
  VerifyPointer(instance_template());
  VerifyPointer(signature());
  VerifyPointer(access_check_info());
1135
  VerifyPointer(cached_property_name());
1136 1137 1138 1139 1140 1141 1142
}


void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
  CHECK(IsObjectTemplateInfo());
  TemplateInfoVerify();
  VerifyPointer(constructor());
1143
  VerifyPointer(data());
1144 1145
}

1146

1147 1148 1149 1150 1151
void AllocationSite::AllocationSiteVerify() {
  CHECK(IsAllocationSite());
}


1152 1153
void AllocationMemento::AllocationMementoVerify() {
  CHECK(IsAllocationMemento());
1154 1155
  VerifyHeapPointer(allocation_site());
  CHECK(!IsValid() || GetAllocationSite()->IsAllocationSite());
1156 1157 1158
}


1159 1160 1161 1162
void Script::ScriptVerify() {
  CHECK(IsScript());
  VerifyPointer(source());
  VerifyPointer(name());
1163
  VerifyPointer(wrapper());
1164
  VerifyPointer(line_ends());
1165 1166 1167
}


1168
void NormalizedMapCache::NormalizedMapCacheVerify() {
1169
  FixedArray::cast(this)->FixedArrayVerify();
1170
  if (FLAG_enable_slow_asserts) {
1171
    Isolate* isolate = GetIsolate();
1172
    for (int i = 0; i < length(); i++) {
1173
      Object* e = FixedArray::get(i);
1174
      if (e->IsMap()) {
1175
        Map::cast(e)->DictionaryMapVerify();
1176
      } else {
1177
        CHECK(e->IsUndefined(isolate));
1178 1179 1180 1181 1182 1183
      }
    }
  }
}


1184 1185 1186
void DebugInfo::DebugInfoVerify() {
  CHECK(IsDebugInfo());
  VerifyPointer(shared());
1187
  VerifyPointer(debug_bytecode_array());
1188 1189 1190 1191 1192 1193 1194 1195
  VerifyPointer(break_points());
}


void BreakPointInfo::BreakPointInfoVerify() {
  CHECK(IsBreakPointInfo());
  VerifyPointer(break_point_objects());
}
1196
#endif  // VERIFY_HEAP
1197

1198
#ifdef DEBUG
1199 1200 1201 1202 1203 1204 1205 1206

void JSObject::IncrementSpillStatistics(SpillInformation* info) {
  info->number_of_objects_++;
  // Named properties
  if (HasFastProperties()) {
    info->number_of_objects_with_fast_properties_++;
    info->number_of_fast_used_fields_   += map()->NextFreePropertyIndex();
    info->number_of_fast_unused_fields_ += map()->unused_property_fields();
1207
  } else if (IsJSGlobalObject()) {
1208 1209 1210 1211
    GlobalDictionary* dict = global_dictionary();
    info->number_of_slow_used_properties_ += dict->NumberOfElements();
    info->number_of_slow_unused_properties_ +=
        dict->Capacity() - dict->NumberOfElements();
1212
  } else {
1213
    NameDictionary* dict = property_dictionary();
1214 1215 1216 1217 1218
    info->number_of_slow_used_properties_ += dict->NumberOfElements();
    info->number_of_slow_unused_properties_ +=
        dict->Capacity() - dict->NumberOfElements();
  }
  // Indexed properties
1219
  switch (GetElementsKind()) {
1220 1221 1222 1223 1224
    case FAST_HOLEY_SMI_ELEMENTS:
    case FAST_SMI_ELEMENTS:
    case FAST_HOLEY_DOUBLE_ELEMENTS:
    case FAST_DOUBLE_ELEMENTS:
    case FAST_HOLEY_ELEMENTS:
1225 1226
    case FAST_ELEMENTS:
    case FAST_STRING_WRAPPER_ELEMENTS: {
1227 1228 1229 1230
      info->number_of_objects_with_fast_elements_++;
      int holes = 0;
      FixedArray* e = FixedArray::cast(elements());
      int len = e->length();
1231
      Isolate* isolate = GetIsolate();
1232
      for (int i = 0; i < len; i++) {
1233
        if (e->get(i)->IsTheHole(isolate)) holes++;
1234 1235 1236 1237
      }
      info->number_of_fast_used_elements_   += len - holes;
      info->number_of_fast_unused_elements_ += holes;
      break;
1238
    }
1239 1240 1241 1242 1243 1244 1245

#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
    case TYPE##_ELEMENTS:

    TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
    { info->number_of_objects_with_fast_elements_++;
1246
      FixedArrayBase* e = FixedArrayBase::cast(elements());
1247 1248 1249
      info->number_of_fast_used_elements_ += e->length();
      break;
    }
1250 1251
    case DICTIONARY_ELEMENTS:
    case SLOW_STRING_WRAPPER_ELEMENTS: {
1252
      SeededNumberDictionary* dict = element_dictionary();
1253 1254 1255 1256 1257
      info->number_of_slow_used_elements_ += dict->NumberOfElements();
      info->number_of_slow_unused_elements_ +=
          dict->Capacity() - dict->NumberOfElements();
      break;
    }
1258 1259
    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
1260
    case NO_ELEMENTS:
1261
      break;
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279
  }
}


void JSObject::SpillInformation::Clear() {
  number_of_objects_ = 0;
  number_of_objects_with_fast_properties_ = 0;
  number_of_objects_with_fast_elements_ = 0;
  number_of_fast_used_fields_ = 0;
  number_of_fast_unused_fields_ = 0;
  number_of_slow_used_properties_ = 0;
  number_of_slow_unused_properties_ = 0;
  number_of_fast_used_elements_ = 0;
  number_of_fast_unused_elements_ = 0;
  number_of_slow_used_elements_ = 0;
  number_of_slow_unused_elements_ = 0;
}

1280

1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
void JSObject::SpillInformation::Print() {
  PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);

  PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
         number_of_objects_with_fast_properties_,
         number_of_fast_used_fields_, number_of_fast_unused_fields_);

  PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
         number_of_objects_ - number_of_objects_with_fast_properties_,
         number_of_slow_used_properties_, number_of_slow_unused_properties_);

  PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
         number_of_objects_with_fast_elements_,
         number_of_fast_used_elements_, number_of_fast_unused_elements_);

  PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
         number_of_objects_ - number_of_objects_with_fast_elements_,
         number_of_slow_used_elements_, number_of_slow_unused_elements_);

  PrintF("\n");
}


1304 1305
bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) {
  if (valid_entries == -1) valid_entries = number_of_descriptors();
1306
  Name* current_key = NULL;
1307
  uint32_t current = 0;
1308
  for (int i = 0; i < number_of_descriptors(); i++) {
1309
    Name* key = GetSortedKey(i);
1310
    if (key == current_key) {
1311
      Print();
1312 1313 1314
      return false;
    }
    current_key = key;
1315
    uint32_t hash = GetSortedKey(i)->Hash();
1316
    if (hash < current) {
1317
      Print();
1318 1319 1320 1321 1322 1323 1324 1325
      return false;
    }
    current = hash;
  }
  return true;
}


1326
bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
1327
  DCHECK(valid_entries == -1);
1328
  Name* prev_key = NULL;
1329
  PropertyKind prev_kind = kData;
1330 1331
  PropertyAttributes prev_attributes = NONE;
  uint32_t prev_hash = 0;
1332
  for (int i = 0; i < number_of_transitions(); i++) {
1333
    Name* key = GetSortedKey(i);
1334
    uint32_t hash = key->Hash();
1335
    PropertyKind kind = kData;
1336 1337 1338 1339
    PropertyAttributes attributes = NONE;
    if (!IsSpecialTransition(key)) {
      Map* target = GetTarget(i);
      PropertyDetails details = GetTargetDetails(key, target);
1340
      kind = details.kind();
1341 1342 1343 1344
      attributes = details.attributes();
    } else {
      // Duplicate entries are not allowed for non-property transitions.
      CHECK_NE(prev_key, key);
1345
    }
1346

1347 1348
    int cmp = CompareKeys(prev_key, prev_hash, prev_kind, prev_attributes, key,
                          hash, kind, attributes);
1349 1350
    if (cmp >= 0) {
      Print();
1351 1352
      return false;
    }
1353 1354 1355
    prev_key = key;
    prev_hash = hash;
    prev_attributes = attributes;
1356
    prev_kind = kind;
1357 1358 1359 1360 1361
  }
  return true;
}


1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
// static
bool TransitionArray::IsSortedNoDuplicates(Map* map) {
  Object* raw_transitions = map->raw_transitions();
  if (IsFullTransitionArray(raw_transitions)) {
    return TransitionArray::cast(raw_transitions)->IsSortedNoDuplicates();
  }
  // Simple and non-existent transitions are always sorted.
  return true;
}


1373 1374 1375 1376 1377
static bool CheckOneBackPointer(Map* current_map, Object* target) {
  return !target->IsMap() || Map::cast(target)->GetBackPointer() == current_map;
}


1378 1379 1380 1381 1382 1383
// static
bool TransitionArray::IsConsistentWithBackPointers(Map* map) {
  Object* transitions = map->raw_transitions();
  for (int i = 0; i < TransitionArray::NumberOfTransitions(transitions); ++i) {
    Map* target = TransitionArray::GetTarget(transitions, i);
    if (!CheckOneBackPointer(map, target)) return false;
1384 1385 1386 1387 1388
  }
  return true;
}


1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
// Estimates if there is a path from the object to a context.
// This function is not precise, and can return false even if
// there is a path to a context.
bool CanLeak(Object* obj, Heap* heap, bool skip_weak_cell) {
  if (!obj->IsHeapObject()) return false;
  if (obj->IsWeakCell()) {
    if (skip_weak_cell) return false;
    return CanLeak(WeakCell::cast(obj)->value(), heap, skip_weak_cell);
  }
  if (obj->IsCell()) {
    return CanLeak(Cell::cast(obj)->value(), heap, skip_weak_cell);
  }
  if (obj->IsPropertyCell()) {
    return CanLeak(PropertyCell::cast(obj)->value(), heap, skip_weak_cell);
  }
  if (obj->IsContext()) return true;
  if (obj->IsMap()) {
    Map* map = Map::cast(obj);
    for (int i = 0; i < Heap::kStrongRootListLength; i++) {
1408 1409
      Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i);
      if (map == heap->root(root_index)) return false;
1410 1411 1412 1413 1414 1415 1416 1417 1418
    }
    return true;
  }
  return CanLeak(HeapObject::cast(obj)->map(), heap, skip_weak_cell);
}


void Code::VerifyEmbeddedObjects(VerifyMode mode) {
  if (kind() == OPTIMIZED_FUNCTION) return;
1419
  Heap* heap = GetIsolate()->heap();
1420 1421 1422
  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
             RelocInfo::ModeMask(RelocInfo::CELL);
  bool skip_weak_cell = (mode == kNoContextSpecificPointers) ? false : true;
1423
  for (RelocIterator it(this, mask); !it.done(); it.next()) {
ulan's avatar
ulan committed
1424 1425 1426 1427
    Object* target = it.rinfo()->rmode() == RelocInfo::CELL
                         ? it.rinfo()->target_cell()
                         : it.rinfo()->target_object();
    CHECK(!CanLeak(target, heap, skip_weak_cell));
1428 1429 1430 1431
  }
}


1432 1433 1434 1435 1436
// Verify that the debugger can redirect old code to the new code.
void Code::VerifyRecompiledCode(Code* old_code, Code* new_code) {
  if (old_code->kind() != FUNCTION) return;
  if (new_code->kind() != FUNCTION) return;
  Isolate* isolate = old_code->GetIsolate();
1437 1438 1439 1440
  // Do not verify during bootstrapping. We may replace code using %SetCode.
  if (isolate->bootstrapper()->IsActive()) return;

  static const int mask = RelocInfo::kCodeTargetMask;
1441 1442 1443 1444 1445 1446 1447
  RelocIterator old_it(old_code, mask);
  RelocIterator new_it(new_code, mask);
  Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck);

  while (!old_it.done()) {
    RelocInfo* rinfo = old_it.rinfo();
    Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1448
    CHECK(!target->is_handler() && !target->is_inline_cache_stub());
1449 1450 1451 1452 1453 1454 1455
    if (target == stack_check) break;
    old_it.next();
  }

  while (!new_it.done()) {
    RelocInfo* rinfo = new_it.rinfo();
    Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1456
    CHECK(!target->is_handler() && !target->is_inline_cache_stub());
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
    if (target == stack_check) break;
    new_it.next();
  }

  // Either both are done because there is no stack check.
  // Or we are past the prologue for both.
  CHECK_EQ(new_it.done(), old_it.done());

  // After the prologue, each call in the old code has a corresponding call
  // in the new code.
  while (!old_it.done() && !new_it.done()) {
    Code* old_target =
        Code::GetCodeFromTargetAddress(old_it.rinfo()->target_address());
    Code* new_target =
        Code::GetCodeFromTargetAddress(new_it.rinfo()->target_address());
    CHECK_EQ(old_target->kind(), new_target->kind());
1473 1474 1475
    // Check call target for equality unless it's an IC or an interrupt check.
    // In both cases they may be patched to be something else.
    if (!old_target->is_handler() && !old_target->is_inline_cache_stub() &&
1476
        new_target != isolate->builtins()->builtin(Builtins::kInterruptCheck)) {
1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487
      CHECK_EQ(old_target, new_target);
    }
    old_it.next();
    new_it.next();
  }

  // Both are done at the same time.
  CHECK_EQ(new_it.done(), old_it.done());
}


1488 1489
#endif  // DEBUG

1490 1491
}  // namespace internal
}  // namespace v8