| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
| 8 #include "src/disasm.h" | 8 #include "src/disasm.h" |
| 9 #include "src/disassembler.h" | 9 #include "src/disassembler.h" |
| 10 #include "src/field-type.h" | 10 #include "src/field-type.h" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 #undef VERIFY_TYPED_ARRAY | 93 #undef VERIFY_TYPED_ARRAY |
| 94 | 94 |
| 95 case CODE_TYPE: | 95 case CODE_TYPE: |
| 96 Code::cast(this)->CodeVerify(); | 96 Code::cast(this)->CodeVerify(); |
| 97 break; | 97 break; |
| 98 case ODDBALL_TYPE: | 98 case ODDBALL_TYPE: |
| 99 Oddball::cast(this)->OddballVerify(); | 99 Oddball::cast(this)->OddballVerify(); |
| 100 break; | 100 break; |
| 101 case JS_OBJECT_TYPE: | 101 case JS_OBJECT_TYPE: |
| 102 case JS_ERROR_TYPE: | 102 case JS_ERROR_TYPE: |
| 103 case JS_ARGUMENTS_TYPE: |
| 103 case JS_API_OBJECT_TYPE: | 104 case JS_API_OBJECT_TYPE: |
| 104 case JS_SPECIAL_API_OBJECT_TYPE: | 105 case JS_SPECIAL_API_OBJECT_TYPE: |
| 105 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 106 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 106 case JS_PROMISE_TYPE: | 107 case JS_PROMISE_TYPE: |
| 107 JSObject::cast(this)->JSObjectVerify(); | 108 JSObject::cast(this)->JSObjectVerify(); |
| 108 break; | 109 break; |
| 109 case JS_ARGUMENTS_TYPE: | |
| 110 JSArgumentsObject::cast(this)->JSArgumentsObjectVerify(); | |
| 111 break; | |
| 112 case JS_GENERATOR_OBJECT_TYPE: | 110 case JS_GENERATOR_OBJECT_TYPE: |
| 113 JSGeneratorObject::cast(this)->JSGeneratorObjectVerify(); | 111 JSGeneratorObject::cast(this)->JSGeneratorObjectVerify(); |
| 114 break; | 112 break; |
| 115 case JS_VALUE_TYPE: | 113 case JS_VALUE_TYPE: |
| 116 JSValue::cast(this)->JSValueVerify(); | 114 JSValue::cast(this)->JSValueVerify(); |
| 117 break; | 115 break; |
| 118 case JS_DATE_TYPE: | 116 case JS_DATE_TYPE: |
| 119 JSDate::cast(this)->JSDateVerify(); | 117 JSDate::cast(this)->JSDateVerify(); |
| 120 break; | 118 break; |
| 121 case JS_BOUND_FUNCTION_TYPE: | 119 case JS_BOUND_FUNCTION_TYPE: |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 } | 239 } |
| 242 | 240 |
| 243 | 241 |
| 244 void FreeSpace::FreeSpaceVerify() { | 242 void FreeSpace::FreeSpaceVerify() { |
| 245 CHECK(IsFreeSpace()); | 243 CHECK(IsFreeSpace()); |
| 246 } | 244 } |
| 247 | 245 |
| 248 | 246 |
| 249 template <class Traits> | 247 template <class Traits> |
| 250 void FixedTypedArray<Traits>::FixedTypedArrayVerify() { | 248 void FixedTypedArray<Traits>::FixedTypedArrayVerify() { |
| 251 CHECK(IsHeapObject()); | 249 CHECK(IsHeapObject() && |
| 252 CHECK(HeapObject::cast(this)->map()->instance_type() == | 250 HeapObject::cast(this)->map()->instance_type() == |
| 253 Traits::kInstanceType); | 251 Traits::kInstanceType); |
| 254 if (base_pointer() == this) { | 252 if (base_pointer() == this) { |
| 255 CHECK(external_pointer() == | 253 CHECK(external_pointer() == |
| 256 ExternalReference::fixed_typed_array_base_data_offset().address()); | 254 ExternalReference::fixed_typed_array_base_data_offset().address()); |
| 257 } else { | 255 } else { |
| 258 CHECK(base_pointer() == nullptr); | 256 CHECK(base_pointer() == nullptr); |
| 259 } | 257 } |
| 260 } | 258 } |
| 261 | 259 |
| 262 | 260 |
| 263 bool JSObject::ElementsAreSafeToExamine() { | 261 bool JSObject::ElementsAreSafeToExamine() { |
| 264 // If a GC was caused while constructing this object, the elements | 262 // If a GC was caused while constructing this object, the elements |
| 265 // pointer may point to a one pointer filler map. | 263 // pointer may point to a one pointer filler map. |
| 266 return reinterpret_cast<Map*>(elements()) != | 264 return reinterpret_cast<Map*>(elements()) != |
| 267 GetHeap()->one_pointer_filler_map(); | 265 GetHeap()->one_pointer_filler_map(); |
| 268 } | 266 } |
| 269 | 267 |
| 270 namespace { | |
| 271 | 268 |
| 272 void VerifyFastProperties(JSReceiver* receiver) { | 269 void JSObject::JSObjectVerify() { |
| 273 // TODO(cbruni): JSProxy support for slow properties | 270 VerifyHeapPointer(properties()); |
| 274 if (!receiver->IsJSObject()) return; | 271 VerifyHeapPointer(elements()); |
| 275 Isolate* isolate = receiver->GetIsolate(); | 272 |
| 276 Map* map = receiver->map(); | 273 if (HasSloppyArgumentsElements()) { |
| 277 CHECK(!map->is_dictionary_map()); | 274 CHECK(this->elements()->IsFixedArray()); |
| 278 JSObject* obj = JSObject::cast(receiver); | 275 CHECK_GE(this->elements()->length(), 2); |
| 279 int actual_unused_property_fields = map->GetInObjectProperties() + | |
| 280 obj->properties()->length() - | |
| 281 map->NextFreePropertyIndex(); | |
| 282 if (map->unused_property_fields() != actual_unused_property_fields) { | |
| 283 // This could actually happen in the middle of StoreTransitionStub | |
| 284 // when the new extended backing store is already set into the object and | |
| 285 // the allocation of the MutableHeapNumber triggers GC (in this case map | |
| 286 // is not updated yet). | |
| 287 CHECK_EQ(map->unused_property_fields(), | |
| 288 actual_unused_property_fields - JSObject::kFieldsAdded); | |
| 289 } | 276 } |
| 290 DescriptorArray* descriptors = map->instance_descriptors(); | 277 |
| 291 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | 278 if (HasFastProperties()) { |
| 292 if (descriptors->GetDetails(i).type() != DATA) continue; | 279 int actual_unused_property_fields = map()->GetInObjectProperties() + |
| 293 Representation r = descriptors->GetDetails(i).representation(); | 280 properties()->length() - |
| 294 FieldIndex index = FieldIndex::ForDescriptor(map, i); | 281 map()->NextFreePropertyIndex(); |
| 295 if (obj->IsUnboxedDoubleField(index)) { | 282 if (map()->unused_property_fields() != actual_unused_property_fields) { |
| 296 DCHECK(r.IsDouble()); | 283 // This could actually happen in the middle of StoreTransitionStub |
| 297 continue; | 284 // when the new extended backing store is already set into the object and |
| 285 // the allocation of the MutableHeapNumber triggers GC (in this case map |
| 286 // is not updated yet). |
| 287 CHECK_EQ(map()->unused_property_fields(), |
| 288 actual_unused_property_fields - JSObject::kFieldsAdded); |
| 298 } | 289 } |
| 299 Object* value = obj->RawFastPropertyAt(index); | 290 DescriptorArray* descriptors = map()->instance_descriptors(); |
| 300 if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber()); | 291 Isolate* isolate = GetIsolate(); |
| 301 if (value->IsUninitialized(isolate)) continue; | 292 for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) { |
| 302 if (r.IsSmi()) DCHECK(value->IsSmi()); | 293 if (descriptors->GetDetails(i).type() == DATA) { |
| 303 if (r.IsHeapObject()) DCHECK(value->IsHeapObject()); | 294 Representation r = descriptors->GetDetails(i).representation(); |
| 304 FieldType* field_type = descriptors->GetFieldType(i); | 295 FieldIndex index = FieldIndex::ForDescriptor(map(), i); |
| 305 bool type_is_none = field_type->IsNone(); | 296 if (IsUnboxedDoubleField(index)) { |
| 306 bool type_is_any = field_type->IsAny(); | 297 DCHECK(r.IsDouble()); |
| 307 if (r.IsNone()) { | 298 continue; |
| 308 CHECK(type_is_none); | 299 } |
| 309 } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) { | 300 Object* value = RawFastPropertyAt(index); |
| 310 // If allocation folding is off then GC could happen during inner | 301 if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber()); |
| 311 // object literal creation and we will end up having and undefined | 302 if (value->IsUninitialized(isolate)) continue; |
| 312 // value that does not match the field type. | 303 if (r.IsSmi()) DCHECK(value->IsSmi()); |
| 313 CHECK(!field_type->NowStable() || field_type->NowContains(value) || | 304 if (r.IsHeapObject()) DCHECK(value->IsHeapObject()); |
| 314 (!FLAG_use_allocation_folding && value->IsUndefined(isolate))); | 305 FieldType* field_type = descriptors->GetFieldType(i); |
| 306 bool type_is_none = field_type->IsNone(); |
| 307 bool type_is_any = field_type->IsAny(); |
| 308 if (r.IsNone()) { |
| 309 CHECK(type_is_none); |
| 310 } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) { |
| 311 // If allocation folding is off then GC could happen during inner |
| 312 // object literal creation and we will end up having and undefined |
| 313 // value that does not match the field type. |
| 314 CHECK(!field_type->NowStable() || field_type->NowContains(value) || |
| 315 (!FLAG_use_allocation_folding && value->IsUndefined(isolate))); |
| 316 } |
| 317 } |
| 315 } | 318 } |
| 316 } | 319 } |
| 320 |
| 321 // If a GC was caused while constructing this object, the elements |
| 322 // pointer may point to a one pointer filler map. |
| 323 if (ElementsAreSafeToExamine()) { |
| 324 CHECK_EQ((map()->has_fast_smi_or_object_elements() || |
| 325 (elements() == GetHeap()->empty_fixed_array()) || |
| 326 HasFastStringWrapperElements()), |
| 327 (elements()->map() == GetHeap()->fixed_array_map() || |
| 328 elements()->map() == GetHeap()->fixed_cow_array_map())); |
| 329 CHECK(map()->has_fast_object_elements() == HasFastObjectElements()); |
| 330 } |
| 317 } | 331 } |
| 318 | 332 |
| 319 template <typename T> | |
| 320 void VerifyDictionary(T* dict) { | |
| 321 CHECK(dict->IsFixedArray()); | |
| 322 CHECK(dict->IsDictionary()); | |
| 323 int capacity = dict->Capacity(); | |
| 324 int nof = dict->NumberOfElements(); | |
| 325 int nod = dict->NumberOfDeletedElements(); | |
| 326 CHECK_LE(capacity, dict->length()); | |
| 327 CHECK_LE(nof, capacity); | |
| 328 CHECK_LE(0, nof + nod); | |
| 329 CHECK_LE(nof + nod, capacity); | |
| 330 } | |
| 331 | |
| 332 void VerifySlowProperties(JSReceiver* obj) { | |
| 333 Map* map = obj->map(); | |
| 334 CHECK(map->is_dictionary_map()); | |
| 335 CHECK_EQ(0, map->NumberOfOwnDescriptors()); | |
| 336 CHECK_EQ(0, map->unused_property_fields()); | |
| 337 CHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength()); | |
| 338 CHECK(obj->properties()->IsDictionary()); | |
| 339 // Kept in-object properties for sow-mode object need to be zapped: | |
| 340 int nof_in_object_properties = map->GetInObjectProperties(); | |
| 341 if (nof_in_object_properties > 0) { | |
| 342 JSObject* js_object = JSObject::cast(obj); | |
| 343 Smi* zap_value = Smi::FromInt(0); | |
| 344 for (int i = 0; i < nof_in_object_properties; i++) { | |
| 345 FieldIndex index = FieldIndex::ForLoadByFieldIndex(map, i); | |
| 346 Object* field = js_object->RawFastPropertyAt(index); | |
| 347 CHECK_EQ(field, zap_value); | |
| 348 } | |
| 349 } | |
| 350 if (obj->IsJSGlobalObject()) { | |
| 351 VerifyDictionary(JSObject::cast(obj)->global_dictionary()); | |
| 352 } else { | |
| 353 VerifyDictionary(obj->property_dictionary()); | |
| 354 } | |
| 355 } | |
| 356 | |
| 357 void VerifyProperties(JSReceiver* obj) { | |
| 358 obj->VerifyHeapPointer(obj->properties()); | |
| 359 if (obj->HasFastProperties()) { | |
| 360 VerifyFastProperties(obj); | |
| 361 } else { | |
| 362 VerifySlowProperties(obj); | |
| 363 } | |
| 364 } | |
| 365 | |
| 366 void VerifyElements(JSObject* obj) { | |
| 367 obj->VerifyHeapPointer(obj->elements()); | |
| 368 // If a GC was caused while constructing this object, the elements | |
| 369 // pointer may point to a one pointer filler map. | |
| 370 if (!obj->ElementsAreSafeToExamine()) return; | |
| 371 Map* map = obj->map(); | |
| 372 Heap* heap = obj->GetHeap(); | |
| 373 FixedArrayBase* elements = obj->elements(); | |
| 374 CHECK_EQ((map->has_fast_smi_or_object_elements() || | |
| 375 (elements == heap->empty_fixed_array()) || | |
| 376 obj->HasFastStringWrapperElements()), | |
| 377 (elements->map() == heap->fixed_array_map() || | |
| 378 elements->map() == heap->fixed_cow_array_map())); | |
| 379 CHECK_EQ(map->has_fast_object_elements(), obj->HasFastObjectElements()); | |
| 380 | |
| 381 ElementsKind kind = obj->GetElementsKind(); | |
| 382 if (IsFastSmiOrObjectElementsKind(kind)) { | |
| 383 CHECK(elements->map() == heap->fixed_array_map() || | |
| 384 elements->map() == heap->fixed_cow_array_map()); | |
| 385 } else if (IsFastDoubleElementsKind(kind)) { | |
| 386 CHECK(elements->IsFixedDoubleArray() || | |
| 387 elements == heap->empty_fixed_array()); | |
| 388 } else if (kind == DICTIONARY_ELEMENTS) { | |
| 389 CHECK(elements->IsSeededNumberDictionary()); | |
| 390 VerifyDictionary(SeededNumberDictionary::cast(elements)); | |
| 391 return; | |
| 392 } else { | |
| 393 CHECK(kind > DICTIONARY_ELEMENTS); | |
| 394 } | |
| 395 CHECK(!IsSloppyArgumentsElements(kind) || | |
| 396 (elements->IsFixedArray() && elements->length() >= 2)); | |
| 397 | |
| 398 if (IsFastPackedElementsKind(kind)) { | |
| 399 uint32_t length = elements->length(); | |
| 400 if (obj->IsJSArray()) { | |
| 401 Object* number = JSArray::cast(obj)->length(); | |
| 402 if (number->IsSmi()) { | |
| 403 length = Min(length, static_cast<uint32_t>(Smi::cast(number)->value())); | |
| 404 } | |
| 405 } | |
| 406 if (kind == FAST_DOUBLE_ELEMENTS) { | |
| 407 for (uint32_t i = 0; i < length; i++) { | |
| 408 CHECK(!FixedDoubleArray::cast(elements)->is_the_hole(i)); | |
| 409 } | |
| 410 } else { | |
| 411 for (uint32_t i = 0; i < length; i++) { | |
| 412 CHECK_NE(FixedArray::cast(elements)->get(i), heap->the_hole_value()); | |
| 413 } | |
| 414 } | |
| 415 } | |
| 416 } | |
| 417 | |
| 418 } // namespace | |
| 419 | |
| 420 void JSObject::JSObjectVerify() { | |
| 421 VerifyProperties(this); | |
| 422 VerifyElements(this); | |
| 423 } | |
| 424 | 333 |
| 425 void Map::MapVerify() { | 334 void Map::MapVerify() { |
| 426 Heap* heap = GetHeap(); | 335 Heap* heap = GetHeap(); |
| 427 CHECK(!heap->InNewSpace(this)); | 336 CHECK(!heap->InNewSpace(this)); |
| 428 CHECK_LE(FIRST_TYPE, instance_type()); | 337 CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE); |
| 429 CHECK_LE(instance_type(), LAST_TYPE); | |
| 430 CHECK(instance_size() == kVariableSizeSentinel || | 338 CHECK(instance_size() == kVariableSizeSentinel || |
| 431 (kPointerSize <= instance_size() && | 339 (kPointerSize <= instance_size() && |
| 432 instance_size() < heap->Capacity())); | 340 instance_size() < heap->Capacity())); |
| 433 CHECK(GetBackPointer()->IsUndefined(heap->isolate()) || | 341 CHECK(GetBackPointer()->IsUndefined(heap->isolate()) || |
| 434 !Map::cast(GetBackPointer())->is_stable()); | 342 !Map::cast(GetBackPointer())->is_stable()); |
| 435 VerifyHeapPointer(prototype()); | 343 VerifyHeapPointer(prototype()); |
| 436 VerifyHeapPointer(instance_descriptors()); | 344 VerifyHeapPointer(instance_descriptors()); |
| 437 SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates()); | 345 SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates()); |
| 438 SLOW_DCHECK(TransitionArray::IsSortedNoDuplicates(this)); | 346 SLOW_DCHECK(TransitionArray::IsSortedNoDuplicates(this)); |
| 439 SLOW_DCHECK(TransitionArray::IsConsistentWithBackPointers(this)); | 347 SLOW_DCHECK(TransitionArray::IsConsistentWithBackPointers(this)); |
| 440 // TODO(ishell): turn it back to SLOW_DCHECK. | 348 // TODO(ishell): turn it back to SLOW_DCHECK. |
| 441 CHECK(!FLAG_unbox_double_fields || | 349 CHECK(!FLAG_unbox_double_fields || |
| 442 layout_descriptor()->IsConsistentWithMap(this)); | 350 layout_descriptor()->IsConsistentWithMap(this)); |
| 443 } | 351 } |
| 444 | 352 |
| 445 | 353 |
| 446 void Map::DictionaryMapVerify() { | 354 void Map::DictionaryMapVerify() { |
| 447 MapVerify(); | 355 MapVerify(); |
| 448 CHECK(is_dictionary_map()); | 356 CHECK(is_dictionary_map()); |
| 449 CHECK(instance_descriptors()->IsEmpty()); | 357 CHECK(instance_descriptors()->IsEmpty()); |
| 450 CHECK_EQ(0, unused_property_fields()); | 358 CHECK_EQ(0, unused_property_fields()); |
| 451 CHECK_EQ(Heap::GetStaticVisitorIdForMap(this), visitor_id()); | 359 CHECK_EQ(Heap::GetStaticVisitorIdForMap(this), visitor_id()); |
| 452 CHECK_EQ(kInvalidEnumCacheSentinel, EnumLength()); | |
| 453 } | 360 } |
| 454 | 361 |
| 455 | 362 |
| 456 void Map::VerifyOmittedMapChecks() { | 363 void Map::VerifyOmittedMapChecks() { |
| 457 if (!FLAG_omit_map_checks_for_leaf_maps) return; | 364 if (!FLAG_omit_map_checks_for_leaf_maps) return; |
| 458 if (!is_stable() || | 365 if (!is_stable() || |
| 459 is_deprecated() || | 366 is_deprecated() || |
| 460 is_dictionary_map()) { | 367 is_dictionary_map()) { |
| 461 CHECK(dependent_code()->IsEmpty(DependentCode::kPrototypeCheckGroup)); | 368 CHECK(dependent_code()->IsEmpty(DependentCode::kPrototypeCheckGroup)); |
| 462 } | 369 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 | 419 |
| 513 void JSGeneratorObject::JSGeneratorObjectVerify() { | 420 void JSGeneratorObject::JSGeneratorObjectVerify() { |
| 514 // In an expression like "new g()", there can be a point where a generator | 421 // In an expression like "new g()", there can be a point where a generator |
| 515 // object is allocated but its fields are all undefined, as it hasn't yet been | 422 // object is allocated but its fields are all undefined, as it hasn't yet been |
| 516 // initialized by the generator. Hence these weak checks. | 423 // initialized by the generator. Hence these weak checks. |
| 517 VerifyObjectField(kFunctionOffset); | 424 VerifyObjectField(kFunctionOffset); |
| 518 VerifyObjectField(kContextOffset); | 425 VerifyObjectField(kContextOffset); |
| 519 VerifyObjectField(kReceiverOffset); | 426 VerifyObjectField(kReceiverOffset); |
| 520 VerifyObjectField(kOperandStackOffset); | 427 VerifyObjectField(kOperandStackOffset); |
| 521 VerifyObjectField(kContinuationOffset); | 428 VerifyObjectField(kContinuationOffset); |
| 522 JSObjectVerify(); | |
| 523 } | |
| 524 | |
| 525 namespace { | |
| 526 | |
| 527 void VerifyArgumentsParameterMap(FixedArray* elements) { | |
| 528 Isolate* isolate = elements->GetIsolate(); | |
| 529 CHECK(elements->IsFixedArray()); | |
| 530 CHECK_GE(elements->length(), 2); | |
| 531 HeapObject* context = HeapObject::cast(elements->get(0)); | |
| 532 HeapObject* arguments = HeapObject::cast(elements->get(1)); | |
| 533 // TODO(cbruni): fix arguments creation to be atomic. | |
| 534 CHECK_IMPLIES(context->IsUndefined(isolate), arguments->IsUndefined(isolate)); | |
| 535 CHECK(context->IsUndefined(isolate) || context->IsContext()); | |
| 536 CHECK(arguments->IsUndefined(isolate) || arguments->IsFixedArray()); | |
| 537 } | |
| 538 | |
| 539 } // namespace | |
| 540 | |
| 541 void JSArgumentsObject::JSArgumentsObjectVerify() { | |
| 542 VerifyObjectField(kLengthOffset); | |
| 543 JSObjectVerify(); | |
| 544 Isolate* isolate = GetIsolate(); | |
| 545 | |
| 546 if (isolate->bootstrapper()->IsActive()) return; | |
| 547 Context* context = isolate->context(); | |
| 548 Object* constructor = map()->GetConstructor(); | |
| 549 if (constructor->IsJSFunction()) { | |
| 550 context = JSFunction::cast(constructor)->context(); | |
| 551 } | |
| 552 // TODO(cbruni): replace with NULL check once all hydrogren stubs manage to | |
| 553 // set up the contexts properly. | |
| 554 if (isolate->context()->IsSmi()) return; | |
| 555 Context* native_context = context->native_context(); | |
| 556 if (map() == native_context->sloppy_arguments_map()) { | |
| 557 // Sloppy arguments without aliased arguments has a normal elements backing | |
| 558 // store which is already verified by JSObjectVerify() above. | |
| 559 } else if (map() == native_context->fast_aliased_arguments_map()) { | |
| 560 CHECK(HasFastArgumentsElements()); | |
| 561 FixedArray* elements = FixedArray::cast(this->elements()); | |
| 562 VerifyArgumentsParameterMap(FixedArray::cast(elements)); | |
| 563 CHECK_EQ(elements->map(), isolate->heap()->sloppy_arguments_elements_map()); | |
| 564 } else if (map() == native_context->slow_aliased_arguments_map()) { | |
| 565 CHECK(HasSlowArgumentsElements()); | |
| 566 FixedArray* elements = FixedArray::cast(this->elements()); | |
| 567 VerifyArgumentsParameterMap(elements); | |
| 568 VerifyDictionary(SeededNumberDictionary::cast(elements->get(1))); | |
| 569 CHECK_EQ(elements->map(), isolate->heap()->sloppy_arguments_elements_map()); | |
| 570 } else if (map() == native_context->strict_arguments_map()) { | |
| 571 CHECK(HasFastElements()); | |
| 572 } else { | |
| 573 // TODO(cbruni): follow up on normalized argument maps. | |
| 574 } | |
| 575 } | 429 } |
| 576 | 430 |
| 577 | 431 |
| 578 void JSValue::JSValueVerify() { | 432 void JSValue::JSValueVerify() { |
| 579 Object* v = value(); | 433 Object* v = value(); |
| 580 if (v->IsHeapObject()) { | 434 if (v->IsHeapObject()) { |
| 581 VerifyHeapPointer(v); | 435 VerifyHeapPointer(v); |
| 582 } | 436 } |
| 583 JSObjectVerify(); | |
| 584 } | 437 } |
| 585 | 438 |
| 586 | 439 |
| 587 void JSDate::JSDateVerify() { | 440 void JSDate::JSDateVerify() { |
| 588 JSObjectVerify(); | |
| 589 if (value()->IsHeapObject()) { | 441 if (value()->IsHeapObject()) { |
| 590 VerifyHeapPointer(value()); | 442 VerifyHeapPointer(value()); |
| 591 } | 443 } |
| 592 Isolate* isolate = GetIsolate(); | 444 Isolate* isolate = GetIsolate(); |
| 593 CHECK(value()->IsUndefined(isolate) || value()->IsSmi() || | 445 CHECK(value()->IsUndefined(isolate) || value()->IsSmi() || |
| 594 value()->IsHeapNumber()); | 446 value()->IsHeapNumber()); |
| 595 CHECK(year()->IsUndefined(isolate) || year()->IsSmi() || year()->IsNaN()); | 447 CHECK(year()->IsUndefined(isolate) || year()->IsSmi() || year()->IsNaN()); |
| 596 CHECK(month()->IsUndefined(isolate) || month()->IsSmi() || month()->IsNaN()); | 448 CHECK(month()->IsUndefined(isolate) || month()->IsSmi() || month()->IsNaN()); |
| 597 CHECK(day()->IsUndefined(isolate) || day()->IsSmi() || day()->IsNaN()); | 449 CHECK(day()->IsUndefined(isolate) || day()->IsSmi() || day()->IsNaN()); |
| 598 CHECK(weekday()->IsUndefined(isolate) || weekday()->IsSmi() || | 450 CHECK(weekday()->IsUndefined(isolate) || weekday()->IsSmi() || |
| (...skipping 29 matching lines...) Expand all Loading... |
| 628 CHECK(0 <= weekday && weekday <= 6); | 480 CHECK(0 <= weekday && weekday <= 6); |
| 629 } | 481 } |
| 630 if (cache_stamp()->IsSmi()) { | 482 if (cache_stamp()->IsSmi()) { |
| 631 CHECK(Smi::cast(cache_stamp())->value() <= | 483 CHECK(Smi::cast(cache_stamp())->value() <= |
| 632 Smi::cast(isolate->date_cache()->stamp())->value()); | 484 Smi::cast(isolate->date_cache()->stamp())->value()); |
| 633 } | 485 } |
| 634 } | 486 } |
| 635 | 487 |
| 636 | 488 |
| 637 void JSMessageObject::JSMessageObjectVerify() { | 489 void JSMessageObject::JSMessageObjectVerify() { |
| 638 JSObjectVerify(); | |
| 639 CHECK(IsJSMessageObject()); | 490 CHECK(IsJSMessageObject()); |
| 640 VerifyObjectField(kStartPositionOffset); | 491 VerifyObjectField(kStartPositionOffset); |
| 641 VerifyObjectField(kEndPositionOffset); | 492 VerifyObjectField(kEndPositionOffset); |
| 642 VerifyObjectField(kArgumentsOffset); | 493 VerifyObjectField(kArgumentsOffset); |
| 643 VerifyObjectField(kScriptOffset); | 494 VerifyObjectField(kScriptOffset); |
| 644 VerifyObjectField(kStackFramesOffset); | 495 VerifyObjectField(kStackFramesOffset); |
| 645 } | 496 } |
| 646 | 497 |
| 647 | 498 |
| 648 void String::StringVerify() { | 499 void String::StringVerify() { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 VerifyObjectField(kBoundTargetFunctionOffset); | 538 VerifyObjectField(kBoundTargetFunctionOffset); |
| 688 VerifyObjectField(kBoundArgumentsOffset); | 539 VerifyObjectField(kBoundArgumentsOffset); |
| 689 CHECK(bound_target_function()->IsCallable()); | 540 CHECK(bound_target_function()->IsCallable()); |
| 690 CHECK(IsCallable()); | 541 CHECK(IsCallable()); |
| 691 CHECK_EQ(IsConstructor(), bound_target_function()->IsConstructor()); | 542 CHECK_EQ(IsConstructor(), bound_target_function()->IsConstructor()); |
| 692 } | 543 } |
| 693 | 544 |
| 694 | 545 |
| 695 void JSFunction::JSFunctionVerify() { | 546 void JSFunction::JSFunctionVerify() { |
| 696 CHECK(IsJSFunction()); | 547 CHECK(IsJSFunction()); |
| 697 JSObjectVerify(); | |
| 698 VerifyObjectField(kPrototypeOrInitialMapOffset); | 548 VerifyObjectField(kPrototypeOrInitialMapOffset); |
| 699 VerifyObjectField(kNextFunctionLinkOffset); | 549 VerifyObjectField(kNextFunctionLinkOffset); |
| 700 CHECK(code()->IsCode()); | 550 CHECK(code()->IsCode()); |
| 701 CHECK(next_function_link() == NULL || | 551 CHECK(next_function_link() == NULL || |
| 702 next_function_link()->IsUndefined(GetIsolate()) || | 552 next_function_link()->IsUndefined(GetIsolate()) || |
| 703 next_function_link()->IsJSFunction()); | 553 next_function_link()->IsJSFunction()); |
| 704 CHECK(map()->is_callable()); | 554 CHECK(map()->is_callable()); |
| 705 } | 555 } |
| 706 | 556 |
| 707 | 557 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 734 } | 584 } |
| 735 | 585 |
| 736 | 586 |
| 737 void JSGlobalObject::JSGlobalObjectVerify() { | 587 void JSGlobalObject::JSGlobalObjectVerify() { |
| 738 CHECK(IsJSGlobalObject()); | 588 CHECK(IsJSGlobalObject()); |
| 739 // Do not check the dummy global object for the builtins. | 589 // Do not check the dummy global object for the builtins. |
| 740 if (GlobalDictionary::cast(properties())->NumberOfElements() == 0 && | 590 if (GlobalDictionary::cast(properties())->NumberOfElements() == 0 && |
| 741 elements()->length() == 0) { | 591 elements()->length() == 0) { |
| 742 return; | 592 return; |
| 743 } | 593 } |
| 744 CHECK(!HasFastProperties()); | |
| 745 JSObjectVerify(); | 594 JSObjectVerify(); |
| 746 } | 595 } |
| 747 | 596 |
| 748 | 597 |
| 749 void Oddball::OddballVerify() { | 598 void Oddball::OddballVerify() { |
| 750 CHECK(IsOddball()); | 599 CHECK(IsOddball()); |
| 751 Heap* heap = GetHeap(); | 600 Heap* heap = GetHeap(); |
| 752 VerifyHeapPointer(to_string()); | 601 VerifyHeapPointer(to_string()); |
| 753 Object* number = to_number(); | 602 Object* number = to_number(); |
| 754 if (number->IsHeapObject()) { | 603 if (number->IsHeapObject()) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { | 687 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { |
| 839 Object* obj = it.rinfo()->target_object(); | 688 Object* obj = it.rinfo()->target_object(); |
| 840 if (IsWeakObject(obj)) { | 689 if (IsWeakObject(obj)) { |
| 841 if (obj->IsMap()) { | 690 if (obj->IsMap()) { |
| 842 Map* map = Map::cast(obj); | 691 Map* map = Map::cast(obj); |
| 843 CHECK(map->dependent_code()->Contains(DependentCode::kWeakCodeGroup, | 692 CHECK(map->dependent_code()->Contains(DependentCode::kWeakCodeGroup, |
| 844 cell)); | 693 cell)); |
| 845 } else if (obj->IsJSObject()) { | 694 } else if (obj->IsJSObject()) { |
| 846 if (isolate->heap()->InNewSpace(obj)) { | 695 if (isolate->heap()->InNewSpace(obj)) { |
| 847 ArrayList* list = | 696 ArrayList* list = |
| 848 isolate->heap()->weak_new_space_object_to_code_list(); | 697 GetIsolate()->heap()->weak_new_space_object_to_code_list(); |
| 849 bool found = false; | 698 bool found = false; |
| 850 for (int i = 0; i < list->Length(); i += 2) { | 699 for (int i = 0; i < list->Length(); i += 2) { |
| 851 WeakCell* obj_cell = WeakCell::cast(list->Get(i)); | 700 WeakCell* obj_cell = WeakCell::cast(list->Get(i)); |
| 852 if (!obj_cell->cleared() && obj_cell->value() == obj && | 701 if (!obj_cell->cleared() && obj_cell->value() == obj && |
| 853 WeakCell::cast(list->Get(i + 1)) == cell) { | 702 WeakCell::cast(list->Get(i + 1)) == cell) { |
| 854 found = true; | 703 found = true; |
| 855 break; | 704 break; |
| 856 } | 705 } |
| 857 } | 706 } |
| 858 CHECK(found); | 707 CHECK(found); |
| 859 } else { | 708 } else { |
| 860 Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate); | 709 Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate); |
| 861 DependentCode* dep = | 710 DependentCode* dep = |
| 862 isolate->heap()->LookupWeakObjectToCodeDependency(key_obj); | 711 GetIsolate()->heap()->LookupWeakObjectToCodeDependency(key_obj); |
| 863 dep->Contains(DependentCode::kWeakCodeGroup, cell); | 712 dep->Contains(DependentCode::kWeakCodeGroup, cell); |
| 864 } | 713 } |
| 865 } | 714 } |
| 866 } | 715 } |
| 867 } | 716 } |
| 868 } | 717 } |
| 869 | 718 |
| 870 | 719 |
| 871 void JSArray::JSArrayVerify() { | 720 void JSArray::JSArrayVerify() { |
| 872 CHECK(IsJSArray()); | |
| 873 JSObjectVerify(); | 721 JSObjectVerify(); |
| 874 Isolate* isolate = GetIsolate(); | 722 Isolate* isolate = GetIsolate(); |
| 875 // Allow undefined for not fully initialized JSArrays | 723 CHECK(length()->IsNumber() || length()->IsUndefined(isolate)); |
| 876 if (length()->IsUndefined(isolate)) { | |
| 877 CHECK_EQ(FixedArray::cast(elements()), | |
| 878 isolate->heap()->empty_fixed_array()); | |
| 879 return; | |
| 880 } | |
| 881 CHECK(length()->IsNumber()); | |
| 882 // If a GC was caused while constructing this array, the elements | 724 // If a GC was caused while constructing this array, the elements |
| 883 // pointer may point to a one pointer filler map. | 725 // pointer may point to a one pointer filler map. |
| 884 if (ElementsAreSafeToExamine()) { | 726 if (ElementsAreSafeToExamine()) { |
| 885 CHECK(elements()->IsFixedArray() || elements()->IsFixedDoubleArray()); | 727 CHECK(elements()->IsUndefined(isolate) || elements()->IsFixedArray() || |
| 728 elements()->IsFixedDoubleArray()); |
| 886 } | 729 } |
| 887 } | 730 } |
| 888 | 731 |
| 732 |
| 889 void JSSet::JSSetVerify() { | 733 void JSSet::JSSetVerify() { |
| 890 CHECK(IsJSSet()); | 734 CHECK(IsJSSet()); |
| 891 JSObjectVerify(); | 735 JSObjectVerify(); |
| 892 VerifyHeapPointer(table()); | 736 VerifyHeapPointer(table()); |
| 893 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate())); | 737 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate())); |
| 894 // TODO(arv): Verify OrderedHashTable too. | 738 // TODO(arv): Verify OrderedHashTable too. |
| 895 } | 739 } |
| 896 | 740 |
| 897 | 741 |
| 898 void JSMap::JSMapVerify() { | 742 void JSMap::JSMapVerify() { |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 if (isolate->bootstrapper()->IsActive()) return; | 1289 if (isolate->bootstrapper()->IsActive()) return; |
| 1446 | 1290 |
| 1447 static const int mask = RelocInfo::kCodeTargetMask; | 1291 static const int mask = RelocInfo::kCodeTargetMask; |
| 1448 RelocIterator old_it(old_code, mask); | 1292 RelocIterator old_it(old_code, mask); |
| 1449 RelocIterator new_it(new_code, mask); | 1293 RelocIterator new_it(new_code, mask); |
| 1450 Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck); | 1294 Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck); |
| 1451 | 1295 |
| 1452 while (!old_it.done()) { | 1296 while (!old_it.done()) { |
| 1453 RelocInfo* rinfo = old_it.rinfo(); | 1297 RelocInfo* rinfo = old_it.rinfo(); |
| 1454 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 1298 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 1455 CHECK(!target->is_handler()); | 1299 CHECK(!target->is_handler() && !target->is_inline_cache_stub()); |
| 1456 CHECK(!target->is_inline_cache_stub()); | |
| 1457 if (target == stack_check) break; | 1300 if (target == stack_check) break; |
| 1458 old_it.next(); | 1301 old_it.next(); |
| 1459 } | 1302 } |
| 1460 | 1303 |
| 1461 while (!new_it.done()) { | 1304 while (!new_it.done()) { |
| 1462 RelocInfo* rinfo = new_it.rinfo(); | 1305 RelocInfo* rinfo = new_it.rinfo(); |
| 1463 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 1306 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 1464 CHECK(!target->is_handler()); | 1307 CHECK(!target->is_handler() && !target->is_inline_cache_stub()); |
| 1465 CHECK(!target->is_inline_cache_stub()); | |
| 1466 if (target == stack_check) break; | 1308 if (target == stack_check) break; |
| 1467 new_it.next(); | 1309 new_it.next(); |
| 1468 } | 1310 } |
| 1469 | 1311 |
| 1470 // Either both are done because there is no stack check. | 1312 // Either both are done because there is no stack check. |
| 1471 // Or we are past the prologue for both. | 1313 // Or we are past the prologue for both. |
| 1472 CHECK_EQ(new_it.done(), old_it.done()); | 1314 CHECK_EQ(new_it.done(), old_it.done()); |
| 1473 | 1315 |
| 1474 // After the prologue, each call in the old code has a corresponding call | 1316 // After the prologue, each call in the old code has a corresponding call |
| 1475 // in the new code. | 1317 // in the new code. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1491 | 1333 |
| 1492 // Both are done at the same time. | 1334 // Both are done at the same time. |
| 1493 CHECK_EQ(new_it.done(), old_it.done()); | 1335 CHECK_EQ(new_it.done(), old_it.done()); |
| 1494 } | 1336 } |
| 1495 | 1337 |
| 1496 | 1338 |
| 1497 #endif // DEBUG | 1339 #endif // DEBUG |
| 1498 | 1340 |
| 1499 } // namespace internal | 1341 } // namespace internal |
| 1500 } // namespace v8 | 1342 } // namespace v8 |
| OLD | NEW |