| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 if (maybe_type->IsFailure()) return maybe_type; | 708 if (maybe_type->IsFailure()) return maybe_type; |
| 709 // Please note we have to update the property details. | 709 // Please note we have to update the property details. |
| 710 property_dictionary()->DetailsAtPut(entry, details); | 710 property_dictionary()->DetailsAtPut(entry, details); |
| 711 } else { | 711 } else { |
| 712 property_dictionary()->SetEntry(entry, name, value, details); | 712 property_dictionary()->SetEntry(entry, name, value, details); |
| 713 } | 713 } |
| 714 return value; | 714 return value; |
| 715 } | 715 } |
| 716 | 716 |
| 717 | 717 |
| 718 MaybeObject* JSObject::DeleteNormalizedProperty(Name* name, DeleteMode mode) { | 718 // TODO(mstarzinger): Temporary wrapper until target is handlified. |
| 719 ASSERT(!HasFastProperties()); | 719 Handle<NameDictionary> NameDictionaryShrink(Handle<NameDictionary> dict, |
| 720 NameDictionary* dictionary = property_dictionary(); | 720 Handle<Name> name) { |
| 721 int entry = dictionary->FindEntry(name); | 721 CALL_HEAP_FUNCTION(dict->GetIsolate(), dict->Shrink(*name), NameDictionary); |
| 722 } |
| 723 |
| 724 |
| 725 static void CellSetValueInferType(Handle<PropertyCell> cell, |
| 726 Handle<Object> value) { |
| 727 CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), cell->SetValueInferType(*value)); |
| 728 } |
| 729 |
| 730 |
| 731 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
| 732 Handle<Name> name, |
| 733 DeleteMode mode) { |
| 734 ASSERT(!object->HasFastProperties()); |
| 735 Isolate* isolate = object->GetIsolate(); |
| 736 Handle<NameDictionary> dictionary(object->property_dictionary()); |
| 737 int entry = dictionary->FindEntry(*name); |
| 722 if (entry != NameDictionary::kNotFound) { | 738 if (entry != NameDictionary::kNotFound) { |
| 723 // If we have a global object set the cell to the hole. | 739 // If we have a global object set the cell to the hole. |
| 724 if (IsGlobalObject()) { | 740 if (object->IsGlobalObject()) { |
| 725 PropertyDetails details = dictionary->DetailsAt(entry); | 741 PropertyDetails details = dictionary->DetailsAt(entry); |
| 726 if (details.IsDontDelete()) { | 742 if (details.IsDontDelete()) { |
| 727 if (mode != FORCE_DELETION) return GetHeap()->false_value(); | 743 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); |
| 728 // When forced to delete global properties, we have to make a | 744 // When forced to delete global properties, we have to make a |
| 729 // map change to invalidate any ICs that think they can load | 745 // map change to invalidate any ICs that think they can load |
| 730 // from the DontDelete cell without checking if it contains | 746 // from the DontDelete cell without checking if it contains |
| 731 // the hole value. | 747 // the hole value. |
| 732 Map* new_map; | 748 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 733 MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | |
| 734 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 735 | |
| 736 ASSERT(new_map->is_dictionary_map()); | 749 ASSERT(new_map->is_dictionary_map()); |
| 737 set_map(new_map); | 750 object->set_map(*new_map); |
| 738 } | 751 } |
| 739 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry)); | 752 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 740 MaybeObject* maybe_type = | 753 CellSetValueInferType(cell, isolate->factory()->the_hole_value()); |
| 741 cell->SetValueInferType(cell->GetHeap()->the_hole_value()); | |
| 742 if (maybe_type->IsFailure()) return maybe_type; | |
| 743 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 754 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| 744 } else { | 755 } else { |
| 745 Object* deleted = dictionary->DeleteProperty(entry, mode); | 756 Handle<Object> deleted(dictionary->DeleteProperty(entry, mode), isolate); |
| 746 if (deleted == GetHeap()->true_value()) { | 757 if (*deleted == isolate->heap()->true_value()) { |
| 747 FixedArray* new_properties = NULL; | 758 Handle<NameDictionary> new_properties = |
| 748 MaybeObject* maybe_properties = dictionary->Shrink(name); | 759 NameDictionaryShrink(dictionary, name); |
| 749 if (!maybe_properties->To(&new_properties)) { | 760 object->set_properties(*new_properties); |
| 750 return maybe_properties; | |
| 751 } | |
| 752 set_properties(new_properties); | |
| 753 } | 761 } |
| 754 return deleted; | 762 return deleted; |
| 755 } | 763 } |
| 756 } | 764 } |
| 757 return GetHeap()->true_value(); | 765 return isolate->factory()->true_value(); |
| 758 } | 766 } |
| 759 | 767 |
| 760 | 768 |
| 761 bool JSObject::IsDirty() { | 769 bool JSObject::IsDirty() { |
| 762 Object* cons_obj = map()->constructor(); | 770 Object* cons_obj = map()->constructor(); |
| 763 if (!cons_obj->IsJSFunction()) | 771 if (!cons_obj->IsJSFunction()) |
| 764 return true; | 772 return true; |
| 765 JSFunction* fun = JSFunction::cast(cons_obj); | 773 JSFunction* fun = JSFunction::cast(cons_obj); |
| 766 if (!fun->shared()->IsApiFunction()) | 774 if (!fun->shared()->IsApiFunction()) |
| 767 return true; | 775 return true; |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1328 double length = JSArray::cast(this)->length()->IsUndefined() | 1336 double length = JSArray::cast(this)->length()->IsUndefined() |
| 1329 ? 0 | 1337 ? 0 |
| 1330 : JSArray::cast(this)->length()->Number(); | 1338 : JSArray::cast(this)->length()->Number(); |
| 1331 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length)); | 1339 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length)); |
| 1332 break; | 1340 break; |
| 1333 } | 1341 } |
| 1334 case JS_WEAK_MAP_TYPE: { | 1342 case JS_WEAK_MAP_TYPE: { |
| 1335 accumulator->Add("<JS WeakMap>"); | 1343 accumulator->Add("<JS WeakMap>"); |
| 1336 break; | 1344 break; |
| 1337 } | 1345 } |
| 1346 case JS_WEAK_SET_TYPE: { |
| 1347 accumulator->Add("<JS WeakSet>"); |
| 1348 break; |
| 1349 } |
| 1338 case JS_REGEXP_TYPE: { | 1350 case JS_REGEXP_TYPE: { |
| 1339 accumulator->Add("<JS RegExp>"); | 1351 accumulator->Add("<JS RegExp>"); |
| 1340 break; | 1352 break; |
| 1341 } | 1353 } |
| 1342 case JS_FUNCTION_TYPE: { | 1354 case JS_FUNCTION_TYPE: { |
| 1343 JSFunction* function = JSFunction::cast(this); | 1355 JSFunction* function = JSFunction::cast(this); |
| 1344 Object* fun_name = function->shared()->DebugName(); | 1356 Object* fun_name = function->shared()->DebugName(); |
| 1345 bool printed = false; | 1357 bool printed = false; |
| 1346 if (fun_name->IsString()) { | 1358 if (fun_name->IsString()) { |
| 1347 String* str = String::cast(fun_name); | 1359 String* str = String::cast(fun_name); |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1638 case JS_MODULE_TYPE: | 1650 case JS_MODULE_TYPE: |
| 1639 case JS_VALUE_TYPE: | 1651 case JS_VALUE_TYPE: |
| 1640 case JS_DATE_TYPE: | 1652 case JS_DATE_TYPE: |
| 1641 case JS_ARRAY_TYPE: | 1653 case JS_ARRAY_TYPE: |
| 1642 case JS_ARRAY_BUFFER_TYPE: | 1654 case JS_ARRAY_BUFFER_TYPE: |
| 1643 case JS_TYPED_ARRAY_TYPE: | 1655 case JS_TYPED_ARRAY_TYPE: |
| 1644 case JS_DATA_VIEW_TYPE: | 1656 case JS_DATA_VIEW_TYPE: |
| 1645 case JS_SET_TYPE: | 1657 case JS_SET_TYPE: |
| 1646 case JS_MAP_TYPE: | 1658 case JS_MAP_TYPE: |
| 1647 case JS_WEAK_MAP_TYPE: | 1659 case JS_WEAK_MAP_TYPE: |
| 1660 case JS_WEAK_SET_TYPE: |
| 1648 case JS_REGEXP_TYPE: | 1661 case JS_REGEXP_TYPE: |
| 1649 case JS_GLOBAL_PROXY_TYPE: | 1662 case JS_GLOBAL_PROXY_TYPE: |
| 1650 case JS_GLOBAL_OBJECT_TYPE: | 1663 case JS_GLOBAL_OBJECT_TYPE: |
| 1651 case JS_BUILTINS_OBJECT_TYPE: | 1664 case JS_BUILTINS_OBJECT_TYPE: |
| 1652 case JS_MESSAGE_OBJECT_TYPE: | 1665 case JS_MESSAGE_OBJECT_TYPE: |
| 1653 JSObject::BodyDescriptor::IterateBody(this, object_size, v); | 1666 JSObject::BodyDescriptor::IterateBody(this, object_size, v); |
| 1654 break; | 1667 break; |
| 1655 case JS_FUNCTION_TYPE: | 1668 case JS_FUNCTION_TYPE: |
| 1656 reinterpret_cast<JSFunction*>(this) | 1669 reinterpret_cast<JSFunction*>(this) |
| 1657 ->JSFunctionIterateBody(object_size, v); | 1670 ->JSFunctionIterateBody(object_size, v); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 break; | 1712 break; |
| 1700 case SHARED_FUNCTION_INFO_TYPE: { | 1713 case SHARED_FUNCTION_INFO_TYPE: { |
| 1701 SharedFunctionInfo::BodyDescriptor::IterateBody(this, v); | 1714 SharedFunctionInfo::BodyDescriptor::IterateBody(this, v); |
| 1702 break; | 1715 break; |
| 1703 } | 1716 } |
| 1704 | 1717 |
| 1705 #define MAKE_STRUCT_CASE(NAME, Name, name) \ | 1718 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
| 1706 case NAME##_TYPE: | 1719 case NAME##_TYPE: |
| 1707 STRUCT_LIST(MAKE_STRUCT_CASE) | 1720 STRUCT_LIST(MAKE_STRUCT_CASE) |
| 1708 #undef MAKE_STRUCT_CASE | 1721 #undef MAKE_STRUCT_CASE |
| 1709 StructBodyDescriptor::IterateBody(this, object_size, v); | 1722 if (type == ALLOCATION_SITE_TYPE) { |
| 1723 AllocationSite::BodyDescriptor::IterateBody(this, v); |
| 1724 } else { |
| 1725 StructBodyDescriptor::IterateBody(this, object_size, v); |
| 1726 } |
| 1710 break; | 1727 break; |
| 1711 default: | 1728 default: |
| 1712 PrintF("Unknown type: %d\n", type); | 1729 PrintF("Unknown type: %d\n", type); |
| 1713 UNREACHABLE(); | 1730 UNREACHABLE(); |
| 1714 } | 1731 } |
| 1715 } | 1732 } |
| 1716 | 1733 |
| 1717 | 1734 |
| 1718 bool HeapNumber::HeapNumberBooleanValue() { | 1735 bool HeapNumber::HeapNumberBooleanValue() { |
| 1719 // NaN, +0, and -0 should return the false object | 1736 // NaN, +0, and -0 should return the false object |
| (...skipping 1804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3524 } | 3541 } |
| 3525 | 3542 |
| 3526 if (strict_mode == kNonStrictMode) return *value; | 3543 if (strict_mode == kNonStrictMode) return *value; |
| 3527 Handle<Object> args2[] = { name, proxy }; | 3544 Handle<Object> args2[] = { name, proxy }; |
| 3528 Handle<Object> error = isolate->factory()->NewTypeError( | 3545 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3529 "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2))); | 3546 "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2))); |
| 3530 return isolate->Throw(*error); | 3547 return isolate->Throw(*error); |
| 3531 } | 3548 } |
| 3532 | 3549 |
| 3533 | 3550 |
| 3534 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler( | 3551 Handle<Object> JSProxy::DeletePropertyWithHandler( |
| 3535 Name* name_raw, DeleteMode mode) { | 3552 Handle<JSProxy> object, Handle<Name> name, DeleteMode mode) { |
| 3536 Isolate* isolate = GetIsolate(); | 3553 Isolate* isolate = object->GetIsolate(); |
| 3537 HandleScope scope(isolate); | |
| 3538 Handle<JSProxy> receiver(this); | |
| 3539 Handle<Object> name(name_raw, isolate); | |
| 3540 | 3554 |
| 3541 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3555 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3542 if (name->IsSymbol()) return isolate->heap()->false_value(); | 3556 if (name->IsSymbol()) return isolate->factory()->false_value(); |
| 3543 | 3557 |
| 3544 Handle<Object> args[] = { name }; | 3558 Handle<Object> args[] = { name }; |
| 3545 Handle<Object> result = CallTrap( | 3559 Handle<Object> result = object->CallTrap( |
| 3546 "delete", Handle<Object>(), ARRAY_SIZE(args), args); | 3560 "delete", Handle<Object>(), ARRAY_SIZE(args), args); |
| 3547 if (isolate->has_pending_exception()) return Failure::Exception(); | 3561 if (isolate->has_pending_exception()) return Handle<Object>(); |
| 3548 | 3562 |
| 3549 bool result_bool = result->BooleanValue(); | 3563 bool result_bool = result->BooleanValue(); |
| 3550 if (mode == STRICT_DELETION && !result_bool) { | 3564 if (mode == STRICT_DELETION && !result_bool) { |
| 3551 Handle<Object> handler(receiver->handler(), isolate); | 3565 Handle<Object> handler(object->handler(), isolate); |
| 3552 Handle<String> trap_name = isolate->factory()->InternalizeOneByteString( | 3566 Handle<String> trap_name = isolate->factory()->InternalizeOneByteString( |
| 3553 STATIC_ASCII_VECTOR("delete")); | 3567 STATIC_ASCII_VECTOR("delete")); |
| 3554 Handle<Object> args[] = { handler, trap_name }; | 3568 Handle<Object> args[] = { handler, trap_name }; |
| 3555 Handle<Object> error = isolate->factory()->NewTypeError( | 3569 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3556 "handler_failed", HandleVector(args, ARRAY_SIZE(args))); | 3570 "handler_failed", HandleVector(args, ARRAY_SIZE(args))); |
| 3557 isolate->Throw(*error); | 3571 isolate->Throw(*error); |
| 3558 return Failure::Exception(); | 3572 return Handle<Object>(); |
| 3559 } | 3573 } |
| 3560 return isolate->heap()->ToBoolean(result_bool); | 3574 return isolate->factory()->ToBoolean(result_bool); |
| 3561 } | 3575 } |
| 3562 | 3576 |
| 3563 | 3577 |
| 3564 MUST_USE_RESULT MaybeObject* JSProxy::DeleteElementWithHandler( | 3578 Handle<Object> JSProxy::DeleteElementWithHandler( |
| 3565 uint32_t index, | 3579 Handle<JSProxy> object, uint32_t index, DeleteMode mode) { |
| 3566 DeleteMode mode) { | 3580 Isolate* isolate = object->GetIsolate(); |
| 3567 Isolate* isolate = GetIsolate(); | |
| 3568 HandleScope scope(isolate); | |
| 3569 Handle<String> name = isolate->factory()->Uint32ToString(index); | 3581 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 3570 return JSProxy::DeletePropertyWithHandler(*name, mode); | 3582 return JSProxy::DeletePropertyWithHandler(object, name, mode); |
| 3571 } | 3583 } |
| 3572 | 3584 |
| 3573 | 3585 |
| 3574 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( | 3586 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( |
| 3575 JSReceiver* receiver_raw, | 3587 JSReceiver* receiver_raw, |
| 3576 Name* name_raw) { | 3588 Name* name_raw) { |
| 3577 Isolate* isolate = GetIsolate(); | 3589 Isolate* isolate = GetIsolate(); |
| 3578 HandleScope scope(isolate); | 3590 HandleScope scope(isolate); |
| 3579 Handle<JSProxy> proxy(this); | 3591 Handle<JSProxy> proxy(this); |
| 3580 Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy. | 3592 Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3593 | 3605 |
| 3594 bool has_pending_exception; | 3606 bool has_pending_exception; |
| 3595 Handle<Object> argv[] = { result }; | 3607 Handle<Object> argv[] = { result }; |
| 3596 Handle<Object> desc = | 3608 Handle<Object> desc = |
| 3597 Execution::Call(isolate->to_complete_property_descriptor(), result, | 3609 Execution::Call(isolate->to_complete_property_descriptor(), result, |
| 3598 ARRAY_SIZE(argv), argv, &has_pending_exception); | 3610 ARRAY_SIZE(argv), argv, &has_pending_exception); |
| 3599 if (has_pending_exception) return NONE; | 3611 if (has_pending_exception) return NONE; |
| 3600 | 3612 |
| 3601 // Convert result to PropertyAttributes. | 3613 // Convert result to PropertyAttributes. |
| 3602 Handle<String> enum_n = isolate->factory()->InternalizeOneByteString( | 3614 Handle<String> enum_n = isolate->factory()->InternalizeOneByteString( |
| 3603 STATIC_ASCII_VECTOR("enumerable")); | 3615 STATIC_ASCII_VECTOR("enumerable_")); |
| 3604 Handle<Object> enumerable(v8::internal::GetProperty(isolate, desc, enum_n)); | 3616 Handle<Object> enumerable(v8::internal::GetProperty(isolate, desc, enum_n)); |
| 3605 if (isolate->has_pending_exception()) return NONE; | 3617 if (isolate->has_pending_exception()) return NONE; |
| 3606 Handle<String> conf_n = isolate->factory()->InternalizeOneByteString( | 3618 Handle<String> conf_n = isolate->factory()->InternalizeOneByteString( |
| 3607 STATIC_ASCII_VECTOR("configurable")); | 3619 STATIC_ASCII_VECTOR("configurable_")); |
| 3608 Handle<Object> configurable(v8::internal::GetProperty(isolate, desc, conf_n)); | 3620 Handle<Object> configurable(v8::internal::GetProperty(isolate, desc, conf_n)); |
| 3609 if (isolate->has_pending_exception()) return NONE; | 3621 if (isolate->has_pending_exception()) return NONE; |
| 3610 Handle<String> writ_n = isolate->factory()->InternalizeOneByteString( | 3622 Handle<String> writ_n = isolate->factory()->InternalizeOneByteString( |
| 3611 STATIC_ASCII_VECTOR("writable")); | 3623 STATIC_ASCII_VECTOR("writable_")); |
| 3612 Handle<Object> writable(v8::internal::GetProperty(isolate, desc, writ_n)); | 3624 Handle<Object> writable(v8::internal::GetProperty(isolate, desc, writ_n)); |
| 3613 if (isolate->has_pending_exception()) return NONE; | 3625 if (isolate->has_pending_exception()) return NONE; |
| 3626 if (!writable->BooleanValue()) { |
| 3627 Handle<String> set_n = isolate->factory()->InternalizeOneByteString( |
| 3628 STATIC_ASCII_VECTOR("set_")); |
| 3629 Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_n)); |
| 3630 if (isolate->has_pending_exception()) return NONE; |
| 3631 writable = isolate->factory()->ToBoolean(!setter->IsUndefined()); |
| 3632 } |
| 3614 | 3633 |
| 3615 if (configurable->IsFalse()) { | 3634 if (configurable->IsFalse()) { |
| 3616 Handle<String> trap = isolate->factory()->InternalizeOneByteString( | 3635 Handle<String> trap = isolate->factory()->InternalizeOneByteString( |
| 3617 STATIC_ASCII_VECTOR("getPropertyDescriptor")); | 3636 STATIC_ASCII_VECTOR("getPropertyDescriptor")); |
| 3618 Handle<Object> args[] = { handler, trap, name }; | 3637 Handle<Object> args[] = { handler, trap, name }; |
| 3619 Handle<Object> error = isolate->factory()->NewTypeError( | 3638 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3620 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); | 3639 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); |
| 3621 isolate->Throw(*error); | 3640 isolate->Throw(*error); |
| 3622 return NONE; | 3641 return NONE; |
| 3623 } | 3642 } |
| (...skipping 1337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4961 SetPropertyPostInterceptor(GetHeap()->hidden_string(), | 4980 SetPropertyPostInterceptor(GetHeap()->hidden_string(), |
| 4962 value, | 4981 value, |
| 4963 DONT_ENUM, | 4982 DONT_ENUM, |
| 4964 kNonStrictMode, | 4983 kNonStrictMode, |
| 4965 OMIT_EXTENSIBILITY_CHECK); | 4984 OMIT_EXTENSIBILITY_CHECK); |
| 4966 if (store_result->IsFailure()) return store_result; | 4985 if (store_result->IsFailure()) return store_result; |
| 4967 return this; | 4986 return this; |
| 4968 } | 4987 } |
| 4969 | 4988 |
| 4970 | 4989 |
| 4971 MaybeObject* JSObject::DeletePropertyPostInterceptor(Name* name, | 4990 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, |
| 4972 DeleteMode mode) { | 4991 Handle<Name> name, |
| 4992 DeleteMode mode) { |
| 4973 // Check local property, ignore interceptor. | 4993 // Check local property, ignore interceptor. |
| 4974 LookupResult result(GetIsolate()); | 4994 Isolate* isolate = object->GetIsolate(); |
| 4975 LocalLookupRealNamedProperty(name, &result); | 4995 LookupResult result(isolate); |
| 4976 if (!result.IsFound()) return GetHeap()->true_value(); | 4996 object->LocalLookupRealNamedProperty(*name, &result); |
| 4997 if (!result.IsFound()) return isolate->factory()->true_value(); |
| 4977 | 4998 |
| 4978 // Normalize object if needed. | 4999 // Normalize object if needed. |
| 4979 Object* obj; | 5000 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 4980 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | |
| 4981 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 4982 } | |
| 4983 | 5001 |
| 4984 return DeleteNormalizedProperty(name, mode); | 5002 return DeleteNormalizedProperty(object, name, mode); |
| 4985 } | 5003 } |
| 4986 | 5004 |
| 4987 | 5005 |
| 4988 MaybeObject* JSObject::DeletePropertyWithInterceptor(Name* name) { | 5006 Handle<Object> JSObject::DeletePropertyWithInterceptor(Handle<JSObject> object, |
| 5007 Handle<Name> name) { |
| 5008 Isolate* isolate = object->GetIsolate(); |
| 5009 |
| 4989 // TODO(rossberg): Support symbols in the API. | 5010 // TODO(rossberg): Support symbols in the API. |
| 4990 if (name->IsSymbol()) return GetHeap()->false_value(); | 5011 if (name->IsSymbol()) return isolate->factory()->false_value(); |
| 4991 | 5012 |
| 4992 Isolate* isolate = GetIsolate(); | 5013 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |
| 4993 HandleScope scope(isolate); | |
| 4994 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | |
| 4995 Handle<String> name_handle(String::cast(name)); | |
| 4996 Handle<JSObject> this_handle(this); | |
| 4997 if (!interceptor->deleter()->IsUndefined()) { | 5014 if (!interceptor->deleter()->IsUndefined()) { |
| 4998 v8::NamedPropertyDeleter deleter = | 5015 v8::NamedPropertyDeleter deleter = |
| 4999 v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter()); | 5016 v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter()); |
| 5000 LOG(isolate, | 5017 LOG(isolate, |
| 5001 ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name)); | 5018 ApiNamedPropertyAccess("interceptor-named-delete", *object, *name)); |
| 5002 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); | 5019 PropertyCallbackArguments args( |
| 5020 isolate, interceptor->data(), *object, *object); |
| 5003 v8::Handle<v8::Boolean> result = | 5021 v8::Handle<v8::Boolean> result = |
| 5004 args.Call(deleter, v8::Utils::ToLocal(name_handle)); | 5022 args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name))); |
| 5005 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 5023 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5006 if (!result.IsEmpty()) { | 5024 if (!result.IsEmpty()) { |
| 5007 ASSERT(result->IsBoolean()); | 5025 ASSERT(result->IsBoolean()); |
| 5008 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 5026 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| 5009 result_internal->VerifyApiCallResultType(); | 5027 result_internal->VerifyApiCallResultType(); |
| 5010 return *result_internal; | 5028 // Rebox CustomArguments::kReturnValueOffset before returning. |
| 5029 return handle(*result_internal, isolate); |
| 5011 } | 5030 } |
| 5012 } | 5031 } |
| 5013 MaybeObject* raw_result = | 5032 Handle<Object> result = |
| 5014 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); | 5033 DeletePropertyPostInterceptor(object, name, NORMAL_DELETION); |
| 5015 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 5034 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5016 return raw_result; | 5035 return result; |
| 5017 } | 5036 } |
| 5018 | 5037 |
| 5019 | 5038 |
| 5020 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { | 5039 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { |
| 5021 Isolate* isolate = GetIsolate(); | 5040 Isolate* isolate = GetIsolate(); |
| 5022 Heap* heap = isolate->heap(); | 5041 Heap* heap = isolate->heap(); |
| 5023 // Make sure that the top context does not change when doing | 5042 // Make sure that the top context does not change when doing |
| 5024 // callbacks or interceptor calls. | 5043 // callbacks or interceptor calls. |
| 5025 AssertNoContextChange ncc; | 5044 AssertNoContextChange ncc; |
| 5026 HandleScope scope(isolate); | 5045 HandleScope scope(isolate); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5043 MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete( | 5062 MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete( |
| 5044 *this_handle, | 5063 *this_handle, |
| 5045 index, | 5064 index, |
| 5046 NORMAL_DELETION); | 5065 NORMAL_DELETION); |
| 5047 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 5066 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 5048 return raw_result; | 5067 return raw_result; |
| 5049 } | 5068 } |
| 5050 | 5069 |
| 5051 | 5070 |
| 5052 Handle<Object> JSObject::DeleteElement(Handle<JSObject> obj, | 5071 Handle<Object> JSObject::DeleteElement(Handle<JSObject> obj, |
| 5053 uint32_t index) { | 5072 uint32_t index, |
| 5073 DeleteMode mode) { |
| 5054 CALL_HEAP_FUNCTION(obj->GetIsolate(), | 5074 CALL_HEAP_FUNCTION(obj->GetIsolate(), |
| 5055 obj->DeleteElement(index, JSObject::NORMAL_DELETION), | 5075 obj->DeleteElement(index, mode), |
| 5056 Object); | 5076 Object); |
| 5057 } | 5077 } |
| 5058 | 5078 |
| 5059 | 5079 |
| 5060 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { | 5080 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { |
| 5061 Isolate* isolate = GetIsolate(); | 5081 Isolate* isolate = GetIsolate(); |
| 5062 // Check access rights if needed. | 5082 // Check access rights if needed. |
| 5063 if (IsAccessCheckNeeded() && | 5083 if (IsAccessCheckNeeded() && |
| 5064 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { | 5084 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { |
| 5065 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); | 5085 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5117 | 5137 |
| 5118 if (should_enqueue_change_record && !self->HasLocalElement(index)) { | 5138 if (should_enqueue_change_record && !self->HasLocalElement(index)) { |
| 5119 Handle<String> name = isolate->factory()->Uint32ToString(index); | 5139 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 5120 EnqueueChangeRecord(self, "deleted", name, old_value); | 5140 EnqueueChangeRecord(self, "deleted", name, old_value); |
| 5121 } | 5141 } |
| 5122 | 5142 |
| 5123 return *hresult; | 5143 return *hresult; |
| 5124 } | 5144 } |
| 5125 | 5145 |
| 5126 | 5146 |
| 5127 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj, | 5147 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
| 5128 Handle<Name> prop) { | 5148 Handle<Name> name, |
| 5129 CALL_HEAP_FUNCTION(obj->GetIsolate(), | 5149 DeleteMode mode) { |
| 5130 obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION), | 5150 Isolate* isolate = object->GetIsolate(); |
| 5131 Object); | |
| 5132 } | |
| 5133 | |
| 5134 | |
| 5135 MaybeObject* JSObject::DeleteProperty(Name* name, DeleteMode mode) { | |
| 5136 Isolate* isolate = GetIsolate(); | |
| 5137 // ECMA-262, 3rd, 8.6.2.5 | 5151 // ECMA-262, 3rd, 8.6.2.5 |
| 5138 ASSERT(name->IsName()); | 5152 ASSERT(name->IsName()); |
| 5139 | 5153 |
| 5140 // Check access rights if needed. | 5154 // Check access rights if needed. |
| 5141 if (IsAccessCheckNeeded() && | 5155 if (object->IsAccessCheckNeeded() && |
| 5142 !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) { | 5156 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_DELETE)) { |
| 5143 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); | 5157 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_DELETE); |
| 5144 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 5158 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5145 return isolate->heap()->false_value(); | 5159 return isolate->factory()->false_value(); |
| 5146 } | 5160 } |
| 5147 | 5161 |
| 5148 if (IsJSGlobalProxy()) { | 5162 if (object->IsJSGlobalProxy()) { |
| 5149 Object* proto = GetPrototype(); | 5163 Object* proto = object->GetPrototype(); |
| 5150 if (proto->IsNull()) return isolate->heap()->false_value(); | 5164 if (proto->IsNull()) return isolate->factory()->false_value(); |
| 5151 ASSERT(proto->IsJSGlobalObject()); | 5165 ASSERT(proto->IsJSGlobalObject()); |
| 5152 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); | 5166 return JSGlobalObject::DeleteProperty( |
| 5167 handle(JSGlobalObject::cast(proto)), name, mode); |
| 5153 } | 5168 } |
| 5154 | 5169 |
| 5155 uint32_t index = 0; | 5170 uint32_t index = 0; |
| 5156 if (name->AsArrayIndex(&index)) { | 5171 if (name->AsArrayIndex(&index)) { |
| 5157 return DeleteElement(index, mode); | 5172 return DeleteElement(object, index, mode); |
| 5158 } | 5173 } |
| 5159 | 5174 |
| 5160 LookupResult lookup(isolate); | 5175 LookupResult lookup(isolate); |
| 5161 LocalLookup(name, &lookup, true); | 5176 object->LocalLookup(*name, &lookup, true); |
| 5162 if (!lookup.IsFound()) return isolate->heap()->true_value(); | 5177 if (!lookup.IsFound()) return isolate->factory()->true_value(); |
| 5163 // Ignore attributes if forcing a deletion. | 5178 // Ignore attributes if forcing a deletion. |
| 5164 if (lookup.IsDontDelete() && mode != FORCE_DELETION) { | 5179 if (lookup.IsDontDelete() && mode != FORCE_DELETION) { |
| 5165 if (mode == STRICT_DELETION) { | 5180 if (mode == STRICT_DELETION) { |
| 5166 // Deleting a non-configurable property in strict mode. | 5181 // Deleting a non-configurable property in strict mode. |
| 5167 HandleScope scope(isolate); | 5182 Handle<Object> args[2] = { name, object }; |
| 5168 Handle<Object> args[2] = { Handle<Object>(name, isolate), | 5183 Handle<Object> error = isolate->factory()->NewTypeError( |
| 5169 Handle<Object>(this, isolate) }; | 5184 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); |
| 5170 return isolate->Throw(*isolate->factory()->NewTypeError( | 5185 isolate->Throw(*error); |
| 5171 "strict_delete_property", HandleVector(args, 2))); | 5186 return Handle<Object>(); |
| 5172 } | 5187 } |
| 5173 return isolate->heap()->false_value(); | 5188 return isolate->factory()->false_value(); |
| 5174 } | 5189 } |
| 5175 | 5190 |
| 5176 // From this point on everything needs to be handlified. | |
| 5177 HandleScope scope(isolate); | |
| 5178 Handle<JSObject> self(this); | |
| 5179 Handle<Name> hname(name); | |
| 5180 | |
| 5181 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 5191 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 5182 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); | 5192 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); |
| 5183 if (is_observed && lookup.IsDataProperty()) { | 5193 if (is_observed && lookup.IsDataProperty()) { |
| 5184 old_value = Object::GetProperty(self, hname); | 5194 old_value = Object::GetProperty(object, name); |
| 5185 } | 5195 } |
| 5186 MaybeObject* result; | 5196 Handle<Object> result; |
| 5187 | 5197 |
| 5188 // Check for interceptor. | 5198 // Check for interceptor. |
| 5189 if (lookup.IsInterceptor()) { | 5199 if (lookup.IsInterceptor()) { |
| 5190 // Skip interceptor if forcing a deletion. | 5200 // Skip interceptor if forcing a deletion. |
| 5191 if (mode == FORCE_DELETION) { | 5201 if (mode == FORCE_DELETION) { |
| 5192 result = self->DeletePropertyPostInterceptor(*hname, mode); | 5202 result = DeletePropertyPostInterceptor(object, name, mode); |
| 5193 } else { | 5203 } else { |
| 5194 result = self->DeletePropertyWithInterceptor(*hname); | 5204 result = DeletePropertyWithInterceptor(object, name); |
| 5195 } | 5205 } |
| 5196 } else { | 5206 } else { |
| 5197 // Normalize object if needed. | 5207 // Normalize object if needed. |
| 5198 Object* obj; | 5208 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 5199 result = self->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | |
| 5200 if (!result->To(&obj)) return result; | |
| 5201 // Make sure the properties are normalized before removing the entry. | 5209 // Make sure the properties are normalized before removing the entry. |
| 5202 result = self->DeleteNormalizedProperty(*hname, mode); | 5210 result = DeleteNormalizedProperty(object, name, mode); |
| 5203 } | 5211 } |
| 5204 | 5212 |
| 5205 Handle<Object> hresult; | 5213 if (is_observed && !object->HasLocalProperty(*name)) { |
| 5206 if (!result->ToHandle(&hresult, isolate)) return result; | 5214 EnqueueChangeRecord(object, "deleted", name, old_value); |
| 5207 | |
| 5208 if (is_observed && !self->HasLocalProperty(*hname)) { | |
| 5209 EnqueueChangeRecord(self, "deleted", hname, old_value); | |
| 5210 } | 5215 } |
| 5211 | 5216 |
| 5212 return *hresult; | 5217 return result; |
| 5213 } | 5218 } |
| 5214 | 5219 |
| 5215 | 5220 |
| 5216 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { | 5221 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, |
| 5217 if (IsJSProxy()) { | 5222 uint32_t index, |
| 5218 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); | 5223 DeleteMode mode) { |
| 5224 if (object->IsJSProxy()) { |
| 5225 return JSProxy::DeleteElementWithHandler( |
| 5226 Handle<JSProxy>::cast(object), index, mode); |
| 5219 } | 5227 } |
| 5220 return JSObject::cast(this)->DeleteElement(index, mode); | 5228 return JSObject::DeleteElement(Handle<JSObject>::cast(object), index, mode); |
| 5221 } | 5229 } |
| 5222 | 5230 |
| 5223 | 5231 |
| 5224 MaybeObject* JSReceiver::DeleteProperty(Name* name, DeleteMode mode) { | 5232 Handle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object, |
| 5225 if (IsJSProxy()) { | 5233 Handle<Name> name, |
| 5226 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); | 5234 DeleteMode mode) { |
| 5235 if (object->IsJSProxy()) { |
| 5236 return JSProxy::DeletePropertyWithHandler( |
| 5237 Handle<JSProxy>::cast(object), name, mode); |
| 5227 } | 5238 } |
| 5228 return JSObject::cast(this)->DeleteProperty(name, mode); | 5239 return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, mode); |
| 5229 } | 5240 } |
| 5230 | 5241 |
| 5231 | 5242 |
| 5232 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 5243 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
| 5233 ElementsKind kind, | 5244 ElementsKind kind, |
| 5234 Object* object) { | 5245 Object* object) { |
| 5235 ASSERT(IsFastObjectElementsKind(kind) || | 5246 ASSERT(IsFastObjectElementsKind(kind) || |
| 5236 kind == DICTIONARY_ELEMENTS); | 5247 kind == DICTIONARY_ELEMENTS); |
| 5237 if (IsFastObjectElementsKind(kind)) { | 5248 if (IsFastObjectElementsKind(kind)) { |
| 5238 int length = IsJSArray() | 5249 int length = IsJSArray() |
| (...skipping 1261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6500 #ifdef VERIFY_HEAP | 6511 #ifdef VERIFY_HEAP |
| 6501 if (FLAG_verify_heap && result->is_shared()) { | 6512 if (FLAG_verify_heap && result->is_shared()) { |
| 6502 result->SharedMapVerify(); | 6513 result->SharedMapVerify(); |
| 6503 } | 6514 } |
| 6504 #endif | 6515 #endif |
| 6505 | 6516 |
| 6506 return result; | 6517 return result; |
| 6507 } | 6518 } |
| 6508 | 6519 |
| 6509 | 6520 |
| 6521 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) { |
| 6522 CALL_HEAP_FUNCTION(map->GetIsolate(), map->CopyDropDescriptors(), Map); |
| 6523 } |
| 6524 |
| 6525 |
| 6510 MaybeObject* Map::CopyDropDescriptors() { | 6526 MaybeObject* Map::CopyDropDescriptors() { |
| 6511 Map* result; | 6527 Map* result; |
| 6512 MaybeObject* maybe_result = RawCopy(instance_size()); | 6528 MaybeObject* maybe_result = RawCopy(instance_size()); |
| 6513 if (!maybe_result->To(&result)) return maybe_result; | 6529 if (!maybe_result->To(&result)) return maybe_result; |
| 6514 | 6530 |
| 6515 // Please note instance_type and instance_size are set when allocated. | 6531 // Please note instance_type and instance_size are set when allocated. |
| 6516 result->set_inobject_properties(inobject_properties()); | 6532 result->set_inobject_properties(inobject_properties()); |
| 6517 result->set_unused_property_fields(unused_property_fields()); | 6533 result->set_unused_property_fields(unused_property_fields()); |
| 6518 | 6534 |
| 6519 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); | 6535 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); |
| (...skipping 2389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8909 if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) { | 8925 if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) { |
| 8910 MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta); | 8926 MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta); |
| 8911 } | 8927 } |
| 8912 | 8928 |
| 8913 | 8929 |
| 8914 if (new_length == 0) return heap->isolate()->factory()->empty_string(); | 8930 if (new_length == 0) return heap->isolate()->factory()->empty_string(); |
| 8915 return string; | 8931 return string; |
| 8916 } | 8932 } |
| 8917 | 8933 |
| 8918 | 8934 |
| 8919 AllocationSiteInfo* AllocationSiteInfo::FindForJSObject(JSObject* object) { | 8935 AllocationMemento* AllocationMemento::FindForJSObject(JSObject* object) { |
| 8920 // Currently, AllocationSiteInfo objects are only allocated immediately | 8936 // Currently, AllocationMemento objects are only allocated immediately |
| 8921 // after JSArrays in NewSpace, and detecting whether a JSArray has one | 8937 // after JSArrays in NewSpace, and detecting whether a JSArray has one |
| 8922 // involves carefully checking the object immediately after the JSArray | 8938 // involves carefully checking the object immediately after the JSArray |
| 8923 // (if there is one) to see if it's an AllocationSiteInfo. | 8939 // (if there is one) to see if it's an AllocationMemento. |
| 8924 if (FLAG_track_allocation_sites && object->GetHeap()->InNewSpace(object)) { | 8940 if (FLAG_track_allocation_sites && object->GetHeap()->InNewSpace(object)) { |
| 8925 Address ptr_end = (reinterpret_cast<Address>(object) - kHeapObjectTag) + | 8941 Address ptr_end = (reinterpret_cast<Address>(object) - kHeapObjectTag) + |
| 8926 object->Size(); | 8942 object->Size(); |
| 8927 if ((ptr_end + AllocationSiteInfo::kSize) <= | 8943 if ((ptr_end + AllocationMemento::kSize) <= |
| 8928 object->GetHeap()->NewSpaceTop()) { | 8944 object->GetHeap()->NewSpaceTop()) { |
| 8929 // There is room in newspace for allocation info. Do we have some? | 8945 // There is room in newspace for allocation info. Do we have some? |
| 8930 Map** possible_allocation_site_info_map = | 8946 Map** possible_allocation_memento_map = |
| 8931 reinterpret_cast<Map**>(ptr_end); | 8947 reinterpret_cast<Map**>(ptr_end); |
| 8932 if (*possible_allocation_site_info_map == | 8948 if (*possible_allocation_memento_map == |
| 8933 object->GetHeap()->allocation_site_info_map()) { | 8949 object->GetHeap()->allocation_memento_map()) { |
| 8934 AllocationSiteInfo* info = AllocationSiteInfo::cast( | 8950 AllocationMemento* memento = AllocationMemento::cast( |
| 8935 reinterpret_cast<Object*>(ptr_end + 1)); | 8951 reinterpret_cast<Object*>(ptr_end + 1)); |
| 8936 return info; | 8952 return memento; |
| 8937 } | 8953 } |
| 8938 } | 8954 } |
| 8939 } | 8955 } |
| 8940 return NULL; | 8956 return NULL; |
| 8941 } | 8957 } |
| 8942 | 8958 |
| 8943 | 8959 |
| 8944 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { | 8960 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { |
| 8945 // For array indexes mix the length into the hash as an array index could | 8961 // For array indexes mix the length into the hash as an array index could |
| 8946 // be zero. | 8962 // be zero. |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9521 | 9537 |
| 9522 | 9538 |
| 9523 Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context, | 9539 Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context, |
| 9524 Handle<Map> initial_map) { | 9540 Handle<Map> initial_map) { |
| 9525 CALL_HEAP_FUNCTION(native_context->GetIsolate(), | 9541 CALL_HEAP_FUNCTION(native_context->GetIsolate(), |
| 9526 CacheInitialJSArrayMaps(*native_context, *initial_map), | 9542 CacheInitialJSArrayMaps(*native_context, *initial_map), |
| 9527 Object); | 9543 Object); |
| 9528 } | 9544 } |
| 9529 | 9545 |
| 9530 | 9546 |
| 9531 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { | 9547 void JSFunction::SetInstancePrototype(Handle<JSFunction> function, |
| 9548 Handle<Object> value) { |
| 9532 ASSERT(value->IsJSReceiver()); | 9549 ASSERT(value->IsJSReceiver()); |
| 9533 Heap* heap = GetHeap(); | |
| 9534 | 9550 |
| 9535 // First some logic for the map of the prototype to make sure it is in fast | 9551 // First some logic for the map of the prototype to make sure it is in fast |
| 9536 // mode. | 9552 // mode. |
| 9537 if (value->IsJSObject()) { | 9553 if (value->IsJSObject()) { |
| 9538 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); | 9554 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); |
| 9539 if (ok->IsFailure()) return ok; | |
| 9540 } | 9555 } |
| 9541 | 9556 |
| 9542 // Now some logic for the maps of the objects that are created by using this | 9557 // Now some logic for the maps of the objects that are created by using this |
| 9543 // function as a constructor. | 9558 // function as a constructor. |
| 9544 if (has_initial_map()) { | 9559 if (function->has_initial_map()) { |
| 9545 // If the function has allocated the initial map replace it with a | 9560 // If the function has allocated the initial map replace it with a |
| 9546 // copy containing the new prototype. Also complete any in-object | 9561 // copy containing the new prototype. Also complete any in-object |
| 9547 // slack tracking that is in progress at this point because it is | 9562 // slack tracking that is in progress at this point because it is |
| 9548 // still tracking the old copy. | 9563 // still tracking the old copy. |
| 9549 if (shared()->IsInobjectSlackTrackingInProgress()) { | 9564 if (function->shared()->IsInobjectSlackTrackingInProgress()) { |
| 9550 shared()->CompleteInobjectSlackTracking(); | 9565 function->shared()->CompleteInobjectSlackTracking(); |
| 9551 } | 9566 } |
| 9552 Map* new_map; | 9567 Handle<Map> new_map = Map::Copy(handle(function->initial_map())); |
| 9553 MaybeObject* maybe_object = initial_map()->Copy(); | 9568 new_map->set_prototype(*value); |
| 9554 if (!maybe_object->To(&new_map)) return maybe_object; | |
| 9555 new_map->set_prototype(value); | |
| 9556 | 9569 |
| 9557 // If the function is used as the global Array function, cache the | 9570 // If the function is used as the global Array function, cache the |
| 9558 // initial map (and transitioned versions) in the native context. | 9571 // initial map (and transitioned versions) in the native context. |
| 9559 Context* native_context = context()->native_context(); | 9572 Context* native_context = function->context()->native_context(); |
| 9560 Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX); | 9573 Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX); |
| 9561 if (array_function->IsJSFunction() && | 9574 if (array_function->IsJSFunction() && |
| 9562 this == JSFunction::cast(array_function)) { | 9575 *function == JSFunction::cast(array_function)) { |
| 9563 MaybeObject* ok = CacheInitialJSArrayMaps(native_context, new_map); | 9576 CacheInitialJSArrayMaps(handle(native_context), new_map); |
| 9564 if (ok->IsFailure()) return ok; | |
| 9565 } | 9577 } |
| 9566 | 9578 |
| 9567 set_initial_map(new_map); | 9579 function->set_initial_map(*new_map); |
| 9568 } else { | 9580 } else { |
| 9569 // Put the value in the initial map field until an initial map is | 9581 // Put the value in the initial map field until an initial map is |
| 9570 // needed. At that point, a new initial map is created and the | 9582 // needed. At that point, a new initial map is created and the |
| 9571 // prototype is put into the initial map where it belongs. | 9583 // prototype is put into the initial map where it belongs. |
| 9572 set_prototype_or_initial_map(value); | 9584 function->set_prototype_or_initial_map(*value); |
| 9573 } | 9585 } |
| 9574 heap->ClearInstanceofCache(); | 9586 function->GetHeap()->ClearInstanceofCache(); |
| 9575 return value; | |
| 9576 } | 9587 } |
| 9577 | 9588 |
| 9578 | 9589 |
| 9579 MaybeObject* JSFunction::SetPrototype(Object* value) { | 9590 void JSFunction::SetPrototype(Handle<JSFunction> function, |
| 9580 ASSERT(should_have_prototype()); | 9591 Handle<Object> value) { |
| 9581 Object* construct_prototype = value; | 9592 ASSERT(function->should_have_prototype()); |
| 9593 Handle<Object> construct_prototype = value; |
| 9582 | 9594 |
| 9583 // If the value is not a JSReceiver, store the value in the map's | 9595 // If the value is not a JSReceiver, store the value in the map's |
| 9584 // constructor field so it can be accessed. Also, set the prototype | 9596 // constructor field so it can be accessed. Also, set the prototype |
| 9585 // used for constructing objects to the original object prototype. | 9597 // used for constructing objects to the original object prototype. |
| 9586 // See ECMA-262 13.2.2. | 9598 // See ECMA-262 13.2.2. |
| 9587 if (!value->IsJSReceiver()) { | 9599 if (!value->IsJSReceiver()) { |
| 9588 // Copy the map so this does not affect unrelated functions. | 9600 // Copy the map so this does not affect unrelated functions. |
| 9589 // Remove map transitions because they point to maps with a | 9601 // Remove map transitions because they point to maps with a |
| 9590 // different prototype. | 9602 // different prototype. |
| 9591 Map* new_map; | 9603 Handle<Map> new_map = Map::Copy(handle(function->map())); |
| 9592 MaybeObject* maybe_new_map = map()->Copy(); | |
| 9593 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 9594 | 9604 |
| 9595 Heap* heap = new_map->GetHeap(); | 9605 function->set_map(*new_map); |
| 9596 set_map(new_map); | 9606 new_map->set_constructor(*value); |
| 9597 new_map->set_constructor(value); | |
| 9598 new_map->set_non_instance_prototype(true); | 9607 new_map->set_non_instance_prototype(true); |
| 9599 construct_prototype = | 9608 Isolate* isolate = new_map->GetIsolate(); |
| 9600 heap->isolate()->context()->native_context()-> | 9609 construct_prototype = handle( |
| 9601 initial_object_prototype(); | 9610 isolate->context()->native_context()->initial_object_prototype(), |
| 9611 isolate); |
| 9602 } else { | 9612 } else { |
| 9603 map()->set_non_instance_prototype(false); | 9613 function->map()->set_non_instance_prototype(false); |
| 9604 } | 9614 } |
| 9605 | 9615 |
| 9606 return SetInstancePrototype(construct_prototype); | 9616 return SetInstancePrototype(function, construct_prototype); |
| 9607 } | 9617 } |
| 9608 | 9618 |
| 9609 | 9619 |
| 9610 void JSFunction::RemovePrototype() { | 9620 void JSFunction::RemovePrototype() { |
| 9611 Context* native_context = context()->native_context(); | 9621 Context* native_context = context()->native_context(); |
| 9612 Map* no_prototype_map = shared()->is_classic_mode() | 9622 Map* no_prototype_map = shared()->is_classic_mode() |
| 9613 ? native_context->function_without_prototype_map() | 9623 ? native_context->function_without_prototype_map() |
| 9614 : native_context->strict_mode_function_without_prototype_map(); | 9624 : native_context->strict_mode_function_without_prototype_map(); |
| 9615 | 9625 |
| 9616 if (map() == no_prototype_map) return; | 9626 if (map() == no_prototype_map) return; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 9635 } | 9645 } |
| 9636 | 9646 |
| 9637 | 9647 |
| 9638 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) { | 9648 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) { |
| 9639 return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex)); | 9649 return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex)); |
| 9640 } | 9650 } |
| 9641 | 9651 |
| 9642 | 9652 |
| 9643 bool JSFunction::PassesHydrogenFilter() { | 9653 bool JSFunction::PassesHydrogenFilter() { |
| 9644 String* name = shared()->DebugName(); | 9654 String* name = shared()->DebugName(); |
| 9645 if (*FLAG_hydrogen_filter != '\0') { | 9655 // The filter string is a pattern that matches functions in this way: |
| 9656 // "*" all; the default |
| 9657 // "-" all but the top-level function |
| 9658 // "-name" all but the function "name" |
| 9659 // "" only the top-level function |
| 9660 // "name" only the function "name" |
| 9661 // "name*" only functions starting with "name" |
| 9662 if (*FLAG_hydrogen_filter != '*') { |
| 9646 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter); | 9663 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter); |
| 9664 if (filter.length() == 0) return name->length() == 0; |
| 9647 if (filter[0] != '-' && name->IsUtf8EqualTo(filter)) return true; | 9665 if (filter[0] != '-' && name->IsUtf8EqualTo(filter)) return true; |
| 9648 if (filter[0] == '-' && | 9666 if (filter[0] == '-' && |
| 9649 !name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) { | 9667 !name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) { |
| 9650 return true; | 9668 return true; |
| 9651 } | 9669 } |
| 9652 if (filter[filter.length() - 1] == '*' && | 9670 if (filter[filter.length() - 1] == '*' && |
| 9653 name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) { | 9671 name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) { |
| 9654 return true; | 9672 return true; |
| 9655 } | 9673 } |
| 9656 return false; | 9674 return false; |
| (...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10779 // If there is no back edge table, the "table start" will be at or after | 10797 // If there is no back edge table, the "table start" will be at or after |
| 10780 // (due to alignment) the end of the instruction stream. | 10798 // (due to alignment) the end of the instruction stream. |
| 10781 if (static_cast<int>(offset) < instruction_size()) { | 10799 if (static_cast<int>(offset) < instruction_size()) { |
| 10782 Address back_edge_cursor = instruction_start() + offset; | 10800 Address back_edge_cursor = instruction_start() + offset; |
| 10783 uint32_t table_length = Memory::uint32_at(back_edge_cursor); | 10801 uint32_t table_length = Memory::uint32_at(back_edge_cursor); |
| 10784 PrintF(out, "Back edges (size = %u)\n", table_length); | 10802 PrintF(out, "Back edges (size = %u)\n", table_length); |
| 10785 PrintF(out, "ast_id pc_offset loop_depth\n"); | 10803 PrintF(out, "ast_id pc_offset loop_depth\n"); |
| 10786 for (uint32_t i = 0; i < table_length; ++i) { | 10804 for (uint32_t i = 0; i < table_length; ++i) { |
| 10787 uint32_t ast_id = Memory::uint32_at(back_edge_cursor); | 10805 uint32_t ast_id = Memory::uint32_at(back_edge_cursor); |
| 10788 uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize); | 10806 uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize); |
| 10789 uint8_t loop_depth = Memory::uint8_at(back_edge_cursor + 2 * kIntSize); | 10807 uint32_t loop_depth = Memory::uint32_at(back_edge_cursor + |
| 10808 2 * kIntSize); |
| 10790 PrintF(out, "%6u %9u %10u\n", ast_id, pc_offset, loop_depth); | 10809 PrintF(out, "%6u %9u %10u\n", ast_id, pc_offset, loop_depth); |
| 10791 back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize; | 10810 back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize; |
| 10792 } | 10811 } |
| 10793 PrintF(out, "\n"); | 10812 PrintF(out, "\n"); |
| 10794 } | 10813 } |
| 10795 #ifdef OBJECT_PRINT | 10814 #ifdef OBJECT_PRINT |
| 10796 if (!type_feedback_info()->IsUndefined()) { | 10815 if (!type_feedback_info()->IsUndefined()) { |
| 10797 TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out); | 10816 TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out); |
| 10798 PrintF(out, "\n"); | 10817 PrintF(out, "\n"); |
| 10799 } | 10818 } |
| (...skipping 1564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12364 object->TransitionElementsKind(to_kind), | 12383 object->TransitionElementsKind(to_kind), |
| 12365 Object); | 12384 Object); |
| 12366 } | 12385 } |
| 12367 | 12386 |
| 12368 | 12387 |
| 12369 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { | 12388 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { |
| 12370 if (!FLAG_track_allocation_sites || !IsJSArray()) { | 12389 if (!FLAG_track_allocation_sites || !IsJSArray()) { |
| 12371 return this; | 12390 return this; |
| 12372 } | 12391 } |
| 12373 | 12392 |
| 12374 AllocationSiteInfo* info = AllocationSiteInfo::FindForJSObject(this); | 12393 AllocationMemento* memento = AllocationMemento::FindForJSObject(this); |
| 12375 if (info == NULL || !info->IsValid()) { | 12394 if (memento == NULL || !memento->IsValid()) { |
| 12376 return this; | 12395 return this; |
| 12377 } | 12396 } |
| 12378 | 12397 |
| 12379 // Walk through to the Allocation Site | 12398 // Walk through to the Allocation Site |
| 12380 AllocationSite* site = info->GetAllocationSite(); | 12399 AllocationSite* site = memento->GetAllocationSite(); |
| 12381 if (site->IsLiteralSite()) { | 12400 if (site->IsLiteralSite()) { |
| 12382 JSArray* transition_info = JSArray::cast(site->transition_info()); | 12401 JSArray* transition_info = JSArray::cast(site->transition_info()); |
| 12383 ElementsKind kind = transition_info->GetElementsKind(); | 12402 ElementsKind kind = transition_info->GetElementsKind(); |
| 12384 // if kind is holey ensure that to_kind is as well. | 12403 // if kind is holey ensure that to_kind is as well. |
| 12385 if (IsHoleyElementsKind(kind)) { | 12404 if (IsHoleyElementsKind(kind)) { |
| 12386 to_kind = GetHoleyElementsKind(to_kind); | 12405 to_kind = GetHoleyElementsKind(to_kind); |
| 12387 } | 12406 } |
| 12388 if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { | 12407 if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { |
| 12389 // If the array is huge, it's not likely to be defined in a local | 12408 // If the array is huge, it's not likely to be defined in a local |
| 12390 // function, so we shouldn't make new instances of it very often. | 12409 // function, so we shouldn't make new instances of it very often. |
| (...skipping 3501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15892 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) { | 15911 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) { |
| 15893 ASSERT(IsPropertyCell()); | 15912 ASSERT(IsPropertyCell()); |
| 15894 set_type_raw(type, ignored); | 15913 set_type_raw(type, ignored); |
| 15895 } | 15914 } |
| 15896 | 15915 |
| 15897 | 15916 |
| 15898 Type* PropertyCell::UpdateType(Handle<PropertyCell> cell, | 15917 Type* PropertyCell::UpdateType(Handle<PropertyCell> cell, |
| 15899 Handle<Object> value) { | 15918 Handle<Object> value) { |
| 15900 Isolate* isolate = cell->GetIsolate(); | 15919 Isolate* isolate = cell->GetIsolate(); |
| 15901 Handle<Type> old_type(cell->type(), isolate); | 15920 Handle<Type> old_type(cell->type(), isolate); |
| 15902 Handle<Type> new_type((value->IsSmi() || value->IsUndefined()) | 15921 Handle<Type> new_type(value->IsConsString() || value->IsTheHole() |
| 15903 ? Type::Constant(value, isolate) | 15922 ? Type::Any() |
| 15904 : Type::Any(), isolate); | 15923 : Type::Constant(value, isolate), isolate); |
| 15905 | 15924 |
| 15906 if (new_type->Is(old_type)) { | 15925 if (new_type->Is(old_type)) { |
| 15907 return *old_type; | 15926 return *old_type; |
| 15908 } | 15927 } |
| 15909 | 15928 |
| 15910 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 15929 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 15911 isolate, DependentCode::kPropertyCellChangedGroup); | 15930 isolate, DependentCode::kPropertyCellChangedGroup); |
| 15912 | 15931 |
| 15913 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { | 15932 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { |
| 15914 return *new_type; | 15933 return *new_type; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15948 | 15967 |
| 15949 void PropertyCell::AddDependentCode(Handle<Code> code) { | 15968 void PropertyCell::AddDependentCode(Handle<Code> code) { |
| 15950 Handle<DependentCode> codes = DependentCode::Insert( | 15969 Handle<DependentCode> codes = DependentCode::Insert( |
| 15951 Handle<DependentCode>(dependent_code()), | 15970 Handle<DependentCode>(dependent_code()), |
| 15952 DependentCode::kPropertyCellChangedGroup, code); | 15971 DependentCode::kPropertyCellChangedGroup, code); |
| 15953 if (*codes != dependent_code()) set_dependent_code(*codes); | 15972 if (*codes != dependent_code()) set_dependent_code(*codes); |
| 15954 } | 15973 } |
| 15955 | 15974 |
| 15956 | 15975 |
| 15957 } } // namespace v8::internal | 15976 } } // namespace v8::internal |
| OLD | NEW |