| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/allocation-site-scopes.h" | 8 #include "src/allocation-site-scopes.h" |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 holder = native_context->string_function()->instance_prototype(); | 117 holder = native_context->string_function()->instance_prototype(); |
| 118 } else if (IsSymbol()) { | 118 } else if (IsSymbol()) { |
| 119 holder = native_context->symbol_function()->instance_prototype(); | 119 holder = native_context->symbol_function()->instance_prototype(); |
| 120 } else if (IsBoolean()) { | 120 } else if (IsBoolean()) { |
| 121 holder = native_context->boolean_function()->instance_prototype(); | 121 holder = native_context->boolean_function()->instance_prototype(); |
| 122 } else { | 122 } else { |
| 123 result->isolate()->PushStackTraceAndDie( | 123 result->isolate()->PushStackTraceAndDie( |
| 124 0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001); | 124 0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001); |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 ASSERT(holder != NULL); // Cannot handle null or undefined. | 127 DCHECK(holder != NULL); // Cannot handle null or undefined. |
| 128 JSReceiver::cast(holder)->Lookup(name, result); | 128 JSReceiver::cast(holder)->Lookup(name, result); |
| 129 } | 129 } |
| 130 | 130 |
| 131 | 131 |
| 132 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) { | 132 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) { |
| 133 for (; it->IsFound(); it->Next()) { | 133 for (; it->IsFound(); it->Next()) { |
| 134 switch (it->state()) { | 134 switch (it->state()) { |
| 135 case LookupIterator::NOT_FOUND: | 135 case LookupIterator::NOT_FOUND: |
| 136 UNREACHABLE(); | 136 UNREACHABLE(); |
| 137 case LookupIterator::JSPROXY: | 137 case LookupIterator::JSPROXY: |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 if (type == this) return true; | 221 if (type == this) return true; |
| 222 } | 222 } |
| 223 // Didn't find the required type in the inheritance chain. | 223 // Didn't find the required type in the inheritance chain. |
| 224 return false; | 224 return false; |
| 225 } | 225 } |
| 226 | 226 |
| 227 | 227 |
| 228 template<typename To> | 228 template<typename To> |
| 229 static inline To* CheckedCast(void *from) { | 229 static inline To* CheckedCast(void *from) { |
| 230 uintptr_t temp = reinterpret_cast<uintptr_t>(from); | 230 uintptr_t temp = reinterpret_cast<uintptr_t>(from); |
| 231 ASSERT(temp % sizeof(To) == 0); | 231 DCHECK(temp % sizeof(To) == 0); |
| 232 return reinterpret_cast<To*>(temp); | 232 return reinterpret_cast<To*>(temp); |
| 233 } | 233 } |
| 234 | 234 |
| 235 | 235 |
| 236 static Handle<Object> PerformCompare(const BitmaskCompareDescriptor& descriptor, | 236 static Handle<Object> PerformCompare(const BitmaskCompareDescriptor& descriptor, |
| 237 char* ptr, | 237 char* ptr, |
| 238 Isolate* isolate) { | 238 Isolate* isolate) { |
| 239 uint32_t bitmask = descriptor.bitmask; | 239 uint32_t bitmask = descriptor.bitmask; |
| 240 uint32_t compare_value = descriptor.compare_value; | 240 uint32_t compare_value = descriptor.compare_value; |
| 241 uint32_t value; | 241 uint32_t value; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 Handle<Object> receiver, | 323 Handle<Object> receiver, |
| 324 Handle<DeclaredAccessorInfo> info, | 324 Handle<DeclaredAccessorInfo> info, |
| 325 Isolate* isolate) { | 325 Isolate* isolate) { |
| 326 DisallowHeapAllocation no_gc; | 326 DisallowHeapAllocation no_gc; |
| 327 char* current = reinterpret_cast<char*>(*receiver); | 327 char* current = reinterpret_cast<char*>(*receiver); |
| 328 DeclaredAccessorDescriptorIterator iterator(info->descriptor()); | 328 DeclaredAccessorDescriptorIterator iterator(info->descriptor()); |
| 329 while (true) { | 329 while (true) { |
| 330 const DeclaredAccessorDescriptorData* data = iterator.Next(); | 330 const DeclaredAccessorDescriptorData* data = iterator.Next(); |
| 331 switch (data->type) { | 331 switch (data->type) { |
| 332 case kDescriptorReturnObject: { | 332 case kDescriptorReturnObject: { |
| 333 ASSERT(iterator.Complete()); | 333 DCHECK(iterator.Complete()); |
| 334 current = *CheckedCast<char*>(current); | 334 current = *CheckedCast<char*>(current); |
| 335 return handle(*CheckedCast<Object*>(current), isolate); | 335 return handle(*CheckedCast<Object*>(current), isolate); |
| 336 } | 336 } |
| 337 case kDescriptorPointerDereference: | 337 case kDescriptorPointerDereference: |
| 338 ASSERT(!iterator.Complete()); | 338 DCHECK(!iterator.Complete()); |
| 339 current = *reinterpret_cast<char**>(current); | 339 current = *reinterpret_cast<char**>(current); |
| 340 break; | 340 break; |
| 341 case kDescriptorPointerShift: | 341 case kDescriptorPointerShift: |
| 342 ASSERT(!iterator.Complete()); | 342 DCHECK(!iterator.Complete()); |
| 343 current += data->pointer_shift_descriptor.byte_offset; | 343 current += data->pointer_shift_descriptor.byte_offset; |
| 344 break; | 344 break; |
| 345 case kDescriptorObjectDereference: { | 345 case kDescriptorObjectDereference: { |
| 346 ASSERT(!iterator.Complete()); | 346 DCHECK(!iterator.Complete()); |
| 347 Object* object = CheckedCast<Object>(current); | 347 Object* object = CheckedCast<Object>(current); |
| 348 int field = data->object_dereference_descriptor.internal_field; | 348 int field = data->object_dereference_descriptor.internal_field; |
| 349 Object* smi = JSObject::cast(object)->GetInternalField(field); | 349 Object* smi = JSObject::cast(object)->GetInternalField(field); |
| 350 ASSERT(smi->IsSmi()); | 350 DCHECK(smi->IsSmi()); |
| 351 current = reinterpret_cast<char*>(smi); | 351 current = reinterpret_cast<char*>(smi); |
| 352 break; | 352 break; |
| 353 } | 353 } |
| 354 case kDescriptorBitmaskCompare: | 354 case kDescriptorBitmaskCompare: |
| 355 ASSERT(iterator.Complete()); | 355 DCHECK(iterator.Complete()); |
| 356 return PerformCompare(data->bitmask_compare_descriptor, | 356 return PerformCompare(data->bitmask_compare_descriptor, |
| 357 current, | 357 current, |
| 358 isolate); | 358 isolate); |
| 359 case kDescriptorPointerCompare: | 359 case kDescriptorPointerCompare: |
| 360 ASSERT(iterator.Complete()); | 360 DCHECK(iterator.Complete()); |
| 361 return PerformCompare(data->pointer_compare_descriptor, | 361 return PerformCompare(data->pointer_compare_descriptor, |
| 362 current, | 362 current, |
| 363 isolate); | 363 isolate); |
| 364 case kDescriptorPrimitiveValue: | 364 case kDescriptorPrimitiveValue: |
| 365 ASSERT(iterator.Complete()); | 365 DCHECK(iterator.Complete()); |
| 366 return GetPrimitiveValue(data->primitive_value_descriptor, | 366 return GetPrimitiveValue(data->primitive_value_descriptor, |
| 367 current, | 367 current, |
| 368 isolate); | 368 isolate); |
| 369 } | 369 } |
| 370 } | 370 } |
| 371 UNREACHABLE(); | 371 UNREACHABLE(); |
| 372 return isolate->factory()->undefined_value(); | 372 return isolate->factory()->undefined_value(); |
| 373 } | 373 } |
| 374 | 374 |
| 375 | 375 |
| 376 Handle<FixedArray> JSObject::EnsureWritableFastElements( | 376 Handle<FixedArray> JSObject::EnsureWritableFastElements( |
| 377 Handle<JSObject> object) { | 377 Handle<JSObject> object) { |
| 378 ASSERT(object->HasFastSmiOrObjectElements()); | 378 DCHECK(object->HasFastSmiOrObjectElements()); |
| 379 Isolate* isolate = object->GetIsolate(); | 379 Isolate* isolate = object->GetIsolate(); |
| 380 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate); | 380 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate); |
| 381 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; | 381 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; |
| 382 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( | 382 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( |
| 383 elems, isolate->factory()->fixed_array_map()); | 383 elems, isolate->factory()->fixed_array_map()); |
| 384 object->set_elements(*writable_elems); | 384 object->set_elements(*writable_elems); |
| 385 isolate->counters()->cow_arrays_converted()->Increment(); | 385 isolate->counters()->cow_arrays_converted()->Increment(); |
| 386 return writable_elems; | 386 return writable_elems; |
| 387 } | 387 } |
| 388 | 388 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 399 return CallTrap( | 399 return CallTrap( |
| 400 proxy, "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args); | 400 proxy, "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args); |
| 401 } | 401 } |
| 402 | 402 |
| 403 | 403 |
| 404 MaybeHandle<Object> Object::GetPropertyWithAccessor(Handle<Object> receiver, | 404 MaybeHandle<Object> Object::GetPropertyWithAccessor(Handle<Object> receiver, |
| 405 Handle<Name> name, | 405 Handle<Name> name, |
| 406 Handle<JSObject> holder, | 406 Handle<JSObject> holder, |
| 407 Handle<Object> structure) { | 407 Handle<Object> structure) { |
| 408 Isolate* isolate = name->GetIsolate(); | 408 Isolate* isolate = name->GetIsolate(); |
| 409 ASSERT(!structure->IsForeign()); | 409 DCHECK(!structure->IsForeign()); |
| 410 // api style callbacks. | 410 // api style callbacks. |
| 411 if (structure->IsAccessorInfo()) { | 411 if (structure->IsAccessorInfo()) { |
| 412 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure); | 412 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure); |
| 413 if (!info->IsCompatibleReceiver(*receiver)) { | 413 if (!info->IsCompatibleReceiver(*receiver)) { |
| 414 Handle<Object> args[2] = { name, receiver }; | 414 Handle<Object> args[2] = { name, receiver }; |
| 415 Handle<Object> error = | 415 Handle<Object> error = |
| 416 isolate->factory()->NewTypeError("incompatible_method_receiver", | 416 isolate->factory()->NewTypeError("incompatible_method_receiver", |
| 417 HandleVector(args, | 417 HandleVector(args, |
| 418 ARRAY_SIZE(args))); | 418 ARRAY_SIZE(args))); |
| 419 return isolate->Throw<Object>(error); | 419 return isolate->Throw<Object>(error); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 } | 473 } |
| 474 | 474 |
| 475 | 475 |
| 476 MaybeHandle<Object> Object::SetPropertyWithAccessor( | 476 MaybeHandle<Object> Object::SetPropertyWithAccessor( |
| 477 Handle<Object> receiver, Handle<Name> name, Handle<Object> value, | 477 Handle<Object> receiver, Handle<Name> name, Handle<Object> value, |
| 478 Handle<JSObject> holder, Handle<Object> structure, StrictMode strict_mode) { | 478 Handle<JSObject> holder, Handle<Object> structure, StrictMode strict_mode) { |
| 479 Isolate* isolate = name->GetIsolate(); | 479 Isolate* isolate = name->GetIsolate(); |
| 480 | 480 |
| 481 // We should never get here to initialize a const with the hole | 481 // We should never get here to initialize a const with the hole |
| 482 // value since a const declaration would conflict with the setter. | 482 // value since a const declaration would conflict with the setter. |
| 483 ASSERT(!structure->IsForeign()); | 483 DCHECK(!structure->IsForeign()); |
| 484 if (structure->IsExecutableAccessorInfo()) { | 484 if (structure->IsExecutableAccessorInfo()) { |
| 485 // Don't call executable accessor setters with non-JSObject receivers. | 485 // Don't call executable accessor setters with non-JSObject receivers. |
| 486 if (!receiver->IsJSObject()) return value; | 486 if (!receiver->IsJSObject()) return value; |
| 487 // api style callbacks | 487 // api style callbacks |
| 488 ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure); | 488 ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure); |
| 489 if (!info->IsCompatibleReceiver(*receiver)) { | 489 if (!info->IsCompatibleReceiver(*receiver)) { |
| 490 Handle<Object> args[2] = { name, receiver }; | 490 Handle<Object> args[2] = { name, receiver }; |
| 491 Handle<Object> error = | 491 Handle<Object> error = |
| 492 isolate->factory()->NewTypeError("incompatible_method_receiver", | 492 isolate->factory()->NewTypeError("incompatible_method_receiver", |
| 493 HandleVector(args, | 493 HandleVector(args, |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 it->GetAccessors(), strict_mode); | 642 it->GetAccessors(), strict_mode); |
| 643 } | 643 } |
| 644 | 644 |
| 645 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_SET); | 645 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_SET); |
| 646 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 646 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); |
| 647 return value; | 647 return value; |
| 648 } | 648 } |
| 649 | 649 |
| 650 | 650 |
| 651 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { | 651 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { |
| 652 ASSERT(!HasFastProperties()); | 652 DCHECK(!HasFastProperties()); |
| 653 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 653 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 654 if (IsGlobalObject()) { | 654 if (IsGlobalObject()) { |
| 655 value = PropertyCell::cast(value)->value(); | 655 value = PropertyCell::cast(value)->value(); |
| 656 } | 656 } |
| 657 ASSERT(!value->IsPropertyCell() && !value->IsCell()); | 657 DCHECK(!value->IsPropertyCell() && !value->IsCell()); |
| 658 return value; | 658 return value; |
| 659 } | 659 } |
| 660 | 660 |
| 661 | 661 |
| 662 Handle<Object> JSObject::GetNormalizedProperty(Handle<JSObject> object, | 662 Handle<Object> JSObject::GetNormalizedProperty(Handle<JSObject> object, |
| 663 const LookupResult* result) { | 663 const LookupResult* result) { |
| 664 ASSERT(!object->HasFastProperties()); | 664 DCHECK(!object->HasFastProperties()); |
| 665 Isolate* isolate = object->GetIsolate(); | 665 Isolate* isolate = object->GetIsolate(); |
| 666 Handle<Object> value(object->property_dictionary()->ValueAt( | 666 Handle<Object> value(object->property_dictionary()->ValueAt( |
| 667 result->GetDictionaryEntry()), isolate); | 667 result->GetDictionaryEntry()), isolate); |
| 668 if (object->IsGlobalObject()) { | 668 if (object->IsGlobalObject()) { |
| 669 value = handle(Handle<PropertyCell>::cast(value)->value(), isolate); | 669 value = handle(Handle<PropertyCell>::cast(value)->value(), isolate); |
| 670 ASSERT(!value->IsTheHole()); | 670 DCHECK(!value->IsTheHole()); |
| 671 } | 671 } |
| 672 ASSERT(!value->IsPropertyCell() && !value->IsCell()); | 672 DCHECK(!value->IsPropertyCell() && !value->IsCell()); |
| 673 return value; | 673 return value; |
| 674 } | 674 } |
| 675 | 675 |
| 676 | 676 |
| 677 void JSObject::SetNormalizedProperty(Handle<JSObject> object, | 677 void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
| 678 const LookupResult* result, | 678 const LookupResult* result, |
| 679 Handle<Object> value) { | 679 Handle<Object> value) { |
| 680 ASSERT(!object->HasFastProperties()); | 680 DCHECK(!object->HasFastProperties()); |
| 681 NameDictionary* property_dictionary = object->property_dictionary(); | 681 NameDictionary* property_dictionary = object->property_dictionary(); |
| 682 if (object->IsGlobalObject()) { | 682 if (object->IsGlobalObject()) { |
| 683 Handle<PropertyCell> cell(PropertyCell::cast( | 683 Handle<PropertyCell> cell(PropertyCell::cast( |
| 684 property_dictionary->ValueAt(result->GetDictionaryEntry()))); | 684 property_dictionary->ValueAt(result->GetDictionaryEntry()))); |
| 685 PropertyCell::SetValueInferType(cell, value); | 685 PropertyCell::SetValueInferType(cell, value); |
| 686 } else { | 686 } else { |
| 687 property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value); | 687 property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value); |
| 688 } | 688 } |
| 689 } | 689 } |
| 690 | 690 |
| 691 | 691 |
| 692 void JSObject::SetNormalizedProperty(Handle<JSObject> object, | 692 void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
| 693 Handle<Name> name, | 693 Handle<Name> name, |
| 694 Handle<Object> value, | 694 Handle<Object> value, |
| 695 PropertyDetails details) { | 695 PropertyDetails details) { |
| 696 ASSERT(!object->HasFastProperties()); | 696 DCHECK(!object->HasFastProperties()); |
| 697 Handle<NameDictionary> property_dictionary(object->property_dictionary()); | 697 Handle<NameDictionary> property_dictionary(object->property_dictionary()); |
| 698 | 698 |
| 699 if (!name->IsUniqueName()) { | 699 if (!name->IsUniqueName()) { |
| 700 name = object->GetIsolate()->factory()->InternalizeString( | 700 name = object->GetIsolate()->factory()->InternalizeString( |
| 701 Handle<String>::cast(name)); | 701 Handle<String>::cast(name)); |
| 702 } | 702 } |
| 703 | 703 |
| 704 int entry = property_dictionary->FindEntry(name); | 704 int entry = property_dictionary->FindEntry(name); |
| 705 if (entry == NameDictionary::kNotFound) { | 705 if (entry == NameDictionary::kNotFound) { |
| 706 Handle<Object> store_value = value; | 706 Handle<Object> store_value = value; |
| 707 if (object->IsGlobalObject()) { | 707 if (object->IsGlobalObject()) { |
| 708 store_value = object->GetIsolate()->factory()->NewPropertyCell(value); | 708 store_value = object->GetIsolate()->factory()->NewPropertyCell(value); |
| 709 } | 709 } |
| 710 | 710 |
| 711 property_dictionary = NameDictionary::Add( | 711 property_dictionary = NameDictionary::Add( |
| 712 property_dictionary, name, store_value, details); | 712 property_dictionary, name, store_value, details); |
| 713 object->set_properties(*property_dictionary); | 713 object->set_properties(*property_dictionary); |
| 714 return; | 714 return; |
| 715 } | 715 } |
| 716 | 716 |
| 717 PropertyDetails original_details = property_dictionary->DetailsAt(entry); | 717 PropertyDetails original_details = property_dictionary->DetailsAt(entry); |
| 718 int enumeration_index; | 718 int enumeration_index; |
| 719 // Preserve the enumeration index unless the property was deleted. | 719 // Preserve the enumeration index unless the property was deleted. |
| 720 if (original_details.IsDeleted()) { | 720 if (original_details.IsDeleted()) { |
| 721 enumeration_index = property_dictionary->NextEnumerationIndex(); | 721 enumeration_index = property_dictionary->NextEnumerationIndex(); |
| 722 property_dictionary->SetNextEnumerationIndex(enumeration_index + 1); | 722 property_dictionary->SetNextEnumerationIndex(enumeration_index + 1); |
| 723 } else { | 723 } else { |
| 724 enumeration_index = original_details.dictionary_index(); | 724 enumeration_index = original_details.dictionary_index(); |
| 725 ASSERT(enumeration_index > 0); | 725 DCHECK(enumeration_index > 0); |
| 726 } | 726 } |
| 727 | 727 |
| 728 details = PropertyDetails( | 728 details = PropertyDetails( |
| 729 details.attributes(), details.type(), enumeration_index); | 729 details.attributes(), details.type(), enumeration_index); |
| 730 | 730 |
| 731 if (object->IsGlobalObject()) { | 731 if (object->IsGlobalObject()) { |
| 732 Handle<PropertyCell> cell( | 732 Handle<PropertyCell> cell( |
| 733 PropertyCell::cast(property_dictionary->ValueAt(entry))); | 733 PropertyCell::cast(property_dictionary->ValueAt(entry))); |
| 734 PropertyCell::SetValueInferType(cell, value); | 734 PropertyCell::SetValueInferType(cell, value); |
| 735 // Please note we have to update the property details. | 735 // Please note we have to update the property details. |
| 736 property_dictionary->DetailsAtPut(entry, details); | 736 property_dictionary->DetailsAtPut(entry, details); |
| 737 } else { | 737 } else { |
| 738 property_dictionary->SetEntry(entry, name, value, details); | 738 property_dictionary->SetEntry(entry, name, value, details); |
| 739 } | 739 } |
| 740 } | 740 } |
| 741 | 741 |
| 742 | 742 |
| 743 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object, | 743 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
| 744 Handle<Name> name, | 744 Handle<Name> name, |
| 745 DeleteMode mode) { | 745 DeleteMode mode) { |
| 746 ASSERT(!object->HasFastProperties()); | 746 DCHECK(!object->HasFastProperties()); |
| 747 Isolate* isolate = object->GetIsolate(); | 747 Isolate* isolate = object->GetIsolate(); |
| 748 Handle<NameDictionary> dictionary(object->property_dictionary()); | 748 Handle<NameDictionary> dictionary(object->property_dictionary()); |
| 749 int entry = dictionary->FindEntry(name); | 749 int entry = dictionary->FindEntry(name); |
| 750 if (entry != NameDictionary::kNotFound) { | 750 if (entry != NameDictionary::kNotFound) { |
| 751 // If we have a global object set the cell to the hole. | 751 // If we have a global object set the cell to the hole. |
| 752 if (object->IsGlobalObject()) { | 752 if (object->IsGlobalObject()) { |
| 753 PropertyDetails details = dictionary->DetailsAt(entry); | 753 PropertyDetails details = dictionary->DetailsAt(entry); |
| 754 if (details.IsDontDelete()) { | 754 if (details.IsDontDelete()) { |
| 755 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); | 755 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); |
| 756 // When forced to delete global properties, we have to make a | 756 // When forced to delete global properties, we have to make a |
| 757 // map change to invalidate any ICs that think they can load | 757 // map change to invalidate any ICs that think they can load |
| 758 // from the DontDelete cell without checking if it contains | 758 // from the DontDelete cell without checking if it contains |
| 759 // the hole value. | 759 // the hole value. |
| 760 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 760 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 761 ASSERT(new_map->is_dictionary_map()); | 761 DCHECK(new_map->is_dictionary_map()); |
| 762 JSObject::MigrateToMap(object, new_map); | 762 JSObject::MigrateToMap(object, new_map); |
| 763 } | 763 } |
| 764 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 764 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 765 Handle<Object> value = isolate->factory()->the_hole_value(); | 765 Handle<Object> value = isolate->factory()->the_hole_value(); |
| 766 PropertyCell::SetValueInferType(cell, value); | 766 PropertyCell::SetValueInferType(cell, value); |
| 767 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 767 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| 768 } else { | 768 } else { |
| 769 Handle<Object> deleted( | 769 Handle<Object> deleted( |
| 770 NameDictionary::DeleteProperty(dictionary, entry, mode)); | 770 NameDictionary::DeleteProperty(dictionary, entry, mode)); |
| 771 if (*deleted == isolate->heap()->true_value()) { | 771 if (*deleted == isolate->heap()->true_value()) { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 } | 892 } |
| 893 if (IsName()) { | 893 if (IsName()) { |
| 894 uint32_t hash = Name::cast(this)->Hash(); | 894 uint32_t hash = Name::cast(this)->Hash(); |
| 895 return Smi::FromInt(hash); | 895 return Smi::FromInt(hash); |
| 896 } | 896 } |
| 897 if (IsOddball()) { | 897 if (IsOddball()) { |
| 898 uint32_t hash = Oddball::cast(this)->to_string()->Hash(); | 898 uint32_t hash = Oddball::cast(this)->to_string()->Hash(); |
| 899 return Smi::FromInt(hash); | 899 return Smi::FromInt(hash); |
| 900 } | 900 } |
| 901 | 901 |
| 902 ASSERT(IsJSReceiver()); | 902 DCHECK(IsJSReceiver()); |
| 903 return JSReceiver::cast(this)->GetIdentityHash(); | 903 return JSReceiver::cast(this)->GetIdentityHash(); |
| 904 } | 904 } |
| 905 | 905 |
| 906 | 906 |
| 907 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) { | 907 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) { |
| 908 Handle<Object> hash(object->GetHash(), isolate); | 908 Handle<Object> hash(object->GetHash(), isolate); |
| 909 if (hash->IsSmi()) return Handle<Smi>::cast(hash); | 909 if (hash->IsSmi()) return Handle<Smi>::cast(hash); |
| 910 | 910 |
| 911 ASSERT(object->IsJSReceiver()); | 911 DCHECK(object->IsJSReceiver()); |
| 912 return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object)); | 912 return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object)); |
| 913 } | 913 } |
| 914 | 914 |
| 915 | 915 |
| 916 bool Object::SameValue(Object* other) { | 916 bool Object::SameValue(Object* other) { |
| 917 if (other == this) return true; | 917 if (other == this) return true; |
| 918 | 918 |
| 919 // The object is either a number, a name, an odd-ball, | 919 // The object is either a number, a name, an odd-ball, |
| 920 // a real JS object, or a Harmony proxy. | 920 // a real JS object, or a Harmony proxy. |
| 921 if (IsNumber() && other->IsNumber()) { | 921 if (IsNumber() && other->IsNumber()) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' || | 1002 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' || |
| 1003 c0 == 'S' || c0 == 'X')) { | 1003 c0 == 'S' || c0 == 'X')) { |
| 1004 return true; // An MP3File, an M. | 1004 return true; // An MP3File, an M. |
| 1005 } | 1005 } |
| 1006 return false; | 1006 return false; |
| 1007 } | 1007 } |
| 1008 | 1008 |
| 1009 | 1009 |
| 1010 Handle<String> String::SlowFlatten(Handle<ConsString> cons, | 1010 Handle<String> String::SlowFlatten(Handle<ConsString> cons, |
| 1011 PretenureFlag pretenure) { | 1011 PretenureFlag pretenure) { |
| 1012 ASSERT(AllowHeapAllocation::IsAllowed()); | 1012 DCHECK(AllowHeapAllocation::IsAllowed()); |
| 1013 ASSERT(cons->second()->length() != 0); | 1013 DCHECK(cons->second()->length() != 0); |
| 1014 Isolate* isolate = cons->GetIsolate(); | 1014 Isolate* isolate = cons->GetIsolate(); |
| 1015 int length = cons->length(); | 1015 int length = cons->length(); |
| 1016 PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure | 1016 PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure |
| 1017 : TENURED; | 1017 : TENURED; |
| 1018 Handle<SeqString> result; | 1018 Handle<SeqString> result; |
| 1019 if (cons->IsOneByteRepresentation()) { | 1019 if (cons->IsOneByteRepresentation()) { |
| 1020 Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString( | 1020 Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString( |
| 1021 length, tenure).ToHandleChecked(); | 1021 length, tenure).ToHandleChecked(); |
| 1022 DisallowHeapAllocation no_gc; | 1022 DisallowHeapAllocation no_gc; |
| 1023 WriteToFlat(*cons, flat->GetChars(), 0, length); | 1023 WriteToFlat(*cons, flat->GetChars(), 0, length); |
| 1024 result = flat; | 1024 result = flat; |
| 1025 } else { | 1025 } else { |
| 1026 Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString( | 1026 Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString( |
| 1027 length, tenure).ToHandleChecked(); | 1027 length, tenure).ToHandleChecked(); |
| 1028 DisallowHeapAllocation no_gc; | 1028 DisallowHeapAllocation no_gc; |
| 1029 WriteToFlat(*cons, flat->GetChars(), 0, length); | 1029 WriteToFlat(*cons, flat->GetChars(), 0, length); |
| 1030 result = flat; | 1030 result = flat; |
| 1031 } | 1031 } |
| 1032 cons->set_first(*result); | 1032 cons->set_first(*result); |
| 1033 cons->set_second(isolate->heap()->empty_string()); | 1033 cons->set_second(isolate->heap()->empty_string()); |
| 1034 ASSERT(result->IsFlat()); | 1034 DCHECK(result->IsFlat()); |
| 1035 return result; | 1035 return result; |
| 1036 } | 1036 } |
| 1037 | 1037 |
| 1038 | 1038 |
| 1039 | 1039 |
| 1040 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { | 1040 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { |
| 1041 // Externalizing twice leaks the external resource, so it's | 1041 // Externalizing twice leaks the external resource, so it's |
| 1042 // prohibited by the API. | 1042 // prohibited by the API. |
| 1043 ASSERT(!this->IsExternalString()); | 1043 DCHECK(!this->IsExternalString()); |
| 1044 #ifdef ENABLE_SLOW_ASSERTS | 1044 #ifdef ENABLE_SLOW_DCHECKS |
| 1045 if (FLAG_enable_slow_asserts) { | 1045 if (FLAG_enable_slow_asserts) { |
| 1046 // Assert that the resource and the string are equivalent. | 1046 // Assert that the resource and the string are equivalent. |
| 1047 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 1047 DCHECK(static_cast<size_t>(this->length()) == resource->length()); |
| 1048 ScopedVector<uc16> smart_chars(this->length()); | 1048 ScopedVector<uc16> smart_chars(this->length()); |
| 1049 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 1049 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 1050 ASSERT(memcmp(smart_chars.start(), | 1050 DCHECK(memcmp(smart_chars.start(), |
| 1051 resource->data(), | 1051 resource->data(), |
| 1052 resource->length() * sizeof(smart_chars[0])) == 0); | 1052 resource->length() * sizeof(smart_chars[0])) == 0); |
| 1053 } | 1053 } |
| 1054 #endif // DEBUG | 1054 #endif // DEBUG |
| 1055 Heap* heap = GetHeap(); | 1055 Heap* heap = GetHeap(); |
| 1056 int size = this->Size(); // Byte size of the original string. | 1056 int size = this->Size(); // Byte size of the original string. |
| 1057 if (size < ExternalString::kShortSize) { | 1057 if (size < ExternalString::kShortSize) { |
| 1058 return false; | 1058 return false; |
| 1059 } | 1059 } |
| 1060 bool is_ascii = this->IsOneByteRepresentation(); | 1060 bool is_ascii = this->IsOneByteRepresentation(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1102 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); | 1102 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); |
| 1103 self->set_resource(resource); | 1103 self->set_resource(resource); |
| 1104 if (is_internalized) self->Hash(); // Force regeneration of the hash value. | 1104 if (is_internalized) self->Hash(); // Force regeneration of the hash value. |
| 1105 | 1105 |
| 1106 heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR); | 1106 heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR); |
| 1107 return true; | 1107 return true; |
| 1108 } | 1108 } |
| 1109 | 1109 |
| 1110 | 1110 |
| 1111 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { | 1111 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { |
| 1112 #ifdef ENABLE_SLOW_ASSERTS | 1112 #ifdef ENABLE_SLOW_DCHECKS |
| 1113 if (FLAG_enable_slow_asserts) { | 1113 if (FLAG_enable_slow_asserts) { |
| 1114 // Assert that the resource and the string are equivalent. | 1114 // Assert that the resource and the string are equivalent. |
| 1115 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 1115 DCHECK(static_cast<size_t>(this->length()) == resource->length()); |
| 1116 if (this->IsTwoByteRepresentation()) { | 1116 if (this->IsTwoByteRepresentation()) { |
| 1117 ScopedVector<uint16_t> smart_chars(this->length()); | 1117 ScopedVector<uint16_t> smart_chars(this->length()); |
| 1118 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 1118 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 1119 ASSERT(String::IsOneByte(smart_chars.start(), this->length())); | 1119 DCHECK(String::IsOneByte(smart_chars.start(), this->length())); |
| 1120 } | 1120 } |
| 1121 ScopedVector<char> smart_chars(this->length()); | 1121 ScopedVector<char> smart_chars(this->length()); |
| 1122 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 1122 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 1123 ASSERT(memcmp(smart_chars.start(), | 1123 DCHECK(memcmp(smart_chars.start(), |
| 1124 resource->data(), | 1124 resource->data(), |
| 1125 resource->length() * sizeof(smart_chars[0])) == 0); | 1125 resource->length() * sizeof(smart_chars[0])) == 0); |
| 1126 } | 1126 } |
| 1127 #endif // DEBUG | 1127 #endif // DEBUG |
| 1128 Heap* heap = GetHeap(); | 1128 Heap* heap = GetHeap(); |
| 1129 int size = this->Size(); // Byte size of the original string. | 1129 int size = this->Size(); // Byte size of the original string. |
| 1130 if (size < ExternalString::kShortSize) { | 1130 if (size < ExternalString::kShortSize) { |
| 1131 return false; | 1131 return false; |
| 1132 } | 1132 } |
| 1133 bool is_internalized = this->IsInternalizedString(); | 1133 bool is_internalized = this->IsInternalizedString(); |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1769 return map()->constructor_name(); | 1769 return map()->constructor_name(); |
| 1770 } | 1770 } |
| 1771 | 1771 |
| 1772 | 1772 |
| 1773 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, | 1773 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, |
| 1774 Handle<Name> name, | 1774 Handle<Name> name, |
| 1775 Handle<HeapType> type, | 1775 Handle<HeapType> type, |
| 1776 PropertyAttributes attributes, | 1776 PropertyAttributes attributes, |
| 1777 Representation representation, | 1777 Representation representation, |
| 1778 TransitionFlag flag) { | 1778 TransitionFlag flag) { |
| 1779 ASSERT(DescriptorArray::kNotFound == | 1779 DCHECK(DescriptorArray::kNotFound == |
| 1780 map->instance_descriptors()->Search( | 1780 map->instance_descriptors()->Search( |
| 1781 *name, map->NumberOfOwnDescriptors())); | 1781 *name, map->NumberOfOwnDescriptors())); |
| 1782 | 1782 |
| 1783 // Ensure the descriptor array does not get too big. | 1783 // Ensure the descriptor array does not get too big. |
| 1784 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) { | 1784 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) { |
| 1785 return MaybeHandle<Map>(); | 1785 return MaybeHandle<Map>(); |
| 1786 } | 1786 } |
| 1787 | 1787 |
| 1788 Isolate* isolate = map->GetIsolate(); | 1788 Isolate* isolate = map->GetIsolate(); |
| 1789 | 1789 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1821 return Map::CopyAddDescriptor(map, &new_constant_desc, flag); | 1821 return Map::CopyAddDescriptor(map, &new_constant_desc, flag); |
| 1822 } | 1822 } |
| 1823 | 1823 |
| 1824 | 1824 |
| 1825 void JSObject::AddFastProperty(Handle<JSObject> object, | 1825 void JSObject::AddFastProperty(Handle<JSObject> object, |
| 1826 Handle<Name> name, | 1826 Handle<Name> name, |
| 1827 Handle<Object> value, | 1827 Handle<Object> value, |
| 1828 PropertyAttributes attributes, | 1828 PropertyAttributes attributes, |
| 1829 StoreFromKeyed store_mode, | 1829 StoreFromKeyed store_mode, |
| 1830 TransitionFlag flag) { | 1830 TransitionFlag flag) { |
| 1831 ASSERT(!object->IsJSGlobalProxy()); | 1831 DCHECK(!object->IsJSGlobalProxy()); |
| 1832 | 1832 |
| 1833 MaybeHandle<Map> maybe_map; | 1833 MaybeHandle<Map> maybe_map; |
| 1834 if (value->IsJSFunction()) { | 1834 if (value->IsJSFunction()) { |
| 1835 maybe_map = Map::CopyWithConstant( | 1835 maybe_map = Map::CopyWithConstant( |
| 1836 handle(object->map()), name, value, attributes, flag); | 1836 handle(object->map()), name, value, attributes, flag); |
| 1837 } else if (!object->map()->TooManyFastProperties(store_mode)) { | 1837 } else if (!object->map()->TooManyFastProperties(store_mode)) { |
| 1838 Isolate* isolate = object->GetIsolate(); | 1838 Isolate* isolate = object->GetIsolate(); |
| 1839 Representation representation = value->OptimalRepresentation(); | 1839 Representation representation = value->OptimalRepresentation(); |
| 1840 maybe_map = Map::CopyWithField( | 1840 maybe_map = Map::CopyWithField( |
| 1841 handle(object->map(), isolate), name, | 1841 handle(object->map(), isolate), name, |
| 1842 value->OptimalType(isolate, representation), | 1842 value->OptimalType(isolate, representation), |
| 1843 attributes, representation, flag); | 1843 attributes, representation, flag); |
| 1844 } | 1844 } |
| 1845 | 1845 |
| 1846 Handle<Map> new_map; | 1846 Handle<Map> new_map; |
| 1847 if (!maybe_map.ToHandle(&new_map)) { | 1847 if (!maybe_map.ToHandle(&new_map)) { |
| 1848 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 1848 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 1849 return; | 1849 return; |
| 1850 } | 1850 } |
| 1851 | 1851 |
| 1852 JSObject::MigrateToNewProperty(object, new_map, value); | 1852 JSObject::MigrateToNewProperty(object, new_map, value); |
| 1853 } | 1853 } |
| 1854 | 1854 |
| 1855 | 1855 |
| 1856 void JSObject::AddSlowProperty(Handle<JSObject> object, | 1856 void JSObject::AddSlowProperty(Handle<JSObject> object, |
| 1857 Handle<Name> name, | 1857 Handle<Name> name, |
| 1858 Handle<Object> value, | 1858 Handle<Object> value, |
| 1859 PropertyAttributes attributes) { | 1859 PropertyAttributes attributes) { |
| 1860 ASSERT(!object->HasFastProperties()); | 1860 DCHECK(!object->HasFastProperties()); |
| 1861 Isolate* isolate = object->GetIsolate(); | 1861 Isolate* isolate = object->GetIsolate(); |
| 1862 Handle<NameDictionary> dict(object->property_dictionary()); | 1862 Handle<NameDictionary> dict(object->property_dictionary()); |
| 1863 if (object->IsGlobalObject()) { | 1863 if (object->IsGlobalObject()) { |
| 1864 // In case name is an orphaned property reuse the cell. | 1864 // In case name is an orphaned property reuse the cell. |
| 1865 int entry = dict->FindEntry(name); | 1865 int entry = dict->FindEntry(name); |
| 1866 if (entry != NameDictionary::kNotFound) { | 1866 if (entry != NameDictionary::kNotFound) { |
| 1867 Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry))); | 1867 Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry))); |
| 1868 PropertyCell::SetValueInferType(cell, value); | 1868 PropertyCell::SetValueInferType(cell, value); |
| 1869 // Assign an enumeration index to the property and update | 1869 // Assign an enumeration index to the property and update |
| 1870 // SetNextEnumerationIndex. | 1870 // SetNextEnumerationIndex. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1882 Handle<NameDictionary> result = | 1882 Handle<NameDictionary> result = |
| 1883 NameDictionary::Add(dict, name, value, details); | 1883 NameDictionary::Add(dict, name, value, details); |
| 1884 if (*dict != *result) object->set_properties(*result); | 1884 if (*dict != *result) object->set_properties(*result); |
| 1885 } | 1885 } |
| 1886 | 1886 |
| 1887 | 1887 |
| 1888 MaybeHandle<Object> JSObject::AddPropertyInternal( | 1888 MaybeHandle<Object> JSObject::AddPropertyInternal( |
| 1889 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, | 1889 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, |
| 1890 PropertyAttributes attributes, JSReceiver::StoreFromKeyed store_mode, | 1890 PropertyAttributes attributes, JSReceiver::StoreFromKeyed store_mode, |
| 1891 ExtensibilityCheck extensibility_check, TransitionFlag transition_flag) { | 1891 ExtensibilityCheck extensibility_check, TransitionFlag transition_flag) { |
| 1892 ASSERT(!object->IsJSGlobalProxy()); | 1892 DCHECK(!object->IsJSGlobalProxy()); |
| 1893 Isolate* isolate = object->GetIsolate(); | 1893 Isolate* isolate = object->GetIsolate(); |
| 1894 | 1894 |
| 1895 if (!name->IsUniqueName()) { | 1895 if (!name->IsUniqueName()) { |
| 1896 name = isolate->factory()->InternalizeString( | 1896 name = isolate->factory()->InternalizeString( |
| 1897 Handle<String>::cast(name)); | 1897 Handle<String>::cast(name)); |
| 1898 } | 1898 } |
| 1899 | 1899 |
| 1900 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && | 1900 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && |
| 1901 !object->map()->is_extensible()) { | 1901 !object->map()->is_extensible()) { |
| 1902 Handle<Object> args[1] = {name}; | 1902 Handle<Object> args[1] = {name}; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1936 } | 1936 } |
| 1937 | 1937 |
| 1938 return function->context()->native_context(); | 1938 return function->context()->native_context(); |
| 1939 } | 1939 } |
| 1940 | 1940 |
| 1941 | 1941 |
| 1942 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 1942 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
| 1943 const char* type_str, | 1943 const char* type_str, |
| 1944 Handle<Name> name, | 1944 Handle<Name> name, |
| 1945 Handle<Object> old_value) { | 1945 Handle<Object> old_value) { |
| 1946 ASSERT(!object->IsJSGlobalProxy()); | 1946 DCHECK(!object->IsJSGlobalProxy()); |
| 1947 ASSERT(!object->IsJSGlobalObject()); | 1947 DCHECK(!object->IsJSGlobalObject()); |
| 1948 Isolate* isolate = object->GetIsolate(); | 1948 Isolate* isolate = object->GetIsolate(); |
| 1949 HandleScope scope(isolate); | 1949 HandleScope scope(isolate); |
| 1950 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); | 1950 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); |
| 1951 Handle<Object> args[] = { type, object, name, old_value }; | 1951 Handle<Object> args[] = { type, object, name, old_value }; |
| 1952 int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4; | 1952 int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4; |
| 1953 | 1953 |
| 1954 Execution::Call(isolate, | 1954 Execution::Call(isolate, |
| 1955 Handle<JSFunction>(isolate->observers_notify_change()), | 1955 Handle<JSFunction>(isolate->observers_notify_change()), |
| 1956 isolate->factory()->undefined_value(), | 1956 isolate->factory()->undefined_value(), |
| 1957 argc, args).Assert(); | 1957 argc, args).Assert(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1996 Object** zap = reinterpret_cast<Object**>(new_end); | 1996 Object** zap = reinterpret_cast<Object**>(new_end); |
| 1997 zap++; // Header of filler must be at least one word so skip that. | 1997 zap++; // Header of filler must be at least one word so skip that. |
| 1998 for (int i = 1; i < to_trim; i++) { | 1998 for (int i = 1; i < to_trim; i++) { |
| 1999 *zap++ = Smi::FromInt(0); | 1999 *zap++ = Smi::FromInt(0); |
| 2000 } | 2000 } |
| 2001 } | 2001 } |
| 2002 | 2002 |
| 2003 | 2003 |
| 2004 template<Heap::InvocationMode mode> | 2004 template<Heap::InvocationMode mode> |
| 2005 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) { | 2005 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) { |
| 2006 ASSERT(elms->map() != heap->fixed_cow_array_map()); | 2006 DCHECK(elms->map() != heap->fixed_cow_array_map()); |
| 2007 // For now this trick is only applied to fixed arrays in new and paged space. | 2007 // For now this trick is only applied to fixed arrays in new and paged space. |
| 2008 ASSERT(!heap->lo_space()->Contains(elms)); | 2008 DCHECK(!heap->lo_space()->Contains(elms)); |
| 2009 | 2009 |
| 2010 const int len = elms->length(); | 2010 const int len = elms->length(); |
| 2011 | 2011 |
| 2012 ASSERT(to_trim < len); | 2012 DCHECK(to_trim < len); |
| 2013 | 2013 |
| 2014 Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim); | 2014 Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim); |
| 2015 | 2015 |
| 2016 if (mode != Heap::FROM_GC || Heap::ShouldZapGarbage()) { | 2016 if (mode != Heap::FROM_GC || Heap::ShouldZapGarbage()) { |
| 2017 ZapEndOfFixedArray(new_end, to_trim); | 2017 ZapEndOfFixedArray(new_end, to_trim); |
| 2018 } | 2018 } |
| 2019 | 2019 |
| 2020 int size_delta = to_trim * kPointerSize; | 2020 int size_delta = to_trim * kPointerSize; |
| 2021 | 2021 |
| 2022 // Technically in new space this write might be omitted (except for | 2022 // Technically in new space this write might be omitted (except for |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2037 profiler->UpdateObjectSizeEvent(elms->address(), elms->Size()); | 2037 profiler->UpdateObjectSizeEvent(elms->address(), elms->Size()); |
| 2038 } | 2038 } |
| 2039 } | 2039 } |
| 2040 | 2040 |
| 2041 | 2041 |
| 2042 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields, | 2042 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields, |
| 2043 int target_inobject, int target_unused, | 2043 int target_inobject, int target_unused, |
| 2044 int* old_number_of_fields) { | 2044 int* old_number_of_fields) { |
| 2045 // If fields were added (or removed), rewrite the instance. | 2045 // If fields were added (or removed), rewrite the instance. |
| 2046 *old_number_of_fields = NumberOfFields(); | 2046 *old_number_of_fields = NumberOfFields(); |
| 2047 ASSERT(target_number_of_fields >= *old_number_of_fields); | 2047 DCHECK(target_number_of_fields >= *old_number_of_fields); |
| 2048 if (target_number_of_fields != *old_number_of_fields) return true; | 2048 if (target_number_of_fields != *old_number_of_fields) return true; |
| 2049 | 2049 |
| 2050 // If smi descriptors were replaced by double descriptors, rewrite. | 2050 // If smi descriptors were replaced by double descriptors, rewrite. |
| 2051 DescriptorArray* old_desc = instance_descriptors(); | 2051 DescriptorArray* old_desc = instance_descriptors(); |
| 2052 DescriptorArray* new_desc = target->instance_descriptors(); | 2052 DescriptorArray* new_desc = target->instance_descriptors(); |
| 2053 int limit = NumberOfOwnDescriptors(); | 2053 int limit = NumberOfOwnDescriptors(); |
| 2054 for (int i = 0; i < limit; i++) { | 2054 for (int i = 0; i < limit; i++) { |
| 2055 if (new_desc->GetDetails(i).representation().IsDouble() != | 2055 if (new_desc->GetDetails(i).representation().IsDouble() != |
| 2056 old_desc->GetDetails(i).representation().IsDouble()) { | 2056 old_desc->GetDetails(i).representation().IsDouble()) { |
| 2057 return true; | 2057 return true; |
| 2058 } | 2058 } |
| 2059 } | 2059 } |
| 2060 | 2060 |
| 2061 // If no fields were added, and no inobject properties were removed, setting | 2061 // If no fields were added, and no inobject properties were removed, setting |
| 2062 // the map is sufficient. | 2062 // the map is sufficient. |
| 2063 if (target_inobject == inobject_properties()) return false; | 2063 if (target_inobject == inobject_properties()) return false; |
| 2064 // In-object slack tracking may have reduced the object size of the new map. | 2064 // In-object slack tracking may have reduced the object size of the new map. |
| 2065 // In that case, succeed if all existing fields were inobject, and they still | 2065 // In that case, succeed if all existing fields were inobject, and they still |
| 2066 // fit within the new inobject size. | 2066 // fit within the new inobject size. |
| 2067 ASSERT(target_inobject < inobject_properties()); | 2067 DCHECK(target_inobject < inobject_properties()); |
| 2068 if (target_number_of_fields <= target_inobject) { | 2068 if (target_number_of_fields <= target_inobject) { |
| 2069 ASSERT(target_number_of_fields + target_unused == target_inobject); | 2069 DCHECK(target_number_of_fields + target_unused == target_inobject); |
| 2070 return false; | 2070 return false; |
| 2071 } | 2071 } |
| 2072 // Otherwise, properties will need to be moved to the backing store. | 2072 // Otherwise, properties will need to be moved to the backing store. |
| 2073 return true; | 2073 return true; |
| 2074 } | 2074 } |
| 2075 | 2075 |
| 2076 | 2076 |
| 2077 Handle<TransitionArray> Map::SetElementsTransitionMap( | 2077 Handle<TransitionArray> Map::SetElementsTransitionMap( |
| 2078 Handle<Map> map, Handle<Map> transitioned_map) { | 2078 Handle<Map> map, Handle<Map> transitioned_map) { |
| 2079 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( | 2079 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2135 object->synchronized_set_map(*new_map); | 2135 object->synchronized_set_map(*new_map); |
| 2136 return; | 2136 return; |
| 2137 } | 2137 } |
| 2138 | 2138 |
| 2139 int total_size = number_of_fields + unused; | 2139 int total_size = number_of_fields + unused; |
| 2140 int external = total_size - inobject; | 2140 int external = total_size - inobject; |
| 2141 | 2141 |
| 2142 if ((old_map->unused_property_fields() == 0) && | 2142 if ((old_map->unused_property_fields() == 0) && |
| 2143 (number_of_fields != old_number_of_fields) && | 2143 (number_of_fields != old_number_of_fields) && |
| 2144 (new_map->GetBackPointer() == *old_map)) { | 2144 (new_map->GetBackPointer() == *old_map)) { |
| 2145 ASSERT(number_of_fields == old_number_of_fields + 1); | 2145 DCHECK(number_of_fields == old_number_of_fields + 1); |
| 2146 // This migration is a transition from a map that has run out out property | 2146 // This migration is a transition from a map that has run out out property |
| 2147 // space. Therefore it could be done by extending the backing store. | 2147 // space. Therefore it could be done by extending the backing store. |
| 2148 Handle<FixedArray> old_storage = handle(object->properties(), isolate); | 2148 Handle<FixedArray> old_storage = handle(object->properties(), isolate); |
| 2149 Handle<FixedArray> new_storage = | 2149 Handle<FixedArray> new_storage = |
| 2150 FixedArray::CopySize(old_storage, external); | 2150 FixedArray::CopySize(old_storage, external); |
| 2151 | 2151 |
| 2152 // Properly initialize newly added property. | 2152 // Properly initialize newly added property. |
| 2153 PropertyDetails details = new_map->GetLastDescriptorDetails(); | 2153 PropertyDetails details = new_map->GetLastDescriptorDetails(); |
| 2154 Handle<Object> value; | 2154 Handle<Object> value; |
| 2155 if (details.representation().IsDouble()) { | 2155 if (details.representation().IsDouble()) { |
| 2156 value = isolate->factory()->NewHeapNumber(0, MUTABLE); | 2156 value = isolate->factory()->NewHeapNumber(0, MUTABLE); |
| 2157 } else { | 2157 } else { |
| 2158 value = isolate->factory()->uninitialized_value(); | 2158 value = isolate->factory()->uninitialized_value(); |
| 2159 } | 2159 } |
| 2160 ASSERT(details.type() == FIELD); | 2160 DCHECK(details.type() == FIELD); |
| 2161 int target_index = details.field_index() - inobject; | 2161 int target_index = details.field_index() - inobject; |
| 2162 ASSERT(target_index >= 0); // Must be a backing store index. | 2162 DCHECK(target_index >= 0); // Must be a backing store index. |
| 2163 new_storage->set(target_index, *value); | 2163 new_storage->set(target_index, *value); |
| 2164 | 2164 |
| 2165 // From here on we cannot fail and we shouldn't GC anymore. | 2165 // From here on we cannot fail and we shouldn't GC anymore. |
| 2166 DisallowHeapAllocation no_allocation; | 2166 DisallowHeapAllocation no_allocation; |
| 2167 | 2167 |
| 2168 // Set the new property value and do the map transition. | 2168 // Set the new property value and do the map transition. |
| 2169 object->set_properties(*new_storage); | 2169 object->set_properties(*new_storage); |
| 2170 object->synchronized_set_map(*new_map); | 2170 object->synchronized_set_map(*new_map); |
| 2171 return; | 2171 return; |
| 2172 } | 2172 } |
| 2173 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); | 2173 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); |
| 2174 | 2174 |
| 2175 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); | 2175 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
| 2176 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); | 2176 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); |
| 2177 int old_nof = old_map->NumberOfOwnDescriptors(); | 2177 int old_nof = old_map->NumberOfOwnDescriptors(); |
| 2178 int new_nof = new_map->NumberOfOwnDescriptors(); | 2178 int new_nof = new_map->NumberOfOwnDescriptors(); |
| 2179 | 2179 |
| 2180 // This method only supports generalizing instances to at least the same | 2180 // This method only supports generalizing instances to at least the same |
| 2181 // number of properties. | 2181 // number of properties. |
| 2182 ASSERT(old_nof <= new_nof); | 2182 DCHECK(old_nof <= new_nof); |
| 2183 | 2183 |
| 2184 for (int i = 0; i < old_nof; i++) { | 2184 for (int i = 0; i < old_nof; i++) { |
| 2185 PropertyDetails details = new_descriptors->GetDetails(i); | 2185 PropertyDetails details = new_descriptors->GetDetails(i); |
| 2186 if (details.type() != FIELD) continue; | 2186 if (details.type() != FIELD) continue; |
| 2187 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2187 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2188 if (old_details.type() == CALLBACKS) { | 2188 if (old_details.type() == CALLBACKS) { |
| 2189 ASSERT(details.representation().IsTagged()); | 2189 DCHECK(details.representation().IsTagged()); |
| 2190 continue; | 2190 continue; |
| 2191 } | 2191 } |
| 2192 ASSERT(old_details.type() == CONSTANT || | 2192 DCHECK(old_details.type() == CONSTANT || |
| 2193 old_details.type() == FIELD); | 2193 old_details.type() == FIELD); |
| 2194 Object* raw_value = old_details.type() == CONSTANT | 2194 Object* raw_value = old_details.type() == CONSTANT |
| 2195 ? old_descriptors->GetValue(i) | 2195 ? old_descriptors->GetValue(i) |
| 2196 : object->RawFastPropertyAt(FieldIndex::ForDescriptor(*old_map, i)); | 2196 : object->RawFastPropertyAt(FieldIndex::ForDescriptor(*old_map, i)); |
| 2197 Handle<Object> value(raw_value, isolate); | 2197 Handle<Object> value(raw_value, isolate); |
| 2198 if (!old_details.representation().IsDouble() && | 2198 if (!old_details.representation().IsDouble() && |
| 2199 details.representation().IsDouble()) { | 2199 details.representation().IsDouble()) { |
| 2200 if (old_details.representation().IsNone()) { | 2200 if (old_details.representation().IsNone()) { |
| 2201 value = handle(Smi::FromInt(0), isolate); | 2201 value = handle(Smi::FromInt(0), isolate); |
| 2202 } | 2202 } |
| 2203 value = Object::NewStorageFor(isolate, value, details.representation()); | 2203 value = Object::NewStorageFor(isolate, value, details.representation()); |
| 2204 } else if (old_details.representation().IsDouble() && | 2204 } else if (old_details.representation().IsDouble() && |
| 2205 !details.representation().IsDouble()) { | 2205 !details.representation().IsDouble()) { |
| 2206 value = Object::WrapForRead(isolate, value, old_details.representation()); | 2206 value = Object::WrapForRead(isolate, value, old_details.representation()); |
| 2207 } | 2207 } |
| 2208 ASSERT(!(details.representation().IsDouble() && value->IsSmi())); | 2208 DCHECK(!(details.representation().IsDouble() && value->IsSmi())); |
| 2209 int target_index = new_descriptors->GetFieldIndex(i) - inobject; | 2209 int target_index = new_descriptors->GetFieldIndex(i) - inobject; |
| 2210 if (target_index < 0) target_index += total_size; | 2210 if (target_index < 0) target_index += total_size; |
| 2211 array->set(target_index, *value); | 2211 array->set(target_index, *value); |
| 2212 } | 2212 } |
| 2213 | 2213 |
| 2214 for (int i = old_nof; i < new_nof; i++) { | 2214 for (int i = old_nof; i < new_nof; i++) { |
| 2215 PropertyDetails details = new_descriptors->GetDetails(i); | 2215 PropertyDetails details = new_descriptors->GetDetails(i); |
| 2216 if (details.type() != FIELD) continue; | 2216 if (details.type() != FIELD) continue; |
| 2217 Handle<Object> value; | 2217 Handle<Object> value; |
| 2218 if (details.representation().IsDouble()) { | 2218 if (details.representation().IsDouble()) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2241 // If there are properties in the new backing store, trim it to the correct | 2241 // If there are properties in the new backing store, trim it to the correct |
| 2242 // size and install the backing store into the object. | 2242 // size and install the backing store into the object. |
| 2243 if (external > 0) { | 2243 if (external > 0) { |
| 2244 RightTrimFixedArray<Heap::FROM_MUTATOR>(heap, *array, inobject); | 2244 RightTrimFixedArray<Heap::FROM_MUTATOR>(heap, *array, inobject); |
| 2245 object->set_properties(*array); | 2245 object->set_properties(*array); |
| 2246 } | 2246 } |
| 2247 | 2247 |
| 2248 // Create filler object past the new instance size. | 2248 // Create filler object past the new instance size. |
| 2249 int new_instance_size = new_map->instance_size(); | 2249 int new_instance_size = new_map->instance_size(); |
| 2250 int instance_size_delta = old_map->instance_size() - new_instance_size; | 2250 int instance_size_delta = old_map->instance_size() - new_instance_size; |
| 2251 ASSERT(instance_size_delta >= 0); | 2251 DCHECK(instance_size_delta >= 0); |
| 2252 | 2252 |
| 2253 if (instance_size_delta > 0) { | 2253 if (instance_size_delta > 0) { |
| 2254 Address address = object->address(); | 2254 Address address = object->address(); |
| 2255 heap->CreateFillerObjectAt( | 2255 heap->CreateFillerObjectAt( |
| 2256 address + new_instance_size, instance_size_delta); | 2256 address + new_instance_size, instance_size_delta); |
| 2257 heap->AdjustLiveBytes(address, -instance_size_delta, Heap::FROM_MUTATOR); | 2257 heap->AdjustLiveBytes(address, -instance_size_delta, Heap::FROM_MUTATOR); |
| 2258 } | 2258 } |
| 2259 | 2259 |
| 2260 // We are storing the new map using release store after creating a filler for | 2260 // We are storing the new map using release store after creating a filler for |
| 2261 // the left-over space to avoid races with the sweeper thread. | 2261 // the left-over space to avoid races with the sweeper thread. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2311 field_index, attributes, Representation::Tagged()); | 2311 field_index, attributes, Representation::Tagged()); |
| 2312 descriptors->Replace(modify_index, &d); | 2312 descriptors->Replace(modify_index, &d); |
| 2313 if (details.type() != FIELD) { | 2313 if (details.type() != FIELD) { |
| 2314 int unused_property_fields = new_map->unused_property_fields() - 1; | 2314 int unused_property_fields = new_map->unused_property_fields() - 1; |
| 2315 if (unused_property_fields < 0) { | 2315 if (unused_property_fields < 0) { |
| 2316 unused_property_fields += JSObject::kFieldsAdded; | 2316 unused_property_fields += JSObject::kFieldsAdded; |
| 2317 } | 2317 } |
| 2318 new_map->set_unused_property_fields(unused_property_fields); | 2318 new_map->set_unused_property_fields(unused_property_fields); |
| 2319 } | 2319 } |
| 2320 } else { | 2320 } else { |
| 2321 ASSERT(details.attributes() == attributes); | 2321 DCHECK(details.attributes() == attributes); |
| 2322 } | 2322 } |
| 2323 | 2323 |
| 2324 if (FLAG_trace_generalization) { | 2324 if (FLAG_trace_generalization) { |
| 2325 HeapType* field_type = (details.type() == FIELD) | 2325 HeapType* field_type = (details.type() == FIELD) |
| 2326 ? map->instance_descriptors()->GetFieldType(modify_index) | 2326 ? map->instance_descriptors()->GetFieldType(modify_index) |
| 2327 : NULL; | 2327 : NULL; |
| 2328 map->PrintGeneralization(stdout, reason, modify_index, | 2328 map->PrintGeneralization(stdout, reason, modify_index, |
| 2329 new_map->NumberOfOwnDescriptors(), | 2329 new_map->NumberOfOwnDescriptors(), |
| 2330 new_map->NumberOfOwnDescriptors(), | 2330 new_map->NumberOfOwnDescriptors(), |
| 2331 details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2331 details.type() == CONSTANT && store_mode == FORCE_FIELD, |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2402 } | 2402 } |
| 2403 } | 2403 } |
| 2404 | 2404 |
| 2405 | 2405 |
| 2406 Map* Map::FindLastMatchMap(int verbatim, | 2406 Map* Map::FindLastMatchMap(int verbatim, |
| 2407 int length, | 2407 int length, |
| 2408 DescriptorArray* descriptors) { | 2408 DescriptorArray* descriptors) { |
| 2409 DisallowHeapAllocation no_allocation; | 2409 DisallowHeapAllocation no_allocation; |
| 2410 | 2410 |
| 2411 // This can only be called on roots of transition trees. | 2411 // This can only be called on roots of transition trees. |
| 2412 ASSERT(GetBackPointer()->IsUndefined()); | 2412 DCHECK(GetBackPointer()->IsUndefined()); |
| 2413 | 2413 |
| 2414 Map* current = this; | 2414 Map* current = this; |
| 2415 | 2415 |
| 2416 for (int i = verbatim; i < length; i++) { | 2416 for (int i = verbatim; i < length; i++) { |
| 2417 if (!current->HasTransitionArray()) break; | 2417 if (!current->HasTransitionArray()) break; |
| 2418 Name* name = descriptors->GetKey(i); | 2418 Name* name = descriptors->GetKey(i); |
| 2419 TransitionArray* transitions = current->transitions(); | 2419 TransitionArray* transitions = current->transitions(); |
| 2420 int transition = transitions->Search(name); | 2420 int transition = transitions->Search(name); |
| 2421 if (transition == TransitionArray::kNotFound) break; | 2421 if (transition == TransitionArray::kNotFound) break; |
| 2422 | 2422 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2436 } | 2436 } |
| 2437 | 2437 |
| 2438 current = next; | 2438 current = next; |
| 2439 } | 2439 } |
| 2440 return current; | 2440 return current; |
| 2441 } | 2441 } |
| 2442 | 2442 |
| 2443 | 2443 |
| 2444 Map* Map::FindFieldOwner(int descriptor) { | 2444 Map* Map::FindFieldOwner(int descriptor) { |
| 2445 DisallowHeapAllocation no_allocation; | 2445 DisallowHeapAllocation no_allocation; |
| 2446 ASSERT_EQ(FIELD, instance_descriptors()->GetDetails(descriptor).type()); | 2446 DCHECK_EQ(FIELD, instance_descriptors()->GetDetails(descriptor).type()); |
| 2447 Map* result = this; | 2447 Map* result = this; |
| 2448 while (true) { | 2448 while (true) { |
| 2449 Object* back = result->GetBackPointer(); | 2449 Object* back = result->GetBackPointer(); |
| 2450 if (back->IsUndefined()) break; | 2450 if (back->IsUndefined()) break; |
| 2451 Map* parent = Map::cast(back); | 2451 Map* parent = Map::cast(back); |
| 2452 if (parent->NumberOfOwnDescriptors() <= descriptor) break; | 2452 if (parent->NumberOfOwnDescriptors() <= descriptor) break; |
| 2453 result = parent; | 2453 result = parent; |
| 2454 } | 2454 } |
| 2455 return result; | 2455 return result; |
| 2456 } | 2456 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2478 // static | 2478 // static |
| 2479 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1, | 2479 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1, |
| 2480 Handle<HeapType> type2, | 2480 Handle<HeapType> type2, |
| 2481 Isolate* isolate) { | 2481 Isolate* isolate) { |
| 2482 static const int kMaxClassesPerFieldType = 5; | 2482 static const int kMaxClassesPerFieldType = 5; |
| 2483 if (type1->NowIs(type2)) return type2; | 2483 if (type1->NowIs(type2)) return type2; |
| 2484 if (type2->NowIs(type1)) return type1; | 2484 if (type2->NowIs(type1)) return type1; |
| 2485 if (type1->NowStable() && type2->NowStable()) { | 2485 if (type1->NowStable() && type2->NowStable()) { |
| 2486 Handle<HeapType> type = HeapType::Union(type1, type2, isolate); | 2486 Handle<HeapType> type = HeapType::Union(type1, type2, isolate); |
| 2487 if (type->NumClasses() <= kMaxClassesPerFieldType) { | 2487 if (type->NumClasses() <= kMaxClassesPerFieldType) { |
| 2488 ASSERT(type->NowStable()); | 2488 DCHECK(type->NowStable()); |
| 2489 ASSERT(type1->NowIs(type)); | 2489 DCHECK(type1->NowIs(type)); |
| 2490 ASSERT(type2->NowIs(type)); | 2490 DCHECK(type2->NowIs(type)); |
| 2491 return type; | 2491 return type; |
| 2492 } | 2492 } |
| 2493 } | 2493 } |
| 2494 return HeapType::Any(isolate); | 2494 return HeapType::Any(isolate); |
| 2495 } | 2495 } |
| 2496 | 2496 |
| 2497 | 2497 |
| 2498 // static | 2498 // static |
| 2499 void Map::GeneralizeFieldType(Handle<Map> map, | 2499 void Map::GeneralizeFieldType(Handle<Map> map, |
| 2500 int modify_index, | 2500 int modify_index, |
| 2501 Handle<HeapType> new_field_type) { | 2501 Handle<HeapType> new_field_type) { |
| 2502 Isolate* isolate = map->GetIsolate(); | 2502 Isolate* isolate = map->GetIsolate(); |
| 2503 | 2503 |
| 2504 // Check if we actually need to generalize the field type at all. | 2504 // Check if we actually need to generalize the field type at all. |
| 2505 Handle<HeapType> old_field_type( | 2505 Handle<HeapType> old_field_type( |
| 2506 map->instance_descriptors()->GetFieldType(modify_index), isolate); | 2506 map->instance_descriptors()->GetFieldType(modify_index), isolate); |
| 2507 if (new_field_type->NowIs(old_field_type)) { | 2507 if (new_field_type->NowIs(old_field_type)) { |
| 2508 ASSERT(Map::GeneralizeFieldType(old_field_type, | 2508 DCHECK(Map::GeneralizeFieldType(old_field_type, |
| 2509 new_field_type, | 2509 new_field_type, |
| 2510 isolate)->NowIs(old_field_type)); | 2510 isolate)->NowIs(old_field_type)); |
| 2511 return; | 2511 return; |
| 2512 } | 2512 } |
| 2513 | 2513 |
| 2514 // Determine the field owner. | 2514 // Determine the field owner. |
| 2515 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); | 2515 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); |
| 2516 Handle<DescriptorArray> descriptors( | 2516 Handle<DescriptorArray> descriptors( |
| 2517 field_owner->instance_descriptors(), isolate); | 2517 field_owner->instance_descriptors(), isolate); |
| 2518 ASSERT_EQ(*old_field_type, descriptors->GetFieldType(modify_index)); | 2518 DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index)); |
| 2519 | 2519 |
| 2520 // Determine the generalized new field type. | 2520 // Determine the generalized new field type. |
| 2521 new_field_type = Map::GeneralizeFieldType( | 2521 new_field_type = Map::GeneralizeFieldType( |
| 2522 old_field_type, new_field_type, isolate); | 2522 old_field_type, new_field_type, isolate); |
| 2523 | 2523 |
| 2524 PropertyDetails details = descriptors->GetDetails(modify_index); | 2524 PropertyDetails details = descriptors->GetDetails(modify_index); |
| 2525 Handle<Name> name(descriptors->GetKey(modify_index)); | 2525 Handle<Name> name(descriptors->GetKey(modify_index)); |
| 2526 field_owner->UpdateFieldType(modify_index, name, new_field_type); | 2526 field_owner->UpdateFieldType(modify_index, name, new_field_type); |
| 2527 field_owner->dependent_code()->DeoptimizeDependentCodeGroup( | 2527 field_owner->dependent_code()->DeoptimizeDependentCodeGroup( |
| 2528 isolate, DependentCode::kFieldTypeGroup); | 2528 isolate, DependentCode::kFieldTypeGroup); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2570 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2570 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2571 Representation old_representation = old_details.representation(); | 2571 Representation old_representation = old_details.representation(); |
| 2572 | 2572 |
| 2573 // It's fine to transition from None to anything but double without any | 2573 // It's fine to transition from None to anything but double without any |
| 2574 // modification to the object, because the default uninitialized value for | 2574 // modification to the object, because the default uninitialized value for |
| 2575 // representation None can be overwritten by both smi and tagged values. | 2575 // representation None can be overwritten by both smi and tagged values. |
| 2576 // Doubles, however, would require a box allocation. | 2576 // Doubles, however, would require a box allocation. |
| 2577 if (old_representation.IsNone() && | 2577 if (old_representation.IsNone() && |
| 2578 !new_representation.IsNone() && | 2578 !new_representation.IsNone() && |
| 2579 !new_representation.IsDouble()) { | 2579 !new_representation.IsDouble()) { |
| 2580 ASSERT(old_details.type() == FIELD); | 2580 DCHECK(old_details.type() == FIELD); |
| 2581 ASSERT(old_descriptors->GetFieldType(modify_index)->NowIs( | 2581 DCHECK(old_descriptors->GetFieldType(modify_index)->NowIs( |
| 2582 HeapType::None())); | 2582 HeapType::None())); |
| 2583 if (FLAG_trace_generalization) { | 2583 if (FLAG_trace_generalization) { |
| 2584 old_map->PrintGeneralization( | 2584 old_map->PrintGeneralization( |
| 2585 stdout, "uninitialized field", | 2585 stdout, "uninitialized field", |
| 2586 modify_index, old_map->NumberOfOwnDescriptors(), | 2586 modify_index, old_map->NumberOfOwnDescriptors(), |
| 2587 old_map->NumberOfOwnDescriptors(), false, | 2587 old_map->NumberOfOwnDescriptors(), false, |
| 2588 old_representation, new_representation, | 2588 old_representation, new_representation, |
| 2589 old_descriptors->GetFieldType(modify_index), *new_field_type); | 2589 old_descriptors->GetFieldType(modify_index), *new_field_type); |
| 2590 } | 2590 } |
| 2591 old_descriptors->SetRepresentation(modify_index, new_representation); | 2591 old_descriptors->SetRepresentation(modify_index, new_representation); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2648 old_field_type = GeneralizeFieldType( | 2648 old_field_type = GeneralizeFieldType( |
| 2649 new_field_type, old_field_type, isolate); | 2649 new_field_type, old_field_type, isolate); |
| 2650 } | 2650 } |
| 2651 GeneralizeFieldType(tmp_map, i, old_field_type); | 2651 GeneralizeFieldType(tmp_map, i, old_field_type); |
| 2652 } else if (tmp_type == CONSTANT) { | 2652 } else if (tmp_type == CONSTANT) { |
| 2653 if (old_type != CONSTANT || | 2653 if (old_type != CONSTANT || |
| 2654 old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) { | 2654 old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) { |
| 2655 break; | 2655 break; |
| 2656 } | 2656 } |
| 2657 } else { | 2657 } else { |
| 2658 ASSERT_EQ(tmp_type, old_type); | 2658 DCHECK_EQ(tmp_type, old_type); |
| 2659 ASSERT_EQ(tmp_descriptors->GetValue(i), old_descriptors->GetValue(i)); | 2659 DCHECK_EQ(tmp_descriptors->GetValue(i), old_descriptors->GetValue(i)); |
| 2660 } | 2660 } |
| 2661 target_map = tmp_map; | 2661 target_map = tmp_map; |
| 2662 } | 2662 } |
| 2663 | 2663 |
| 2664 // Directly change the map if the target map is more general. | 2664 // Directly change the map if the target map is more general. |
| 2665 Handle<DescriptorArray> target_descriptors( | 2665 Handle<DescriptorArray> target_descriptors( |
| 2666 target_map->instance_descriptors(), isolate); | 2666 target_map->instance_descriptors(), isolate); |
| 2667 int target_nof = target_map->NumberOfOwnDescriptors(); | 2667 int target_nof = target_map->NumberOfOwnDescriptors(); |
| 2668 if (target_nof == old_nof && | 2668 if (target_nof == old_nof && |
| 2669 (store_mode != FORCE_FIELD || | 2669 (store_mode != FORCE_FIELD || |
| 2670 target_descriptors->GetDetails(modify_index).type() == FIELD)) { | 2670 target_descriptors->GetDetails(modify_index).type() == FIELD)) { |
| 2671 ASSERT(modify_index < target_nof); | 2671 DCHECK(modify_index < target_nof); |
| 2672 ASSERT(new_representation.fits_into( | 2672 DCHECK(new_representation.fits_into( |
| 2673 target_descriptors->GetDetails(modify_index).representation())); | 2673 target_descriptors->GetDetails(modify_index).representation())); |
| 2674 ASSERT(target_descriptors->GetDetails(modify_index).type() != FIELD || | 2674 DCHECK(target_descriptors->GetDetails(modify_index).type() != FIELD || |
| 2675 new_field_type->NowIs( | 2675 new_field_type->NowIs( |
| 2676 target_descriptors->GetFieldType(modify_index))); | 2676 target_descriptors->GetFieldType(modify_index))); |
| 2677 return target_map; | 2677 return target_map; |
| 2678 } | 2678 } |
| 2679 | 2679 |
| 2680 // Find the last compatible target map in the transition tree. | 2680 // Find the last compatible target map in the transition tree. |
| 2681 for (int i = target_nof; i < old_nof; ++i) { | 2681 for (int i = target_nof; i < old_nof; ++i) { |
| 2682 int j = target_map->SearchTransition(old_descriptors->GetKey(i)); | 2682 int j = target_map->SearchTransition(old_descriptors->GetKey(i)); |
| 2683 if (j == TransitionArray::kNotFound) break; | 2683 if (j == TransitionArray::kNotFound) break; |
| 2684 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2684 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2700 target_nof = target_map->NumberOfOwnDescriptors(); | 2700 target_nof = target_map->NumberOfOwnDescriptors(); |
| 2701 target_descriptors = handle(target_map->instance_descriptors(), isolate); | 2701 target_descriptors = handle(target_map->instance_descriptors(), isolate); |
| 2702 | 2702 |
| 2703 // Allocate a new descriptor array large enough to hold the required | 2703 // Allocate a new descriptor array large enough to hold the required |
| 2704 // descriptors, with minimally the exact same size as the old descriptor | 2704 // descriptors, with minimally the exact same size as the old descriptor |
| 2705 // array. | 2705 // array. |
| 2706 int new_slack = Max( | 2706 int new_slack = Max( |
| 2707 old_nof, old_descriptors->number_of_descriptors()) - old_nof; | 2707 old_nof, old_descriptors->number_of_descriptors()) - old_nof; |
| 2708 Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate( | 2708 Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate( |
| 2709 isolate, old_nof, new_slack); | 2709 isolate, old_nof, new_slack); |
| 2710 ASSERT(new_descriptors->length() > target_descriptors->length() || | 2710 DCHECK(new_descriptors->length() > target_descriptors->length() || |
| 2711 new_descriptors->NumberOfSlackDescriptors() > 0 || | 2711 new_descriptors->NumberOfSlackDescriptors() > 0 || |
| 2712 new_descriptors->number_of_descriptors() == | 2712 new_descriptors->number_of_descriptors() == |
| 2713 old_descriptors->number_of_descriptors()); | 2713 old_descriptors->number_of_descriptors()); |
| 2714 ASSERT(new_descriptors->number_of_descriptors() == old_nof); | 2714 DCHECK(new_descriptors->number_of_descriptors() == old_nof); |
| 2715 | 2715 |
| 2716 // 0 -> |root_nof| | 2716 // 0 -> |root_nof| |
| 2717 int current_offset = 0; | 2717 int current_offset = 0; |
| 2718 for (int i = 0; i < root_nof; ++i) { | 2718 for (int i = 0; i < root_nof; ++i) { |
| 2719 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2719 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2720 if (old_details.type() == FIELD) current_offset++; | 2720 if (old_details.type() == FIELD) current_offset++; |
| 2721 Descriptor d(handle(old_descriptors->GetKey(i), isolate), | 2721 Descriptor d(handle(old_descriptors->GetKey(i), isolate), |
| 2722 handle(old_descriptors->GetValue(i), isolate), | 2722 handle(old_descriptors->GetValue(i), isolate), |
| 2723 old_details); | 2723 old_details); |
| 2724 new_descriptors->Set(i, &d); | 2724 new_descriptors->Set(i, &d); |
| 2725 } | 2725 } |
| 2726 | 2726 |
| 2727 // |root_nof| -> |target_nof| | 2727 // |root_nof| -> |target_nof| |
| 2728 for (int i = root_nof; i < target_nof; ++i) { | 2728 for (int i = root_nof; i < target_nof; ++i) { |
| 2729 Handle<Name> target_key(target_descriptors->GetKey(i), isolate); | 2729 Handle<Name> target_key(target_descriptors->GetKey(i), isolate); |
| 2730 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2730 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2731 PropertyDetails target_details = target_descriptors->GetDetails(i); | 2731 PropertyDetails target_details = target_descriptors->GetDetails(i); |
| 2732 target_details = target_details.CopyWithRepresentation( | 2732 target_details = target_details.CopyWithRepresentation( |
| 2733 old_details.representation().generalize( | 2733 old_details.representation().generalize( |
| 2734 target_details.representation())); | 2734 target_details.representation())); |
| 2735 if (modify_index == i) { | 2735 if (modify_index == i) { |
| 2736 target_details = target_details.CopyWithRepresentation( | 2736 target_details = target_details.CopyWithRepresentation( |
| 2737 new_representation.generalize(target_details.representation())); | 2737 new_representation.generalize(target_details.representation())); |
| 2738 } | 2738 } |
| 2739 ASSERT_EQ(old_details.attributes(), target_details.attributes()); | 2739 DCHECK_EQ(old_details.attributes(), target_details.attributes()); |
| 2740 if (old_details.type() == FIELD || | 2740 if (old_details.type() == FIELD || |
| 2741 target_details.type() == FIELD || | 2741 target_details.type() == FIELD || |
| 2742 (modify_index == i && store_mode == FORCE_FIELD) || | 2742 (modify_index == i && store_mode == FORCE_FIELD) || |
| 2743 (target_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { | 2743 (target_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { |
| 2744 Handle<HeapType> old_field_type = (old_details.type() == FIELD) | 2744 Handle<HeapType> old_field_type = (old_details.type() == FIELD) |
| 2745 ? handle(old_descriptors->GetFieldType(i), isolate) | 2745 ? handle(old_descriptors->GetFieldType(i), isolate) |
| 2746 : old_descriptors->GetValue(i)->OptimalType( | 2746 : old_descriptors->GetValue(i)->OptimalType( |
| 2747 isolate, target_details.representation()); | 2747 isolate, target_details.representation()); |
| 2748 Handle<HeapType> target_field_type = (target_details.type() == FIELD) | 2748 Handle<HeapType> target_field_type = (target_details.type() == FIELD) |
| 2749 ? handle(target_descriptors->GetFieldType(i), isolate) | 2749 ? handle(target_descriptors->GetFieldType(i), isolate) |
| 2750 : target_descriptors->GetValue(i)->OptimalType( | 2750 : target_descriptors->GetValue(i)->OptimalType( |
| 2751 isolate, target_details.representation()); | 2751 isolate, target_details.representation()); |
| 2752 target_field_type = GeneralizeFieldType( | 2752 target_field_type = GeneralizeFieldType( |
| 2753 target_field_type, old_field_type, isolate); | 2753 target_field_type, old_field_type, isolate); |
| 2754 if (modify_index == i) { | 2754 if (modify_index == i) { |
| 2755 target_field_type = GeneralizeFieldType( | 2755 target_field_type = GeneralizeFieldType( |
| 2756 target_field_type, new_field_type, isolate); | 2756 target_field_type, new_field_type, isolate); |
| 2757 } | 2757 } |
| 2758 FieldDescriptor d(target_key, | 2758 FieldDescriptor d(target_key, |
| 2759 current_offset++, | 2759 current_offset++, |
| 2760 target_field_type, | 2760 target_field_type, |
| 2761 target_details.attributes(), | 2761 target_details.attributes(), |
| 2762 target_details.representation()); | 2762 target_details.representation()); |
| 2763 new_descriptors->Set(i, &d); | 2763 new_descriptors->Set(i, &d); |
| 2764 } else { | 2764 } else { |
| 2765 ASSERT_NE(FIELD, target_details.type()); | 2765 DCHECK_NE(FIELD, target_details.type()); |
| 2766 Descriptor d(target_key, | 2766 Descriptor d(target_key, |
| 2767 handle(target_descriptors->GetValue(i), isolate), | 2767 handle(target_descriptors->GetValue(i), isolate), |
| 2768 target_details); | 2768 target_details); |
| 2769 new_descriptors->Set(i, &d); | 2769 new_descriptors->Set(i, &d); |
| 2770 } | 2770 } |
| 2771 } | 2771 } |
| 2772 | 2772 |
| 2773 // |target_nof| -> |old_nof| | 2773 // |target_nof| -> |old_nof| |
| 2774 for (int i = target_nof; i < old_nof; ++i) { | 2774 for (int i = target_nof; i < old_nof; ++i) { |
| 2775 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2775 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2776 Handle<Name> old_key(old_descriptors->GetKey(i), isolate); | 2776 Handle<Name> old_key(old_descriptors->GetKey(i), isolate); |
| 2777 if (modify_index == i) { | 2777 if (modify_index == i) { |
| 2778 old_details = old_details.CopyWithRepresentation( | 2778 old_details = old_details.CopyWithRepresentation( |
| 2779 new_representation.generalize(old_details.representation())); | 2779 new_representation.generalize(old_details.representation())); |
| 2780 } | 2780 } |
| 2781 if (old_details.type() == FIELD) { | 2781 if (old_details.type() == FIELD) { |
| 2782 Handle<HeapType> old_field_type( | 2782 Handle<HeapType> old_field_type( |
| 2783 old_descriptors->GetFieldType(i), isolate); | 2783 old_descriptors->GetFieldType(i), isolate); |
| 2784 if (modify_index == i) { | 2784 if (modify_index == i) { |
| 2785 old_field_type = GeneralizeFieldType( | 2785 old_field_type = GeneralizeFieldType( |
| 2786 old_field_type, new_field_type, isolate); | 2786 old_field_type, new_field_type, isolate); |
| 2787 } | 2787 } |
| 2788 FieldDescriptor d(old_key, | 2788 FieldDescriptor d(old_key, |
| 2789 current_offset++, | 2789 current_offset++, |
| 2790 old_field_type, | 2790 old_field_type, |
| 2791 old_details.attributes(), | 2791 old_details.attributes(), |
| 2792 old_details.representation()); | 2792 old_details.representation()); |
| 2793 new_descriptors->Set(i, &d); | 2793 new_descriptors->Set(i, &d); |
| 2794 } else { | 2794 } else { |
| 2795 ASSERT(old_details.type() == CONSTANT || old_details.type() == CALLBACKS); | 2795 DCHECK(old_details.type() == CONSTANT || old_details.type() == CALLBACKS); |
| 2796 if (modify_index == i && store_mode == FORCE_FIELD) { | 2796 if (modify_index == i && store_mode == FORCE_FIELD) { |
| 2797 FieldDescriptor d(old_key, | 2797 FieldDescriptor d(old_key, |
| 2798 current_offset++, | 2798 current_offset++, |
| 2799 GeneralizeFieldType( | 2799 GeneralizeFieldType( |
| 2800 old_descriptors->GetValue(i)->OptimalType( | 2800 old_descriptors->GetValue(i)->OptimalType( |
| 2801 isolate, old_details.representation()), | 2801 isolate, old_details.representation()), |
| 2802 new_field_type, isolate), | 2802 new_field_type, isolate), |
| 2803 old_details.attributes(), | 2803 old_details.attributes(), |
| 2804 old_details.representation()); | 2804 old_details.representation()); |
| 2805 new_descriptors->Set(i, &d); | 2805 new_descriptors->Set(i, &d); |
| 2806 } else { | 2806 } else { |
| 2807 ASSERT_NE(FIELD, old_details.type()); | 2807 DCHECK_NE(FIELD, old_details.type()); |
| 2808 Descriptor d(old_key, | 2808 Descriptor d(old_key, |
| 2809 handle(old_descriptors->GetValue(i), isolate), | 2809 handle(old_descriptors->GetValue(i), isolate), |
| 2810 old_details); | 2810 old_details); |
| 2811 new_descriptors->Set(i, &d); | 2811 new_descriptors->Set(i, &d); |
| 2812 } | 2812 } |
| 2813 } | 2813 } |
| 2814 } | 2814 } |
| 2815 | 2815 |
| 2816 new_descriptors->Sort(); | 2816 new_descriptors->Sort(); |
| 2817 | 2817 |
| 2818 ASSERT(store_mode != FORCE_FIELD || | 2818 DCHECK(store_mode != FORCE_FIELD || |
| 2819 new_descriptors->GetDetails(modify_index).type() == FIELD); | 2819 new_descriptors->GetDetails(modify_index).type() == FIELD); |
| 2820 | 2820 |
| 2821 Handle<Map> split_map(root_map->FindLastMatchMap( | 2821 Handle<Map> split_map(root_map->FindLastMatchMap( |
| 2822 root_nof, old_nof, *new_descriptors), isolate); | 2822 root_nof, old_nof, *new_descriptors), isolate); |
| 2823 int split_nof = split_map->NumberOfOwnDescriptors(); | 2823 int split_nof = split_map->NumberOfOwnDescriptors(); |
| 2824 ASSERT_NE(old_nof, split_nof); | 2824 DCHECK_NE(old_nof, split_nof); |
| 2825 | 2825 |
| 2826 split_map->DeprecateTarget( | 2826 split_map->DeprecateTarget( |
| 2827 old_descriptors->GetKey(split_nof), *new_descriptors); | 2827 old_descriptors->GetKey(split_nof), *new_descriptors); |
| 2828 | 2828 |
| 2829 if (FLAG_trace_generalization) { | 2829 if (FLAG_trace_generalization) { |
| 2830 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2830 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2831 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | 2831 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); |
| 2832 Handle<HeapType> old_field_type = (old_details.type() == FIELD) | 2832 Handle<HeapType> old_field_type = (old_details.type() == FIELD) |
| 2833 ? handle(old_descriptors->GetFieldType(modify_index), isolate) | 2833 ? handle(old_descriptors->GetFieldType(modify_index), isolate) |
| 2834 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), | 2834 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3087 } | 3087 } |
| 3088 | 3088 |
| 3089 | 3089 |
| 3090 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, | 3090 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, |
| 3091 Handle<Object> value) { | 3091 Handle<Object> value) { |
| 3092 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot | 3092 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot |
| 3093 // have own properties. | 3093 // have own properties. |
| 3094 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 3094 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
| 3095 | 3095 |
| 3096 // Store on the holder which may be hidden behind the receiver. | 3096 // Store on the holder which may be hidden behind the receiver. |
| 3097 ASSERT(it->HolderIsReceiverOrHiddenPrototype()); | 3097 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); |
| 3098 | 3098 |
| 3099 // Old value for the observation change record. | 3099 // Old value for the observation change record. |
| 3100 // Fetch before transforming the object since the encoding may become | 3100 // Fetch before transforming the object since the encoding may become |
| 3101 // incompatible with what's cached in |it|. | 3101 // incompatible with what's cached in |it|. |
| 3102 bool is_observed = | 3102 bool is_observed = |
| 3103 receiver->map()->is_observed() && | 3103 receiver->map()->is_observed() && |
| 3104 !it->name().is_identical_to(it->factory()->hidden_string()); | 3104 !it->name().is_identical_to(it->factory()->hidden_string()); |
| 3105 MaybeHandle<Object> maybe_old; | 3105 MaybeHandle<Object> maybe_old; |
| 3106 if (is_observed) maybe_old = it->GetDataValue(); | 3106 if (is_observed) maybe_old = it->GetDataValue(); |
| 3107 | 3107 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3120 | 3120 |
| 3121 return value; | 3121 return value; |
| 3122 } | 3122 } |
| 3123 | 3123 |
| 3124 | 3124 |
| 3125 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, | 3125 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
| 3126 Handle<Object> value, | 3126 Handle<Object> value, |
| 3127 PropertyAttributes attributes, | 3127 PropertyAttributes attributes, |
| 3128 StrictMode strict_mode, | 3128 StrictMode strict_mode, |
| 3129 StoreFromKeyed store_mode) { | 3129 StoreFromKeyed store_mode) { |
| 3130 ASSERT(!it->GetReceiver()->IsJSProxy()); | 3130 DCHECK(!it->GetReceiver()->IsJSProxy()); |
| 3131 if (!it->GetReceiver()->IsJSObject()) { | 3131 if (!it->GetReceiver()->IsJSObject()) { |
| 3132 // TODO(verwaest): Throw a TypeError with a more specific message. | 3132 // TODO(verwaest): Throw a TypeError with a more specific message. |
| 3133 return WriteToReadOnlyProperty(it, value, strict_mode); | 3133 return WriteToReadOnlyProperty(it, value, strict_mode); |
| 3134 } | 3134 } |
| 3135 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 3135 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
| 3136 | 3136 |
| 3137 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) | 3137 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) |
| 3138 // instead. If the prototype is Null, the proxy is detached. | 3138 // instead. If the prototype is Null, the proxy is detached. |
| 3139 if (receiver->IsJSGlobalProxy()) { | 3139 if (receiver->IsJSGlobalProxy()) { |
| 3140 // Trying to assign to a detached proxy. | 3140 // Trying to assign to a detached proxy. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3210 } | 3210 } |
| 3211 } | 3211 } |
| 3212 } | 3212 } |
| 3213 *found = false; | 3213 *found = false; |
| 3214 return isolate->factory()->the_hole_value(); | 3214 return isolate->factory()->the_hole_value(); |
| 3215 } | 3215 } |
| 3216 | 3216 |
| 3217 | 3217 |
| 3218 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { | 3218 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { |
| 3219 // Only supports adding slack to owned descriptors. | 3219 // Only supports adding slack to owned descriptors. |
| 3220 ASSERT(map->owns_descriptors()); | 3220 DCHECK(map->owns_descriptors()); |
| 3221 | 3221 |
| 3222 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 3222 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 3223 int old_size = map->NumberOfOwnDescriptors(); | 3223 int old_size = map->NumberOfOwnDescriptors(); |
| 3224 if (slack <= descriptors->NumberOfSlackDescriptors()) return; | 3224 if (slack <= descriptors->NumberOfSlackDescriptors()) return; |
| 3225 | 3225 |
| 3226 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( | 3226 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |
| 3227 descriptors, old_size, slack); | 3227 descriptors, old_size, slack); |
| 3228 | 3228 |
| 3229 if (old_size == 0) { | 3229 if (old_size == 0) { |
| 3230 map->set_instance_descriptors(*new_descriptors); | 3230 map->set_instance_descriptors(*new_descriptors); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3330 array->set(valid_descriptors, *entry); | 3330 array->set(valid_descriptors, *entry); |
| 3331 } | 3331 } |
| 3332 }; | 3332 }; |
| 3333 | 3333 |
| 3334 | 3334 |
| 3335 void Map::AppendCallbackDescriptors(Handle<Map> map, | 3335 void Map::AppendCallbackDescriptors(Handle<Map> map, |
| 3336 Handle<Object> descriptors) { | 3336 Handle<Object> descriptors) { |
| 3337 int nof = map->NumberOfOwnDescriptors(); | 3337 int nof = map->NumberOfOwnDescriptors(); |
| 3338 Handle<DescriptorArray> array(map->instance_descriptors()); | 3338 Handle<DescriptorArray> array(map->instance_descriptors()); |
| 3339 NeanderArray callbacks(descriptors); | 3339 NeanderArray callbacks(descriptors); |
| 3340 ASSERT(array->NumberOfSlackDescriptors() >= callbacks.length()); | 3340 DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length()); |
| 3341 nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof); | 3341 nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof); |
| 3342 map->SetNumberOfOwnDescriptors(nof); | 3342 map->SetNumberOfOwnDescriptors(nof); |
| 3343 } | 3343 } |
| 3344 | 3344 |
| 3345 | 3345 |
| 3346 int AccessorInfo::AppendUnique(Handle<Object> descriptors, | 3346 int AccessorInfo::AppendUnique(Handle<Object> descriptors, |
| 3347 Handle<FixedArray> array, | 3347 Handle<FixedArray> array, |
| 3348 int valid_descriptors) { | 3348 int valid_descriptors) { |
| 3349 NeanderArray callbacks(descriptors); | 3349 NeanderArray callbacks(descriptors); |
| 3350 ASSERT(array->length() >= callbacks.length() + valid_descriptors); | 3350 DCHECK(array->length() >= callbacks.length() + valid_descriptors); |
| 3351 return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks, | 3351 return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks, |
| 3352 array, | 3352 array, |
| 3353 valid_descriptors); | 3353 valid_descriptors); |
| 3354 } | 3354 } |
| 3355 | 3355 |
| 3356 | 3356 |
| 3357 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { | 3357 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { |
| 3358 ASSERT(!map.is_null()); | 3358 DCHECK(!map.is_null()); |
| 3359 for (int i = 0; i < maps->length(); ++i) { | 3359 for (int i = 0; i < maps->length(); ++i) { |
| 3360 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true; | 3360 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true; |
| 3361 } | 3361 } |
| 3362 return false; | 3362 return false; |
| 3363 } | 3363 } |
| 3364 | 3364 |
| 3365 | 3365 |
| 3366 template <class T> | 3366 template <class T> |
| 3367 static Handle<T> MaybeNull(T* p) { | 3367 static Handle<T> MaybeNull(T* p) { |
| 3368 if (p == NULL) return Handle<T>::null(); | 3368 if (p == NULL) return Handle<T>::null(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3414 } | 3414 } |
| 3415 | 3415 |
| 3416 ElementsKind kind = map->elements_kind(); | 3416 ElementsKind kind = map->elements_kind(); |
| 3417 while (kind != target_kind) { | 3417 while (kind != target_kind) { |
| 3418 kind = GetNextTransitionElementsKind(kind); | 3418 kind = GetNextTransitionElementsKind(kind); |
| 3419 if (!current_map->HasElementsTransition()) return current_map; | 3419 if (!current_map->HasElementsTransition()) return current_map; |
| 3420 current_map = current_map->elements_transition_map(); | 3420 current_map = current_map->elements_transition_map(); |
| 3421 } | 3421 } |
| 3422 | 3422 |
| 3423 if (to_kind != kind && current_map->HasElementsTransition()) { | 3423 if (to_kind != kind && current_map->HasElementsTransition()) { |
| 3424 ASSERT(to_kind == DICTIONARY_ELEMENTS); | 3424 DCHECK(to_kind == DICTIONARY_ELEMENTS); |
| 3425 Map* next_map = current_map->elements_transition_map(); | 3425 Map* next_map = current_map->elements_transition_map(); |
| 3426 if (next_map->elements_kind() == to_kind) return next_map; | 3426 if (next_map->elements_kind() == to_kind) return next_map; |
| 3427 } | 3427 } |
| 3428 | 3428 |
| 3429 ASSERT(current_map->elements_kind() == target_kind); | 3429 DCHECK(current_map->elements_kind() == target_kind); |
| 3430 return current_map; | 3430 return current_map; |
| 3431 } | 3431 } |
| 3432 | 3432 |
| 3433 | 3433 |
| 3434 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { | 3434 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { |
| 3435 Map* to_map = FindClosestElementsTransition(this, to_kind); | 3435 Map* to_map = FindClosestElementsTransition(this, to_kind); |
| 3436 if (to_map->elements_kind() == to_kind) return to_map; | 3436 if (to_map->elements_kind() == to_kind) return to_map; |
| 3437 return NULL; | 3437 return NULL; |
| 3438 } | 3438 } |
| 3439 | 3439 |
| 3440 | 3440 |
| 3441 bool Map::IsMapInArrayPrototypeChain() { | 3441 bool Map::IsMapInArrayPrototypeChain() { |
| 3442 Isolate* isolate = GetIsolate(); | 3442 Isolate* isolate = GetIsolate(); |
| 3443 if (isolate->initial_array_prototype()->map() == this) { | 3443 if (isolate->initial_array_prototype()->map() == this) { |
| 3444 return true; | 3444 return true; |
| 3445 } | 3445 } |
| 3446 | 3446 |
| 3447 if (isolate->initial_object_prototype()->map() == this) { | 3447 if (isolate->initial_object_prototype()->map() == this) { |
| 3448 return true; | 3448 return true; |
| 3449 } | 3449 } |
| 3450 | 3450 |
| 3451 return false; | 3451 return false; |
| 3452 } | 3452 } |
| 3453 | 3453 |
| 3454 | 3454 |
| 3455 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map, | 3455 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map, |
| 3456 ElementsKind to_kind) { | 3456 ElementsKind to_kind) { |
| 3457 ASSERT(IsTransitionElementsKind(map->elements_kind())); | 3457 DCHECK(IsTransitionElementsKind(map->elements_kind())); |
| 3458 | 3458 |
| 3459 Handle<Map> current_map = map; | 3459 Handle<Map> current_map = map; |
| 3460 | 3460 |
| 3461 ElementsKind kind = map->elements_kind(); | 3461 ElementsKind kind = map->elements_kind(); |
| 3462 while (kind != to_kind && !IsTerminalElementsKind(kind)) { | 3462 while (kind != to_kind && !IsTerminalElementsKind(kind)) { |
| 3463 kind = GetNextTransitionElementsKind(kind); | 3463 kind = GetNextTransitionElementsKind(kind); |
| 3464 current_map = Map::CopyAsElementsKind( | 3464 current_map = Map::CopyAsElementsKind( |
| 3465 current_map, kind, INSERT_TRANSITION); | 3465 current_map, kind, INSERT_TRANSITION); |
| 3466 } | 3466 } |
| 3467 | 3467 |
| 3468 // In case we are exiting the fast elements kind system, just add the map in | 3468 // In case we are exiting the fast elements kind system, just add the map in |
| 3469 // the end. | 3469 // the end. |
| 3470 if (kind != to_kind) { | 3470 if (kind != to_kind) { |
| 3471 current_map = Map::CopyAsElementsKind( | 3471 current_map = Map::CopyAsElementsKind( |
| 3472 current_map, to_kind, INSERT_TRANSITION); | 3472 current_map, to_kind, INSERT_TRANSITION); |
| 3473 } | 3473 } |
| 3474 | 3474 |
| 3475 ASSERT(current_map->elements_kind() == to_kind); | 3475 DCHECK(current_map->elements_kind() == to_kind); |
| 3476 return current_map; | 3476 return current_map; |
| 3477 } | 3477 } |
| 3478 | 3478 |
| 3479 | 3479 |
| 3480 Handle<Map> Map::TransitionElementsTo(Handle<Map> map, | 3480 Handle<Map> Map::TransitionElementsTo(Handle<Map> map, |
| 3481 ElementsKind to_kind) { | 3481 ElementsKind to_kind) { |
| 3482 ElementsKind from_kind = map->elements_kind(); | 3482 ElementsKind from_kind = map->elements_kind(); |
| 3483 if (from_kind == to_kind) return map; | 3483 if (from_kind == to_kind) return map; |
| 3484 | 3484 |
| 3485 Isolate* isolate = map->GetIsolate(); | 3485 Isolate* isolate = map->GetIsolate(); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3547 return Map::TransitionElementsTo(map, to_kind); | 3547 return Map::TransitionElementsTo(map, to_kind); |
| 3548 } | 3548 } |
| 3549 | 3549 |
| 3550 | 3550 |
| 3551 void JSObject::LookupOwnRealNamedProperty(Handle<Name> name, | 3551 void JSObject::LookupOwnRealNamedProperty(Handle<Name> name, |
| 3552 LookupResult* result) { | 3552 LookupResult* result) { |
| 3553 DisallowHeapAllocation no_gc; | 3553 DisallowHeapAllocation no_gc; |
| 3554 if (IsJSGlobalProxy()) { | 3554 if (IsJSGlobalProxy()) { |
| 3555 PrototypeIterator iter(GetIsolate(), this); | 3555 PrototypeIterator iter(GetIsolate(), this); |
| 3556 if (iter.IsAtEnd()) return result->NotFound(); | 3556 if (iter.IsAtEnd()) return result->NotFound(); |
| 3557 ASSERT(iter.GetCurrent()->IsJSGlobalObject()); | 3557 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
| 3558 return JSObject::cast(iter.GetCurrent()) | 3558 return JSObject::cast(iter.GetCurrent()) |
| 3559 ->LookupOwnRealNamedProperty(name, result); | 3559 ->LookupOwnRealNamedProperty(name, result); |
| 3560 } | 3560 } |
| 3561 | 3561 |
| 3562 if (HasFastProperties()) { | 3562 if (HasFastProperties()) { |
| 3563 map()->LookupDescriptor(this, *name, result); | 3563 map()->LookupDescriptor(this, *name, result); |
| 3564 // A property or a map transition was found. We return all of these result | 3564 // A property or a map transition was found. We return all of these result |
| 3565 // types because LookupOwnRealNamedProperty is used when setting | 3565 // types because LookupOwnRealNamedProperty is used when setting |
| 3566 // properties where map transitions are handled. | 3566 // properties where map transitions are handled. |
| 3567 ASSERT(!result->IsFound() || | 3567 DCHECK(!result->IsFound() || |
| 3568 (result->holder() == this && result->IsFastPropertyType())); | 3568 (result->holder() == this && result->IsFastPropertyType())); |
| 3569 return; | 3569 return; |
| 3570 } | 3570 } |
| 3571 | 3571 |
| 3572 int entry = property_dictionary()->FindEntry(name); | 3572 int entry = property_dictionary()->FindEntry(name); |
| 3573 if (entry != NameDictionary::kNotFound) { | 3573 if (entry != NameDictionary::kNotFound) { |
| 3574 Object* value = property_dictionary()->ValueAt(entry); | 3574 Object* value = property_dictionary()->ValueAt(entry); |
| 3575 if (IsGlobalObject()) { | 3575 if (IsGlobalObject()) { |
| 3576 PropertyDetails d = property_dictionary()->DetailsAt(entry); | 3576 PropertyDetails d = property_dictionary()->DetailsAt(entry); |
| 3577 if (d.IsDeleted() || PropertyCell::cast(value)->value()->IsTheHole()) { | 3577 if (d.IsDeleted() || PropertyCell::cast(value)->value()->IsTheHole()) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3600 | 3600 |
| 3601 void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name, | 3601 void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name, |
| 3602 LookupResult* result) { | 3602 LookupResult* result) { |
| 3603 DisallowHeapAllocation no_gc; | 3603 DisallowHeapAllocation no_gc; |
| 3604 Isolate* isolate = GetIsolate(); | 3604 Isolate* isolate = GetIsolate(); |
| 3605 for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd(); iter.Advance()) { | 3605 for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd(); iter.Advance()) { |
| 3606 if (iter.GetCurrent()->IsJSProxy()) { | 3606 if (iter.GetCurrent()->IsJSProxy()) { |
| 3607 return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); | 3607 return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); |
| 3608 } | 3608 } |
| 3609 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); | 3609 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); |
| 3610 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); | 3610 DCHECK(!(result->IsFound() && result->type() == INTERCEPTOR)); |
| 3611 if (result->IsFound()) return; | 3611 if (result->IsFound()) return; |
| 3612 } | 3612 } |
| 3613 result->NotFound(); | 3613 result->NotFound(); |
| 3614 } | 3614 } |
| 3615 | 3615 |
| 3616 | 3616 |
| 3617 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, | 3617 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, |
| 3618 Handle<Name> name) { | 3618 Handle<Name> name) { |
| 3619 Isolate* isolate = proxy->GetIsolate(); | 3619 Isolate* isolate = proxy->GetIsolate(); |
| 3620 | 3620 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3696 ARRAY_SIZE(argv), | 3696 ARRAY_SIZE(argv), |
| 3697 argv), | 3697 argv), |
| 3698 Object); | 3698 Object); |
| 3699 | 3699 |
| 3700 // [[GetProperty]] requires to check that all properties are configurable. | 3700 // [[GetProperty]] requires to check that all properties are configurable. |
| 3701 Handle<String> configurable_name = | 3701 Handle<String> configurable_name = |
| 3702 isolate->factory()->InternalizeOneByteString( | 3702 isolate->factory()->InternalizeOneByteString( |
| 3703 STATIC_ASCII_VECTOR("configurable_")); | 3703 STATIC_ASCII_VECTOR("configurable_")); |
| 3704 Handle<Object> configurable = | 3704 Handle<Object> configurable = |
| 3705 Object::GetProperty(desc, configurable_name).ToHandleChecked(); | 3705 Object::GetProperty(desc, configurable_name).ToHandleChecked(); |
| 3706 ASSERT(configurable->IsBoolean()); | 3706 DCHECK(configurable->IsBoolean()); |
| 3707 if (configurable->IsFalse()) { | 3707 if (configurable->IsFalse()) { |
| 3708 Handle<String> trap = | 3708 Handle<String> trap = |
| 3709 isolate->factory()->InternalizeOneByteString( | 3709 isolate->factory()->InternalizeOneByteString( |
| 3710 STATIC_ASCII_VECTOR("getPropertyDescriptor")); | 3710 STATIC_ASCII_VECTOR("getPropertyDescriptor")); |
| 3711 Handle<Object> args[] = { handler, trap, name }; | 3711 Handle<Object> args[] = { handler, trap, name }; |
| 3712 Handle<Object> error = isolate->factory()->NewTypeError( | 3712 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3713 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); | 3713 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); |
| 3714 return isolate->Throw<Object>(error); | 3714 return isolate->Throw<Object>(error); |
| 3715 } | 3715 } |
| 3716 ASSERT(configurable->IsTrue()); | 3716 DCHECK(configurable->IsTrue()); |
| 3717 | 3717 |
| 3718 // Check for DataDescriptor. | 3718 // Check for DataDescriptor. |
| 3719 Handle<String> hasWritable_name = | 3719 Handle<String> hasWritable_name = |
| 3720 isolate->factory()->InternalizeOneByteString( | 3720 isolate->factory()->InternalizeOneByteString( |
| 3721 STATIC_ASCII_VECTOR("hasWritable_")); | 3721 STATIC_ASCII_VECTOR("hasWritable_")); |
| 3722 Handle<Object> hasWritable = | 3722 Handle<Object> hasWritable = |
| 3723 Object::GetProperty(desc, hasWritable_name).ToHandleChecked(); | 3723 Object::GetProperty(desc, hasWritable_name).ToHandleChecked(); |
| 3724 ASSERT(hasWritable->IsBoolean()); | 3724 DCHECK(hasWritable->IsBoolean()); |
| 3725 if (hasWritable->IsTrue()) { | 3725 if (hasWritable->IsTrue()) { |
| 3726 Handle<String> writable_name = | 3726 Handle<String> writable_name = |
| 3727 isolate->factory()->InternalizeOneByteString( | 3727 isolate->factory()->InternalizeOneByteString( |
| 3728 STATIC_ASCII_VECTOR("writable_")); | 3728 STATIC_ASCII_VECTOR("writable_")); |
| 3729 Handle<Object> writable = | 3729 Handle<Object> writable = |
| 3730 Object::GetProperty(desc, writable_name).ToHandleChecked(); | 3730 Object::GetProperty(desc, writable_name).ToHandleChecked(); |
| 3731 ASSERT(writable->IsBoolean()); | 3731 DCHECK(writable->IsBoolean()); |
| 3732 *done = writable->IsFalse(); | 3732 *done = writable->IsFalse(); |
| 3733 if (!*done) return isolate->factory()->the_hole_value(); | 3733 if (!*done) return isolate->factory()->the_hole_value(); |
| 3734 if (strict_mode == SLOPPY) return value; | 3734 if (strict_mode == SLOPPY) return value; |
| 3735 Handle<Object> args[] = { name, receiver }; | 3735 Handle<Object> args[] = { name, receiver }; |
| 3736 Handle<Object> error = isolate->factory()->NewTypeError( | 3736 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3737 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 3737 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 3738 return isolate->Throw<Object>(error); | 3738 return isolate->Throw<Object>(error); |
| 3739 } | 3739 } |
| 3740 | 3740 |
| 3741 // We have an AccessorDescriptor. | 3741 // We have an AccessorDescriptor. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3883 | 3883 |
| 3884 // Save identity hash. | 3884 // Save identity hash. |
| 3885 Handle<Object> hash(proxy->GetIdentityHash(), isolate); | 3885 Handle<Object> hash(proxy->GetIdentityHash(), isolate); |
| 3886 | 3886 |
| 3887 if (proxy->IsJSFunctionProxy()) { | 3887 if (proxy->IsJSFunctionProxy()) { |
| 3888 isolate->factory()->BecomeJSFunction(proxy); | 3888 isolate->factory()->BecomeJSFunction(proxy); |
| 3889 // Code will be set on the JavaScript side. | 3889 // Code will be set on the JavaScript side. |
| 3890 } else { | 3890 } else { |
| 3891 isolate->factory()->BecomeJSObject(proxy); | 3891 isolate->factory()->BecomeJSObject(proxy); |
| 3892 } | 3892 } |
| 3893 ASSERT(proxy->IsJSObject()); | 3893 DCHECK(proxy->IsJSObject()); |
| 3894 | 3894 |
| 3895 // Inherit identity, if it was present. | 3895 // Inherit identity, if it was present. |
| 3896 if (hash->IsSmi()) { | 3896 if (hash->IsSmi()) { |
| 3897 JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy), | 3897 JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy), |
| 3898 Handle<Smi>::cast(hash)); | 3898 Handle<Smi>::cast(hash)); |
| 3899 } | 3899 } |
| 3900 } | 3900 } |
| 3901 | 3901 |
| 3902 | 3902 |
| 3903 MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy, | 3903 MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3923 return isolate->Throw<Object>(error); | 3923 return isolate->Throw<Object>(error); |
| 3924 } | 3924 } |
| 3925 trap = Handle<Object>(derived); | 3925 trap = Handle<Object>(derived); |
| 3926 } | 3926 } |
| 3927 | 3927 |
| 3928 return Execution::Call(isolate, trap, handler, argc, argv); | 3928 return Execution::Call(isolate, trap, handler, argc, argv); |
| 3929 } | 3929 } |
| 3930 | 3930 |
| 3931 | 3931 |
| 3932 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { | 3932 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { |
| 3933 ASSERT(object->map()->inobject_properties() == map->inobject_properties()); | 3933 DCHECK(object->map()->inobject_properties() == map->inobject_properties()); |
| 3934 ElementsKind obj_kind = object->map()->elements_kind(); | 3934 ElementsKind obj_kind = object->map()->elements_kind(); |
| 3935 ElementsKind map_kind = map->elements_kind(); | 3935 ElementsKind map_kind = map->elements_kind(); |
| 3936 if (map_kind != obj_kind) { | 3936 if (map_kind != obj_kind) { |
| 3937 ElementsKind to_kind = map_kind; | 3937 ElementsKind to_kind = map_kind; |
| 3938 if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) || | 3938 if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) || |
| 3939 IsDictionaryElementsKind(obj_kind)) { | 3939 IsDictionaryElementsKind(obj_kind)) { |
| 3940 to_kind = obj_kind; | 3940 to_kind = obj_kind; |
| 3941 } | 3941 } |
| 3942 if (IsDictionaryElementsKind(to_kind)) { | 3942 if (IsDictionaryElementsKind(to_kind)) { |
| 3943 NormalizeElements(object); | 3943 NormalizeElements(object); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4025 object->WriteToField(map->LastAdded(), *value); | 4025 object->WriteToField(map->LastAdded(), *value); |
| 4026 } | 4026 } |
| 4027 | 4027 |
| 4028 | 4028 |
| 4029 void JSObject::WriteToField(int descriptor, Object* value) { | 4029 void JSObject::WriteToField(int descriptor, Object* value) { |
| 4030 DisallowHeapAllocation no_gc; | 4030 DisallowHeapAllocation no_gc; |
| 4031 | 4031 |
| 4032 DescriptorArray* desc = map()->instance_descriptors(); | 4032 DescriptorArray* desc = map()->instance_descriptors(); |
| 4033 PropertyDetails details = desc->GetDetails(descriptor); | 4033 PropertyDetails details = desc->GetDetails(descriptor); |
| 4034 | 4034 |
| 4035 ASSERT(details.type() == FIELD); | 4035 DCHECK(details.type() == FIELD); |
| 4036 | 4036 |
| 4037 FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor); | 4037 FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor); |
| 4038 if (details.representation().IsDouble()) { | 4038 if (details.representation().IsDouble()) { |
| 4039 // Nothing more to be done. | 4039 // Nothing more to be done. |
| 4040 if (value->IsUninitialized()) return; | 4040 if (value->IsUninitialized()) return; |
| 4041 HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index)); | 4041 HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index)); |
| 4042 ASSERT(box->IsMutableHeapNumber()); | 4042 DCHECK(box->IsMutableHeapNumber()); |
| 4043 box->set_value(value->Number()); | 4043 box->set_value(value->Number()); |
| 4044 } else { | 4044 } else { |
| 4045 FastPropertyAtPut(index, value); | 4045 FastPropertyAtPut(index, value); |
| 4046 } | 4046 } |
| 4047 } | 4047 } |
| 4048 | 4048 |
| 4049 | 4049 |
| 4050 void JSObject::SetPropertyToField(LookupResult* lookup, Handle<Object> value) { | 4050 void JSObject::SetPropertyToField(LookupResult* lookup, Handle<Object> value) { |
| 4051 if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) { | 4051 if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) { |
| 4052 Representation field_representation = value->OptimalRepresentation(); | 4052 Representation field_representation = value->OptimalRepresentation(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4101 ConvertAndSetOwnProperty(lookup, name, value, attributes); | 4101 ConvertAndSetOwnProperty(lookup, name, value, attributes); |
| 4102 } | 4102 } |
| 4103 } | 4103 } |
| 4104 | 4104 |
| 4105 | 4105 |
| 4106 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name, | 4106 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name, |
| 4107 Handle<Object> value, | 4107 Handle<Object> value, |
| 4108 PropertyAttributes attributes) { | 4108 PropertyAttributes attributes) { |
| 4109 #ifdef DEBUG | 4109 #ifdef DEBUG |
| 4110 uint32_t index; | 4110 uint32_t index; |
| 4111 ASSERT(!object->IsJSProxy()); | 4111 DCHECK(!object->IsJSProxy()); |
| 4112 ASSERT(!name->AsArrayIndex(&index)); | 4112 DCHECK(!name->AsArrayIndex(&index)); |
| 4113 LookupIterator it(object, name, LookupIterator::CHECK_OWN_REAL); | 4113 LookupIterator it(object, name, LookupIterator::CHECK_OWN_REAL); |
| 4114 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); | 4114 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); |
| 4115 ASSERT(maybe.has_value); | 4115 DCHECK(maybe.has_value); |
| 4116 ASSERT(!it.IsFound()); | 4116 DCHECK(!it.IsFound()); |
| 4117 ASSERT(object->map()->is_extensible()); | 4117 DCHECK(object->map()->is_extensible()); |
| 4118 #endif | 4118 #endif |
| 4119 SetOwnPropertyIgnoreAttributes(object, name, value, attributes, | 4119 SetOwnPropertyIgnoreAttributes(object, name, value, attributes, |
| 4120 OMIT_EXTENSIBILITY_CHECK).Check(); | 4120 OMIT_EXTENSIBILITY_CHECK).Check(); |
| 4121 } | 4121 } |
| 4122 | 4122 |
| 4123 | 4123 |
| 4124 // Reconfigures a property to a data property with attributes, even if it is not | 4124 // Reconfigures a property to a data property with attributes, even if it is not |
| 4125 // reconfigurable. | 4125 // reconfigurable. |
| 4126 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( | 4126 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( |
| 4127 Handle<JSObject> object, | 4127 Handle<JSObject> object, |
| 4128 Handle<Name> name, | 4128 Handle<Name> name, |
| 4129 Handle<Object> value, | 4129 Handle<Object> value, |
| 4130 PropertyAttributes attributes, | 4130 PropertyAttributes attributes, |
| 4131 ExtensibilityCheck extensibility_check, | 4131 ExtensibilityCheck extensibility_check, |
| 4132 StoreFromKeyed store_from_keyed, | 4132 StoreFromKeyed store_from_keyed, |
| 4133 ExecutableAccessorInfoHandling handling) { | 4133 ExecutableAccessorInfoHandling handling) { |
| 4134 ASSERT(!value->IsTheHole()); | 4134 DCHECK(!value->IsTheHole()); |
| 4135 Isolate* isolate = object->GetIsolate(); | 4135 Isolate* isolate = object->GetIsolate(); |
| 4136 | 4136 |
| 4137 // Make sure that the top context does not change when doing callbacks or | 4137 // Make sure that the top context does not change when doing callbacks or |
| 4138 // interceptor calls. | 4138 // interceptor calls. |
| 4139 AssertNoContextChange ncc(isolate); | 4139 AssertNoContextChange ncc(isolate); |
| 4140 | 4140 |
| 4141 LookupResult lookup(isolate); | 4141 LookupResult lookup(isolate); |
| 4142 object->LookupOwn(name, &lookup, true); | 4142 object->LookupOwn(name, &lookup, true); |
| 4143 if (!lookup.IsFound()) { | 4143 if (!lookup.IsFound()) { |
| 4144 object->map()->LookupTransition(*object, *name, &lookup); | 4144 object->map()->LookupTransition(*object, *name, &lookup); |
| 4145 } | 4145 } |
| 4146 | 4146 |
| 4147 // Check access rights if needed. | 4147 // Check access rights if needed. |
| 4148 if (object->IsAccessCheckNeeded()) { | 4148 if (object->IsAccessCheckNeeded()) { |
| 4149 if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { | 4149 if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { |
| 4150 LookupIterator it(object, name, LookupIterator::CHECK_OWN); | 4150 LookupIterator it(object, name, LookupIterator::CHECK_OWN); |
| 4151 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY); | 4151 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY); |
| 4152 } | 4152 } |
| 4153 } | 4153 } |
| 4154 | 4154 |
| 4155 if (object->IsJSGlobalProxy()) { | 4155 if (object->IsJSGlobalProxy()) { |
| 4156 PrototypeIterator iter(isolate, object); | 4156 PrototypeIterator iter(isolate, object); |
| 4157 if (iter.IsAtEnd()) return value; | 4157 if (iter.IsAtEnd()) return value; |
| 4158 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 4158 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 4159 return SetOwnPropertyIgnoreAttributes( | 4159 return SetOwnPropertyIgnoreAttributes( |
| 4160 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), name, | 4160 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), name, |
| 4161 value, attributes, extensibility_check); | 4161 value, attributes, extensibility_check); |
| 4162 } | 4162 } |
| 4163 | 4163 |
| 4164 if (lookup.IsInterceptor() || | 4164 if (lookup.IsInterceptor() || |
| 4165 (lookup.IsDescriptorOrDictionary() && lookup.type() == CALLBACKS)) { | 4165 (lookup.IsDescriptorOrDictionary() && lookup.type() == CALLBACKS)) { |
| 4166 object->LookupOwnRealNamedProperty(name, &lookup); | 4166 object->LookupOwnRealNamedProperty(name, &lookup); |
| 4167 } | 4167 } |
| 4168 | 4168 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4303 PropertyCallbackArguments args( | 4303 PropertyCallbackArguments args( |
| 4304 isolate, interceptor->data(), *receiver, *holder); | 4304 isolate, interceptor->data(), *receiver, *holder); |
| 4305 if (!interceptor->query()->IsUndefined()) { | 4305 if (!interceptor->query()->IsUndefined()) { |
| 4306 v8::NamedPropertyQueryCallback query = | 4306 v8::NamedPropertyQueryCallback query = |
| 4307 v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query()); | 4307 v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query()); |
| 4308 LOG(isolate, | 4308 LOG(isolate, |
| 4309 ApiNamedPropertyAccess("interceptor-named-has", *holder, *name)); | 4309 ApiNamedPropertyAccess("interceptor-named-has", *holder, *name)); |
| 4310 v8::Handle<v8::Integer> result = | 4310 v8::Handle<v8::Integer> result = |
| 4311 args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name))); | 4311 args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name))); |
| 4312 if (!result.IsEmpty()) { | 4312 if (!result.IsEmpty()) { |
| 4313 ASSERT(result->IsInt32()); | 4313 DCHECK(result->IsInt32()); |
| 4314 return maybe(static_cast<PropertyAttributes>(result->Int32Value())); | 4314 return maybe(static_cast<PropertyAttributes>(result->Int32Value())); |
| 4315 } | 4315 } |
| 4316 } else if (!interceptor->getter()->IsUndefined()) { | 4316 } else if (!interceptor->getter()->IsUndefined()) { |
| 4317 v8::NamedPropertyGetterCallback getter = | 4317 v8::NamedPropertyGetterCallback getter = |
| 4318 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); | 4318 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); |
| 4319 LOG(isolate, | 4319 LOG(isolate, |
| 4320 ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name)); | 4320 ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name)); |
| 4321 v8::Handle<v8::Value> result = | 4321 v8::Handle<v8::Value> result = |
| 4322 args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name))); | 4322 args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name))); |
| 4323 if (!result.IsEmpty()) return maybe(DONT_ENUM); | 4323 if (!result.IsEmpty()) return maybe(DONT_ENUM); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4381 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { | 4381 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { |
| 4382 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); | 4382 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); |
| 4383 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>()); | 4383 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>()); |
| 4384 return maybe(ABSENT); | 4384 return maybe(ABSENT); |
| 4385 } | 4385 } |
| 4386 } | 4386 } |
| 4387 | 4387 |
| 4388 if (object->IsJSGlobalProxy()) { | 4388 if (object->IsJSGlobalProxy()) { |
| 4389 PrototypeIterator iter(isolate, object); | 4389 PrototypeIterator iter(isolate, object); |
| 4390 if (iter.IsAtEnd()) return maybe(ABSENT); | 4390 if (iter.IsAtEnd()) return maybe(ABSENT); |
| 4391 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 4391 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 4392 return JSObject::GetElementAttributeWithReceiver( | 4392 return JSObject::GetElementAttributeWithReceiver( |
| 4393 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver, | 4393 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver, |
| 4394 index, check_prototype); | 4394 index, check_prototype); |
| 4395 } | 4395 } |
| 4396 | 4396 |
| 4397 // Check for lookup interceptor except when bootstrapping. | 4397 // Check for lookup interceptor except when bootstrapping. |
| 4398 if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) { | 4398 if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) { |
| 4399 return JSObject::GetElementAttributeWithInterceptor( | 4399 return JSObject::GetElementAttributeWithInterceptor( |
| 4400 object, receiver, index, check_prototype); | 4400 object, receiver, index, check_prototype); |
| 4401 } | 4401 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4484 !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) { | 4484 !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) { |
| 4485 return MaybeHandle<Map>(); | 4485 return MaybeHandle<Map>(); |
| 4486 } | 4486 } |
| 4487 return handle(Map::cast(value)); | 4487 return handle(Map::cast(value)); |
| 4488 } | 4488 } |
| 4489 | 4489 |
| 4490 | 4490 |
| 4491 void NormalizedMapCache::Set(Handle<Map> fast_map, | 4491 void NormalizedMapCache::Set(Handle<Map> fast_map, |
| 4492 Handle<Map> normalized_map) { | 4492 Handle<Map> normalized_map) { |
| 4493 DisallowHeapAllocation no_gc; | 4493 DisallowHeapAllocation no_gc; |
| 4494 ASSERT(normalized_map->is_dictionary_map()); | 4494 DCHECK(normalized_map->is_dictionary_map()); |
| 4495 FixedArray::set(GetIndex(fast_map), *normalized_map); | 4495 FixedArray::set(GetIndex(fast_map), *normalized_map); |
| 4496 } | 4496 } |
| 4497 | 4497 |
| 4498 | 4498 |
| 4499 void NormalizedMapCache::Clear() { | 4499 void NormalizedMapCache::Clear() { |
| 4500 int entries = length(); | 4500 int entries = length(); |
| 4501 for (int i = 0; i != entries; i++) { | 4501 for (int i = 0; i != entries; i++) { |
| 4502 set_undefined(i); | 4502 set_undefined(i); |
| 4503 } | 4503 } |
| 4504 } | 4504 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4521 Handle<Map> new_map = Map::Normalize(map, mode); | 4521 Handle<Map> new_map = Map::Normalize(map, mode); |
| 4522 | 4522 |
| 4523 MigrateFastToSlow(object, new_map, expected_additional_properties); | 4523 MigrateFastToSlow(object, new_map, expected_additional_properties); |
| 4524 } | 4524 } |
| 4525 | 4525 |
| 4526 | 4526 |
| 4527 void JSObject::MigrateFastToSlow(Handle<JSObject> object, | 4527 void JSObject::MigrateFastToSlow(Handle<JSObject> object, |
| 4528 Handle<Map> new_map, | 4528 Handle<Map> new_map, |
| 4529 int expected_additional_properties) { | 4529 int expected_additional_properties) { |
| 4530 // The global object is always normalized. | 4530 // The global object is always normalized. |
| 4531 ASSERT(!object->IsGlobalObject()); | 4531 DCHECK(!object->IsGlobalObject()); |
| 4532 // JSGlobalProxy must never be normalized | 4532 // JSGlobalProxy must never be normalized |
| 4533 ASSERT(!object->IsJSGlobalProxy()); | 4533 DCHECK(!object->IsJSGlobalProxy()); |
| 4534 | 4534 |
| 4535 Isolate* isolate = object->GetIsolate(); | 4535 Isolate* isolate = object->GetIsolate(); |
| 4536 HandleScope scope(isolate); | 4536 HandleScope scope(isolate); |
| 4537 Handle<Map> map(object->map()); | 4537 Handle<Map> map(object->map()); |
| 4538 | 4538 |
| 4539 // Allocate new content. | 4539 // Allocate new content. |
| 4540 int real_size = map->NumberOfOwnDescriptors(); | 4540 int real_size = map->NumberOfOwnDescriptors(); |
| 4541 int property_count = real_size; | 4541 int property_count = real_size; |
| 4542 if (expected_additional_properties > 0) { | 4542 if (expected_additional_properties > 0) { |
| 4543 property_count += expected_additional_properties; | 4543 property_count += expected_additional_properties; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4558 details.attributes(), NORMAL, i + 1); | 4558 details.attributes(), NORMAL, i + 1); |
| 4559 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4559 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 4560 break; | 4560 break; |
| 4561 } | 4561 } |
| 4562 case FIELD: { | 4562 case FIELD: { |
| 4563 Handle<Name> key(descs->GetKey(i)); | 4563 Handle<Name> key(descs->GetKey(i)); |
| 4564 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4564 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
| 4565 Handle<Object> value( | 4565 Handle<Object> value( |
| 4566 object->RawFastPropertyAt(index), isolate); | 4566 object->RawFastPropertyAt(index), isolate); |
| 4567 if (details.representation().IsDouble()) { | 4567 if (details.representation().IsDouble()) { |
| 4568 ASSERT(value->IsMutableHeapNumber()); | 4568 DCHECK(value->IsMutableHeapNumber()); |
| 4569 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); | 4569 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); |
| 4570 value = isolate->factory()->NewHeapNumber(old->value()); | 4570 value = isolate->factory()->NewHeapNumber(old->value()); |
| 4571 } | 4571 } |
| 4572 PropertyDetails d = | 4572 PropertyDetails d = |
| 4573 PropertyDetails(details.attributes(), NORMAL, i + 1); | 4573 PropertyDetails(details.attributes(), NORMAL, i + 1); |
| 4574 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4574 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 4575 break; | 4575 break; |
| 4576 } | 4576 } |
| 4577 case CALLBACKS: { | 4577 case CALLBACKS: { |
| 4578 Handle<Name> key(descs->GetKey(i)); | 4578 Handle<Name> key(descs->GetKey(i)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4594 | 4594 |
| 4595 // Copy the next enumeration index from instance descriptor. | 4595 // Copy the next enumeration index from instance descriptor. |
| 4596 dictionary->SetNextEnumerationIndex(real_size + 1); | 4596 dictionary->SetNextEnumerationIndex(real_size + 1); |
| 4597 | 4597 |
| 4598 // From here on we cannot fail and we shouldn't GC anymore. | 4598 // From here on we cannot fail and we shouldn't GC anymore. |
| 4599 DisallowHeapAllocation no_allocation; | 4599 DisallowHeapAllocation no_allocation; |
| 4600 | 4600 |
| 4601 // Resize the object in the heap if necessary. | 4601 // Resize the object in the heap if necessary. |
| 4602 int new_instance_size = new_map->instance_size(); | 4602 int new_instance_size = new_map->instance_size(); |
| 4603 int instance_size_delta = map->instance_size() - new_instance_size; | 4603 int instance_size_delta = map->instance_size() - new_instance_size; |
| 4604 ASSERT(instance_size_delta >= 0); | 4604 DCHECK(instance_size_delta >= 0); |
| 4605 | 4605 |
| 4606 if (instance_size_delta > 0) { | 4606 if (instance_size_delta > 0) { |
| 4607 Heap* heap = isolate->heap(); | 4607 Heap* heap = isolate->heap(); |
| 4608 heap->CreateFillerObjectAt(object->address() + new_instance_size, | 4608 heap->CreateFillerObjectAt(object->address() + new_instance_size, |
| 4609 instance_size_delta); | 4609 instance_size_delta); |
| 4610 heap->AdjustLiveBytes(object->address(), -instance_size_delta, | 4610 heap->AdjustLiveBytes(object->address(), -instance_size_delta, |
| 4611 Heap::FROM_MUTATOR); | 4611 Heap::FROM_MUTATOR); |
| 4612 } | 4612 } |
| 4613 | 4613 |
| 4614 // We are storing the new map using release store after creating a filler for | 4614 // We are storing the new map using release store after creating a filler for |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4625 os << "Object properties have been normalized:\n"; | 4625 os << "Object properties have been normalized:\n"; |
| 4626 object->Print(os); | 4626 object->Print(os); |
| 4627 } | 4627 } |
| 4628 #endif | 4628 #endif |
| 4629 } | 4629 } |
| 4630 | 4630 |
| 4631 | 4631 |
| 4632 void JSObject::MigrateSlowToFast(Handle<JSObject> object, | 4632 void JSObject::MigrateSlowToFast(Handle<JSObject> object, |
| 4633 int unused_property_fields) { | 4633 int unused_property_fields) { |
| 4634 if (object->HasFastProperties()) return; | 4634 if (object->HasFastProperties()) return; |
| 4635 ASSERT(!object->IsGlobalObject()); | 4635 DCHECK(!object->IsGlobalObject()); |
| 4636 Isolate* isolate = object->GetIsolate(); | 4636 Isolate* isolate = object->GetIsolate(); |
| 4637 Factory* factory = isolate->factory(); | 4637 Factory* factory = isolate->factory(); |
| 4638 Handle<NameDictionary> dictionary(object->property_dictionary()); | 4638 Handle<NameDictionary> dictionary(object->property_dictionary()); |
| 4639 | 4639 |
| 4640 // Make sure we preserve dictionary representation if there are too many | 4640 // Make sure we preserve dictionary representation if there are too many |
| 4641 // descriptors. | 4641 // descriptors. |
| 4642 int number_of_elements = dictionary->NumberOfElements(); | 4642 int number_of_elements = dictionary->NumberOfElements(); |
| 4643 if (number_of_elements > kMaxNumberOfDescriptors) return; | 4643 if (number_of_elements > kMaxNumberOfDescriptors) return; |
| 4644 | 4644 |
| 4645 if (number_of_elements != dictionary->NextEnumerationIndex()) { | 4645 if (number_of_elements != dictionary->NextEnumerationIndex()) { |
| 4646 NameDictionary::DoGenerateNewEnumerationIndices(dictionary); | 4646 NameDictionary::DoGenerateNewEnumerationIndices(dictionary); |
| 4647 } | 4647 } |
| 4648 | 4648 |
| 4649 int instance_descriptor_length = 0; | 4649 int instance_descriptor_length = 0; |
| 4650 int number_of_fields = 0; | 4650 int number_of_fields = 0; |
| 4651 | 4651 |
| 4652 // Compute the length of the instance descriptor. | 4652 // Compute the length of the instance descriptor. |
| 4653 int capacity = dictionary->Capacity(); | 4653 int capacity = dictionary->Capacity(); |
| 4654 for (int i = 0; i < capacity; i++) { | 4654 for (int i = 0; i < capacity; i++) { |
| 4655 Object* k = dictionary->KeyAt(i); | 4655 Object* k = dictionary->KeyAt(i); |
| 4656 if (dictionary->IsKey(k)) { | 4656 if (dictionary->IsKey(k)) { |
| 4657 Object* value = dictionary->ValueAt(i); | 4657 Object* value = dictionary->ValueAt(i); |
| 4658 PropertyType type = dictionary->DetailsAt(i).type(); | 4658 PropertyType type = dictionary->DetailsAt(i).type(); |
| 4659 ASSERT(type != FIELD); | 4659 DCHECK(type != FIELD); |
| 4660 instance_descriptor_length++; | 4660 instance_descriptor_length++; |
| 4661 if (type == NORMAL && !value->IsJSFunction()) { | 4661 if (type == NORMAL && !value->IsJSFunction()) { |
| 4662 number_of_fields += 1; | 4662 number_of_fields += 1; |
| 4663 } | 4663 } |
| 4664 } | 4664 } |
| 4665 } | 4665 } |
| 4666 | 4666 |
| 4667 int inobject_props = object->map()->inobject_properties(); | 4667 int inobject_props = object->map()->inobject_properties(); |
| 4668 | 4668 |
| 4669 // Allocate new map. | 4669 // Allocate new map. |
| 4670 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 4670 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 4671 new_map->set_dictionary_map(false); | 4671 new_map->set_dictionary_map(false); |
| 4672 | 4672 |
| 4673 if (instance_descriptor_length == 0) { | 4673 if (instance_descriptor_length == 0) { |
| 4674 DisallowHeapAllocation no_gc; | 4674 DisallowHeapAllocation no_gc; |
| 4675 ASSERT_LE(unused_property_fields, inobject_props); | 4675 DCHECK_LE(unused_property_fields, inobject_props); |
| 4676 // Transform the object. | 4676 // Transform the object. |
| 4677 new_map->set_unused_property_fields(inobject_props); | 4677 new_map->set_unused_property_fields(inobject_props); |
| 4678 object->synchronized_set_map(*new_map); | 4678 object->synchronized_set_map(*new_map); |
| 4679 object->set_properties(isolate->heap()->empty_fixed_array()); | 4679 object->set_properties(isolate->heap()->empty_fixed_array()); |
| 4680 // Check that it really works. | 4680 // Check that it really works. |
| 4681 ASSERT(object->HasFastProperties()); | 4681 DCHECK(object->HasFastProperties()); |
| 4682 return; | 4682 return; |
| 4683 } | 4683 } |
| 4684 | 4684 |
| 4685 // Allocate the instance descriptor. | 4685 // Allocate the instance descriptor. |
| 4686 Handle<DescriptorArray> descriptors = DescriptorArray::Allocate( | 4686 Handle<DescriptorArray> descriptors = DescriptorArray::Allocate( |
| 4687 isolate, instance_descriptor_length); | 4687 isolate, instance_descriptor_length); |
| 4688 | 4688 |
| 4689 int number_of_allocated_fields = | 4689 int number_of_allocated_fields = |
| 4690 number_of_fields + unused_property_fields - inobject_props; | 4690 number_of_fields + unused_property_fields - inobject_props; |
| 4691 if (number_of_allocated_fields < 0) { | 4691 if (number_of_allocated_fields < 0) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4740 } else if (type == CALLBACKS) { | 4740 } else if (type == CALLBACKS) { |
| 4741 CallbacksDescriptor d(key, | 4741 CallbacksDescriptor d(key, |
| 4742 handle(value, isolate), | 4742 handle(value, isolate), |
| 4743 details.attributes()); | 4743 details.attributes()); |
| 4744 descriptors->Set(enumeration_index - 1, &d); | 4744 descriptors->Set(enumeration_index - 1, &d); |
| 4745 } else { | 4745 } else { |
| 4746 UNREACHABLE(); | 4746 UNREACHABLE(); |
| 4747 } | 4747 } |
| 4748 } | 4748 } |
| 4749 } | 4749 } |
| 4750 ASSERT(current_offset == number_of_fields); | 4750 DCHECK(current_offset == number_of_fields); |
| 4751 | 4751 |
| 4752 descriptors->Sort(); | 4752 descriptors->Sort(); |
| 4753 | 4753 |
| 4754 DisallowHeapAllocation no_gc; | 4754 DisallowHeapAllocation no_gc; |
| 4755 new_map->InitializeDescriptors(*descriptors); | 4755 new_map->InitializeDescriptors(*descriptors); |
| 4756 new_map->set_unused_property_fields(unused_property_fields); | 4756 new_map->set_unused_property_fields(unused_property_fields); |
| 4757 | 4757 |
| 4758 // Transform the object. | 4758 // Transform the object. |
| 4759 object->synchronized_set_map(*new_map); | 4759 object->synchronized_set_map(*new_map); |
| 4760 | 4760 |
| 4761 object->set_properties(*fields); | 4761 object->set_properties(*fields); |
| 4762 ASSERT(object->IsJSObject()); | 4762 DCHECK(object->IsJSObject()); |
| 4763 | 4763 |
| 4764 // Check that it really works. | 4764 // Check that it really works. |
| 4765 ASSERT(object->HasFastProperties()); | 4765 DCHECK(object->HasFastProperties()); |
| 4766 } | 4766 } |
| 4767 | 4767 |
| 4768 | 4768 |
| 4769 void JSObject::ResetElements(Handle<JSObject> object) { | 4769 void JSObject::ResetElements(Handle<JSObject> object) { |
| 4770 Heap* heap = object->GetIsolate()->heap(); | 4770 Heap* heap = object->GetIsolate()->heap(); |
| 4771 CHECK(object->map() != heap->sloppy_arguments_elements_map()); | 4771 CHECK(object->map() != heap->sloppy_arguments_elements_map()); |
| 4772 object->set_elements(object->map()->GetInitialElements()); | 4772 object->set_elements(object->map()->GetInitialElements()); |
| 4773 } | 4773 } |
| 4774 | 4774 |
| 4775 | 4775 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4798 dictionary = | 4798 dictionary = |
| 4799 SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details); | 4799 SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details); |
| 4800 } | 4800 } |
| 4801 } | 4801 } |
| 4802 return dictionary; | 4802 return dictionary; |
| 4803 } | 4803 } |
| 4804 | 4804 |
| 4805 | 4805 |
| 4806 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4806 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
| 4807 Handle<JSObject> object) { | 4807 Handle<JSObject> object) { |
| 4808 ASSERT(!object->HasExternalArrayElements() && | 4808 DCHECK(!object->HasExternalArrayElements() && |
| 4809 !object->HasFixedTypedArrayElements()); | 4809 !object->HasFixedTypedArrayElements()); |
| 4810 Isolate* isolate = object->GetIsolate(); | 4810 Isolate* isolate = object->GetIsolate(); |
| 4811 | 4811 |
| 4812 // Find the backing store. | 4812 // Find the backing store. |
| 4813 Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements())); | 4813 Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements())); |
| 4814 bool is_arguments = | 4814 bool is_arguments = |
| 4815 (array->map() == isolate->heap()->sloppy_arguments_elements_map()); | 4815 (array->map() == isolate->heap()->sloppy_arguments_elements_map()); |
| 4816 if (is_arguments) { | 4816 if (is_arguments) { |
| 4817 array = handle(FixedArrayBase::cast( | 4817 array = handle(FixedArrayBase::cast( |
| 4818 Handle<FixedArray>::cast(array)->get(1))); | 4818 Handle<FixedArray>::cast(array)->get(1))); |
| 4819 } | 4819 } |
| 4820 if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array); | 4820 if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array); |
| 4821 | 4821 |
| 4822 ASSERT(object->HasFastSmiOrObjectElements() || | 4822 DCHECK(object->HasFastSmiOrObjectElements() || |
| 4823 object->HasFastDoubleElements() || | 4823 object->HasFastDoubleElements() || |
| 4824 object->HasFastArgumentsElements()); | 4824 object->HasFastArgumentsElements()); |
| 4825 // Compute the effective length and allocate a new backing store. | 4825 // Compute the effective length and allocate a new backing store. |
| 4826 int length = object->IsJSArray() | 4826 int length = object->IsJSArray() |
| 4827 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() | 4827 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() |
| 4828 : array->length(); | 4828 : array->length(); |
| 4829 int old_capacity = 0; | 4829 int old_capacity = 0; |
| 4830 int used_elements = 0; | 4830 int used_elements = 0; |
| 4831 object->GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 4831 object->GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 4832 Handle<SeededNumberDictionary> dictionary = | 4832 Handle<SeededNumberDictionary> dictionary = |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4850 isolate->counters()->elements_to_dictionary()->Increment(); | 4850 isolate->counters()->elements_to_dictionary()->Increment(); |
| 4851 | 4851 |
| 4852 #ifdef DEBUG | 4852 #ifdef DEBUG |
| 4853 if (FLAG_trace_normalization) { | 4853 if (FLAG_trace_normalization) { |
| 4854 OFStream os(stdout); | 4854 OFStream os(stdout); |
| 4855 os << "Object elements have been normalized:\n"; | 4855 os << "Object elements have been normalized:\n"; |
| 4856 object->Print(os); | 4856 object->Print(os); |
| 4857 } | 4857 } |
| 4858 #endif | 4858 #endif |
| 4859 | 4859 |
| 4860 ASSERT(object->HasDictionaryElements() || | 4860 DCHECK(object->HasDictionaryElements() || |
| 4861 object->HasDictionaryArgumentsElements()); | 4861 object->HasDictionaryArgumentsElements()); |
| 4862 return dictionary; | 4862 return dictionary; |
| 4863 } | 4863 } |
| 4864 | 4864 |
| 4865 | 4865 |
| 4866 static Smi* GenerateIdentityHash(Isolate* isolate) { | 4866 static Smi* GenerateIdentityHash(Isolate* isolate) { |
| 4867 int hash_value; | 4867 int hash_value; |
| 4868 int attempts = 0; | 4868 int attempts = 0; |
| 4869 do { | 4869 do { |
| 4870 // Generate a random 32-bit hash value but limit range to fit | 4870 // Generate a random 32-bit hash value but limit range to fit |
| 4871 // within a smi. | 4871 // within a smi. |
| 4872 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; | 4872 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; |
| 4873 attempts++; | 4873 attempts++; |
| 4874 } while (hash_value == 0 && attempts < 30); | 4874 } while (hash_value == 0 && attempts < 30); |
| 4875 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 | 4875 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
| 4876 | 4876 |
| 4877 return Smi::FromInt(hash_value); | 4877 return Smi::FromInt(hash_value); |
| 4878 } | 4878 } |
| 4879 | 4879 |
| 4880 | 4880 |
| 4881 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) { | 4881 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) { |
| 4882 ASSERT(!object->IsJSGlobalProxy()); | 4882 DCHECK(!object->IsJSGlobalProxy()); |
| 4883 Isolate* isolate = object->GetIsolate(); | 4883 Isolate* isolate = object->GetIsolate(); |
| 4884 SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash); | 4884 SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash); |
| 4885 } | 4885 } |
| 4886 | 4886 |
| 4887 | 4887 |
| 4888 template<typename ProxyType> | 4888 template<typename ProxyType> |
| 4889 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) { | 4889 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) { |
| 4890 Isolate* isolate = proxy->GetIsolate(); | 4890 Isolate* isolate = proxy->GetIsolate(); |
| 4891 | 4891 |
| 4892 Handle<Object> maybe_hash(proxy->hash(), isolate); | 4892 Handle<Object> maybe_hash(proxy->hash(), isolate); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4933 } | 4933 } |
| 4934 | 4934 |
| 4935 | 4935 |
| 4936 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { | 4936 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { |
| 4937 return GetOrCreateIdentityHashHelper(proxy); | 4937 return GetOrCreateIdentityHashHelper(proxy); |
| 4938 } | 4938 } |
| 4939 | 4939 |
| 4940 | 4940 |
| 4941 Object* JSObject::GetHiddenProperty(Handle<Name> key) { | 4941 Object* JSObject::GetHiddenProperty(Handle<Name> key) { |
| 4942 DisallowHeapAllocation no_gc; | 4942 DisallowHeapAllocation no_gc; |
| 4943 ASSERT(key->IsUniqueName()); | 4943 DCHECK(key->IsUniqueName()); |
| 4944 if (IsJSGlobalProxy()) { | 4944 if (IsJSGlobalProxy()) { |
| 4945 // JSGlobalProxies store their hash internally. | 4945 // JSGlobalProxies store their hash internally. |
| 4946 ASSERT(*key != GetHeap()->identity_hash_string()); | 4946 DCHECK(*key != GetHeap()->identity_hash_string()); |
| 4947 // For a proxy, use the prototype as target object. | 4947 // For a proxy, use the prototype as target object. |
| 4948 PrototypeIterator iter(GetIsolate(), this); | 4948 PrototypeIterator iter(GetIsolate(), this); |
| 4949 // If the proxy is detached, return undefined. | 4949 // If the proxy is detached, return undefined. |
| 4950 if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); | 4950 if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); |
| 4951 ASSERT(iter.GetCurrent()->IsJSGlobalObject()); | 4951 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
| 4952 return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key); | 4952 return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key); |
| 4953 } | 4953 } |
| 4954 ASSERT(!IsJSGlobalProxy()); | 4954 DCHECK(!IsJSGlobalProxy()); |
| 4955 Object* inline_value = GetHiddenPropertiesHashTable(); | 4955 Object* inline_value = GetHiddenPropertiesHashTable(); |
| 4956 | 4956 |
| 4957 if (inline_value->IsSmi()) { | 4957 if (inline_value->IsSmi()) { |
| 4958 // Handle inline-stored identity hash. | 4958 // Handle inline-stored identity hash. |
| 4959 if (*key == GetHeap()->identity_hash_string()) { | 4959 if (*key == GetHeap()->identity_hash_string()) { |
| 4960 return inline_value; | 4960 return inline_value; |
| 4961 } else { | 4961 } else { |
| 4962 return GetHeap()->the_hole_value(); | 4962 return GetHeap()->the_hole_value(); |
| 4963 } | 4963 } |
| 4964 } | 4964 } |
| 4965 | 4965 |
| 4966 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); | 4966 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); |
| 4967 | 4967 |
| 4968 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); | 4968 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); |
| 4969 Object* entry = hashtable->Lookup(key); | 4969 Object* entry = hashtable->Lookup(key); |
| 4970 return entry; | 4970 return entry; |
| 4971 } | 4971 } |
| 4972 | 4972 |
| 4973 | 4973 |
| 4974 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, | 4974 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, |
| 4975 Handle<Name> key, | 4975 Handle<Name> key, |
| 4976 Handle<Object> value) { | 4976 Handle<Object> value) { |
| 4977 Isolate* isolate = object->GetIsolate(); | 4977 Isolate* isolate = object->GetIsolate(); |
| 4978 | 4978 |
| 4979 ASSERT(key->IsUniqueName()); | 4979 DCHECK(key->IsUniqueName()); |
| 4980 if (object->IsJSGlobalProxy()) { | 4980 if (object->IsJSGlobalProxy()) { |
| 4981 // JSGlobalProxies store their hash internally. | 4981 // JSGlobalProxies store their hash internally. |
| 4982 ASSERT(*key != *isolate->factory()->identity_hash_string()); | 4982 DCHECK(*key != *isolate->factory()->identity_hash_string()); |
| 4983 // For a proxy, use the prototype as target object. | 4983 // For a proxy, use the prototype as target object. |
| 4984 PrototypeIterator iter(isolate, object); | 4984 PrototypeIterator iter(isolate, object); |
| 4985 // If the proxy is detached, return undefined. | 4985 // If the proxy is detached, return undefined. |
| 4986 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); | 4986 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); |
| 4987 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 4987 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 4988 return SetHiddenProperty( | 4988 return SetHiddenProperty( |
| 4989 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key, | 4989 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key, |
| 4990 value); | 4990 value); |
| 4991 } | 4991 } |
| 4992 ASSERT(!object->IsJSGlobalProxy()); | 4992 DCHECK(!object->IsJSGlobalProxy()); |
| 4993 | 4993 |
| 4994 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | 4994 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); |
| 4995 | 4995 |
| 4996 // If there is no backing store yet, store the identity hash inline. | 4996 // If there is no backing store yet, store the identity hash inline. |
| 4997 if (value->IsSmi() && | 4997 if (value->IsSmi() && |
| 4998 *key == *isolate->factory()->identity_hash_string() && | 4998 *key == *isolate->factory()->identity_hash_string() && |
| 4999 (inline_value->IsUndefined() || inline_value->IsSmi())) { | 4999 (inline_value->IsUndefined() || inline_value->IsSmi())) { |
| 5000 return JSObject::SetHiddenPropertiesHashTable(object, value); | 5000 return JSObject::SetHiddenPropertiesHashTable(object, value); |
| 5001 } | 5001 } |
| 5002 | 5002 |
| 5003 Handle<ObjectHashTable> hashtable = | 5003 Handle<ObjectHashTable> hashtable = |
| 5004 GetOrCreateHiddenPropertiesHashtable(object); | 5004 GetOrCreateHiddenPropertiesHashtable(object); |
| 5005 | 5005 |
| 5006 // If it was found, check if the key is already in the dictionary. | 5006 // If it was found, check if the key is already in the dictionary. |
| 5007 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, | 5007 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, |
| 5008 value); | 5008 value); |
| 5009 if (*new_table != *hashtable) { | 5009 if (*new_table != *hashtable) { |
| 5010 // If adding the key expanded the dictionary (i.e., Add returned a new | 5010 // If adding the key expanded the dictionary (i.e., Add returned a new |
| 5011 // dictionary), store it back to the object. | 5011 // dictionary), store it back to the object. |
| 5012 SetHiddenPropertiesHashTable(object, new_table); | 5012 SetHiddenPropertiesHashTable(object, new_table); |
| 5013 } | 5013 } |
| 5014 | 5014 |
| 5015 // Return this to mark success. | 5015 // Return this to mark success. |
| 5016 return object; | 5016 return object; |
| 5017 } | 5017 } |
| 5018 | 5018 |
| 5019 | 5019 |
| 5020 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { | 5020 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { |
| 5021 Isolate* isolate = object->GetIsolate(); | 5021 Isolate* isolate = object->GetIsolate(); |
| 5022 ASSERT(key->IsUniqueName()); | 5022 DCHECK(key->IsUniqueName()); |
| 5023 | 5023 |
| 5024 if (object->IsJSGlobalProxy()) { | 5024 if (object->IsJSGlobalProxy()) { |
| 5025 PrototypeIterator iter(isolate, object); | 5025 PrototypeIterator iter(isolate, object); |
| 5026 if (iter.IsAtEnd()) return; | 5026 if (iter.IsAtEnd()) return; |
| 5027 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5027 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 5028 return DeleteHiddenProperty( | 5028 return DeleteHiddenProperty( |
| 5029 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key); | 5029 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key); |
| 5030 } | 5030 } |
| 5031 | 5031 |
| 5032 Object* inline_value = object->GetHiddenPropertiesHashTable(); | 5032 Object* inline_value = object->GetHiddenPropertiesHashTable(); |
| 5033 | 5033 |
| 5034 // We never delete (inline-stored) identity hashes. | 5034 // We never delete (inline-stored) identity hashes. |
| 5035 ASSERT(*key != *isolate->factory()->identity_hash_string()); | 5035 DCHECK(*key != *isolate->factory()->identity_hash_string()); |
| 5036 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; | 5036 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; |
| 5037 | 5037 |
| 5038 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); | 5038 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); |
| 5039 bool was_present = false; | 5039 bool was_present = false; |
| 5040 ObjectHashTable::Remove(hashtable, key, &was_present); | 5040 ObjectHashTable::Remove(hashtable, key, &was_present); |
| 5041 } | 5041 } |
| 5042 | 5042 |
| 5043 | 5043 |
| 5044 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { | 5044 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { |
| 5045 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); | 5045 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); |
| 5046 LookupIterator it(object, hidden, LookupIterator::CHECK_OWN_REAL); | 5046 LookupIterator it(object, hidden, LookupIterator::CHECK_OWN_REAL); |
| 5047 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); | 5047 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); |
| 5048 // Cannot get an exception since the hidden_string isn't accessible to JS. | 5048 // Cannot get an exception since the hidden_string isn't accessible to JS. |
| 5049 ASSERT(maybe.has_value); | 5049 DCHECK(maybe.has_value); |
| 5050 return maybe.value != ABSENT; | 5050 return maybe.value != ABSENT; |
| 5051 } | 5051 } |
| 5052 | 5052 |
| 5053 | 5053 |
| 5054 Object* JSObject::GetHiddenPropertiesHashTable() { | 5054 Object* JSObject::GetHiddenPropertiesHashTable() { |
| 5055 ASSERT(!IsJSGlobalProxy()); | 5055 DCHECK(!IsJSGlobalProxy()); |
| 5056 if (HasFastProperties()) { | 5056 if (HasFastProperties()) { |
| 5057 // If the object has fast properties, check whether the first slot | 5057 // If the object has fast properties, check whether the first slot |
| 5058 // in the descriptor array matches the hidden string. Since the | 5058 // in the descriptor array matches the hidden string. Since the |
| 5059 // hidden strings hash code is zero (and no other name has hash | 5059 // hidden strings hash code is zero (and no other name has hash |
| 5060 // code zero) it will always occupy the first entry if present. | 5060 // code zero) it will always occupy the first entry if present. |
| 5061 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 5061 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
| 5062 if (descriptors->number_of_descriptors() > 0) { | 5062 if (descriptors->number_of_descriptors() > 0) { |
| 5063 int sorted_index = descriptors->GetSortedKeyIndex(0); | 5063 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 5064 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && | 5064 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && |
| 5065 sorted_index < map()->NumberOfOwnDescriptors()) { | 5065 sorted_index < map()->NumberOfOwnDescriptors()) { |
| 5066 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 5066 DCHECK(descriptors->GetType(sorted_index) == FIELD); |
| 5067 ASSERT(descriptors->GetDetails(sorted_index).representation(). | 5067 DCHECK(descriptors->GetDetails(sorted_index).representation(). |
| 5068 IsCompatibleForLoad(Representation::Tagged())); | 5068 IsCompatibleForLoad(Representation::Tagged())); |
| 5069 FieldIndex index = FieldIndex::ForDescriptor(this->map(), | 5069 FieldIndex index = FieldIndex::ForDescriptor(this->map(), |
| 5070 sorted_index); | 5070 sorted_index); |
| 5071 return this->RawFastPropertyAt(index); | 5071 return this->RawFastPropertyAt(index); |
| 5072 } else { | 5072 } else { |
| 5073 return GetHeap()->undefined_value(); | 5073 return GetHeap()->undefined_value(); |
| 5074 } | 5074 } |
| 5075 } else { | 5075 } else { |
| 5076 return GetHeap()->undefined_value(); | 5076 return GetHeap()->undefined_value(); |
| 5077 } | 5077 } |
| 5078 } else { | 5078 } else { |
| 5079 Isolate* isolate = GetIsolate(); | 5079 Isolate* isolate = GetIsolate(); |
| 5080 LookupResult result(isolate); | 5080 LookupResult result(isolate); |
| 5081 LookupOwnRealNamedProperty(isolate->factory()->hidden_string(), &result); | 5081 LookupOwnRealNamedProperty(isolate->factory()->hidden_string(), &result); |
| 5082 if (result.IsFound()) { | 5082 if (result.IsFound()) { |
| 5083 ASSERT(result.IsNormal()); | 5083 DCHECK(result.IsNormal()); |
| 5084 ASSERT(result.holder() == this); | 5084 DCHECK(result.holder() == this); |
| 5085 return GetNormalizedProperty(&result); | 5085 return GetNormalizedProperty(&result); |
| 5086 } | 5086 } |
| 5087 return GetHeap()->undefined_value(); | 5087 return GetHeap()->undefined_value(); |
| 5088 } | 5088 } |
| 5089 } | 5089 } |
| 5090 | 5090 |
| 5091 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable( | 5091 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable( |
| 5092 Handle<JSObject> object) { | 5092 Handle<JSObject> object) { |
| 5093 Isolate* isolate = object->GetIsolate(); | 5093 Isolate* isolate = object->GetIsolate(); |
| 5094 | 5094 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5112 JSObject::SetOwnPropertyIgnoreAttributes( | 5112 JSObject::SetOwnPropertyIgnoreAttributes( |
| 5113 object, isolate->factory()->hidden_string(), | 5113 object, isolate->factory()->hidden_string(), |
| 5114 hashtable, DONT_ENUM).Assert(); | 5114 hashtable, DONT_ENUM).Assert(); |
| 5115 | 5115 |
| 5116 return hashtable; | 5116 return hashtable; |
| 5117 } | 5117 } |
| 5118 | 5118 |
| 5119 | 5119 |
| 5120 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, | 5120 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
| 5121 Handle<Object> value) { | 5121 Handle<Object> value) { |
| 5122 ASSERT(!object->IsJSGlobalProxy()); | 5122 DCHECK(!object->IsJSGlobalProxy()); |
| 5123 | 5123 |
| 5124 Isolate* isolate = object->GetIsolate(); | 5124 Isolate* isolate = object->GetIsolate(); |
| 5125 | 5125 |
| 5126 // We can store the identity hash inline iff there is no backing store | 5126 // We can store the identity hash inline iff there is no backing store |
| 5127 // for hidden properties yet. | 5127 // for hidden properties yet. |
| 5128 ASSERT(JSObject::HasHiddenProperties(object) != value->IsSmi()); | 5128 DCHECK(JSObject::HasHiddenProperties(object) != value->IsSmi()); |
| 5129 if (object->HasFastProperties()) { | 5129 if (object->HasFastProperties()) { |
| 5130 // If the object has fast properties, check whether the first slot | 5130 // If the object has fast properties, check whether the first slot |
| 5131 // in the descriptor array matches the hidden string. Since the | 5131 // in the descriptor array matches the hidden string. Since the |
| 5132 // hidden strings hash code is zero (and no other name has hash | 5132 // hidden strings hash code is zero (and no other name has hash |
| 5133 // code zero) it will always occupy the first entry if present. | 5133 // code zero) it will always occupy the first entry if present. |
| 5134 DescriptorArray* descriptors = object->map()->instance_descriptors(); | 5134 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 5135 if (descriptors->number_of_descriptors() > 0) { | 5135 if (descriptors->number_of_descriptors() > 0) { |
| 5136 int sorted_index = descriptors->GetSortedKeyIndex(0); | 5136 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 5137 if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string() | 5137 if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string() |
| 5138 && sorted_index < object->map()->NumberOfOwnDescriptors()) { | 5138 && sorted_index < object->map()->NumberOfOwnDescriptors()) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5177 v8::NamedPropertyDeleterCallback deleter = | 5177 v8::NamedPropertyDeleterCallback deleter = |
| 5178 v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter()); | 5178 v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter()); |
| 5179 LOG(isolate, | 5179 LOG(isolate, |
| 5180 ApiNamedPropertyAccess("interceptor-named-delete", *object, *name)); | 5180 ApiNamedPropertyAccess("interceptor-named-delete", *object, *name)); |
| 5181 PropertyCallbackArguments args( | 5181 PropertyCallbackArguments args( |
| 5182 isolate, interceptor->data(), *object, *object); | 5182 isolate, interceptor->data(), *object, *object); |
| 5183 v8::Handle<v8::Boolean> result = | 5183 v8::Handle<v8::Boolean> result = |
| 5184 args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name))); | 5184 args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name))); |
| 5185 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5185 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5186 if (!result.IsEmpty()) { | 5186 if (!result.IsEmpty()) { |
| 5187 ASSERT(result->IsBoolean()); | 5187 DCHECK(result->IsBoolean()); |
| 5188 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 5188 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| 5189 result_internal->VerifyApiCallResultType(); | 5189 result_internal->VerifyApiCallResultType(); |
| 5190 // Rebox CustomArguments::kReturnValueOffset before returning. | 5190 // Rebox CustomArguments::kReturnValueOffset before returning. |
| 5191 return handle(*result_internal, isolate); | 5191 return handle(*result_internal, isolate); |
| 5192 } | 5192 } |
| 5193 } | 5193 } |
| 5194 Handle<Object> result = | 5194 Handle<Object> result = |
| 5195 DeletePropertyPostInterceptor(object, name, NORMAL_DELETION); | 5195 DeletePropertyPostInterceptor(object, name, NORMAL_DELETION); |
| 5196 return result; | 5196 return result; |
| 5197 } | 5197 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5211 if (interceptor->deleter()->IsUndefined()) return factory->false_value(); | 5211 if (interceptor->deleter()->IsUndefined()) return factory->false_value(); |
| 5212 v8::IndexedPropertyDeleterCallback deleter = | 5212 v8::IndexedPropertyDeleterCallback deleter = |
| 5213 v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); | 5213 v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); |
| 5214 LOG(isolate, | 5214 LOG(isolate, |
| 5215 ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index)); | 5215 ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index)); |
| 5216 PropertyCallbackArguments args( | 5216 PropertyCallbackArguments args( |
| 5217 isolate, interceptor->data(), *object, *object); | 5217 isolate, interceptor->data(), *object, *object); |
| 5218 v8::Handle<v8::Boolean> result = args.Call(deleter, index); | 5218 v8::Handle<v8::Boolean> result = args.Call(deleter, index); |
| 5219 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5219 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5220 if (!result.IsEmpty()) { | 5220 if (!result.IsEmpty()) { |
| 5221 ASSERT(result->IsBoolean()); | 5221 DCHECK(result->IsBoolean()); |
| 5222 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 5222 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| 5223 result_internal->VerifyApiCallResultType(); | 5223 result_internal->VerifyApiCallResultType(); |
| 5224 // Rebox CustomArguments::kReturnValueOffset before returning. | 5224 // Rebox CustomArguments::kReturnValueOffset before returning. |
| 5225 return handle(*result_internal, isolate); | 5225 return handle(*result_internal, isolate); |
| 5226 } | 5226 } |
| 5227 MaybeHandle<Object> delete_result = object->GetElementsAccessor()->Delete( | 5227 MaybeHandle<Object> delete_result = object->GetElementsAccessor()->Delete( |
| 5228 object, index, NORMAL_DELETION); | 5228 object, index, NORMAL_DELETION); |
| 5229 return delete_result; | 5229 return delete_result; |
| 5230 } | 5230 } |
| 5231 | 5231 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5254 HandleVector(args, 2)); | 5254 HandleVector(args, 2)); |
| 5255 isolate->Throw(*error); | 5255 isolate->Throw(*error); |
| 5256 return Handle<Object>(); | 5256 return Handle<Object>(); |
| 5257 } | 5257 } |
| 5258 return factory->false_value(); | 5258 return factory->false_value(); |
| 5259 } | 5259 } |
| 5260 | 5260 |
| 5261 if (object->IsJSGlobalProxy()) { | 5261 if (object->IsJSGlobalProxy()) { |
| 5262 PrototypeIterator iter(isolate, object); | 5262 PrototypeIterator iter(isolate, object); |
| 5263 if (iter.IsAtEnd()) return factory->false_value(); | 5263 if (iter.IsAtEnd()) return factory->false_value(); |
| 5264 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5264 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 5265 return DeleteElement( | 5265 return DeleteElement( |
| 5266 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, | 5266 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, |
| 5267 mode); | 5267 mode); |
| 5268 } | 5268 } |
| 5269 | 5269 |
| 5270 Handle<Object> old_value; | 5270 Handle<Object> old_value; |
| 5271 bool should_enqueue_change_record = false; | 5271 bool should_enqueue_change_record = false; |
| 5272 if (object->map()->is_observed()) { | 5272 if (object->map()->is_observed()) { |
| 5273 Maybe<bool> maybe = HasOwnElement(object, index); | 5273 Maybe<bool> maybe = HasOwnElement(object, index); |
| 5274 if (!maybe.has_value) return MaybeHandle<Object>(); | 5274 if (!maybe.has_value) return MaybeHandle<Object>(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 5304 | 5304 |
| 5305 return result; | 5305 return result; |
| 5306 } | 5306 } |
| 5307 | 5307 |
| 5308 | 5308 |
| 5309 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, | 5309 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
| 5310 Handle<Name> name, | 5310 Handle<Name> name, |
| 5311 DeleteMode mode) { | 5311 DeleteMode mode) { |
| 5312 Isolate* isolate = object->GetIsolate(); | 5312 Isolate* isolate = object->GetIsolate(); |
| 5313 // ECMA-262, 3rd, 8.6.2.5 | 5313 // ECMA-262, 3rd, 8.6.2.5 |
| 5314 ASSERT(name->IsName()); | 5314 DCHECK(name->IsName()); |
| 5315 | 5315 |
| 5316 // Check access rights if needed. | 5316 // Check access rights if needed. |
| 5317 if (object->IsAccessCheckNeeded() && | 5317 if (object->IsAccessCheckNeeded() && |
| 5318 !isolate->MayNamedAccess(object, name, v8::ACCESS_DELETE)) { | 5318 !isolate->MayNamedAccess(object, name, v8::ACCESS_DELETE)) { |
| 5319 isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE); | 5319 isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE); |
| 5320 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5320 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5321 return isolate->factory()->false_value(); | 5321 return isolate->factory()->false_value(); |
| 5322 } | 5322 } |
| 5323 | 5323 |
| 5324 if (object->IsJSGlobalProxy()) { | 5324 if (object->IsJSGlobalProxy()) { |
| 5325 PrototypeIterator iter(isolate, object); | 5325 PrototypeIterator iter(isolate, object); |
| 5326 if (iter.IsAtEnd()) return isolate->factory()->false_value(); | 5326 if (iter.IsAtEnd()) return isolate->factory()->false_value(); |
| 5327 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5327 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 5328 return JSGlobalObject::DeleteProperty( | 5328 return JSGlobalObject::DeleteProperty( |
| 5329 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)), name, | 5329 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)), name, |
| 5330 mode); | 5330 mode); |
| 5331 } | 5331 } |
| 5332 | 5332 |
| 5333 uint32_t index = 0; | 5333 uint32_t index = 0; |
| 5334 if (name->AsArrayIndex(&index)) { | 5334 if (name->AsArrayIndex(&index)) { |
| 5335 return DeleteElement(object, index, mode); | 5335 return DeleteElement(object, index, mode); |
| 5336 } | 5336 } |
| 5337 | 5337 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5407 return JSProxy::DeletePropertyWithHandler( | 5407 return JSProxy::DeletePropertyWithHandler( |
| 5408 Handle<JSProxy>::cast(object), name, mode); | 5408 Handle<JSProxy>::cast(object), name, mode); |
| 5409 } | 5409 } |
| 5410 return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, mode); | 5410 return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, mode); |
| 5411 } | 5411 } |
| 5412 | 5412 |
| 5413 | 5413 |
| 5414 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 5414 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
| 5415 ElementsKind kind, | 5415 ElementsKind kind, |
| 5416 Object* object) { | 5416 Object* object) { |
| 5417 ASSERT(IsFastObjectElementsKind(kind) || | 5417 DCHECK(IsFastObjectElementsKind(kind) || |
| 5418 kind == DICTIONARY_ELEMENTS); | 5418 kind == DICTIONARY_ELEMENTS); |
| 5419 if (IsFastObjectElementsKind(kind)) { | 5419 if (IsFastObjectElementsKind(kind)) { |
| 5420 int length = IsJSArray() | 5420 int length = IsJSArray() |
| 5421 ? Smi::cast(JSArray::cast(this)->length())->value() | 5421 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 5422 : elements->length(); | 5422 : elements->length(); |
| 5423 for (int i = 0; i < length; ++i) { | 5423 for (int i = 0; i < length; ++i) { |
| 5424 Object* element = elements->get(i); | 5424 Object* element = elements->get(i); |
| 5425 if (!element->IsTheHole() && element == object) return true; | 5425 if (!element->IsTheHole() && element == object) return true; |
| 5426 } | 5426 } |
| 5427 } else { | 5427 } else { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5555 !isolate->MayNamedAccess( | 5555 !isolate->MayNamedAccess( |
| 5556 object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { | 5556 object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { |
| 5557 isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS); | 5557 isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS); |
| 5558 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5558 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5559 return isolate->factory()->false_value(); | 5559 return isolate->factory()->false_value(); |
| 5560 } | 5560 } |
| 5561 | 5561 |
| 5562 if (object->IsJSGlobalProxy()) { | 5562 if (object->IsJSGlobalProxy()) { |
| 5563 PrototypeIterator iter(isolate, object); | 5563 PrototypeIterator iter(isolate, object); |
| 5564 if (iter.IsAtEnd()) return object; | 5564 if (iter.IsAtEnd()) return object; |
| 5565 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5565 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 5566 return PreventExtensions( | 5566 return PreventExtensions( |
| 5567 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); | 5567 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); |
| 5568 } | 5568 } |
| 5569 | 5569 |
| 5570 // It's not possible to seal objects with external array elements | 5570 // It's not possible to seal objects with external array elements |
| 5571 if (object->HasExternalArrayElements() || | 5571 if (object->HasExternalArrayElements() || |
| 5572 object->HasFixedTypedArrayElements()) { | 5572 object->HasFixedTypedArrayElements()) { |
| 5573 Handle<Object> error = | 5573 Handle<Object> error = |
| 5574 isolate->factory()->NewTypeError( | 5574 isolate->factory()->NewTypeError( |
| 5575 "cant_prevent_ext_external_array_elements", | 5575 "cant_prevent_ext_external_array_elements", |
| 5576 HandleVector(&object, 1)); | 5576 HandleVector(&object, 1)); |
| 5577 return isolate->Throw<Object>(error); | 5577 return isolate->Throw<Object>(error); |
| 5578 } | 5578 } |
| 5579 | 5579 |
| 5580 // If there are fast elements we normalize. | 5580 // If there are fast elements we normalize. |
| 5581 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 5581 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 5582 ASSERT(object->HasDictionaryElements() || | 5582 DCHECK(object->HasDictionaryElements() || |
| 5583 object->HasDictionaryArgumentsElements()); | 5583 object->HasDictionaryArgumentsElements()); |
| 5584 | 5584 |
| 5585 // Make sure that we never go back to fast case. | 5585 // Make sure that we never go back to fast case. |
| 5586 dictionary->set_requires_slow_elements(); | 5586 dictionary->set_requires_slow_elements(); |
| 5587 | 5587 |
| 5588 // Do a map transition, other objects with this map may still | 5588 // Do a map transition, other objects with this map may still |
| 5589 // be extensible. | 5589 // be extensible. |
| 5590 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5590 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5591 Handle<Map> new_map = Map::Copy(handle(object->map())); | 5591 Handle<Map> new_map = Map::Copy(handle(object->map())); |
| 5592 | 5592 |
| 5593 new_map->set_is_extensible(false); | 5593 new_map->set_is_extensible(false); |
| 5594 JSObject::MigrateToMap(object, new_map); | 5594 JSObject::MigrateToMap(object, new_map); |
| 5595 ASSERT(!object->map()->is_extensible()); | 5595 DCHECK(!object->map()->is_extensible()); |
| 5596 | 5596 |
| 5597 if (object->map()->is_observed()) { | 5597 if (object->map()->is_observed()) { |
| 5598 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), | 5598 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), |
| 5599 isolate->factory()->the_hole_value()); | 5599 isolate->factory()->the_hole_value()); |
| 5600 } | 5600 } |
| 5601 return object; | 5601 return object; |
| 5602 } | 5602 } |
| 5603 | 5603 |
| 5604 | 5604 |
| 5605 template<typename Dictionary> | 5605 template<typename Dictionary> |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5622 details = details.CopyAddAttributes( | 5622 details = details.CopyAddAttributes( |
| 5623 static_cast<PropertyAttributes>(attrs)); | 5623 static_cast<PropertyAttributes>(attrs)); |
| 5624 dictionary->DetailsAtPut(i, details); | 5624 dictionary->DetailsAtPut(i, details); |
| 5625 } | 5625 } |
| 5626 } | 5626 } |
| 5627 } | 5627 } |
| 5628 | 5628 |
| 5629 | 5629 |
| 5630 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) { | 5630 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) { |
| 5631 // Freezing sloppy arguments should be handled elsewhere. | 5631 // Freezing sloppy arguments should be handled elsewhere. |
| 5632 ASSERT(!object->HasSloppyArgumentsElements()); | 5632 DCHECK(!object->HasSloppyArgumentsElements()); |
| 5633 ASSERT(!object->map()->is_observed()); | 5633 DCHECK(!object->map()->is_observed()); |
| 5634 | 5634 |
| 5635 if (object->map()->is_frozen()) return object; | 5635 if (object->map()->is_frozen()) return object; |
| 5636 | 5636 |
| 5637 Isolate* isolate = object->GetIsolate(); | 5637 Isolate* isolate = object->GetIsolate(); |
| 5638 if (object->IsAccessCheckNeeded() && | 5638 if (object->IsAccessCheckNeeded() && |
| 5639 !isolate->MayNamedAccess( | 5639 !isolate->MayNamedAccess( |
| 5640 object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { | 5640 object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { |
| 5641 isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS); | 5641 isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS); |
| 5642 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5642 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5643 return isolate->factory()->false_value(); | 5643 return isolate->factory()->false_value(); |
| 5644 } | 5644 } |
| 5645 | 5645 |
| 5646 if (object->IsJSGlobalProxy()) { | 5646 if (object->IsJSGlobalProxy()) { |
| 5647 PrototypeIterator iter(isolate, object); | 5647 PrototypeIterator iter(isolate, object); |
| 5648 if (iter.IsAtEnd()) return object; | 5648 if (iter.IsAtEnd()) return object; |
| 5649 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5649 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 5650 return Freeze(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); | 5650 return Freeze(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); |
| 5651 } | 5651 } |
| 5652 | 5652 |
| 5653 // It's not possible to freeze objects with external array elements | 5653 // It's not possible to freeze objects with external array elements |
| 5654 if (object->HasExternalArrayElements() || | 5654 if (object->HasExternalArrayElements() || |
| 5655 object->HasFixedTypedArrayElements()) { | 5655 object->HasFixedTypedArrayElements()) { |
| 5656 Handle<Object> error = | 5656 Handle<Object> error = |
| 5657 isolate->factory()->NewTypeError( | 5657 isolate->factory()->NewTypeError( |
| 5658 "cant_prevent_ext_external_array_elements", | 5658 "cant_prevent_ext_external_array_elements", |
| 5659 HandleVector(&object, 1)); | 5659 HandleVector(&object, 1)); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 5680 new_element_dictionary = | 5680 new_element_dictionary = |
| 5681 isolate->factory()->empty_slow_element_dictionary(); | 5681 isolate->factory()->empty_slow_element_dictionary(); |
| 5682 } | 5682 } |
| 5683 } | 5683 } |
| 5684 | 5684 |
| 5685 Handle<Map> old_map(object->map(), isolate); | 5685 Handle<Map> old_map(object->map(), isolate); |
| 5686 int transition_index = old_map->SearchTransition( | 5686 int transition_index = old_map->SearchTransition( |
| 5687 isolate->heap()->frozen_symbol()); | 5687 isolate->heap()->frozen_symbol()); |
| 5688 if (transition_index != TransitionArray::kNotFound) { | 5688 if (transition_index != TransitionArray::kNotFound) { |
| 5689 Handle<Map> transition_map(old_map->GetTransition(transition_index)); | 5689 Handle<Map> transition_map(old_map->GetTransition(transition_index)); |
| 5690 ASSERT(transition_map->has_dictionary_elements()); | 5690 DCHECK(transition_map->has_dictionary_elements()); |
| 5691 ASSERT(transition_map->is_frozen()); | 5691 DCHECK(transition_map->is_frozen()); |
| 5692 ASSERT(!transition_map->is_extensible()); | 5692 DCHECK(!transition_map->is_extensible()); |
| 5693 JSObject::MigrateToMap(object, transition_map); | 5693 JSObject::MigrateToMap(object, transition_map); |
| 5694 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5694 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
| 5695 // Create a new descriptor array with fully-frozen properties | 5695 // Create a new descriptor array with fully-frozen properties |
| 5696 Handle<Map> new_map = Map::CopyForFreeze(old_map); | 5696 Handle<Map> new_map = Map::CopyForFreeze(old_map); |
| 5697 JSObject::MigrateToMap(object, new_map); | 5697 JSObject::MigrateToMap(object, new_map); |
| 5698 } else { | 5698 } else { |
| 5699 // Slow path: need to normalize properties for safety | 5699 // Slow path: need to normalize properties for safety |
| 5700 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 5700 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 5701 | 5701 |
| 5702 // Create a new map, since other objects with this map may be extensible. | 5702 // Create a new map, since other objects with this map may be extensible. |
| 5703 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5703 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5704 Handle<Map> new_map = Map::Copy(handle(object->map())); | 5704 Handle<Map> new_map = Map::Copy(handle(object->map())); |
| 5705 new_map->freeze(); | 5705 new_map->freeze(); |
| 5706 new_map->set_is_extensible(false); | 5706 new_map->set_is_extensible(false); |
| 5707 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 5707 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 5708 JSObject::MigrateToMap(object, new_map); | 5708 JSObject::MigrateToMap(object, new_map); |
| 5709 | 5709 |
| 5710 // Freeze dictionary-mode properties | 5710 // Freeze dictionary-mode properties |
| 5711 FreezeDictionary(object->property_dictionary()); | 5711 FreezeDictionary(object->property_dictionary()); |
| 5712 } | 5712 } |
| 5713 | 5713 |
| 5714 ASSERT(object->map()->has_dictionary_elements()); | 5714 DCHECK(object->map()->has_dictionary_elements()); |
| 5715 if (!new_element_dictionary.is_null()) { | 5715 if (!new_element_dictionary.is_null()) { |
| 5716 object->set_elements(*new_element_dictionary); | 5716 object->set_elements(*new_element_dictionary); |
| 5717 } | 5717 } |
| 5718 | 5718 |
| 5719 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { | 5719 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { |
| 5720 SeededNumberDictionary* dictionary = object->element_dictionary(); | 5720 SeededNumberDictionary* dictionary = object->element_dictionary(); |
| 5721 // Make sure we never go back to the fast case | 5721 // Make sure we never go back to the fast case |
| 5722 dictionary->set_requires_slow_elements(); | 5722 dictionary->set_requires_slow_elements(); |
| 5723 // Freeze all elements in the dictionary | 5723 // Freeze all elements in the dictionary |
| 5724 FreezeDictionary(dictionary); | 5724 FreezeDictionary(dictionary); |
| 5725 } | 5725 } |
| 5726 | 5726 |
| 5727 return object; | 5727 return object; |
| 5728 } | 5728 } |
| 5729 | 5729 |
| 5730 | 5730 |
| 5731 void JSObject::SetObserved(Handle<JSObject> object) { | 5731 void JSObject::SetObserved(Handle<JSObject> object) { |
| 5732 ASSERT(!object->IsJSGlobalProxy()); | 5732 DCHECK(!object->IsJSGlobalProxy()); |
| 5733 ASSERT(!object->IsJSGlobalObject()); | 5733 DCHECK(!object->IsJSGlobalObject()); |
| 5734 Isolate* isolate = object->GetIsolate(); | 5734 Isolate* isolate = object->GetIsolate(); |
| 5735 Handle<Map> new_map; | 5735 Handle<Map> new_map; |
| 5736 Handle<Map> old_map(object->map(), isolate); | 5736 Handle<Map> old_map(object->map(), isolate); |
| 5737 ASSERT(!old_map->is_observed()); | 5737 DCHECK(!old_map->is_observed()); |
| 5738 int transition_index = old_map->SearchTransition( | 5738 int transition_index = old_map->SearchTransition( |
| 5739 isolate->heap()->observed_symbol()); | 5739 isolate->heap()->observed_symbol()); |
| 5740 if (transition_index != TransitionArray::kNotFound) { | 5740 if (transition_index != TransitionArray::kNotFound) { |
| 5741 new_map = handle(old_map->GetTransition(transition_index), isolate); | 5741 new_map = handle(old_map->GetTransition(transition_index), isolate); |
| 5742 ASSERT(new_map->is_observed()); | 5742 DCHECK(new_map->is_observed()); |
| 5743 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5743 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
| 5744 new_map = Map::CopyForObserved(old_map); | 5744 new_map = Map::CopyForObserved(old_map); |
| 5745 } else { | 5745 } else { |
| 5746 new_map = Map::Copy(old_map); | 5746 new_map = Map::Copy(old_map); |
| 5747 new_map->set_is_observed(); | 5747 new_map->set_is_observed(); |
| 5748 } | 5748 } |
| 5749 JSObject::MigrateToMap(object, new_map); | 5749 JSObject::MigrateToMap(object, new_map); |
| 5750 } | 5750 } |
| 5751 | 5751 |
| 5752 | 5752 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5817 Handle<AllocationSite> site_to_pass; | 5817 Handle<AllocationSite> site_to_pass; |
| 5818 if (site_context()->ShouldCreateMemento(object)) { | 5818 if (site_context()->ShouldCreateMemento(object)) { |
| 5819 site_to_pass = site_context()->current(); | 5819 site_to_pass = site_context()->current(); |
| 5820 } | 5820 } |
| 5821 copy = isolate->factory()->CopyJSObjectWithAllocationSite( | 5821 copy = isolate->factory()->CopyJSObjectWithAllocationSite( |
| 5822 object, site_to_pass); | 5822 object, site_to_pass); |
| 5823 } else { | 5823 } else { |
| 5824 copy = object; | 5824 copy = object; |
| 5825 } | 5825 } |
| 5826 | 5826 |
| 5827 ASSERT(copying || copy.is_identical_to(object)); | 5827 DCHECK(copying || copy.is_identical_to(object)); |
| 5828 | 5828 |
| 5829 ElementsKind kind = copy->GetElementsKind(); | 5829 ElementsKind kind = copy->GetElementsKind(); |
| 5830 if (copying && IsFastSmiOrObjectElementsKind(kind) && | 5830 if (copying && IsFastSmiOrObjectElementsKind(kind) && |
| 5831 FixedArray::cast(copy->elements())->map() == | 5831 FixedArray::cast(copy->elements())->map() == |
| 5832 isolate->heap()->fixed_cow_array_map()) { | 5832 isolate->heap()->fixed_cow_array_map()) { |
| 5833 isolate->counters()->cow_arrays_created_runtime()->Increment(); | 5833 isolate->counters()->cow_arrays_created_runtime()->Increment(); |
| 5834 } | 5834 } |
| 5835 | 5835 |
| 5836 if (!shallow) { | 5836 if (!shallow) { |
| 5837 HandleScope scope(isolate); | 5837 HandleScope scope(isolate); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5856 } | 5856 } |
| 5857 if (copying) { | 5857 if (copying) { |
| 5858 copy->FastPropertyAtPut(index, *value); | 5858 copy->FastPropertyAtPut(index, *value); |
| 5859 } | 5859 } |
| 5860 } | 5860 } |
| 5861 } else { | 5861 } else { |
| 5862 Handle<FixedArray> names = | 5862 Handle<FixedArray> names = |
| 5863 isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties()); | 5863 isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties()); |
| 5864 copy->GetOwnPropertyNames(*names, 0); | 5864 copy->GetOwnPropertyNames(*names, 0); |
| 5865 for (int i = 0; i < names->length(); i++) { | 5865 for (int i = 0; i < names->length(); i++) { |
| 5866 ASSERT(names->get(i)->IsString()); | 5866 DCHECK(names->get(i)->IsString()); |
| 5867 Handle<String> key_string(String::cast(names->get(i))); | 5867 Handle<String> key_string(String::cast(names->get(i))); |
| 5868 Maybe<PropertyAttributes> maybe = | 5868 Maybe<PropertyAttributes> maybe = |
| 5869 JSReceiver::GetOwnPropertyAttributes(copy, key_string); | 5869 JSReceiver::GetOwnPropertyAttributes(copy, key_string); |
| 5870 ASSERT(maybe.has_value); | 5870 DCHECK(maybe.has_value); |
| 5871 PropertyAttributes attributes = maybe.value; | 5871 PropertyAttributes attributes = maybe.value; |
| 5872 // Only deep copy fields from the object literal expression. | 5872 // Only deep copy fields from the object literal expression. |
| 5873 // In particular, don't try to copy the length attribute of | 5873 // In particular, don't try to copy the length attribute of |
| 5874 // an array. | 5874 // an array. |
| 5875 if (attributes != NONE) continue; | 5875 if (attributes != NONE) continue; |
| 5876 Handle<Object> value = | 5876 Handle<Object> value = |
| 5877 Object::GetProperty(copy, key_string).ToHandleChecked(); | 5877 Object::GetProperty(copy, key_string).ToHandleChecked(); |
| 5878 if (value->IsJSObject()) { | 5878 if (value->IsJSObject()) { |
| 5879 Handle<JSObject> result; | 5879 Handle<JSObject> result; |
| 5880 ASSIGN_RETURN_ON_EXCEPTION( | 5880 ASSIGN_RETURN_ON_EXCEPTION( |
| 5881 isolate, result, | 5881 isolate, result, |
| 5882 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), | 5882 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), |
| 5883 JSObject); | 5883 JSObject); |
| 5884 if (copying) { | 5884 if (copying) { |
| 5885 // Creating object copy for literals. No strict mode needed. | 5885 // Creating object copy for literals. No strict mode needed. |
| 5886 JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert(); | 5886 JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert(); |
| 5887 } | 5887 } |
| 5888 } | 5888 } |
| 5889 } | 5889 } |
| 5890 } | 5890 } |
| 5891 | 5891 |
| 5892 // Deep copy own elements. | 5892 // Deep copy own elements. |
| 5893 // Pixel elements cannot be created using an object literal. | 5893 // Pixel elements cannot be created using an object literal. |
| 5894 ASSERT(!copy->HasExternalArrayElements()); | 5894 DCHECK(!copy->HasExternalArrayElements()); |
| 5895 switch (kind) { | 5895 switch (kind) { |
| 5896 case FAST_SMI_ELEMENTS: | 5896 case FAST_SMI_ELEMENTS: |
| 5897 case FAST_ELEMENTS: | 5897 case FAST_ELEMENTS: |
| 5898 case FAST_HOLEY_SMI_ELEMENTS: | 5898 case FAST_HOLEY_SMI_ELEMENTS: |
| 5899 case FAST_HOLEY_ELEMENTS: { | 5899 case FAST_HOLEY_ELEMENTS: { |
| 5900 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); | 5900 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); |
| 5901 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { | 5901 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { |
| 5902 #ifdef DEBUG | 5902 #ifdef DEBUG |
| 5903 for (int i = 0; i < elements->length(); i++) { | 5903 for (int i = 0; i < elements->length(); i++) { |
| 5904 ASSERT(!elements->get(i)->IsJSObject()); | 5904 DCHECK(!elements->get(i)->IsJSObject()); |
| 5905 } | 5905 } |
| 5906 #endif | 5906 #endif |
| 5907 } else { | 5907 } else { |
| 5908 for (int i = 0; i < elements->length(); i++) { | 5908 for (int i = 0; i < elements->length(); i++) { |
| 5909 Handle<Object> value(elements->get(i), isolate); | 5909 Handle<Object> value(elements->get(i), isolate); |
| 5910 ASSERT(value->IsSmi() || | 5910 DCHECK(value->IsSmi() || |
| 5911 value->IsTheHole() || | 5911 value->IsTheHole() || |
| 5912 (IsFastObjectElementsKind(copy->GetElementsKind()))); | 5912 (IsFastObjectElementsKind(copy->GetElementsKind()))); |
| 5913 if (value->IsJSObject()) { | 5913 if (value->IsJSObject()) { |
| 5914 Handle<JSObject> result; | 5914 Handle<JSObject> result; |
| 5915 ASSIGN_RETURN_ON_EXCEPTION( | 5915 ASSIGN_RETURN_ON_EXCEPTION( |
| 5916 isolate, result, | 5916 isolate, result, |
| 5917 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), | 5917 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), |
| 5918 JSObject); | 5918 JSObject); |
| 5919 if (copying) { | 5919 if (copying) { |
| 5920 elements->set(i, *result); | 5920 elements->set(i, *result); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5969 } | 5969 } |
| 5970 | 5970 |
| 5971 | 5971 |
| 5972 MaybeHandle<JSObject> JSObject::DeepWalk( | 5972 MaybeHandle<JSObject> JSObject::DeepWalk( |
| 5973 Handle<JSObject> object, | 5973 Handle<JSObject> object, |
| 5974 AllocationSiteCreationContext* site_context) { | 5974 AllocationSiteCreationContext* site_context) { |
| 5975 JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false, | 5975 JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false, |
| 5976 kNoHints); | 5976 kNoHints); |
| 5977 MaybeHandle<JSObject> result = v.StructureWalk(object); | 5977 MaybeHandle<JSObject> result = v.StructureWalk(object); |
| 5978 Handle<JSObject> for_assert; | 5978 Handle<JSObject> for_assert; |
| 5979 ASSERT(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object)); | 5979 DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object)); |
| 5980 return result; | 5980 return result; |
| 5981 } | 5981 } |
| 5982 | 5982 |
| 5983 | 5983 |
| 5984 MaybeHandle<JSObject> JSObject::DeepCopy( | 5984 MaybeHandle<JSObject> JSObject::DeepCopy( |
| 5985 Handle<JSObject> object, | 5985 Handle<JSObject> object, |
| 5986 AllocationSiteUsageContext* site_context, | 5986 AllocationSiteUsageContext* site_context, |
| 5987 DeepCopyHints hints) { | 5987 DeepCopyHints hints) { |
| 5988 JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints); | 5988 JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints); |
| 5989 MaybeHandle<JSObject> copy = v.StructureWalk(object); | 5989 MaybeHandle<JSObject> copy = v.StructureWalk(object); |
| 5990 Handle<JSObject> for_assert; | 5990 Handle<JSObject> for_assert; |
| 5991 ASSERT(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object)); | 5991 DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object)); |
| 5992 return copy; | 5992 return copy; |
| 5993 } | 5993 } |
| 5994 | 5994 |
| 5995 | 5995 |
| 5996 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object, | 5996 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object, |
| 5997 Handle<Name> key) { | 5997 Handle<Name> key) { |
| 5998 Isolate* isolate = object->GetIsolate(); | 5998 Isolate* isolate = object->GetIsolate(); |
| 5999 LookupResult lookup(isolate); | 5999 LookupResult lookup(isolate); |
| 6000 { | 6000 { |
| 6001 DisallowHeapAllocation no_allocation; | 6001 DisallowHeapAllocation no_allocation; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6035 // - No prototype has enumerable properties/elements. | 6035 // - No prototype has enumerable properties/elements. |
| 6036 bool JSReceiver::IsSimpleEnum() { | 6036 bool JSReceiver::IsSimpleEnum() { |
| 6037 for (PrototypeIterator iter(GetIsolate(), this, | 6037 for (PrototypeIterator iter(GetIsolate(), this, |
| 6038 PrototypeIterator::START_AT_RECEIVER); | 6038 PrototypeIterator::START_AT_RECEIVER); |
| 6039 !iter.IsAtEnd(); iter.Advance()) { | 6039 !iter.IsAtEnd(); iter.Advance()) { |
| 6040 if (!iter.GetCurrent()->IsJSObject()) return false; | 6040 if (!iter.GetCurrent()->IsJSObject()) return false; |
| 6041 JSObject* curr = JSObject::cast(iter.GetCurrent()); | 6041 JSObject* curr = JSObject::cast(iter.GetCurrent()); |
| 6042 int enum_length = curr->map()->EnumLength(); | 6042 int enum_length = curr->map()->EnumLength(); |
| 6043 if (enum_length == kInvalidEnumCacheSentinel) return false; | 6043 if (enum_length == kInvalidEnumCacheSentinel) return false; |
| 6044 if (curr->IsAccessCheckNeeded()) return false; | 6044 if (curr->IsAccessCheckNeeded()) return false; |
| 6045 ASSERT(!curr->HasNamedInterceptor()); | 6045 DCHECK(!curr->HasNamedInterceptor()); |
| 6046 ASSERT(!curr->HasIndexedInterceptor()); | 6046 DCHECK(!curr->HasIndexedInterceptor()); |
| 6047 if (curr->NumberOfEnumElements() > 0) return false; | 6047 if (curr->NumberOfEnumElements() > 0) return false; |
| 6048 if (curr != this && enum_length != 0) return false; | 6048 if (curr != this && enum_length != 0) return false; |
| 6049 } | 6049 } |
| 6050 return true; | 6050 return true; |
| 6051 } | 6051 } |
| 6052 | 6052 |
| 6053 | 6053 |
| 6054 static bool FilterKey(Object* key, PropertyAttributes filter) { | 6054 static bool FilterKey(Object* key, PropertyAttributes filter) { |
| 6055 if ((filter & SYMBOLIC) && key->IsSymbol()) { | 6055 if ((filter & SYMBOLIC) && key->IsSymbol()) { |
| 6056 return true; | 6056 return true; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6096 if (current_index > max_index) max_index = current_index; | 6096 if (current_index > max_index) max_index = current_index; |
| 6097 } | 6097 } |
| 6098 } | 6098 } |
| 6099 return max_index + 1; | 6099 return max_index + 1; |
| 6100 } | 6100 } |
| 6101 | 6101 |
| 6102 | 6102 |
| 6103 void JSReceiver::LookupOwn( | 6103 void JSReceiver::LookupOwn( |
| 6104 Handle<Name> name, LookupResult* result, bool search_hidden_prototypes) { | 6104 Handle<Name> name, LookupResult* result, bool search_hidden_prototypes) { |
| 6105 DisallowHeapAllocation no_gc; | 6105 DisallowHeapAllocation no_gc; |
| 6106 ASSERT(name->IsName()); | 6106 DCHECK(name->IsName()); |
| 6107 | 6107 |
| 6108 if (IsJSGlobalProxy()) { | 6108 if (IsJSGlobalProxy()) { |
| 6109 PrototypeIterator iter(GetIsolate(), this); | 6109 PrototypeIterator iter(GetIsolate(), this); |
| 6110 if (iter.IsAtEnd()) return result->NotFound(); | 6110 if (iter.IsAtEnd()) return result->NotFound(); |
| 6111 ASSERT(iter.GetCurrent()->IsJSGlobalObject()); | 6111 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
| 6112 return JSReceiver::cast(iter.GetCurrent()) | 6112 return JSReceiver::cast(iter.GetCurrent()) |
| 6113 ->LookupOwn(name, result, search_hidden_prototypes); | 6113 ->LookupOwn(name, result, search_hidden_prototypes); |
| 6114 } | 6114 } |
| 6115 | 6115 |
| 6116 if (IsJSProxy()) { | 6116 if (IsJSProxy()) { |
| 6117 result->HandlerResult(JSProxy::cast(this)); | 6117 result->HandlerResult(JSProxy::cast(this)); |
| 6118 return; | 6118 return; |
| 6119 } | 6119 } |
| 6120 | 6120 |
| 6121 // Do not use inline caching if the object is a non-global object | 6121 // Do not use inline caching if the object is a non-global object |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6163 for (int i = 0; i < len; i++) { | 6163 for (int i = 0; i < len; i++) { |
| 6164 Object* e = array->get(i); | 6164 Object* e = array->get(i); |
| 6165 if (!(e->IsString() || e->IsNumber())) return false; | 6165 if (!(e->IsString() || e->IsNumber())) return false; |
| 6166 } | 6166 } |
| 6167 return true; | 6167 return true; |
| 6168 } | 6168 } |
| 6169 | 6169 |
| 6170 | 6170 |
| 6171 static Handle<FixedArray> ReduceFixedArrayTo( | 6171 static Handle<FixedArray> ReduceFixedArrayTo( |
| 6172 Handle<FixedArray> array, int length) { | 6172 Handle<FixedArray> array, int length) { |
| 6173 ASSERT(array->length() >= length); | 6173 DCHECK(array->length() >= length); |
| 6174 if (array->length() == length) return array; | 6174 if (array->length() == length) return array; |
| 6175 | 6175 |
| 6176 Handle<FixedArray> new_array = | 6176 Handle<FixedArray> new_array = |
| 6177 array->GetIsolate()->factory()->NewFixedArray(length); | 6177 array->GetIsolate()->factory()->NewFixedArray(length); |
| 6178 for (int i = 0; i < length; ++i) new_array->set(i, array->get(i)); | 6178 for (int i = 0; i < length; ++i) new_array->set(i, array->get(i)); |
| 6179 return new_array; | 6179 return new_array; |
| 6180 } | 6180 } |
| 6181 | 6181 |
| 6182 | 6182 |
| 6183 static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, | 6183 static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, |
| 6184 bool cache_result) { | 6184 bool cache_result) { |
| 6185 Isolate* isolate = object->GetIsolate(); | 6185 Isolate* isolate = object->GetIsolate(); |
| 6186 if (object->HasFastProperties()) { | 6186 if (object->HasFastProperties()) { |
| 6187 int own_property_count = object->map()->EnumLength(); | 6187 int own_property_count = object->map()->EnumLength(); |
| 6188 // If the enum length of the given map is set to kInvalidEnumCache, this | 6188 // If the enum length of the given map is set to kInvalidEnumCache, this |
| 6189 // means that the map itself has never used the present enum cache. The | 6189 // means that the map itself has never used the present enum cache. The |
| 6190 // first step to using the cache is to set the enum length of the map by | 6190 // first step to using the cache is to set the enum length of the map by |
| 6191 // counting the number of own descriptors that are not DONT_ENUM or | 6191 // counting the number of own descriptors that are not DONT_ENUM or |
| 6192 // SYMBOLIC. | 6192 // SYMBOLIC. |
| 6193 if (own_property_count == kInvalidEnumCacheSentinel) { | 6193 if (own_property_count == kInvalidEnumCacheSentinel) { |
| 6194 own_property_count = object->map()->NumberOfDescribedProperties( | 6194 own_property_count = object->map()->NumberOfDescribedProperties( |
| 6195 OWN_DESCRIPTORS, DONT_SHOW); | 6195 OWN_DESCRIPTORS, DONT_SHOW); |
| 6196 } else { | 6196 } else { |
| 6197 ASSERT(own_property_count == object->map()->NumberOfDescribedProperties( | 6197 DCHECK(own_property_count == object->map()->NumberOfDescribedProperties( |
| 6198 OWN_DESCRIPTORS, DONT_SHOW)); | 6198 OWN_DESCRIPTORS, DONT_SHOW)); |
| 6199 } | 6199 } |
| 6200 | 6200 |
| 6201 if (object->map()->instance_descriptors()->HasEnumCache()) { | 6201 if (object->map()->instance_descriptors()->HasEnumCache()) { |
| 6202 DescriptorArray* desc = object->map()->instance_descriptors(); | 6202 DescriptorArray* desc = object->map()->instance_descriptors(); |
| 6203 Handle<FixedArray> keys(desc->GetEnumCache(), isolate); | 6203 Handle<FixedArray> keys(desc->GetEnumCache(), isolate); |
| 6204 | 6204 |
| 6205 // In case the number of properties required in the enum are actually | 6205 // In case the number of properties required in the enum are actually |
| 6206 // present, we can reuse the enum cache. Otherwise, this means that the | 6206 // present, we can reuse the enum cache. Otherwise, this means that the |
| 6207 // enum cache was generated for a previous (smaller) version of the | 6207 // enum cache was generated for a previous (smaller) version of the |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6244 indices = Handle<FixedArray>(); | 6244 indices = Handle<FixedArray>(); |
| 6245 } else { | 6245 } else { |
| 6246 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); | 6246 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); |
| 6247 int load_by_field_index = field_index.GetLoadByFieldIndex(); | 6247 int load_by_field_index = field_index.GetLoadByFieldIndex(); |
| 6248 indices->set(index, Smi::FromInt(load_by_field_index)); | 6248 indices->set(index, Smi::FromInt(load_by_field_index)); |
| 6249 } | 6249 } |
| 6250 } | 6250 } |
| 6251 index++; | 6251 index++; |
| 6252 } | 6252 } |
| 6253 } | 6253 } |
| 6254 ASSERT(index == storage->length()); | 6254 DCHECK(index == storage->length()); |
| 6255 | 6255 |
| 6256 Handle<FixedArray> bridge_storage = | 6256 Handle<FixedArray> bridge_storage = |
| 6257 isolate->factory()->NewFixedArray( | 6257 isolate->factory()->NewFixedArray( |
| 6258 DescriptorArray::kEnumCacheBridgeLength); | 6258 DescriptorArray::kEnumCacheBridgeLength); |
| 6259 DescriptorArray* desc = object->map()->instance_descriptors(); | 6259 DescriptorArray* desc = object->map()->instance_descriptors(); |
| 6260 desc->SetEnumCache(*bridge_storage, | 6260 desc->SetEnumCache(*bridge_storage, |
| 6261 *storage, | 6261 *storage, |
| 6262 indices.is_null() ? Object::cast(Smi::FromInt(0)) | 6262 indices.is_null() ? Object::cast(Smi::FromInt(0)) |
| 6263 : Object::cast(*indices)); | 6263 : Object::cast(*indices)); |
| 6264 if (cache_result) { | 6264 if (cache_result) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6324 } | 6324 } |
| 6325 | 6325 |
| 6326 // Compute the element keys. | 6326 // Compute the element keys. |
| 6327 Handle<FixedArray> element_keys = | 6327 Handle<FixedArray> element_keys = |
| 6328 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); | 6328 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); |
| 6329 current->GetEnumElementKeys(*element_keys); | 6329 current->GetEnumElementKeys(*element_keys); |
| 6330 ASSIGN_RETURN_ON_EXCEPTION( | 6330 ASSIGN_RETURN_ON_EXCEPTION( |
| 6331 isolate, content, | 6331 isolate, content, |
| 6332 FixedArray::UnionOfKeys(content, element_keys), | 6332 FixedArray::UnionOfKeys(content, element_keys), |
| 6333 FixedArray); | 6333 FixedArray); |
| 6334 ASSERT(ContainsOnlyValidKeys(content)); | 6334 DCHECK(ContainsOnlyValidKeys(content)); |
| 6335 | 6335 |
| 6336 // Add the element keys from the interceptor. | 6336 // Add the element keys from the interceptor. |
| 6337 if (current->HasIndexedInterceptor()) { | 6337 if (current->HasIndexedInterceptor()) { |
| 6338 Handle<JSObject> result; | 6338 Handle<JSObject> result; |
| 6339 if (JSObject::GetKeysForIndexedInterceptor( | 6339 if (JSObject::GetKeysForIndexedInterceptor( |
| 6340 current, object).ToHandle(&result)) { | 6340 current, object).ToHandle(&result)) { |
| 6341 ASSIGN_RETURN_ON_EXCEPTION( | 6341 ASSIGN_RETURN_ON_EXCEPTION( |
| 6342 isolate, content, | 6342 isolate, content, |
| 6343 FixedArray::AddKeysFromArrayLike(content, result), | 6343 FixedArray::AddKeysFromArrayLike(content, result), |
| 6344 FixedArray); | 6344 FixedArray); |
| 6345 } | 6345 } |
| 6346 ASSERT(ContainsOnlyValidKeys(content)); | 6346 DCHECK(ContainsOnlyValidKeys(content)); |
| 6347 } | 6347 } |
| 6348 | 6348 |
| 6349 // We can cache the computed property keys if access checks are | 6349 // We can cache the computed property keys if access checks are |
| 6350 // not needed and no interceptors are involved. | 6350 // not needed and no interceptors are involved. |
| 6351 // | 6351 // |
| 6352 // We do not use the cache if the object has elements and | 6352 // We do not use the cache if the object has elements and |
| 6353 // therefore it does not make sense to cache the property names | 6353 // therefore it does not make sense to cache the property names |
| 6354 // for arguments objects. Arguments objects will always have | 6354 // for arguments objects. Arguments objects will always have |
| 6355 // elements. | 6355 // elements. |
| 6356 // Wrapped strings have elements, but don't have an elements | 6356 // Wrapped strings have elements, but don't have an elements |
| 6357 // array or dictionary. So the fast inline test for whether to | 6357 // array or dictionary. So the fast inline test for whether to |
| 6358 // use the cache says yes, so we should not create a cache. | 6358 // use the cache says yes, so we should not create a cache. |
| 6359 bool cache_enum_keys = | 6359 bool cache_enum_keys = |
| 6360 ((current->map()->constructor() != *arguments_function) && | 6360 ((current->map()->constructor() != *arguments_function) && |
| 6361 !current->IsJSValue() && | 6361 !current->IsJSValue() && |
| 6362 !current->IsAccessCheckNeeded() && | 6362 !current->IsAccessCheckNeeded() && |
| 6363 !current->HasNamedInterceptor() && | 6363 !current->HasNamedInterceptor() && |
| 6364 !current->HasIndexedInterceptor()); | 6364 !current->HasIndexedInterceptor()); |
| 6365 // Compute the property keys and cache them if possible. | 6365 // Compute the property keys and cache them if possible. |
| 6366 ASSIGN_RETURN_ON_EXCEPTION( | 6366 ASSIGN_RETURN_ON_EXCEPTION( |
| 6367 isolate, content, | 6367 isolate, content, |
| 6368 FixedArray::UnionOfKeys( | 6368 FixedArray::UnionOfKeys( |
| 6369 content, GetEnumPropertyKeys(current, cache_enum_keys)), | 6369 content, GetEnumPropertyKeys(current, cache_enum_keys)), |
| 6370 FixedArray); | 6370 FixedArray); |
| 6371 ASSERT(ContainsOnlyValidKeys(content)); | 6371 DCHECK(ContainsOnlyValidKeys(content)); |
| 6372 | 6372 |
| 6373 // Add the property keys from the interceptor. | 6373 // Add the property keys from the interceptor. |
| 6374 if (current->HasNamedInterceptor()) { | 6374 if (current->HasNamedInterceptor()) { |
| 6375 Handle<JSObject> result; | 6375 Handle<JSObject> result; |
| 6376 if (JSObject::GetKeysForNamedInterceptor( | 6376 if (JSObject::GetKeysForNamedInterceptor( |
| 6377 current, object).ToHandle(&result)) { | 6377 current, object).ToHandle(&result)) { |
| 6378 ASSIGN_RETURN_ON_EXCEPTION( | 6378 ASSIGN_RETURN_ON_EXCEPTION( |
| 6379 isolate, content, | 6379 isolate, content, |
| 6380 FixedArray::AddKeysFromArrayLike(content, result), | 6380 FixedArray::AddKeysFromArrayLike(content, result), |
| 6381 FixedArray); | 6381 FixedArray); |
| 6382 } | 6382 } |
| 6383 ASSERT(ContainsOnlyValidKeys(content)); | 6383 DCHECK(ContainsOnlyValidKeys(content)); |
| 6384 } | 6384 } |
| 6385 | 6385 |
| 6386 // If we only want own properties we bail out after the first | 6386 // If we only want own properties we bail out after the first |
| 6387 // iteration. | 6387 // iteration. |
| 6388 if (type == OWN_ONLY) break; | 6388 if (type == OWN_ONLY) break; |
| 6389 } | 6389 } |
| 6390 return content; | 6390 return content; |
| 6391 } | 6391 } |
| 6392 | 6392 |
| 6393 | 6393 |
| 6394 // Try to update an accessor in an elements dictionary. Return true if the | 6394 // Try to update an accessor in an elements dictionary. Return true if the |
| 6395 // update succeeded, and false otherwise. | 6395 // update succeeded, and false otherwise. |
| 6396 static bool UpdateGetterSetterInDictionary( | 6396 static bool UpdateGetterSetterInDictionary( |
| 6397 SeededNumberDictionary* dictionary, | 6397 SeededNumberDictionary* dictionary, |
| 6398 uint32_t index, | 6398 uint32_t index, |
| 6399 Object* getter, | 6399 Object* getter, |
| 6400 Object* setter, | 6400 Object* setter, |
| 6401 PropertyAttributes attributes) { | 6401 PropertyAttributes attributes) { |
| 6402 int entry = dictionary->FindEntry(index); | 6402 int entry = dictionary->FindEntry(index); |
| 6403 if (entry != SeededNumberDictionary::kNotFound) { | 6403 if (entry != SeededNumberDictionary::kNotFound) { |
| 6404 Object* result = dictionary->ValueAt(entry); | 6404 Object* result = dictionary->ValueAt(entry); |
| 6405 PropertyDetails details = dictionary->DetailsAt(entry); | 6405 PropertyDetails details = dictionary->DetailsAt(entry); |
| 6406 if (details.type() == CALLBACKS && result->IsAccessorPair()) { | 6406 if (details.type() == CALLBACKS && result->IsAccessorPair()) { |
| 6407 ASSERT(!details.IsDontDelete()); | 6407 DCHECK(!details.IsDontDelete()); |
| 6408 if (details.attributes() != attributes) { | 6408 if (details.attributes() != attributes) { |
| 6409 dictionary->DetailsAtPut( | 6409 dictionary->DetailsAtPut( |
| 6410 entry, | 6410 entry, |
| 6411 PropertyDetails(attributes, CALLBACKS, index)); | 6411 PropertyDetails(attributes, CALLBACKS, index)); |
| 6412 } | 6412 } |
| 6413 AccessorPair::cast(result)->SetComponents(getter, setter); | 6413 AccessorPair::cast(result)->SetComponents(getter, setter); |
| 6414 return true; | 6414 return true; |
| 6415 } | 6415 } |
| 6416 } | 6416 } |
| 6417 return false; | 6417 return false; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6553 void JSObject::SetElementCallback(Handle<JSObject> object, | 6553 void JSObject::SetElementCallback(Handle<JSObject> object, |
| 6554 uint32_t index, | 6554 uint32_t index, |
| 6555 Handle<Object> structure, | 6555 Handle<Object> structure, |
| 6556 PropertyAttributes attributes) { | 6556 PropertyAttributes attributes) { |
| 6557 Heap* heap = object->GetHeap(); | 6557 Heap* heap = object->GetHeap(); |
| 6558 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6558 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
| 6559 | 6559 |
| 6560 // Normalize elements to make this operation simple. | 6560 // Normalize elements to make this operation simple. |
| 6561 bool had_dictionary_elements = object->HasDictionaryElements(); | 6561 bool had_dictionary_elements = object->HasDictionaryElements(); |
| 6562 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6562 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 6563 ASSERT(object->HasDictionaryElements() || | 6563 DCHECK(object->HasDictionaryElements() || |
| 6564 object->HasDictionaryArgumentsElements()); | 6564 object->HasDictionaryArgumentsElements()); |
| 6565 // Update the dictionary with the new CALLBACKS property. | 6565 // Update the dictionary with the new CALLBACKS property. |
| 6566 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6566 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
| 6567 details); | 6567 details); |
| 6568 dictionary->set_requires_slow_elements(); | 6568 dictionary->set_requires_slow_elements(); |
| 6569 | 6569 |
| 6570 // Update the dictionary backing store on the object. | 6570 // Update the dictionary backing store on the object. |
| 6571 if (object->elements()->map() == heap->sloppy_arguments_elements_map()) { | 6571 if (object->elements()->map() == heap->sloppy_arguments_elements_map()) { |
| 6572 // Also delete any parameter alias. | 6572 // Also delete any parameter alias. |
| 6573 // | 6573 // |
| (...skipping 20 matching lines...) Expand all Loading... |
| 6594 Handle<Name> name, | 6594 Handle<Name> name, |
| 6595 Handle<Object> structure, | 6595 Handle<Object> structure, |
| 6596 PropertyAttributes attributes) { | 6596 PropertyAttributes attributes) { |
| 6597 // Normalize object to make this operation simple. | 6597 // Normalize object to make this operation simple. |
| 6598 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 6598 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 6599 | 6599 |
| 6600 // For the global object allocate a new map to invalidate the global inline | 6600 // For the global object allocate a new map to invalidate the global inline |
| 6601 // caches which have a global property cell reference directly in the code. | 6601 // caches which have a global property cell reference directly in the code. |
| 6602 if (object->IsGlobalObject()) { | 6602 if (object->IsGlobalObject()) { |
| 6603 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 6603 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 6604 ASSERT(new_map->is_dictionary_map()); | 6604 DCHECK(new_map->is_dictionary_map()); |
| 6605 JSObject::MigrateToMap(object, new_map); | 6605 JSObject::MigrateToMap(object, new_map); |
| 6606 | 6606 |
| 6607 // When running crankshaft, changing the map is not enough. We | 6607 // When running crankshaft, changing the map is not enough. We |
| 6608 // need to deoptimize all functions that rely on this global | 6608 // need to deoptimize all functions that rely on this global |
| 6609 // object. | 6609 // object. |
| 6610 Deoptimizer::DeoptimizeGlobalObject(*object); | 6610 Deoptimizer::DeoptimizeGlobalObject(*object); |
| 6611 } | 6611 } |
| 6612 | 6612 |
| 6613 // Update the dictionary with the new CALLBACKS property. | 6613 // Update the dictionary with the new CALLBACKS property. |
| 6614 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6614 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 6626 if (object->IsAccessCheckNeeded() && | 6626 if (object->IsAccessCheckNeeded() && |
| 6627 !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { | 6627 !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { |
| 6628 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); | 6628 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); |
| 6629 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 6629 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 6630 return isolate->factory()->undefined_value(); | 6630 return isolate->factory()->undefined_value(); |
| 6631 } | 6631 } |
| 6632 | 6632 |
| 6633 if (object->IsJSGlobalProxy()) { | 6633 if (object->IsJSGlobalProxy()) { |
| 6634 PrototypeIterator iter(isolate, object); | 6634 PrototypeIterator iter(isolate, object); |
| 6635 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); | 6635 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); |
| 6636 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 6636 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 6637 DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), | 6637 DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), |
| 6638 name, getter, setter, attributes); | 6638 name, getter, setter, attributes); |
| 6639 return isolate->factory()->undefined_value(); | 6639 return isolate->factory()->undefined_value(); |
| 6640 } | 6640 } |
| 6641 | 6641 |
| 6642 // Make sure that the top context does not change when doing callbacks or | 6642 // Make sure that the top context does not change when doing callbacks or |
| 6643 // interceptor calls. | 6643 // interceptor calls. |
| 6644 AssertNoContextChange ncc(isolate); | 6644 AssertNoContextChange ncc(isolate); |
| 6645 | 6645 |
| 6646 // Try to flatten before operating on the string. | 6646 // Try to flatten before operating on the string. |
| 6647 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); | 6647 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); |
| 6648 | 6648 |
| 6649 uint32_t index = 0; | 6649 uint32_t index = 0; |
| 6650 bool is_element = name->AsArrayIndex(&index); | 6650 bool is_element = name->AsArrayIndex(&index); |
| 6651 | 6651 |
| 6652 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6652 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 6653 bool is_observed = object->map()->is_observed() && | 6653 bool is_observed = object->map()->is_observed() && |
| 6654 *name != isolate->heap()->hidden_string(); | 6654 *name != isolate->heap()->hidden_string(); |
| 6655 bool preexists = false; | 6655 bool preexists = false; |
| 6656 if (is_observed) { | 6656 if (is_observed) { |
| 6657 if (is_element) { | 6657 if (is_element) { |
| 6658 Maybe<bool> maybe = HasOwnElement(object, index); | 6658 Maybe<bool> maybe = HasOwnElement(object, index); |
| 6659 // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used | 6659 // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used |
| 6660 // uninitialized in this function". | 6660 // uninitialized in this function". |
| 6661 if (!maybe.has_value) { | 6661 if (!maybe.has_value) { |
| 6662 ASSERT(false); | 6662 DCHECK(false); |
| 6663 return isolate->factory()->undefined_value(); | 6663 return isolate->factory()->undefined_value(); |
| 6664 } | 6664 } |
| 6665 preexists = maybe.value; | 6665 preexists = maybe.value; |
| 6666 if (preexists && GetOwnElementAccessorPair(object, index).is_null()) { | 6666 if (preexists && GetOwnElementAccessorPair(object, index).is_null()) { |
| 6667 old_value = | 6667 old_value = |
| 6668 Object::GetElement(isolate, object, index).ToHandleChecked(); | 6668 Object::GetElement(isolate, object, index).ToHandleChecked(); |
| 6669 } | 6669 } |
| 6670 } else { | 6670 } else { |
| 6671 LookupResult lookup(isolate); | 6671 LookupResult lookup(isolate); |
| 6672 object->LookupOwn(name, &lookup, true); | 6672 object->LookupOwn(name, &lookup, true); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6720 // the slow case. | 6720 // the slow case. |
| 6721 return false; | 6721 return false; |
| 6722 } | 6722 } |
| 6723 | 6723 |
| 6724 | 6724 |
| 6725 bool JSObject::DefineFastAccessor(Handle<JSObject> object, | 6725 bool JSObject::DefineFastAccessor(Handle<JSObject> object, |
| 6726 Handle<Name> name, | 6726 Handle<Name> name, |
| 6727 AccessorComponent component, | 6727 AccessorComponent component, |
| 6728 Handle<Object> accessor, | 6728 Handle<Object> accessor, |
| 6729 PropertyAttributes attributes) { | 6729 PropertyAttributes attributes) { |
| 6730 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); | 6730 DCHECK(accessor->IsSpecFunction() || accessor->IsUndefined()); |
| 6731 Isolate* isolate = object->GetIsolate(); | 6731 Isolate* isolate = object->GetIsolate(); |
| 6732 LookupResult result(isolate); | 6732 LookupResult result(isolate); |
| 6733 object->LookupOwn(name, &result); | 6733 object->LookupOwn(name, &result); |
| 6734 | 6734 |
| 6735 if (result.IsFound() && !result.IsPropertyCallbacks()) { | 6735 if (result.IsFound() && !result.IsPropertyCallbacks()) { |
| 6736 return false; | 6736 return false; |
| 6737 } | 6737 } |
| 6738 | 6738 |
| 6739 // Return success if the same accessor with the same attributes already exist. | 6739 // Return success if the same accessor with the same attributes already exist. |
| 6740 AccessorPair* source_accessors = NULL; | 6740 AccessorPair* source_accessors = NULL; |
| 6741 if (result.IsPropertyCallbacks()) { | 6741 if (result.IsPropertyCallbacks()) { |
| 6742 Object* callback_value = result.GetCallbackObject(); | 6742 Object* callback_value = result.GetCallbackObject(); |
| 6743 if (callback_value->IsAccessorPair()) { | 6743 if (callback_value->IsAccessorPair()) { |
| 6744 source_accessors = AccessorPair::cast(callback_value); | 6744 source_accessors = AccessorPair::cast(callback_value); |
| 6745 Object* entry = source_accessors->get(component); | 6745 Object* entry = source_accessors->get(component); |
| 6746 if (entry == *accessor && result.GetAttributes() == attributes) { | 6746 if (entry == *accessor && result.GetAttributes() == attributes) { |
| 6747 return true; | 6747 return true; |
| 6748 } | 6748 } |
| 6749 } else { | 6749 } else { |
| 6750 return false; | 6750 return false; |
| 6751 } | 6751 } |
| 6752 | 6752 |
| 6753 int descriptor_number = result.GetDescriptorIndex(); | 6753 int descriptor_number = result.GetDescriptorIndex(); |
| 6754 | 6754 |
| 6755 object->map()->LookupTransition(*object, *name, &result); | 6755 object->map()->LookupTransition(*object, *name, &result); |
| 6756 | 6756 |
| 6757 if (result.IsFound()) { | 6757 if (result.IsFound()) { |
| 6758 Handle<Map> target(result.GetTransitionTarget()); | 6758 Handle<Map> target(result.GetTransitionTarget()); |
| 6759 ASSERT(target->NumberOfOwnDescriptors() == | 6759 DCHECK(target->NumberOfOwnDescriptors() == |
| 6760 object->map()->NumberOfOwnDescriptors()); | 6760 object->map()->NumberOfOwnDescriptors()); |
| 6761 // This works since descriptors are sorted in order of addition. | 6761 // This works since descriptors are sorted in order of addition. |
| 6762 ASSERT(Name::Equals( | 6762 DCHECK(Name::Equals( |
| 6763 handle(object->map()->instance_descriptors()->GetKey( | 6763 handle(object->map()->instance_descriptors()->GetKey( |
| 6764 descriptor_number)), | 6764 descriptor_number)), |
| 6765 name)); | 6765 name)); |
| 6766 return TryAccessorTransition(object, target, descriptor_number, | 6766 return TryAccessorTransition(object, target, descriptor_number, |
| 6767 component, accessor, attributes); | 6767 component, accessor, attributes); |
| 6768 } | 6768 } |
| 6769 } else { | 6769 } else { |
| 6770 // If not, lookup a transition. | 6770 // If not, lookup a transition. |
| 6771 object->map()->LookupTransition(*object, *name, &result); | 6771 object->map()->LookupTransition(*object, *name, &result); |
| 6772 | 6772 |
| 6773 // If there is a transition, try to follow it. | 6773 // If there is a transition, try to follow it. |
| 6774 if (result.IsFound()) { | 6774 if (result.IsFound()) { |
| 6775 Handle<Map> target(result.GetTransitionTarget()); | 6775 Handle<Map> target(result.GetTransitionTarget()); |
| 6776 int descriptor_number = target->LastAdded(); | 6776 int descriptor_number = target->LastAdded(); |
| 6777 ASSERT(Name::Equals(name, | 6777 DCHECK(Name::Equals(name, |
| 6778 handle(target->instance_descriptors()->GetKey(descriptor_number)))); | 6778 handle(target->instance_descriptors()->GetKey(descriptor_number)))); |
| 6779 return TryAccessorTransition(object, target, descriptor_number, | 6779 return TryAccessorTransition(object, target, descriptor_number, |
| 6780 component, accessor, attributes); | 6780 component, accessor, attributes); |
| 6781 } | 6781 } |
| 6782 } | 6782 } |
| 6783 | 6783 |
| 6784 // If there is no transition yet, add a transition to the a new accessor pair | 6784 // If there is no transition yet, add a transition to the a new accessor pair |
| 6785 // containing the accessor. Allocate a new pair if there were no source | 6785 // containing the accessor. Allocate a new pair if there were no source |
| 6786 // accessors. Otherwise, copy the pair and modify the accessor. | 6786 // accessors. Otherwise, copy the pair and modify the accessor. |
| 6787 Handle<AccessorPair> accessors = source_accessors != NULL | 6787 Handle<AccessorPair> accessors = source_accessors != NULL |
| (...skipping 20 matching lines...) Expand all Loading... |
| 6808 if (object->IsAccessCheckNeeded() && | 6808 if (object->IsAccessCheckNeeded() && |
| 6809 !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { | 6809 !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { |
| 6810 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); | 6810 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); |
| 6811 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 6811 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 6812 return factory->undefined_value(); | 6812 return factory->undefined_value(); |
| 6813 } | 6813 } |
| 6814 | 6814 |
| 6815 if (object->IsJSGlobalProxy()) { | 6815 if (object->IsJSGlobalProxy()) { |
| 6816 PrototypeIterator iter(isolate, object); | 6816 PrototypeIterator iter(isolate, object); |
| 6817 if (iter.IsAtEnd()) return object; | 6817 if (iter.IsAtEnd()) return object; |
| 6818 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 6818 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 6819 return SetAccessor( | 6819 return SetAccessor( |
| 6820 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), info); | 6820 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), info); |
| 6821 } | 6821 } |
| 6822 | 6822 |
| 6823 // Make sure that the top context does not change when doing callbacks or | 6823 // Make sure that the top context does not change when doing callbacks or |
| 6824 // interceptor calls. | 6824 // interceptor calls. |
| 6825 AssertNoContextChange ncc(isolate); | 6825 AssertNoContextChange ncc(isolate); |
| 6826 | 6826 |
| 6827 // Try to flatten before operating on the string. | 6827 // Try to flatten before operating on the string. |
| 6828 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); | 6828 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6943 | 6943 |
| 6944 Object* JSObject::SlowReverseLookup(Object* value) { | 6944 Object* JSObject::SlowReverseLookup(Object* value) { |
| 6945 if (HasFastProperties()) { | 6945 if (HasFastProperties()) { |
| 6946 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); | 6946 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); |
| 6947 DescriptorArray* descs = map()->instance_descriptors(); | 6947 DescriptorArray* descs = map()->instance_descriptors(); |
| 6948 for (int i = 0; i < number_of_own_descriptors; i++) { | 6948 for (int i = 0; i < number_of_own_descriptors; i++) { |
| 6949 if (descs->GetType(i) == FIELD) { | 6949 if (descs->GetType(i) == FIELD) { |
| 6950 Object* property = | 6950 Object* property = |
| 6951 RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i)); | 6951 RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i)); |
| 6952 if (descs->GetDetails(i).representation().IsDouble()) { | 6952 if (descs->GetDetails(i).representation().IsDouble()) { |
| 6953 ASSERT(property->IsMutableHeapNumber()); | 6953 DCHECK(property->IsMutableHeapNumber()); |
| 6954 if (value->IsNumber() && property->Number() == value->Number()) { | 6954 if (value->IsNumber() && property->Number() == value->Number()) { |
| 6955 return descs->GetKey(i); | 6955 return descs->GetKey(i); |
| 6956 } | 6956 } |
| 6957 } else if (property == value) { | 6957 } else if (property == value) { |
| 6958 return descs->GetKey(i); | 6958 return descs->GetKey(i); |
| 6959 } | 6959 } |
| 6960 } else if (descs->GetType(i) == CONSTANT) { | 6960 } else if (descs->GetType(i) == CONSTANT) { |
| 6961 if (descs->GetConstant(i) == value) { | 6961 if (descs->GetConstant(i) == value) { |
| 6962 return descs->GetKey(i); | 6962 return descs->GetKey(i); |
| 6963 } | 6963 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 6988 } | 6988 } |
| 6989 new_bit_field3 = ConstructionCount::update(new_bit_field3, | 6989 new_bit_field3 = ConstructionCount::update(new_bit_field3, |
| 6990 JSFunction::kNoSlackTracking); | 6990 JSFunction::kNoSlackTracking); |
| 6991 result->set_bit_field3(new_bit_field3); | 6991 result->set_bit_field3(new_bit_field3); |
| 6992 return result; | 6992 return result; |
| 6993 } | 6993 } |
| 6994 | 6994 |
| 6995 | 6995 |
| 6996 Handle<Map> Map::Normalize(Handle<Map> fast_map, | 6996 Handle<Map> Map::Normalize(Handle<Map> fast_map, |
| 6997 PropertyNormalizationMode mode) { | 6997 PropertyNormalizationMode mode) { |
| 6998 ASSERT(!fast_map->is_dictionary_map()); | 6998 DCHECK(!fast_map->is_dictionary_map()); |
| 6999 | 6999 |
| 7000 Isolate* isolate = fast_map->GetIsolate(); | 7000 Isolate* isolate = fast_map->GetIsolate(); |
| 7001 Handle<NormalizedMapCache> cache( | 7001 Handle<NormalizedMapCache> cache( |
| 7002 isolate->context()->native_context()->normalized_map_cache()); | 7002 isolate->context()->native_context()->normalized_map_cache()); |
| 7003 | 7003 |
| 7004 Handle<Map> new_map; | 7004 Handle<Map> new_map; |
| 7005 if (cache->Get(fast_map, mode).ToHandle(&new_map)) { | 7005 if (cache->Get(fast_map, mode).ToHandle(&new_map)) { |
| 7006 #ifdef VERIFY_HEAP | 7006 #ifdef VERIFY_HEAP |
| 7007 if (FLAG_verify_heap) { | 7007 if (FLAG_verify_heap) { |
| 7008 new_map->SharedMapVerify(); | 7008 new_map->SharedMapVerify(); |
| 7009 } | 7009 } |
| 7010 #endif | 7010 #endif |
| 7011 #ifdef ENABLE_SLOW_ASSERTS | 7011 #ifdef ENABLE_SLOW_DCHECKS |
| 7012 if (FLAG_enable_slow_asserts) { | 7012 if (FLAG_enable_slow_asserts) { |
| 7013 // The cached map should match newly created normalized map bit-by-bit, | 7013 // The cached map should match newly created normalized map bit-by-bit, |
| 7014 // except for the code cache, which can contain some ics which can be | 7014 // except for the code cache, which can contain some ics which can be |
| 7015 // applied to the shared map. | 7015 // applied to the shared map. |
| 7016 Handle<Map> fresh = Map::CopyNormalized( | 7016 Handle<Map> fresh = Map::CopyNormalized( |
| 7017 fast_map, mode, SHARED_NORMALIZED_MAP); | 7017 fast_map, mode, SHARED_NORMALIZED_MAP); |
| 7018 | 7018 |
| 7019 ASSERT(memcmp(fresh->address(), | 7019 DCHECK(memcmp(fresh->address(), |
| 7020 new_map->address(), | 7020 new_map->address(), |
| 7021 Map::kCodeCacheOffset) == 0); | 7021 Map::kCodeCacheOffset) == 0); |
| 7022 STATIC_ASSERT(Map::kDependentCodeOffset == | 7022 STATIC_ASSERT(Map::kDependentCodeOffset == |
| 7023 Map::kCodeCacheOffset + kPointerSize); | 7023 Map::kCodeCacheOffset + kPointerSize); |
| 7024 int offset = Map::kDependentCodeOffset + kPointerSize; | 7024 int offset = Map::kDependentCodeOffset + kPointerSize; |
| 7025 ASSERT(memcmp(fresh->address() + offset, | 7025 DCHECK(memcmp(fresh->address() + offset, |
| 7026 new_map->address() + offset, | 7026 new_map->address() + offset, |
| 7027 Map::kSize - offset) == 0); | 7027 Map::kSize - offset) == 0); |
| 7028 } | 7028 } |
| 7029 #endif | 7029 #endif |
| 7030 } else { | 7030 } else { |
| 7031 new_map = Map::CopyNormalized(fast_map, mode, SHARED_NORMALIZED_MAP); | 7031 new_map = Map::CopyNormalized(fast_map, mode, SHARED_NORMALIZED_MAP); |
| 7032 cache->Set(fast_map, new_map); | 7032 cache->Set(fast_map, new_map); |
| 7033 isolate->counters()->normalized_maps()->Increment(); | 7033 isolate->counters()->normalized_maps()->Increment(); |
| 7034 } | 7034 } |
| 7035 fast_map->NotifyLeafMapLayoutChange(); | 7035 fast_map->NotifyLeafMapLayoutChange(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7080 return result; | 7080 return result; |
| 7081 } | 7081 } |
| 7082 | 7082 |
| 7083 | 7083 |
| 7084 Handle<Map> Map::ShareDescriptor(Handle<Map> map, | 7084 Handle<Map> Map::ShareDescriptor(Handle<Map> map, |
| 7085 Handle<DescriptorArray> descriptors, | 7085 Handle<DescriptorArray> descriptors, |
| 7086 Descriptor* descriptor) { | 7086 Descriptor* descriptor) { |
| 7087 // Sanity check. This path is only to be taken if the map owns its descriptor | 7087 // Sanity check. This path is only to be taken if the map owns its descriptor |
| 7088 // array, implying that its NumberOfOwnDescriptors equals the number of | 7088 // array, implying that its NumberOfOwnDescriptors equals the number of |
| 7089 // descriptors in the descriptor array. | 7089 // descriptors in the descriptor array. |
| 7090 ASSERT(map->NumberOfOwnDescriptors() == | 7090 DCHECK(map->NumberOfOwnDescriptors() == |
| 7091 map->instance_descriptors()->number_of_descriptors()); | 7091 map->instance_descriptors()->number_of_descriptors()); |
| 7092 | 7092 |
| 7093 Handle<Map> result = CopyDropDescriptors(map); | 7093 Handle<Map> result = CopyDropDescriptors(map); |
| 7094 Handle<Name> name = descriptor->GetKey(); | 7094 Handle<Name> name = descriptor->GetKey(); |
| 7095 Handle<TransitionArray> transitions = | 7095 Handle<TransitionArray> transitions = |
| 7096 TransitionArray::CopyInsert(map, name, result, SIMPLE_TRANSITION); | 7096 TransitionArray::CopyInsert(map, name, result, SIMPLE_TRANSITION); |
| 7097 | 7097 |
| 7098 // Ensure there's space for the new descriptor in the shared descriptor array. | 7098 // Ensure there's space for the new descriptor in the shared descriptor array. |
| 7099 if (descriptors->NumberOfSlackDescriptors() == 0) { | 7099 if (descriptors->NumberOfSlackDescriptors() == 0) { |
| 7100 int old_size = descriptors->number_of_descriptors(); | 7100 int old_size = descriptors->number_of_descriptors(); |
| 7101 if (old_size == 0) { | 7101 if (old_size == 0) { |
| 7102 descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1); | 7102 descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1); |
| 7103 } else { | 7103 } else { |
| 7104 EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2); | 7104 EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2); |
| 7105 descriptors = handle(map->instance_descriptors()); | 7105 descriptors = handle(map->instance_descriptors()); |
| 7106 } | 7106 } |
| 7107 } | 7107 } |
| 7108 | 7108 |
| 7109 // Commit the state atomically. | 7109 // Commit the state atomically. |
| 7110 DisallowHeapAllocation no_gc; | 7110 DisallowHeapAllocation no_gc; |
| 7111 | 7111 |
| 7112 descriptors->Append(descriptor); | 7112 descriptors->Append(descriptor); |
| 7113 result->SetBackPointer(*map); | 7113 result->SetBackPointer(*map); |
| 7114 result->InitializeDescriptors(*descriptors); | 7114 result->InitializeDescriptors(*descriptors); |
| 7115 | 7115 |
| 7116 ASSERT(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); | 7116 DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); |
| 7117 | 7117 |
| 7118 map->set_transitions(*transitions); | 7118 map->set_transitions(*transitions); |
| 7119 map->set_owns_descriptors(false); | 7119 map->set_owns_descriptors(false); |
| 7120 | 7120 |
| 7121 return result; | 7121 return result; |
| 7122 } | 7122 } |
| 7123 | 7123 |
| 7124 | 7124 |
| 7125 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, | 7125 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, |
| 7126 Handle<DescriptorArray> descriptors, | 7126 Handle<DescriptorArray> descriptors, |
| 7127 TransitionFlag flag, | 7127 TransitionFlag flag, |
| 7128 MaybeHandle<Name> maybe_name, | 7128 MaybeHandle<Name> maybe_name, |
| 7129 SimpleTransitionFlag simple_flag) { | 7129 SimpleTransitionFlag simple_flag) { |
| 7130 ASSERT(descriptors->IsSortedNoDuplicates()); | 7130 DCHECK(descriptors->IsSortedNoDuplicates()); |
| 7131 | 7131 |
| 7132 Handle<Map> result = CopyDropDescriptors(map); | 7132 Handle<Map> result = CopyDropDescriptors(map); |
| 7133 result->InitializeDescriptors(*descriptors); | 7133 result->InitializeDescriptors(*descriptors); |
| 7134 | 7134 |
| 7135 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { | 7135 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { |
| 7136 Handle<Name> name; | 7136 Handle<Name> name; |
| 7137 CHECK(maybe_name.ToHandle(&name)); | 7137 CHECK(maybe_name.ToHandle(&name)); |
| 7138 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( | 7138 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( |
| 7139 map, name, result, simple_flag); | 7139 map, name, result, simple_flag); |
| 7140 map->set_transitions(*transitions); | 7140 map->set_transitions(*transitions); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 7151 | 7151 |
| 7152 return result; | 7152 return result; |
| 7153 } | 7153 } |
| 7154 | 7154 |
| 7155 | 7155 |
| 7156 // Since this method is used to rewrite an existing transition tree, it can | 7156 // Since this method is used to rewrite an existing transition tree, it can |
| 7157 // always insert transitions without checking. | 7157 // always insert transitions without checking. |
| 7158 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, | 7158 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
| 7159 int new_descriptor, | 7159 int new_descriptor, |
| 7160 Handle<DescriptorArray> descriptors) { | 7160 Handle<DescriptorArray> descriptors) { |
| 7161 ASSERT(descriptors->IsSortedNoDuplicates()); | 7161 DCHECK(descriptors->IsSortedNoDuplicates()); |
| 7162 | 7162 |
| 7163 Handle<Map> result = CopyDropDescriptors(map); | 7163 Handle<Map> result = CopyDropDescriptors(map); |
| 7164 | 7164 |
| 7165 result->InitializeDescriptors(*descriptors); | 7165 result->InitializeDescriptors(*descriptors); |
| 7166 result->SetNumberOfOwnDescriptors(new_descriptor + 1); | 7166 result->SetNumberOfOwnDescriptors(new_descriptor + 1); |
| 7167 | 7167 |
| 7168 int unused_property_fields = map->unused_property_fields(); | 7168 int unused_property_fields = map->unused_property_fields(); |
| 7169 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { | 7169 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { |
| 7170 unused_property_fields = map->unused_property_fields() - 1; | 7170 unused_property_fields = map->unused_property_fields() - 1; |
| 7171 if (unused_property_fields < 0) { | 7171 if (unused_property_fields < 0) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 7183 map->set_transitions(*transitions); | 7183 map->set_transitions(*transitions); |
| 7184 result->SetBackPointer(*map); | 7184 result->SetBackPointer(*map); |
| 7185 | 7185 |
| 7186 return result; | 7186 return result; |
| 7187 } | 7187 } |
| 7188 | 7188 |
| 7189 | 7189 |
| 7190 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, | 7190 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, |
| 7191 TransitionFlag flag) { | 7191 TransitionFlag flag) { |
| 7192 if (flag == INSERT_TRANSITION) { | 7192 if (flag == INSERT_TRANSITION) { |
| 7193 ASSERT(!map->HasElementsTransition() || | 7193 DCHECK(!map->HasElementsTransition() || |
| 7194 ((map->elements_transition_map()->elements_kind() == | 7194 ((map->elements_transition_map()->elements_kind() == |
| 7195 DICTIONARY_ELEMENTS || | 7195 DICTIONARY_ELEMENTS || |
| 7196 IsExternalArrayElementsKind( | 7196 IsExternalArrayElementsKind( |
| 7197 map->elements_transition_map()->elements_kind())) && | 7197 map->elements_transition_map()->elements_kind())) && |
| 7198 (kind == DICTIONARY_ELEMENTS || | 7198 (kind == DICTIONARY_ELEMENTS || |
| 7199 IsExternalArrayElementsKind(kind)))); | 7199 IsExternalArrayElementsKind(kind)))); |
| 7200 ASSERT(!IsFastElementsKind(kind) || | 7200 DCHECK(!IsFastElementsKind(kind) || |
| 7201 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); | 7201 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); |
| 7202 ASSERT(kind != map->elements_kind()); | 7202 DCHECK(kind != map->elements_kind()); |
| 7203 } | 7203 } |
| 7204 | 7204 |
| 7205 bool insert_transition = | 7205 bool insert_transition = |
| 7206 flag == INSERT_TRANSITION && !map->HasElementsTransition(); | 7206 flag == INSERT_TRANSITION && !map->HasElementsTransition(); |
| 7207 | 7207 |
| 7208 if (insert_transition && map->owns_descriptors()) { | 7208 if (insert_transition && map->owns_descriptors()) { |
| 7209 // In case the map owned its own descriptors, share the descriptors and | 7209 // In case the map owned its own descriptors, share the descriptors and |
| 7210 // transfer ownership to the new map. | 7210 // transfer ownership to the new map. |
| 7211 Handle<Map> new_map = CopyDropDescriptors(map); | 7211 Handle<Map> new_map = CopyDropDescriptors(map); |
| 7212 | 7212 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 7229 if (insert_transition) { | 7229 if (insert_transition) { |
| 7230 SetElementsTransitionMap(map, new_map); | 7230 SetElementsTransitionMap(map, new_map); |
| 7231 new_map->SetBackPointer(*map); | 7231 new_map->SetBackPointer(*map); |
| 7232 } | 7232 } |
| 7233 | 7233 |
| 7234 return new_map; | 7234 return new_map; |
| 7235 } | 7235 } |
| 7236 | 7236 |
| 7237 | 7237 |
| 7238 Handle<Map> Map::CopyForObserved(Handle<Map> map) { | 7238 Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
| 7239 ASSERT(!map->is_observed()); | 7239 DCHECK(!map->is_observed()); |
| 7240 | 7240 |
| 7241 Isolate* isolate = map->GetIsolate(); | 7241 Isolate* isolate = map->GetIsolate(); |
| 7242 | 7242 |
| 7243 // In case the map owned its own descriptors, share the descriptors and | 7243 // In case the map owned its own descriptors, share the descriptors and |
| 7244 // transfer ownership to the new map. | 7244 // transfer ownership to the new map. |
| 7245 Handle<Map> new_map; | 7245 Handle<Map> new_map; |
| 7246 if (map->owns_descriptors()) { | 7246 if (map->owns_descriptors()) { |
| 7247 new_map = CopyDropDescriptors(map); | 7247 new_map = CopyDropDescriptors(map); |
| 7248 } else { | 7248 } else { |
| 7249 new_map = Copy(map); | 7249 new_map = Copy(map); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7320 | 7320 |
| 7321 | 7321 |
| 7322 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) { | 7322 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) { |
| 7323 PropertyDetails details = GetDetails(descriptor); | 7323 PropertyDetails details = GetDetails(descriptor); |
| 7324 switch (details.type()) { | 7324 switch (details.type()) { |
| 7325 case FIELD: | 7325 case FIELD: |
| 7326 return value->FitsRepresentation(details.representation()) && | 7326 return value->FitsRepresentation(details.representation()) && |
| 7327 GetFieldType(descriptor)->NowContains(value); | 7327 GetFieldType(descriptor)->NowContains(value); |
| 7328 | 7328 |
| 7329 case CONSTANT: | 7329 case CONSTANT: |
| 7330 ASSERT(GetConstant(descriptor) != value || | 7330 DCHECK(GetConstant(descriptor) != value || |
| 7331 value->FitsRepresentation(details.representation())); | 7331 value->FitsRepresentation(details.representation())); |
| 7332 return GetConstant(descriptor) == value; | 7332 return GetConstant(descriptor) == value; |
| 7333 | 7333 |
| 7334 case CALLBACKS: | 7334 case CALLBACKS: |
| 7335 return false; | 7335 return false; |
| 7336 | 7336 |
| 7337 case NORMAL: | 7337 case NORMAL: |
| 7338 case INTERCEPTOR: | 7338 case INTERCEPTOR: |
| 7339 case HANDLER: | 7339 case HANDLER: |
| 7340 case NONEXISTENT: | 7340 case NONEXISTENT: |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7511 | 7511 |
| 7512 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map, | 7512 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map, |
| 7513 Handle<DescriptorArray> descriptors, | 7513 Handle<DescriptorArray> descriptors, |
| 7514 Descriptor* descriptor, | 7514 Descriptor* descriptor, |
| 7515 int insertion_index, | 7515 int insertion_index, |
| 7516 TransitionFlag flag) { | 7516 TransitionFlag flag) { |
| 7517 // Ensure the key is unique. | 7517 // Ensure the key is unique. |
| 7518 descriptor->KeyToUniqueName(); | 7518 descriptor->KeyToUniqueName(); |
| 7519 | 7519 |
| 7520 Handle<Name> key = descriptor->GetKey(); | 7520 Handle<Name> key = descriptor->GetKey(); |
| 7521 ASSERT(*key == descriptors->GetKey(insertion_index)); | 7521 DCHECK(*key == descriptors->GetKey(insertion_index)); |
| 7522 | 7522 |
| 7523 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( | 7523 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |
| 7524 descriptors, map->NumberOfOwnDescriptors()); | 7524 descriptors, map->NumberOfOwnDescriptors()); |
| 7525 | 7525 |
| 7526 new_descriptors->Replace(insertion_index, descriptor); | 7526 new_descriptors->Replace(insertion_index, descriptor); |
| 7527 | 7527 |
| 7528 SimpleTransitionFlag simple_flag = | 7528 SimpleTransitionFlag simple_flag = |
| 7529 (insertion_index == descriptors->number_of_descriptors() - 1) | 7529 (insertion_index == descriptors->number_of_descriptors() - 1) |
| 7530 ? SIMPLE_TRANSITION | 7530 ? SIMPLE_TRANSITION |
| 7531 : FULL_TRANSITION; | 7531 : FULL_TRANSITION; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7565 if (!code_cache()->IsFixedArray()) { | 7565 if (!code_cache()->IsFixedArray()) { |
| 7566 return CodeCache::cast(code_cache())->GetIndex(name, code); | 7566 return CodeCache::cast(code_cache())->GetIndex(name, code); |
| 7567 } | 7567 } |
| 7568 return -1; | 7568 return -1; |
| 7569 } | 7569 } |
| 7570 | 7570 |
| 7571 | 7571 |
| 7572 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) { | 7572 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) { |
| 7573 // No GC is supposed to happen between a call to IndexInCodeCache and | 7573 // No GC is supposed to happen between a call to IndexInCodeCache and |
| 7574 // RemoveFromCodeCache so the code cache must be there. | 7574 // RemoveFromCodeCache so the code cache must be there. |
| 7575 ASSERT(!code_cache()->IsFixedArray()); | 7575 DCHECK(!code_cache()->IsFixedArray()); |
| 7576 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); | 7576 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); |
| 7577 } | 7577 } |
| 7578 | 7578 |
| 7579 | 7579 |
| 7580 // An iterator over all map transitions in an descriptor array, reusing the | 7580 // An iterator over all map transitions in an descriptor array, reusing the |
| 7581 // constructor field of the map while it is running. Negative values in | 7581 // constructor field of the map while it is running. Negative values in |
| 7582 // the constructor field indicate an active map transition iteration. The | 7582 // the constructor field indicate an active map transition iteration. The |
| 7583 // original constructor is restored after iterating over all entries. | 7583 // original constructor is restored after iterating over all entries. |
| 7584 class IntrusiveMapTransitionIterator { | 7584 class IntrusiveMapTransitionIterator { |
| 7585 public: | 7585 public: |
| 7586 IntrusiveMapTransitionIterator( | 7586 IntrusiveMapTransitionIterator( |
| 7587 Map* map, TransitionArray* transition_array, Object* constructor) | 7587 Map* map, TransitionArray* transition_array, Object* constructor) |
| 7588 : map_(map), | 7588 : map_(map), |
| 7589 transition_array_(transition_array), | 7589 transition_array_(transition_array), |
| 7590 constructor_(constructor) { } | 7590 constructor_(constructor) { } |
| 7591 | 7591 |
| 7592 void StartIfNotStarted() { | 7592 void StartIfNotStarted() { |
| 7593 ASSERT(!(*IteratorField())->IsSmi() || IsIterating()); | 7593 DCHECK(!(*IteratorField())->IsSmi() || IsIterating()); |
| 7594 if (!(*IteratorField())->IsSmi()) { | 7594 if (!(*IteratorField())->IsSmi()) { |
| 7595 ASSERT(*IteratorField() == constructor_); | 7595 DCHECK(*IteratorField() == constructor_); |
| 7596 *IteratorField() = Smi::FromInt(-1); | 7596 *IteratorField() = Smi::FromInt(-1); |
| 7597 } | 7597 } |
| 7598 } | 7598 } |
| 7599 | 7599 |
| 7600 bool IsIterating() { | 7600 bool IsIterating() { |
| 7601 return (*IteratorField())->IsSmi() && | 7601 return (*IteratorField())->IsSmi() && |
| 7602 Smi::cast(*IteratorField())->value() < 0; | 7602 Smi::cast(*IteratorField())->value() < 0; |
| 7603 } | 7603 } |
| 7604 | 7604 |
| 7605 Map* Next() { | 7605 Map* Next() { |
| 7606 ASSERT(IsIterating()); | 7606 DCHECK(IsIterating()); |
| 7607 int value = Smi::cast(*IteratorField())->value(); | 7607 int value = Smi::cast(*IteratorField())->value(); |
| 7608 int index = -value - 1; | 7608 int index = -value - 1; |
| 7609 int number_of_transitions = transition_array_->number_of_transitions(); | 7609 int number_of_transitions = transition_array_->number_of_transitions(); |
| 7610 while (index < number_of_transitions) { | 7610 while (index < number_of_transitions) { |
| 7611 *IteratorField() = Smi::FromInt(value - 1); | 7611 *IteratorField() = Smi::FromInt(value - 1); |
| 7612 return transition_array_->GetTarget(index); | 7612 return transition_array_->GetTarget(index); |
| 7613 } | 7613 } |
| 7614 | 7614 |
| 7615 *IteratorField() = constructor_; | 7615 *IteratorField() = constructor_; |
| 7616 return NULL; | 7616 return NULL; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7632 // indicate an active prototype transition iteration. The original constructor | 7632 // indicate an active prototype transition iteration. The original constructor |
| 7633 // is restored after iterating over all entries. | 7633 // is restored after iterating over all entries. |
| 7634 class IntrusivePrototypeTransitionIterator { | 7634 class IntrusivePrototypeTransitionIterator { |
| 7635 public: | 7635 public: |
| 7636 IntrusivePrototypeTransitionIterator( | 7636 IntrusivePrototypeTransitionIterator( |
| 7637 Map* map, HeapObject* proto_trans, Object* constructor) | 7637 Map* map, HeapObject* proto_trans, Object* constructor) |
| 7638 : map_(map), proto_trans_(proto_trans), constructor_(constructor) { } | 7638 : map_(map), proto_trans_(proto_trans), constructor_(constructor) { } |
| 7639 | 7639 |
| 7640 void StartIfNotStarted() { | 7640 void StartIfNotStarted() { |
| 7641 if (!(*IteratorField())->IsSmi()) { | 7641 if (!(*IteratorField())->IsSmi()) { |
| 7642 ASSERT(*IteratorField() == constructor_); | 7642 DCHECK(*IteratorField() == constructor_); |
| 7643 *IteratorField() = Smi::FromInt(0); | 7643 *IteratorField() = Smi::FromInt(0); |
| 7644 } | 7644 } |
| 7645 } | 7645 } |
| 7646 | 7646 |
| 7647 bool IsIterating() { | 7647 bool IsIterating() { |
| 7648 return (*IteratorField())->IsSmi() && | 7648 return (*IteratorField())->IsSmi() && |
| 7649 Smi::cast(*IteratorField())->value() >= 0; | 7649 Smi::cast(*IteratorField())->value() >= 0; |
| 7650 } | 7650 } |
| 7651 | 7651 |
| 7652 Map* Next() { | 7652 Map* Next() { |
| 7653 ASSERT(IsIterating()); | 7653 DCHECK(IsIterating()); |
| 7654 int transitionNumber = Smi::cast(*IteratorField())->value(); | 7654 int transitionNumber = Smi::cast(*IteratorField())->value(); |
| 7655 if (transitionNumber < NumberOfTransitions()) { | 7655 if (transitionNumber < NumberOfTransitions()) { |
| 7656 *IteratorField() = Smi::FromInt(transitionNumber + 1); | 7656 *IteratorField() = Smi::FromInt(transitionNumber + 1); |
| 7657 return GetTransition(transitionNumber); | 7657 return GetTransition(transitionNumber); |
| 7658 } | 7658 } |
| 7659 *IteratorField() = constructor_; | 7659 *IteratorField() = constructor_; |
| 7660 return NULL; | 7660 return NULL; |
| 7661 } | 7661 } |
| 7662 | 7662 |
| 7663 private: | 7663 private: |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7791 if (code->type() == Code::NORMAL) { | 7791 if (code->type() == Code::NORMAL) { |
| 7792 // Make sure that a hash table is allocated for the normal load code cache. | 7792 // Make sure that a hash table is allocated for the normal load code cache. |
| 7793 if (code_cache->normal_type_cache()->IsUndefined()) { | 7793 if (code_cache->normal_type_cache()->IsUndefined()) { |
| 7794 Handle<Object> result = | 7794 Handle<Object> result = |
| 7795 CodeCacheHashTable::New(code_cache->GetIsolate(), | 7795 CodeCacheHashTable::New(code_cache->GetIsolate(), |
| 7796 CodeCacheHashTable::kInitialSize); | 7796 CodeCacheHashTable::kInitialSize); |
| 7797 code_cache->set_normal_type_cache(*result); | 7797 code_cache->set_normal_type_cache(*result); |
| 7798 } | 7798 } |
| 7799 UpdateNormalTypeCache(code_cache, name, code); | 7799 UpdateNormalTypeCache(code_cache, name, code); |
| 7800 } else { | 7800 } else { |
| 7801 ASSERT(code_cache->default_cache()->IsFixedArray()); | 7801 DCHECK(code_cache->default_cache()->IsFixedArray()); |
| 7802 UpdateDefaultCache(code_cache, name, code); | 7802 UpdateDefaultCache(code_cache, name, code); |
| 7803 } | 7803 } |
| 7804 } | 7804 } |
| 7805 | 7805 |
| 7806 | 7806 |
| 7807 void CodeCache::UpdateDefaultCache( | 7807 void CodeCache::UpdateDefaultCache( |
| 7808 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { | 7808 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { |
| 7809 // When updating the default code cache we disregard the type encoded in the | 7809 // When updating the default code cache we disregard the type encoded in the |
| 7810 // flags. This allows call constant stubs to overwrite call field | 7810 // flags. This allows call constant stubs to overwrite call field |
| 7811 // stubs, etc. | 7811 // stubs, etc. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7846 cache->set(deleted_index + kCodeCacheEntryNameOffset, *name); | 7846 cache->set(deleted_index + kCodeCacheEntryNameOffset, *name); |
| 7847 cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code); | 7847 cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code); |
| 7848 return; | 7848 return; |
| 7849 } | 7849 } |
| 7850 } | 7850 } |
| 7851 | 7851 |
| 7852 // Extend the code cache with some new entries (at least one). Must be a | 7852 // Extend the code cache with some new entries (at least one). Must be a |
| 7853 // multiple of the entry size. | 7853 // multiple of the entry size. |
| 7854 int new_length = length + ((length >> 1)) + kCodeCacheEntrySize; | 7854 int new_length = length + ((length >> 1)) + kCodeCacheEntrySize; |
| 7855 new_length = new_length - new_length % kCodeCacheEntrySize; | 7855 new_length = new_length - new_length % kCodeCacheEntrySize; |
| 7856 ASSERT((new_length % kCodeCacheEntrySize) == 0); | 7856 DCHECK((new_length % kCodeCacheEntrySize) == 0); |
| 7857 cache = FixedArray::CopySize(cache, new_length); | 7857 cache = FixedArray::CopySize(cache, new_length); |
| 7858 | 7858 |
| 7859 // Add the (name, code) pair to the new cache. | 7859 // Add the (name, code) pair to the new cache. |
| 7860 cache->set(length + kCodeCacheEntryNameOffset, *name); | 7860 cache->set(length + kCodeCacheEntryNameOffset, *name); |
| 7861 cache->set(length + kCodeCacheEntryCodeOffset, *code); | 7861 cache->set(length + kCodeCacheEntryCodeOffset, *code); |
| 7862 code_cache->set_default_cache(*cache); | 7862 code_cache->set_default_cache(*cache); |
| 7863 } | 7863 } |
| 7864 | 7864 |
| 7865 | 7865 |
| 7866 void CodeCache::UpdateNormalTypeCache( | 7866 void CodeCache::UpdateNormalTypeCache( |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7923 int len = array->length(); | 7923 int len = array->length(); |
| 7924 for (int i = 0; i < len; i += kCodeCacheEntrySize) { | 7924 for (int i = 0; i < len; i += kCodeCacheEntrySize) { |
| 7925 if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1; | 7925 if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1; |
| 7926 } | 7926 } |
| 7927 return -1; | 7927 return -1; |
| 7928 } | 7928 } |
| 7929 | 7929 |
| 7930 | 7930 |
| 7931 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) { | 7931 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) { |
| 7932 if (code->type() == Code::NORMAL) { | 7932 if (code->type() == Code::NORMAL) { |
| 7933 ASSERT(!normal_type_cache()->IsUndefined()); | 7933 DCHECK(!normal_type_cache()->IsUndefined()); |
| 7934 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); | 7934 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); |
| 7935 ASSERT(cache->GetIndex(Name::cast(name), code->flags()) == index); | 7935 DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index); |
| 7936 cache->RemoveByIndex(index); | 7936 cache->RemoveByIndex(index); |
| 7937 } else { | 7937 } else { |
| 7938 FixedArray* array = default_cache(); | 7938 FixedArray* array = default_cache(); |
| 7939 ASSERT(array->length() >= index && array->get(index)->IsCode()); | 7939 DCHECK(array->length() >= index && array->get(index)->IsCode()); |
| 7940 // Use null instead of undefined for deleted elements to distinguish | 7940 // Use null instead of undefined for deleted elements to distinguish |
| 7941 // deleted elements from unused elements. This distinction is used | 7941 // deleted elements from unused elements. This distinction is used |
| 7942 // when looking up in the cache and when updating the cache. | 7942 // when looking up in the cache and when updating the cache. |
| 7943 ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset); | 7943 DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset); |
| 7944 array->set_null(index - 1); // Name. | 7944 array->set_null(index - 1); // Name. |
| 7945 array->set_null(index); // Code. | 7945 array->set_null(index); // Code. |
| 7946 } | 7946 } |
| 7947 } | 7947 } |
| 7948 | 7948 |
| 7949 | 7949 |
| 7950 // The key in the code cache hash table consists of the property name and the | 7950 // The key in the code cache hash table consists of the property name and the |
| 7951 // code object. The actual match is on the name and the code flags. If a key | 7951 // code object. The actual match is on the name and the code flags. If a key |
| 7952 // is created using the flags and not a code object it can only be used for | 7952 // is created using the flags and not a code object it can only be used for |
| 7953 // lookup not to create a new entry. | 7953 // lookup not to create a new entry. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8026 | 8026 |
| 8027 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) { | 8027 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) { |
| 8028 DisallowHeapAllocation no_alloc; | 8028 DisallowHeapAllocation no_alloc; |
| 8029 CodeCacheHashTableKey key(handle(name), flags); | 8029 CodeCacheHashTableKey key(handle(name), flags); |
| 8030 int entry = FindEntry(&key); | 8030 int entry = FindEntry(&key); |
| 8031 return (entry == kNotFound) ? -1 : entry; | 8031 return (entry == kNotFound) ? -1 : entry; |
| 8032 } | 8032 } |
| 8033 | 8033 |
| 8034 | 8034 |
| 8035 void CodeCacheHashTable::RemoveByIndex(int index) { | 8035 void CodeCacheHashTable::RemoveByIndex(int index) { |
| 8036 ASSERT(index >= 0); | 8036 DCHECK(index >= 0); |
| 8037 Heap* heap = GetHeap(); | 8037 Heap* heap = GetHeap(); |
| 8038 set(EntryToIndex(index), heap->the_hole_value()); | 8038 set(EntryToIndex(index), heap->the_hole_value()); |
| 8039 set(EntryToIndex(index) + 1, heap->the_hole_value()); | 8039 set(EntryToIndex(index) + 1, heap->the_hole_value()); |
| 8040 ElementRemoved(); | 8040 ElementRemoved(); |
| 8041 } | 8041 } |
| 8042 | 8042 |
| 8043 | 8043 |
| 8044 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache, | 8044 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache, |
| 8045 MapHandleList* maps, | 8045 MapHandleList* maps, |
| 8046 Code::Flags flags, | 8046 Code::Flags flags, |
| 8047 Handle<Code> code) { | 8047 Handle<Code> code) { |
| 8048 Isolate* isolate = code_cache->GetIsolate(); | 8048 Isolate* isolate = code_cache->GetIsolate(); |
| 8049 if (code_cache->cache()->IsUndefined()) { | 8049 if (code_cache->cache()->IsUndefined()) { |
| 8050 Handle<PolymorphicCodeCacheHashTable> result = | 8050 Handle<PolymorphicCodeCacheHashTable> result = |
| 8051 PolymorphicCodeCacheHashTable::New( | 8051 PolymorphicCodeCacheHashTable::New( |
| 8052 isolate, | 8052 isolate, |
| 8053 PolymorphicCodeCacheHashTable::kInitialSize); | 8053 PolymorphicCodeCacheHashTable::kInitialSize); |
| 8054 code_cache->set_cache(*result); | 8054 code_cache->set_cache(*result); |
| 8055 } else { | 8055 } else { |
| 8056 // This entry shouldn't be contained in the cache yet. | 8056 // This entry shouldn't be contained in the cache yet. |
| 8057 ASSERT(PolymorphicCodeCacheHashTable::cast(code_cache->cache()) | 8057 DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache()) |
| 8058 ->Lookup(maps, flags)->IsUndefined()); | 8058 ->Lookup(maps, flags)->IsUndefined()); |
| 8059 } | 8059 } |
| 8060 Handle<PolymorphicCodeCacheHashTable> hash_table = | 8060 Handle<PolymorphicCodeCacheHashTable> hash_table = |
| 8061 handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache())); | 8061 handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache())); |
| 8062 Handle<PolymorphicCodeCacheHashTable> new_cache = | 8062 Handle<PolymorphicCodeCacheHashTable> new_cache = |
| 8063 PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code); | 8063 PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code); |
| 8064 code_cache->set_cache(*new_cache); | 8064 code_cache->set_cache(*new_cache); |
| 8065 } | 8065 } |
| 8066 | 8066 |
| 8067 | 8067 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8187 | 8187 |
| 8188 Handle<Object> obj = key.AsHandle(hash_table->GetIsolate()); | 8188 Handle<Object> obj = key.AsHandle(hash_table->GetIsolate()); |
| 8189 cache->set(EntryToIndex(entry), *obj); | 8189 cache->set(EntryToIndex(entry), *obj); |
| 8190 cache->set(EntryToIndex(entry) + 1, *code); | 8190 cache->set(EntryToIndex(entry) + 1, *code); |
| 8191 cache->ElementAdded(); | 8191 cache->ElementAdded(); |
| 8192 return cache; | 8192 return cache; |
| 8193 } | 8193 } |
| 8194 | 8194 |
| 8195 | 8195 |
| 8196 void FixedArray::Shrink(int new_length) { | 8196 void FixedArray::Shrink(int new_length) { |
| 8197 ASSERT(0 <= new_length && new_length <= length()); | 8197 DCHECK(0 <= new_length && new_length <= length()); |
| 8198 if (new_length < length()) { | 8198 if (new_length < length()) { |
| 8199 RightTrimFixedArray<Heap::FROM_MUTATOR>( | 8199 RightTrimFixedArray<Heap::FROM_MUTATOR>( |
| 8200 GetHeap(), this, length() - new_length); | 8200 GetHeap(), this, length() - new_length); |
| 8201 } | 8201 } |
| 8202 } | 8202 } |
| 8203 | 8203 |
| 8204 | 8204 |
| 8205 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( | 8205 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( |
| 8206 Handle<FixedArray> content, | 8206 Handle<FixedArray> content, |
| 8207 Handle<JSObject> array) { | 8207 Handle<JSObject> array) { |
| 8208 ASSERT(array->IsJSArray() || array->HasSloppyArgumentsElements()); | 8208 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements()); |
| 8209 ElementsAccessor* accessor = array->GetElementsAccessor(); | 8209 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 8210 Handle<FixedArray> result; | 8210 Handle<FixedArray> result; |
| 8211 ASSIGN_RETURN_ON_EXCEPTION( | 8211 ASSIGN_RETURN_ON_EXCEPTION( |
| 8212 array->GetIsolate(), result, | 8212 array->GetIsolate(), result, |
| 8213 accessor->AddElementsToFixedArray(array, array, content), | 8213 accessor->AddElementsToFixedArray(array, array, content), |
| 8214 FixedArray); | 8214 FixedArray); |
| 8215 | 8215 |
| 8216 #ifdef ENABLE_SLOW_ASSERTS | 8216 #ifdef ENABLE_SLOW_DCHECKS |
| 8217 if (FLAG_enable_slow_asserts) { | 8217 if (FLAG_enable_slow_asserts) { |
| 8218 DisallowHeapAllocation no_allocation; | 8218 DisallowHeapAllocation no_allocation; |
| 8219 for (int i = 0; i < result->length(); i++) { | 8219 for (int i = 0; i < result->length(); i++) { |
| 8220 Object* current = result->get(i); | 8220 Object* current = result->get(i); |
| 8221 ASSERT(current->IsNumber() || current->IsName()); | 8221 DCHECK(current->IsNumber() || current->IsName()); |
| 8222 } | 8222 } |
| 8223 } | 8223 } |
| 8224 #endif | 8224 #endif |
| 8225 return result; | 8225 return result; |
| 8226 } | 8226 } |
| 8227 | 8227 |
| 8228 | 8228 |
| 8229 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first, | 8229 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first, |
| 8230 Handle<FixedArray> second) { | 8230 Handle<FixedArray> second) { |
| 8231 ElementsAccessor* accessor = ElementsAccessor::ForArray(second); | 8231 ElementsAccessor* accessor = ElementsAccessor::ForArray(second); |
| 8232 Handle<FixedArray> result; | 8232 Handle<FixedArray> result; |
| 8233 ASSIGN_RETURN_ON_EXCEPTION( | 8233 ASSIGN_RETURN_ON_EXCEPTION( |
| 8234 first->GetIsolate(), result, | 8234 first->GetIsolate(), result, |
| 8235 accessor->AddElementsToFixedArray( | 8235 accessor->AddElementsToFixedArray( |
| 8236 Handle<Object>::null(), // receiver | 8236 Handle<Object>::null(), // receiver |
| 8237 Handle<JSObject>::null(), // holder | 8237 Handle<JSObject>::null(), // holder |
| 8238 first, | 8238 first, |
| 8239 Handle<FixedArrayBase>::cast(second)), | 8239 Handle<FixedArrayBase>::cast(second)), |
| 8240 FixedArray); | 8240 FixedArray); |
| 8241 | 8241 |
| 8242 #ifdef ENABLE_SLOW_ASSERTS | 8242 #ifdef ENABLE_SLOW_DCHECKS |
| 8243 if (FLAG_enable_slow_asserts) { | 8243 if (FLAG_enable_slow_asserts) { |
| 8244 DisallowHeapAllocation no_allocation; | 8244 DisallowHeapAllocation no_allocation; |
| 8245 for (int i = 0; i < result->length(); i++) { | 8245 for (int i = 0; i < result->length(); i++) { |
| 8246 Object* current = result->get(i); | 8246 Object* current = result->get(i); |
| 8247 ASSERT(current->IsNumber() || current->IsName()); | 8247 DCHECK(current->IsNumber() || current->IsName()); |
| 8248 } | 8248 } |
| 8249 } | 8249 } |
| 8250 #endif | 8250 #endif |
| 8251 return result; | 8251 return result; |
| 8252 } | 8252 } |
| 8253 | 8253 |
| 8254 | 8254 |
| 8255 Handle<FixedArray> FixedArray::CopySize( | 8255 Handle<FixedArray> FixedArray::CopySize( |
| 8256 Handle<FixedArray> array, int new_length, PretenureFlag pretenure) { | 8256 Handle<FixedArray> array, int new_length, PretenureFlag pretenure) { |
| 8257 Isolate* isolate = array->GetIsolate(); | 8257 Isolate* isolate = array->GetIsolate(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8289 if (get(i) != other->get(i)) return false; | 8289 if (get(i) != other->get(i)) return false; |
| 8290 } | 8290 } |
| 8291 return true; | 8291 return true; |
| 8292 } | 8292 } |
| 8293 #endif | 8293 #endif |
| 8294 | 8294 |
| 8295 | 8295 |
| 8296 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate, | 8296 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate, |
| 8297 int number_of_descriptors, | 8297 int number_of_descriptors, |
| 8298 int slack) { | 8298 int slack) { |
| 8299 ASSERT(0 <= number_of_descriptors); | 8299 DCHECK(0 <= number_of_descriptors); |
| 8300 Factory* factory = isolate->factory(); | 8300 Factory* factory = isolate->factory(); |
| 8301 // Do not use DescriptorArray::cast on incomplete object. | 8301 // Do not use DescriptorArray::cast on incomplete object. |
| 8302 int size = number_of_descriptors + slack; | 8302 int size = number_of_descriptors + slack; |
| 8303 if (size == 0) return factory->empty_descriptor_array(); | 8303 if (size == 0) return factory->empty_descriptor_array(); |
| 8304 // Allocate the array of keys. | 8304 // Allocate the array of keys. |
| 8305 Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size)); | 8305 Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size)); |
| 8306 | 8306 |
| 8307 result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors)); | 8307 result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors)); |
| 8308 result->set(kEnumCacheIndex, Smi::FromInt(0)); | 8308 result->set(kEnumCacheIndex, Smi::FromInt(0)); |
| 8309 return Handle<DescriptorArray>::cast(result); | 8309 return Handle<DescriptorArray>::cast(result); |
| 8310 } | 8310 } |
| 8311 | 8311 |
| 8312 | 8312 |
| 8313 void DescriptorArray::ClearEnumCache() { | 8313 void DescriptorArray::ClearEnumCache() { |
| 8314 set(kEnumCacheIndex, Smi::FromInt(0)); | 8314 set(kEnumCacheIndex, Smi::FromInt(0)); |
| 8315 } | 8315 } |
| 8316 | 8316 |
| 8317 | 8317 |
| 8318 void DescriptorArray::Replace(int index, Descriptor* descriptor) { | 8318 void DescriptorArray::Replace(int index, Descriptor* descriptor) { |
| 8319 descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index)); | 8319 descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index)); |
| 8320 Set(index, descriptor); | 8320 Set(index, descriptor); |
| 8321 } | 8321 } |
| 8322 | 8322 |
| 8323 | 8323 |
| 8324 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 8324 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
| 8325 FixedArray* new_cache, | 8325 FixedArray* new_cache, |
| 8326 Object* new_index_cache) { | 8326 Object* new_index_cache) { |
| 8327 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); | 8327 DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength); |
| 8328 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); | 8328 DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); |
| 8329 ASSERT(!IsEmpty()); | 8329 DCHECK(!IsEmpty()); |
| 8330 ASSERT(!HasEnumCache() || new_cache->length() > GetEnumCache()->length()); | 8330 DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length()); |
| 8331 FixedArray::cast(bridge_storage)-> | 8331 FixedArray::cast(bridge_storage)-> |
| 8332 set(kEnumCacheBridgeCacheIndex, new_cache); | 8332 set(kEnumCacheBridgeCacheIndex, new_cache); |
| 8333 FixedArray::cast(bridge_storage)-> | 8333 FixedArray::cast(bridge_storage)-> |
| 8334 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); | 8334 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); |
| 8335 set(kEnumCacheIndex, bridge_storage); | 8335 set(kEnumCacheIndex, bridge_storage); |
| 8336 } | 8336 } |
| 8337 | 8337 |
| 8338 | 8338 |
| 8339 void DescriptorArray::CopyFrom(int index, | 8339 void DescriptorArray::CopyFrom(int index, |
| 8340 DescriptorArray* src, | 8340 DescriptorArray* src, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8396 if (right_child_hash > child_hash) { | 8396 if (right_child_hash > child_hash) { |
| 8397 child_index++; | 8397 child_index++; |
| 8398 child_hash = right_child_hash; | 8398 child_hash = right_child_hash; |
| 8399 } | 8399 } |
| 8400 } | 8400 } |
| 8401 if (child_hash <= parent_hash) break; | 8401 if (child_hash <= parent_hash) break; |
| 8402 SwapSortedKeys(parent_index, child_index); | 8402 SwapSortedKeys(parent_index, child_index); |
| 8403 parent_index = child_index; | 8403 parent_index = child_index; |
| 8404 } | 8404 } |
| 8405 } | 8405 } |
| 8406 ASSERT(IsSortedNoDuplicates()); | 8406 DCHECK(IsSortedNoDuplicates()); |
| 8407 } | 8407 } |
| 8408 | 8408 |
| 8409 | 8409 |
| 8410 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) { | 8410 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) { |
| 8411 Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair(); | 8411 Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair(); |
| 8412 copy->set_getter(pair->getter()); | 8412 copy->set_getter(pair->getter()); |
| 8413 copy->set_setter(pair->setter()); | 8413 copy->set_setter(pair->setter()); |
| 8414 return copy; | 8414 return copy; |
| 8415 } | 8415 } |
| 8416 | 8416 |
| 8417 | 8417 |
| 8418 Object* AccessorPair::GetComponent(AccessorComponent component) { | 8418 Object* AccessorPair::GetComponent(AccessorComponent component) { |
| 8419 Object* accessor = get(component); | 8419 Object* accessor = get(component); |
| 8420 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; | 8420 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; |
| 8421 } | 8421 } |
| 8422 | 8422 |
| 8423 | 8423 |
| 8424 Handle<DeoptimizationInputData> DeoptimizationInputData::New( | 8424 Handle<DeoptimizationInputData> DeoptimizationInputData::New( |
| 8425 Isolate* isolate, int deopt_entry_count, int return_patch_address_count, | 8425 Isolate* isolate, int deopt_entry_count, int return_patch_address_count, |
| 8426 PretenureFlag pretenure) { | 8426 PretenureFlag pretenure) { |
| 8427 ASSERT(deopt_entry_count + return_patch_address_count > 0); | 8427 DCHECK(deopt_entry_count + return_patch_address_count > 0); |
| 8428 Handle<FixedArray> deoptimization_data = | 8428 Handle<FixedArray> deoptimization_data = |
| 8429 Handle<FixedArray>::cast(isolate->factory()->NewFixedArray( | 8429 Handle<FixedArray>::cast(isolate->factory()->NewFixedArray( |
| 8430 LengthFor(deopt_entry_count, return_patch_address_count), pretenure)); | 8430 LengthFor(deopt_entry_count, return_patch_address_count), pretenure)); |
| 8431 deoptimization_data->set(kDeoptEntryCountIndex, | 8431 deoptimization_data->set(kDeoptEntryCountIndex, |
| 8432 Smi::FromInt(deopt_entry_count)); | 8432 Smi::FromInt(deopt_entry_count)); |
| 8433 deoptimization_data->set(kReturnAddressPatchEntryCountIndex, | 8433 deoptimization_data->set(kReturnAddressPatchEntryCountIndex, |
| 8434 Smi::FromInt(return_patch_address_count)); | 8434 Smi::FromInt(return_patch_address_count)); |
| 8435 return Handle<DeoptimizationInputData>::cast(deoptimization_data); | 8435 return Handle<DeoptimizationInputData>::cast(deoptimization_data); |
| 8436 } | 8436 } |
| 8437 | 8437 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 8464 #endif | 8464 #endif |
| 8465 | 8465 |
| 8466 | 8466 |
| 8467 bool String::LooksValid() { | 8467 bool String::LooksValid() { |
| 8468 if (!GetIsolate()->heap()->Contains(this)) return false; | 8468 if (!GetIsolate()->heap()->Contains(this)) return false; |
| 8469 return true; | 8469 return true; |
| 8470 } | 8470 } |
| 8471 | 8471 |
| 8472 | 8472 |
| 8473 String::FlatContent String::GetFlatContent() { | 8473 String::FlatContent String::GetFlatContent() { |
| 8474 ASSERT(!AllowHeapAllocation::IsAllowed()); | 8474 DCHECK(!AllowHeapAllocation::IsAllowed()); |
| 8475 int length = this->length(); | 8475 int length = this->length(); |
| 8476 StringShape shape(this); | 8476 StringShape shape(this); |
| 8477 String* string = this; | 8477 String* string = this; |
| 8478 int offset = 0; | 8478 int offset = 0; |
| 8479 if (shape.representation_tag() == kConsStringTag) { | 8479 if (shape.representation_tag() == kConsStringTag) { |
| 8480 ConsString* cons = ConsString::cast(string); | 8480 ConsString* cons = ConsString::cast(string); |
| 8481 if (cons->second()->length() != 0) { | 8481 if (cons->second()->length() != 0) { |
| 8482 return FlatContent(); | 8482 return FlatContent(); |
| 8483 } | 8483 } |
| 8484 string = cons->first(); | 8484 string = cons->first(); |
| 8485 shape = StringShape(string); | 8485 shape = StringShape(string); |
| 8486 } | 8486 } |
| 8487 if (shape.representation_tag() == kSlicedStringTag) { | 8487 if (shape.representation_tag() == kSlicedStringTag) { |
| 8488 SlicedString* slice = SlicedString::cast(string); | 8488 SlicedString* slice = SlicedString::cast(string); |
| 8489 offset = slice->offset(); | 8489 offset = slice->offset(); |
| 8490 string = slice->parent(); | 8490 string = slice->parent(); |
| 8491 shape = StringShape(string); | 8491 shape = StringShape(string); |
| 8492 ASSERT(shape.representation_tag() != kConsStringTag && | 8492 DCHECK(shape.representation_tag() != kConsStringTag && |
| 8493 shape.representation_tag() != kSlicedStringTag); | 8493 shape.representation_tag() != kSlicedStringTag); |
| 8494 } | 8494 } |
| 8495 if (shape.encoding_tag() == kOneByteStringTag) { | 8495 if (shape.encoding_tag() == kOneByteStringTag) { |
| 8496 const uint8_t* start; | 8496 const uint8_t* start; |
| 8497 if (shape.representation_tag() == kSeqStringTag) { | 8497 if (shape.representation_tag() == kSeqStringTag) { |
| 8498 start = SeqOneByteString::cast(string)->GetChars(); | 8498 start = SeqOneByteString::cast(string)->GetChars(); |
| 8499 } else { | 8499 } else { |
| 8500 start = ExternalAsciiString::cast(string)->GetChars(); | 8500 start = ExternalAsciiString::cast(string)->GetChars(); |
| 8501 } | 8501 } |
| 8502 return FlatContent(start + offset, length); | 8502 return FlatContent(start + offset, length); |
| 8503 } else { | 8503 } else { |
| 8504 ASSERT(shape.encoding_tag() == kTwoByteStringTag); | 8504 DCHECK(shape.encoding_tag() == kTwoByteStringTag); |
| 8505 const uc16* start; | 8505 const uc16* start; |
| 8506 if (shape.representation_tag() == kSeqStringTag) { | 8506 if (shape.representation_tag() == kSeqStringTag) { |
| 8507 start = SeqTwoByteString::cast(string)->GetChars(); | 8507 start = SeqTwoByteString::cast(string)->GetChars(); |
| 8508 } else { | 8508 } else { |
| 8509 start = ExternalTwoByteString::cast(string)->GetChars(); | 8509 start = ExternalTwoByteString::cast(string)->GetChars(); |
| 8510 } | 8510 } |
| 8511 return FlatContent(start + offset, length); | 8511 return FlatContent(start + offset, length); |
| 8512 } | 8512 } |
| 8513 } | 8513 } |
| 8514 | 8514 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8565 | 8565 |
| 8566 | 8566 |
| 8567 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls, | 8567 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls, |
| 8568 RobustnessFlag robust_flag, | 8568 RobustnessFlag robust_flag, |
| 8569 int* length_return) { | 8569 int* length_return) { |
| 8570 return ToCString(allow_nulls, robust_flag, 0, -1, length_return); | 8570 return ToCString(allow_nulls, robust_flag, 0, -1, length_return); |
| 8571 } | 8571 } |
| 8572 | 8572 |
| 8573 | 8573 |
| 8574 const uc16* String::GetTwoByteData(unsigned start) { | 8574 const uc16* String::GetTwoByteData(unsigned start) { |
| 8575 ASSERT(!IsOneByteRepresentationUnderneath()); | 8575 DCHECK(!IsOneByteRepresentationUnderneath()); |
| 8576 switch (StringShape(this).representation_tag()) { | 8576 switch (StringShape(this).representation_tag()) { |
| 8577 case kSeqStringTag: | 8577 case kSeqStringTag: |
| 8578 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); | 8578 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); |
| 8579 case kExternalStringTag: | 8579 case kExternalStringTag: |
| 8580 return ExternalTwoByteString::cast(this)-> | 8580 return ExternalTwoByteString::cast(this)-> |
| 8581 ExternalTwoByteStringGetData(start); | 8581 ExternalTwoByteStringGetData(start); |
| 8582 case kSlicedStringTag: { | 8582 case kSlicedStringTag: { |
| 8583 SlicedString* slice = SlicedString::cast(this); | 8583 SlicedString* slice = SlicedString::cast(this); |
| 8584 return slice->parent()->GetTwoByteData(start + slice->offset()); | 8584 return slice->parent()->GetTwoByteData(start + slice->offset()); |
| 8585 } | 8585 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8683 : Relocatable(isolate), | 8683 : Relocatable(isolate), |
| 8684 str_(0), | 8684 str_(0), |
| 8685 is_ascii_(true), | 8685 is_ascii_(true), |
| 8686 length_(input.length()), | 8686 length_(input.length()), |
| 8687 start_(input.start()) { } | 8687 start_(input.start()) { } |
| 8688 | 8688 |
| 8689 | 8689 |
| 8690 void FlatStringReader::PostGarbageCollection() { | 8690 void FlatStringReader::PostGarbageCollection() { |
| 8691 if (str_ == NULL) return; | 8691 if (str_ == NULL) return; |
| 8692 Handle<String> str(str_); | 8692 Handle<String> str(str_); |
| 8693 ASSERT(str->IsFlat()); | 8693 DCHECK(str->IsFlat()); |
| 8694 DisallowHeapAllocation no_gc; | 8694 DisallowHeapAllocation no_gc; |
| 8695 // This does not actually prevent the vector from being relocated later. | 8695 // This does not actually prevent the vector from being relocated later. |
| 8696 String::FlatContent content = str->GetFlatContent(); | 8696 String::FlatContent content = str->GetFlatContent(); |
| 8697 ASSERT(content.IsFlat()); | 8697 DCHECK(content.IsFlat()); |
| 8698 is_ascii_ = content.IsAscii(); | 8698 is_ascii_ = content.IsAscii(); |
| 8699 if (is_ascii_) { | 8699 if (is_ascii_) { |
| 8700 start_ = content.ToOneByteVector().start(); | 8700 start_ = content.ToOneByteVector().start(); |
| 8701 } else { | 8701 } else { |
| 8702 start_ = content.ToUC16Vector().start(); | 8702 start_ = content.ToUC16Vector().start(); |
| 8703 } | 8703 } |
| 8704 } | 8704 } |
| 8705 | 8705 |
| 8706 | 8706 |
| 8707 void ConsStringIteratorOp::Initialize(ConsString* cons_string, int offset) { | 8707 void ConsStringIteratorOp::Initialize(ConsString* cons_string, int offset) { |
| 8708 ASSERT(cons_string != NULL); | 8708 DCHECK(cons_string != NULL); |
| 8709 root_ = cons_string; | 8709 root_ = cons_string; |
| 8710 consumed_ = offset; | 8710 consumed_ = offset; |
| 8711 // Force stack blown condition to trigger restart. | 8711 // Force stack blown condition to trigger restart. |
| 8712 depth_ = 1; | 8712 depth_ = 1; |
| 8713 maximum_depth_ = kStackSize + depth_; | 8713 maximum_depth_ = kStackSize + depth_; |
| 8714 ASSERT(StackBlown()); | 8714 DCHECK(StackBlown()); |
| 8715 } | 8715 } |
| 8716 | 8716 |
| 8717 | 8717 |
| 8718 String* ConsStringIteratorOp::Continue(int* offset_out) { | 8718 String* ConsStringIteratorOp::Continue(int* offset_out) { |
| 8719 ASSERT(depth_ != 0); | 8719 DCHECK(depth_ != 0); |
| 8720 ASSERT_EQ(0, *offset_out); | 8720 DCHECK_EQ(0, *offset_out); |
| 8721 bool blew_stack = StackBlown(); | 8721 bool blew_stack = StackBlown(); |
| 8722 String* string = NULL; | 8722 String* string = NULL; |
| 8723 // Get the next leaf if there is one. | 8723 // Get the next leaf if there is one. |
| 8724 if (!blew_stack) string = NextLeaf(&blew_stack); | 8724 if (!blew_stack) string = NextLeaf(&blew_stack); |
| 8725 // Restart search from root. | 8725 // Restart search from root. |
| 8726 if (blew_stack) { | 8726 if (blew_stack) { |
| 8727 ASSERT(string == NULL); | 8727 DCHECK(string == NULL); |
| 8728 string = Search(offset_out); | 8728 string = Search(offset_out); |
| 8729 } | 8729 } |
| 8730 // Ensure future calls return null immediately. | 8730 // Ensure future calls return null immediately. |
| 8731 if (string == NULL) Reset(NULL); | 8731 if (string == NULL) Reset(NULL); |
| 8732 return string; | 8732 return string; |
| 8733 } | 8733 } |
| 8734 | 8734 |
| 8735 | 8735 |
| 8736 String* ConsStringIteratorOp::Search(int* offset_out) { | 8736 String* ConsStringIteratorOp::Search(int* offset_out) { |
| 8737 ConsString* cons_string = root_; | 8737 ConsString* cons_string = root_; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8776 if (length == 0) { | 8776 if (length == 0) { |
| 8777 // Reset so future operations will return null immediately. | 8777 // Reset so future operations will return null immediately. |
| 8778 Reset(NULL); | 8778 Reset(NULL); |
| 8779 return NULL; | 8779 return NULL; |
| 8780 } | 8780 } |
| 8781 // Tell the stack we're done descending. | 8781 // Tell the stack we're done descending. |
| 8782 AdjustMaximumDepth(); | 8782 AdjustMaximumDepth(); |
| 8783 // Pop stack so next iteration is in correct place. | 8783 // Pop stack so next iteration is in correct place. |
| 8784 Pop(); | 8784 Pop(); |
| 8785 } | 8785 } |
| 8786 ASSERT(length != 0); | 8786 DCHECK(length != 0); |
| 8787 // Adjust return values and exit. | 8787 // Adjust return values and exit. |
| 8788 consumed_ = offset + length; | 8788 consumed_ = offset + length; |
| 8789 *offset_out = consumed - offset; | 8789 *offset_out = consumed - offset; |
| 8790 return string; | 8790 return string; |
| 8791 } | 8791 } |
| 8792 UNREACHABLE(); | 8792 UNREACHABLE(); |
| 8793 return NULL; | 8793 return NULL; |
| 8794 } | 8794 } |
| 8795 | 8795 |
| 8796 | 8796 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 8822 cons_string = ConsString::cast(string); | 8822 cons_string = ConsString::cast(string); |
| 8823 PushRight(cons_string); | 8823 PushRight(cons_string); |
| 8824 // Need to traverse all the way left. | 8824 // Need to traverse all the way left. |
| 8825 while (true) { | 8825 while (true) { |
| 8826 // Continue left. | 8826 // Continue left. |
| 8827 string = cons_string->first(); | 8827 string = cons_string->first(); |
| 8828 type = string->map()->instance_type(); | 8828 type = string->map()->instance_type(); |
| 8829 if ((type & kStringRepresentationMask) != kConsStringTag) { | 8829 if ((type & kStringRepresentationMask) != kConsStringTag) { |
| 8830 AdjustMaximumDepth(); | 8830 AdjustMaximumDepth(); |
| 8831 int length = string->length(); | 8831 int length = string->length(); |
| 8832 ASSERT(length != 0); | 8832 DCHECK(length != 0); |
| 8833 consumed_ += length; | 8833 consumed_ += length; |
| 8834 return string; | 8834 return string; |
| 8835 } | 8835 } |
| 8836 cons_string = ConsString::cast(string); | 8836 cons_string = ConsString::cast(string); |
| 8837 PushLeft(cons_string); | 8837 PushLeft(cons_string); |
| 8838 } | 8838 } |
| 8839 } | 8839 } |
| 8840 UNREACHABLE(); | 8840 UNREACHABLE(); |
| 8841 return NULL; | 8841 return NULL; |
| 8842 } | 8842 } |
| 8843 | 8843 |
| 8844 | 8844 |
| 8845 uint16_t ConsString::ConsStringGet(int index) { | 8845 uint16_t ConsString::ConsStringGet(int index) { |
| 8846 ASSERT(index >= 0 && index < this->length()); | 8846 DCHECK(index >= 0 && index < this->length()); |
| 8847 | 8847 |
| 8848 // Check for a flattened cons string | 8848 // Check for a flattened cons string |
| 8849 if (second()->length() == 0) { | 8849 if (second()->length() == 0) { |
| 8850 String* left = first(); | 8850 String* left = first(); |
| 8851 return left->Get(index); | 8851 return left->Get(index); |
| 8852 } | 8852 } |
| 8853 | 8853 |
| 8854 String* string = String::cast(this); | 8854 String* string = String::cast(this); |
| 8855 | 8855 |
| 8856 while (true) { | 8856 while (true) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 8880 | 8880 |
| 8881 template <typename sinkchar> | 8881 template <typename sinkchar> |
| 8882 void String::WriteToFlat(String* src, | 8882 void String::WriteToFlat(String* src, |
| 8883 sinkchar* sink, | 8883 sinkchar* sink, |
| 8884 int f, | 8884 int f, |
| 8885 int t) { | 8885 int t) { |
| 8886 String* source = src; | 8886 String* source = src; |
| 8887 int from = f; | 8887 int from = f; |
| 8888 int to = t; | 8888 int to = t; |
| 8889 while (true) { | 8889 while (true) { |
| 8890 ASSERT(0 <= from && from <= to && to <= source->length()); | 8890 DCHECK(0 <= from && from <= to && to <= source->length()); |
| 8891 switch (StringShape(source).full_representation_tag()) { | 8891 switch (StringShape(source).full_representation_tag()) { |
| 8892 case kOneByteStringTag | kExternalStringTag: { | 8892 case kOneByteStringTag | kExternalStringTag: { |
| 8893 CopyChars(sink, | 8893 CopyChars(sink, |
| 8894 ExternalAsciiString::cast(source)->GetChars() + from, | 8894 ExternalAsciiString::cast(source)->GetChars() + from, |
| 8895 to - from); | 8895 to - from); |
| 8896 return; | 8896 return; |
| 8897 } | 8897 } |
| 8898 case kTwoByteStringTag | kExternalStringTag: { | 8898 case kTwoByteStringTag | kExternalStringTag: { |
| 8899 const uc16* data = | 8899 const uc16* data = |
| 8900 ExternalTwoByteString::cast(source)->GetChars(); | 8900 ExternalTwoByteString::cast(source)->GetChars(); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8997 bool include_ending_line) { | 8997 bool include_ending_line) { |
| 8998 src = Flatten(src); | 8998 src = Flatten(src); |
| 8999 // Rough estimate of line count based on a roughly estimated average | 8999 // Rough estimate of line count based on a roughly estimated average |
| 9000 // length of (unpacked) code. | 9000 // length of (unpacked) code. |
| 9001 int line_count_estimate = src->length() >> 4; | 9001 int line_count_estimate = src->length() >> 4; |
| 9002 List<int> line_ends(line_count_estimate); | 9002 List<int> line_ends(line_count_estimate); |
| 9003 Isolate* isolate = src->GetIsolate(); | 9003 Isolate* isolate = src->GetIsolate(); |
| 9004 { DisallowHeapAllocation no_allocation; // ensure vectors stay valid. | 9004 { DisallowHeapAllocation no_allocation; // ensure vectors stay valid. |
| 9005 // Dispatch on type of strings. | 9005 // Dispatch on type of strings. |
| 9006 String::FlatContent content = src->GetFlatContent(); | 9006 String::FlatContent content = src->GetFlatContent(); |
| 9007 ASSERT(content.IsFlat()); | 9007 DCHECK(content.IsFlat()); |
| 9008 if (content.IsAscii()) { | 9008 if (content.IsAscii()) { |
| 9009 CalculateLineEndsImpl(isolate, | 9009 CalculateLineEndsImpl(isolate, |
| 9010 &line_ends, | 9010 &line_ends, |
| 9011 content.ToOneByteVector(), | 9011 content.ToOneByteVector(), |
| 9012 include_ending_line); | 9012 include_ending_line); |
| 9013 } else { | 9013 } else { |
| 9014 CalculateLineEndsImpl(isolate, | 9014 CalculateLineEndsImpl(isolate, |
| 9015 &line_ends, | 9015 &line_ends, |
| 9016 content.ToUC16Vector(), | 9016 content.ToUC16Vector(), |
| 9017 include_ending_line); | 9017 include_ending_line); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9062 } | 9062 } |
| 9063 } | 9063 } |
| 9064 return true; | 9064 return true; |
| 9065 } | 9065 } |
| 9066 | 9066 |
| 9067 | 9067 |
| 9068 template<typename Chars1, typename Chars2> | 9068 template<typename Chars1, typename Chars2> |
| 9069 class RawStringComparator : public AllStatic { | 9069 class RawStringComparator : public AllStatic { |
| 9070 public: | 9070 public: |
| 9071 static inline bool compare(const Chars1* a, const Chars2* b, int len) { | 9071 static inline bool compare(const Chars1* a, const Chars2* b, int len) { |
| 9072 ASSERT(sizeof(Chars1) != sizeof(Chars2)); | 9072 DCHECK(sizeof(Chars1) != sizeof(Chars2)); |
| 9073 for (int i = 0; i < len; i++) { | 9073 for (int i = 0; i < len; i++) { |
| 9074 if (a[i] != b[i]) { | 9074 if (a[i] != b[i]) { |
| 9075 return false; | 9075 return false; |
| 9076 } | 9076 } |
| 9077 } | 9077 } |
| 9078 return true; | 9078 return true; |
| 9079 } | 9079 } |
| 9080 }; | 9080 }; |
| 9081 | 9081 |
| 9082 | 9082 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9120 length_ = length; | 9120 length_ = length; |
| 9121 } | 9121 } |
| 9122 | 9122 |
| 9123 inline void VisitTwoByteString(const uint16_t* chars, int length) { | 9123 inline void VisitTwoByteString(const uint16_t* chars, int length) { |
| 9124 is_one_byte_ = false; | 9124 is_one_byte_ = false; |
| 9125 buffer16_ = chars; | 9125 buffer16_ = chars; |
| 9126 length_ = length; | 9126 length_ = length; |
| 9127 } | 9127 } |
| 9128 | 9128 |
| 9129 void Advance(int consumed) { | 9129 void Advance(int consumed) { |
| 9130 ASSERT(consumed <= length_); | 9130 DCHECK(consumed <= length_); |
| 9131 // Still in buffer. | 9131 // Still in buffer. |
| 9132 if (length_ != consumed) { | 9132 if (length_ != consumed) { |
| 9133 if (is_one_byte_) { | 9133 if (is_one_byte_) { |
| 9134 buffer8_ += consumed; | 9134 buffer8_ += consumed; |
| 9135 } else { | 9135 } else { |
| 9136 buffer16_ += consumed; | 9136 buffer16_ += consumed; |
| 9137 } | 9137 } |
| 9138 length_ -= consumed; | 9138 length_ -= consumed; |
| 9139 return; | 9139 return; |
| 9140 } | 9140 } |
| 9141 // Advance state. | 9141 // Advance state. |
| 9142 int offset; | 9142 int offset; |
| 9143 String* next = op_->Next(&offset); | 9143 String* next = op_->Next(&offset); |
| 9144 ASSERT_EQ(0, offset); | 9144 DCHECK_EQ(0, offset); |
| 9145 ASSERT(next != NULL); | 9145 DCHECK(next != NULL); |
| 9146 String::VisitFlat(this, next); | 9146 String::VisitFlat(this, next); |
| 9147 } | 9147 } |
| 9148 | 9148 |
| 9149 ConsStringIteratorOp* const op_; | 9149 ConsStringIteratorOp* const op_; |
| 9150 bool is_one_byte_; | 9150 bool is_one_byte_; |
| 9151 int length_; | 9151 int length_; |
| 9152 union { | 9152 union { |
| 9153 const uint8_t* buffer8_; | 9153 const uint8_t* buffer8_; |
| 9154 const uint16_t* buffer16_; | 9154 const uint16_t* buffer16_; |
| 9155 }; | 9155 }; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 9171 const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_); | 9171 const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_); |
| 9172 return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check); | 9172 return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check); |
| 9173 } | 9173 } |
| 9174 | 9174 |
| 9175 bool Equals(String* string_1, String* string_2) { | 9175 bool Equals(String* string_1, String* string_2) { |
| 9176 int length = string_1->length(); | 9176 int length = string_1->length(); |
| 9177 state_1_.Init(string_1); | 9177 state_1_.Init(string_1); |
| 9178 state_2_.Init(string_2); | 9178 state_2_.Init(string_2); |
| 9179 while (true) { | 9179 while (true) { |
| 9180 int to_check = Min(state_1_.length_, state_2_.length_); | 9180 int to_check = Min(state_1_.length_, state_2_.length_); |
| 9181 ASSERT(to_check > 0 && to_check <= length); | 9181 DCHECK(to_check > 0 && to_check <= length); |
| 9182 bool is_equal; | 9182 bool is_equal; |
| 9183 if (state_1_.is_one_byte_) { | 9183 if (state_1_.is_one_byte_) { |
| 9184 if (state_2_.is_one_byte_) { | 9184 if (state_2_.is_one_byte_) { |
| 9185 is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check); | 9185 is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check); |
| 9186 } else { | 9186 } else { |
| 9187 is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check); | 9187 is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check); |
| 9188 } | 9188 } |
| 9189 } else { | 9189 } else { |
| 9190 if (state_2_.is_one_byte_) { | 9190 if (state_2_.is_one_byte_) { |
| 9191 is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check); | 9191 is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 9213 bool String::SlowEquals(String* other) { | 9213 bool String::SlowEquals(String* other) { |
| 9214 DisallowHeapAllocation no_gc; | 9214 DisallowHeapAllocation no_gc; |
| 9215 // Fast check: negative check with lengths. | 9215 // Fast check: negative check with lengths. |
| 9216 int len = length(); | 9216 int len = length(); |
| 9217 if (len != other->length()) return false; | 9217 if (len != other->length()) return false; |
| 9218 if (len == 0) return true; | 9218 if (len == 0) return true; |
| 9219 | 9219 |
| 9220 // Fast check: if hash code is computed for both strings | 9220 // Fast check: if hash code is computed for both strings |
| 9221 // a fast negative check can be performed. | 9221 // a fast negative check can be performed. |
| 9222 if (HasHashCode() && other->HasHashCode()) { | 9222 if (HasHashCode() && other->HasHashCode()) { |
| 9223 #ifdef ENABLE_SLOW_ASSERTS | 9223 #ifdef ENABLE_SLOW_DCHECKS |
| 9224 if (FLAG_enable_slow_asserts) { | 9224 if (FLAG_enable_slow_asserts) { |
| 9225 if (Hash() != other->Hash()) { | 9225 if (Hash() != other->Hash()) { |
| 9226 bool found_difference = false; | 9226 bool found_difference = false; |
| 9227 for (int i = 0; i < len; i++) { | 9227 for (int i = 0; i < len; i++) { |
| 9228 if (Get(i) != other->Get(i)) { | 9228 if (Get(i) != other->Get(i)) { |
| 9229 found_difference = true; | 9229 found_difference = true; |
| 9230 break; | 9230 break; |
| 9231 } | 9231 } |
| 9232 } | 9232 } |
| 9233 ASSERT(found_difference); | 9233 DCHECK(found_difference); |
| 9234 } | 9234 } |
| 9235 } | 9235 } |
| 9236 #endif | 9236 #endif |
| 9237 if (Hash() != other->Hash()) return false; | 9237 if (Hash() != other->Hash()) return false; |
| 9238 } | 9238 } |
| 9239 | 9239 |
| 9240 // We know the strings are both non-empty. Compare the first chars | 9240 // We know the strings are both non-empty. Compare the first chars |
| 9241 // before we try to flatten the strings. | 9241 // before we try to flatten the strings. |
| 9242 if (this->Get(0) != other->Get(0)) return false; | 9242 if (this->Get(0) != other->Get(0)) return false; |
| 9243 | 9243 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 9257 | 9257 |
| 9258 bool String::SlowEquals(Handle<String> one, Handle<String> two) { | 9258 bool String::SlowEquals(Handle<String> one, Handle<String> two) { |
| 9259 // Fast check: negative check with lengths. | 9259 // Fast check: negative check with lengths. |
| 9260 int one_length = one->length(); | 9260 int one_length = one->length(); |
| 9261 if (one_length != two->length()) return false; | 9261 if (one_length != two->length()) return false; |
| 9262 if (one_length == 0) return true; | 9262 if (one_length == 0) return true; |
| 9263 | 9263 |
| 9264 // Fast check: if hash code is computed for both strings | 9264 // Fast check: if hash code is computed for both strings |
| 9265 // a fast negative check can be performed. | 9265 // a fast negative check can be performed. |
| 9266 if (one->HasHashCode() && two->HasHashCode()) { | 9266 if (one->HasHashCode() && two->HasHashCode()) { |
| 9267 #ifdef ENABLE_SLOW_ASSERTS | 9267 #ifdef ENABLE_SLOW_DCHECKS |
| 9268 if (FLAG_enable_slow_asserts) { | 9268 if (FLAG_enable_slow_asserts) { |
| 9269 if (one->Hash() != two->Hash()) { | 9269 if (one->Hash() != two->Hash()) { |
| 9270 bool found_difference = false; | 9270 bool found_difference = false; |
| 9271 for (int i = 0; i < one_length; i++) { | 9271 for (int i = 0; i < one_length; i++) { |
| 9272 if (one->Get(i) != two->Get(i)) { | 9272 if (one->Get(i) != two->Get(i)) { |
| 9273 found_difference = true; | 9273 found_difference = true; |
| 9274 break; | 9274 break; |
| 9275 } | 9275 } |
| 9276 } | 9276 } |
| 9277 ASSERT(found_difference); | 9277 DCHECK(found_difference); |
| 9278 } | 9278 } |
| 9279 } | 9279 } |
| 9280 #endif | 9280 #endif |
| 9281 if (one->Hash() != two->Hash()) return false; | 9281 if (one->Hash() != two->Hash()) return false; |
| 9282 } | 9282 } |
| 9283 | 9283 |
| 9284 // We know the strings are both non-empty. Compare the first chars | 9284 // We know the strings are both non-empty. Compare the first chars |
| 9285 // before we try to flatten the strings. | 9285 // before we try to flatten the strings. |
| 9286 if (one->Get(0) != two->Get(0)) return false; | 9286 if (one->Get(0) != two->Get(0)) return false; |
| 9287 | 9287 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9330 (str_len < slen || | 9330 (str_len < slen || |
| 9331 str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) { | 9331 str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) { |
| 9332 return false; | 9332 return false; |
| 9333 } | 9333 } |
| 9334 int i; | 9334 int i; |
| 9335 unsigned remaining_in_str = static_cast<unsigned>(str_len); | 9335 unsigned remaining_in_str = static_cast<unsigned>(str_len); |
| 9336 const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start()); | 9336 const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start()); |
| 9337 for (i = 0; i < slen && remaining_in_str > 0; i++) { | 9337 for (i = 0; i < slen && remaining_in_str > 0; i++) { |
| 9338 unsigned cursor = 0; | 9338 unsigned cursor = 0; |
| 9339 uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor); | 9339 uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor); |
| 9340 ASSERT(cursor > 0 && cursor <= remaining_in_str); | 9340 DCHECK(cursor > 0 && cursor <= remaining_in_str); |
| 9341 if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) { | 9341 if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) { |
| 9342 if (i > slen - 1) return false; | 9342 if (i > slen - 1) return false; |
| 9343 if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false; | 9343 if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false; |
| 9344 if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false; | 9344 if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false; |
| 9345 } else { | 9345 } else { |
| 9346 if (Get(i) != r) return false; | 9346 if (Get(i) != r) return false; |
| 9347 } | 9347 } |
| 9348 utf8_data += cursor; | 9348 utf8_data += cursor; |
| 9349 remaining_in_str -= cursor; | 9349 remaining_in_str -= cursor; |
| 9350 } | 9350 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 9378 } | 9378 } |
| 9379 for (int i = 0; i < slen; i++) { | 9379 for (int i = 0; i < slen; i++) { |
| 9380 if (Get(i) != str[i]) return false; | 9380 if (Get(i) != str[i]) return false; |
| 9381 } | 9381 } |
| 9382 return true; | 9382 return true; |
| 9383 } | 9383 } |
| 9384 | 9384 |
| 9385 | 9385 |
| 9386 uint32_t String::ComputeAndSetHash() { | 9386 uint32_t String::ComputeAndSetHash() { |
| 9387 // Should only be called if hash code has not yet been computed. | 9387 // Should only be called if hash code has not yet been computed. |
| 9388 ASSERT(!HasHashCode()); | 9388 DCHECK(!HasHashCode()); |
| 9389 | 9389 |
| 9390 // Store the hash code in the object. | 9390 // Store the hash code in the object. |
| 9391 uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed()); | 9391 uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed()); |
| 9392 set_hash_field(field); | 9392 set_hash_field(field); |
| 9393 | 9393 |
| 9394 // Check the hash code is there. | 9394 // Check the hash code is there. |
| 9395 ASSERT(HasHashCode()); | 9395 DCHECK(HasHashCode()); |
| 9396 uint32_t result = field >> kHashShift; | 9396 uint32_t result = field >> kHashShift; |
| 9397 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. | 9397 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. |
| 9398 return result; | 9398 return result; |
| 9399 } | 9399 } |
| 9400 | 9400 |
| 9401 | 9401 |
| 9402 bool String::ComputeArrayIndex(uint32_t* index) { | 9402 bool String::ComputeArrayIndex(uint32_t* index) { |
| 9403 int length = this->length(); | 9403 int length = this->length(); |
| 9404 if (length == 0 || length > kMaxArrayIndexSize) return false; | 9404 if (length == 0 || length > kMaxArrayIndexSize) return false; |
| 9405 ConsStringIteratorOp op; | 9405 ConsStringIteratorOp op; |
| 9406 StringCharacterStream stream(this, &op); | 9406 StringCharacterStream stream(this, &op); |
| 9407 return StringToArrayIndex(&stream, index); | 9407 return StringToArrayIndex(&stream, index); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 9424 | 9424 |
| 9425 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) { | 9425 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) { |
| 9426 int new_size, old_size; | 9426 int new_size, old_size; |
| 9427 int old_length = string->length(); | 9427 int old_length = string->length(); |
| 9428 if (old_length <= new_length) return string; | 9428 if (old_length <= new_length) return string; |
| 9429 | 9429 |
| 9430 if (string->IsSeqOneByteString()) { | 9430 if (string->IsSeqOneByteString()) { |
| 9431 old_size = SeqOneByteString::SizeFor(old_length); | 9431 old_size = SeqOneByteString::SizeFor(old_length); |
| 9432 new_size = SeqOneByteString::SizeFor(new_length); | 9432 new_size = SeqOneByteString::SizeFor(new_length); |
| 9433 } else { | 9433 } else { |
| 9434 ASSERT(string->IsSeqTwoByteString()); | 9434 DCHECK(string->IsSeqTwoByteString()); |
| 9435 old_size = SeqTwoByteString::SizeFor(old_length); | 9435 old_size = SeqTwoByteString::SizeFor(old_length); |
| 9436 new_size = SeqTwoByteString::SizeFor(new_length); | 9436 new_size = SeqTwoByteString::SizeFor(new_length); |
| 9437 } | 9437 } |
| 9438 | 9438 |
| 9439 int delta = old_size - new_size; | 9439 int delta = old_size - new_size; |
| 9440 | 9440 |
| 9441 Address start_of_string = string->address(); | 9441 Address start_of_string = string->address(); |
| 9442 ASSERT_OBJECT_ALIGNED(start_of_string); | 9442 DCHECK_OBJECT_ALIGNED(start_of_string); |
| 9443 ASSERT_OBJECT_ALIGNED(start_of_string + new_size); | 9443 DCHECK_OBJECT_ALIGNED(start_of_string + new_size); |
| 9444 | 9444 |
| 9445 Heap* heap = string->GetHeap(); | 9445 Heap* heap = string->GetHeap(); |
| 9446 NewSpace* newspace = heap->new_space(); | 9446 NewSpace* newspace = heap->new_space(); |
| 9447 if (newspace->Contains(start_of_string) && | 9447 if (newspace->Contains(start_of_string) && |
| 9448 newspace->top() == start_of_string + old_size) { | 9448 newspace->top() == start_of_string + old_size) { |
| 9449 // Last allocated object in new space. Simply lower allocation top. | 9449 // Last allocated object in new space. Simply lower allocation top. |
| 9450 newspace->set_top(start_of_string + new_size); | 9450 newspace->set_top(start_of_string + new_size); |
| 9451 } else { | 9451 } else { |
| 9452 // Sizes are pointer size aligned, so that we can use filler objects | 9452 // Sizes are pointer size aligned, so that we can use filler objects |
| 9453 // that are a multiple of pointer size. | 9453 // that are a multiple of pointer size. |
| 9454 heap->CreateFillerObjectAt(start_of_string + new_size, delta); | 9454 heap->CreateFillerObjectAt(start_of_string + new_size, delta); |
| 9455 } | 9455 } |
| 9456 heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR); | 9456 heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR); |
| 9457 | 9457 |
| 9458 // We are storing the new length using release store after creating a filler | 9458 // We are storing the new length using release store after creating a filler |
| 9459 // for the left-over space to avoid races with the sweeper thread. | 9459 // for the left-over space to avoid races with the sweeper thread. |
| 9460 string->synchronized_set_length(new_length); | 9460 string->synchronized_set_length(new_length); |
| 9461 | 9461 |
| 9462 if (new_length == 0) return heap->isolate()->factory()->empty_string(); | 9462 if (new_length == 0) return heap->isolate()->factory()->empty_string(); |
| 9463 return string; | 9463 return string; |
| 9464 } | 9464 } |
| 9465 | 9465 |
| 9466 | 9466 |
| 9467 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { | 9467 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { |
| 9468 // For array indexes mix the length into the hash as an array index could | 9468 // For array indexes mix the length into the hash as an array index could |
| 9469 // be zero. | 9469 // be zero. |
| 9470 ASSERT(length > 0); | 9470 DCHECK(length > 0); |
| 9471 ASSERT(length <= String::kMaxArrayIndexSize); | 9471 DCHECK(length <= String::kMaxArrayIndexSize); |
| 9472 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 9472 DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) < |
| 9473 (1 << String::kArrayIndexValueBits)); | 9473 (1 << String::kArrayIndexValueBits)); |
| 9474 | 9474 |
| 9475 value <<= String::ArrayIndexValueBits::kShift; | 9475 value <<= String::ArrayIndexValueBits::kShift; |
| 9476 value |= length << String::ArrayIndexLengthBits::kShift; | 9476 value |= length << String::ArrayIndexLengthBits::kShift; |
| 9477 | 9477 |
| 9478 ASSERT((value & String::kIsNotArrayIndexMask) == 0); | 9478 DCHECK((value & String::kIsNotArrayIndexMask) == 0); |
| 9479 ASSERT((length > String::kMaxCachedArrayIndexLength) || | 9479 DCHECK((length > String::kMaxCachedArrayIndexLength) || |
| 9480 (value & String::kContainsCachedArrayIndexMask) == 0); | 9480 (value & String::kContainsCachedArrayIndexMask) == 0); |
| 9481 return value; | 9481 return value; |
| 9482 } | 9482 } |
| 9483 | 9483 |
| 9484 | 9484 |
| 9485 uint32_t StringHasher::GetHashField() { | 9485 uint32_t StringHasher::GetHashField() { |
| 9486 if (length_ <= String::kMaxHashCalcLength) { | 9486 if (length_ <= String::kMaxHashCalcLength) { |
| 9487 if (is_array_index_) { | 9487 if (is_array_index_) { |
| 9488 return MakeArrayIndexHash(array_index_, length_); | 9488 return MakeArrayIndexHash(array_index_, length_); |
| 9489 } | 9489 } |
| 9490 return (GetHashCore(raw_running_hash_) << String::kHashShift) | | 9490 return (GetHashCore(raw_running_hash_) << String::kHashShift) | |
| 9491 String::kIsNotArrayIndexMask; | 9491 String::kIsNotArrayIndexMask; |
| 9492 } else { | 9492 } else { |
| 9493 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask; | 9493 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask; |
| 9494 } | 9494 } |
| 9495 } | 9495 } |
| 9496 | 9496 |
| 9497 | 9497 |
| 9498 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars, | 9498 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars, |
| 9499 uint32_t seed, | 9499 uint32_t seed, |
| 9500 int* utf16_length_out) { | 9500 int* utf16_length_out) { |
| 9501 int vector_length = chars.length(); | 9501 int vector_length = chars.length(); |
| 9502 // Handle some edge cases | 9502 // Handle some edge cases |
| 9503 if (vector_length <= 1) { | 9503 if (vector_length <= 1) { |
| 9504 ASSERT(vector_length == 0 || | 9504 DCHECK(vector_length == 0 || |
| 9505 static_cast<uint8_t>(chars.start()[0]) <= | 9505 static_cast<uint8_t>(chars.start()[0]) <= |
| 9506 unibrow::Utf8::kMaxOneByteChar); | 9506 unibrow::Utf8::kMaxOneByteChar); |
| 9507 *utf16_length_out = vector_length; | 9507 *utf16_length_out = vector_length; |
| 9508 return HashSequentialString(chars.start(), vector_length, seed); | 9508 return HashSequentialString(chars.start(), vector_length, seed); |
| 9509 } | 9509 } |
| 9510 // Start with a fake length which won't affect computation. | 9510 // Start with a fake length which won't affect computation. |
| 9511 // It will be updated later. | 9511 // It will be updated later. |
| 9512 StringHasher hasher(String::kMaxArrayIndexSize, seed); | 9512 StringHasher hasher(String::kMaxArrayIndexSize, seed); |
| 9513 unsigned remaining = static_cast<unsigned>(vector_length); | 9513 unsigned remaining = static_cast<unsigned>(vector_length); |
| 9514 const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start()); | 9514 const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start()); |
| 9515 int utf16_length = 0; | 9515 int utf16_length = 0; |
| 9516 bool is_index = true; | 9516 bool is_index = true; |
| 9517 ASSERT(hasher.is_array_index_); | 9517 DCHECK(hasher.is_array_index_); |
| 9518 while (remaining > 0) { | 9518 while (remaining > 0) { |
| 9519 unsigned consumed = 0; | 9519 unsigned consumed = 0; |
| 9520 uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed); | 9520 uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed); |
| 9521 ASSERT(consumed > 0 && consumed <= remaining); | 9521 DCHECK(consumed > 0 && consumed <= remaining); |
| 9522 stream += consumed; | 9522 stream += consumed; |
| 9523 remaining -= consumed; | 9523 remaining -= consumed; |
| 9524 bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode; | 9524 bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode; |
| 9525 utf16_length += is_two_characters ? 2 : 1; | 9525 utf16_length += is_two_characters ? 2 : 1; |
| 9526 // No need to keep hashing. But we do need to calculate utf16_length. | 9526 // No need to keep hashing. But we do need to calculate utf16_length. |
| 9527 if (utf16_length > String::kMaxHashCalcLength) continue; | 9527 if (utf16_length > String::kMaxHashCalcLength) continue; |
| 9528 if (is_two_characters) { | 9528 if (is_two_characters) { |
| 9529 uint16_t c1 = unibrow::Utf16::LeadSurrogate(c); | 9529 uint16_t c1 = unibrow::Utf16::LeadSurrogate(c); |
| 9530 uint16_t c2 = unibrow::Utf16::TrailSurrogate(c); | 9530 uint16_t c2 = unibrow::Utf16::TrailSurrogate(c); |
| 9531 hasher.AddCharacter(c1); | 9531 hasher.AddCharacter(c1); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9638 // If there are no transitions to be cleared, return. | 9638 // If there are no transitions to be cleared, return. |
| 9639 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 9639 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
| 9640 // properly cleared. | 9640 // properly cleared. |
| 9641 if (transition_index == t->number_of_transitions()) return; | 9641 if (transition_index == t->number_of_transitions()) return; |
| 9642 | 9642 |
| 9643 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 9643 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 9644 | 9644 |
| 9645 if (descriptors_owner_died) { | 9645 if (descriptors_owner_died) { |
| 9646 if (number_of_own_descriptors > 0) { | 9646 if (number_of_own_descriptors > 0) { |
| 9647 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); | 9647 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); |
| 9648 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); | 9648 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); |
| 9649 set_owns_descriptors(true); | 9649 set_owns_descriptors(true); |
| 9650 } else { | 9650 } else { |
| 9651 ASSERT(descriptors == GetHeap()->empty_descriptor_array()); | 9651 DCHECK(descriptors == GetHeap()->empty_descriptor_array()); |
| 9652 } | 9652 } |
| 9653 } | 9653 } |
| 9654 | 9654 |
| 9655 // Note that we never eliminate a transition array, though we might right-trim | 9655 // Note that we never eliminate a transition array, though we might right-trim |
| 9656 // such that number_of_transitions() == 0. If this assumption changes, | 9656 // such that number_of_transitions() == 0. If this assumption changes, |
| 9657 // TransitionArray::CopyInsert() will need to deal with the case that a | 9657 // TransitionArray::CopyInsert() will need to deal with the case that a |
| 9658 // transition array disappeared during GC. | 9658 // transition array disappeared during GC. |
| 9659 int trim = t->number_of_transitions() - transition_index; | 9659 int trim = t->number_of_transitions() - transition_index; |
| 9660 if (trim > 0) { | 9660 if (trim > 0) { |
| 9661 RightTrimFixedArray<Heap::FROM_GC>(heap, t, t->IsSimpleTransition() | 9661 RightTrimFixedArray<Heap::FROM_GC>(heap, t, t->IsSimpleTransition() |
| 9662 ? trim : trim * TransitionArray::kTransitionSize); | 9662 ? trim : trim * TransitionArray::kTransitionSize); |
| 9663 } | 9663 } |
| 9664 ASSERT(HasTransitionArray()); | 9664 DCHECK(HasTransitionArray()); |
| 9665 } | 9665 } |
| 9666 | 9666 |
| 9667 | 9667 |
| 9668 int Map::Hash() { | 9668 int Map::Hash() { |
| 9669 // For performance reasons we only hash the 3 most variable fields of a map: | 9669 // For performance reasons we only hash the 3 most variable fields of a map: |
| 9670 // constructor, prototype and bit_field2. | 9670 // constructor, prototype and bit_field2. |
| 9671 | 9671 |
| 9672 // Shift away the tag. | 9672 // Shift away the tag. |
| 9673 int hash = (static_cast<uint32_t>( | 9673 int hash = (static_cast<uint32_t>( |
| 9674 reinterpret_cast<uintptr_t>(constructor())) >> 2); | 9674 reinterpret_cast<uintptr_t>(constructor())) >> 2); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9754 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { | 9754 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { |
| 9755 // Iterate over all fields in the body but take care in dealing with | 9755 // Iterate over all fields in the body but take care in dealing with |
| 9756 // the code entry. | 9756 // the code entry. |
| 9757 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 9757 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
| 9758 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 9758 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
| 9759 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 9759 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
| 9760 } | 9760 } |
| 9761 | 9761 |
| 9762 | 9762 |
| 9763 void JSFunction::MarkForOptimization() { | 9763 void JSFunction::MarkForOptimization() { |
| 9764 ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints()); | 9764 DCHECK(is_compiled() || GetIsolate()->DebuggerHasBreakPoints()); |
| 9765 ASSERT(!IsOptimized()); | 9765 DCHECK(!IsOptimized()); |
| 9766 ASSERT(shared()->allows_lazy_compilation() || | 9766 DCHECK(shared()->allows_lazy_compilation() || |
| 9767 code()->optimizable()); | 9767 code()->optimizable()); |
| 9768 ASSERT(!shared()->is_generator()); | 9768 DCHECK(!shared()->is_generator()); |
| 9769 set_code_no_write_barrier( | 9769 set_code_no_write_barrier( |
| 9770 GetIsolate()->builtins()->builtin(Builtins::kCompileOptimized)); | 9770 GetIsolate()->builtins()->builtin(Builtins::kCompileOptimized)); |
| 9771 // No write barrier required, since the builtin is part of the root set. | 9771 // No write barrier required, since the builtin is part of the root set. |
| 9772 } | 9772 } |
| 9773 | 9773 |
| 9774 | 9774 |
| 9775 void JSFunction::MarkForConcurrentOptimization() { | 9775 void JSFunction::MarkForConcurrentOptimization() { |
| 9776 ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints()); | 9776 DCHECK(is_compiled() || GetIsolate()->DebuggerHasBreakPoints()); |
| 9777 ASSERT(!IsOptimized()); | 9777 DCHECK(!IsOptimized()); |
| 9778 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); | 9778 DCHECK(shared()->allows_lazy_compilation() || code()->optimizable()); |
| 9779 ASSERT(!shared()->is_generator()); | 9779 DCHECK(!shared()->is_generator()); |
| 9780 ASSERT(GetIsolate()->concurrent_recompilation_enabled()); | 9780 DCHECK(GetIsolate()->concurrent_recompilation_enabled()); |
| 9781 if (FLAG_trace_concurrent_recompilation) { | 9781 if (FLAG_trace_concurrent_recompilation) { |
| 9782 PrintF(" ** Marking "); | 9782 PrintF(" ** Marking "); |
| 9783 PrintName(); | 9783 PrintName(); |
| 9784 PrintF(" for concurrent recompilation.\n"); | 9784 PrintF(" for concurrent recompilation.\n"); |
| 9785 } | 9785 } |
| 9786 set_code_no_write_barrier( | 9786 set_code_no_write_barrier( |
| 9787 GetIsolate()->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); | 9787 GetIsolate()->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); |
| 9788 // No write barrier required, since the builtin is part of the root set. | 9788 // No write barrier required, since the builtin is part of the root set. |
| 9789 } | 9789 } |
| 9790 | 9790 |
| 9791 | 9791 |
| 9792 void JSFunction::MarkInOptimizationQueue() { | 9792 void JSFunction::MarkInOptimizationQueue() { |
| 9793 // We can only arrive here via the concurrent-recompilation builtin. If | 9793 // We can only arrive here via the concurrent-recompilation builtin. If |
| 9794 // break points were set, the code would point to the lazy-compile builtin. | 9794 // break points were set, the code would point to the lazy-compile builtin. |
| 9795 ASSERT(!GetIsolate()->DebuggerHasBreakPoints()); | 9795 DCHECK(!GetIsolate()->DebuggerHasBreakPoints()); |
| 9796 ASSERT(IsMarkedForConcurrentOptimization() && !IsOptimized()); | 9796 DCHECK(IsMarkedForConcurrentOptimization() && !IsOptimized()); |
| 9797 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); | 9797 DCHECK(shared()->allows_lazy_compilation() || code()->optimizable()); |
| 9798 ASSERT(GetIsolate()->concurrent_recompilation_enabled()); | 9798 DCHECK(GetIsolate()->concurrent_recompilation_enabled()); |
| 9799 if (FLAG_trace_concurrent_recompilation) { | 9799 if (FLAG_trace_concurrent_recompilation) { |
| 9800 PrintF(" ** Queueing "); | 9800 PrintF(" ** Queueing "); |
| 9801 PrintName(); | 9801 PrintName(); |
| 9802 PrintF(" for concurrent recompilation.\n"); | 9802 PrintF(" for concurrent recompilation.\n"); |
| 9803 } | 9803 } |
| 9804 set_code_no_write_barrier( | 9804 set_code_no_write_barrier( |
| 9805 GetIsolate()->builtins()->builtin(Builtins::kInOptimizationQueue)); | 9805 GetIsolate()->builtins()->builtin(Builtins::kInOptimizationQueue)); |
| 9806 // No write barrier required, since the builtin is part of the root set. | 9806 // No write barrier required, since the builtin is part of the root set. |
| 9807 } | 9807 } |
| 9808 | 9808 |
| 9809 | 9809 |
| 9810 void SharedFunctionInfo::AddToOptimizedCodeMap( | 9810 void SharedFunctionInfo::AddToOptimizedCodeMap( |
| 9811 Handle<SharedFunctionInfo> shared, | 9811 Handle<SharedFunctionInfo> shared, |
| 9812 Handle<Context> native_context, | 9812 Handle<Context> native_context, |
| 9813 Handle<Code> code, | 9813 Handle<Code> code, |
| 9814 Handle<FixedArray> literals, | 9814 Handle<FixedArray> literals, |
| 9815 BailoutId osr_ast_id) { | 9815 BailoutId osr_ast_id) { |
| 9816 Isolate* isolate = shared->GetIsolate(); | 9816 Isolate* isolate = shared->GetIsolate(); |
| 9817 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 9817 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
| 9818 ASSERT(native_context->IsNativeContext()); | 9818 DCHECK(native_context->IsNativeContext()); |
| 9819 STATIC_ASSERT(kEntryLength == 4); | 9819 STATIC_ASSERT(kEntryLength == 4); |
| 9820 Handle<FixedArray> new_code_map; | 9820 Handle<FixedArray> new_code_map; |
| 9821 Handle<Object> value(shared->optimized_code_map(), isolate); | 9821 Handle<Object> value(shared->optimized_code_map(), isolate); |
| 9822 int old_length; | 9822 int old_length; |
| 9823 if (value->IsSmi()) { | 9823 if (value->IsSmi()) { |
| 9824 // No optimized code map. | 9824 // No optimized code map. |
| 9825 ASSERT_EQ(0, Smi::cast(*value)->value()); | 9825 DCHECK_EQ(0, Smi::cast(*value)->value()); |
| 9826 // Create 3 entries per context {context, code, literals}. | 9826 // Create 3 entries per context {context, code, literals}. |
| 9827 new_code_map = isolate->factory()->NewFixedArray(kInitialLength); | 9827 new_code_map = isolate->factory()->NewFixedArray(kInitialLength); |
| 9828 old_length = kEntriesStart; | 9828 old_length = kEntriesStart; |
| 9829 } else { | 9829 } else { |
| 9830 // Copy old map and append one new entry. | 9830 // Copy old map and append one new entry. |
| 9831 Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value); | 9831 Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value); |
| 9832 ASSERT_EQ(-1, shared->SearchOptimizedCodeMap(*native_context, osr_ast_id)); | 9832 DCHECK_EQ(-1, shared->SearchOptimizedCodeMap(*native_context, osr_ast_id)); |
| 9833 old_length = old_code_map->length(); | 9833 old_length = old_code_map->length(); |
| 9834 new_code_map = FixedArray::CopySize( | 9834 new_code_map = FixedArray::CopySize( |
| 9835 old_code_map, old_length + kEntryLength); | 9835 old_code_map, old_length + kEntryLength); |
| 9836 // Zap the old map for the sake of the heap verifier. | 9836 // Zap the old map for the sake of the heap verifier. |
| 9837 if (Heap::ShouldZapGarbage()) { | 9837 if (Heap::ShouldZapGarbage()) { |
| 9838 Object** data = old_code_map->data_start(); | 9838 Object** data = old_code_map->data_start(); |
| 9839 MemsetPointer(data, isolate->heap()->the_hole_value(), old_length); | 9839 MemsetPointer(data, isolate->heap()->the_hole_value(), old_length); |
| 9840 } | 9840 } |
| 9841 } | 9841 } |
| 9842 new_code_map->set(old_length + kContextOffset, *native_context); | 9842 new_code_map->set(old_length + kContextOffset, *native_context); |
| 9843 new_code_map->set(old_length + kCachedCodeOffset, *code); | 9843 new_code_map->set(old_length + kCachedCodeOffset, *code); |
| 9844 new_code_map->set(old_length + kLiteralsOffset, *literals); | 9844 new_code_map->set(old_length + kLiteralsOffset, *literals); |
| 9845 new_code_map->set(old_length + kOsrAstIdOffset, | 9845 new_code_map->set(old_length + kOsrAstIdOffset, |
| 9846 Smi::FromInt(osr_ast_id.ToInt())); | 9846 Smi::FromInt(osr_ast_id.ToInt())); |
| 9847 | 9847 |
| 9848 #ifdef DEBUG | 9848 #ifdef DEBUG |
| 9849 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 9849 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
| 9850 ASSERT(new_code_map->get(i + kContextOffset)->IsNativeContext()); | 9850 DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext()); |
| 9851 ASSERT(new_code_map->get(i + kCachedCodeOffset)->IsCode()); | 9851 DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode()); |
| 9852 ASSERT(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() == | 9852 DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() == |
| 9853 Code::OPTIMIZED_FUNCTION); | 9853 Code::OPTIMIZED_FUNCTION); |
| 9854 ASSERT(new_code_map->get(i + kLiteralsOffset)->IsFixedArray()); | 9854 DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray()); |
| 9855 ASSERT(new_code_map->get(i + kOsrAstIdOffset)->IsSmi()); | 9855 DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi()); |
| 9856 } | 9856 } |
| 9857 #endif | 9857 #endif |
| 9858 shared->set_optimized_code_map(*new_code_map); | 9858 shared->set_optimized_code_map(*new_code_map); |
| 9859 } | 9859 } |
| 9860 | 9860 |
| 9861 | 9861 |
| 9862 FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) { | 9862 FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) { |
| 9863 ASSERT(index > kEntriesStart); | 9863 DCHECK(index > kEntriesStart); |
| 9864 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 9864 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
| 9865 if (!bound()) { | 9865 if (!bound()) { |
| 9866 FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1)); | 9866 FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1)); |
| 9867 ASSERT_NE(NULL, cached_literals); | 9867 DCHECK_NE(NULL, cached_literals); |
| 9868 return cached_literals; | 9868 return cached_literals; |
| 9869 } | 9869 } |
| 9870 return NULL; | 9870 return NULL; |
| 9871 } | 9871 } |
| 9872 | 9872 |
| 9873 | 9873 |
| 9874 Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) { | 9874 Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) { |
| 9875 ASSERT(index > kEntriesStart); | 9875 DCHECK(index > kEntriesStart); |
| 9876 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 9876 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
| 9877 Code* code = Code::cast(code_map->get(index)); | 9877 Code* code = Code::cast(code_map->get(index)); |
| 9878 ASSERT_NE(NULL, code); | 9878 DCHECK_NE(NULL, code); |
| 9879 return code; | 9879 return code; |
| 9880 } | 9880 } |
| 9881 | 9881 |
| 9882 | 9882 |
| 9883 void SharedFunctionInfo::ClearOptimizedCodeMap() { | 9883 void SharedFunctionInfo::ClearOptimizedCodeMap() { |
| 9884 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 9884 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
| 9885 | 9885 |
| 9886 // If the next map link slot is already used then the function was | 9886 // If the next map link slot is already used then the function was |
| 9887 // enqueued with code flushing and we remove it now. | 9887 // enqueued with code flushing and we remove it now. |
| 9888 if (!code_map->get(kNextMapIndex)->IsUndefined()) { | 9888 if (!code_map->get(kNextMapIndex)->IsUndefined()) { |
| 9889 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher(); | 9889 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher(); |
| 9890 flusher->EvictOptimizedCodeMap(this); | 9890 flusher->EvictOptimizedCodeMap(this); |
| 9891 } | 9891 } |
| 9892 | 9892 |
| 9893 ASSERT(code_map->get(kNextMapIndex)->IsUndefined()); | 9893 DCHECK(code_map->get(kNextMapIndex)->IsUndefined()); |
| 9894 set_optimized_code_map(Smi::FromInt(0)); | 9894 set_optimized_code_map(Smi::FromInt(0)); |
| 9895 } | 9895 } |
| 9896 | 9896 |
| 9897 | 9897 |
| 9898 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, | 9898 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, |
| 9899 const char* reason) { | 9899 const char* reason) { |
| 9900 DisallowHeapAllocation no_gc; | 9900 DisallowHeapAllocation no_gc; |
| 9901 if (optimized_code_map()->IsSmi()) return; | 9901 if (optimized_code_map()->IsSmi()) return; |
| 9902 | 9902 |
| 9903 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 9903 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
| 9904 int dst = kEntriesStart; | 9904 int dst = kEntriesStart; |
| 9905 int length = code_map->length(); | 9905 int length = code_map->length(); |
| 9906 for (int src = kEntriesStart; src < length; src += kEntryLength) { | 9906 for (int src = kEntriesStart; src < length; src += kEntryLength) { |
| 9907 ASSERT(code_map->get(src)->IsNativeContext()); | 9907 DCHECK(code_map->get(src)->IsNativeContext()); |
| 9908 if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) { | 9908 if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) { |
| 9909 // Evict the src entry by not copying it to the dst entry. | 9909 // Evict the src entry by not copying it to the dst entry. |
| 9910 if (FLAG_trace_opt) { | 9910 if (FLAG_trace_opt) { |
| 9911 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 9911 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
| 9912 ShortPrint(); | 9912 ShortPrint(); |
| 9913 BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value()); | 9913 BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value()); |
| 9914 if (osr.IsNone()) { | 9914 if (osr.IsNone()) { |
| 9915 PrintF("]\n"); | 9915 PrintF("]\n"); |
| 9916 } else { | 9916 } else { |
| 9917 PrintF(" (osr ast id %d)]\n", osr.ToInt()); | 9917 PrintF(" (osr ast id %d)]\n", osr.ToInt()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 9935 if (dst != length) { | 9935 if (dst != length) { |
| 9936 // Always trim even when array is cleared because of heap verifier. | 9936 // Always trim even when array is cleared because of heap verifier. |
| 9937 RightTrimFixedArray<Heap::FROM_MUTATOR>(GetHeap(), code_map, length - dst); | 9937 RightTrimFixedArray<Heap::FROM_MUTATOR>(GetHeap(), code_map, length - dst); |
| 9938 if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap(); | 9938 if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap(); |
| 9939 } | 9939 } |
| 9940 } | 9940 } |
| 9941 | 9941 |
| 9942 | 9942 |
| 9943 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { | 9943 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { |
| 9944 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 9944 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
| 9945 ASSERT(shrink_by % kEntryLength == 0); | 9945 DCHECK(shrink_by % kEntryLength == 0); |
| 9946 ASSERT(shrink_by <= code_map->length() - kEntriesStart); | 9946 DCHECK(shrink_by <= code_map->length() - kEntriesStart); |
| 9947 // Always trim even when array is cleared because of heap verifier. | 9947 // Always trim even when array is cleared because of heap verifier. |
| 9948 RightTrimFixedArray<Heap::FROM_GC>(GetHeap(), code_map, shrink_by); | 9948 RightTrimFixedArray<Heap::FROM_GC>(GetHeap(), code_map, shrink_by); |
| 9949 if (code_map->length() == kEntriesStart) { | 9949 if (code_map->length() == kEntriesStart) { |
| 9950 ClearOptimizedCodeMap(); | 9950 ClearOptimizedCodeMap(); |
| 9951 } | 9951 } |
| 9952 } | 9952 } |
| 9953 | 9953 |
| 9954 | 9954 |
| 9955 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { | 9955 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { |
| 9956 if (object->IsGlobalObject()) return; | 9956 if (object->IsGlobalObject()) return; |
| 9957 | 9957 |
| 9958 // Make sure prototypes are fast objects and their maps have the bit set | 9958 // Make sure prototypes are fast objects and their maps have the bit set |
| 9959 // so they remain fast. | 9959 // so they remain fast. |
| 9960 if (!object->HasFastProperties()) { | 9960 if (!object->HasFastProperties()) { |
| 9961 MigrateSlowToFast(object, 0); | 9961 MigrateSlowToFast(object, 0); |
| 9962 } | 9962 } |
| 9963 } | 9963 } |
| 9964 | 9964 |
| 9965 | 9965 |
| 9966 Handle<Object> CacheInitialJSArrayMaps( | 9966 Handle<Object> CacheInitialJSArrayMaps( |
| 9967 Handle<Context> native_context, Handle<Map> initial_map) { | 9967 Handle<Context> native_context, Handle<Map> initial_map) { |
| 9968 // Replace all of the cached initial array maps in the native context with | 9968 // Replace all of the cached initial array maps in the native context with |
| 9969 // the appropriate transitioned elements kind maps. | 9969 // the appropriate transitioned elements kind maps. |
| 9970 Factory* factory = native_context->GetIsolate()->factory(); | 9970 Factory* factory = native_context->GetIsolate()->factory(); |
| 9971 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( | 9971 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( |
| 9972 kElementsKindCount, TENURED); | 9972 kElementsKindCount, TENURED); |
| 9973 | 9973 |
| 9974 Handle<Map> current_map = initial_map; | 9974 Handle<Map> current_map = initial_map; |
| 9975 ElementsKind kind = current_map->elements_kind(); | 9975 ElementsKind kind = current_map->elements_kind(); |
| 9976 ASSERT(kind == GetInitialFastElementsKind()); | 9976 DCHECK(kind == GetInitialFastElementsKind()); |
| 9977 maps->set(kind, *current_map); | 9977 maps->set(kind, *current_map); |
| 9978 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; | 9978 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; |
| 9979 i < kFastElementsKindCount; ++i) { | 9979 i < kFastElementsKindCount; ++i) { |
| 9980 Handle<Map> new_map; | 9980 Handle<Map> new_map; |
| 9981 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); | 9981 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); |
| 9982 if (current_map->HasElementsTransition()) { | 9982 if (current_map->HasElementsTransition()) { |
| 9983 new_map = handle(current_map->elements_transition_map()); | 9983 new_map = handle(current_map->elements_transition_map()); |
| 9984 ASSERT(new_map->elements_kind() == next_kind); | 9984 DCHECK(new_map->elements_kind() == next_kind); |
| 9985 } else { | 9985 } else { |
| 9986 new_map = Map::CopyAsElementsKind( | 9986 new_map = Map::CopyAsElementsKind( |
| 9987 current_map, next_kind, INSERT_TRANSITION); | 9987 current_map, next_kind, INSERT_TRANSITION); |
| 9988 } | 9988 } |
| 9989 maps->set(next_kind, *new_map); | 9989 maps->set(next_kind, *new_map); |
| 9990 current_map = new_map; | 9990 current_map = new_map; |
| 9991 } | 9991 } |
| 9992 native_context->set_js_array_maps(*maps); | 9992 native_context->set_js_array_maps(*maps); |
| 9993 return initial_map; | 9993 return initial_map; |
| 9994 } | 9994 } |
| 9995 | 9995 |
| 9996 | 9996 |
| 9997 void JSFunction::SetInstancePrototype(Handle<JSFunction> function, | 9997 void JSFunction::SetInstancePrototype(Handle<JSFunction> function, |
| 9998 Handle<Object> value) { | 9998 Handle<Object> value) { |
| 9999 Isolate* isolate = function->GetIsolate(); | 9999 Isolate* isolate = function->GetIsolate(); |
| 10000 | 10000 |
| 10001 ASSERT(value->IsJSReceiver()); | 10001 DCHECK(value->IsJSReceiver()); |
| 10002 | 10002 |
| 10003 // First some logic for the map of the prototype to make sure it is in fast | 10003 // First some logic for the map of the prototype to make sure it is in fast |
| 10004 // mode. | 10004 // mode. |
| 10005 if (value->IsJSObject()) { | 10005 if (value->IsJSObject()) { |
| 10006 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); | 10006 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); |
| 10007 } | 10007 } |
| 10008 | 10008 |
| 10009 // Now some logic for the maps of the objects that are created by using this | 10009 // Now some logic for the maps of the objects that are created by using this |
| 10010 // function as a constructor. | 10010 // function as a constructor. |
| 10011 if (function->has_initial_map()) { | 10011 if (function->has_initial_map()) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 10039 // needed. At that point, a new initial map is created and the | 10039 // needed. At that point, a new initial map is created and the |
| 10040 // prototype is put into the initial map where it belongs. | 10040 // prototype is put into the initial map where it belongs. |
| 10041 function->set_prototype_or_initial_map(*value); | 10041 function->set_prototype_or_initial_map(*value); |
| 10042 } | 10042 } |
| 10043 isolate->heap()->ClearInstanceofCache(); | 10043 isolate->heap()->ClearInstanceofCache(); |
| 10044 } | 10044 } |
| 10045 | 10045 |
| 10046 | 10046 |
| 10047 void JSFunction::SetPrototype(Handle<JSFunction> function, | 10047 void JSFunction::SetPrototype(Handle<JSFunction> function, |
| 10048 Handle<Object> value) { | 10048 Handle<Object> value) { |
| 10049 ASSERT(function->should_have_prototype()); | 10049 DCHECK(function->should_have_prototype()); |
| 10050 Handle<Object> construct_prototype = value; | 10050 Handle<Object> construct_prototype = value; |
| 10051 | 10051 |
| 10052 // If the value is not a JSReceiver, store the value in the map's | 10052 // If the value is not a JSReceiver, store the value in the map's |
| 10053 // constructor field so it can be accessed. Also, set the prototype | 10053 // constructor field so it can be accessed. Also, set the prototype |
| 10054 // used for constructing objects to the original object prototype. | 10054 // used for constructing objects to the original object prototype. |
| 10055 // See ECMA-262 13.2.2. | 10055 // See ECMA-262 13.2.2. |
| 10056 if (!value->IsJSReceiver()) { | 10056 if (!value->IsJSReceiver()) { |
| 10057 // Copy the map so this does not affect unrelated functions. | 10057 // Copy the map so this does not affect unrelated functions. |
| 10058 // Remove map transitions because they point to maps with a | 10058 // Remove map transitions because they point to maps with a |
| 10059 // different prototype. | 10059 // different prototype. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10128 } | 10128 } |
| 10129 JSObject::OptimizeAsPrototype( | 10129 JSObject::OptimizeAsPrototype( |
| 10130 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); | 10130 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); |
| 10131 } | 10131 } |
| 10132 } else { | 10132 } else { |
| 10133 prototype = isolate->factory()->NewFunctionPrototype(function); | 10133 prototype = isolate->factory()->NewFunctionPrototype(function); |
| 10134 } | 10134 } |
| 10135 map->set_inobject_properties(in_object_properties); | 10135 map->set_inobject_properties(in_object_properties); |
| 10136 map->set_unused_property_fields(in_object_properties); | 10136 map->set_unused_property_fields(in_object_properties); |
| 10137 map->set_prototype(*prototype); | 10137 map->set_prototype(*prototype); |
| 10138 ASSERT(map->has_fast_object_elements()); | 10138 DCHECK(map->has_fast_object_elements()); |
| 10139 | 10139 |
| 10140 // Finally link initial map and constructor function. | 10140 // Finally link initial map and constructor function. |
| 10141 function->set_initial_map(*map); | 10141 function->set_initial_map(*map); |
| 10142 map->set_constructor(*function); | 10142 map->set_constructor(*function); |
| 10143 | 10143 |
| 10144 if (!function->shared()->is_generator()) { | 10144 if (!function->shared()->is_generator()) { |
| 10145 function->StartInobjectSlackTracking(); | 10145 function->StartInobjectSlackTracking(); |
| 10146 } | 10146 } |
| 10147 } | 10147 } |
| 10148 | 10148 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10212 oddball->set_kind(kind); | 10212 oddball->set_kind(kind); |
| 10213 } | 10213 } |
| 10214 | 10214 |
| 10215 | 10215 |
| 10216 void Script::InitLineEnds(Handle<Script> script) { | 10216 void Script::InitLineEnds(Handle<Script> script) { |
| 10217 if (!script->line_ends()->IsUndefined()) return; | 10217 if (!script->line_ends()->IsUndefined()) return; |
| 10218 | 10218 |
| 10219 Isolate* isolate = script->GetIsolate(); | 10219 Isolate* isolate = script->GetIsolate(); |
| 10220 | 10220 |
| 10221 if (!script->source()->IsString()) { | 10221 if (!script->source()->IsString()) { |
| 10222 ASSERT(script->source()->IsUndefined()); | 10222 DCHECK(script->source()->IsUndefined()); |
| 10223 Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0); | 10223 Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0); |
| 10224 script->set_line_ends(*empty); | 10224 script->set_line_ends(*empty); |
| 10225 ASSERT(script->line_ends()->IsFixedArray()); | 10225 DCHECK(script->line_ends()->IsFixedArray()); |
| 10226 return; | 10226 return; |
| 10227 } | 10227 } |
| 10228 | 10228 |
| 10229 Handle<String> src(String::cast(script->source()), isolate); | 10229 Handle<String> src(String::cast(script->source()), isolate); |
| 10230 | 10230 |
| 10231 Handle<FixedArray> array = String::CalculateLineEnds(src, true); | 10231 Handle<FixedArray> array = String::CalculateLineEnds(src, true); |
| 10232 | 10232 |
| 10233 if (*array != isolate->heap()->empty_fixed_array()) { | 10233 if (*array != isolate->heap()->empty_fixed_array()) { |
| 10234 array->set_map(isolate->heap()->fixed_cow_array_map()); | 10234 array->set_map(isolate->heap()->fixed_cow_array_map()); |
| 10235 } | 10235 } |
| 10236 | 10236 |
| 10237 script->set_line_ends(*array); | 10237 script->set_line_ends(*array); |
| 10238 ASSERT(script->line_ends()->IsFixedArray()); | 10238 DCHECK(script->line_ends()->IsFixedArray()); |
| 10239 } | 10239 } |
| 10240 | 10240 |
| 10241 | 10241 |
| 10242 int Script::GetColumnNumber(Handle<Script> script, int code_pos) { | 10242 int Script::GetColumnNumber(Handle<Script> script, int code_pos) { |
| 10243 int line_number = GetLineNumber(script, code_pos); | 10243 int line_number = GetLineNumber(script, code_pos); |
| 10244 if (line_number == -1) return -1; | 10244 if (line_number == -1) return -1; |
| 10245 | 10245 |
| 10246 DisallowHeapAllocation no_allocation; | 10246 DisallowHeapAllocation no_allocation; |
| 10247 FixedArray* line_ends_array = FixedArray::cast(script->line_ends()); | 10247 FixedArray* line_ends_array = FixedArray::cast(script->line_ends()); |
| 10248 line_number = line_number - script->line_offset()->value(); | 10248 line_number = line_number - script->line_offset()->value(); |
| 10249 if (line_number == 0) return code_pos + script->column_offset()->value(); | 10249 if (line_number == 0) return code_pos + script->column_offset()->value(); |
| 10250 int prev_line_end_pos = | 10250 int prev_line_end_pos = |
| 10251 Smi::cast(line_ends_array->get(line_number - 1))->value(); | 10251 Smi::cast(line_ends_array->get(line_number - 1))->value(); |
| 10252 return code_pos - (prev_line_end_pos + 1); | 10252 return code_pos - (prev_line_end_pos + 1); |
| 10253 } | 10253 } |
| 10254 | 10254 |
| 10255 | 10255 |
| 10256 int Script::GetLineNumberWithArray(int code_pos) { | 10256 int Script::GetLineNumberWithArray(int code_pos) { |
| 10257 DisallowHeapAllocation no_allocation; | 10257 DisallowHeapAllocation no_allocation; |
| 10258 ASSERT(line_ends()->IsFixedArray()); | 10258 DCHECK(line_ends()->IsFixedArray()); |
| 10259 FixedArray* line_ends_array = FixedArray::cast(line_ends()); | 10259 FixedArray* line_ends_array = FixedArray::cast(line_ends()); |
| 10260 int line_ends_len = line_ends_array->length(); | 10260 int line_ends_len = line_ends_array->length(); |
| 10261 if (line_ends_len == 0) return -1; | 10261 if (line_ends_len == 0) return -1; |
| 10262 | 10262 |
| 10263 if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) { | 10263 if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) { |
| 10264 return line_offset()->value(); | 10264 return line_offset()->value(); |
| 10265 } | 10265 } |
| 10266 | 10266 |
| 10267 int left = 0; | 10267 int left = 0; |
| 10268 int right = line_ends_len; | 10268 int right = line_ends_len; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10302 | 10302 |
| 10303 | 10303 |
| 10304 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) { | 10304 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) { |
| 10305 Isolate* isolate = script->GetIsolate(); | 10305 Isolate* isolate = script->GetIsolate(); |
| 10306 Handle<String> name_or_source_url_key = | 10306 Handle<String> name_or_source_url_key = |
| 10307 isolate->factory()->InternalizeOneByteString( | 10307 isolate->factory()->InternalizeOneByteString( |
| 10308 STATIC_ASCII_VECTOR("nameOrSourceURL")); | 10308 STATIC_ASCII_VECTOR("nameOrSourceURL")); |
| 10309 Handle<JSObject> script_wrapper = Script::GetWrapper(script); | 10309 Handle<JSObject> script_wrapper = Script::GetWrapper(script); |
| 10310 Handle<Object> property = Object::GetProperty( | 10310 Handle<Object> property = Object::GetProperty( |
| 10311 script_wrapper, name_or_source_url_key).ToHandleChecked(); | 10311 script_wrapper, name_or_source_url_key).ToHandleChecked(); |
| 10312 ASSERT(property->IsJSFunction()); | 10312 DCHECK(property->IsJSFunction()); |
| 10313 Handle<JSFunction> method = Handle<JSFunction>::cast(property); | 10313 Handle<JSFunction> method = Handle<JSFunction>::cast(property); |
| 10314 Handle<Object> result; | 10314 Handle<Object> result; |
| 10315 // Do not check against pending exception, since this function may be called | 10315 // Do not check against pending exception, since this function may be called |
| 10316 // when an exception has already been pending. | 10316 // when an exception has already been pending. |
| 10317 if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) { | 10317 if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) { |
| 10318 return isolate->factory()->undefined_value(); | 10318 return isolate->factory()->undefined_value(); |
| 10319 } | 10319 } |
| 10320 return result; | 10320 return result; |
| 10321 } | 10321 } |
| 10322 | 10322 |
| 10323 | 10323 |
| 10324 // Wrappers for scripts are kept alive and cached in weak global | 10324 // Wrappers for scripts are kept alive and cached in weak global |
| 10325 // handles referred from foreign objects held by the scripts as long as | 10325 // handles referred from foreign objects held by the scripts as long as |
| 10326 // they are used. When they are not used anymore, the garbage | 10326 // they are used. When they are not used anymore, the garbage |
| 10327 // collector will call the weak callback on the global handle | 10327 // collector will call the weak callback on the global handle |
| 10328 // associated with the wrapper and get rid of both the wrapper and the | 10328 // associated with the wrapper and get rid of both the wrapper and the |
| 10329 // handle. | 10329 // handle. |
| 10330 static void ClearWrapperCacheWeakCallback( | 10330 static void ClearWrapperCacheWeakCallback( |
| 10331 const v8::WeakCallbackData<v8::Value, void>& data) { | 10331 const v8::WeakCallbackData<v8::Value, void>& data) { |
| 10332 Object** location = reinterpret_cast<Object**>(data.GetParameter()); | 10332 Object** location = reinterpret_cast<Object**>(data.GetParameter()); |
| 10333 JSValue* wrapper = JSValue::cast(*location); | 10333 JSValue* wrapper = JSValue::cast(*location); |
| 10334 Script::cast(wrapper->value())->ClearWrapperCache(); | 10334 Script::cast(wrapper->value())->ClearWrapperCache(); |
| 10335 } | 10335 } |
| 10336 | 10336 |
| 10337 | 10337 |
| 10338 void Script::ClearWrapperCache() { | 10338 void Script::ClearWrapperCache() { |
| 10339 Foreign* foreign = wrapper(); | 10339 Foreign* foreign = wrapper(); |
| 10340 Object** location = reinterpret_cast<Object**>(foreign->foreign_address()); | 10340 Object** location = reinterpret_cast<Object**>(foreign->foreign_address()); |
| 10341 ASSERT_EQ(foreign->foreign_address(), reinterpret_cast<Address>(location)); | 10341 DCHECK_EQ(foreign->foreign_address(), reinterpret_cast<Address>(location)); |
| 10342 foreign->set_foreign_address(0); | 10342 foreign->set_foreign_address(0); |
| 10343 GlobalHandles::Destroy(location); | 10343 GlobalHandles::Destroy(location); |
| 10344 GetIsolate()->counters()->script_wrappers()->Decrement(); | 10344 GetIsolate()->counters()->script_wrappers()->Decrement(); |
| 10345 } | 10345 } |
| 10346 | 10346 |
| 10347 | 10347 |
| 10348 Handle<JSObject> Script::GetWrapper(Handle<Script> script) { | 10348 Handle<JSObject> Script::GetWrapper(Handle<Script> script) { |
| 10349 if (script->wrapper()->foreign_address() != NULL) { | 10349 if (script->wrapper()->foreign_address() != NULL) { |
| 10350 // Return a handle for the existing script wrapper from the cache. | 10350 // Return a handle for the existing script wrapper from the cache. |
| 10351 return Handle<JSValue>( | 10351 return Handle<JSValue>( |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10466 int length = code_relocation->length(); | 10466 int length = code_relocation->length(); |
| 10467 if (length != recompiled_relocation->length()) return false; | 10467 if (length != recompiled_relocation->length()) return false; |
| 10468 int compare = memcmp(code_relocation->GetDataStartAddress(), | 10468 int compare = memcmp(code_relocation->GetDataStartAddress(), |
| 10469 recompiled_relocation->GetDataStartAddress(), | 10469 recompiled_relocation->GetDataStartAddress(), |
| 10470 length); | 10470 length); |
| 10471 return compare == 0; | 10471 return compare == 0; |
| 10472 } | 10472 } |
| 10473 | 10473 |
| 10474 | 10474 |
| 10475 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) { | 10475 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) { |
| 10476 ASSERT(!has_deoptimization_support()); | 10476 DCHECK(!has_deoptimization_support()); |
| 10477 DisallowHeapAllocation no_allocation; | 10477 DisallowHeapAllocation no_allocation; |
| 10478 Code* code = this->code(); | 10478 Code* code = this->code(); |
| 10479 if (IsCodeEquivalent(code, recompiled)) { | 10479 if (IsCodeEquivalent(code, recompiled)) { |
| 10480 // Copy the deoptimization data from the recompiled code. | 10480 // Copy the deoptimization data from the recompiled code. |
| 10481 code->set_deoptimization_data(recompiled->deoptimization_data()); | 10481 code->set_deoptimization_data(recompiled->deoptimization_data()); |
| 10482 code->set_has_deoptimization_support(true); | 10482 code->set_has_deoptimization_support(true); |
| 10483 } else { | 10483 } else { |
| 10484 // TODO(3025757): In case the recompiled isn't equivalent to the | 10484 // TODO(3025757): In case the recompiled isn't equivalent to the |
| 10485 // old code, we have to replace it. We should try to avoid this | 10485 // old code, we have to replace it. We should try to avoid this |
| 10486 // altogether because it flushes valuable type feedback by | 10486 // altogether because it flushes valuable type feedback by |
| 10487 // effectively resetting all IC state. | 10487 // effectively resetting all IC state. |
| 10488 ReplaceCode(recompiled); | 10488 ReplaceCode(recompiled); |
| 10489 } | 10489 } |
| 10490 ASSERT(has_deoptimization_support()); | 10490 DCHECK(has_deoptimization_support()); |
| 10491 } | 10491 } |
| 10492 | 10492 |
| 10493 | 10493 |
| 10494 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) { | 10494 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) { |
| 10495 // Disable optimization for the shared function info and mark the | 10495 // Disable optimization for the shared function info and mark the |
| 10496 // code as non-optimizable. The marker on the shared function info | 10496 // code as non-optimizable. The marker on the shared function info |
| 10497 // is there because we flush non-optimized code thereby loosing the | 10497 // is there because we flush non-optimized code thereby loosing the |
| 10498 // non-optimizable information for the code. When the code is | 10498 // non-optimizable information for the code. When the code is |
| 10499 // regenerated and set on the shared function info it is marked as | 10499 // regenerated and set on the shared function info it is marked as |
| 10500 // non-optimizable if optimization is disabled for the shared | 10500 // non-optimizable if optimization is disabled for the shared |
| 10501 // function info. | 10501 // function info. |
| 10502 set_optimization_disabled(true); | 10502 set_optimization_disabled(true); |
| 10503 set_bailout_reason(reason); | 10503 set_bailout_reason(reason); |
| 10504 // Code should be the lazy compilation stub or else unoptimized. If the | 10504 // Code should be the lazy compilation stub or else unoptimized. If the |
| 10505 // latter, disable optimization for the code too. | 10505 // latter, disable optimization for the code too. |
| 10506 ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN); | 10506 DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN); |
| 10507 if (code()->kind() == Code::FUNCTION) { | 10507 if (code()->kind() == Code::FUNCTION) { |
| 10508 code()->set_optimizable(false); | 10508 code()->set_optimizable(false); |
| 10509 } | 10509 } |
| 10510 PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this)); | 10510 PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this)); |
| 10511 if (FLAG_trace_opt) { | 10511 if (FLAG_trace_opt) { |
| 10512 PrintF("[disabled optimization for "); | 10512 PrintF("[disabled optimization for "); |
| 10513 ShortPrint(); | 10513 ShortPrint(); |
| 10514 PrintF(", reason: %s]\n", GetBailoutReason(reason)); | 10514 PrintF(", reason: %s]\n", GetBailoutReason(reason)); |
| 10515 } | 10515 } |
| 10516 } | 10516 } |
| 10517 | 10517 |
| 10518 | 10518 |
| 10519 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) { | 10519 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) { |
| 10520 ASSERT(!id.IsNone()); | 10520 DCHECK(!id.IsNone()); |
| 10521 Code* unoptimized = code(); | 10521 Code* unoptimized = code(); |
| 10522 DeoptimizationOutputData* data = | 10522 DeoptimizationOutputData* data = |
| 10523 DeoptimizationOutputData::cast(unoptimized->deoptimization_data()); | 10523 DeoptimizationOutputData::cast(unoptimized->deoptimization_data()); |
| 10524 unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this); | 10524 unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this); |
| 10525 USE(ignore); | 10525 USE(ignore); |
| 10526 return true; // Return true if there was no ASSERT. | 10526 return true; // Return true if there was no DCHECK. |
| 10527 } | 10527 } |
| 10528 | 10528 |
| 10529 | 10529 |
| 10530 void JSFunction::StartInobjectSlackTracking() { | 10530 void JSFunction::StartInobjectSlackTracking() { |
| 10531 ASSERT(has_initial_map() && !IsInobjectSlackTrackingInProgress()); | 10531 DCHECK(has_initial_map() && !IsInobjectSlackTrackingInProgress()); |
| 10532 | 10532 |
| 10533 if (!FLAG_clever_optimizations) return; | 10533 if (!FLAG_clever_optimizations) return; |
| 10534 Map* map = initial_map(); | 10534 Map* map = initial_map(); |
| 10535 | 10535 |
| 10536 // Only initiate the tracking the first time. | 10536 // Only initiate the tracking the first time. |
| 10537 if (map->done_inobject_slack_tracking()) return; | 10537 if (map->done_inobject_slack_tracking()) return; |
| 10538 map->set_done_inobject_slack_tracking(true); | 10538 map->set_done_inobject_slack_tracking(true); |
| 10539 | 10539 |
| 10540 // No tracking during the snapshot construction phase. | 10540 // No tracking during the snapshot construction phase. |
| 10541 Isolate* isolate = GetIsolate(); | 10541 Isolate* isolate = GetIsolate(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10580 map->set_inobject_properties(map->inobject_properties() - slack); | 10580 map->set_inobject_properties(map->inobject_properties() - slack); |
| 10581 map->set_unused_property_fields(map->unused_property_fields() - slack); | 10581 map->set_unused_property_fields(map->unused_property_fields() - slack); |
| 10582 map->set_instance_size(map->instance_size() - slack * kPointerSize); | 10582 map->set_instance_size(map->instance_size() - slack * kPointerSize); |
| 10583 | 10583 |
| 10584 // Visitor id might depend on the instance size, recalculate it. | 10584 // Visitor id might depend on the instance size, recalculate it. |
| 10585 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); | 10585 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); |
| 10586 } | 10586 } |
| 10587 | 10587 |
| 10588 | 10588 |
| 10589 void JSFunction::CompleteInobjectSlackTracking() { | 10589 void JSFunction::CompleteInobjectSlackTracking() { |
| 10590 ASSERT(has_initial_map()); | 10590 DCHECK(has_initial_map()); |
| 10591 Map* map = initial_map(); | 10591 Map* map = initial_map(); |
| 10592 | 10592 |
| 10593 ASSERT(map->done_inobject_slack_tracking()); | 10593 DCHECK(map->done_inobject_slack_tracking()); |
| 10594 map->set_construction_count(kNoSlackTracking); | 10594 map->set_construction_count(kNoSlackTracking); |
| 10595 | 10595 |
| 10596 int slack = map->unused_property_fields(); | 10596 int slack = map->unused_property_fields(); |
| 10597 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); | 10597 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); |
| 10598 if (slack != 0) { | 10598 if (slack != 0) { |
| 10599 // Resize the initial map and all maps in its transition tree. | 10599 // Resize the initial map and all maps in its transition tree. |
| 10600 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); | 10600 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); |
| 10601 } | 10601 } |
| 10602 } | 10602 } |
| 10603 | 10603 |
| 10604 | 10604 |
| 10605 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, | 10605 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, |
| 10606 BailoutId osr_ast_id) { | 10606 BailoutId osr_ast_id) { |
| 10607 DisallowHeapAllocation no_gc; | 10607 DisallowHeapAllocation no_gc; |
| 10608 ASSERT(native_context->IsNativeContext()); | 10608 DCHECK(native_context->IsNativeContext()); |
| 10609 if (!FLAG_cache_optimized_code) return -1; | 10609 if (!FLAG_cache_optimized_code) return -1; |
| 10610 Object* value = optimized_code_map(); | 10610 Object* value = optimized_code_map(); |
| 10611 if (!value->IsSmi()) { | 10611 if (!value->IsSmi()) { |
| 10612 FixedArray* optimized_code_map = FixedArray::cast(value); | 10612 FixedArray* optimized_code_map = FixedArray::cast(value); |
| 10613 int length = optimized_code_map->length(); | 10613 int length = optimized_code_map->length(); |
| 10614 Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt()); | 10614 Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt()); |
| 10615 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 10615 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
| 10616 if (optimized_code_map->get(i + kContextOffset) == native_context && | 10616 if (optimized_code_map->get(i + kContextOffset) == native_context && |
| 10617 optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) { | 10617 optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) { |
| 10618 return i + kCachedCodeOffset; | 10618 return i + kCachedCodeOffset; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 10638 | 10638 |
| 10639 #define DECLARE_TAG(ignore1, ignore2, name) name, | 10639 #define DECLARE_TAG(ignore1, ignore2, name) name, |
| 10640 const char* const VisitorSynchronization::kTagNames[ | 10640 const char* const VisitorSynchronization::kTagNames[ |
| 10641 VisitorSynchronization::kNumberOfSyncTags] = { | 10641 VisitorSynchronization::kNumberOfSyncTags] = { |
| 10642 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) | 10642 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) |
| 10643 }; | 10643 }; |
| 10644 #undef DECLARE_TAG | 10644 #undef DECLARE_TAG |
| 10645 | 10645 |
| 10646 | 10646 |
| 10647 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) { | 10647 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) { |
| 10648 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); | 10648 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); |
| 10649 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 10649 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 10650 Object* old_target = target; | 10650 Object* old_target = target; |
| 10651 VisitPointer(&target); | 10651 VisitPointer(&target); |
| 10652 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. | 10652 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 10653 } | 10653 } |
| 10654 | 10654 |
| 10655 | 10655 |
| 10656 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) { | 10656 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) { |
| 10657 ASSERT(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); | 10657 DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); |
| 10658 Object* stub = rinfo->code_age_stub(); | 10658 Object* stub = rinfo->code_age_stub(); |
| 10659 if (stub) { | 10659 if (stub) { |
| 10660 VisitPointer(&stub); | 10660 VisitPointer(&stub); |
| 10661 } | 10661 } |
| 10662 } | 10662 } |
| 10663 | 10663 |
| 10664 | 10664 |
| 10665 void ObjectVisitor::VisitCodeEntry(Address entry_address) { | 10665 void ObjectVisitor::VisitCodeEntry(Address entry_address) { |
| 10666 Object* code = Code::GetObjectFromEntryAddress(entry_address); | 10666 Object* code = Code::GetObjectFromEntryAddress(entry_address); |
| 10667 Object* old_code = code; | 10667 Object* old_code = code; |
| 10668 VisitPointer(&code); | 10668 VisitPointer(&code); |
| 10669 if (code != old_code) { | 10669 if (code != old_code) { |
| 10670 Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry(); | 10670 Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry(); |
| 10671 } | 10671 } |
| 10672 } | 10672 } |
| 10673 | 10673 |
| 10674 | 10674 |
| 10675 void ObjectVisitor::VisitCell(RelocInfo* rinfo) { | 10675 void ObjectVisitor::VisitCell(RelocInfo* rinfo) { |
| 10676 ASSERT(rinfo->rmode() == RelocInfo::CELL); | 10676 DCHECK(rinfo->rmode() == RelocInfo::CELL); |
| 10677 Object* cell = rinfo->target_cell(); | 10677 Object* cell = rinfo->target_cell(); |
| 10678 Object* old_cell = cell; | 10678 Object* old_cell = cell; |
| 10679 VisitPointer(&cell); | 10679 VisitPointer(&cell); |
| 10680 if (cell != old_cell) { | 10680 if (cell != old_cell) { |
| 10681 rinfo->set_target_cell(reinterpret_cast<Cell*>(cell)); | 10681 rinfo->set_target_cell(reinterpret_cast<Cell*>(cell)); |
| 10682 } | 10682 } |
| 10683 } | 10683 } |
| 10684 | 10684 |
| 10685 | 10685 |
| 10686 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) { | 10686 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) { |
| 10687 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && | 10687 DCHECK((RelocInfo::IsJSReturn(rinfo->rmode()) && |
| 10688 rinfo->IsPatchedReturnSequence()) || | 10688 rinfo->IsPatchedReturnSequence()) || |
| 10689 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 10689 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 10690 rinfo->IsPatchedDebugBreakSlotSequence())); | 10690 rinfo->IsPatchedDebugBreakSlotSequence())); |
| 10691 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 10691 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 10692 Object* old_target = target; | 10692 Object* old_target = target; |
| 10693 VisitPointer(&target); | 10693 VisitPointer(&target); |
| 10694 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. | 10694 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 10695 } | 10695 } |
| 10696 | 10696 |
| 10697 | 10697 |
| 10698 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { | 10698 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { |
| 10699 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 10699 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
| 10700 Object* p = rinfo->target_object(); | 10700 Object* p = rinfo->target_object(); |
| 10701 VisitPointer(&p); | 10701 VisitPointer(&p); |
| 10702 } | 10702 } |
| 10703 | 10703 |
| 10704 | 10704 |
| 10705 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { | 10705 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { |
| 10706 Address p = rinfo->target_reference(); | 10706 Address p = rinfo->target_reference(); |
| 10707 VisitExternalReference(&p); | 10707 VisitExternalReference(&p); |
| 10708 } | 10708 } |
| 10709 | 10709 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 10732 | 10732 |
| 10733 void Code::Relocate(intptr_t delta) { | 10733 void Code::Relocate(intptr_t delta) { |
| 10734 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { | 10734 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { |
| 10735 it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH); | 10735 it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH); |
| 10736 } | 10736 } |
| 10737 CpuFeatures::FlushICache(instruction_start(), instruction_size()); | 10737 CpuFeatures::FlushICache(instruction_start(), instruction_size()); |
| 10738 } | 10738 } |
| 10739 | 10739 |
| 10740 | 10740 |
| 10741 void Code::CopyFrom(const CodeDesc& desc) { | 10741 void Code::CopyFrom(const CodeDesc& desc) { |
| 10742 ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT); | 10742 DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT); |
| 10743 | 10743 |
| 10744 // copy code | 10744 // copy code |
| 10745 CopyBytes(instruction_start(), desc.buffer, | 10745 CopyBytes(instruction_start(), desc.buffer, |
| 10746 static_cast<size_t>(desc.instr_size)); | 10746 static_cast<size_t>(desc.instr_size)); |
| 10747 | 10747 |
| 10748 // copy reloc info | 10748 // copy reloc info |
| 10749 CopyBytes(relocation_start(), | 10749 CopyBytes(relocation_start(), |
| 10750 desc.buffer + desc.buffer_size - desc.reloc_size, | 10750 desc.buffer + desc.buffer_size - desc.reloc_size, |
| 10751 static_cast<size_t>(desc.reloc_size)); | 10751 static_cast<size_t>(desc.reloc_size)); |
| 10752 | 10752 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10848 } | 10848 } |
| 10849 | 10849 |
| 10850 | 10850 |
| 10851 SafepointEntry Code::GetSafepointEntry(Address pc) { | 10851 SafepointEntry Code::GetSafepointEntry(Address pc) { |
| 10852 SafepointTable table(this); | 10852 SafepointTable table(this); |
| 10853 return table.FindEntry(pc); | 10853 return table.FindEntry(pc); |
| 10854 } | 10854 } |
| 10855 | 10855 |
| 10856 | 10856 |
| 10857 Object* Code::FindNthObject(int n, Map* match_map) { | 10857 Object* Code::FindNthObject(int n, Map* match_map) { |
| 10858 ASSERT(is_inline_cache_stub()); | 10858 DCHECK(is_inline_cache_stub()); |
| 10859 DisallowHeapAllocation no_allocation; | 10859 DisallowHeapAllocation no_allocation; |
| 10860 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 10860 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 10861 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10861 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10862 RelocInfo* info = it.rinfo(); | 10862 RelocInfo* info = it.rinfo(); |
| 10863 Object* object = info->target_object(); | 10863 Object* object = info->target_object(); |
| 10864 if (object->IsHeapObject()) { | 10864 if (object->IsHeapObject()) { |
| 10865 if (HeapObject::cast(object)->map() == match_map) { | 10865 if (HeapObject::cast(object)->map() == match_map) { |
| 10866 if (--n == 0) return object; | 10866 if (--n == 0) return object; |
| 10867 } | 10867 } |
| 10868 } | 10868 } |
| 10869 } | 10869 } |
| 10870 return NULL; | 10870 return NULL; |
| 10871 } | 10871 } |
| 10872 | 10872 |
| 10873 | 10873 |
| 10874 AllocationSite* Code::FindFirstAllocationSite() { | 10874 AllocationSite* Code::FindFirstAllocationSite() { |
| 10875 Object* result = FindNthObject(1, GetHeap()->allocation_site_map()); | 10875 Object* result = FindNthObject(1, GetHeap()->allocation_site_map()); |
| 10876 return (result != NULL) ? AllocationSite::cast(result) : NULL; | 10876 return (result != NULL) ? AllocationSite::cast(result) : NULL; |
| 10877 } | 10877 } |
| 10878 | 10878 |
| 10879 | 10879 |
| 10880 Map* Code::FindFirstMap() { | 10880 Map* Code::FindFirstMap() { |
| 10881 Object* result = FindNthObject(1, GetHeap()->meta_map()); | 10881 Object* result = FindNthObject(1, GetHeap()->meta_map()); |
| 10882 return (result != NULL) ? Map::cast(result) : NULL; | 10882 return (result != NULL) ? Map::cast(result) : NULL; |
| 10883 } | 10883 } |
| 10884 | 10884 |
| 10885 | 10885 |
| 10886 void Code::FindAndReplace(const FindAndReplacePattern& pattern) { | 10886 void Code::FindAndReplace(const FindAndReplacePattern& pattern) { |
| 10887 ASSERT(is_inline_cache_stub() || is_handler()); | 10887 DCHECK(is_inline_cache_stub() || is_handler()); |
| 10888 DisallowHeapAllocation no_allocation; | 10888 DisallowHeapAllocation no_allocation; |
| 10889 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 10889 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 10890 STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32); | 10890 STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32); |
| 10891 int current_pattern = 0; | 10891 int current_pattern = 0; |
| 10892 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10892 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10893 RelocInfo* info = it.rinfo(); | 10893 RelocInfo* info = it.rinfo(); |
| 10894 Object* object = info->target_object(); | 10894 Object* object = info->target_object(); |
| 10895 if (object->IsHeapObject()) { | 10895 if (object->IsHeapObject()) { |
| 10896 Map* map = HeapObject::cast(object)->map(); | 10896 Map* map = HeapObject::cast(object)->map(); |
| 10897 if (map == *pattern.find_[current_pattern]) { | 10897 if (map == *pattern.find_[current_pattern]) { |
| 10898 info->set_target_object(*pattern.replace_[current_pattern]); | 10898 info->set_target_object(*pattern.replace_[current_pattern]); |
| 10899 if (++current_pattern == pattern.count_) return; | 10899 if (++current_pattern == pattern.count_) return; |
| 10900 } | 10900 } |
| 10901 } | 10901 } |
| 10902 } | 10902 } |
| 10903 UNREACHABLE(); | 10903 UNREACHABLE(); |
| 10904 } | 10904 } |
| 10905 | 10905 |
| 10906 | 10906 |
| 10907 void Code::FindAllMaps(MapHandleList* maps) { | 10907 void Code::FindAllMaps(MapHandleList* maps) { |
| 10908 ASSERT(is_inline_cache_stub()); | 10908 DCHECK(is_inline_cache_stub()); |
| 10909 DisallowHeapAllocation no_allocation; | 10909 DisallowHeapAllocation no_allocation; |
| 10910 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 10910 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 10911 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10911 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10912 RelocInfo* info = it.rinfo(); | 10912 RelocInfo* info = it.rinfo(); |
| 10913 Object* object = info->target_object(); | 10913 Object* object = info->target_object(); |
| 10914 if (object->IsMap()) maps->Add(handle(Map::cast(object))); | 10914 if (object->IsMap()) maps->Add(handle(Map::cast(object))); |
| 10915 } | 10915 } |
| 10916 } | 10916 } |
| 10917 | 10917 |
| 10918 | 10918 |
| 10919 Code* Code::FindFirstHandler() { | 10919 Code* Code::FindFirstHandler() { |
| 10920 ASSERT(is_inline_cache_stub()); | 10920 DCHECK(is_inline_cache_stub()); |
| 10921 DisallowHeapAllocation no_allocation; | 10921 DisallowHeapAllocation no_allocation; |
| 10922 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | 10922 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); |
| 10923 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10923 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10924 RelocInfo* info = it.rinfo(); | 10924 RelocInfo* info = it.rinfo(); |
| 10925 Code* code = Code::GetCodeFromTargetAddress(info->target_address()); | 10925 Code* code = Code::GetCodeFromTargetAddress(info->target_address()); |
| 10926 if (code->kind() == Code::HANDLER) return code; | 10926 if (code->kind() == Code::HANDLER) return code; |
| 10927 } | 10927 } |
| 10928 return NULL; | 10928 return NULL; |
| 10929 } | 10929 } |
| 10930 | 10930 |
| 10931 | 10931 |
| 10932 bool Code::FindHandlers(CodeHandleList* code_list, int length) { | 10932 bool Code::FindHandlers(CodeHandleList* code_list, int length) { |
| 10933 ASSERT(is_inline_cache_stub()); | 10933 DCHECK(is_inline_cache_stub()); |
| 10934 DisallowHeapAllocation no_allocation; | 10934 DisallowHeapAllocation no_allocation; |
| 10935 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | 10935 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); |
| 10936 int i = 0; | 10936 int i = 0; |
| 10937 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10937 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10938 if (i == length) return true; | 10938 if (i == length) return true; |
| 10939 RelocInfo* info = it.rinfo(); | 10939 RelocInfo* info = it.rinfo(); |
| 10940 Code* code = Code::GetCodeFromTargetAddress(info->target_address()); | 10940 Code* code = Code::GetCodeFromTargetAddress(info->target_address()); |
| 10941 // IC stubs with handlers never contain non-handler code objects before | 10941 // IC stubs with handlers never contain non-handler code objects before |
| 10942 // handler targets. | 10942 // handler targets. |
| 10943 if (code->kind() != Code::HANDLER) break; | 10943 if (code->kind() != Code::HANDLER) break; |
| 10944 code_list->Add(Handle<Code>(code)); | 10944 code_list->Add(Handle<Code>(code)); |
| 10945 i++; | 10945 i++; |
| 10946 } | 10946 } |
| 10947 return i == length; | 10947 return i == length; |
| 10948 } | 10948 } |
| 10949 | 10949 |
| 10950 | 10950 |
| 10951 MaybeHandle<Code> Code::FindHandlerForMap(Map* map) { | 10951 MaybeHandle<Code> Code::FindHandlerForMap(Map* map) { |
| 10952 ASSERT(is_inline_cache_stub()); | 10952 DCHECK(is_inline_cache_stub()); |
| 10953 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | | 10953 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
| 10954 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 10954 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 10955 bool return_next = false; | 10955 bool return_next = false; |
| 10956 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10956 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10957 RelocInfo* info = it.rinfo(); | 10957 RelocInfo* info = it.rinfo(); |
| 10958 if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) { | 10958 if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) { |
| 10959 Object* object = info->target_object(); | 10959 Object* object = info->target_object(); |
| 10960 if (object == map) return_next = true; | 10960 if (object == map) return_next = true; |
| 10961 } else if (return_next) { | 10961 } else if (return_next) { |
| 10962 Code* code = Code::GetCodeFromTargetAddress(info->target_address()); | 10962 Code* code = Code::GetCodeFromTargetAddress(info->target_address()); |
| 10963 ASSERT(code->kind() == Code::HANDLER); | 10963 DCHECK(code->kind() == Code::HANDLER); |
| 10964 return handle(code); | 10964 return handle(code); |
| 10965 } | 10965 } |
| 10966 } | 10966 } |
| 10967 return MaybeHandle<Code>(); | 10967 return MaybeHandle<Code>(); |
| 10968 } | 10968 } |
| 10969 | 10969 |
| 10970 | 10970 |
| 10971 Name* Code::FindFirstName() { | 10971 Name* Code::FindFirstName() { |
| 10972 ASSERT(is_inline_cache_stub()); | 10972 DCHECK(is_inline_cache_stub()); |
| 10973 DisallowHeapAllocation no_allocation; | 10973 DisallowHeapAllocation no_allocation; |
| 10974 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 10974 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 10975 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10975 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10976 RelocInfo* info = it.rinfo(); | 10976 RelocInfo* info = it.rinfo(); |
| 10977 Object* object = info->target_object(); | 10977 Object* object = info->target_object(); |
| 10978 if (object->IsName()) return Name::cast(object); | 10978 if (object->IsName()) return Name::cast(object); |
| 10979 } | 10979 } |
| 10980 return NULL; | 10980 return NULL; |
| 10981 } | 10981 } |
| 10982 | 10982 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11028 vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap), | 11028 vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap), |
| 11029 SKIP_WRITE_BARRIER); | 11029 SKIP_WRITE_BARRIER); |
| 11030 } | 11030 } |
| 11031 } | 11031 } |
| 11032 } | 11032 } |
| 11033 } | 11033 } |
| 11034 | 11034 |
| 11035 | 11035 |
| 11036 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) { | 11036 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) { |
| 11037 DisallowHeapAllocation no_gc; | 11037 DisallowHeapAllocation no_gc; |
| 11038 ASSERT(kind() == FUNCTION); | 11038 DCHECK(kind() == FUNCTION); |
| 11039 BackEdgeTable back_edges(this, &no_gc); | 11039 BackEdgeTable back_edges(this, &no_gc); |
| 11040 for (uint32_t i = 0; i < back_edges.length(); i++) { | 11040 for (uint32_t i = 0; i < back_edges.length(); i++) { |
| 11041 if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i); | 11041 if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i); |
| 11042 } | 11042 } |
| 11043 return BailoutId::None(); | 11043 return BailoutId::None(); |
| 11044 } | 11044 } |
| 11045 | 11045 |
| 11046 | 11046 |
| 11047 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) { | 11047 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) { |
| 11048 DisallowHeapAllocation no_gc; | 11048 DisallowHeapAllocation no_gc; |
| 11049 ASSERT(kind() == FUNCTION); | 11049 DCHECK(kind() == FUNCTION); |
| 11050 BackEdgeTable back_edges(this, &no_gc); | 11050 BackEdgeTable back_edges(this, &no_gc); |
| 11051 for (uint32_t i = 0; i < back_edges.length(); i++) { | 11051 for (uint32_t i = 0; i < back_edges.length(); i++) { |
| 11052 if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i); | 11052 if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i); |
| 11053 } | 11053 } |
| 11054 UNREACHABLE(); // We expect to find the back edge. | 11054 UNREACHABLE(); // We expect to find the back edge. |
| 11055 return 0; | 11055 return 0; |
| 11056 } | 11056 } |
| 11057 | 11057 |
| 11058 | 11058 |
| 11059 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) { | 11059 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11171 #define HANDLE_CODE_AGE(AGE) \ | 11171 #define HANDLE_CODE_AGE(AGE) \ |
| 11172 case k##AGE##CodeAge: { \ | 11172 case k##AGE##CodeAge: { \ |
| 11173 Code* stub = parity == EVEN_MARKING_PARITY \ | 11173 Code* stub = parity == EVEN_MARKING_PARITY \ |
| 11174 ? *builtins->Make##AGE##CodeYoungAgainEvenMarking() \ | 11174 ? *builtins->Make##AGE##CodeYoungAgainEvenMarking() \ |
| 11175 : *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ | 11175 : *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ |
| 11176 return stub; \ | 11176 return stub; \ |
| 11177 } | 11177 } |
| 11178 CODE_AGE_LIST(HANDLE_CODE_AGE) | 11178 CODE_AGE_LIST(HANDLE_CODE_AGE) |
| 11179 #undef HANDLE_CODE_AGE | 11179 #undef HANDLE_CODE_AGE |
| 11180 case kNotExecutedCodeAge: { | 11180 case kNotExecutedCodeAge: { |
| 11181 ASSERT(parity == NO_MARKING_PARITY); | 11181 DCHECK(parity == NO_MARKING_PARITY); |
| 11182 return *builtins->MarkCodeAsExecutedOnce(); | 11182 return *builtins->MarkCodeAsExecutedOnce(); |
| 11183 } | 11183 } |
| 11184 case kExecutedOnceCodeAge: { | 11184 case kExecutedOnceCodeAge: { |
| 11185 ASSERT(parity == NO_MARKING_PARITY); | 11185 DCHECK(parity == NO_MARKING_PARITY); |
| 11186 return *builtins->MarkCodeAsExecutedTwice(); | 11186 return *builtins->MarkCodeAsExecutedTwice(); |
| 11187 } | 11187 } |
| 11188 default: | 11188 default: |
| 11189 UNREACHABLE(); | 11189 UNREACHABLE(); |
| 11190 break; | 11190 break; |
| 11191 } | 11191 } |
| 11192 return NULL; | 11192 return NULL; |
| 11193 } | 11193 } |
| 11194 | 11194 |
| 11195 | 11195 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11264 | 11264 |
| 11265 if (!FLAG_print_code_verbose) { | 11265 if (!FLAG_print_code_verbose) { |
| 11266 os << "\n"; | 11266 os << "\n"; |
| 11267 continue; | 11267 continue; |
| 11268 } | 11268 } |
| 11269 // Print details of the frame translation. | 11269 // Print details of the frame translation. |
| 11270 int translation_index = TranslationIndex(i)->value(); | 11270 int translation_index = TranslationIndex(i)->value(); |
| 11271 TranslationIterator iterator(TranslationByteArray(), translation_index); | 11271 TranslationIterator iterator(TranslationByteArray(), translation_index); |
| 11272 Translation::Opcode opcode = | 11272 Translation::Opcode opcode = |
| 11273 static_cast<Translation::Opcode>(iterator.Next()); | 11273 static_cast<Translation::Opcode>(iterator.Next()); |
| 11274 ASSERT(Translation::BEGIN == opcode); | 11274 DCHECK(Translation::BEGIN == opcode); |
| 11275 int frame_count = iterator.Next(); | 11275 int frame_count = iterator.Next(); |
| 11276 int jsframe_count = iterator.Next(); | 11276 int jsframe_count = iterator.Next(); |
| 11277 os << " " << Translation::StringFor(opcode) | 11277 os << " " << Translation::StringFor(opcode) |
| 11278 << " {frame count=" << frame_count | 11278 << " {frame count=" << frame_count |
| 11279 << ", js frame count=" << jsframe_count << "}\n"; | 11279 << ", js frame count=" << jsframe_count << "}\n"; |
| 11280 | 11280 |
| 11281 while (iterator.HasNext() && | 11281 while (iterator.HasNext() && |
| 11282 Translation::BEGIN != | 11282 Translation::BEGIN != |
| 11283 (opcode = static_cast<Translation::Opcode>(iterator.Next()))) { | 11283 (opcode = static_cast<Translation::Opcode>(iterator.Next()))) { |
| 11284 Vector<char> buf2 = Vector<char>::New(128); | 11284 Vector<char> buf2 = Vector<char>::New(128); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11483 const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true); | 11483 const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true); |
| 11484 os << "major_key = " << (n == NULL ? "null" : n) << "\n"; | 11484 os << "major_key = " << (n == NULL ? "null" : n) << "\n"; |
| 11485 } | 11485 } |
| 11486 if (is_inline_cache_stub()) { | 11486 if (is_inline_cache_stub()) { |
| 11487 os << "ic_state = " << ICState2String(ic_state()) << "\n"; | 11487 os << "ic_state = " << ICState2String(ic_state()) << "\n"; |
| 11488 PrintExtraICState(os, kind(), extra_ic_state()); | 11488 PrintExtraICState(os, kind(), extra_ic_state()); |
| 11489 if (ic_state() == MONOMORPHIC) { | 11489 if (ic_state() == MONOMORPHIC) { |
| 11490 os << "type = " << StubType2String(type()) << "\n"; | 11490 os << "type = " << StubType2String(type()) << "\n"; |
| 11491 } | 11491 } |
| 11492 if (is_compare_ic_stub()) { | 11492 if (is_compare_ic_stub()) { |
| 11493 ASSERT(CodeStub::GetMajorKey(this) == CodeStub::CompareIC); | 11493 DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC); |
| 11494 CompareIC::State left_state, right_state, handler_state; | 11494 CompareIC::State left_state, right_state, handler_state; |
| 11495 Token::Value op; | 11495 Token::Value op; |
| 11496 ICCompareStub::DecodeKey(stub_key(), &left_state, &right_state, | 11496 ICCompareStub::DecodeKey(stub_key(), &left_state, &right_state, |
| 11497 &handler_state, &op); | 11497 &handler_state, &op); |
| 11498 os << "compare_state = " << CompareIC::GetStateName(left_state) << "*" | 11498 os << "compare_state = " << CompareIC::GetStateName(left_state) << "*" |
| 11499 << CompareIC::GetStateName(right_state) << " -> " | 11499 << CompareIC::GetStateName(right_state) << " -> " |
| 11500 << CompareIC::GetStateName(handler_state) << "\n"; | 11500 << CompareIC::GetStateName(handler_state) << "\n"; |
| 11501 os << "compare_operation = " << Token::Name(op) << "\n"; | 11501 os << "compare_operation = " << Token::Name(op) << "\n"; |
| 11502 } | 11502 } |
| 11503 } | 11503 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11587 } | 11587 } |
| 11588 #endif // ENABLE_DISASSEMBLER | 11588 #endif // ENABLE_DISASSEMBLER |
| 11589 | 11589 |
| 11590 | 11590 |
| 11591 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength( | 11591 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength( |
| 11592 Handle<JSObject> object, | 11592 Handle<JSObject> object, |
| 11593 int capacity, | 11593 int capacity, |
| 11594 int length, | 11594 int length, |
| 11595 SetFastElementsCapacitySmiMode smi_mode) { | 11595 SetFastElementsCapacitySmiMode smi_mode) { |
| 11596 // We should never end in here with a pixel or external array. | 11596 // We should never end in here with a pixel or external array. |
| 11597 ASSERT(!object->HasExternalArrayElements()); | 11597 DCHECK(!object->HasExternalArrayElements()); |
| 11598 | 11598 |
| 11599 // Allocate a new fast elements backing store. | 11599 // Allocate a new fast elements backing store. |
| 11600 Handle<FixedArray> new_elements = | 11600 Handle<FixedArray> new_elements = |
| 11601 object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity); | 11601 object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity); |
| 11602 | 11602 |
| 11603 ElementsKind elements_kind = object->GetElementsKind(); | 11603 ElementsKind elements_kind = object->GetElementsKind(); |
| 11604 ElementsKind new_elements_kind; | 11604 ElementsKind new_elements_kind; |
| 11605 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, | 11605 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, |
| 11606 // or if it's allowed and the old elements array contained only SMIs. | 11606 // or if it's allowed and the old elements array contained only SMIs. |
| 11607 bool has_fast_smi_elements = | 11607 bool has_fast_smi_elements = |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11647 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length)); | 11647 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length)); |
| 11648 } | 11648 } |
| 11649 return new_elements; | 11649 return new_elements; |
| 11650 } | 11650 } |
| 11651 | 11651 |
| 11652 | 11652 |
| 11653 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object, | 11653 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object, |
| 11654 int capacity, | 11654 int capacity, |
| 11655 int length) { | 11655 int length) { |
| 11656 // We should never end in here with a pixel or external array. | 11656 // We should never end in here with a pixel or external array. |
| 11657 ASSERT(!object->HasExternalArrayElements()); | 11657 DCHECK(!object->HasExternalArrayElements()); |
| 11658 | 11658 |
| 11659 Handle<FixedArrayBase> elems = | 11659 Handle<FixedArrayBase> elems = |
| 11660 object->GetIsolate()->factory()->NewFixedDoubleArray(capacity); | 11660 object->GetIsolate()->factory()->NewFixedDoubleArray(capacity); |
| 11661 | 11661 |
| 11662 ElementsKind elements_kind = object->GetElementsKind(); | 11662 ElementsKind elements_kind = object->GetElementsKind(); |
| 11663 CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS); | 11663 CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS); |
| 11664 ElementsKind new_elements_kind = elements_kind; | 11664 ElementsKind new_elements_kind = elements_kind; |
| 11665 if (IsHoleyElementsKind(elements_kind)) { | 11665 if (IsHoleyElementsKind(elements_kind)) { |
| 11666 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS; | 11666 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS; |
| 11667 } else { | 11667 } else { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 11683 } | 11683 } |
| 11684 | 11684 |
| 11685 if (object->IsJSArray()) { | 11685 if (object->IsJSArray()) { |
| 11686 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length)); | 11686 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length)); |
| 11687 } | 11687 } |
| 11688 } | 11688 } |
| 11689 | 11689 |
| 11690 | 11690 |
| 11691 // static | 11691 // static |
| 11692 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) { | 11692 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) { |
| 11693 ASSERT(capacity >= 0); | 11693 DCHECK(capacity >= 0); |
| 11694 array->GetIsolate()->factory()->NewJSArrayStorage( | 11694 array->GetIsolate()->factory()->NewJSArrayStorage( |
| 11695 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); | 11695 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); |
| 11696 } | 11696 } |
| 11697 | 11697 |
| 11698 | 11698 |
| 11699 void JSArray::Expand(Handle<JSArray> array, int required_size) { | 11699 void JSArray::Expand(Handle<JSArray> array, int required_size) { |
| 11700 ElementsAccessor* accessor = array->GetElementsAccessor(); | 11700 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 11701 accessor->SetCapacityAndLength(array, required_size, required_size); | 11701 accessor->SetCapacityAndLength(array, required_size, required_size); |
| 11702 } | 11702 } |
| 11703 | 11703 |
| 11704 | 11704 |
| 11705 // Returns false if the passed-in index is marked non-configurable, | 11705 // Returns false if the passed-in index is marked non-configurable, |
| 11706 // which will cause the ES5 truncation operation to halt, and thus | 11706 // which will cause the ES5 truncation operation to halt, and thus |
| 11707 // no further old values need be collected. | 11707 // no further old values need be collected. |
| 11708 static bool GetOldValue(Isolate* isolate, | 11708 static bool GetOldValue(Isolate* isolate, |
| 11709 Handle<JSObject> object, | 11709 Handle<JSObject> object, |
| 11710 uint32_t index, | 11710 uint32_t index, |
| 11711 List<Handle<Object> >* old_values, | 11711 List<Handle<Object> >* old_values, |
| 11712 List<uint32_t>* indices) { | 11712 List<uint32_t>* indices) { |
| 11713 Maybe<PropertyAttributes> maybe = | 11713 Maybe<PropertyAttributes> maybe = |
| 11714 JSReceiver::GetOwnElementAttribute(object, index); | 11714 JSReceiver::GetOwnElementAttribute(object, index); |
| 11715 ASSERT(maybe.has_value); | 11715 DCHECK(maybe.has_value); |
| 11716 ASSERT(maybe.value != ABSENT); | 11716 DCHECK(maybe.value != ABSENT); |
| 11717 if (maybe.value == DONT_DELETE) return false; | 11717 if (maybe.value == DONT_DELETE) return false; |
| 11718 Handle<Object> value; | 11718 Handle<Object> value; |
| 11719 if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) { | 11719 if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) { |
| 11720 value = Handle<Object>::cast(isolate->factory()->the_hole_value()); | 11720 value = Handle<Object>::cast(isolate->factory()->the_hole_value()); |
| 11721 } else { | 11721 } else { |
| 11722 value = Object::GetElement(isolate, object, index).ToHandleChecked(); | 11722 value = Object::GetElement(isolate, object, index).ToHandleChecked(); |
| 11723 } | 11723 } |
| 11724 old_values->Add(value); | 11724 old_values->Add(value); |
| 11725 indices->Add(index); | 11725 indices->Add(index); |
| 11726 return true; | 11726 return true; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11781 // space size, then force it to go dictionary mode. | 11781 // space size, then force it to go dictionary mode. |
| 11782 int max_fast_array_size = static_cast<int>( | 11782 int max_fast_array_size = static_cast<int>( |
| 11783 (array->GetHeap()->MaxOldGenerationSize() / kDoubleSize) / 4); | 11783 (array->GetHeap()->MaxOldGenerationSize() / kDoubleSize) / 4); |
| 11784 if (new_length_handle->IsNumber() && | 11784 if (new_length_handle->IsNumber() && |
| 11785 NumberToInt32(*new_length_handle) >= max_fast_array_size) { | 11785 NumberToInt32(*new_length_handle) >= max_fast_array_size) { |
| 11786 NormalizeElements(array); | 11786 NormalizeElements(array); |
| 11787 } | 11787 } |
| 11788 } | 11788 } |
| 11789 | 11789 |
| 11790 // We should never end in here with a pixel or external array. | 11790 // We should never end in here with a pixel or external array. |
| 11791 ASSERT(array->AllowsSetElementsLength()); | 11791 DCHECK(array->AllowsSetElementsLength()); |
| 11792 if (!array->map()->is_observed()) { | 11792 if (!array->map()->is_observed()) { |
| 11793 return array->GetElementsAccessor()->SetLength(array, new_length_handle); | 11793 return array->GetElementsAccessor()->SetLength(array, new_length_handle); |
| 11794 } | 11794 } |
| 11795 | 11795 |
| 11796 Isolate* isolate = array->GetIsolate(); | 11796 Isolate* isolate = array->GetIsolate(); |
| 11797 List<uint32_t> indices; | 11797 List<uint32_t> indices; |
| 11798 List<Handle<Object> > old_values; | 11798 List<Handle<Object> > old_values; |
| 11799 Handle<Object> old_length_handle(array->length(), isolate); | 11799 Handle<Object> old_length_handle(array->length(), isolate); |
| 11800 uint32_t old_length = 0; | 11800 uint32_t old_length = 0; |
| 11801 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 11801 CHECK(old_length_handle->ToArrayIndex(&old_length)); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11887 return Handle<Map>(Map::cast(result)); | 11887 return Handle<Map>(Map::cast(result)); |
| 11888 } | 11888 } |
| 11889 } | 11889 } |
| 11890 return Handle<Map>(); | 11890 return Handle<Map>(); |
| 11891 } | 11891 } |
| 11892 | 11892 |
| 11893 | 11893 |
| 11894 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, | 11894 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, |
| 11895 Handle<Object> prototype, | 11895 Handle<Object> prototype, |
| 11896 Handle<Map> target_map) { | 11896 Handle<Map> target_map) { |
| 11897 ASSERT(target_map->IsMap()); | 11897 DCHECK(target_map->IsMap()); |
| 11898 ASSERT(HeapObject::cast(*prototype)->map()->IsMap()); | 11898 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); |
| 11899 // Don't cache prototype transition if this map is shared. | 11899 // Don't cache prototype transition if this map is shared. |
| 11900 if (map->is_shared() || !FLAG_cache_prototype_transitions) return map; | 11900 if (map->is_shared() || !FLAG_cache_prototype_transitions) return map; |
| 11901 | 11901 |
| 11902 const int step = kProtoTransitionElementsPerEntry; | 11902 const int step = kProtoTransitionElementsPerEntry; |
| 11903 const int header = kProtoTransitionHeaderSize; | 11903 const int header = kProtoTransitionHeaderSize; |
| 11904 | 11904 |
| 11905 Handle<FixedArray> cache(map->GetPrototypeTransitions()); | 11905 Handle<FixedArray> cache(map->GetPrototypeTransitions()); |
| 11906 int capacity = (cache->length() - header) / step; | 11906 int capacity = (cache->length() - header) / step; |
| 11907 int transitions = map->NumberOfProtoTransitions() + 1; | 11907 int transitions = map->NumberOfProtoTransitions() + 1; |
| 11908 | 11908 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11966 Handle<Code> code) { | 11966 Handle<Code> code) { |
| 11967 Handle<DependentCode> codes = DependentCode::Insert( | 11967 Handle<DependentCode> codes = DependentCode::Insert( |
| 11968 Handle<DependentCode>(map->dependent_code()), group, code); | 11968 Handle<DependentCode>(map->dependent_code()), group, code); |
| 11969 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); | 11969 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); |
| 11970 } | 11970 } |
| 11971 | 11971 |
| 11972 | 11972 |
| 11973 // static | 11973 // static |
| 11974 void Map::AddDependentIC(Handle<Map> map, | 11974 void Map::AddDependentIC(Handle<Map> map, |
| 11975 Handle<Code> stub) { | 11975 Handle<Code> stub) { |
| 11976 ASSERT(stub->next_code_link()->IsUndefined()); | 11976 DCHECK(stub->next_code_link()->IsUndefined()); |
| 11977 int n = map->dependent_code()->number_of_entries(DependentCode::kWeakICGroup); | 11977 int n = map->dependent_code()->number_of_entries(DependentCode::kWeakICGroup); |
| 11978 if (n == 0) { | 11978 if (n == 0) { |
| 11979 // Slow path: insert the head of the list with possible heap allocation. | 11979 // Slow path: insert the head of the list with possible heap allocation. |
| 11980 Map::AddDependentCode(map, DependentCode::kWeakICGroup, stub); | 11980 Map::AddDependentCode(map, DependentCode::kWeakICGroup, stub); |
| 11981 } else { | 11981 } else { |
| 11982 // Fast path: link the stub to the existing head of the list without any | 11982 // Fast path: link the stub to the existing head of the list without any |
| 11983 // heap allocation. | 11983 // heap allocation. |
| 11984 ASSERT(n == 1); | 11984 DCHECK(n == 1); |
| 11985 map->dependent_code()->AddToDependentICList(stub); | 11985 map->dependent_code()->AddToDependentICList(stub); |
| 11986 } | 11986 } |
| 11987 } | 11987 } |
| 11988 | 11988 |
| 11989 | 11989 |
| 11990 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) { | 11990 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) { |
| 11991 Recompute(entries); | 11991 Recompute(entries); |
| 11992 } | 11992 } |
| 11993 | 11993 |
| 11994 | 11994 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12065 int end = starts.at(group + 1); | 12065 int end = starts.at(group + 1); |
| 12066 for (int i = start; i < end; i++) { | 12066 for (int i = start; i < end; i++) { |
| 12067 if (object_at(i) == info_wrapper) { | 12067 if (object_at(i) == info_wrapper) { |
| 12068 set_object_at(i, code); | 12068 set_object_at(i, code); |
| 12069 break; | 12069 break; |
| 12070 } | 12070 } |
| 12071 } | 12071 } |
| 12072 | 12072 |
| 12073 #ifdef DEBUG | 12073 #ifdef DEBUG |
| 12074 for (int i = start; i < end; i++) { | 12074 for (int i = start; i < end; i++) { |
| 12075 ASSERT(is_code_at(i) || compilation_info_at(i) != info); | 12075 DCHECK(is_code_at(i) || compilation_info_at(i) != info); |
| 12076 } | 12076 } |
| 12077 #endif | 12077 #endif |
| 12078 } | 12078 } |
| 12079 | 12079 |
| 12080 | 12080 |
| 12081 void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group, | 12081 void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group, |
| 12082 CompilationInfo* info) { | 12082 CompilationInfo* info) { |
| 12083 DisallowHeapAllocation no_allocation; | 12083 DisallowHeapAllocation no_allocation; |
| 12084 AllowDeferredHandleDereference get_object_wrapper; | 12084 AllowDeferredHandleDereference get_object_wrapper; |
| 12085 Foreign* info_wrapper = *info->object_wrapper(); | 12085 Foreign* info_wrapper = *info->object_wrapper(); |
| 12086 GroupStartIndexes starts(this); | 12086 GroupStartIndexes starts(this); |
| 12087 int start = starts.at(group); | 12087 int start = starts.at(group); |
| 12088 int end = starts.at(group + 1); | 12088 int end = starts.at(group + 1); |
| 12089 // Find compilation info wrapper. | 12089 // Find compilation info wrapper. |
| 12090 int info_pos = -1; | 12090 int info_pos = -1; |
| 12091 for (int i = start; i < end; i++) { | 12091 for (int i = start; i < end; i++) { |
| 12092 if (object_at(i) == info_wrapper) { | 12092 if (object_at(i) == info_wrapper) { |
| 12093 info_pos = i; | 12093 info_pos = i; |
| 12094 break; | 12094 break; |
| 12095 } | 12095 } |
| 12096 } | 12096 } |
| 12097 if (info_pos == -1) return; // Not found. | 12097 if (info_pos == -1) return; // Not found. |
| 12098 int gap = info_pos; | 12098 int gap = info_pos; |
| 12099 // Use the last of each group to fill the gap in the previous group. | 12099 // Use the last of each group to fill the gap in the previous group. |
| 12100 for (int i = group; i < kGroupCount; i++) { | 12100 for (int i = group; i < kGroupCount; i++) { |
| 12101 int last_of_group = starts.at(i + 1) - 1; | 12101 int last_of_group = starts.at(i + 1) - 1; |
| 12102 ASSERT(last_of_group >= gap); | 12102 DCHECK(last_of_group >= gap); |
| 12103 if (last_of_group == gap) continue; | 12103 if (last_of_group == gap) continue; |
| 12104 copy(last_of_group, gap); | 12104 copy(last_of_group, gap); |
| 12105 gap = last_of_group; | 12105 gap = last_of_group; |
| 12106 } | 12106 } |
| 12107 ASSERT(gap == starts.number_of_entries() - 1); | 12107 DCHECK(gap == starts.number_of_entries() - 1); |
| 12108 clear_at(gap); // Clear last gap. | 12108 clear_at(gap); // Clear last gap. |
| 12109 set_number_of_entries(group, end - start - 1); | 12109 set_number_of_entries(group, end - start - 1); |
| 12110 | 12110 |
| 12111 #ifdef DEBUG | 12111 #ifdef DEBUG |
| 12112 for (int i = start; i < end - 1; i++) { | 12112 for (int i = start; i < end - 1; i++) { |
| 12113 ASSERT(is_code_at(i) || compilation_info_at(i) != info); | 12113 DCHECK(is_code_at(i) || compilation_info_at(i) != info); |
| 12114 } | 12114 } |
| 12115 #endif | 12115 #endif |
| 12116 } | 12116 } |
| 12117 | 12117 |
| 12118 | 12118 |
| 12119 static bool CodeListContains(Object* head, Code* code) { | 12119 static bool CodeListContains(Object* head, Code* code) { |
| 12120 while (!head->IsUndefined()) { | 12120 while (!head->IsUndefined()) { |
| 12121 if (head == code) return true; | 12121 if (head == code) return true; |
| 12122 head = Code::cast(head)->next_code_link(); | 12122 head = Code::cast(head)->next_code_link(); |
| 12123 } | 12123 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12173 clear_at(i); | 12173 clear_at(i); |
| 12174 } | 12174 } |
| 12175 set_number_of_entries(group, 0); | 12175 set_number_of_entries(group, 0); |
| 12176 return marked; | 12176 return marked; |
| 12177 } | 12177 } |
| 12178 | 12178 |
| 12179 | 12179 |
| 12180 void DependentCode::DeoptimizeDependentCodeGroup( | 12180 void DependentCode::DeoptimizeDependentCodeGroup( |
| 12181 Isolate* isolate, | 12181 Isolate* isolate, |
| 12182 DependentCode::DependencyGroup group) { | 12182 DependentCode::DependencyGroup group) { |
| 12183 ASSERT(AllowCodeDependencyChange::IsAllowed()); | 12183 DCHECK(AllowCodeDependencyChange::IsAllowed()); |
| 12184 DisallowHeapAllocation no_allocation_scope; | 12184 DisallowHeapAllocation no_allocation_scope; |
| 12185 bool marked = MarkCodeForDeoptimization(isolate, group); | 12185 bool marked = MarkCodeForDeoptimization(isolate, group); |
| 12186 | 12186 |
| 12187 if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate); | 12187 if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate); |
| 12188 } | 12188 } |
| 12189 | 12189 |
| 12190 | 12190 |
| 12191 void DependentCode::AddToDependentICList(Handle<Code> stub) { | 12191 void DependentCode::AddToDependentICList(Handle<Code> stub) { |
| 12192 DisallowHeapAllocation no_heap_allocation; | 12192 DisallowHeapAllocation no_heap_allocation; |
| 12193 GroupStartIndexes starts(this); | 12193 GroupStartIndexes starts(this); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12280 Handle<Map> map(real_receiver->map()); | 12280 Handle<Map> map(real_receiver->map()); |
| 12281 | 12281 |
| 12282 // Nothing to do if prototype is already set. | 12282 // Nothing to do if prototype is already set. |
| 12283 if (map->prototype() == *value) return value; | 12283 if (map->prototype() == *value) return value; |
| 12284 | 12284 |
| 12285 if (value->IsJSObject()) { | 12285 if (value->IsJSObject()) { |
| 12286 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); | 12286 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); |
| 12287 } | 12287 } |
| 12288 | 12288 |
| 12289 Handle<Map> new_map = Map::TransitionToPrototype(map, value); | 12289 Handle<Map> new_map = Map::TransitionToPrototype(map, value); |
| 12290 ASSERT(new_map->prototype() == *value); | 12290 DCHECK(new_map->prototype() == *value); |
| 12291 JSObject::MigrateToMap(real_receiver, new_map); | 12291 JSObject::MigrateToMap(real_receiver, new_map); |
| 12292 | 12292 |
| 12293 if (!dictionary_elements_in_chain && | 12293 if (!dictionary_elements_in_chain && |
| 12294 new_map->DictionaryElementsInPrototypeChainOnly()) { | 12294 new_map->DictionaryElementsInPrototypeChainOnly()) { |
| 12295 // If the prototype chain didn't previously have element callbacks, then | 12295 // If the prototype chain didn't previously have element callbacks, then |
| 12296 // KeyedStoreICs need to be cleared to ensure any that involve this | 12296 // KeyedStoreICs need to be cleared to ensure any that involve this |
| 12297 // map go generic. | 12297 // map go generic. |
| 12298 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); | 12298 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); |
| 12299 } | 12299 } |
| 12300 | 12300 |
| 12301 heap->ClearInstanceofCache(); | 12301 heap->ClearInstanceofCache(); |
| 12302 ASSERT(size == object->Size()); | 12302 DCHECK(size == object->Size()); |
| 12303 return value; | 12303 return value; |
| 12304 } | 12304 } |
| 12305 | 12305 |
| 12306 | 12306 |
| 12307 void JSObject::EnsureCanContainElements(Handle<JSObject> object, | 12307 void JSObject::EnsureCanContainElements(Handle<JSObject> object, |
| 12308 Arguments* args, | 12308 Arguments* args, |
| 12309 uint32_t first_arg, | 12309 uint32_t first_arg, |
| 12310 uint32_t arg_count, | 12310 uint32_t arg_count, |
| 12311 EnsureElementsMode mode) { | 12311 EnsureElementsMode mode) { |
| 12312 // Elements in |Arguments| are ordered backwards (because they're on the | 12312 // Elements in |Arguments| are ordered backwards (because they're on the |
| 12313 // stack), but the method that's called here iterates over them in forward | 12313 // stack), but the method that's called here iterates over them in forward |
| 12314 // direction. | 12314 // direction. |
| 12315 return EnsureCanContainElements( | 12315 return EnsureCanContainElements( |
| 12316 object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode); | 12316 object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode); |
| 12317 } | 12317 } |
| 12318 | 12318 |
| 12319 | 12319 |
| 12320 MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair( | 12320 MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair( |
| 12321 Handle<JSObject> object, | 12321 Handle<JSObject> object, |
| 12322 uint32_t index) { | 12322 uint32_t index) { |
| 12323 if (object->IsJSGlobalProxy()) { | 12323 if (object->IsJSGlobalProxy()) { |
| 12324 PrototypeIterator iter(object->GetIsolate(), object); | 12324 PrototypeIterator iter(object->GetIsolate(), object); |
| 12325 if (iter.IsAtEnd()) return MaybeHandle<AccessorPair>(); | 12325 if (iter.IsAtEnd()) return MaybeHandle<AccessorPair>(); |
| 12326 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 12326 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 12327 return GetOwnElementAccessorPair( | 12327 return GetOwnElementAccessorPair( |
| 12328 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); | 12328 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); |
| 12329 } | 12329 } |
| 12330 | 12330 |
| 12331 // Check for lookup interceptor. | 12331 // Check for lookup interceptor. |
| 12332 if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>(); | 12332 if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>(); |
| 12333 | 12333 |
| 12334 return object->GetElementsAccessor()->GetAccessorPair(object, object, index); | 12334 return object->GetElementsAccessor()->GetAccessorPair(object, object, index); |
| 12335 } | 12335 } |
| 12336 | 12336 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12370 } | 12370 } |
| 12371 | 12371 |
| 12372 | 12372 |
| 12373 MaybeHandle<Object> JSObject::GetElementWithCallback( | 12373 MaybeHandle<Object> JSObject::GetElementWithCallback( |
| 12374 Handle<JSObject> object, | 12374 Handle<JSObject> object, |
| 12375 Handle<Object> receiver, | 12375 Handle<Object> receiver, |
| 12376 Handle<Object> structure, | 12376 Handle<Object> structure, |
| 12377 uint32_t index, | 12377 uint32_t index, |
| 12378 Handle<Object> holder) { | 12378 Handle<Object> holder) { |
| 12379 Isolate* isolate = object->GetIsolate(); | 12379 Isolate* isolate = object->GetIsolate(); |
| 12380 ASSERT(!structure->IsForeign()); | 12380 DCHECK(!structure->IsForeign()); |
| 12381 // api style callbacks. | 12381 // api style callbacks. |
| 12382 if (structure->IsExecutableAccessorInfo()) { | 12382 if (structure->IsExecutableAccessorInfo()) { |
| 12383 Handle<ExecutableAccessorInfo> data = | 12383 Handle<ExecutableAccessorInfo> data = |
| 12384 Handle<ExecutableAccessorInfo>::cast(structure); | 12384 Handle<ExecutableAccessorInfo>::cast(structure); |
| 12385 Object* fun_obj = data->getter(); | 12385 Object* fun_obj = data->getter(); |
| 12386 v8::AccessorGetterCallback call_fun = | 12386 v8::AccessorGetterCallback call_fun = |
| 12387 v8::ToCData<v8::AccessorGetterCallback>(fun_obj); | 12387 v8::ToCData<v8::AccessorGetterCallback>(fun_obj); |
| 12388 if (call_fun == NULL) return isolate->factory()->undefined_value(); | 12388 if (call_fun == NULL) return isolate->factory()->undefined_value(); |
| 12389 Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder); | 12389 Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder); |
| 12390 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12390 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12427 MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, | 12427 MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, |
| 12428 Handle<Object> structure, | 12428 Handle<Object> structure, |
| 12429 uint32_t index, | 12429 uint32_t index, |
| 12430 Handle<Object> value, | 12430 Handle<Object> value, |
| 12431 Handle<JSObject> holder, | 12431 Handle<JSObject> holder, |
| 12432 StrictMode strict_mode) { | 12432 StrictMode strict_mode) { |
| 12433 Isolate* isolate = object->GetIsolate(); | 12433 Isolate* isolate = object->GetIsolate(); |
| 12434 | 12434 |
| 12435 // We should never get here to initialize a const with the hole | 12435 // We should never get here to initialize a const with the hole |
| 12436 // value since a const declaration would conflict with the setter. | 12436 // value since a const declaration would conflict with the setter. |
| 12437 ASSERT(!value->IsTheHole()); | 12437 DCHECK(!value->IsTheHole()); |
| 12438 ASSERT(!structure->IsForeign()); | 12438 DCHECK(!structure->IsForeign()); |
| 12439 if (structure->IsExecutableAccessorInfo()) { | 12439 if (structure->IsExecutableAccessorInfo()) { |
| 12440 // api style callbacks | 12440 // api style callbacks |
| 12441 Handle<ExecutableAccessorInfo> data = | 12441 Handle<ExecutableAccessorInfo> data = |
| 12442 Handle<ExecutableAccessorInfo>::cast(structure); | 12442 Handle<ExecutableAccessorInfo>::cast(structure); |
| 12443 Object* call_obj = data->setter(); | 12443 Object* call_obj = data->setter(); |
| 12444 v8::AccessorSetterCallback call_fun = | 12444 v8::AccessorSetterCallback call_fun = |
| 12445 v8::ToCData<v8::AccessorSetterCallback>(call_obj); | 12445 v8::ToCData<v8::AccessorSetterCallback>(call_obj); |
| 12446 if (call_fun == NULL) return value; | 12446 if (call_fun == NULL) return value; |
| 12447 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12447 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 12448 Handle<String> key(isolate->factory()->NumberToString(number)); | 12448 Handle<String> key(isolate->factory()->NumberToString(number)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12505 | 12505 |
| 12506 | 12506 |
| 12507 // Adding n elements in fast case is O(n*n). | 12507 // Adding n elements in fast case is O(n*n). |
| 12508 // Note: revisit design to have dual undefined values to capture absent | 12508 // Note: revisit design to have dual undefined values to capture absent |
| 12509 // elements. | 12509 // elements. |
| 12510 MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object, | 12510 MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object, |
| 12511 uint32_t index, | 12511 uint32_t index, |
| 12512 Handle<Object> value, | 12512 Handle<Object> value, |
| 12513 StrictMode strict_mode, | 12513 StrictMode strict_mode, |
| 12514 bool check_prototype) { | 12514 bool check_prototype) { |
| 12515 ASSERT(object->HasFastSmiOrObjectElements() || | 12515 DCHECK(object->HasFastSmiOrObjectElements() || |
| 12516 object->HasFastArgumentsElements()); | 12516 object->HasFastArgumentsElements()); |
| 12517 | 12517 |
| 12518 Isolate* isolate = object->GetIsolate(); | 12518 Isolate* isolate = object->GetIsolate(); |
| 12519 | 12519 |
| 12520 // Array optimizations rely on the prototype lookups of Array objects always | 12520 // Array optimizations rely on the prototype lookups of Array objects always |
| 12521 // returning undefined. If there is a store to the initial prototype object, | 12521 // returning undefined. If there is a store to the initial prototype object, |
| 12522 // make sure all of these optimizations are invalidated. | 12522 // make sure all of these optimizations are invalidated. |
| 12523 if (isolate->is_initial_object_prototype(*object) || | 12523 if (isolate->is_initial_object_prototype(*object) || |
| 12524 isolate->is_initial_array_prototype(*object)) { | 12524 isolate->is_initial_array_prototype(*object)) { |
| 12525 object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate, | 12525 object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12568 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); | 12568 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); |
| 12569 TransitionElementsKind(object, transitioned_kind); | 12569 TransitionElementsKind(object, transitioned_kind); |
| 12570 } | 12570 } |
| 12571 | 12571 |
| 12572 // Check if the capacity of the backing store needs to be increased, or if | 12572 // Check if the capacity of the backing store needs to be increased, or if |
| 12573 // a transition to slow elements is necessary. | 12573 // a transition to slow elements is necessary. |
| 12574 if (index >= capacity) { | 12574 if (index >= capacity) { |
| 12575 bool convert_to_slow = true; | 12575 bool convert_to_slow = true; |
| 12576 if ((index - capacity) < kMaxGap) { | 12576 if ((index - capacity) < kMaxGap) { |
| 12577 new_capacity = NewElementsCapacity(index + 1); | 12577 new_capacity = NewElementsCapacity(index + 1); |
| 12578 ASSERT(new_capacity > index); | 12578 DCHECK(new_capacity > index); |
| 12579 if (!object->ShouldConvertToSlowElements(new_capacity)) { | 12579 if (!object->ShouldConvertToSlowElements(new_capacity)) { |
| 12580 convert_to_slow = false; | 12580 convert_to_slow = false; |
| 12581 } | 12581 } |
| 12582 } | 12582 } |
| 12583 if (convert_to_slow) { | 12583 if (convert_to_slow) { |
| 12584 NormalizeElements(object); | 12584 NormalizeElements(object); |
| 12585 return SetDictionaryElement(object, index, value, NONE, strict_mode, | 12585 return SetDictionaryElement(object, index, value, NONE, strict_mode, |
| 12586 check_prototype); | 12586 check_prototype); |
| 12587 } | 12587 } |
| 12588 } | 12588 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 12602 } | 12602 } |
| 12603 // Change elements kind from Smi-only to generic FAST if necessary. | 12603 // Change elements kind from Smi-only to generic FAST if necessary. |
| 12604 if (object->HasFastSmiElements() && !value->IsSmi()) { | 12604 if (object->HasFastSmiElements() && !value->IsSmi()) { |
| 12605 ElementsKind kind = object->HasFastHoleyElements() | 12605 ElementsKind kind = object->HasFastHoleyElements() |
| 12606 ? FAST_HOLEY_ELEMENTS | 12606 ? FAST_HOLEY_ELEMENTS |
| 12607 : FAST_ELEMENTS; | 12607 : FAST_ELEMENTS; |
| 12608 | 12608 |
| 12609 UpdateAllocationSite(object, kind); | 12609 UpdateAllocationSite(object, kind); |
| 12610 Handle<Map> new_map = GetElementsTransitionMap(object, kind); | 12610 Handle<Map> new_map = GetElementsTransitionMap(object, kind); |
| 12611 JSObject::MigrateToMap(object, new_map); | 12611 JSObject::MigrateToMap(object, new_map); |
| 12612 ASSERT(IsFastObjectElementsKind(object->GetElementsKind())); | 12612 DCHECK(IsFastObjectElementsKind(object->GetElementsKind())); |
| 12613 } | 12613 } |
| 12614 // Increase backing store capacity if that's been decided previously. | 12614 // Increase backing store capacity if that's been decided previously. |
| 12615 if (new_capacity != capacity) { | 12615 if (new_capacity != capacity) { |
| 12616 SetFastElementsCapacitySmiMode smi_mode = | 12616 SetFastElementsCapacitySmiMode smi_mode = |
| 12617 value->IsSmi() && object->HasFastSmiElements() | 12617 value->IsSmi() && object->HasFastSmiElements() |
| 12618 ? kAllowSmiElements | 12618 ? kAllowSmiElements |
| 12619 : kDontAllowSmiElements; | 12619 : kDontAllowSmiElements; |
| 12620 Handle<FixedArray> new_elements = | 12620 Handle<FixedArray> new_elements = |
| 12621 SetFastElementsCapacityAndLength(object, new_capacity, array_length, | 12621 SetFastElementsCapacityAndLength(object, new_capacity, array_length, |
| 12622 smi_mode); | 12622 smi_mode); |
| 12623 new_elements->set(index, *value); | 12623 new_elements->set(index, *value); |
| 12624 JSObject::ValidateElements(object); | 12624 JSObject::ValidateElements(object); |
| 12625 return value; | 12625 return value; |
| 12626 } | 12626 } |
| 12627 | 12627 |
| 12628 // Finally, set the new element and length. | 12628 // Finally, set the new element and length. |
| 12629 ASSERT(object->elements()->IsFixedArray()); | 12629 DCHECK(object->elements()->IsFixedArray()); |
| 12630 backing_store->set(index, *value); | 12630 backing_store->set(index, *value); |
| 12631 if (must_update_array_length) { | 12631 if (must_update_array_length) { |
| 12632 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); | 12632 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); |
| 12633 } | 12633 } |
| 12634 return value; | 12634 return value; |
| 12635 } | 12635 } |
| 12636 | 12636 |
| 12637 | 12637 |
| 12638 MaybeHandle<Object> JSObject::SetDictionaryElement( | 12638 MaybeHandle<Object> JSObject::SetDictionaryElement( |
| 12639 Handle<JSObject> object, | 12639 Handle<JSObject> object, |
| 12640 uint32_t index, | 12640 uint32_t index, |
| 12641 Handle<Object> value, | 12641 Handle<Object> value, |
| 12642 PropertyAttributes attributes, | 12642 PropertyAttributes attributes, |
| 12643 StrictMode strict_mode, | 12643 StrictMode strict_mode, |
| 12644 bool check_prototype, | 12644 bool check_prototype, |
| 12645 SetPropertyMode set_mode) { | 12645 SetPropertyMode set_mode) { |
| 12646 ASSERT(object->HasDictionaryElements() || | 12646 DCHECK(object->HasDictionaryElements() || |
| 12647 object->HasDictionaryArgumentsElements()); | 12647 object->HasDictionaryArgumentsElements()); |
| 12648 Isolate* isolate = object->GetIsolate(); | 12648 Isolate* isolate = object->GetIsolate(); |
| 12649 | 12649 |
| 12650 // Insert element in the dictionary. | 12650 // Insert element in the dictionary. |
| 12651 Handle<FixedArray> elements(FixedArray::cast(object->elements())); | 12651 Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
| 12652 bool is_arguments = | 12652 bool is_arguments = |
| 12653 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); | 12653 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); |
| 12654 Handle<SeededNumberDictionary> dictionary(is_arguments | 12654 Handle<SeededNumberDictionary> dictionary(is_arguments |
| 12655 ? SeededNumberDictionary::cast(elements->get(1)) | 12655 ? SeededNumberDictionary::cast(elements->get(1)) |
| 12656 : SeededNumberDictionary::cast(*elements)); | 12656 : SeededNumberDictionary::cast(*elements)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 12682 HandleVector(args, 2)); | 12682 HandleVector(args, 2)); |
| 12683 return isolate->Throw<Object>(error); | 12683 return isolate->Throw<Object>(error); |
| 12684 } | 12684 } |
| 12685 } | 12685 } |
| 12686 // Elements of the arguments object in slow mode might be slow aliases. | 12686 // Elements of the arguments object in slow mode might be slow aliases. |
| 12687 if (is_arguments && element->IsAliasedArgumentsEntry()) { | 12687 if (is_arguments && element->IsAliasedArgumentsEntry()) { |
| 12688 Handle<AliasedArgumentsEntry> entry = | 12688 Handle<AliasedArgumentsEntry> entry = |
| 12689 Handle<AliasedArgumentsEntry>::cast(element); | 12689 Handle<AliasedArgumentsEntry>::cast(element); |
| 12690 Handle<Context> context(Context::cast(elements->get(0))); | 12690 Handle<Context> context(Context::cast(elements->get(0))); |
| 12691 int context_index = entry->aliased_context_slot(); | 12691 int context_index = entry->aliased_context_slot(); |
| 12692 ASSERT(!context->get(context_index)->IsTheHole()); | 12692 DCHECK(!context->get(context_index)->IsTheHole()); |
| 12693 context->set(context_index, *value); | 12693 context->set(context_index, *value); |
| 12694 // For elements that are still writable we keep slow aliasing. | 12694 // For elements that are still writable we keep slow aliasing. |
| 12695 if (!details.IsReadOnly()) value = element; | 12695 if (!details.IsReadOnly()) value = element; |
| 12696 } | 12696 } |
| 12697 dictionary->ValueAtPut(entry, *value); | 12697 dictionary->ValueAtPut(entry, *value); |
| 12698 } | 12698 } |
| 12699 } else { | 12699 } else { |
| 12700 // Index not already used. Look for an accessor in the prototype chain. | 12700 // Index not already used. Look for an accessor in the prototype chain. |
| 12701 // Can cause GC! | 12701 // Can cause GC! |
| 12702 if (check_prototype) { | 12702 if (check_prototype) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12773 } | 12773 } |
| 12774 return value; | 12774 return value; |
| 12775 } | 12775 } |
| 12776 | 12776 |
| 12777 MaybeHandle<Object> JSObject::SetFastDoubleElement( | 12777 MaybeHandle<Object> JSObject::SetFastDoubleElement( |
| 12778 Handle<JSObject> object, | 12778 Handle<JSObject> object, |
| 12779 uint32_t index, | 12779 uint32_t index, |
| 12780 Handle<Object> value, | 12780 Handle<Object> value, |
| 12781 StrictMode strict_mode, | 12781 StrictMode strict_mode, |
| 12782 bool check_prototype) { | 12782 bool check_prototype) { |
| 12783 ASSERT(object->HasFastDoubleElements()); | 12783 DCHECK(object->HasFastDoubleElements()); |
| 12784 | 12784 |
| 12785 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); | 12785 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); |
| 12786 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); | 12786 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); |
| 12787 | 12787 |
| 12788 // If storing to an element that isn't in the array, pass the store request | 12788 // If storing to an element that isn't in the array, pass the store request |
| 12789 // up the prototype chain before storing in the receiver's elements. | 12789 // up the prototype chain before storing in the receiver's elements. |
| 12790 if (check_prototype && | 12790 if (check_prototype && |
| 12791 (index >= elms_length || | 12791 (index >= elms_length || |
| 12792 Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) { | 12792 Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) { |
| 12793 bool found; | 12793 bool found; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12846 } | 12846 } |
| 12847 } | 12847 } |
| 12848 return value; | 12848 return value; |
| 12849 } | 12849 } |
| 12850 | 12850 |
| 12851 // Allow gap in fast case. | 12851 // Allow gap in fast case. |
| 12852 if ((index - elms_length) < kMaxGap) { | 12852 if ((index - elms_length) < kMaxGap) { |
| 12853 // Try allocating extra space. | 12853 // Try allocating extra space. |
| 12854 int new_capacity = NewElementsCapacity(index+1); | 12854 int new_capacity = NewElementsCapacity(index+1); |
| 12855 if (!object->ShouldConvertToSlowElements(new_capacity)) { | 12855 if (!object->ShouldConvertToSlowElements(new_capacity)) { |
| 12856 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 12856 DCHECK(static_cast<uint32_t>(new_capacity) > index); |
| 12857 SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1); | 12857 SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1); |
| 12858 FixedDoubleArray::cast(object->elements())->set(index, double_value); | 12858 FixedDoubleArray::cast(object->elements())->set(index, double_value); |
| 12859 JSObject::ValidateElements(object); | 12859 JSObject::ValidateElements(object); |
| 12860 return value; | 12860 return value; |
| 12861 } | 12861 } |
| 12862 } | 12862 } |
| 12863 | 12863 |
| 12864 // Otherwise default to slow case. | 12864 // Otherwise default to slow case. |
| 12865 ASSERT(object->HasFastDoubleElements()); | 12865 DCHECK(object->HasFastDoubleElements()); |
| 12866 ASSERT(object->map()->has_fast_double_elements()); | 12866 DCHECK(object->map()->has_fast_double_elements()); |
| 12867 ASSERT(object->elements()->IsFixedDoubleArray() || | 12867 DCHECK(object->elements()->IsFixedDoubleArray() || |
| 12868 object->elements()->length() == 0); | 12868 object->elements()->length() == 0); |
| 12869 | 12869 |
| 12870 NormalizeElements(object); | 12870 NormalizeElements(object); |
| 12871 ASSERT(object->HasDictionaryElements()); | 12871 DCHECK(object->HasDictionaryElements()); |
| 12872 return SetElement(object, index, value, NONE, strict_mode, check_prototype); | 12872 return SetElement(object, index, value, NONE, strict_mode, check_prototype); |
| 12873 } | 12873 } |
| 12874 | 12874 |
| 12875 | 12875 |
| 12876 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, | 12876 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, |
| 12877 uint32_t index, | 12877 uint32_t index, |
| 12878 Handle<Object> value, | 12878 Handle<Object> value, |
| 12879 PropertyAttributes attributes, | 12879 PropertyAttributes attributes, |
| 12880 StrictMode strict_mode) { | 12880 StrictMode strict_mode) { |
| 12881 if (object->IsJSProxy()) { | 12881 if (object->IsJSProxy()) { |
| 12882 return JSProxy::SetElementWithHandler( | 12882 return JSProxy::SetElementWithHandler( |
| 12883 Handle<JSProxy>::cast(object), object, index, value, strict_mode); | 12883 Handle<JSProxy>::cast(object), object, index, value, strict_mode); |
| 12884 } | 12884 } |
| 12885 return JSObject::SetElement( | 12885 return JSObject::SetElement( |
| 12886 Handle<JSObject>::cast(object), index, value, attributes, strict_mode); | 12886 Handle<JSObject>::cast(object), index, value, attributes, strict_mode); |
| 12887 } | 12887 } |
| 12888 | 12888 |
| 12889 | 12889 |
| 12890 MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object, | 12890 MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object, |
| 12891 uint32_t index, | 12891 uint32_t index, |
| 12892 Handle<Object> value, | 12892 Handle<Object> value, |
| 12893 StrictMode strict_mode) { | 12893 StrictMode strict_mode) { |
| 12894 ASSERT(!object->HasExternalArrayElements()); | 12894 DCHECK(!object->HasExternalArrayElements()); |
| 12895 return JSObject::SetElement(object, index, value, NONE, strict_mode, false); | 12895 return JSObject::SetElement(object, index, value, NONE, strict_mode, false); |
| 12896 } | 12896 } |
| 12897 | 12897 |
| 12898 | 12898 |
| 12899 MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object, | 12899 MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object, |
| 12900 uint32_t index, | 12900 uint32_t index, |
| 12901 Handle<Object> value, | 12901 Handle<Object> value, |
| 12902 PropertyAttributes attributes, | 12902 PropertyAttributes attributes, |
| 12903 StrictMode strict_mode, | 12903 StrictMode strict_mode, |
| 12904 bool check_prototype, | 12904 bool check_prototype, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 12919 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_SET)) { | 12919 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_SET)) { |
| 12920 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); | 12920 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); |
| 12921 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 12921 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 12922 return value; | 12922 return value; |
| 12923 } | 12923 } |
| 12924 } | 12924 } |
| 12925 | 12925 |
| 12926 if (object->IsJSGlobalProxy()) { | 12926 if (object->IsJSGlobalProxy()) { |
| 12927 PrototypeIterator iter(isolate, object); | 12927 PrototypeIterator iter(isolate, object); |
| 12928 if (iter.IsAtEnd()) return value; | 12928 if (iter.IsAtEnd()) return value; |
| 12929 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 12929 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 12930 return SetElement( | 12930 return SetElement( |
| 12931 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, | 12931 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, |
| 12932 value, attributes, strict_mode, check_prototype, set_mode); | 12932 value, attributes, strict_mode, check_prototype, set_mode); |
| 12933 } | 12933 } |
| 12934 | 12934 |
| 12935 // Don't allow element properties to be redefined for external arrays. | 12935 // Don't allow element properties to be redefined for external arrays. |
| 12936 if ((object->HasExternalArrayElements() || | 12936 if ((object->HasExternalArrayElements() || |
| 12937 object->HasFixedTypedArrayElements()) && | 12937 object->HasFixedTypedArrayElements()) && |
| 12938 set_mode == DEFINE_PROPERTY) { | 12938 set_mode == DEFINE_PROPERTY) { |
| 12939 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12939 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13036 | 13036 |
| 13037 | 13037 |
| 13038 MaybeHandle<Object> JSObject::SetElementWithoutInterceptor( | 13038 MaybeHandle<Object> JSObject::SetElementWithoutInterceptor( |
| 13039 Handle<JSObject> object, | 13039 Handle<JSObject> object, |
| 13040 uint32_t index, | 13040 uint32_t index, |
| 13041 Handle<Object> value, | 13041 Handle<Object> value, |
| 13042 PropertyAttributes attributes, | 13042 PropertyAttributes attributes, |
| 13043 StrictMode strict_mode, | 13043 StrictMode strict_mode, |
| 13044 bool check_prototype, | 13044 bool check_prototype, |
| 13045 SetPropertyMode set_mode) { | 13045 SetPropertyMode set_mode) { |
| 13046 ASSERT(object->HasDictionaryElements() || | 13046 DCHECK(object->HasDictionaryElements() || |
| 13047 object->HasDictionaryArgumentsElements() || | 13047 object->HasDictionaryArgumentsElements() || |
| 13048 (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); | 13048 (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); |
| 13049 Isolate* isolate = object->GetIsolate(); | 13049 Isolate* isolate = object->GetIsolate(); |
| 13050 if (FLAG_trace_external_array_abuse && | 13050 if (FLAG_trace_external_array_abuse && |
| 13051 IsExternalArrayElementsKind(object->GetElementsKind())) { | 13051 IsExternalArrayElementsKind(object->GetElementsKind())) { |
| 13052 CheckArrayAbuse(object, "external elements write", index); | 13052 CheckArrayAbuse(object, "external elements write", index); |
| 13053 } | 13053 } |
| 13054 if (FLAG_trace_js_array_abuse && | 13054 if (FLAG_trace_js_array_abuse && |
| 13055 !IsExternalArrayElementsKind(object->GetElementsKind())) { | 13055 !IsExternalArrayElementsKind(object->GetElementsKind())) { |
| 13056 if (object->IsJSArray()) { | 13056 if (object->IsJSArray()) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13098 set_mode); | 13098 set_mode); |
| 13099 case SLOPPY_ARGUMENTS_ELEMENTS: { | 13099 case SLOPPY_ARGUMENTS_ELEMENTS: { |
| 13100 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | 13100 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 13101 uint32_t length = parameter_map->length(); | 13101 uint32_t length = parameter_map->length(); |
| 13102 Handle<Object> probe = index < length - 2 ? | 13102 Handle<Object> probe = index < length - 2 ? |
| 13103 Handle<Object>(parameter_map->get(index + 2), isolate) : | 13103 Handle<Object>(parameter_map->get(index + 2), isolate) : |
| 13104 Handle<Object>(); | 13104 Handle<Object>(); |
| 13105 if (!probe.is_null() && !probe->IsTheHole()) { | 13105 if (!probe.is_null() && !probe->IsTheHole()) { |
| 13106 Handle<Context> context(Context::cast(parameter_map->get(0))); | 13106 Handle<Context> context(Context::cast(parameter_map->get(0))); |
| 13107 int context_index = Handle<Smi>::cast(probe)->value(); | 13107 int context_index = Handle<Smi>::cast(probe)->value(); |
| 13108 ASSERT(!context->get(context_index)->IsTheHole()); | 13108 DCHECK(!context->get(context_index)->IsTheHole()); |
| 13109 context->set(context_index, *value); | 13109 context->set(context_index, *value); |
| 13110 // Redefining attributes of an aliased element destroys fast aliasing. | 13110 // Redefining attributes of an aliased element destroys fast aliasing. |
| 13111 if (set_mode == SET_PROPERTY || attributes == NONE) return value; | 13111 if (set_mode == SET_PROPERTY || attributes == NONE) return value; |
| 13112 parameter_map->set_the_hole(index + 2); | 13112 parameter_map->set_the_hole(index + 2); |
| 13113 // For elements that are still writable we re-establish slow aliasing. | 13113 // For elements that are still writable we re-establish slow aliasing. |
| 13114 if ((attributes & READ_ONLY) == 0) { | 13114 if ((attributes & READ_ONLY) == 0) { |
| 13115 value = Handle<Object>::cast( | 13115 value = Handle<Object>::cast( |
| 13116 isolate->factory()->NewAliasedArgumentsEntry(context_index)); | 13116 isolate->factory()->NewAliasedArgumentsEntry(context_index)); |
| 13117 } | 13117 } |
| 13118 } | 13118 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 13146 | 13146 |
| 13147 | 13147 |
| 13148 PretenureFlag AllocationSite::GetPretenureMode() { | 13148 PretenureFlag AllocationSite::GetPretenureMode() { |
| 13149 PretenureDecision mode = pretenure_decision(); | 13149 PretenureDecision mode = pretenure_decision(); |
| 13150 // Zombie objects "decide" to be untenured. | 13150 // Zombie objects "decide" to be untenured. |
| 13151 return mode == kTenure ? TENURED : NOT_TENURED; | 13151 return mode == kTenure ? TENURED : NOT_TENURED; |
| 13152 } | 13152 } |
| 13153 | 13153 |
| 13154 | 13154 |
| 13155 bool AllocationSite::IsNestedSite() { | 13155 bool AllocationSite::IsNestedSite() { |
| 13156 ASSERT(FLAG_trace_track_allocation_sites); | 13156 DCHECK(FLAG_trace_track_allocation_sites); |
| 13157 Object* current = GetHeap()->allocation_sites_list(); | 13157 Object* current = GetHeap()->allocation_sites_list(); |
| 13158 while (current->IsAllocationSite()) { | 13158 while (current->IsAllocationSite()) { |
| 13159 AllocationSite* current_site = AllocationSite::cast(current); | 13159 AllocationSite* current_site = AllocationSite::cast(current); |
| 13160 if (current_site->nested_site() == this) { | 13160 if (current_site->nested_site() == this) { |
| 13161 return true; | 13161 return true; |
| 13162 } | 13162 } |
| 13163 current = current_site->weak_next(); | 13163 current = current_site->weak_next(); |
| 13164 } | 13164 } |
| 13165 return false; | 13165 return false; |
| 13166 } | 13166 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13279 if (IsFastElementsKind(to_kind)) { | 13279 if (IsFastElementsKind(to_kind)) { |
| 13280 UpdateAllocationSite(object, to_kind); | 13280 UpdateAllocationSite(object, to_kind); |
| 13281 } | 13281 } |
| 13282 | 13282 |
| 13283 Isolate* isolate = object->GetIsolate(); | 13283 Isolate* isolate = object->GetIsolate(); |
| 13284 if (object->elements() == isolate->heap()->empty_fixed_array() || | 13284 if (object->elements() == isolate->heap()->empty_fixed_array() || |
| 13285 (IsFastSmiOrObjectElementsKind(from_kind) && | 13285 (IsFastSmiOrObjectElementsKind(from_kind) && |
| 13286 IsFastSmiOrObjectElementsKind(to_kind)) || | 13286 IsFastSmiOrObjectElementsKind(to_kind)) || |
| 13287 (from_kind == FAST_DOUBLE_ELEMENTS && | 13287 (from_kind == FAST_DOUBLE_ELEMENTS && |
| 13288 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { | 13288 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { |
| 13289 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); | 13289 DCHECK(from_kind != TERMINAL_FAST_ELEMENTS_KIND); |
| 13290 // No change is needed to the elements() buffer, the transition | 13290 // No change is needed to the elements() buffer, the transition |
| 13291 // only requires a map change. | 13291 // only requires a map change. |
| 13292 Handle<Map> new_map = GetElementsTransitionMap(object, to_kind); | 13292 Handle<Map> new_map = GetElementsTransitionMap(object, to_kind); |
| 13293 MigrateToMap(object, new_map); | 13293 MigrateToMap(object, new_map); |
| 13294 if (FLAG_trace_elements_transitions) { | 13294 if (FLAG_trace_elements_transitions) { |
| 13295 Handle<FixedArrayBase> elms(object->elements()); | 13295 Handle<FixedArrayBase> elms(object->elements()); |
| 13296 PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms); | 13296 PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms); |
| 13297 } | 13297 } |
| 13298 return; | 13298 return; |
| 13299 } | 13299 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13358 if (index >= old_len && index != 0xffffffff) { | 13358 if (index >= old_len && index != 0xffffffff) { |
| 13359 Handle<Object> len = array->GetIsolate()->factory()->NewNumber( | 13359 Handle<Object> len = array->GetIsolate()->factory()->NewNumber( |
| 13360 static_cast<double>(index) + 1); | 13360 static_cast<double>(index) + 1); |
| 13361 array->set_length(*len); | 13361 array->set_length(*len); |
| 13362 } | 13362 } |
| 13363 } | 13363 } |
| 13364 | 13364 |
| 13365 | 13365 |
| 13366 bool JSArray::IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map) { | 13366 bool JSArray::IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map) { |
| 13367 Isolate* isolate = jsarray_map->GetIsolate(); | 13367 Isolate* isolate = jsarray_map->GetIsolate(); |
| 13368 ASSERT(!jsarray_map->is_dictionary_map()); | 13368 DCHECK(!jsarray_map->is_dictionary_map()); |
| 13369 LookupResult lookup(isolate); | 13369 LookupResult lookup(isolate); |
| 13370 Handle<Name> length_string = isolate->factory()->length_string(); | 13370 Handle<Name> length_string = isolate->factory()->length_string(); |
| 13371 jsarray_map->LookupDescriptor(NULL, *length_string, &lookup); | 13371 jsarray_map->LookupDescriptor(NULL, *length_string, &lookup); |
| 13372 return lookup.IsReadOnly(); | 13372 return lookup.IsReadOnly(); |
| 13373 } | 13373 } |
| 13374 | 13374 |
| 13375 | 13375 |
| 13376 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, | 13376 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, |
| 13377 uint32_t index) { | 13377 uint32_t index) { |
| 13378 uint32_t length = 0; | 13378 uint32_t length = 0; |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13552 int old_capacity = 0; | 13552 int old_capacity = 0; |
| 13553 int used_elements = 0; | 13553 int used_elements = 0; |
| 13554 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 13554 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 13555 int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) * | 13555 int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) * |
| 13556 SeededNumberDictionary::kEntrySize; | 13556 SeededNumberDictionary::kEntrySize; |
| 13557 return 3 * dictionary_size <= new_capacity; | 13557 return 3 * dictionary_size <= new_capacity; |
| 13558 } | 13558 } |
| 13559 | 13559 |
| 13560 | 13560 |
| 13561 bool JSObject::ShouldConvertToFastElements() { | 13561 bool JSObject::ShouldConvertToFastElements() { |
| 13562 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 13562 DCHECK(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
| 13563 // If the elements are sparse, we should not go back to fast case. | 13563 // If the elements are sparse, we should not go back to fast case. |
| 13564 if (!HasDenseElements()) return false; | 13564 if (!HasDenseElements()) return false; |
| 13565 // An object requiring access checks is never allowed to have fast | 13565 // An object requiring access checks is never allowed to have fast |
| 13566 // elements. If it had fast elements we would skip security checks. | 13566 // elements. If it had fast elements we would skip security checks. |
| 13567 if (IsAccessCheckNeeded()) return false; | 13567 if (IsAccessCheckNeeded()) return false; |
| 13568 // Observed objects may not go to fast mode because they rely on map checks, | 13568 // Observed objects may not go to fast mode because they rely on map checks, |
| 13569 // and for fast element accesses we sometimes check element kinds only. | 13569 // and for fast element accesses we sometimes check element kinds only. |
| 13570 if (map()->is_observed()) return false; | 13570 if (map()->is_observed()) return false; |
| 13571 | 13571 |
| 13572 FixedArray* elements = FixedArray::cast(this->elements()); | 13572 FixedArray* elements = FixedArray::cast(this->elements()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 13592 SeededNumberDictionary::kEntrySize; | 13592 SeededNumberDictionary::kEntrySize; |
| 13593 return 2 * dictionary_size >= array_size; | 13593 return 2 * dictionary_size >= array_size; |
| 13594 } | 13594 } |
| 13595 | 13595 |
| 13596 | 13596 |
| 13597 bool JSObject::ShouldConvertToFastDoubleElements( | 13597 bool JSObject::ShouldConvertToFastDoubleElements( |
| 13598 bool* has_smi_only_elements) { | 13598 bool* has_smi_only_elements) { |
| 13599 *has_smi_only_elements = false; | 13599 *has_smi_only_elements = false; |
| 13600 if (HasSloppyArgumentsElements()) return false; | 13600 if (HasSloppyArgumentsElements()) return false; |
| 13601 if (FLAG_unbox_double_arrays) { | 13601 if (FLAG_unbox_double_arrays) { |
| 13602 ASSERT(HasDictionaryElements()); | 13602 DCHECK(HasDictionaryElements()); |
| 13603 SeededNumberDictionary* dictionary = element_dictionary(); | 13603 SeededNumberDictionary* dictionary = element_dictionary(); |
| 13604 bool found_double = false; | 13604 bool found_double = false; |
| 13605 for (int i = 0; i < dictionary->Capacity(); i++) { | 13605 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 13606 Object* key = dictionary->KeyAt(i); | 13606 Object* key = dictionary->KeyAt(i); |
| 13607 if (key->IsNumber()) { | 13607 if (key->IsNumber()) { |
| 13608 Object* value = dictionary->ValueAt(i); | 13608 Object* value = dictionary->ValueAt(i); |
| 13609 if (!value->IsNumber()) return false; | 13609 if (!value->IsNumber()) return false; |
| 13610 if (!value->IsSmi()) { | 13610 if (!value->IsSmi()) { |
| 13611 found_double = true; | 13611 found_double = true; |
| 13612 } | 13612 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13650 int pos = 0; | 13650 int pos = 0; |
| 13651 int capacity = DerivedHashTable::Capacity(); | 13651 int capacity = DerivedHashTable::Capacity(); |
| 13652 DisallowHeapAllocation no_gc; | 13652 DisallowHeapAllocation no_gc; |
| 13653 WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc); | 13653 WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc); |
| 13654 for (int i = 0; i < capacity; i++) { | 13654 for (int i = 0; i < capacity; i++) { |
| 13655 Object* k = Dictionary::KeyAt(i); | 13655 Object* k = Dictionary::KeyAt(i); |
| 13656 if (Dictionary::IsKey(k)) { | 13656 if (Dictionary::IsKey(k)) { |
| 13657 elements->set(pos++, ValueAt(i), mode); | 13657 elements->set(pos++, ValueAt(i), mode); |
| 13658 } | 13658 } |
| 13659 } | 13659 } |
| 13660 ASSERT(pos == elements->length()); | 13660 DCHECK(pos == elements->length()); |
| 13661 } | 13661 } |
| 13662 | 13662 |
| 13663 | 13663 |
| 13664 InterceptorInfo* JSObject::GetNamedInterceptor() { | 13664 InterceptorInfo* JSObject::GetNamedInterceptor() { |
| 13665 ASSERT(map()->has_named_interceptor()); | 13665 DCHECK(map()->has_named_interceptor()); |
| 13666 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 13666 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 13667 ASSERT(constructor->shared()->IsApiFunction()); | 13667 DCHECK(constructor->shared()->IsApiFunction()); |
| 13668 Object* result = | 13668 Object* result = |
| 13669 constructor->shared()->get_api_func_data()->named_property_handler(); | 13669 constructor->shared()->get_api_func_data()->named_property_handler(); |
| 13670 return InterceptorInfo::cast(result); | 13670 return InterceptorInfo::cast(result); |
| 13671 } | 13671 } |
| 13672 | 13672 |
| 13673 | 13673 |
| 13674 InterceptorInfo* JSObject::GetIndexedInterceptor() { | 13674 InterceptorInfo* JSObject::GetIndexedInterceptor() { |
| 13675 ASSERT(map()->has_indexed_interceptor()); | 13675 DCHECK(map()->has_indexed_interceptor()); |
| 13676 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 13676 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 13677 ASSERT(constructor->shared()->IsApiFunction()); | 13677 DCHECK(constructor->shared()->IsApiFunction()); |
| 13678 Object* result = | 13678 Object* result = |
| 13679 constructor->shared()->get_api_func_data()->indexed_property_handler(); | 13679 constructor->shared()->get_api_func_data()->indexed_property_handler(); |
| 13680 return InterceptorInfo::cast(result); | 13680 return InterceptorInfo::cast(result); |
| 13681 } | 13681 } |
| 13682 | 13682 |
| 13683 | 13683 |
| 13684 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor( | 13684 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor( |
| 13685 Handle<JSObject> holder, | 13685 Handle<JSObject> holder, |
| 13686 Handle<Object> receiver, | 13686 Handle<Object> receiver, |
| 13687 Handle<Name> name) { | 13687 Handle<Name> name) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13793 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); | 13793 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); |
| 13794 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>()); | 13794 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>()); |
| 13795 return maybe(false); | 13795 return maybe(false); |
| 13796 } | 13796 } |
| 13797 } | 13797 } |
| 13798 | 13798 |
| 13799 if (object->IsJSGlobalProxy()) { | 13799 if (object->IsJSGlobalProxy()) { |
| 13800 HandleScope scope(isolate); | 13800 HandleScope scope(isolate); |
| 13801 PrototypeIterator iter(isolate, object); | 13801 PrototypeIterator iter(isolate, object); |
| 13802 if (iter.IsAtEnd()) return maybe(false); | 13802 if (iter.IsAtEnd()) return maybe(false); |
| 13803 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 13803 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 13804 return HasRealElementProperty( | 13804 return HasRealElementProperty( |
| 13805 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); | 13805 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); |
| 13806 } | 13806 } |
| 13807 | 13807 |
| 13808 Maybe<PropertyAttributes> result = | 13808 Maybe<PropertyAttributes> result = |
| 13809 GetElementAttributeWithoutInterceptor(object, object, index, false); | 13809 GetElementAttributeWithoutInterceptor(object, object, index, false); |
| 13810 if (!result.has_value) return Maybe<bool>(); | 13810 if (!result.has_value) return Maybe<bool>(); |
| 13811 return maybe(result.value != ABSENT); | 13811 return maybe(result.value != ABSENT); |
| 13812 } | 13812 } |
| 13813 | 13813 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13867 NumberToUint32(numbers->get(j)))) { | 13867 NumberToUint32(numbers->get(j)))) { |
| 13868 content->SwapPairs(numbers, j - 1, j); | 13868 content->SwapPairs(numbers, j - 1, j); |
| 13869 j--; | 13869 j--; |
| 13870 } | 13870 } |
| 13871 } | 13871 } |
| 13872 } | 13872 } |
| 13873 | 13873 |
| 13874 | 13874 |
| 13875 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) { | 13875 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) { |
| 13876 // In-place heap sort. | 13876 // In-place heap sort. |
| 13877 ASSERT(content->length() == numbers->length()); | 13877 DCHECK(content->length() == numbers->length()); |
| 13878 | 13878 |
| 13879 // Bottom-up max-heap construction. | 13879 // Bottom-up max-heap construction. |
| 13880 for (int i = 1; i < len; ++i) { | 13880 for (int i = 1; i < len; ++i) { |
| 13881 int child_index = i; | 13881 int child_index = i; |
| 13882 while (child_index > 0) { | 13882 while (child_index > 0) { |
| 13883 int parent_index = ((child_index + 1) >> 1) - 1; | 13883 int parent_index = ((child_index + 1) >> 1) - 1; |
| 13884 uint32_t parent_value = NumberToUint32(numbers->get(parent_index)); | 13884 uint32_t parent_value = NumberToUint32(numbers->get(parent_index)); |
| 13885 uint32_t child_value = NumberToUint32(numbers->get(child_index)); | 13885 uint32_t child_value = NumberToUint32(numbers->get(child_index)); |
| 13886 if (parent_value < child_value) { | 13886 if (parent_value < child_value) { |
| 13887 content->SwapPairs(numbers, parent_index, child_index); | 13887 content->SwapPairs(numbers, parent_index, child_index); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 13913 content->SwapPairs(numbers, parent_index, child_index + 1); | 13913 content->SwapPairs(numbers, parent_index, child_index + 1); |
| 13914 parent_index = child_index + 1; | 13914 parent_index = child_index + 1; |
| 13915 } | 13915 } |
| 13916 } | 13916 } |
| 13917 } | 13917 } |
| 13918 } | 13918 } |
| 13919 | 13919 |
| 13920 | 13920 |
| 13921 // Sort this array and the numbers as pairs wrt. the (distinct) numbers. | 13921 // Sort this array and the numbers as pairs wrt. the (distinct) numbers. |
| 13922 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) { | 13922 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) { |
| 13923 ASSERT(this->length() == numbers->length()); | 13923 DCHECK(this->length() == numbers->length()); |
| 13924 // For small arrays, simply use insertion sort. | 13924 // For small arrays, simply use insertion sort. |
| 13925 if (len <= 10) { | 13925 if (len <= 10) { |
| 13926 InsertionSortPairs(this, numbers, len); | 13926 InsertionSortPairs(this, numbers, len); |
| 13927 return; | 13927 return; |
| 13928 } | 13928 } |
| 13929 // Check the range of indices. | 13929 // Check the range of indices. |
| 13930 uint32_t min_index = NumberToUint32(numbers->get(0)); | 13930 uint32_t min_index = NumberToUint32(numbers->get(0)); |
| 13931 uint32_t max_index = min_index; | 13931 uint32_t max_index = min_index; |
| 13932 uint32_t i; | 13932 uint32_t i; |
| 13933 for (i = 1; i < len; i++) { | 13933 for (i = 1; i < len; i++) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 13956 return; | 13956 return; |
| 13957 } | 13957 } |
| 13958 } | 13958 } |
| 13959 | 13959 |
| 13960 | 13960 |
| 13961 // Fill in the names of own properties into the supplied storage. The main | 13961 // Fill in the names of own properties into the supplied storage. The main |
| 13962 // purpose of this function is to provide reflection information for the object | 13962 // purpose of this function is to provide reflection information for the object |
| 13963 // mirrors. | 13963 // mirrors. |
| 13964 void JSObject::GetOwnPropertyNames( | 13964 void JSObject::GetOwnPropertyNames( |
| 13965 FixedArray* storage, int index, PropertyAttributes filter) { | 13965 FixedArray* storage, int index, PropertyAttributes filter) { |
| 13966 ASSERT(storage->length() >= (NumberOfOwnProperties(filter) - index)); | 13966 DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index)); |
| 13967 if (HasFastProperties()) { | 13967 if (HasFastProperties()) { |
| 13968 int real_size = map()->NumberOfOwnDescriptors(); | 13968 int real_size = map()->NumberOfOwnDescriptors(); |
| 13969 DescriptorArray* descs = map()->instance_descriptors(); | 13969 DescriptorArray* descs = map()->instance_descriptors(); |
| 13970 for (int i = 0; i < real_size; i++) { | 13970 for (int i = 0; i < real_size; i++) { |
| 13971 if ((descs->GetDetails(i).attributes() & filter) == 0 && | 13971 if ((descs->GetDetails(i).attributes() & filter) == 0 && |
| 13972 !FilterKey(descs->GetKey(i), filter)) { | 13972 !FilterKey(descs->GetKey(i), filter)) { |
| 13973 storage->set(index++, descs->GetKey(i)); | 13973 storage->set(index++, descs->GetKey(i)); |
| 13974 } | 13974 } |
| 13975 } | 13975 } |
| 13976 } else { | 13976 } else { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14013 Smi::cast(JSArray::cast(this)->length())->value() : | 14013 Smi::cast(JSArray::cast(this)->length())->value() : |
| 14014 FixedArray::cast(elements())->length(); | 14014 FixedArray::cast(elements())->length(); |
| 14015 for (int i = 0; i < length; i++) { | 14015 for (int i = 0; i < length; i++) { |
| 14016 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 14016 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 14017 if (storage != NULL) { | 14017 if (storage != NULL) { |
| 14018 storage->set(counter, Smi::FromInt(i)); | 14018 storage->set(counter, Smi::FromInt(i)); |
| 14019 } | 14019 } |
| 14020 counter++; | 14020 counter++; |
| 14021 } | 14021 } |
| 14022 } | 14022 } |
| 14023 ASSERT(!storage || storage->length() >= counter); | 14023 DCHECK(!storage || storage->length() >= counter); |
| 14024 break; | 14024 break; |
| 14025 } | 14025 } |
| 14026 case FAST_DOUBLE_ELEMENTS: | 14026 case FAST_DOUBLE_ELEMENTS: |
| 14027 case FAST_HOLEY_DOUBLE_ELEMENTS: { | 14027 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
| 14028 int length = IsJSArray() ? | 14028 int length = IsJSArray() ? |
| 14029 Smi::cast(JSArray::cast(this)->length())->value() : | 14029 Smi::cast(JSArray::cast(this)->length())->value() : |
| 14030 FixedArrayBase::cast(elements())->length(); | 14030 FixedArrayBase::cast(elements())->length(); |
| 14031 for (int i = 0; i < length; i++) { | 14031 for (int i = 0; i < length; i++) { |
| 14032 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { | 14032 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { |
| 14033 if (storage != NULL) { | 14033 if (storage != NULL) { |
| 14034 storage->set(counter, Smi::FromInt(i)); | 14034 storage->set(counter, Smi::FromInt(i)); |
| 14035 } | 14035 } |
| 14036 counter++; | 14036 counter++; |
| 14037 } | 14037 } |
| 14038 } | 14038 } |
| 14039 ASSERT(!storage || storage->length() >= counter); | 14039 DCHECK(!storage || storage->length() >= counter); |
| 14040 break; | 14040 break; |
| 14041 } | 14041 } |
| 14042 | 14042 |
| 14043 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 14043 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 14044 case EXTERNAL_##TYPE##_ELEMENTS: \ | 14044 case EXTERNAL_##TYPE##_ELEMENTS: \ |
| 14045 case TYPE##_ELEMENTS: \ | 14045 case TYPE##_ELEMENTS: \ |
| 14046 | 14046 |
| 14047 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 14047 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 14048 #undef TYPED_ARRAY_CASE | 14048 #undef TYPED_ARRAY_CASE |
| 14049 { | 14049 { |
| 14050 int length = FixedArrayBase::cast(elements())->length(); | 14050 int length = FixedArrayBase::cast(elements())->length(); |
| 14051 while (counter < length) { | 14051 while (counter < length) { |
| 14052 if (storage != NULL) { | 14052 if (storage != NULL) { |
| 14053 storage->set(counter, Smi::FromInt(counter)); | 14053 storage->set(counter, Smi::FromInt(counter)); |
| 14054 } | 14054 } |
| 14055 counter++; | 14055 counter++; |
| 14056 } | 14056 } |
| 14057 ASSERT(!storage || storage->length() >= counter); | 14057 DCHECK(!storage || storage->length() >= counter); |
| 14058 break; | 14058 break; |
| 14059 } | 14059 } |
| 14060 | 14060 |
| 14061 case DICTIONARY_ELEMENTS: { | 14061 case DICTIONARY_ELEMENTS: { |
| 14062 if (storage != NULL) { | 14062 if (storage != NULL) { |
| 14063 element_dictionary()->CopyKeysTo(storage, | 14063 element_dictionary()->CopyKeysTo(storage, |
| 14064 filter, | 14064 filter, |
| 14065 SeededNumberDictionary::SORTED); | 14065 SeededNumberDictionary::SORTED); |
| 14066 } | 14066 } |
| 14067 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); | 14067 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14115 if (val->IsString()) { | 14115 if (val->IsString()) { |
| 14116 String* str = String::cast(val); | 14116 String* str = String::cast(val); |
| 14117 if (storage) { | 14117 if (storage) { |
| 14118 for (int i = 0; i < str->length(); i++) { | 14118 for (int i = 0; i < str->length(); i++) { |
| 14119 storage->set(counter + i, Smi::FromInt(i)); | 14119 storage->set(counter + i, Smi::FromInt(i)); |
| 14120 } | 14120 } |
| 14121 } | 14121 } |
| 14122 counter += str->length(); | 14122 counter += str->length(); |
| 14123 } | 14123 } |
| 14124 } | 14124 } |
| 14125 ASSERT(!storage || storage->length() == counter); | 14125 DCHECK(!storage || storage->length() == counter); |
| 14126 return counter; | 14126 return counter; |
| 14127 } | 14127 } |
| 14128 | 14128 |
| 14129 | 14129 |
| 14130 int JSObject::GetEnumElementKeys(FixedArray* storage) { | 14130 int JSObject::GetEnumElementKeys(FixedArray* storage) { |
| 14131 return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM)); | 14131 return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM)); |
| 14132 } | 14132 } |
| 14133 | 14133 |
| 14134 | 14134 |
| 14135 // StringSharedKeys are used as keys in the eval cache. | 14135 // StringSharedKeys are used as keys in the eval cache. |
| 14136 class StringSharedKey : public HashTableKey { | 14136 class StringSharedKey : public HashTableKey { |
| 14137 public: | 14137 public: |
| 14138 StringSharedKey(Handle<String> source, | 14138 StringSharedKey(Handle<String> source, |
| 14139 Handle<SharedFunctionInfo> shared, | 14139 Handle<SharedFunctionInfo> shared, |
| 14140 StrictMode strict_mode, | 14140 StrictMode strict_mode, |
| 14141 int scope_position) | 14141 int scope_position) |
| 14142 : source_(source), | 14142 : source_(source), |
| 14143 shared_(shared), | 14143 shared_(shared), |
| 14144 strict_mode_(strict_mode), | 14144 strict_mode_(strict_mode), |
| 14145 scope_position_(scope_position) { } | 14145 scope_position_(scope_position) { } |
| 14146 | 14146 |
| 14147 bool IsMatch(Object* other) V8_OVERRIDE { | 14147 bool IsMatch(Object* other) V8_OVERRIDE { |
| 14148 DisallowHeapAllocation no_allocation; | 14148 DisallowHeapAllocation no_allocation; |
| 14149 if (!other->IsFixedArray()) return false; | 14149 if (!other->IsFixedArray()) return false; |
| 14150 FixedArray* other_array = FixedArray::cast(other); | 14150 FixedArray* other_array = FixedArray::cast(other); |
| 14151 SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0)); | 14151 SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0)); |
| 14152 if (shared != *shared_) return false; | 14152 if (shared != *shared_) return false; |
| 14153 int strict_unchecked = Smi::cast(other_array->get(2))->value(); | 14153 int strict_unchecked = Smi::cast(other_array->get(2))->value(); |
| 14154 ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT); | 14154 DCHECK(strict_unchecked == SLOPPY || strict_unchecked == STRICT); |
| 14155 StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked); | 14155 StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked); |
| 14156 if (strict_mode != strict_mode_) return false; | 14156 if (strict_mode != strict_mode_) return false; |
| 14157 int scope_position = Smi::cast(other_array->get(3))->value(); | 14157 int scope_position = Smi::cast(other_array->get(3))->value(); |
| 14158 if (scope_position != scope_position_) return false; | 14158 if (scope_position != scope_position_) return false; |
| 14159 String* source = String::cast(other_array->get(1)); | 14159 String* source = String::cast(other_array->get(1)); |
| 14160 return source->Equals(*source_); | 14160 return source->Equals(*source_); |
| 14161 } | 14161 } |
| 14162 | 14162 |
| 14163 static uint32_t StringSharedHashHelper(String* source, | 14163 static uint32_t StringSharedHashHelper(String* source, |
| 14164 SharedFunctionInfo* shared, | 14164 SharedFunctionInfo* shared, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 14183 return StringSharedHashHelper(*source_, *shared_, strict_mode_, | 14183 return StringSharedHashHelper(*source_, *shared_, strict_mode_, |
| 14184 scope_position_); | 14184 scope_position_); |
| 14185 } | 14185 } |
| 14186 | 14186 |
| 14187 uint32_t HashForObject(Object* obj) V8_OVERRIDE { | 14187 uint32_t HashForObject(Object* obj) V8_OVERRIDE { |
| 14188 DisallowHeapAllocation no_allocation; | 14188 DisallowHeapAllocation no_allocation; |
| 14189 FixedArray* other_array = FixedArray::cast(obj); | 14189 FixedArray* other_array = FixedArray::cast(obj); |
| 14190 SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0)); | 14190 SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0)); |
| 14191 String* source = String::cast(other_array->get(1)); | 14191 String* source = String::cast(other_array->get(1)); |
| 14192 int strict_unchecked = Smi::cast(other_array->get(2))->value(); | 14192 int strict_unchecked = Smi::cast(other_array->get(2))->value(); |
| 14193 ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT); | 14193 DCHECK(strict_unchecked == SLOPPY || strict_unchecked == STRICT); |
| 14194 StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked); | 14194 StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked); |
| 14195 int scope_position = Smi::cast(other_array->get(3))->value(); | 14195 int scope_position = Smi::cast(other_array->get(3))->value(); |
| 14196 return StringSharedHashHelper( | 14196 return StringSharedHashHelper( |
| 14197 source, shared, strict_mode, scope_position); | 14197 source, shared, strict_mode, scope_position); |
| 14198 } | 14198 } |
| 14199 | 14199 |
| 14200 | 14200 |
| 14201 Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE { | 14201 Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE { |
| 14202 Handle<FixedArray> array = isolate->factory()->NewFixedArray(4); | 14202 Handle<FixedArray> array = isolate->factory()->NewFixedArray(4); |
| 14203 array->set(0, *shared_); | 14203 array->set(0, *shared_); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14334 return String::cast(other)->Hash(); | 14334 return String::cast(other)->Hash(); |
| 14335 } | 14335 } |
| 14336 | 14336 |
| 14337 virtual Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE { | 14337 virtual Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE { |
| 14338 // Internalize the string if possible. | 14338 // Internalize the string if possible. |
| 14339 MaybeHandle<Map> maybe_map = | 14339 MaybeHandle<Map> maybe_map = |
| 14340 isolate->factory()->InternalizedStringMapForString(string_); | 14340 isolate->factory()->InternalizedStringMapForString(string_); |
| 14341 Handle<Map> map; | 14341 Handle<Map> map; |
| 14342 if (maybe_map.ToHandle(&map)) { | 14342 if (maybe_map.ToHandle(&map)) { |
| 14343 string_->set_map_no_write_barrier(*map); | 14343 string_->set_map_no_write_barrier(*map); |
| 14344 ASSERT(string_->IsInternalizedString()); | 14344 DCHECK(string_->IsInternalizedString()); |
| 14345 return string_; | 14345 return string_; |
| 14346 } | 14346 } |
| 14347 // Otherwise allocate a new internalized string. | 14347 // Otherwise allocate a new internalized string. |
| 14348 return isolate->factory()->NewInternalizedStringImpl( | 14348 return isolate->factory()->NewInternalizedStringImpl( |
| 14349 string_, string_->length(), string_->hash_field()); | 14349 string_, string_->length(), string_->hash_field()); |
| 14350 } | 14350 } |
| 14351 | 14351 |
| 14352 static uint32_t StringHash(Object* obj) { | 14352 static uint32_t StringHash(Object* obj) { |
| 14353 return String::cast(obj)->Hash(); | 14353 return String::cast(obj)->Hash(); |
| 14354 } | 14354 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 14370 kHeaderSize + length() * kPointerSize); | 14370 kHeaderSize + length() * kPointerSize); |
| 14371 } | 14371 } |
| 14372 | 14372 |
| 14373 | 14373 |
| 14374 template<typename Derived, typename Shape, typename Key> | 14374 template<typename Derived, typename Shape, typename Key> |
| 14375 Handle<Derived> HashTable<Derived, Shape, Key>::New( | 14375 Handle<Derived> HashTable<Derived, Shape, Key>::New( |
| 14376 Isolate* isolate, | 14376 Isolate* isolate, |
| 14377 int at_least_space_for, | 14377 int at_least_space_for, |
| 14378 MinimumCapacity capacity_option, | 14378 MinimumCapacity capacity_option, |
| 14379 PretenureFlag pretenure) { | 14379 PretenureFlag pretenure) { |
| 14380 ASSERT(0 <= at_least_space_for); | 14380 DCHECK(0 <= at_least_space_for); |
| 14381 ASSERT(!capacity_option || IsPowerOf2(at_least_space_for)); | 14381 DCHECK(!capacity_option || IsPowerOf2(at_least_space_for)); |
| 14382 int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY) | 14382 int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY) |
| 14383 ? at_least_space_for | 14383 ? at_least_space_for |
| 14384 : ComputeCapacity(at_least_space_for); | 14384 : ComputeCapacity(at_least_space_for); |
| 14385 if (capacity > HashTable::kMaxCapacity) { | 14385 if (capacity > HashTable::kMaxCapacity) { |
| 14386 v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true); | 14386 v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true); |
| 14387 } | 14387 } |
| 14388 | 14388 |
| 14389 Factory* factory = isolate->factory(); | 14389 Factory* factory = isolate->factory(); |
| 14390 int length = EntryToIndex(capacity); | 14390 int length = EntryToIndex(capacity); |
| 14391 Handle<FixedArray> array = factory->NewFixedArray(length, pretenure); | 14391 Handle<FixedArray> array = factory->NewFixedArray(length, pretenure); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14425 if (element->IsUndefined()) break; // Empty entry. | 14425 if (element->IsUndefined()) break; // Empty entry. |
| 14426 if (*key == element) return entry; | 14426 if (*key == element) return entry; |
| 14427 if (!element->IsUniqueName() && | 14427 if (!element->IsUniqueName() && |
| 14428 !element->IsTheHole() && | 14428 !element->IsTheHole() && |
| 14429 Name::cast(element)->Equals(*key)) { | 14429 Name::cast(element)->Equals(*key)) { |
| 14430 // Replace a key that is a non-internalized string by the equivalent | 14430 // Replace a key that is a non-internalized string by the equivalent |
| 14431 // internalized string for faster further lookups. | 14431 // internalized string for faster further lookups. |
| 14432 set(index, *key); | 14432 set(index, *key); |
| 14433 return entry; | 14433 return entry; |
| 14434 } | 14434 } |
| 14435 ASSERT(element->IsTheHole() || !Name::cast(element)->Equals(*key)); | 14435 DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key)); |
| 14436 entry = NextProbe(entry, count++, capacity); | 14436 entry = NextProbe(entry, count++, capacity); |
| 14437 } | 14437 } |
| 14438 return kNotFound; | 14438 return kNotFound; |
| 14439 } | 14439 } |
| 14440 | 14440 |
| 14441 | 14441 |
| 14442 template<typename Derived, typename Shape, typename Key> | 14442 template<typename Derived, typename Shape, typename Key> |
| 14443 void HashTable<Derived, Shape, Key>::Rehash( | 14443 void HashTable<Derived, Shape, Key>::Rehash( |
| 14444 Handle<Derived> new_table, | 14444 Handle<Derived> new_table, |
| 14445 Key key) { | 14445 Key key) { |
| 14446 ASSERT(NumberOfElements() < new_table->Capacity()); | 14446 DCHECK(NumberOfElements() < new_table->Capacity()); |
| 14447 | 14447 |
| 14448 DisallowHeapAllocation no_gc; | 14448 DisallowHeapAllocation no_gc; |
| 14449 WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc); | 14449 WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc); |
| 14450 | 14450 |
| 14451 // Copy prefix to new array. | 14451 // Copy prefix to new array. |
| 14452 for (int i = kPrefixStartIndex; | 14452 for (int i = kPrefixStartIndex; |
| 14453 i < kPrefixStartIndex + Shape::kPrefixSize; | 14453 i < kPrefixStartIndex + Shape::kPrefixSize; |
| 14454 i++) { | 14454 i++) { |
| 14455 new_table->set(i, get(i), mode); | 14455 new_table->set(i, get(i), mode); |
| 14456 } | 14456 } |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14765 int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >:: | 14765 int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >:: |
| 14766 NumberOfEnumElements(); | 14766 NumberOfEnumElements(); |
| 14767 | 14767 |
| 14768 template | 14768 template |
| 14769 int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>:: | 14769 int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>:: |
| 14770 FindEntry(uint32_t); | 14770 FindEntry(uint32_t); |
| 14771 | 14771 |
| 14772 | 14772 |
| 14773 Handle<Object> JSObject::PrepareSlowElementsForSort( | 14773 Handle<Object> JSObject::PrepareSlowElementsForSort( |
| 14774 Handle<JSObject> object, uint32_t limit) { | 14774 Handle<JSObject> object, uint32_t limit) { |
| 14775 ASSERT(object->HasDictionaryElements()); | 14775 DCHECK(object->HasDictionaryElements()); |
| 14776 Isolate* isolate = object->GetIsolate(); | 14776 Isolate* isolate = object->GetIsolate(); |
| 14777 // Must stay in dictionary mode, either because of requires_slow_elements, | 14777 // Must stay in dictionary mode, either because of requires_slow_elements, |
| 14778 // or because we are not going to sort (and therefore compact) all of the | 14778 // or because we are not going to sort (and therefore compact) all of the |
| 14779 // elements. | 14779 // elements. |
| 14780 Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate); | 14780 Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate); |
| 14781 Handle<SeededNumberDictionary> new_dict = | 14781 Handle<SeededNumberDictionary> new_dict = |
| 14782 SeededNumberDictionary::New(isolate, dict->NumberOfElements()); | 14782 SeededNumberDictionary::New(isolate, dict->NumberOfElements()); |
| 14783 | 14783 |
| 14784 uint32_t pos = 0; | 14784 uint32_t pos = 0; |
| 14785 uint32_t undefs = 0; | 14785 uint32_t undefs = 0; |
| 14786 int capacity = dict->Capacity(); | 14786 int capacity = dict->Capacity(); |
| 14787 Handle<Smi> bailout(Smi::FromInt(-1), isolate); | 14787 Handle<Smi> bailout(Smi::FromInt(-1), isolate); |
| 14788 // Entry to the new dictionary does not cause it to grow, as we have | 14788 // Entry to the new dictionary does not cause it to grow, as we have |
| 14789 // allocated one that is large enough for all entries. | 14789 // allocated one that is large enough for all entries. |
| 14790 DisallowHeapAllocation no_gc; | 14790 DisallowHeapAllocation no_gc; |
| 14791 for (int i = 0; i < capacity; i++) { | 14791 for (int i = 0; i < capacity; i++) { |
| 14792 Object* k = dict->KeyAt(i); | 14792 Object* k = dict->KeyAt(i); |
| 14793 if (!dict->IsKey(k)) continue; | 14793 if (!dict->IsKey(k)) continue; |
| 14794 | 14794 |
| 14795 ASSERT(k->IsNumber()); | 14795 DCHECK(k->IsNumber()); |
| 14796 ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0); | 14796 DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0); |
| 14797 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0); | 14797 DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0); |
| 14798 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32); | 14798 DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32); |
| 14799 | 14799 |
| 14800 HandleScope scope(isolate); | 14800 HandleScope scope(isolate); |
| 14801 Handle<Object> value(dict->ValueAt(i), isolate); | 14801 Handle<Object> value(dict->ValueAt(i), isolate); |
| 14802 PropertyDetails details = dict->DetailsAt(i); | 14802 PropertyDetails details = dict->DetailsAt(i); |
| 14803 if (details.type() == CALLBACKS || details.IsReadOnly()) { | 14803 if (details.type() == CALLBACKS || details.IsReadOnly()) { |
| 14804 // Bail out and do the sorting of undefineds and array holes in JS. | 14804 // Bail out and do the sorting of undefineds and array holes in JS. |
| 14805 // Also bail out if the element is not supposed to be moved. | 14805 // Also bail out if the element is not supposed to be moved. |
| 14806 return bailout; | 14806 return bailout; |
| 14807 } | 14807 } |
| 14808 | 14808 |
| 14809 uint32_t key = NumberToUint32(k); | 14809 uint32_t key = NumberToUint32(k); |
| 14810 if (key < limit) { | 14810 if (key < limit) { |
| 14811 if (value->IsUndefined()) { | 14811 if (value->IsUndefined()) { |
| 14812 undefs++; | 14812 undefs++; |
| 14813 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 14813 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 14814 // Adding an entry with the key beyond smi-range requires | 14814 // Adding an entry with the key beyond smi-range requires |
| 14815 // allocation. Bailout. | 14815 // allocation. Bailout. |
| 14816 return bailout; | 14816 return bailout; |
| 14817 } else { | 14817 } else { |
| 14818 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 14818 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
| 14819 new_dict, pos, value, details); | 14819 new_dict, pos, value, details); |
| 14820 ASSERT(result.is_identical_to(new_dict)); | 14820 DCHECK(result.is_identical_to(new_dict)); |
| 14821 USE(result); | 14821 USE(result); |
| 14822 pos++; | 14822 pos++; |
| 14823 } | 14823 } |
| 14824 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) { | 14824 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 14825 // Adding an entry with the key beyond smi-range requires | 14825 // Adding an entry with the key beyond smi-range requires |
| 14826 // allocation. Bailout. | 14826 // allocation. Bailout. |
| 14827 return bailout; | 14827 return bailout; |
| 14828 } else { | 14828 } else { |
| 14829 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 14829 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
| 14830 new_dict, key, value, details); | 14830 new_dict, key, value, details); |
| 14831 ASSERT(result.is_identical_to(new_dict)); | 14831 DCHECK(result.is_identical_to(new_dict)); |
| 14832 USE(result); | 14832 USE(result); |
| 14833 } | 14833 } |
| 14834 } | 14834 } |
| 14835 | 14835 |
| 14836 uint32_t result = pos; | 14836 uint32_t result = pos; |
| 14837 PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0); | 14837 PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0); |
| 14838 while (undefs > 0) { | 14838 while (undefs > 0) { |
| 14839 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 14839 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 14840 // Adding an entry with the key beyond smi-range requires | 14840 // Adding an entry with the key beyond smi-range requires |
| 14841 // allocation. Bailout. | 14841 // allocation. Bailout. |
| 14842 return bailout; | 14842 return bailout; |
| 14843 } | 14843 } |
| 14844 HandleScope scope(isolate); | 14844 HandleScope scope(isolate); |
| 14845 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 14845 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
| 14846 new_dict, pos, isolate->factory()->undefined_value(), no_details); | 14846 new_dict, pos, isolate->factory()->undefined_value(), no_details); |
| 14847 ASSERT(result.is_identical_to(new_dict)); | 14847 DCHECK(result.is_identical_to(new_dict)); |
| 14848 USE(result); | 14848 USE(result); |
| 14849 pos++; | 14849 pos++; |
| 14850 undefs--; | 14850 undefs--; |
| 14851 } | 14851 } |
| 14852 | 14852 |
| 14853 object->set_elements(*new_dict); | 14853 object->set_elements(*new_dict); |
| 14854 | 14854 |
| 14855 AllowHeapAllocation allocate_return_value; | 14855 AllowHeapAllocation allocate_return_value; |
| 14856 return isolate->factory()->NewNumberFromUint(result); | 14856 return isolate->factory()->NewNumberFromUint(result); |
| 14857 } | 14857 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14891 | 14891 |
| 14892 JSObject::SetMapAndElements(object, new_map, fast_elements); | 14892 JSObject::SetMapAndElements(object, new_map, fast_elements); |
| 14893 } else if (object->HasExternalArrayElements() || | 14893 } else if (object->HasExternalArrayElements() || |
| 14894 object->HasFixedTypedArrayElements()) { | 14894 object->HasFixedTypedArrayElements()) { |
| 14895 // Typed arrays cannot have holes or undefined elements. | 14895 // Typed arrays cannot have holes or undefined elements. |
| 14896 return handle(Smi::FromInt( | 14896 return handle(Smi::FromInt( |
| 14897 FixedArrayBase::cast(object->elements())->length()), isolate); | 14897 FixedArrayBase::cast(object->elements())->length()), isolate); |
| 14898 } else if (!object->HasFastDoubleElements()) { | 14898 } else if (!object->HasFastDoubleElements()) { |
| 14899 EnsureWritableFastElements(object); | 14899 EnsureWritableFastElements(object); |
| 14900 } | 14900 } |
| 14901 ASSERT(object->HasFastSmiOrObjectElements() || | 14901 DCHECK(object->HasFastSmiOrObjectElements() || |
| 14902 object->HasFastDoubleElements()); | 14902 object->HasFastDoubleElements()); |
| 14903 | 14903 |
| 14904 // Collect holes at the end, undefined before that and the rest at the | 14904 // Collect holes at the end, undefined before that and the rest at the |
| 14905 // start, and return the number of non-hole, non-undefined values. | 14905 // start, and return the number of non-hole, non-undefined values. |
| 14906 | 14906 |
| 14907 Handle<FixedArrayBase> elements_base(object->elements()); | 14907 Handle<FixedArrayBase> elements_base(object->elements()); |
| 14908 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 14908 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
| 14909 if (limit > elements_length) { | 14909 if (limit > elements_length) { |
| 14910 limit = elements_length ; | 14910 limit = elements_length ; |
| 14911 } | 14911 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15047 } else if (double_value > 255) { | 15047 } else if (double_value > 255) { |
| 15048 // Greater than 255 clamp to 255. | 15048 // Greater than 255 clamp to 255. |
| 15049 clamped_value = 255; | 15049 clamped_value = 255; |
| 15050 } else { | 15050 } else { |
| 15051 // Other doubles are rounded to the nearest integer. | 15051 // Other doubles are rounded to the nearest integer. |
| 15052 clamped_value = static_cast<uint8_t>(lrint(double_value)); | 15052 clamped_value = static_cast<uint8_t>(lrint(double_value)); |
| 15053 } | 15053 } |
| 15054 } else { | 15054 } else { |
| 15055 // Clamp undefined to zero (default). All other types have been | 15055 // Clamp undefined to zero (default). All other types have been |
| 15056 // converted to a number type further up in the call chain. | 15056 // converted to a number type further up in the call chain. |
| 15057 ASSERT(value->IsUndefined()); | 15057 DCHECK(value->IsUndefined()); |
| 15058 } | 15058 } |
| 15059 array->set(index, clamped_value); | 15059 array->set(index, clamped_value); |
| 15060 } | 15060 } |
| 15061 return handle(Smi::FromInt(clamped_value), array->GetIsolate()); | 15061 return handle(Smi::FromInt(clamped_value), array->GetIsolate()); |
| 15062 } | 15062 } |
| 15063 | 15063 |
| 15064 | 15064 |
| 15065 template<typename ExternalArrayClass, typename ValueType> | 15065 template<typename ExternalArrayClass, typename ValueType> |
| 15066 static Handle<Object> ExternalArrayIntSetter( | 15066 static Handle<Object> ExternalArrayIntSetter( |
| 15067 Isolate* isolate, | 15067 Isolate* isolate, |
| 15068 Handle<ExternalArrayClass> receiver, | 15068 Handle<ExternalArrayClass> receiver, |
| 15069 uint32_t index, | 15069 uint32_t index, |
| 15070 Handle<Object> value) { | 15070 Handle<Object> value) { |
| 15071 ValueType cast_value = 0; | 15071 ValueType cast_value = 0; |
| 15072 if (index < static_cast<uint32_t>(receiver->length())) { | 15072 if (index < static_cast<uint32_t>(receiver->length())) { |
| 15073 if (value->IsSmi()) { | 15073 if (value->IsSmi()) { |
| 15074 int int_value = Handle<Smi>::cast(value)->value(); | 15074 int int_value = Handle<Smi>::cast(value)->value(); |
| 15075 cast_value = static_cast<ValueType>(int_value); | 15075 cast_value = static_cast<ValueType>(int_value); |
| 15076 } else if (value->IsHeapNumber()) { | 15076 } else if (value->IsHeapNumber()) { |
| 15077 double double_value = Handle<HeapNumber>::cast(value)->value(); | 15077 double double_value = Handle<HeapNumber>::cast(value)->value(); |
| 15078 cast_value = static_cast<ValueType>(DoubleToInt32(double_value)); | 15078 cast_value = static_cast<ValueType>(DoubleToInt32(double_value)); |
| 15079 } else { | 15079 } else { |
| 15080 // Clamp undefined to zero (default). All other types have been | 15080 // Clamp undefined to zero (default). All other types have been |
| 15081 // converted to a number type further up in the call chain. | 15081 // converted to a number type further up in the call chain. |
| 15082 ASSERT(value->IsUndefined()); | 15082 DCHECK(value->IsUndefined()); |
| 15083 } | 15083 } |
| 15084 receiver->set(index, cast_value); | 15084 receiver->set(index, cast_value); |
| 15085 } | 15085 } |
| 15086 return isolate->factory()->NewNumberFromInt(cast_value); | 15086 return isolate->factory()->NewNumberFromInt(cast_value); |
| 15087 } | 15087 } |
| 15088 | 15088 |
| 15089 | 15089 |
| 15090 Handle<Object> ExternalInt8Array::SetValue(Handle<ExternalInt8Array> array, | 15090 Handle<Object> ExternalInt8Array::SetValue(Handle<ExternalInt8Array> array, |
| 15091 uint32_t index, | 15091 uint32_t index, |
| 15092 Handle<Object> value) { | 15092 Handle<Object> value) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15135 if (index < static_cast<uint32_t>(array->length())) { | 15135 if (index < static_cast<uint32_t>(array->length())) { |
| 15136 if (value->IsSmi()) { | 15136 if (value->IsSmi()) { |
| 15137 int int_value = Handle<Smi>::cast(value)->value(); | 15137 int int_value = Handle<Smi>::cast(value)->value(); |
| 15138 cast_value = static_cast<uint32_t>(int_value); | 15138 cast_value = static_cast<uint32_t>(int_value); |
| 15139 } else if (value->IsHeapNumber()) { | 15139 } else if (value->IsHeapNumber()) { |
| 15140 double double_value = Handle<HeapNumber>::cast(value)->value(); | 15140 double double_value = Handle<HeapNumber>::cast(value)->value(); |
| 15141 cast_value = static_cast<uint32_t>(DoubleToUint32(double_value)); | 15141 cast_value = static_cast<uint32_t>(DoubleToUint32(double_value)); |
| 15142 } else { | 15142 } else { |
| 15143 // Clamp undefined to zero (default). All other types have been | 15143 // Clamp undefined to zero (default). All other types have been |
| 15144 // converted to a number type further up in the call chain. | 15144 // converted to a number type further up in the call chain. |
| 15145 ASSERT(value->IsUndefined()); | 15145 DCHECK(value->IsUndefined()); |
| 15146 } | 15146 } |
| 15147 array->set(index, cast_value); | 15147 array->set(index, cast_value); |
| 15148 } | 15148 } |
| 15149 return array->GetIsolate()->factory()->NewNumberFromUint(cast_value); | 15149 return array->GetIsolate()->factory()->NewNumberFromUint(cast_value); |
| 15150 } | 15150 } |
| 15151 | 15151 |
| 15152 | 15152 |
| 15153 Handle<Object> ExternalFloat32Array::SetValue( | 15153 Handle<Object> ExternalFloat32Array::SetValue( |
| 15154 Handle<ExternalFloat32Array> array, | 15154 Handle<ExternalFloat32Array> array, |
| 15155 uint32_t index, | 15155 uint32_t index, |
| 15156 Handle<Object> value) { | 15156 Handle<Object> value) { |
| 15157 float cast_value = static_cast<float>(base::OS::nan_value()); | 15157 float cast_value = static_cast<float>(base::OS::nan_value()); |
| 15158 if (index < static_cast<uint32_t>(array->length())) { | 15158 if (index < static_cast<uint32_t>(array->length())) { |
| 15159 if (value->IsSmi()) { | 15159 if (value->IsSmi()) { |
| 15160 int int_value = Handle<Smi>::cast(value)->value(); | 15160 int int_value = Handle<Smi>::cast(value)->value(); |
| 15161 cast_value = static_cast<float>(int_value); | 15161 cast_value = static_cast<float>(int_value); |
| 15162 } else if (value->IsHeapNumber()) { | 15162 } else if (value->IsHeapNumber()) { |
| 15163 double double_value = Handle<HeapNumber>::cast(value)->value(); | 15163 double double_value = Handle<HeapNumber>::cast(value)->value(); |
| 15164 cast_value = static_cast<float>(double_value); | 15164 cast_value = static_cast<float>(double_value); |
| 15165 } else { | 15165 } else { |
| 15166 // Clamp undefined to NaN (default). All other types have been | 15166 // Clamp undefined to NaN (default). All other types have been |
| 15167 // converted to a number type further up in the call chain. | 15167 // converted to a number type further up in the call chain. |
| 15168 ASSERT(value->IsUndefined()); | 15168 DCHECK(value->IsUndefined()); |
| 15169 } | 15169 } |
| 15170 array->set(index, cast_value); | 15170 array->set(index, cast_value); |
| 15171 } | 15171 } |
| 15172 return array->GetIsolate()->factory()->NewNumber(cast_value); | 15172 return array->GetIsolate()->factory()->NewNumber(cast_value); |
| 15173 } | 15173 } |
| 15174 | 15174 |
| 15175 | 15175 |
| 15176 Handle<Object> ExternalFloat64Array::SetValue( | 15176 Handle<Object> ExternalFloat64Array::SetValue( |
| 15177 Handle<ExternalFloat64Array> array, | 15177 Handle<ExternalFloat64Array> array, |
| 15178 uint32_t index, | 15178 uint32_t index, |
| 15179 Handle<Object> value) { | 15179 Handle<Object> value) { |
| 15180 double double_value = base::OS::nan_value(); | 15180 double double_value = base::OS::nan_value(); |
| 15181 if (index < static_cast<uint32_t>(array->length())) { | 15181 if (index < static_cast<uint32_t>(array->length())) { |
| 15182 if (value->IsNumber()) { | 15182 if (value->IsNumber()) { |
| 15183 double_value = value->Number(); | 15183 double_value = value->Number(); |
| 15184 } else { | 15184 } else { |
| 15185 // Clamp undefined to NaN (default). All other types have been | 15185 // Clamp undefined to NaN (default). All other types have been |
| 15186 // converted to a number type further up in the call chain. | 15186 // converted to a number type further up in the call chain. |
| 15187 ASSERT(value->IsUndefined()); | 15187 DCHECK(value->IsUndefined()); |
| 15188 } | 15188 } |
| 15189 array->set(index, double_value); | 15189 array->set(index, double_value); |
| 15190 } | 15190 } |
| 15191 return array->GetIsolate()->factory()->NewNumber(double_value); | 15191 return array->GetIsolate()->factory()->NewNumber(double_value); |
| 15192 } | 15192 } |
| 15193 | 15193 |
| 15194 | 15194 |
| 15195 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { | 15195 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
| 15196 ASSERT(!HasFastProperties()); | 15196 DCHECK(!HasFastProperties()); |
| 15197 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 15197 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 15198 return PropertyCell::cast(value); | 15198 return PropertyCell::cast(value); |
| 15199 } | 15199 } |
| 15200 | 15200 |
| 15201 | 15201 |
| 15202 Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell( | 15202 Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell( |
| 15203 Handle<JSGlobalObject> global, | 15203 Handle<JSGlobalObject> global, |
| 15204 Handle<Name> name) { | 15204 Handle<Name> name) { |
| 15205 ASSERT(!global->HasFastProperties()); | 15205 DCHECK(!global->HasFastProperties()); |
| 15206 int entry = global->property_dictionary()->FindEntry(name); | 15206 int entry = global->property_dictionary()->FindEntry(name); |
| 15207 if (entry == NameDictionary::kNotFound) { | 15207 if (entry == NameDictionary::kNotFound) { |
| 15208 Isolate* isolate = global->GetIsolate(); | 15208 Isolate* isolate = global->GetIsolate(); |
| 15209 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( | 15209 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( |
| 15210 isolate->factory()->the_hole_value()); | 15210 isolate->factory()->the_hole_value()); |
| 15211 PropertyDetails details(NONE, NORMAL, 0); | 15211 PropertyDetails details(NONE, NORMAL, 0); |
| 15212 details = details.AsDeleted(); | 15212 details = details.AsDeleted(); |
| 15213 Handle<NameDictionary> dictionary = NameDictionary::Add( | 15213 Handle<NameDictionary> dictionary = NameDictionary::Add( |
| 15214 handle(global->property_dictionary()), name, cell, details); | 15214 handle(global->property_dictionary()), name, cell, details); |
| 15215 global->set_properties(*dictionary); | 15215 global->set_properties(*dictionary); |
| 15216 return cell; | 15216 return cell; |
| 15217 } else { | 15217 } else { |
| 15218 Object* value = global->property_dictionary()->ValueAt(entry); | 15218 Object* value = global->property_dictionary()->ValueAt(entry); |
| 15219 ASSERT(value->IsPropertyCell()); | 15219 DCHECK(value->IsPropertyCell()); |
| 15220 return handle(PropertyCell::cast(value)); | 15220 return handle(PropertyCell::cast(value)); |
| 15221 } | 15221 } |
| 15222 } | 15222 } |
| 15223 | 15223 |
| 15224 | 15224 |
| 15225 // This class is used for looking up two character strings in the string table. | 15225 // This class is used for looking up two character strings in the string table. |
| 15226 // If we don't have a hit we don't want to waste much time so we unroll the | 15226 // If we don't have a hit we don't want to waste much time so we unroll the |
| 15227 // string hash calculation loop here for speed. Doesn't work if the two | 15227 // string hash calculation loop here for speed. Doesn't work if the two |
| 15228 // characters form a decimal integer, since such strings have a different hash | 15228 // characters form a decimal integer, since such strings have a different hash |
| 15229 // algorithm. | 15229 // algorithm. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 15247 if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash; | 15247 if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash; |
| 15248 hash_ = hash; | 15248 hash_ = hash; |
| 15249 #ifdef DEBUG | 15249 #ifdef DEBUG |
| 15250 // If this assert fails then we failed to reproduce the two-character | 15250 // If this assert fails then we failed to reproduce the two-character |
| 15251 // version of the string hashing algorithm above. One reason could be | 15251 // version of the string hashing algorithm above. One reason could be |
| 15252 // that we were passed two digits as characters, since the hash | 15252 // that we were passed two digits as characters, since the hash |
| 15253 // algorithm is different in that case. | 15253 // algorithm is different in that case. |
| 15254 uint16_t chars[2] = {c1, c2}; | 15254 uint16_t chars[2] = {c1, c2}; |
| 15255 uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed); | 15255 uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed); |
| 15256 hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask; | 15256 hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask; |
| 15257 ASSERT_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash)); | 15257 DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash)); |
| 15258 #endif | 15258 #endif |
| 15259 } | 15259 } |
| 15260 | 15260 |
| 15261 bool IsMatch(Object* o) V8_OVERRIDE { | 15261 bool IsMatch(Object* o) V8_OVERRIDE { |
| 15262 if (!o->IsString()) return false; | 15262 if (!o->IsString()) return false; |
| 15263 String* other = String::cast(o); | 15263 String* other = String::cast(o); |
| 15264 if (other->length() != 2) return false; | 15264 if (other->length() != 2) return false; |
| 15265 if (other->Get(0) != c1_) return false; | 15265 if (other->Get(0) != c1_) return false; |
| 15266 return other->Get(1) == c2_; | 15266 return other->Get(1) == c2_; |
| 15267 } | 15267 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15299 MaybeHandle<String> StringTable::LookupStringIfExists( | 15299 MaybeHandle<String> StringTable::LookupStringIfExists( |
| 15300 Isolate* isolate, | 15300 Isolate* isolate, |
| 15301 Handle<String> string) { | 15301 Handle<String> string) { |
| 15302 Handle<StringTable> string_table = isolate->factory()->string_table(); | 15302 Handle<StringTable> string_table = isolate->factory()->string_table(); |
| 15303 InternalizedStringKey key(string); | 15303 InternalizedStringKey key(string); |
| 15304 int entry = string_table->FindEntry(&key); | 15304 int entry = string_table->FindEntry(&key); |
| 15305 if (entry == kNotFound) { | 15305 if (entry == kNotFound) { |
| 15306 return MaybeHandle<String>(); | 15306 return MaybeHandle<String>(); |
| 15307 } else { | 15307 } else { |
| 15308 Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate); | 15308 Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate); |
| 15309 ASSERT(StringShape(*result).IsInternalized()); | 15309 DCHECK(StringShape(*result).IsInternalized()); |
| 15310 return result; | 15310 return result; |
| 15311 } | 15311 } |
| 15312 } | 15312 } |
| 15313 | 15313 |
| 15314 | 15314 |
| 15315 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists( | 15315 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists( |
| 15316 Isolate* isolate, | 15316 Isolate* isolate, |
| 15317 uint16_t c1, | 15317 uint16_t c1, |
| 15318 uint16_t c2) { | 15318 uint16_t c2) { |
| 15319 Handle<StringTable> string_table = isolate->factory()->string_table(); | 15319 Handle<StringTable> string_table = isolate->factory()->string_table(); |
| 15320 TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed()); | 15320 TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed()); |
| 15321 int entry = string_table->FindEntry(&key); | 15321 int entry = string_table->FindEntry(&key); |
| 15322 if (entry == kNotFound) { | 15322 if (entry == kNotFound) { |
| 15323 return MaybeHandle<String>(); | 15323 return MaybeHandle<String>(); |
| 15324 } else { | 15324 } else { |
| 15325 Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate); | 15325 Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate); |
| 15326 ASSERT(StringShape(*result).IsInternalized()); | 15326 DCHECK(StringShape(*result).IsInternalized()); |
| 15327 return result; | 15327 return result; |
| 15328 } | 15328 } |
| 15329 } | 15329 } |
| 15330 | 15330 |
| 15331 | 15331 |
| 15332 Handle<String> StringTable::LookupString(Isolate* isolate, | 15332 Handle<String> StringTable::LookupString(Isolate* isolate, |
| 15333 Handle<String> string) { | 15333 Handle<String> string) { |
| 15334 InternalizedStringKey key(string); | 15334 InternalizedStringKey key(string); |
| 15335 return LookupKey(isolate, &key); | 15335 return LookupKey(isolate, &key); |
| 15336 } | 15336 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15519 new_cache->ElementAdded(); | 15519 new_cache->ElementAdded(); |
| 15520 return new_cache; | 15520 return new_cache; |
| 15521 } | 15521 } |
| 15522 | 15522 |
| 15523 | 15523 |
| 15524 template<typename Derived, typename Shape, typename Key> | 15524 template<typename Derived, typename Shape, typename Key> |
| 15525 Handle<Derived> Dictionary<Derived, Shape, Key>::New( | 15525 Handle<Derived> Dictionary<Derived, Shape, Key>::New( |
| 15526 Isolate* isolate, | 15526 Isolate* isolate, |
| 15527 int at_least_space_for, | 15527 int at_least_space_for, |
| 15528 PretenureFlag pretenure) { | 15528 PretenureFlag pretenure) { |
| 15529 ASSERT(0 <= at_least_space_for); | 15529 DCHECK(0 <= at_least_space_for); |
| 15530 Handle<Derived> dict = DerivedHashTable::New(isolate, | 15530 Handle<Derived> dict = DerivedHashTable::New(isolate, |
| 15531 at_least_space_for, | 15531 at_least_space_for, |
| 15532 USE_DEFAULT_MINIMUM_CAPACITY, | 15532 USE_DEFAULT_MINIMUM_CAPACITY, |
| 15533 pretenure); | 15533 pretenure); |
| 15534 | 15534 |
| 15535 // Initialize the next enumeration index. | 15535 // Initialize the next enumeration index. |
| 15536 dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex); | 15536 dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
| 15537 return dict; | 15537 return dict; |
| 15538 } | 15538 } |
| 15539 | 15539 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15646 } | 15646 } |
| 15647 | 15647 |
| 15648 | 15648 |
| 15649 template<typename Derived, typename Shape, typename Key> | 15649 template<typename Derived, typename Shape, typename Key> |
| 15650 Handle<Derived> Dictionary<Derived, Shape, Key>::Add( | 15650 Handle<Derived> Dictionary<Derived, Shape, Key>::Add( |
| 15651 Handle<Derived> dictionary, | 15651 Handle<Derived> dictionary, |
| 15652 Key key, | 15652 Key key, |
| 15653 Handle<Object> value, | 15653 Handle<Object> value, |
| 15654 PropertyDetails details) { | 15654 PropertyDetails details) { |
| 15655 // Valdate key is absent. | 15655 // Valdate key is absent. |
| 15656 SLOW_ASSERT((dictionary->FindEntry(key) == Dictionary::kNotFound)); | 15656 SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound)); |
| 15657 // Check whether the dictionary should be extended. | 15657 // Check whether the dictionary should be extended. |
| 15658 dictionary = EnsureCapacity(dictionary, 1, key); | 15658 dictionary = EnsureCapacity(dictionary, 1, key); |
| 15659 | 15659 |
| 15660 AddEntry(dictionary, key, value, details, dictionary->Hash(key)); | 15660 AddEntry(dictionary, key, value, details, dictionary->Hash(key)); |
| 15661 return dictionary; | 15661 return dictionary; |
| 15662 } | 15662 } |
| 15663 | 15663 |
| 15664 | 15664 |
| 15665 // Add a key, value pair to the dictionary. | 15665 // Add a key, value pair to the dictionary. |
| 15666 template<typename Derived, typename Shape, typename Key> | 15666 template<typename Derived, typename Shape, typename Key> |
| (...skipping 11 matching lines...) Expand all Loading... |
| 15678 if (!details.IsDeleted() && | 15678 if (!details.IsDeleted() && |
| 15679 details.dictionary_index() == 0 && | 15679 details.dictionary_index() == 0 && |
| 15680 Shape::kIsEnumerable) { | 15680 Shape::kIsEnumerable) { |
| 15681 // Assign an enumeration index to the property and update | 15681 // Assign an enumeration index to the property and update |
| 15682 // SetNextEnumerationIndex. | 15682 // SetNextEnumerationIndex. |
| 15683 int index = dictionary->NextEnumerationIndex(); | 15683 int index = dictionary->NextEnumerationIndex(); |
| 15684 details = PropertyDetails(details.attributes(), details.type(), index); | 15684 details = PropertyDetails(details.attributes(), details.type(), index); |
| 15685 dictionary->SetNextEnumerationIndex(index + 1); | 15685 dictionary->SetNextEnumerationIndex(index + 1); |
| 15686 } | 15686 } |
| 15687 dictionary->SetEntry(entry, k, value, details); | 15687 dictionary->SetEntry(entry, k, value, details); |
| 15688 ASSERT((dictionary->KeyAt(entry)->IsNumber() || | 15688 DCHECK((dictionary->KeyAt(entry)->IsNumber() || |
| 15689 dictionary->KeyAt(entry)->IsName())); | 15689 dictionary->KeyAt(entry)->IsName())); |
| 15690 dictionary->ElementAdded(); | 15690 dictionary->ElementAdded(); |
| 15691 } | 15691 } |
| 15692 | 15692 |
| 15693 | 15693 |
| 15694 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { | 15694 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { |
| 15695 DisallowHeapAllocation no_allocation; | 15695 DisallowHeapAllocation no_allocation; |
| 15696 // If the dictionary requires slow elements an element has already | 15696 // If the dictionary requires slow elements an element has already |
| 15697 // been added at a high index. | 15697 // been added at a high index. |
| 15698 if (requires_slow_elements()) return; | 15698 if (requires_slow_elements()) return; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 15710 } | 15710 } |
| 15711 } | 15711 } |
| 15712 | 15712 |
| 15713 | 15713 |
| 15714 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry( | 15714 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry( |
| 15715 Handle<SeededNumberDictionary> dictionary, | 15715 Handle<SeededNumberDictionary> dictionary, |
| 15716 uint32_t key, | 15716 uint32_t key, |
| 15717 Handle<Object> value, | 15717 Handle<Object> value, |
| 15718 PropertyDetails details) { | 15718 PropertyDetails details) { |
| 15719 dictionary->UpdateMaxNumberKey(key); | 15719 dictionary->UpdateMaxNumberKey(key); |
| 15720 SLOW_ASSERT(dictionary->FindEntry(key) == kNotFound); | 15720 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); |
| 15721 return Add(dictionary, key, value, details); | 15721 return Add(dictionary, key, value, details); |
| 15722 } | 15722 } |
| 15723 | 15723 |
| 15724 | 15724 |
| 15725 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( | 15725 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( |
| 15726 Handle<UnseededNumberDictionary> dictionary, | 15726 Handle<UnseededNumberDictionary> dictionary, |
| 15727 uint32_t key, | 15727 uint32_t key, |
| 15728 Handle<Object> value) { | 15728 Handle<Object> value) { |
| 15729 SLOW_ASSERT(dictionary->FindEntry(key) == kNotFound); | 15729 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); |
| 15730 return Add(dictionary, key, value, PropertyDetails(NONE, NORMAL, 0)); | 15730 return Add(dictionary, key, value, PropertyDetails(NONE, NORMAL, 0)); |
| 15731 } | 15731 } |
| 15732 | 15732 |
| 15733 | 15733 |
| 15734 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( | 15734 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( |
| 15735 Handle<SeededNumberDictionary> dictionary, | 15735 Handle<SeededNumberDictionary> dictionary, |
| 15736 uint32_t key, | 15736 uint32_t key, |
| 15737 Handle<Object> value) { | 15737 Handle<Object> value) { |
| 15738 dictionary->UpdateMaxNumberKey(key); | 15738 dictionary->UpdateMaxNumberKey(key); |
| 15739 return AtPut(dictionary, key, value); | 15739 return AtPut(dictionary, key, value); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15805 return NumberOfElementsFilterAttributes( | 15805 return NumberOfElementsFilterAttributes( |
| 15806 static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC)); | 15806 static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC)); |
| 15807 } | 15807 } |
| 15808 | 15808 |
| 15809 | 15809 |
| 15810 template<typename Derived, typename Shape, typename Key> | 15810 template<typename Derived, typename Shape, typename Key> |
| 15811 void Dictionary<Derived, Shape, Key>::CopyKeysTo( | 15811 void Dictionary<Derived, Shape, Key>::CopyKeysTo( |
| 15812 FixedArray* storage, | 15812 FixedArray* storage, |
| 15813 PropertyAttributes filter, | 15813 PropertyAttributes filter, |
| 15814 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { | 15814 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { |
| 15815 ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter)); | 15815 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); |
| 15816 int capacity = DerivedHashTable::Capacity(); | 15816 int capacity = DerivedHashTable::Capacity(); |
| 15817 int index = 0; | 15817 int index = 0; |
| 15818 for (int i = 0; i < capacity; i++) { | 15818 for (int i = 0; i < capacity; i++) { |
| 15819 Object* k = DerivedHashTable::KeyAt(i); | 15819 Object* k = DerivedHashTable::KeyAt(i); |
| 15820 if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) { | 15820 if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) { |
| 15821 PropertyDetails details = DetailsAt(i); | 15821 PropertyDetails details = DetailsAt(i); |
| 15822 if (details.IsDeleted()) continue; | 15822 if (details.IsDeleted()) continue; |
| 15823 PropertyAttributes attr = details.attributes(); | 15823 PropertyAttributes attr = details.attributes(); |
| 15824 if ((attr & filter) == 0) storage->set(index++, k); | 15824 if ((attr & filter) == 0) storage->set(index++, k); |
| 15825 } | 15825 } |
| 15826 } | 15826 } |
| 15827 if (sort_mode == Dictionary::SORTED) { | 15827 if (sort_mode == Dictionary::SORTED) { |
| 15828 storage->SortPairs(storage, index); | 15828 storage->SortPairs(storage, index); |
| 15829 } | 15829 } |
| 15830 ASSERT(storage->length() >= index); | 15830 DCHECK(storage->length() >= index); |
| 15831 } | 15831 } |
| 15832 | 15832 |
| 15833 | 15833 |
| 15834 struct EnumIndexComparator { | 15834 struct EnumIndexComparator { |
| 15835 explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { } | 15835 explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { } |
| 15836 bool operator() (Smi* a, Smi* b) { | 15836 bool operator() (Smi* a, Smi* b) { |
| 15837 PropertyDetails da(dict->DetailsAt(a->value())); | 15837 PropertyDetails da(dict->DetailsAt(a->value())); |
| 15838 PropertyDetails db(dict->DetailsAt(b->value())); | 15838 PropertyDetails db(dict->DetailsAt(b->value())); |
| 15839 return da.dictionary_index() < db.dictionary_index(); | 15839 return da.dictionary_index() < db.dictionary_index(); |
| 15840 } | 15840 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 15866 } | 15866 } |
| 15867 } | 15867 } |
| 15868 | 15868 |
| 15869 | 15869 |
| 15870 template<typename Derived, typename Shape, typename Key> | 15870 template<typename Derived, typename Shape, typename Key> |
| 15871 void Dictionary<Derived, Shape, Key>::CopyKeysTo( | 15871 void Dictionary<Derived, Shape, Key>::CopyKeysTo( |
| 15872 FixedArray* storage, | 15872 FixedArray* storage, |
| 15873 int index, | 15873 int index, |
| 15874 PropertyAttributes filter, | 15874 PropertyAttributes filter, |
| 15875 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { | 15875 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { |
| 15876 ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter)); | 15876 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); |
| 15877 int capacity = DerivedHashTable::Capacity(); | 15877 int capacity = DerivedHashTable::Capacity(); |
| 15878 for (int i = 0; i < capacity; i++) { | 15878 for (int i = 0; i < capacity; i++) { |
| 15879 Object* k = DerivedHashTable::KeyAt(i); | 15879 Object* k = DerivedHashTable::KeyAt(i); |
| 15880 if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) { | 15880 if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) { |
| 15881 PropertyDetails details = DetailsAt(i); | 15881 PropertyDetails details = DetailsAt(i); |
| 15882 if (details.IsDeleted()) continue; | 15882 if (details.IsDeleted()) continue; |
| 15883 PropertyAttributes attr = details.attributes(); | 15883 PropertyAttributes attr = details.attributes(); |
| 15884 if ((attr & filter) == 0) storage->set(index++, k); | 15884 if ((attr & filter) == 0) storage->set(index++, k); |
| 15885 } | 15885 } |
| 15886 } | 15886 } |
| 15887 if (sort_mode == Dictionary::SORTED) { | 15887 if (sort_mode == Dictionary::SORTED) { |
| 15888 storage->SortPairs(storage, index); | 15888 storage->SortPairs(storage, index); |
| 15889 } | 15889 } |
| 15890 ASSERT(storage->length() >= index); | 15890 DCHECK(storage->length() >= index); |
| 15891 } | 15891 } |
| 15892 | 15892 |
| 15893 | 15893 |
| 15894 // Backwards lookup (slow). | 15894 // Backwards lookup (slow). |
| 15895 template<typename Derived, typename Shape, typename Key> | 15895 template<typename Derived, typename Shape, typename Key> |
| 15896 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { | 15896 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { |
| 15897 int capacity = DerivedHashTable::Capacity(); | 15897 int capacity = DerivedHashTable::Capacity(); |
| 15898 for (int i = 0; i < capacity; i++) { | 15898 for (int i = 0; i < capacity; i++) { |
| 15899 Object* k = DerivedHashTable::KeyAt(i); | 15899 Object* k = DerivedHashTable::KeyAt(i); |
| 15900 if (Dictionary::IsKey(k)) { | 15900 if (Dictionary::IsKey(k)) { |
| 15901 Object* e = ValueAt(i); | 15901 Object* e = ValueAt(i); |
| 15902 if (e->IsPropertyCell()) { | 15902 if (e->IsPropertyCell()) { |
| 15903 e = PropertyCell::cast(e)->value(); | 15903 e = PropertyCell::cast(e)->value(); |
| 15904 } | 15904 } |
| 15905 if (e == value) return k; | 15905 if (e == value) return k; |
| 15906 } | 15906 } |
| 15907 } | 15907 } |
| 15908 Heap* heap = Dictionary::GetHeap(); | 15908 Heap* heap = Dictionary::GetHeap(); |
| 15909 return heap->undefined_value(); | 15909 return heap->undefined_value(); |
| 15910 } | 15910 } |
| 15911 | 15911 |
| 15912 | 15912 |
| 15913 Object* ObjectHashTable::Lookup(Handle<Object> key) { | 15913 Object* ObjectHashTable::Lookup(Handle<Object> key) { |
| 15914 DisallowHeapAllocation no_gc; | 15914 DisallowHeapAllocation no_gc; |
| 15915 ASSERT(IsKey(*key)); | 15915 DCHECK(IsKey(*key)); |
| 15916 | 15916 |
| 15917 // If the object does not have an identity hash, it was never used as a key. | 15917 // If the object does not have an identity hash, it was never used as a key. |
| 15918 Object* hash = key->GetHash(); | 15918 Object* hash = key->GetHash(); |
| 15919 if (hash->IsUndefined()) { | 15919 if (hash->IsUndefined()) { |
| 15920 return GetHeap()->the_hole_value(); | 15920 return GetHeap()->the_hole_value(); |
| 15921 } | 15921 } |
| 15922 int entry = FindEntry(key); | 15922 int entry = FindEntry(key); |
| 15923 if (entry == kNotFound) return GetHeap()->the_hole_value(); | 15923 if (entry == kNotFound) return GetHeap()->the_hole_value(); |
| 15924 return get(EntryToIndex(entry) + 1); | 15924 return get(EntryToIndex(entry) + 1); |
| 15925 } | 15925 } |
| 15926 | 15926 |
| 15927 | 15927 |
| 15928 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, | 15928 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
| 15929 Handle<Object> key, | 15929 Handle<Object> key, |
| 15930 Handle<Object> value) { | 15930 Handle<Object> value) { |
| 15931 ASSERT(table->IsKey(*key)); | 15931 DCHECK(table->IsKey(*key)); |
| 15932 ASSERT(!value->IsTheHole()); | 15932 DCHECK(!value->IsTheHole()); |
| 15933 | 15933 |
| 15934 Isolate* isolate = table->GetIsolate(); | 15934 Isolate* isolate = table->GetIsolate(); |
| 15935 | 15935 |
| 15936 // Make sure the key object has an identity hash code. | 15936 // Make sure the key object has an identity hash code. |
| 15937 Handle<Smi> hash = Object::GetOrCreateHash(isolate, key); | 15937 Handle<Smi> hash = Object::GetOrCreateHash(isolate, key); |
| 15938 | 15938 |
| 15939 int entry = table->FindEntry(key); | 15939 int entry = table->FindEntry(key); |
| 15940 | 15940 |
| 15941 // Key is already in table, just overwrite value. | 15941 // Key is already in table, just overwrite value. |
| 15942 if (entry != kNotFound) { | 15942 if (entry != kNotFound) { |
| 15943 table->set(EntryToIndex(entry) + 1, *value); | 15943 table->set(EntryToIndex(entry) + 1, *value); |
| 15944 return table; | 15944 return table; |
| 15945 } | 15945 } |
| 15946 | 15946 |
| 15947 // Check whether the hash table should be extended. | 15947 // Check whether the hash table should be extended. |
| 15948 table = EnsureCapacity(table, 1, key); | 15948 table = EnsureCapacity(table, 1, key); |
| 15949 table->AddEntry(table->FindInsertionEntry(hash->value()), | 15949 table->AddEntry(table->FindInsertionEntry(hash->value()), |
| 15950 *key, | 15950 *key, |
| 15951 *value); | 15951 *value); |
| 15952 return table; | 15952 return table; |
| 15953 } | 15953 } |
| 15954 | 15954 |
| 15955 | 15955 |
| 15956 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table, | 15956 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table, |
| 15957 Handle<Object> key, | 15957 Handle<Object> key, |
| 15958 bool* was_present) { | 15958 bool* was_present) { |
| 15959 ASSERT(table->IsKey(*key)); | 15959 DCHECK(table->IsKey(*key)); |
| 15960 | 15960 |
| 15961 Object* hash = key->GetHash(); | 15961 Object* hash = key->GetHash(); |
| 15962 if (hash->IsUndefined()) { | 15962 if (hash->IsUndefined()) { |
| 15963 *was_present = false; | 15963 *was_present = false; |
| 15964 return table; | 15964 return table; |
| 15965 } | 15965 } |
| 15966 | 15966 |
| 15967 int entry = table->FindEntry(key); | 15967 int entry = table->FindEntry(key); |
| 15968 if (entry == kNotFound) { | 15968 if (entry == kNotFound) { |
| 15969 *was_present = false; | 15969 *was_present = false; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 15985 | 15985 |
| 15986 void ObjectHashTable::RemoveEntry(int entry) { | 15986 void ObjectHashTable::RemoveEntry(int entry) { |
| 15987 set_the_hole(EntryToIndex(entry)); | 15987 set_the_hole(EntryToIndex(entry)); |
| 15988 set_the_hole(EntryToIndex(entry) + 1); | 15988 set_the_hole(EntryToIndex(entry) + 1); |
| 15989 ElementRemoved(); | 15989 ElementRemoved(); |
| 15990 } | 15990 } |
| 15991 | 15991 |
| 15992 | 15992 |
| 15993 Object* WeakHashTable::Lookup(Handle<Object> key) { | 15993 Object* WeakHashTable::Lookup(Handle<Object> key) { |
| 15994 DisallowHeapAllocation no_gc; | 15994 DisallowHeapAllocation no_gc; |
| 15995 ASSERT(IsKey(*key)); | 15995 DCHECK(IsKey(*key)); |
| 15996 int entry = FindEntry(key); | 15996 int entry = FindEntry(key); |
| 15997 if (entry == kNotFound) return GetHeap()->the_hole_value(); | 15997 if (entry == kNotFound) return GetHeap()->the_hole_value(); |
| 15998 return get(EntryToValueIndex(entry)); | 15998 return get(EntryToValueIndex(entry)); |
| 15999 } | 15999 } |
| 16000 | 16000 |
| 16001 | 16001 |
| 16002 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table, | 16002 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table, |
| 16003 Handle<Object> key, | 16003 Handle<Object> key, |
| 16004 Handle<Object> value) { | 16004 Handle<Object> value) { |
| 16005 ASSERT(table->IsKey(*key)); | 16005 DCHECK(table->IsKey(*key)); |
| 16006 int entry = table->FindEntry(key); | 16006 int entry = table->FindEntry(key); |
| 16007 // Key is already in table, just overwrite value. | 16007 // Key is already in table, just overwrite value. |
| 16008 if (entry != kNotFound) { | 16008 if (entry != kNotFound) { |
| 16009 // TODO(ulan): Skipping write barrier is a temporary solution to avoid | 16009 // TODO(ulan): Skipping write barrier is a temporary solution to avoid |
| 16010 // memory leaks. Remove this once we have special visitor for weak fixed | 16010 // memory leaks. Remove this once we have special visitor for weak fixed |
| 16011 // arrays. | 16011 // arrays. |
| 16012 table->set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER); | 16012 table->set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER); |
| 16013 return table; | 16013 return table; |
| 16014 } | 16014 } |
| 16015 | 16015 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16058 table->SetNumberOfBuckets(num_buckets); | 16058 table->SetNumberOfBuckets(num_buckets); |
| 16059 table->SetNumberOfElements(0); | 16059 table->SetNumberOfElements(0); |
| 16060 table->SetNumberOfDeletedElements(0); | 16060 table->SetNumberOfDeletedElements(0); |
| 16061 return table; | 16061 return table; |
| 16062 } | 16062 } |
| 16063 | 16063 |
| 16064 | 16064 |
| 16065 template<class Derived, class Iterator, int entrysize> | 16065 template<class Derived, class Iterator, int entrysize> |
| 16066 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable( | 16066 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable( |
| 16067 Handle<Derived> table) { | 16067 Handle<Derived> table) { |
| 16068 ASSERT(!table->IsObsolete()); | 16068 DCHECK(!table->IsObsolete()); |
| 16069 | 16069 |
| 16070 int nof = table->NumberOfElements(); | 16070 int nof = table->NumberOfElements(); |
| 16071 int nod = table->NumberOfDeletedElements(); | 16071 int nod = table->NumberOfDeletedElements(); |
| 16072 int capacity = table->Capacity(); | 16072 int capacity = table->Capacity(); |
| 16073 if ((nof + nod) < capacity) return table; | 16073 if ((nof + nod) < capacity) return table; |
| 16074 // Don't need to grow if we can simply clear out deleted entries instead. | 16074 // Don't need to grow if we can simply clear out deleted entries instead. |
| 16075 // Note that we can't compact in place, though, so we always allocate | 16075 // Note that we can't compact in place, though, so we always allocate |
| 16076 // a new table. | 16076 // a new table. |
| 16077 return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity); | 16077 return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity); |
| 16078 } | 16078 } |
| 16079 | 16079 |
| 16080 | 16080 |
| 16081 template<class Derived, class Iterator, int entrysize> | 16081 template<class Derived, class Iterator, int entrysize> |
| 16082 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink( | 16082 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink( |
| 16083 Handle<Derived> table) { | 16083 Handle<Derived> table) { |
| 16084 ASSERT(!table->IsObsolete()); | 16084 DCHECK(!table->IsObsolete()); |
| 16085 | 16085 |
| 16086 int nof = table->NumberOfElements(); | 16086 int nof = table->NumberOfElements(); |
| 16087 int capacity = table->Capacity(); | 16087 int capacity = table->Capacity(); |
| 16088 if (nof >= (capacity >> 2)) return table; | 16088 if (nof >= (capacity >> 2)) return table; |
| 16089 return Rehash(table, capacity / 2); | 16089 return Rehash(table, capacity / 2); |
| 16090 } | 16090 } |
| 16091 | 16091 |
| 16092 | 16092 |
| 16093 template<class Derived, class Iterator, int entrysize> | 16093 template<class Derived, class Iterator, int entrysize> |
| 16094 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear( | 16094 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear( |
| 16095 Handle<Derived> table) { | 16095 Handle<Derived> table) { |
| 16096 ASSERT(!table->IsObsolete()); | 16096 DCHECK(!table->IsObsolete()); |
| 16097 | 16097 |
| 16098 Handle<Derived> new_table = | 16098 Handle<Derived> new_table = |
| 16099 Allocate(table->GetIsolate(), | 16099 Allocate(table->GetIsolate(), |
| 16100 kMinCapacity, | 16100 kMinCapacity, |
| 16101 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED); | 16101 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED); |
| 16102 | 16102 |
| 16103 table->SetNextTable(*new_table); | 16103 table->SetNextTable(*new_table); |
| 16104 table->SetNumberOfDeletedElements(-1); | 16104 table->SetNumberOfDeletedElements(-1); |
| 16105 | 16105 |
| 16106 return new_table; | 16106 return new_table; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 16117 } | 16117 } |
| 16118 *was_present = true; | 16118 *was_present = true; |
| 16119 table->RemoveEntry(entry); | 16119 table->RemoveEntry(entry); |
| 16120 return Shrink(table); | 16120 return Shrink(table); |
| 16121 } | 16121 } |
| 16122 | 16122 |
| 16123 | 16123 |
| 16124 template<class Derived, class Iterator, int entrysize> | 16124 template<class Derived, class Iterator, int entrysize> |
| 16125 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash( | 16125 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash( |
| 16126 Handle<Derived> table, int new_capacity) { | 16126 Handle<Derived> table, int new_capacity) { |
| 16127 ASSERT(!table->IsObsolete()); | 16127 DCHECK(!table->IsObsolete()); |
| 16128 | 16128 |
| 16129 Handle<Derived> new_table = | 16129 Handle<Derived> new_table = |
| 16130 Allocate(table->GetIsolate(), | 16130 Allocate(table->GetIsolate(), |
| 16131 new_capacity, | 16131 new_capacity, |
| 16132 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED); | 16132 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED); |
| 16133 int nof = table->NumberOfElements(); | 16133 int nof = table->NumberOfElements(); |
| 16134 int nod = table->NumberOfDeletedElements(); | 16134 int nod = table->NumberOfDeletedElements(); |
| 16135 int new_buckets = new_table->NumberOfBuckets(); | 16135 int new_buckets = new_table->NumberOfBuckets(); |
| 16136 int new_entry = 0; | 16136 int new_entry = 0; |
| 16137 int removed_holes_index = 0; | 16137 int removed_holes_index = 0; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 16150 int new_index = new_table->EntryToIndex(new_entry); | 16150 int new_index = new_table->EntryToIndex(new_entry); |
| 16151 int old_index = table->EntryToIndex(old_entry); | 16151 int old_index = table->EntryToIndex(old_entry); |
| 16152 for (int i = 0; i < entrysize; ++i) { | 16152 for (int i = 0; i < entrysize; ++i) { |
| 16153 Object* value = table->get(old_index + i); | 16153 Object* value = table->get(old_index + i); |
| 16154 new_table->set(new_index + i, value); | 16154 new_table->set(new_index + i, value); |
| 16155 } | 16155 } |
| 16156 new_table->set(new_index + kChainOffset, chain_entry); | 16156 new_table->set(new_index + kChainOffset, chain_entry); |
| 16157 ++new_entry; | 16157 ++new_entry; |
| 16158 } | 16158 } |
| 16159 | 16159 |
| 16160 ASSERT_EQ(nod, removed_holes_index); | 16160 DCHECK_EQ(nod, removed_holes_index); |
| 16161 | 16161 |
| 16162 new_table->SetNumberOfElements(nof); | 16162 new_table->SetNumberOfElements(nof); |
| 16163 table->SetNextTable(*new_table); | 16163 table->SetNextTable(*new_table); |
| 16164 | 16164 |
| 16165 return new_table; | 16165 return new_table; |
| 16166 } | 16166 } |
| 16167 | 16167 |
| 16168 | 16168 |
| 16169 template <class Derived, class Iterator, int entrysize> | 16169 template <class Derived, class Iterator, int entrysize> |
| 16170 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry( | 16170 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry( |
| 16171 Handle<Object> key, int hash) { | 16171 Handle<Object> key, int hash) { |
| 16172 ASSERT(!IsObsolete()); | 16172 DCHECK(!IsObsolete()); |
| 16173 | 16173 |
| 16174 DisallowHeapAllocation no_gc; | 16174 DisallowHeapAllocation no_gc; |
| 16175 ASSERT(!key->IsTheHole()); | 16175 DCHECK(!key->IsTheHole()); |
| 16176 for (int entry = HashToEntry(hash); entry != kNotFound; | 16176 for (int entry = HashToEntry(hash); entry != kNotFound; |
| 16177 entry = ChainAt(entry)) { | 16177 entry = ChainAt(entry)) { |
| 16178 Object* candidate = KeyAt(entry); | 16178 Object* candidate = KeyAt(entry); |
| 16179 if (candidate->SameValueZero(*key)) | 16179 if (candidate->SameValueZero(*key)) |
| 16180 return entry; | 16180 return entry; |
| 16181 } | 16181 } |
| 16182 return kNotFound; | 16182 return kNotFound; |
| 16183 } | 16183 } |
| 16184 | 16184 |
| 16185 | 16185 |
| 16186 template <class Derived, class Iterator, int entrysize> | 16186 template <class Derived, class Iterator, int entrysize> |
| 16187 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry( | 16187 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry( |
| 16188 Handle<Object> key) { | 16188 Handle<Object> key) { |
| 16189 DisallowHeapAllocation no_gc; | 16189 DisallowHeapAllocation no_gc; |
| 16190 Object* hash = key->GetHash(); | 16190 Object* hash = key->GetHash(); |
| 16191 if (!hash->IsSmi()) return kNotFound; | 16191 if (!hash->IsSmi()) return kNotFound; |
| 16192 return FindEntry(key, Smi::cast(hash)->value()); | 16192 return FindEntry(key, Smi::cast(hash)->value()); |
| 16193 } | 16193 } |
| 16194 | 16194 |
| 16195 | 16195 |
| 16196 template <class Derived, class Iterator, int entrysize> | 16196 template <class Derived, class Iterator, int entrysize> |
| 16197 int OrderedHashTable<Derived, Iterator, entrysize>::AddEntry(int hash) { | 16197 int OrderedHashTable<Derived, Iterator, entrysize>::AddEntry(int hash) { |
| 16198 ASSERT(!IsObsolete()); | 16198 DCHECK(!IsObsolete()); |
| 16199 | 16199 |
| 16200 int entry = UsedCapacity(); | 16200 int entry = UsedCapacity(); |
| 16201 int bucket = HashToBucket(hash); | 16201 int bucket = HashToBucket(hash); |
| 16202 int index = EntryToIndex(entry); | 16202 int index = EntryToIndex(entry); |
| 16203 Object* chain_entry = get(kHashTableStartIndex + bucket); | 16203 Object* chain_entry = get(kHashTableStartIndex + bucket); |
| 16204 set(kHashTableStartIndex + bucket, Smi::FromInt(entry)); | 16204 set(kHashTableStartIndex + bucket, Smi::FromInt(entry)); |
| 16205 set(index + kChainOffset, chain_entry); | 16205 set(index + kChainOffset, chain_entry); |
| 16206 SetNumberOfElements(NumberOfElements() + 1); | 16206 SetNumberOfElements(NumberOfElements() + 1); |
| 16207 return index; | 16207 return index; |
| 16208 } | 16208 } |
| 16209 | 16209 |
| 16210 | 16210 |
| 16211 template<class Derived, class Iterator, int entrysize> | 16211 template<class Derived, class Iterator, int entrysize> |
| 16212 void OrderedHashTable<Derived, Iterator, entrysize>::RemoveEntry(int entry) { | 16212 void OrderedHashTable<Derived, Iterator, entrysize>::RemoveEntry(int entry) { |
| 16213 ASSERT(!IsObsolete()); | 16213 DCHECK(!IsObsolete()); |
| 16214 | 16214 |
| 16215 int index = EntryToIndex(entry); | 16215 int index = EntryToIndex(entry); |
| 16216 for (int i = 0; i < entrysize; ++i) { | 16216 for (int i = 0; i < entrysize; ++i) { |
| 16217 set_the_hole(index + i); | 16217 set_the_hole(index + i); |
| 16218 } | 16218 } |
| 16219 SetNumberOfElements(NumberOfElements() - 1); | 16219 SetNumberOfElements(NumberOfElements() - 1); |
| 16220 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1); | 16220 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1); |
| 16221 } | 16221 } |
| 16222 | 16222 |
| 16223 | 16223 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16307 DisallowHeapAllocation no_gc; | 16307 DisallowHeapAllocation no_gc; |
| 16308 int entry = FindEntry(key); | 16308 int entry = FindEntry(key); |
| 16309 if (entry == kNotFound) return GetHeap()->the_hole_value(); | 16309 if (entry == kNotFound) return GetHeap()->the_hole_value(); |
| 16310 return ValueAt(entry); | 16310 return ValueAt(entry); |
| 16311 } | 16311 } |
| 16312 | 16312 |
| 16313 | 16313 |
| 16314 Handle<OrderedHashMap> OrderedHashMap::Put(Handle<OrderedHashMap> table, | 16314 Handle<OrderedHashMap> OrderedHashMap::Put(Handle<OrderedHashMap> table, |
| 16315 Handle<Object> key, | 16315 Handle<Object> key, |
| 16316 Handle<Object> value) { | 16316 Handle<Object> value) { |
| 16317 ASSERT(!key->IsTheHole()); | 16317 DCHECK(!key->IsTheHole()); |
| 16318 | 16318 |
| 16319 int hash = GetOrCreateHash(table->GetIsolate(), key)->value(); | 16319 int hash = GetOrCreateHash(table->GetIsolate(), key)->value(); |
| 16320 int entry = table->FindEntry(key, hash); | 16320 int entry = table->FindEntry(key, hash); |
| 16321 | 16321 |
| 16322 if (entry != kNotFound) { | 16322 if (entry != kNotFound) { |
| 16323 table->set(table->EntryToIndex(entry) + kValueOffset, *value); | 16323 table->set(table->EntryToIndex(entry) + kValueOffset, *value); |
| 16324 return table; | 16324 return table; |
| 16325 } | 16325 } |
| 16326 | 16326 |
| 16327 table = EnsureGrowable(table); | 16327 table = EnsureGrowable(table); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16441 DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator( | 16441 DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator( |
| 16442 DeclaredAccessorDescriptor* descriptor) | 16442 DeclaredAccessorDescriptor* descriptor) |
| 16443 : array_(descriptor->serialized_data()->GetDataStartAddress()), | 16443 : array_(descriptor->serialized_data()->GetDataStartAddress()), |
| 16444 length_(descriptor->serialized_data()->length()), | 16444 length_(descriptor->serialized_data()->length()), |
| 16445 offset_(0) { | 16445 offset_(0) { |
| 16446 } | 16446 } |
| 16447 | 16447 |
| 16448 | 16448 |
| 16449 const DeclaredAccessorDescriptorData* | 16449 const DeclaredAccessorDescriptorData* |
| 16450 DeclaredAccessorDescriptorIterator::Next() { | 16450 DeclaredAccessorDescriptorIterator::Next() { |
| 16451 ASSERT(offset_ < length_); | 16451 DCHECK(offset_ < length_); |
| 16452 uint8_t* ptr = &array_[offset_]; | 16452 uint8_t* ptr = &array_[offset_]; |
| 16453 ASSERT(reinterpret_cast<uintptr_t>(ptr) % sizeof(uintptr_t) == 0); | 16453 DCHECK(reinterpret_cast<uintptr_t>(ptr) % sizeof(uintptr_t) == 0); |
| 16454 const DeclaredAccessorDescriptorData* data = | 16454 const DeclaredAccessorDescriptorData* data = |
| 16455 reinterpret_cast<const DeclaredAccessorDescriptorData*>(ptr); | 16455 reinterpret_cast<const DeclaredAccessorDescriptorData*>(ptr); |
| 16456 offset_ += sizeof(*data); | 16456 offset_ += sizeof(*data); |
| 16457 ASSERT(offset_ <= length_); | 16457 DCHECK(offset_ <= length_); |
| 16458 return data; | 16458 return data; |
| 16459 } | 16459 } |
| 16460 | 16460 |
| 16461 | 16461 |
| 16462 Handle<DeclaredAccessorDescriptor> DeclaredAccessorDescriptor::Create( | 16462 Handle<DeclaredAccessorDescriptor> DeclaredAccessorDescriptor::Create( |
| 16463 Isolate* isolate, | 16463 Isolate* isolate, |
| 16464 const DeclaredAccessorDescriptorData& descriptor, | 16464 const DeclaredAccessorDescriptorData& descriptor, |
| 16465 Handle<DeclaredAccessorDescriptor> previous) { | 16465 Handle<DeclaredAccessorDescriptor> previous) { |
| 16466 int previous_length = | 16466 int previous_length = |
| 16467 previous.is_null() ? 0 : previous->serialized_data()->length(); | 16467 previous.is_null() ? 0 : previous->serialized_data()->length(); |
| 16468 int length = sizeof(descriptor) + previous_length; | 16468 int length = sizeof(descriptor) + previous_length; |
| 16469 Handle<ByteArray> serialized_descriptor = | 16469 Handle<ByteArray> serialized_descriptor = |
| 16470 isolate->factory()->NewByteArray(length); | 16470 isolate->factory()->NewByteArray(length); |
| 16471 Handle<DeclaredAccessorDescriptor> value = | 16471 Handle<DeclaredAccessorDescriptor> value = |
| 16472 isolate->factory()->NewDeclaredAccessorDescriptor(); | 16472 isolate->factory()->NewDeclaredAccessorDescriptor(); |
| 16473 value->set_serialized_data(*serialized_descriptor); | 16473 value->set_serialized_data(*serialized_descriptor); |
| 16474 // Copy in the data. | 16474 // Copy in the data. |
| 16475 { | 16475 { |
| 16476 DisallowHeapAllocation no_allocation; | 16476 DisallowHeapAllocation no_allocation; |
| 16477 uint8_t* array = serialized_descriptor->GetDataStartAddress(); | 16477 uint8_t* array = serialized_descriptor->GetDataStartAddress(); |
| 16478 if (previous_length != 0) { | 16478 if (previous_length != 0) { |
| 16479 uint8_t* previous_array = | 16479 uint8_t* previous_array = |
| 16480 previous->serialized_data()->GetDataStartAddress(); | 16480 previous->serialized_data()->GetDataStartAddress(); |
| 16481 MemCopy(array, previous_array, previous_length); | 16481 MemCopy(array, previous_array, previous_length); |
| 16482 array += previous_length; | 16482 array += previous_length; |
| 16483 } | 16483 } |
| 16484 ASSERT(reinterpret_cast<uintptr_t>(array) % sizeof(uintptr_t) == 0); | 16484 DCHECK(reinterpret_cast<uintptr_t>(array) % sizeof(uintptr_t) == 0); |
| 16485 DeclaredAccessorDescriptorData* data = | 16485 DeclaredAccessorDescriptorData* data = |
| 16486 reinterpret_cast<DeclaredAccessorDescriptorData*>(array); | 16486 reinterpret_cast<DeclaredAccessorDescriptorData*>(array); |
| 16487 *data = descriptor; | 16487 *data = descriptor; |
| 16488 } | 16488 } |
| 16489 return value; | 16489 return value; |
| 16490 } | 16490 } |
| 16491 | 16491 |
| 16492 | 16492 |
| 16493 // Check if there is a break point at this code position. | 16493 // Check if there is a break point at this code position. |
| 16494 bool DebugInfo::HasBreakPoint(int code_position) { | 16494 bool DebugInfo::HasBreakPoint(int code_position) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16558 isolate->factory()->NewFixedArray( | 16558 isolate->factory()->NewFixedArray( |
| 16559 old_break_points->length() + | 16559 old_break_points->length() + |
| 16560 DebugInfo::kEstimatedNofBreakPointsInFunction); | 16560 DebugInfo::kEstimatedNofBreakPointsInFunction); |
| 16561 | 16561 |
| 16562 debug_info->set_break_points(*new_break_points); | 16562 debug_info->set_break_points(*new_break_points); |
| 16563 for (int i = 0; i < old_break_points->length(); i++) { | 16563 for (int i = 0; i < old_break_points->length(); i++) { |
| 16564 new_break_points->set(i, old_break_points->get(i)); | 16564 new_break_points->set(i, old_break_points->get(i)); |
| 16565 } | 16565 } |
| 16566 index = old_break_points->length(); | 16566 index = old_break_points->length(); |
| 16567 } | 16567 } |
| 16568 ASSERT(index != kNoBreakPointInfo); | 16568 DCHECK(index != kNoBreakPointInfo); |
| 16569 | 16569 |
| 16570 // Allocate new BreakPointInfo object and set the break point. | 16570 // Allocate new BreakPointInfo object and set the break point. |
| 16571 Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast( | 16571 Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast( |
| 16572 isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE)); | 16572 isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE)); |
| 16573 new_break_point_info->set_code_position(Smi::FromInt(code_position)); | 16573 new_break_point_info->set_code_position(Smi::FromInt(code_position)); |
| 16574 new_break_point_info->set_source_position(Smi::FromInt(source_position)); | 16574 new_break_point_info->set_source_position(Smi::FromInt(source_position)); |
| 16575 new_break_point_info-> | 16575 new_break_point_info-> |
| 16576 set_statement_position(Smi::FromInt(statement_position)); | 16576 set_statement_position(Smi::FromInt(statement_position)); |
| 16577 new_break_point_info->set_break_point_objects( | 16577 new_break_point_info->set_break_point_objects( |
| 16578 isolate->heap()->undefined_value()); | 16578 isolate->heap()->undefined_value()); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16650 if (break_point_info->break_point_objects()->IsUndefined()) return; | 16650 if (break_point_info->break_point_objects()->IsUndefined()) return; |
| 16651 // If there is a single break point clear it if it is the same. | 16651 // If there is a single break point clear it if it is the same. |
| 16652 if (!break_point_info->break_point_objects()->IsFixedArray()) { | 16652 if (!break_point_info->break_point_objects()->IsFixedArray()) { |
| 16653 if (break_point_info->break_point_objects() == *break_point_object) { | 16653 if (break_point_info->break_point_objects() == *break_point_object) { |
| 16654 break_point_info->set_break_point_objects( | 16654 break_point_info->set_break_point_objects( |
| 16655 isolate->heap()->undefined_value()); | 16655 isolate->heap()->undefined_value()); |
| 16656 } | 16656 } |
| 16657 return; | 16657 return; |
| 16658 } | 16658 } |
| 16659 // If there are multiple break points shrink the array | 16659 // If there are multiple break points shrink the array |
| 16660 ASSERT(break_point_info->break_point_objects()->IsFixedArray()); | 16660 DCHECK(break_point_info->break_point_objects()->IsFixedArray()); |
| 16661 Handle<FixedArray> old_array = | 16661 Handle<FixedArray> old_array = |
| 16662 Handle<FixedArray>( | 16662 Handle<FixedArray>( |
| 16663 FixedArray::cast(break_point_info->break_point_objects())); | 16663 FixedArray::cast(break_point_info->break_point_objects())); |
| 16664 Handle<FixedArray> new_array = | 16664 Handle<FixedArray> new_array = |
| 16665 isolate->factory()->NewFixedArray(old_array->length() - 1); | 16665 isolate->factory()->NewFixedArray(old_array->length() - 1); |
| 16666 int found_count = 0; | 16666 int found_count = 0; |
| 16667 for (int i = 0; i < old_array->length(); i++) { | 16667 for (int i = 0; i < old_array->length(); i++) { |
| 16668 if (old_array->get(i) == *break_point_object) { | 16668 if (old_array->get(i) == *break_point_object) { |
| 16669 ASSERT(found_count == 0); | 16669 DCHECK(found_count == 0); |
| 16670 found_count++; | 16670 found_count++; |
| 16671 } else { | 16671 } else { |
| 16672 new_array->set(i - found_count, old_array->get(i)); | 16672 new_array->set(i - found_count, old_array->get(i)); |
| 16673 } | 16673 } |
| 16674 } | 16674 } |
| 16675 // If the break point was found in the list change it. | 16675 // If the break point was found in the list change it. |
| 16676 if (found_count > 0) break_point_info->set_break_point_objects(*new_array); | 16676 if (found_count > 0) break_point_info->set_break_point_objects(*new_array); |
| 16677 } | 16677 } |
| 16678 | 16678 |
| 16679 | 16679 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16745 } | 16745 } |
| 16746 | 16746 |
| 16747 | 16747 |
| 16748 Object* JSDate::GetField(Object* object, Smi* index) { | 16748 Object* JSDate::GetField(Object* object, Smi* index) { |
| 16749 return JSDate::cast(object)->DoGetField( | 16749 return JSDate::cast(object)->DoGetField( |
| 16750 static_cast<FieldIndex>(index->value())); | 16750 static_cast<FieldIndex>(index->value())); |
| 16751 } | 16751 } |
| 16752 | 16752 |
| 16753 | 16753 |
| 16754 Object* JSDate::DoGetField(FieldIndex index) { | 16754 Object* JSDate::DoGetField(FieldIndex index) { |
| 16755 ASSERT(index != kDateValue); | 16755 DCHECK(index != kDateValue); |
| 16756 | 16756 |
| 16757 DateCache* date_cache = GetIsolate()->date_cache(); | 16757 DateCache* date_cache = GetIsolate()->date_cache(); |
| 16758 | 16758 |
| 16759 if (index < kFirstUncachedField) { | 16759 if (index < kFirstUncachedField) { |
| 16760 Object* stamp = cache_stamp(); | 16760 Object* stamp = cache_stamp(); |
| 16761 if (stamp != date_cache->stamp() && stamp->IsSmi()) { | 16761 if (stamp != date_cache->stamp() && stamp->IsSmi()) { |
| 16762 // Since the stamp is not NaN, the value is also not NaN. | 16762 // Since the stamp is not NaN, the value is also not NaN. |
| 16763 int64_t local_time_ms = | 16763 int64_t local_time_ms = |
| 16764 date_cache->ToLocal(static_cast<int64_t>(value()->Number())); | 16764 date_cache->ToLocal(static_cast<int64_t>(value()->Number())); |
| 16765 SetCachedFields(local_time_ms, date_cache); | 16765 SetCachedFields(local_time_ms, date_cache); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 16783 double time = value()->Number(); | 16783 double time = value()->Number(); |
| 16784 if (std::isnan(time)) return GetIsolate()->heap()->nan_value(); | 16784 if (std::isnan(time)) return GetIsolate()->heap()->nan_value(); |
| 16785 | 16785 |
| 16786 int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time)); | 16786 int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time)); |
| 16787 int days = DateCache::DaysFromTime(local_time_ms); | 16787 int days = DateCache::DaysFromTime(local_time_ms); |
| 16788 | 16788 |
| 16789 if (index == kDays) return Smi::FromInt(days); | 16789 if (index == kDays) return Smi::FromInt(days); |
| 16790 | 16790 |
| 16791 int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days); | 16791 int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days); |
| 16792 if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000); | 16792 if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000); |
| 16793 ASSERT(index == kTimeInDay); | 16793 DCHECK(index == kTimeInDay); |
| 16794 return Smi::FromInt(time_in_day_ms); | 16794 return Smi::FromInt(time_in_day_ms); |
| 16795 } | 16795 } |
| 16796 | 16796 |
| 16797 | 16797 |
| 16798 Object* JSDate::GetUTCField(FieldIndex index, | 16798 Object* JSDate::GetUTCField(FieldIndex index, |
| 16799 double value, | 16799 double value, |
| 16800 DateCache* date_cache) { | 16800 DateCache* date_cache) { |
| 16801 ASSERT(index >= kFirstUTCField); | 16801 DCHECK(index >= kFirstUTCField); |
| 16802 | 16802 |
| 16803 if (std::isnan(value)) return GetIsolate()->heap()->nan_value(); | 16803 if (std::isnan(value)) return GetIsolate()->heap()->nan_value(); |
| 16804 | 16804 |
| 16805 int64_t time_ms = static_cast<int64_t>(value); | 16805 int64_t time_ms = static_cast<int64_t>(value); |
| 16806 | 16806 |
| 16807 if (index == kTimezoneOffset) { | 16807 if (index == kTimezoneOffset) { |
| 16808 return Smi::FromInt(date_cache->TimezoneOffset(time_ms)); | 16808 return Smi::FromInt(date_cache->TimezoneOffset(time_ms)); |
| 16809 } | 16809 } |
| 16810 | 16810 |
| 16811 int days = DateCache::DaysFromTime(time_ms); | 16811 int days = DateCache::DaysFromTime(time_ms); |
| 16812 | 16812 |
| 16813 if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days)); | 16813 if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days)); |
| 16814 | 16814 |
| 16815 if (index <= kDayUTC) { | 16815 if (index <= kDayUTC) { |
| 16816 int year, month, day; | 16816 int year, month, day; |
| 16817 date_cache->YearMonthDayFromDays(days, &year, &month, &day); | 16817 date_cache->YearMonthDayFromDays(days, &year, &month, &day); |
| 16818 if (index == kYearUTC) return Smi::FromInt(year); | 16818 if (index == kYearUTC) return Smi::FromInt(year); |
| 16819 if (index == kMonthUTC) return Smi::FromInt(month); | 16819 if (index == kMonthUTC) return Smi::FromInt(month); |
| 16820 ASSERT(index == kDayUTC); | 16820 DCHECK(index == kDayUTC); |
| 16821 return Smi::FromInt(day); | 16821 return Smi::FromInt(day); |
| 16822 } | 16822 } |
| 16823 | 16823 |
| 16824 int time_in_day_ms = DateCache::TimeInDay(time_ms, days); | 16824 int time_in_day_ms = DateCache::TimeInDay(time_ms, days); |
| 16825 switch (index) { | 16825 switch (index) { |
| 16826 case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000)); | 16826 case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000)); |
| 16827 case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60); | 16827 case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60); |
| 16828 case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60); | 16828 case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60); |
| 16829 case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000); | 16829 case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000); |
| 16830 case kDaysUTC: return Smi::FromInt(days); | 16830 case kDaysUTC: return Smi::FromInt(days); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16869 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 16869 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
| 16870 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 16870 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
| 16871 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 16871 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
| 16872 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 16872 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
| 16873 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 16873 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
| 16874 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 16874 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| 16875 } | 16875 } |
| 16876 | 16876 |
| 16877 | 16877 |
| 16878 void JSArrayBuffer::Neuter() { | 16878 void JSArrayBuffer::Neuter() { |
| 16879 ASSERT(is_external()); | 16879 DCHECK(is_external()); |
| 16880 set_backing_store(NULL); | 16880 set_backing_store(NULL); |
| 16881 set_byte_length(Smi::FromInt(0)); | 16881 set_byte_length(Smi::FromInt(0)); |
| 16882 } | 16882 } |
| 16883 | 16883 |
| 16884 | 16884 |
| 16885 void JSArrayBufferView::NeuterView() { | 16885 void JSArrayBufferView::NeuterView() { |
| 16886 set_byte_offset(Smi::FromInt(0)); | 16886 set_byte_offset(Smi::FromInt(0)); |
| 16887 set_byte_length(Smi::FromInt(0)); | 16887 set_byte_length(Smi::FromInt(0)); |
| 16888 } | 16888 } |
| 16889 | 16889 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 16914 } | 16914 } |
| 16915 } | 16915 } |
| 16916 | 16916 |
| 16917 | 16917 |
| 16918 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer( | 16918 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer( |
| 16919 Handle<JSTypedArray> typed_array) { | 16919 Handle<JSTypedArray> typed_array) { |
| 16920 | 16920 |
| 16921 Handle<Map> map(typed_array->map()); | 16921 Handle<Map> map(typed_array->map()); |
| 16922 Isolate* isolate = typed_array->GetIsolate(); | 16922 Isolate* isolate = typed_array->GetIsolate(); |
| 16923 | 16923 |
| 16924 ASSERT(IsFixedTypedArrayElementsKind(map->elements_kind())); | 16924 DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind())); |
| 16925 | 16925 |
| 16926 Handle<Map> new_map = Map::TransitionElementsTo( | 16926 Handle<Map> new_map = Map::TransitionElementsTo( |
| 16927 map, | 16927 map, |
| 16928 FixedToExternalElementsKind(map->elements_kind())); | 16928 FixedToExternalElementsKind(map->elements_kind())); |
| 16929 | 16929 |
| 16930 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 16930 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
| 16931 Handle<FixedTypedArrayBase> fixed_typed_array( | 16931 Handle<FixedTypedArrayBase> fixed_typed_array( |
| 16932 FixedTypedArrayBase::cast(typed_array->elements())); | 16932 FixedTypedArrayBase::cast(typed_array->elements())); |
| 16933 Runtime::SetupArrayBufferAllocatingData(isolate, buffer, | 16933 Runtime::SetupArrayBufferAllocatingData(isolate, buffer, |
| 16934 fixed_typed_array->DataSize(), false); | 16934 fixed_typed_array->DataSize(), false); |
| 16935 memcpy(buffer->backing_store(), | 16935 memcpy(buffer->backing_store(), |
| 16936 fixed_typed_array->DataPtr(), | 16936 fixed_typed_array->DataPtr(), |
| 16937 fixed_typed_array->DataSize()); | 16937 fixed_typed_array->DataSize()); |
| 16938 Handle<ExternalArray> new_elements = | 16938 Handle<ExternalArray> new_elements = |
| 16939 isolate->factory()->NewExternalArray( | 16939 isolate->factory()->NewExternalArray( |
| 16940 fixed_typed_array->length(), typed_array->type(), | 16940 fixed_typed_array->length(), typed_array->type(), |
| 16941 static_cast<uint8_t*>(buffer->backing_store())); | 16941 static_cast<uint8_t*>(buffer->backing_store())); |
| 16942 | 16942 |
| 16943 buffer->set_weak_first_view(*typed_array); | 16943 buffer->set_weak_first_view(*typed_array); |
| 16944 ASSERT(typed_array->weak_next() == isolate->heap()->undefined_value()); | 16944 DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value()); |
| 16945 typed_array->set_buffer(*buffer); | 16945 typed_array->set_buffer(*buffer); |
| 16946 JSObject::SetMapAndElements(typed_array, new_map, new_elements); | 16946 JSObject::SetMapAndElements(typed_array, new_map, new_elements); |
| 16947 | 16947 |
| 16948 return buffer; | 16948 return buffer; |
| 16949 } | 16949 } |
| 16950 | 16950 |
| 16951 | 16951 |
| 16952 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() { | 16952 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() { |
| 16953 Handle<Object> result(buffer(), GetIsolate()); | 16953 Handle<Object> result(buffer(), GetIsolate()); |
| 16954 if (*result != Smi::FromInt(0)) { | 16954 if (*result != Smi::FromInt(0)) { |
| 16955 ASSERT(IsExternalArrayElementsKind(map()->elements_kind())); | 16955 DCHECK(IsExternalArrayElementsKind(map()->elements_kind())); |
| 16956 return Handle<JSArrayBuffer>::cast(result); | 16956 return Handle<JSArrayBuffer>::cast(result); |
| 16957 } | 16957 } |
| 16958 Handle<JSTypedArray> self(this); | 16958 Handle<JSTypedArray> self(this); |
| 16959 return MaterializeArrayBuffer(self); | 16959 return MaterializeArrayBuffer(self); |
| 16960 } | 16960 } |
| 16961 | 16961 |
| 16962 | 16962 |
| 16963 HeapType* PropertyCell::type() { | 16963 HeapType* PropertyCell::type() { |
| 16964 return static_cast<HeapType*>(type_raw()); | 16964 return static_cast<HeapType*>(type_raw()); |
| 16965 } | 16965 } |
| 16966 | 16966 |
| 16967 | 16967 |
| 16968 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) { | 16968 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) { |
| 16969 ASSERT(IsPropertyCell()); | 16969 DCHECK(IsPropertyCell()); |
| 16970 set_type_raw(type, ignored); | 16970 set_type_raw(type, ignored); |
| 16971 } | 16971 } |
| 16972 | 16972 |
| 16973 | 16973 |
| 16974 Handle<HeapType> PropertyCell::UpdatedType(Handle<PropertyCell> cell, | 16974 Handle<HeapType> PropertyCell::UpdatedType(Handle<PropertyCell> cell, |
| 16975 Handle<Object> value) { | 16975 Handle<Object> value) { |
| 16976 Isolate* isolate = cell->GetIsolate(); | 16976 Isolate* isolate = cell->GetIsolate(); |
| 16977 Handle<HeapType> old_type(cell->type(), isolate); | 16977 Handle<HeapType> old_type(cell->type(), isolate); |
| 16978 Handle<HeapType> new_type = HeapType::Constant(value, isolate); | 16978 Handle<HeapType> new_type = HeapType::Constant(value, isolate); |
| 16979 | 16979 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 17007 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), | 17007 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), |
| 17008 DependentCode::kPropertyCellChangedGroup, | 17008 DependentCode::kPropertyCellChangedGroup, |
| 17009 info->object_wrapper()); | 17009 info->object_wrapper()); |
| 17010 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17010 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
| 17011 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17011 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
| 17012 cell, info->zone()); | 17012 cell, info->zone()); |
| 17013 } | 17013 } |
| 17014 | 17014 |
| 17015 | 17015 |
| 17016 const char* GetBailoutReason(BailoutReason reason) { | 17016 const char* GetBailoutReason(BailoutReason reason) { |
| 17017 ASSERT(reason < kLastErrorMessage); | 17017 DCHECK(reason < kLastErrorMessage); |
| 17018 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17018 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 17019 static const char* error_messages_[] = { | 17019 static const char* error_messages_[] = { |
| 17020 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17020 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 17021 }; | 17021 }; |
| 17022 #undef ERROR_MESSAGES_TEXTS | 17022 #undef ERROR_MESSAGES_TEXTS |
| 17023 return error_messages_[reason]; | 17023 return error_messages_[reason]; |
| 17024 } | 17024 } |
| 17025 | 17025 |
| 17026 | 17026 |
| 17027 } } // namespace v8::internal | 17027 } } // namespace v8::internal |
| OLD | NEW |