Chromium Code Reviews| 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: | |
| 104 case JS_API_OBJECT_TYPE: | 103 case JS_API_OBJECT_TYPE: |
| 105 case JS_SPECIAL_API_OBJECT_TYPE: | 104 case JS_SPECIAL_API_OBJECT_TYPE: |
| 106 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 105 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 107 case JS_PROMISE_TYPE: | 106 case JS_PROMISE_TYPE: |
| 108 JSObject::cast(this)->JSObjectVerify(); | 107 JSObject::cast(this)->JSObjectVerify(); |
| 109 break; | 108 break; |
| 109 case JS_ARGUMENTS_TYPE: | |
| 110 JSArgumentsObject::cast(this)->JSArgumentsObjectVerify(); | |
| 111 break; | |
| 110 case JS_GENERATOR_OBJECT_TYPE: | 112 case JS_GENERATOR_OBJECT_TYPE: |
| 111 JSGeneratorObject::cast(this)->JSGeneratorObjectVerify(); | 113 JSGeneratorObject::cast(this)->JSGeneratorObjectVerify(); |
| 112 break; | 114 break; |
| 113 case JS_VALUE_TYPE: | 115 case JS_VALUE_TYPE: |
| 114 JSValue::cast(this)->JSValueVerify(); | 116 JSValue::cast(this)->JSValueVerify(); |
| 115 break; | 117 break; |
| 116 case JS_DATE_TYPE: | 118 case JS_DATE_TYPE: |
| 117 JSDate::cast(this)->JSDateVerify(); | 119 JSDate::cast(this)->JSDateVerify(); |
| 118 break; | 120 break; |
| 119 case JS_BOUND_FUNCTION_TYPE: | 121 case JS_BOUND_FUNCTION_TYPE: |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 } | 241 } |
| 240 | 242 |
| 241 | 243 |
| 242 void FreeSpace::FreeSpaceVerify() { | 244 void FreeSpace::FreeSpaceVerify() { |
| 243 CHECK(IsFreeSpace()); | 245 CHECK(IsFreeSpace()); |
| 244 } | 246 } |
| 245 | 247 |
| 246 | 248 |
| 247 template <class Traits> | 249 template <class Traits> |
| 248 void FixedTypedArray<Traits>::FixedTypedArrayVerify() { | 250 void FixedTypedArray<Traits>::FixedTypedArrayVerify() { |
| 249 CHECK(IsHeapObject() && | 251 CHECK(IsHeapObject()); |
| 250 HeapObject::cast(this)->map()->instance_type() == | 252 CHECK(HeapObject::cast(this)->map()->instance_type() == |
| 251 Traits::kInstanceType); | 253 Traits::kInstanceType); |
| 252 if (base_pointer() == this) { | 254 if (base_pointer() == this) { |
| 253 CHECK(external_pointer() == | 255 CHECK(external_pointer() == |
| 254 ExternalReference::fixed_typed_array_base_data_offset().address()); | 256 ExternalReference::fixed_typed_array_base_data_offset().address()); |
| 255 } else { | 257 } else { |
| 256 CHECK(base_pointer() == nullptr); | 258 CHECK(base_pointer() == nullptr); |
| 257 } | 259 } |
| 258 } | 260 } |
| 259 | 261 |
| 260 | 262 |
| 261 bool JSObject::ElementsAreSafeToExamine() { | 263 bool JSObject::ElementsAreSafeToExamine() { |
| 262 // If a GC was caused while constructing this object, the elements | 264 // If a GC was caused while constructing this object, the elements |
| 263 // pointer may point to a one pointer filler map. | 265 // pointer may point to a one pointer filler map. |
| 264 return reinterpret_cast<Map*>(elements()) != | 266 return reinterpret_cast<Map*>(elements()) != |
| 265 GetHeap()->one_pointer_filler_map(); | 267 GetHeap()->one_pointer_filler_map(); |
| 266 } | 268 } |
| 267 | 269 |
| 270 namespace { | |
|
Igor Sheludko
2016/07/08 08:38:22
Add a blank line after this line.
Camillo Bruni
2016/07/11 11:46:38
done
| |
| 271 void VerifyFastProperties(JSReceiver* receiver) { | |
| 272 // TODO(cbruni): JSProxy support for slow properties | |
| 273 if (!receiver->IsJSObject()) return; | |
| 274 Isolate* isolate = receiver->GetIsolate(); | |
| 275 Map* map = receiver->map(); | |
| 276 JSObject* obj = JSObject::cast(receiver); | |
| 277 int actual_unused_property_fields = map->GetInObjectProperties() + | |
| 278 obj->properties()->length() - | |
| 279 map->NextFreePropertyIndex(); | |
| 280 if (map->unused_property_fields() != actual_unused_property_fields) { | |
| 281 // This could actually happen in the middle of StoreTransitionStub | |
| 282 // when the new extended backing store is already set into the object and | |
| 283 // the allocation of the MutableHeapNumber triggers GC (in this case map | |
| 284 // is not updated yet). | |
| 285 CHECK_EQ(map->unused_property_fields(), | |
| 286 actual_unused_property_fields - JSObject::kFieldsAdded); | |
| 287 } | |
| 288 DescriptorArray* descriptors = map->instance_descriptors(); | |
| 289 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | |
| 290 if (descriptors->GetDetails(i).type() != DATA) continue; | |
| 291 Representation r = descriptors->GetDetails(i).representation(); | |
| 292 FieldIndex index = FieldIndex::ForDescriptor(map, i); | |
| 293 if (obj->IsUnboxedDoubleField(index)) { | |
| 294 DCHECK(r.IsDouble()); | |
| 295 continue; | |
| 296 } | |
| 297 Object* value = obj->RawFastPropertyAt(index); | |
| 298 if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber()); | |
| 299 if (value->IsUninitialized(isolate)) continue; | |
| 300 if (r.IsSmi()) DCHECK(value->IsSmi()); | |
| 301 if (r.IsHeapObject()) DCHECK(value->IsHeapObject()); | |
| 302 FieldType* field_type = descriptors->GetFieldType(i); | |
| 303 bool type_is_none = field_type->IsNone(); | |
| 304 bool type_is_any = field_type->IsAny(); | |
| 305 if (r.IsNone()) { | |
| 306 CHECK(type_is_none); | |
| 307 } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) { | |
| 308 // If allocation folding is off then GC could happen during inner | |
| 309 // object literal creation and we will end up having and undefined | |
| 310 // value that does not match the field type. | |
| 311 CHECK(!field_type->NowStable() || field_type->NowContains(value) || | |
| 312 (!FLAG_use_allocation_folding && value->IsUndefined(isolate))); | |
| 313 } | |
| 314 } | |
| 315 } | |
| 268 | 316 |
| 269 void JSObject::JSObjectVerify() { | 317 void VerifySlowProperties(JSReceiver* obj) { |
| 270 VerifyHeapPointer(properties()); | 318 CHECK(obj->properties()->IsDictionary()); |
| 271 VerifyHeapPointer(elements()); | 319 } |
| 272 | 320 |
| 273 if (HasSloppyArgumentsElements()) { | 321 void VerifyProperties(JSReceiver* obj) { |
| 274 CHECK(this->elements()->IsFixedArray()); | 322 obj->VerifyHeapPointer(obj->properties()); |
| 275 CHECK_GE(this->elements()->length(), 2); | 323 if (obj->HasFastProperties()) { |
| 324 VerifyFastProperties(obj); | |
| 325 } else { | |
|
Igor Sheludko
2016/07/08 08:38:22
Instead of VerifySlowProperties:
} else if (obj->
Camillo Bruni
2016/07/11 11:46:39
Kept the separate method to do further checks but
| |
| 326 VerifySlowProperties(obj); | |
| 276 } | 327 } |
| 328 } | |
| 277 | 329 |
| 278 if (HasFastProperties()) { | 330 template <typename T> |
| 279 int actual_unused_property_fields = map()->GetInObjectProperties() + | 331 void VerifyDictionary(T* dict) { |
| 280 properties()->length() - | 332 CHECK(dict->IsFixedArray()); |
| 281 map()->NextFreePropertyIndex(); | 333 CHECK(dict->IsDictionary()); |
| 282 if (map()->unused_property_fields() != actual_unused_property_fields) { | 334 int capacity = dict->Capacity(); |
| 283 // This could actually happen in the middle of StoreTransitionStub | 335 int nof = dict->NumberOfElements(); |
| 284 // when the new extended backing store is already set into the object and | 336 int nod = dict->NumberOfDeletedElements(); |
| 285 // the allocation of the MutableHeapNumber triggers GC (in this case map | 337 CHECK_LE(capacity, dict->length()); |
| 286 // is not updated yet). | 338 CHECK_LE(nof, capacity); |
| 287 CHECK_EQ(map()->unused_property_fields(), | 339 CHECK_LE(0, nof + nod); |
| 288 actual_unused_property_fields - JSObject::kFieldsAdded); | 340 CHECK_LE(nof + nod, capacity); |
| 341 } | |
| 342 | |
| 343 void VerifyElements(JSObject* obj) { | |
| 344 obj->VerifyHeapPointer(obj->elements()); | |
| 345 // If a GC was caused while constructing this object, the elements | |
| 346 // pointer may point to a one pointer filler map. | |
| 347 if (!obj->ElementsAreSafeToExamine()) return; | |
| 348 Map* map = obj->map(); | |
| 349 Heap* heap = obj->GetHeap(); | |
| 350 FixedArrayBase* elements = obj->elements(); | |
| 351 CHECK_EQ((map->has_fast_smi_or_object_elements() || | |
| 352 (elements == heap->empty_fixed_array()) || | |
| 353 obj->HasFastStringWrapperElements()), | |
| 354 (elements->map() == heap->fixed_array_map() || | |
| 355 elements->map() == heap->fixed_cow_array_map())); | |
| 356 CHECK(map->has_fast_object_elements() == obj->HasFastObjectElements()); | |
|
Igor Sheludko
2016/07/08 08:38:22
CHECK_EQ?
Camillo Bruni
2016/07/11 11:46:39
copy pasta
| |
| 357 | |
| 358 // If a GC was caused while constructing this object, the elements | |
|
Igor Sheludko
2016/07/08 08:38:22
I think this comment belongs only to ElementAreSaf
Camillo Bruni
2016/07/11 11:46:39
right.
| |
| 359 // pointer may point to a one pointer filler map. | |
| 360 ElementsKind kind = obj->GetElementsKind(); | |
| 361 if (IsFastSmiOrObjectElementsKind(kind)) { | |
| 362 CHECK(elements->map() == heap->fixed_array_map() || | |
| 363 elements->map() == heap->fixed_cow_array_map()); | |
| 364 } else if (IsFastDoubleElementsKind(kind)) { | |
| 365 CHECK(elements->IsFixedDoubleArray() || | |
| 366 elements == heap->empty_fixed_array()); | |
| 367 } else if (kind == DICTIONARY_ELEMENTS) { | |
| 368 CHECK(elements->IsSeededNumberDictionary()); | |
| 369 VerifyDictionary(SeededNumberDictionary::cast(elements)); | |
|
Igor Sheludko
2016/07/08 08:38:22
I think this check also applies to SLOW_SLOPPY_ARG
Camillo Bruni
2016/07/11 11:46:39
eventually I will have to put a switch statement h
| |
| 370 return; | |
| 371 } else { | |
| 372 CHECK(kind > DICTIONARY_ELEMENTS); | |
| 373 } | |
| 374 CHECK(!IsSloppyArgumentsElements(kind) || | |
| 375 (elements->IsFixedArray() && elements->length() >= 2)); | |
| 376 | |
| 377 if (IsFastPackedElementsKind(kind)) { | |
| 378 uint32_t length = elements->length(); | |
| 379 if (obj->IsJSArray()) { | |
| 380 Object* number = JSArray::cast(obj)->length(); | |
| 381 if (number->IsSmi()) { | |
| 382 length = Min(length, static_cast<uint32_t>(Smi::cast(number)->value())); | |
| 383 } | |
| 289 } | 384 } |
| 290 DescriptorArray* descriptors = map()->instance_descriptors(); | 385 if (kind == FAST_DOUBLE_ELEMENTS) { |
| 291 Isolate* isolate = GetIsolate(); | 386 for (uint32_t i = 0; i < length; i++) { |
| 292 for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) { | 387 CHECK(!FixedDoubleArray::cast(elements)->is_the_hole(i)); |
| 293 if (descriptors->GetDetails(i).type() == DATA) { | 388 } |
| 294 Representation r = descriptors->GetDetails(i).representation(); | 389 } else { |
| 295 FieldIndex index = FieldIndex::ForDescriptor(map(), i); | 390 for (uint32_t i = 0; i < length; i++) { |
| 296 if (IsUnboxedDoubleField(index)) { | 391 CHECK_NE(FixedArray::cast(elements)->get(i), heap->the_hole_value()); |
| 297 DCHECK(r.IsDouble()); | |
| 298 continue; | |
| 299 } | |
| 300 Object* value = RawFastPropertyAt(index); | |
| 301 if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber()); | |
| 302 if (value->IsUninitialized(isolate)) continue; | |
| 303 if (r.IsSmi()) DCHECK(value->IsSmi()); | |
| 304 if (r.IsHeapObject()) DCHECK(value->IsHeapObject()); | |
| 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 } | 392 } |
| 318 } | 393 } |
| 319 } | 394 } |
| 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 } | |
| 331 } | 395 } |
| 332 | 396 |
| 397 } // namespace | |
| 398 | |
| 399 void JSObject::JSObjectVerify() { | |
| 400 VerifyProperties(this); | |
| 401 VerifyElements(this); | |
| 402 } | |
| 333 | 403 |
| 334 void Map::MapVerify() { | 404 void Map::MapVerify() { |
| 335 Heap* heap = GetHeap(); | 405 Heap* heap = GetHeap(); |
| 336 CHECK(!heap->InNewSpace(this)); | 406 CHECK(!heap->InNewSpace(this)); |
| 337 CHECK(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE); | 407 CHECK(FIRST_TYPE <= instance_type()); |
|
Igor Sheludko
2016/07/08 08:38:22
CHECK_LE?
Camillo Bruni
2016/07/11 11:46:39
done.
| |
| 408 CHECK(instance_type() <= LAST_TYPE); | |
| 338 CHECK(instance_size() == kVariableSizeSentinel || | 409 CHECK(instance_size() == kVariableSizeSentinel || |
| 339 (kPointerSize <= instance_size() && | 410 (kPointerSize <= instance_size() && |
| 340 instance_size() < heap->Capacity())); | 411 instance_size() < heap->Capacity())); |
| 341 CHECK(GetBackPointer()->IsUndefined(heap->isolate()) || | 412 CHECK(GetBackPointer()->IsUndefined(heap->isolate()) || |
| 342 !Map::cast(GetBackPointer())->is_stable()); | 413 !Map::cast(GetBackPointer())->is_stable()); |
| 343 VerifyHeapPointer(prototype()); | 414 VerifyHeapPointer(prototype()); |
| 344 VerifyHeapPointer(instance_descriptors()); | 415 VerifyHeapPointer(instance_descriptors()); |
| 345 SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates()); | 416 SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates()); |
| 346 SLOW_DCHECK(TransitionArray::IsSortedNoDuplicates(this)); | 417 SLOW_DCHECK(TransitionArray::IsSortedNoDuplicates(this)); |
| 347 SLOW_DCHECK(TransitionArray::IsConsistentWithBackPointers(this)); | 418 SLOW_DCHECK(TransitionArray::IsConsistentWithBackPointers(this)); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 | 490 |
| 420 void JSGeneratorObject::JSGeneratorObjectVerify() { | 491 void JSGeneratorObject::JSGeneratorObjectVerify() { |
| 421 // In an expression like "new g()", there can be a point where a generator | 492 // In an expression like "new g()", there can be a point where a generator |
| 422 // object is allocated but its fields are all undefined, as it hasn't yet been | 493 // object is allocated but its fields are all undefined, as it hasn't yet been |
| 423 // initialized by the generator. Hence these weak checks. | 494 // initialized by the generator. Hence these weak checks. |
| 424 VerifyObjectField(kFunctionOffset); | 495 VerifyObjectField(kFunctionOffset); |
| 425 VerifyObjectField(kContextOffset); | 496 VerifyObjectField(kContextOffset); |
| 426 VerifyObjectField(kReceiverOffset); | 497 VerifyObjectField(kReceiverOffset); |
| 427 VerifyObjectField(kOperandStackOffset); | 498 VerifyObjectField(kOperandStackOffset); |
| 428 VerifyObjectField(kContinuationOffset); | 499 VerifyObjectField(kContinuationOffset); |
| 500 JSObjectVerify(); | |
| 501 } | |
| 502 | |
| 503 void JSArgumentsObject::JSArgumentsObjectVerify() { | |
| 504 VerifyObjectField(kLengthOffset); | |
| 505 JSObjectVerify(); | |
| 506 Isolate* isolate = GetIsolate(); | |
| 507 | |
| 508 // TODO(cbruni): replace with NULL check once all hydrogren stubs manage to | |
| 509 // set up the contexts properly | |
| 510 if (isolate->context()->IsSmi()) return; | |
| 511 if (isolate->bootstrapper()->IsActive()) return; | |
| 512 if (map() == *isolate->sloppy_arguments_map()) { | |
| 513 // TODO(cbruni): normal array-like size verification | |
| 514 } else if (map() == *isolate->fast_aliased_arguments_map()) { | |
| 515 CHECK(HasFastArgumentsElements()); | |
| 516 CHECK(this->elements()->IsFixedArray()); | |
| 517 CHECK_GE(this->elements()->length(), 2); | |
| 518 } else if (map() == *isolate->slow_aliased_arguments_map()) { | |
| 519 CHECK(HasSlowArgumentsElements()); | |
| 520 CHECK(this->elements()->IsFixedArray()); | |
| 521 CHECK_GE(this->elements()->length(), 2); | |
| 522 } else if (map() == *isolate->strict_arguments_map()) { | |
| 523 Object* length = *Object::GetProperty(handle(this, isolate), | |
|
Igor Sheludko
2016/07/08 08:38:22
This is scary. I guess heap verification should no
Camillo Bruni
2016/07/11 11:46:39
right, also I just noticed that this can be easily
| |
| 524 isolate->factory()->length_string()) | |
| 525 .ToHandleChecked(); | |
| 526 CHECK_EQ(Smi::cast(length)->value(), elements()->length()); | |
| 527 CHECK(HasFastElements()); | |
| 528 } else { | |
| 529 PrintF("."); | |
|
Igor Sheludko
2016/07/08 08:38:22
Surprise! :)
Camillo Bruni
2016/07/11 11:46:39
... as good as unreachable.
| |
| 530 } | |
| 429 } | 531 } |
| 430 | 532 |
| 431 | 533 |
| 432 void JSValue::JSValueVerify() { | 534 void JSValue::JSValueVerify() { |
| 433 Object* v = value(); | 535 Object* v = value(); |
| 434 if (v->IsHeapObject()) { | 536 if (v->IsHeapObject()) { |
| 435 VerifyHeapPointer(v); | 537 VerifyHeapPointer(v); |
| 436 } | 538 } |
| 539 JSObjectVerify(); | |
| 437 } | 540 } |
| 438 | 541 |
| 439 | 542 |
| 440 void JSDate::JSDateVerify() { | 543 void JSDate::JSDateVerify() { |
|
Igor Sheludko
2016/07/08 08:38:22
JSDate and all other JSObject builtins should also
| |
| 441 if (value()->IsHeapObject()) { | 544 if (value()->IsHeapObject()) { |
| 442 VerifyHeapPointer(value()); | 545 VerifyHeapPointer(value()); |
| 443 } | 546 } |
| 444 Isolate* isolate = GetIsolate(); | 547 Isolate* isolate = GetIsolate(); |
| 445 CHECK(value()->IsUndefined(isolate) || value()->IsSmi() || | 548 CHECK(value()->IsUndefined(isolate) || value()->IsSmi() || |
| 446 value()->IsHeapNumber()); | 549 value()->IsHeapNumber()); |
| 447 CHECK(year()->IsUndefined(isolate) || year()->IsSmi() || year()->IsNaN()); | 550 CHECK(year()->IsUndefined(isolate) || year()->IsSmi() || year()->IsNaN()); |
| 448 CHECK(month()->IsUndefined(isolate) || month()->IsSmi() || month()->IsNaN()); | 551 CHECK(month()->IsUndefined(isolate) || month()->IsSmi() || month()->IsNaN()); |
| 449 CHECK(day()->IsUndefined(isolate) || day()->IsSmi() || day()->IsNaN()); | 552 CHECK(day()->IsUndefined(isolate) || day()->IsSmi() || day()->IsNaN()); |
| 450 CHECK(weekday()->IsUndefined(isolate) || weekday()->IsSmi() || | 553 CHECK(weekday()->IsUndefined(isolate) || weekday()->IsSmi() || |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 VerifyObjectField(kBoundTargetFunctionOffset); | 641 VerifyObjectField(kBoundTargetFunctionOffset); |
| 539 VerifyObjectField(kBoundArgumentsOffset); | 642 VerifyObjectField(kBoundArgumentsOffset); |
| 540 CHECK(bound_target_function()->IsCallable()); | 643 CHECK(bound_target_function()->IsCallable()); |
| 541 CHECK(IsCallable()); | 644 CHECK(IsCallable()); |
| 542 CHECK_EQ(IsConstructor(), bound_target_function()->IsConstructor()); | 645 CHECK_EQ(IsConstructor(), bound_target_function()->IsConstructor()); |
| 543 } | 646 } |
| 544 | 647 |
| 545 | 648 |
| 546 void JSFunction::JSFunctionVerify() { | 649 void JSFunction::JSFunctionVerify() { |
| 547 CHECK(IsJSFunction()); | 650 CHECK(IsJSFunction()); |
| 651 JSObjectVerify(); | |
| 548 VerifyObjectField(kPrototypeOrInitialMapOffset); | 652 VerifyObjectField(kPrototypeOrInitialMapOffset); |
| 549 VerifyObjectField(kNextFunctionLinkOffset); | 653 VerifyObjectField(kNextFunctionLinkOffset); |
| 550 CHECK(code()->IsCode()); | 654 CHECK(code()->IsCode()); |
| 551 CHECK(next_function_link() == NULL || | 655 CHECK(next_function_link() == NULL || |
| 552 next_function_link()->IsUndefined(GetIsolate()) || | 656 next_function_link()->IsUndefined(GetIsolate()) || |
| 553 next_function_link()->IsJSFunction()); | 657 next_function_link()->IsJSFunction()); |
| 554 CHECK(map()->is_callable()); | 658 CHECK(map()->is_callable()); |
| 555 } | 659 } |
| 556 | 660 |
| 557 | 661 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 584 } | 688 } |
| 585 | 689 |
| 586 | 690 |
| 587 void JSGlobalObject::JSGlobalObjectVerify() { | 691 void JSGlobalObject::JSGlobalObjectVerify() { |
| 588 CHECK(IsJSGlobalObject()); | 692 CHECK(IsJSGlobalObject()); |
| 589 // Do not check the dummy global object for the builtins. | 693 // Do not check the dummy global object for the builtins. |
| 590 if (GlobalDictionary::cast(properties())->NumberOfElements() == 0 && | 694 if (GlobalDictionary::cast(properties())->NumberOfElements() == 0 && |
| 591 elements()->length() == 0) { | 695 elements()->length() == 0) { |
| 592 return; | 696 return; |
| 593 } | 697 } |
| 698 CHECK(!HasFastProperties()); | |
| 594 JSObjectVerify(); | 699 JSObjectVerify(); |
| 595 } | 700 } |
| 596 | 701 |
| 597 | 702 |
| 598 void Oddball::OddballVerify() { | 703 void Oddball::OddballVerify() { |
| 599 CHECK(IsOddball()); | 704 CHECK(IsOddball()); |
| 600 Heap* heap = GetHeap(); | 705 Heap* heap = GetHeap(); |
| 601 VerifyHeapPointer(to_string()); | 706 VerifyHeapPointer(to_string()); |
| 602 Object* number = to_number(); | 707 Object* number = to_number(); |
| 603 if (number->IsHeapObject()) { | 708 if (number->IsHeapObject()) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 687 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { | 792 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { |
| 688 Object* obj = it.rinfo()->target_object(); | 793 Object* obj = it.rinfo()->target_object(); |
| 689 if (IsWeakObject(obj)) { | 794 if (IsWeakObject(obj)) { |
| 690 if (obj->IsMap()) { | 795 if (obj->IsMap()) { |
| 691 Map* map = Map::cast(obj); | 796 Map* map = Map::cast(obj); |
| 692 CHECK(map->dependent_code()->Contains(DependentCode::kWeakCodeGroup, | 797 CHECK(map->dependent_code()->Contains(DependentCode::kWeakCodeGroup, |
| 693 cell)); | 798 cell)); |
| 694 } else if (obj->IsJSObject()) { | 799 } else if (obj->IsJSObject()) { |
| 695 if (isolate->heap()->InNewSpace(obj)) { | 800 if (isolate->heap()->InNewSpace(obj)) { |
| 696 ArrayList* list = | 801 ArrayList* list = |
| 697 GetIsolate()->heap()->weak_new_space_object_to_code_list(); | 802 isolate->heap()->weak_new_space_object_to_code_list(); |
| 698 bool found = false; | 803 bool found = false; |
| 699 for (int i = 0; i < list->Length(); i += 2) { | 804 for (int i = 0; i < list->Length(); i += 2) { |
| 700 WeakCell* obj_cell = WeakCell::cast(list->Get(i)); | 805 WeakCell* obj_cell = WeakCell::cast(list->Get(i)); |
| 701 if (!obj_cell->cleared() && obj_cell->value() == obj && | 806 if (!obj_cell->cleared() && obj_cell->value() == obj && |
| 702 WeakCell::cast(list->Get(i + 1)) == cell) { | 807 WeakCell::cast(list->Get(i + 1)) == cell) { |
| 703 found = true; | 808 found = true; |
| 704 break; | 809 break; |
| 705 } | 810 } |
| 706 } | 811 } |
| 707 CHECK(found); | 812 CHECK(found); |
| 708 } else { | 813 } else { |
| 709 Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate); | 814 Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate); |
| 710 DependentCode* dep = | 815 DependentCode* dep = |
| 711 GetIsolate()->heap()->LookupWeakObjectToCodeDependency(key_obj); | 816 isolate->heap()->LookupWeakObjectToCodeDependency(key_obj); |
| 712 dep->Contains(DependentCode::kWeakCodeGroup, cell); | 817 dep->Contains(DependentCode::kWeakCodeGroup, cell); |
| 713 } | 818 } |
| 714 } | 819 } |
| 715 } | 820 } |
| 716 } | 821 } |
| 717 } | 822 } |
| 718 | 823 |
| 719 | 824 |
| 720 void JSArray::JSArrayVerify() { | 825 void JSArray::JSArrayVerify() { |
| 826 CHECK(IsJSArray()); | |
| 721 JSObjectVerify(); | 827 JSObjectVerify(); |
| 722 Isolate* isolate = GetIsolate(); | 828 Isolate* isolate = GetIsolate(); |
| 723 CHECK(length()->IsNumber() || length()->IsUndefined(isolate)); | 829 // Allow undefined for not fully initialized JSArrays |
| 830 if (length()->IsUndefined(isolate)) { | |
| 831 CHECK_EQ(FixedArray::cast(elements()), | |
| 832 isolate->heap()->empty_fixed_array()); | |
| 833 return; | |
| 834 } | |
| 835 CHECK(length()->IsNumber()); | |
| 724 // If a GC was caused while constructing this array, the elements | 836 // If a GC was caused while constructing this array, the elements |
| 725 // pointer may point to a one pointer filler map. | 837 // pointer may point to a one pointer filler map. |
| 726 if (ElementsAreSafeToExamine()) { | 838 if (ElementsAreSafeToExamine()) { |
| 727 CHECK(elements()->IsUndefined(isolate) || elements()->IsFixedArray() || | 839 CHECK(elements()->IsFixedArray() || elements()->IsFixedDoubleArray()); |
| 728 elements()->IsFixedDoubleArray()); | |
| 729 } | 840 } |
| 730 } | 841 } |
| 731 | 842 |
| 732 | |
| 733 void JSSet::JSSetVerify() { | 843 void JSSet::JSSetVerify() { |
| 734 CHECK(IsJSSet()); | 844 CHECK(IsJSSet()); |
| 735 JSObjectVerify(); | 845 JSObjectVerify(); |
| 736 VerifyHeapPointer(table()); | 846 VerifyHeapPointer(table()); |
| 737 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate())); | 847 CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate())); |
| 738 // TODO(arv): Verify OrderedHashTable too. | 848 // TODO(arv): Verify OrderedHashTable too. |
| 739 } | 849 } |
| 740 | 850 |
| 741 | 851 |
| 742 void JSMap::JSMapVerify() { | 852 void JSMap::JSMapVerify() { |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1289 if (isolate->bootstrapper()->IsActive()) return; | 1399 if (isolate->bootstrapper()->IsActive()) return; |
| 1290 | 1400 |
| 1291 static const int mask = RelocInfo::kCodeTargetMask; | 1401 static const int mask = RelocInfo::kCodeTargetMask; |
| 1292 RelocIterator old_it(old_code, mask); | 1402 RelocIterator old_it(old_code, mask); |
| 1293 RelocIterator new_it(new_code, mask); | 1403 RelocIterator new_it(new_code, mask); |
| 1294 Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck); | 1404 Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck); |
| 1295 | 1405 |
| 1296 while (!old_it.done()) { | 1406 while (!old_it.done()) { |
| 1297 RelocInfo* rinfo = old_it.rinfo(); | 1407 RelocInfo* rinfo = old_it.rinfo(); |
| 1298 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 1408 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 1299 CHECK(!target->is_handler() && !target->is_inline_cache_stub()); | 1409 CHECK(!target->is_handler()); |
| 1410 CHECK(!target->is_inline_cache_stub()); | |
| 1300 if (target == stack_check) break; | 1411 if (target == stack_check) break; |
| 1301 old_it.next(); | 1412 old_it.next(); |
| 1302 } | 1413 } |
| 1303 | 1414 |
| 1304 while (!new_it.done()) { | 1415 while (!new_it.done()) { |
| 1305 RelocInfo* rinfo = new_it.rinfo(); | 1416 RelocInfo* rinfo = new_it.rinfo(); |
| 1306 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 1417 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 1307 CHECK(!target->is_handler() && !target->is_inline_cache_stub()); | 1418 CHECK(!target->is_handler()); |
| 1419 CHECK(!target->is_inline_cache_stub()); | |
| 1308 if (target == stack_check) break; | 1420 if (target == stack_check) break; |
| 1309 new_it.next(); | 1421 new_it.next(); |
| 1310 } | 1422 } |
| 1311 | 1423 |
| 1312 // Either both are done because there is no stack check. | 1424 // Either both are done because there is no stack check. |
| 1313 // Or we are past the prologue for both. | 1425 // Or we are past the prologue for both. |
| 1314 CHECK_EQ(new_it.done(), old_it.done()); | 1426 CHECK_EQ(new_it.done(), old_it.done()); |
| 1315 | 1427 |
| 1316 // After the prologue, each call in the old code has a corresponding call | 1428 // After the prologue, each call in the old code has a corresponding call |
| 1317 // in the new code. | 1429 // in the new code. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1333 | 1445 |
| 1334 // Both are done at the same time. | 1446 // Both are done at the same time. |
| 1335 CHECK_EQ(new_it.done(), old_it.done()); | 1447 CHECK_EQ(new_it.done(), old_it.done()); |
| 1336 } | 1448 } |
| 1337 | 1449 |
| 1338 | 1450 |
| 1339 #endif // DEBUG | 1451 #endif // DEBUG |
| 1340 | 1452 |
| 1341 } // namespace internal | 1453 } // namespace internal |
| 1342 } // namespace v8 | 1454 } // namespace v8 |
| OLD | NEW |