Chromium Code Reviews| 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 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 633 ASSERT(!HasFastProperties()); | 633 ASSERT(!HasFastProperties()); |
| 634 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 634 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 635 if (IsGlobalObject()) { | 635 if (IsGlobalObject()) { |
| 636 value = PropertyCell::cast(value)->value(); | 636 value = PropertyCell::cast(value)->value(); |
| 637 } | 637 } |
| 638 ASSERT(!value->IsPropertyCell() && !value->IsCell()); | 638 ASSERT(!value->IsPropertyCell() && !value->IsCell()); |
| 639 return value; | 639 return value; |
| 640 } | 640 } |
| 641 | 641 |
| 642 | 642 |
| 643 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, | 643 void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
| 644 LookupResult* result, | 644 LookupResult* result, |
| 645 Handle<Object> value) { | 645 Handle<Object> value) { |
| 646 CALL_HEAP_FUNCTION(object->GetIsolate(), | 646 ASSERT(!object->HasFastProperties()); |
| 647 object->SetNormalizedProperty(result, *value), | 647 NameDictionary* property_dictionary = object->property_dictionary(); |
| 648 Object); | 648 if (object->IsGlobalObject()) { |
| 649 Handle<PropertyCell> cell(PropertyCell::cast( | |
| 650 property_dictionary->ValueAt(result->GetDictionaryEntry()))); | |
| 651 PropertyCell::SetValueInferType(cell, value); | |
| 652 } else { | |
| 653 property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value); | |
| 654 } | |
| 649 } | 655 } |
| 650 | 656 |
| 651 | 657 |
| 652 MaybeObject* JSObject::SetNormalizedProperty(LookupResult* result, | 658 // TODO(mstarzinger): Temporary wrapper until handlified. |
| 653 Object* value) { | 659 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, |
| 654 ASSERT(!HasFastProperties()); | 660 Handle<Name> name, |
| 655 if (IsGlobalObject()) { | 661 Handle<Object> value, |
| 656 PropertyCell* cell = PropertyCell::cast( | 662 PropertyDetails details) { |
| 657 property_dictionary()->ValueAt(result->GetDictionaryEntry())); | 663 CALL_HEAP_FUNCTION(dict->GetIsolate(), |
| 658 MaybeObject* maybe_type = cell->SetValueInferType(value); | 664 dict->Add(*name, *value, details), |
| 659 if (maybe_type->IsFailure()) return maybe_type; | 665 NameDictionary); |
| 660 } else { | |
| 661 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); | |
| 662 } | |
| 663 return value; | |
| 664 } | 666 } |
| 665 | 667 |
| 666 | 668 |
| 667 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, | 669 void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
| 668 Handle<Name> key, | 670 Handle<Name> name, |
| 669 Handle<Object> value, | 671 Handle<Object> value, |
| 670 PropertyDetails details) { | 672 PropertyDetails details) { |
| 671 CALL_HEAP_FUNCTION(object->GetIsolate(), | 673 ASSERT(!object->HasFastProperties()); |
| 672 object->SetNormalizedProperty(*key, *value, details), | 674 Handle<NameDictionary> property_dictionary(object->property_dictionary()); |
| 673 Object); | 675 int entry = property_dictionary->FindEntry(*name); |
| 674 } | |
| 675 | |
| 676 | |
| 677 MaybeObject* JSObject::SetNormalizedProperty(Name* name, | |
| 678 Object* value, | |
| 679 PropertyDetails details) { | |
| 680 ASSERT(!HasFastProperties()); | |
| 681 int entry = property_dictionary()->FindEntry(name); | |
| 682 if (entry == NameDictionary::kNotFound) { | 676 if (entry == NameDictionary::kNotFound) { |
| 683 Object* store_value = value; | 677 Handle<Object> store_value = value; |
| 684 if (IsGlobalObject()) { | 678 if (object->IsGlobalObject()) { |
| 685 Heap* heap = name->GetHeap(); | 679 store_value = object->GetIsolate()->factory()->NewPropertyCell(value); |
| 686 MaybeObject* maybe_store_value = heap->AllocatePropertyCell(value); | |
| 687 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; | |
| 688 } | 680 } |
| 689 Object* dict; | 681 property_dictionary = |
| 690 { MaybeObject* maybe_dict = | 682 NameDictionaryAdd(property_dictionary, name, store_value, details); |
| 691 property_dictionary()->Add(name, store_value, details); | 683 object->set_properties(*property_dictionary); |
| 692 if (!maybe_dict->ToObject(&dict)) return maybe_dict; | 684 return; |
| 693 } | |
| 694 set_properties(NameDictionary::cast(dict)); | |
| 695 return value; | |
| 696 } | 685 } |
| 697 | 686 |
| 698 PropertyDetails original_details = property_dictionary()->DetailsAt(entry); | 687 PropertyDetails original_details = property_dictionary->DetailsAt(entry); |
| 699 int enumeration_index; | 688 int enumeration_index; |
| 700 // Preserve the enumeration index unless the property was deleted. | 689 // Preserve the enumeration index unless the property was deleted. |
| 701 if (original_details.IsDeleted()) { | 690 if (original_details.IsDeleted()) { |
| 702 enumeration_index = property_dictionary()->NextEnumerationIndex(); | 691 enumeration_index = property_dictionary->NextEnumerationIndex(); |
| 703 property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1); | 692 property_dictionary->SetNextEnumerationIndex(enumeration_index + 1); |
| 704 } else { | 693 } else { |
| 705 enumeration_index = original_details.dictionary_index(); | 694 enumeration_index = original_details.dictionary_index(); |
| 706 ASSERT(enumeration_index > 0); | 695 ASSERT(enumeration_index > 0); |
| 707 } | 696 } |
| 708 | 697 |
| 709 details = PropertyDetails( | 698 details = PropertyDetails( |
| 710 details.attributes(), details.type(), enumeration_index); | 699 details.attributes(), details.type(), enumeration_index); |
| 711 | 700 |
| 712 if (IsGlobalObject()) { | 701 if (object->IsGlobalObject()) { |
| 713 PropertyCell* cell = | 702 Handle<PropertyCell> cell( |
| 714 PropertyCell::cast(property_dictionary()->ValueAt(entry)); | 703 PropertyCell::cast(property_dictionary->ValueAt(entry))); |
| 715 MaybeObject* maybe_type = cell->SetValueInferType(value); | 704 PropertyCell::SetValueInferType(cell, value); |
| 716 if (maybe_type->IsFailure()) return maybe_type; | |
| 717 // Please note we have to update the property details. | 705 // Please note we have to update the property details. |
| 718 property_dictionary()->DetailsAtPut(entry, details); | 706 property_dictionary->DetailsAtPut(entry, details); |
| 719 } else { | 707 } else { |
| 720 property_dictionary()->SetEntry(entry, name, value, details); | 708 property_dictionary->SetEntry(entry, *name, *value, details); |
| 721 } | 709 } |
| 722 return value; | |
| 723 } | 710 } |
| 724 | 711 |
| 725 | 712 |
| 726 // TODO(mstarzinger): Temporary wrapper until target is handlified. | 713 // TODO(mstarzinger): Temporary wrapper until target is handlified. |
| 727 Handle<NameDictionary> NameDictionaryShrink(Handle<NameDictionary> dict, | 714 Handle<NameDictionary> NameDictionaryShrink(Handle<NameDictionary> dict, |
| 728 Handle<Name> name) { | 715 Handle<Name> name) { |
| 729 CALL_HEAP_FUNCTION(dict->GetIsolate(), dict->Shrink(*name), NameDictionary); | 716 CALL_HEAP_FUNCTION(dict->GetIsolate(), dict->Shrink(*name), NameDictionary); |
| 730 } | 717 } |
| 731 | 718 |
| 732 | 719 |
| 733 static void CellSetValueInferType(Handle<PropertyCell> cell, | |
| 734 Handle<Object> value) { | |
| 735 CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), cell->SetValueInferType(*value)); | |
| 736 } | |
| 737 | |
| 738 | |
| 739 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object, | 720 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
| 740 Handle<Name> name, | 721 Handle<Name> name, |
| 741 DeleteMode mode) { | 722 DeleteMode mode) { |
| 742 ASSERT(!object->HasFastProperties()); | 723 ASSERT(!object->HasFastProperties()); |
| 743 Isolate* isolate = object->GetIsolate(); | 724 Isolate* isolate = object->GetIsolate(); |
| 744 Handle<NameDictionary> dictionary(object->property_dictionary()); | 725 Handle<NameDictionary> dictionary(object->property_dictionary()); |
| 745 int entry = dictionary->FindEntry(*name); | 726 int entry = dictionary->FindEntry(*name); |
| 746 if (entry != NameDictionary::kNotFound) { | 727 if (entry != NameDictionary::kNotFound) { |
| 747 // If we have a global object set the cell to the hole. | 728 // If we have a global object set the cell to the hole. |
| 748 if (object->IsGlobalObject()) { | 729 if (object->IsGlobalObject()) { |
| 749 PropertyDetails details = dictionary->DetailsAt(entry); | 730 PropertyDetails details = dictionary->DetailsAt(entry); |
| 750 if (details.IsDontDelete()) { | 731 if (details.IsDontDelete()) { |
| 751 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); | 732 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); |
| 752 // When forced to delete global properties, we have to make a | 733 // When forced to delete global properties, we have to make a |
| 753 // map change to invalidate any ICs that think they can load | 734 // map change to invalidate any ICs that think they can load |
| 754 // from the DontDelete cell without checking if it contains | 735 // from the DontDelete cell without checking if it contains |
| 755 // the hole value. | 736 // the hole value. |
| 756 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 737 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 757 ASSERT(new_map->is_dictionary_map()); | 738 ASSERT(new_map->is_dictionary_map()); |
| 758 object->set_map(*new_map); | 739 object->set_map(*new_map); |
| 759 } | 740 } |
| 760 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 741 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 761 CellSetValueInferType(cell, isolate->factory()->the_hole_value()); | 742 Handle<Object> value = isolate->factory()->the_hole_value(); |
| 743 PropertyCell::SetValueInferType(cell, value); | |
| 762 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 744 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| 763 } else { | 745 } else { |
| 764 Handle<Object> deleted(dictionary->DeleteProperty(entry, mode), isolate); | 746 Handle<Object> deleted(dictionary->DeleteProperty(entry, mode), isolate); |
| 765 if (*deleted == isolate->heap()->true_value()) { | 747 if (*deleted == isolate->heap()->true_value()) { |
| 766 Handle<NameDictionary> new_properties = | 748 Handle<NameDictionary> new_properties = |
| 767 NameDictionaryShrink(dictionary, name); | 749 NameDictionaryShrink(dictionary, name); |
| 768 object->set_properties(*new_properties); | 750 object->set_properties(*new_properties); |
| 769 } | 751 } |
| 770 return deleted; | 752 return deleted; |
| 771 } | 753 } |
| (...skipping 1244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2016 : initial_flag; | 1998 : initial_flag; |
| 2017 | 1999 |
| 2018 // Allocate new instance descriptors with (name, constant) added. | 2000 // Allocate new instance descriptors with (name, constant) added. |
| 2019 Handle<Map> new_map = CopyAddConstantDescriptor( | 2001 Handle<Map> new_map = CopyAddConstantDescriptor( |
| 2020 handle(object->map()), name, constant, attributes, flag); | 2002 handle(object->map()), name, constant, attributes, flag); |
| 2021 | 2003 |
| 2022 object->set_map(*new_map); | 2004 object->set_map(*new_map); |
| 2023 } | 2005 } |
| 2024 | 2006 |
| 2025 | 2007 |
| 2026 // TODO(mstarzinger): Temporary wrapper until handlified. | |
| 2027 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, | |
| 2028 Handle<Name> name, | |
| 2029 Handle<Object> value, | |
| 2030 PropertyDetails details) { | |
| 2031 CALL_HEAP_FUNCTION(dict->GetIsolate(), | |
| 2032 dict->Add(*name, *value, details), | |
| 2033 NameDictionary); | |
| 2034 } | |
| 2035 | |
| 2036 | |
| 2037 void JSObject::AddSlowProperty(Handle<JSObject> object, | 2008 void JSObject::AddSlowProperty(Handle<JSObject> object, |
| 2038 Handle<Name> name, | 2009 Handle<Name> name, |
| 2039 Handle<Object> value, | 2010 Handle<Object> value, |
| 2040 PropertyAttributes attributes) { | 2011 PropertyAttributes attributes) { |
| 2041 ASSERT(!object->HasFastProperties()); | 2012 ASSERT(!object->HasFastProperties()); |
| 2042 Isolate* isolate = object->GetIsolate(); | 2013 Isolate* isolate = object->GetIsolate(); |
| 2043 Handle<NameDictionary> dict(object->property_dictionary()); | 2014 Handle<NameDictionary> dict(object->property_dictionary()); |
| 2044 if (object->IsGlobalObject()) { | 2015 if (object->IsGlobalObject()) { |
| 2045 // In case name is an orphaned property reuse the cell. | 2016 // In case name is an orphaned property reuse the cell. |
| 2046 int entry = dict->FindEntry(*name); | 2017 int entry = dict->FindEntry(*name); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2179 } | 2150 } |
| 2180 bool done = false; | 2151 bool done = false; |
| 2181 Handle<Object> result_object = SetPropertyViaPrototypes( | 2152 Handle<Object> result_object = SetPropertyViaPrototypes( |
| 2182 object, name, value, attributes, strict_mode, &done); | 2153 object, name, value, attributes, strict_mode, &done); |
| 2183 if (done) return result_object; | 2154 if (done) return result_object; |
| 2184 // Add a new real property. | 2155 // Add a new real property. |
| 2185 return AddProperty(object, name, value, attributes, strict_mode); | 2156 return AddProperty(object, name, value, attributes, strict_mode); |
| 2186 } | 2157 } |
| 2187 | 2158 |
| 2188 | 2159 |
| 2189 static Handle<Object> ReplaceSlowProperty(Handle<JSObject> object, | 2160 static void ReplaceSlowProperty(Handle<JSObject> object, |
| 2190 Handle<Name> name, | 2161 Handle<Name> name, |
| 2191 Handle<Object> value, | 2162 Handle<Object> value, |
| 2192 PropertyAttributes attributes) { | 2163 PropertyAttributes attributes) { |
| 2193 NameDictionary* dictionary = object->property_dictionary(); | 2164 NameDictionary* dictionary = object->property_dictionary(); |
| 2194 int old_index = dictionary->FindEntry(*name); | 2165 int old_index = dictionary->FindEntry(*name); |
| 2195 int new_enumeration_index = 0; // 0 means "Use the next available index." | 2166 int new_enumeration_index = 0; // 0 means "Use the next available index." |
| 2196 if (old_index != -1) { | 2167 if (old_index != -1) { |
| 2197 // All calls to ReplaceSlowProperty have had all transitions removed. | 2168 // All calls to ReplaceSlowProperty have had all transitions removed. |
| 2198 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); | 2169 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); |
| 2199 } | 2170 } |
| 2200 | 2171 |
| 2201 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); | 2172 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
| 2202 return JSObject::SetNormalizedProperty(object, name, value, new_details); | 2173 JSObject::SetNormalizedProperty(object, name, value, new_details); |
| 2203 } | 2174 } |
| 2204 | 2175 |
| 2205 | 2176 |
| 2206 const char* Representation::Mnemonic() const { | 2177 const char* Representation::Mnemonic() const { |
| 2207 switch (kind_) { | 2178 switch (kind_) { |
| 2208 case kNone: return "v"; | 2179 case kNone: return "v"; |
| 2209 case kTagged: return "t"; | 2180 case kTagged: return "t"; |
| 2210 case kSmi: return "s"; | 2181 case kSmi: return "s"; |
| 2211 case kDouble: return "d"; | 2182 case kDouble: return "d"; |
| 2212 case kInteger32: return "i"; | 2183 case kInteger32: return "i"; |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2782 LookupResult result(object->GetIsolate()); | 2753 LookupResult result(object->GetIsolate()); |
| 2783 object->LocalLookup(*name, &result, true); | 2754 object->LocalLookup(*name, &result, true); |
| 2784 if (!result.IsFound()) { | 2755 if (!result.IsFound()) { |
| 2785 object->map()->LookupTransition(JSObject::cast(*object), *name, &result); | 2756 object->map()->LookupTransition(JSObject::cast(*object), *name, &result); |
| 2786 } | 2757 } |
| 2787 return SetProperty(object, &result, name, value, attributes, strict_mode, | 2758 return SetProperty(object, &result, name, value, attributes, strict_mode, |
| 2788 store_mode); | 2759 store_mode); |
| 2789 } | 2760 } |
| 2790 | 2761 |
| 2791 | 2762 |
| 2792 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, | 2763 Handle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object, |
| 2793 Name* name, | 2764 Handle<Object> structure, |
| 2794 Object* value, | 2765 Handle<Name> name, |
| 2795 JSObject* holder, | 2766 Handle<Object> value, |
| 2796 StrictModeFlag strict_mode) { | 2767 Handle<JSObject> holder, |
| 2797 Isolate* isolate = GetIsolate(); | 2768 StrictModeFlag strict_mode) { |
| 2798 HandleScope scope(isolate); | 2769 Isolate* isolate = object->GetIsolate(); |
| 2799 | 2770 |
| 2800 // We should never get here to initialize a const with the hole | 2771 // We should never get here to initialize a const with the hole |
| 2801 // value since a const declaration would conflict with the setter. | 2772 // value since a const declaration would conflict with the setter. |
| 2802 ASSERT(!value->IsTheHole()); | 2773 ASSERT(!value->IsTheHole()); |
| 2803 Handle<Object> value_handle(value, isolate); | |
| 2804 | 2774 |
| 2805 // To accommodate both the old and the new api we switch on the | 2775 // To accommodate both the old and the new api we switch on the |
| 2806 // data structure used to store the callbacks. Eventually foreign | 2776 // data structure used to store the callbacks. Eventually foreign |
| 2807 // callbacks should be phased out. | 2777 // callbacks should be phased out. |
| 2808 if (structure->IsForeign()) { | 2778 if (structure->IsForeign()) { |
| 2809 AccessorDescriptor* callback = | 2779 AccessorDescriptor* callback = |
| 2810 reinterpret_cast<AccessorDescriptor*>( | 2780 reinterpret_cast<AccessorDescriptor*>( |
| 2811 Foreign::cast(structure)->foreign_address()); | 2781 Handle<Foreign>::cast(structure)->foreign_address()); |
| 2812 MaybeObject* obj = (callback->setter)( | 2782 CALL_AND_RETRY_OR_DIE(isolate, |
| 2813 isolate, this, value, callback->data); | 2783 (callback->setter)( |
| 2814 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2784 isolate, *object, *value, callback->data), |
| 2815 if (obj->IsFailure()) return obj; | 2785 break, |
| 2816 return *value_handle; | 2786 return Handle<Object>()); |
| 2787 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
| 2788 return value; | |
| 2817 } | 2789 } |
| 2818 | 2790 |
| 2819 if (structure->IsExecutableAccessorInfo()) { | 2791 if (structure->IsExecutableAccessorInfo()) { |
| 2820 // api style callbacks | 2792 // api style callbacks |
| 2821 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure); | 2793 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure); |
| 2822 if (!data->IsCompatibleReceiver(this)) { | 2794 if (!data->IsCompatibleReceiver(*object)) { |
| 2823 Handle<Object> name_handle(name, isolate); | 2795 Handle<Object> args[2] = { name, object }; |
| 2824 Handle<Object> receiver_handle(this, isolate); | |
| 2825 Handle<Object> args[2] = { name_handle, receiver_handle }; | |
| 2826 Handle<Object> error = | 2796 Handle<Object> error = |
| 2827 isolate->factory()->NewTypeError("incompatible_method_receiver", | 2797 isolate->factory()->NewTypeError("incompatible_method_receiver", |
| 2828 HandleVector(args, | 2798 HandleVector(args, |
| 2829 ARRAY_SIZE(args))); | 2799 ARRAY_SIZE(args))); |
| 2830 return isolate->Throw(*error); | 2800 isolate->Throw(*error); |
| 2801 return Handle<Object>(); | |
| 2831 } | 2802 } |
| 2832 // TODO(rossberg): Support symbols in the API. | 2803 // TODO(rossberg): Support symbols in the API. |
| 2833 if (name->IsSymbol()) return value; | 2804 if (name->IsSymbol()) return value; |
| 2834 Object* call_obj = data->setter(); | 2805 Object* call_obj = data->setter(); |
| 2835 v8::AccessorSetterCallback call_fun = | 2806 v8::AccessorSetterCallback call_fun = |
| 2836 v8::ToCData<v8::AccessorSetterCallback>(call_obj); | 2807 v8::ToCData<v8::AccessorSetterCallback>(call_obj); |
| 2837 if (call_fun == NULL) return value; | 2808 if (call_fun == NULL) return value; |
| 2838 Handle<String> key(String::cast(name)); | 2809 Handle<String> key = Handle<String>::cast(name); |
| 2839 LOG(isolate, ApiNamedPropertyAccess("store", this, name)); | 2810 LOG(isolate, ApiNamedPropertyAccess("store", *object, *name)); |
| 2840 PropertyCallbackArguments args( | 2811 PropertyCallbackArguments args( |
| 2841 isolate, data->data(), this, JSObject::cast(holder)); | 2812 isolate, data->data(), *object, JSObject::cast(*holder)); |
| 2842 args.Call(call_fun, | 2813 args.Call(call_fun, |
| 2843 v8::Utils::ToLocal(key), | 2814 v8::Utils::ToLocal(key), |
| 2844 v8::Utils::ToLocal(value_handle)); | 2815 v8::Utils::ToLocal(value)); |
| 2845 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2816 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 2846 return *value_handle; | 2817 return value; |
| 2847 } | 2818 } |
| 2848 | 2819 |
| 2849 if (structure->IsAccessorPair()) { | 2820 if (structure->IsAccessorPair()) { |
| 2850 Object* setter = AccessorPair::cast(structure)->setter(); | 2821 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
| 2851 if (setter->IsSpecFunction()) { | 2822 if (setter->IsSpecFunction()) { |
| 2852 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 2823 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 2853 return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value); | 2824 CALL_HEAP_FUNCTION(isolate, |
| 2825 object->SetPropertyWithDefinedSetter( | |
| 2826 JSReceiver::cast(*setter), *value), | |
| 2827 Object); | |
| 2854 } else { | 2828 } else { |
| 2855 if (strict_mode == kNonStrictMode) { | 2829 if (strict_mode == kNonStrictMode) { |
| 2856 return value; | 2830 return value; |
| 2857 } | 2831 } |
| 2858 Handle<Name> key(name); | 2832 Handle<Object> args[2] = { name, holder }; |
| 2859 Handle<Object> holder_handle(holder, isolate); | 2833 Handle<Object> error = |
| 2860 Handle<Object> args[2] = { key, holder_handle }; | 2834 isolate->factory()->NewTypeError("no_setter_in_callback", |
| 2861 return isolate->Throw( | 2835 HandleVector(args, 2)); |
| 2862 *isolate->factory()->NewTypeError("no_setter_in_callback", | 2836 isolate->Throw(*error); |
| 2863 HandleVector(args, 2))); | 2837 return Handle<Object>(); |
| 2864 } | 2838 } |
| 2865 } | 2839 } |
| 2866 | 2840 |
| 2867 // TODO(dcarney): Handle correctly. | 2841 // TODO(dcarney): Handle correctly. |
| 2868 if (structure->IsDeclaredAccessorInfo()) { | 2842 if (structure->IsDeclaredAccessorInfo()) { |
| 2869 return value; | 2843 return value; |
| 2870 } | 2844 } |
| 2871 | 2845 |
| 2872 UNREACHABLE(); | 2846 UNREACHABLE(); |
| 2873 return NULL; | 2847 return Handle<Object>(); |
| 2874 } | 2848 } |
| 2875 | 2849 |
| 2876 | 2850 |
| 2877 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter, | 2851 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter, |
| 2878 Object* value) { | 2852 Object* value) { |
| 2879 Isolate* isolate = GetIsolate(); | 2853 Isolate* isolate = GetIsolate(); |
| 2880 Handle<Object> value_handle(value, isolate); | 2854 Handle<Object> value_handle(value, isolate); |
| 2881 Handle<JSReceiver> fun(setter, isolate); | 2855 Handle<JSReceiver> fun(setter, isolate); |
| 2882 Handle<JSReceiver> self(this, isolate); | 2856 Handle<JSReceiver> self(this, isolate); |
| 2883 #ifdef ENABLE_DEBUGGER_SUPPORT | 2857 #ifdef ENABLE_DEBUGGER_SUPPORT |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 2902 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( | 2876 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( |
| 2903 uint32_t index, | 2877 uint32_t index, |
| 2904 Object* value, | 2878 Object* value, |
| 2905 bool* found, | 2879 bool* found, |
| 2906 StrictModeFlag strict_mode) { | 2880 StrictModeFlag strict_mode) { |
| 2907 Heap* heap = GetHeap(); | 2881 Heap* heap = GetHeap(); |
| 2908 for (Object* pt = GetPrototype(); | 2882 for (Object* pt = GetPrototype(); |
| 2909 pt != heap->null_value(); | 2883 pt != heap->null_value(); |
| 2910 pt = pt->GetPrototype(GetIsolate())) { | 2884 pt = pt->GetPrototype(GetIsolate())) { |
| 2911 if (pt->IsJSProxy()) { | 2885 if (pt->IsJSProxy()) { |
| 2912 String* name; | 2886 Isolate* isolate = GetIsolate(); |
| 2913 MaybeObject* maybe = heap->Uint32ToString(index); | 2887 HandleScope scope(isolate); |
| 2914 if (!maybe->To<String>(&name)) { | 2888 Handle<JSProxy> proxy(JSProxy::cast(pt)); |
| 2915 *found = true; // Force abort | 2889 Handle<JSObject> self(this, isolate); |
| 2916 return maybe; | 2890 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 2917 } | 2891 Handle<Object> value_handle(value, isolate); |
| 2918 return JSProxy::cast(pt)->SetPropertyViaPrototypesWithHandler( | 2892 Handle<Object> result = JSProxy::SetPropertyViaPrototypesWithHandler( |
| 2919 this, name, value, NONE, strict_mode, found); | 2893 proxy, self, name, value_handle, NONE, strict_mode, found); |
| 2894 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
| 2895 return *result; | |
| 2920 } | 2896 } |
| 2921 if (!JSObject::cast(pt)->HasDictionaryElements()) { | 2897 if (!JSObject::cast(pt)->HasDictionaryElements()) { |
| 2922 continue; | 2898 continue; |
| 2923 } | 2899 } |
| 2924 SeededNumberDictionary* dictionary = | 2900 SeededNumberDictionary* dictionary = |
| 2925 JSObject::cast(pt)->element_dictionary(); | 2901 JSObject::cast(pt)->element_dictionary(); |
| 2926 int entry = dictionary->FindEntry(index); | 2902 int entry = dictionary->FindEntry(index); |
| 2927 if (entry != SeededNumberDictionary::kNotFound) { | 2903 if (entry != SeededNumberDictionary::kNotFound) { |
| 2928 PropertyDetails details = dictionary->DetailsAt(entry); | 2904 PropertyDetails details = dictionary->DetailsAt(entry); |
| 2929 if (details.type() == CALLBACKS) { | 2905 if (details.type() == CALLBACKS) { |
| 2930 *found = true; | 2906 *found = true; |
| 2931 return SetElementWithCallback(dictionary->ValueAt(entry), | 2907 Isolate* isolate = GetIsolate(); |
| 2932 index, | 2908 HandleScope scope(isolate); |
| 2933 value, | 2909 Handle<JSObject> self(this, isolate); |
| 2934 JSObject::cast(pt), | 2910 Handle<Object> structure(dictionary->ValueAt(entry), isolate); |
| 2935 strict_mode); | 2911 Handle<Object> value_handle(value, isolate); |
| 2912 Handle<JSObject> holder(JSObject::cast(pt)); | |
| 2913 Handle<Object> result = SetElementWithCallback( | |
| 2914 self, structure, index, value_handle, holder, strict_mode); | |
| 2915 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
| 2916 return *result; | |
| 2936 } | 2917 } |
| 2937 } | 2918 } |
| 2938 } | 2919 } |
| 2939 *found = false; | 2920 *found = false; |
| 2940 return heap->the_hole_value(); | 2921 return heap->the_hole_value(); |
| 2941 } | 2922 } |
| 2942 | 2923 |
| 2924 | |
| 2943 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, | 2925 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, |
| 2944 Handle<Name> name, | 2926 Handle<Name> name, |
| 2945 Handle<Object> value, | 2927 Handle<Object> value, |
| 2946 PropertyAttributes attributes, | 2928 PropertyAttributes attributes, |
| 2947 StrictModeFlag strict_mode, | 2929 StrictModeFlag strict_mode, |
| 2948 bool* done) { | 2930 bool* done) { |
| 2949 Isolate* isolate = object->GetIsolate(); | 2931 Isolate* isolate = object->GetIsolate(); |
| 2950 | 2932 |
| 2951 *done = false; | 2933 *done = false; |
| 2952 // We could not find a local property so let's check whether there is an | 2934 // We could not find a local property so let's check whether there is an |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2964 case INTERCEPTOR: { | 2946 case INTERCEPTOR: { |
| 2965 PropertyAttributes attr = | 2947 PropertyAttributes attr = |
| 2966 result.holder()->GetPropertyAttributeWithInterceptor( | 2948 result.holder()->GetPropertyAttributeWithInterceptor( |
| 2967 *object, *name, true); | 2949 *object, *name, true); |
| 2968 *done = !!(attr & READ_ONLY); | 2950 *done = !!(attr & READ_ONLY); |
| 2969 break; | 2951 break; |
| 2970 } | 2952 } |
| 2971 case CALLBACKS: { | 2953 case CALLBACKS: { |
| 2972 if (!FLAG_es5_readonly && result.IsReadOnly()) break; | 2954 if (!FLAG_es5_readonly && result.IsReadOnly()) break; |
| 2973 *done = true; | 2955 *done = true; |
| 2974 CALL_HEAP_FUNCTION(isolate, | 2956 Handle<Object> callback_object(result.GetCallbackObject(), isolate); |
| 2975 object->SetPropertyWithCallback( | 2957 return SetPropertyWithCallback(object, callback_object, name, value, |
| 2976 result.GetCallbackObject(), | 2958 handle(result.holder()), strict_mode); |
| 2977 *name, *value, result.holder(), strict_mode), | |
| 2978 Object); | |
| 2979 } | 2959 } |
| 2980 case HANDLER: { | 2960 case HANDLER: { |
| 2981 CALL_HEAP_FUNCTION(isolate, | 2961 Handle<JSProxy> proxy(result.proxy()); |
| 2982 result.proxy()->SetPropertyViaPrototypesWithHandler( | 2962 return JSProxy::SetPropertyViaPrototypesWithHandler( |
| 2983 *object, *name, *value, attributes, strict_mode, | 2963 proxy, object, name, value, attributes, strict_mode, done); |
| 2984 done), | |
| 2985 Object); | |
| 2986 } | 2964 } |
| 2987 case TRANSITION: | 2965 case TRANSITION: |
| 2988 case NONEXISTENT: | 2966 case NONEXISTENT: |
| 2989 UNREACHABLE(); | 2967 UNREACHABLE(); |
| 2990 break; | 2968 break; |
| 2991 } | 2969 } |
| 2992 } | 2970 } |
| 2993 | 2971 |
| 2994 // If we get here with *done true, we have encountered a read-only property. | 2972 // If we get here with *done true, we have encountered a read-only property. |
| 2995 if (!FLAG_es5_readonly) *done = false; | 2973 if (!FLAG_es5_readonly) *done = false; |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3349 } | 3327 } |
| 3350 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 3328 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 3351 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); | 3329 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); |
| 3352 if (result->IsFound()) return; | 3330 if (result->IsFound()) return; |
| 3353 } | 3331 } |
| 3354 result->NotFound(); | 3332 result->NotFound(); |
| 3355 } | 3333 } |
| 3356 | 3334 |
| 3357 | 3335 |
| 3358 // We only need to deal with CALLBACKS and INTERCEPTORS | 3336 // We only need to deal with CALLBACKS and INTERCEPTORS |
| 3359 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck( | 3337 Handle<Object> JSObject::SetPropertyWithFailedAccessCheck( |
| 3338 Handle<JSObject> object, | |
| 3360 LookupResult* result, | 3339 LookupResult* result, |
| 3361 Name* name, | 3340 Handle<Name> name, |
| 3362 Object* value, | 3341 Handle<Object> value, |
| 3363 bool check_prototype, | 3342 bool check_prototype, |
| 3364 StrictModeFlag strict_mode) { | 3343 StrictModeFlag strict_mode) { |
| 3365 if (check_prototype && !result->IsProperty()) { | 3344 if (check_prototype && !result->IsProperty()) { |
| 3366 LookupRealNamedPropertyInPrototypes(name, result); | 3345 object->LookupRealNamedPropertyInPrototypes(*name, result); |
| 3367 } | 3346 } |
| 3368 | 3347 |
| 3369 if (result->IsProperty()) { | 3348 if (result->IsProperty()) { |
| 3370 if (!result->IsReadOnly()) { | 3349 if (!result->IsReadOnly()) { |
| 3371 switch (result->type()) { | 3350 switch (result->type()) { |
| 3372 case CALLBACKS: { | 3351 case CALLBACKS: { |
| 3373 Object* obj = result->GetCallbackObject(); | 3352 Object* obj = result->GetCallbackObject(); |
| 3374 if (obj->IsAccessorInfo()) { | 3353 if (obj->IsAccessorInfo()) { |
| 3375 AccessorInfo* info = AccessorInfo::cast(obj); | 3354 Handle<AccessorInfo> info(AccessorInfo::cast(obj)); |
| 3376 if (info->all_can_write()) { | 3355 if (info->all_can_write()) { |
| 3377 return SetPropertyWithCallback(result->GetCallbackObject(), | 3356 return SetPropertyWithCallback(object, |
| 3357 info, | |
| 3378 name, | 3358 name, |
| 3379 value, | 3359 value, |
| 3380 result->holder(), | 3360 handle(result->holder()), |
| 3381 strict_mode); | 3361 strict_mode); |
| 3382 } | 3362 } |
| 3383 } else if (obj->IsAccessorPair()) { | 3363 } else if (obj->IsAccessorPair()) { |
| 3384 AccessorPair* pair = AccessorPair::cast(obj); | 3364 Handle<AccessorPair> pair(AccessorPair::cast(obj)); |
| 3385 if (pair->all_can_read()) { | 3365 if (pair->all_can_read()) { |
| 3386 return SetPropertyWithCallback(result->GetCallbackObject(), | 3366 return SetPropertyWithCallback(object, |
| 3367 pair, | |
| 3387 name, | 3368 name, |
| 3388 value, | 3369 value, |
| 3389 result->holder(), | 3370 handle(result->holder()), |
| 3390 strict_mode); | 3371 strict_mode); |
| 3391 } | 3372 } |
| 3392 } | 3373 } |
| 3393 break; | 3374 break; |
| 3394 } | 3375 } |
| 3395 case INTERCEPTOR: { | 3376 case INTERCEPTOR: { |
| 3396 // Try lookup real named properties. Note that only property can be | 3377 // Try lookup real named properties. Note that only property can be |
| 3397 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. | 3378 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. |
| 3398 LookupResult r(GetIsolate()); | 3379 LookupResult r(object->GetIsolate()); |
| 3399 LookupRealNamedProperty(name, &r); | 3380 object->LookupRealNamedProperty(*name, &r); |
| 3400 if (r.IsProperty()) { | 3381 if (r.IsProperty()) { |
| 3401 return SetPropertyWithFailedAccessCheck(&r, | 3382 return SetPropertyWithFailedAccessCheck(object, |
| 3383 &r, | |
| 3402 name, | 3384 name, |
| 3403 value, | 3385 value, |
| 3404 check_prototype, | 3386 check_prototype, |
| 3405 strict_mode); | 3387 strict_mode); |
| 3406 } | 3388 } |
| 3407 break; | 3389 break; |
| 3408 } | 3390 } |
| 3409 default: { | 3391 default: { |
| 3410 break; | 3392 break; |
| 3411 } | 3393 } |
| 3412 } | 3394 } |
| 3413 } | 3395 } |
| 3414 } | 3396 } |
| 3415 | 3397 |
| 3416 Isolate* isolate = GetIsolate(); | 3398 Isolate* isolate = object->GetIsolate(); |
| 3417 HandleScope scope(isolate); | 3399 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); |
| 3418 Handle<Object> value_handle(value, isolate); | 3400 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 3419 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 3401 return value; |
| 3420 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
| 3421 return *value_handle; | |
| 3422 } | 3402 } |
| 3423 | 3403 |
| 3424 | 3404 |
| 3425 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 3405 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
| 3426 LookupResult* result, | 3406 LookupResult* result, |
| 3427 Handle<Name> key, | 3407 Handle<Name> key, |
| 3428 Handle<Object> value, | 3408 Handle<Object> value, |
| 3429 PropertyAttributes attributes, | 3409 PropertyAttributes attributes, |
| 3430 StrictModeFlag strict_mode, | 3410 StrictModeFlag strict_mode, |
| 3431 StoreFromKeyed store_mode) { | 3411 StoreFromKeyed store_mode) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3466 if (name->IsSymbol()) return value; | 3446 if (name->IsSymbol()) return value; |
| 3467 | 3447 |
| 3468 Handle<Object> args[] = { receiver, name, value }; | 3448 Handle<Object> args[] = { receiver, name, value }; |
| 3469 proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); | 3449 proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); |
| 3470 if (isolate->has_pending_exception()) return Handle<Object>(); | 3450 if (isolate->has_pending_exception()) return Handle<Object>(); |
| 3471 | 3451 |
| 3472 return value; | 3452 return value; |
| 3473 } | 3453 } |
| 3474 | 3454 |
| 3475 | 3455 |
| 3476 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler( | 3456 Handle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( |
| 3477 JSReceiver* receiver_raw, | 3457 Handle<JSProxy> proxy, |
| 3478 Name* name_raw, | 3458 Handle<JSReceiver> receiver, |
| 3479 Object* value_raw, | 3459 Handle<Name> name, |
| 3460 Handle<Object> value, | |
| 3480 PropertyAttributes attributes, | 3461 PropertyAttributes attributes, |
| 3481 StrictModeFlag strict_mode, | 3462 StrictModeFlag strict_mode, |
| 3482 bool* done) { | 3463 bool* done) { |
| 3483 Isolate* isolate = GetIsolate(); | 3464 Isolate* isolate = proxy->GetIsolate(); |
| 3484 Handle<JSProxy> proxy(this); | 3465 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. |
| 3485 Handle<JSReceiver> receiver(receiver_raw); | |
| 3486 Handle<Name> name(name_raw); | |
| 3487 Handle<Object> value(value_raw, isolate); | |
| 3488 Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy. | |
| 3489 | 3466 |
| 3490 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3467 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3491 if (name->IsSymbol()) { | 3468 if (name->IsSymbol()) { |
| 3492 *done = false; | 3469 *done = false; |
| 3493 return isolate->heap()->the_hole_value(); | 3470 return isolate->factory()->the_hole_value(); |
| 3494 } | 3471 } |
| 3495 | 3472 |
| 3496 *done = true; // except where redefined... | 3473 *done = true; // except where redefined... |
| 3497 Handle<Object> args[] = { name }; | 3474 Handle<Object> args[] = { name }; |
| 3498 Handle<Object> result = proxy->CallTrap( | 3475 Handle<Object> result = proxy->CallTrap( |
| 3499 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); | 3476 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); |
| 3500 if (isolate->has_pending_exception()) return Failure::Exception(); | 3477 if (isolate->has_pending_exception()) return Handle<Object>(); |
| 3501 | 3478 |
| 3502 if (result->IsUndefined()) { | 3479 if (result->IsUndefined()) { |
| 3503 *done = false; | 3480 *done = false; |
| 3504 return isolate->heap()->the_hole_value(); | 3481 return isolate->factory()->the_hole_value(); |
| 3505 } | 3482 } |
| 3506 | 3483 |
| 3507 // Emulate [[GetProperty]] semantics for proxies. | 3484 // Emulate [[GetProperty]] semantics for proxies. |
| 3508 bool has_pending_exception; | 3485 bool has_pending_exception; |
| 3509 Handle<Object> argv[] = { result }; | 3486 Handle<Object> argv[] = { result }; |
| 3510 Handle<Object> desc = Execution::Call( | 3487 Handle<Object> desc = Execution::Call( |
| 3511 isolate, isolate->to_complete_property_descriptor(), result, | 3488 isolate, isolate->to_complete_property_descriptor(), result, |
| 3512 ARRAY_SIZE(argv), argv, &has_pending_exception); | 3489 ARRAY_SIZE(argv), argv, &has_pending_exception); |
| 3513 if (has_pending_exception) return Failure::Exception(); | 3490 if (has_pending_exception) return Handle<Object>(); |
| 3514 | 3491 |
| 3515 // [[GetProperty]] requires to check that all properties are configurable. | 3492 // [[GetProperty]] requires to check that all properties are configurable. |
| 3516 Handle<String> configurable_name = | 3493 Handle<String> configurable_name = |
| 3517 isolate->factory()->InternalizeOneByteString( | 3494 isolate->factory()->InternalizeOneByteString( |
| 3518 STATIC_ASCII_VECTOR("configurable_")); | 3495 STATIC_ASCII_VECTOR("configurable_")); |
| 3519 Handle<Object> configurable( | 3496 Handle<Object> configurable( |
| 3520 v8::internal::GetProperty(isolate, desc, configurable_name)); | 3497 v8::internal::GetProperty(isolate, desc, configurable_name)); |
| 3521 ASSERT(!isolate->has_pending_exception()); | 3498 ASSERT(!isolate->has_pending_exception()); |
| 3522 ASSERT(configurable->IsTrue() || configurable->IsFalse()); | 3499 ASSERT(configurable->IsTrue() || configurable->IsFalse()); |
| 3523 if (configurable->IsFalse()) { | 3500 if (configurable->IsFalse()) { |
| 3524 Handle<String> trap = | 3501 Handle<String> trap = |
| 3525 isolate->factory()->InternalizeOneByteString( | 3502 isolate->factory()->InternalizeOneByteString( |
| 3526 STATIC_ASCII_VECTOR("getPropertyDescriptor")); | 3503 STATIC_ASCII_VECTOR("getPropertyDescriptor")); |
| 3527 Handle<Object> args[] = { handler, trap, name }; | 3504 Handle<Object> args[] = { handler, trap, name }; |
| 3528 Handle<Object> error = isolate->factory()->NewTypeError( | 3505 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3529 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); | 3506 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); |
| 3530 return isolate->Throw(*error); | 3507 isolate->Throw(*error); |
| 3508 return Handle<Object>(); | |
| 3531 } | 3509 } |
| 3532 ASSERT(configurable->IsTrue()); | 3510 ASSERT(configurable->IsTrue()); |
| 3533 | 3511 |
| 3534 // Check for DataDescriptor. | 3512 // Check for DataDescriptor. |
| 3535 Handle<String> hasWritable_name = | 3513 Handle<String> hasWritable_name = |
| 3536 isolate->factory()->InternalizeOneByteString( | 3514 isolate->factory()->InternalizeOneByteString( |
| 3537 STATIC_ASCII_VECTOR("hasWritable_")); | 3515 STATIC_ASCII_VECTOR("hasWritable_")); |
| 3538 Handle<Object> hasWritable( | 3516 Handle<Object> hasWritable( |
| 3539 v8::internal::GetProperty(isolate, desc, hasWritable_name)); | 3517 v8::internal::GetProperty(isolate, desc, hasWritable_name)); |
| 3540 ASSERT(!isolate->has_pending_exception()); | 3518 ASSERT(!isolate->has_pending_exception()); |
| 3541 ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse()); | 3519 ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse()); |
| 3542 if (hasWritable->IsTrue()) { | 3520 if (hasWritable->IsTrue()) { |
| 3543 Handle<String> writable_name = | 3521 Handle<String> writable_name = |
| 3544 isolate->factory()->InternalizeOneByteString( | 3522 isolate->factory()->InternalizeOneByteString( |
| 3545 STATIC_ASCII_VECTOR("writable_")); | 3523 STATIC_ASCII_VECTOR("writable_")); |
| 3546 Handle<Object> writable( | 3524 Handle<Object> writable( |
| 3547 v8::internal::GetProperty(isolate, desc, writable_name)); | 3525 v8::internal::GetProperty(isolate, desc, writable_name)); |
| 3548 ASSERT(!isolate->has_pending_exception()); | 3526 ASSERT(!isolate->has_pending_exception()); |
| 3549 ASSERT(writable->IsTrue() || writable->IsFalse()); | 3527 ASSERT(writable->IsTrue() || writable->IsFalse()); |
| 3550 *done = writable->IsFalse(); | 3528 *done = writable->IsFalse(); |
| 3551 if (!*done) return GetHeap()->the_hole_value(); | 3529 if (!*done) return isolate->factory()->the_hole_value(); |
| 3552 if (strict_mode == kNonStrictMode) return *value; | 3530 if (strict_mode == kNonStrictMode) return value; |
| 3553 Handle<Object> args[] = { name, receiver }; | 3531 Handle<Object> args[] = { name, receiver }; |
| 3554 Handle<Object> error = isolate->factory()->NewTypeError( | 3532 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3555 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 3533 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 3556 return isolate->Throw(*error); | 3534 isolate->Throw(*error); |
| 3535 return Handle<Object>(); | |
| 3557 } | 3536 } |
| 3558 | 3537 |
| 3559 // We have an AccessorDescriptor. | 3538 // We have an AccessorDescriptor. |
| 3560 Handle<String> set_name = isolate->factory()->InternalizeOneByteString( | 3539 Handle<String> set_name = isolate->factory()->InternalizeOneByteString( |
| 3561 STATIC_ASCII_VECTOR("set_")); | 3540 STATIC_ASCII_VECTOR("set_")); |
| 3562 Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_name)); | 3541 Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_name)); |
| 3563 ASSERT(!isolate->has_pending_exception()); | 3542 ASSERT(!isolate->has_pending_exception()); |
| 3564 if (!setter->IsUndefined()) { | 3543 if (!setter->IsUndefined()) { |
| 3565 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 3544 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 3566 return receiver->SetPropertyWithDefinedSetter( | 3545 CALL_HEAP_FUNCTION(isolate, |
| 3567 JSReceiver::cast(*setter), *value); | 3546 receiver->SetPropertyWithDefinedSetter( |
| 3547 JSReceiver::cast(*setter), *value), | |
| 3548 Object); | |
| 3568 } | 3549 } |
| 3569 | 3550 |
| 3570 if (strict_mode == kNonStrictMode) return *value; | 3551 if (strict_mode == kNonStrictMode) return value; |
| 3571 Handle<Object> args2[] = { name, proxy }; | 3552 Handle<Object> args2[] = { name, proxy }; |
| 3572 Handle<Object> error = isolate->factory()->NewTypeError( | 3553 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3573 "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2))); | 3554 "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2))); |
| 3574 return isolate->Throw(*error); | 3555 isolate->Throw(*error); |
| 3556 return Handle<Object>(); | |
| 3575 } | 3557 } |
| 3576 | 3558 |
| 3577 | 3559 |
| 3578 Handle<Object> JSProxy::DeletePropertyWithHandler( | 3560 Handle<Object> JSProxy::DeletePropertyWithHandler( |
| 3579 Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) { | 3561 Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) { |
| 3580 Isolate* isolate = proxy->GetIsolate(); | 3562 Isolate* isolate = proxy->GetIsolate(); |
| 3581 | 3563 |
| 3582 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3564 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3583 if (name->IsSymbol()) return isolate->factory()->false_value(); | 3565 if (name->IsSymbol()) return isolate->factory()->false_value(); |
| 3584 | 3566 |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3807 descriptors = transition_map->instance_descriptors(); | 3789 descriptors = transition_map->instance_descriptors(); |
| 3808 representation = descriptors->GetDetails(descriptor).representation(); | 3790 representation = descriptors->GetDetails(descriptor).representation(); |
| 3809 } | 3791 } |
| 3810 | 3792 |
| 3811 int field_index = descriptors->GetFieldIndex(descriptor); | 3793 int field_index = descriptors->GetFieldIndex(descriptor); |
| 3812 return AddFastPropertyUsingMap( | 3794 return AddFastPropertyUsingMap( |
| 3813 object, transition_map, name, value, field_index, representation); | 3795 object, transition_map, name, value, field_index, representation); |
| 3814 } | 3796 } |
| 3815 | 3797 |
| 3816 | 3798 |
| 3817 static Handle<Object> SetPropertyToField(LookupResult* lookup, | 3799 static void SetPropertyToField(LookupResult* lookup, |
| 3818 Handle<Name> name, | 3800 Handle<Name> name, |
| 3819 Handle<Object> value) { | 3801 Handle<Object> value) { |
| 3820 Representation representation = lookup->representation(); | 3802 Representation representation = lookup->representation(); |
| 3821 if (!value->FitsRepresentation(representation) || | 3803 if (!value->FitsRepresentation(representation) || |
| 3822 lookup->type() == CONSTANT) { | 3804 lookup->type() == CONSTANT) { |
| 3823 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), | 3805 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), |
| 3824 lookup->GetDescriptorIndex(), | 3806 lookup->GetDescriptorIndex(), |
| 3825 value->OptimalRepresentation(), | 3807 value->OptimalRepresentation(), |
| 3826 FORCE_FIELD); | 3808 FORCE_FIELD); |
| 3827 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); | 3809 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
| 3828 int descriptor = lookup->GetDescriptorIndex(); | 3810 int descriptor = lookup->GetDescriptorIndex(); |
| 3829 representation = desc->GetDetails(descriptor).representation(); | 3811 representation = desc->GetDetails(descriptor).representation(); |
| 3830 } | 3812 } |
| 3831 | 3813 |
| 3832 if (FLAG_track_double_fields && representation.IsDouble()) { | 3814 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 3833 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( | 3815 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
| 3834 lookup->GetFieldIndex().field_index())); | 3816 lookup->GetFieldIndex().field_index())); |
| 3835 storage->set_value(value->Number()); | 3817 storage->set_value(value->Number()); |
| 3836 return value; | 3818 return; |
| 3837 } | 3819 } |
| 3838 | 3820 |
| 3839 lookup->holder()->FastPropertyAtPut( | 3821 lookup->holder()->FastPropertyAtPut( |
| 3840 lookup->GetFieldIndex().field_index(), *value); | 3822 lookup->GetFieldIndex().field_index(), *value); |
| 3841 return value; | |
| 3842 } | 3823 } |
| 3843 | 3824 |
| 3844 | 3825 |
| 3845 static Handle<Object> ConvertAndSetLocalProperty( | 3826 static void ConvertAndSetLocalProperty(LookupResult* lookup, |
| 3846 LookupResult* lookup, | 3827 Handle<Name> name, |
| 3847 Handle<Name> name, | 3828 Handle<Object> value, |
| 3848 Handle<Object> value, | 3829 PropertyAttributes attributes) { |
| 3849 PropertyAttributes attributes) { | |
| 3850 Handle<JSObject> object(lookup->holder()); | 3830 Handle<JSObject> object(lookup->holder()); |
| 3851 if (object->TooManyFastProperties()) { | 3831 if (object->TooManyFastProperties()) { |
| 3852 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 3832 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 3853 } | 3833 } |
| 3854 | 3834 |
| 3855 if (!object->HasFastProperties()) { | 3835 if (!object->HasFastProperties()) { |
| 3856 return ReplaceSlowProperty(object, name, value, attributes); | 3836 ReplaceSlowProperty(object, name, value, attributes); |
| 3837 return; | |
| 3857 } | 3838 } |
| 3858 | 3839 |
| 3859 int descriptor_index = lookup->GetDescriptorIndex(); | 3840 int descriptor_index = lookup->GetDescriptorIndex(); |
| 3860 if (lookup->GetAttributes() == attributes) { | 3841 if (lookup->GetAttributes() == attributes) { |
| 3861 JSObject::GeneralizeFieldRepresentation( | 3842 JSObject::GeneralizeFieldRepresentation( |
| 3862 object, descriptor_index, Representation::Tagged(), FORCE_FIELD); | 3843 object, descriptor_index, Representation::Tagged(), FORCE_FIELD); |
| 3863 } else { | 3844 } else { |
| 3864 Handle<Map> old_map(object->map()); | 3845 Handle<Map> old_map(object->map()); |
| 3865 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map, | 3846 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map, |
| 3866 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); | 3847 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); |
| 3867 JSObject::MigrateToMap(object, new_map); | 3848 JSObject::MigrateToMap(object, new_map); |
| 3868 } | 3849 } |
| 3869 | 3850 |
| 3870 DescriptorArray* descriptors = object->map()->instance_descriptors(); | 3851 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 3871 int index = descriptors->GetDetails(descriptor_index).field_index(); | 3852 int index = descriptors->GetDetails(descriptor_index).field_index(); |
| 3872 object->FastPropertyAtPut(index, *value); | 3853 object->FastPropertyAtPut(index, *value); |
| 3873 return value; | |
| 3874 } | 3854 } |
| 3875 | 3855 |
| 3876 | 3856 |
| 3877 static Handle<Object> SetPropertyToFieldWithAttributes( | 3857 static void SetPropertyToFieldWithAttributes(LookupResult* lookup, |
| 3878 LookupResult* lookup, | 3858 Handle<Name> name, |
| 3879 Handle<Name> name, | 3859 Handle<Object> value, |
| 3880 Handle<Object> value, | 3860 PropertyAttributes attributes) { |
| 3881 PropertyAttributes attributes) { | |
| 3882 if (lookup->GetAttributes() == attributes) { | 3861 if (lookup->GetAttributes() == attributes) { |
| 3883 if (value->IsUninitialized()) return value; | 3862 if (value->IsUninitialized()) return; |
| 3884 return SetPropertyToField(lookup, name, value); | 3863 SetPropertyToField(lookup, name, value); |
| 3885 } else { | 3864 } else { |
| 3886 return ConvertAndSetLocalProperty(lookup, name, value, attributes); | 3865 ConvertAndSetLocalProperty(lookup, name, value, attributes); |
| 3887 } | 3866 } |
| 3888 } | 3867 } |
| 3889 | 3868 |
| 3890 | 3869 |
| 3891 Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object, | 3870 Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object, |
| 3892 LookupResult* lookup, | 3871 LookupResult* lookup, |
| 3893 Handle<Name> name, | 3872 Handle<Name> name, |
| 3894 Handle<Object> value, | 3873 Handle<Object> value, |
| 3895 PropertyAttributes attributes, | 3874 PropertyAttributes attributes, |
| 3896 StrictModeFlag strict_mode, | 3875 StrictModeFlag strict_mode, |
| 3897 StoreFromKeyed store_mode) { | 3876 StoreFromKeyed store_mode) { |
| 3898 Isolate* isolate = object->GetIsolate(); | 3877 Isolate* isolate = object->GetIsolate(); |
| 3899 | 3878 |
| 3900 // Make sure that the top context does not change when doing callbacks or | 3879 // Make sure that the top context does not change when doing callbacks or |
| 3901 // interceptor calls. | 3880 // interceptor calls. |
| 3902 AssertNoContextChange ncc; | 3881 AssertNoContextChange ncc; |
| 3903 | 3882 |
| 3904 // Optimization for 2-byte strings often used as keys in a decompression | 3883 // Optimization for 2-byte strings often used as keys in a decompression |
| 3905 // dictionary. We internalize these short keys to avoid constantly | 3884 // dictionary. We internalize these short keys to avoid constantly |
| 3906 // reallocating them. | 3885 // reallocating them. |
| 3907 if (name->IsString() && !name->IsInternalizedString() && | 3886 if (name->IsString() && !name->IsInternalizedString() && |
| 3908 Handle<String>::cast(name)->length() <= 2) { | 3887 Handle<String>::cast(name)->length() <= 2) { |
| 3909 name = isolate->factory()->InternalizeString(Handle<String>::cast(name)); | 3888 name = isolate->factory()->InternalizeString(Handle<String>::cast(name)); |
| 3910 } | 3889 } |
| 3911 | 3890 |
| 3912 // Check access rights if needed. | 3891 // Check access rights if needed. |
| 3913 if (object->IsAccessCheckNeeded()) { | 3892 if (object->IsAccessCheckNeeded()) { |
| 3914 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { | 3893 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
| 3915 CALL_HEAP_FUNCTION( | 3894 return SetPropertyWithFailedAccessCheck(object, lookup, name, value, |
| 3916 isolate, | 3895 true, strict_mode); |
| 3917 object->SetPropertyWithFailedAccessCheck( | |
| 3918 lookup, *name, *value, true, strict_mode), | |
| 3919 Object); | |
| 3920 } | 3896 } |
| 3921 } | 3897 } |
| 3922 | 3898 |
| 3923 if (object->IsJSGlobalProxy()) { | 3899 if (object->IsJSGlobalProxy()) { |
| 3924 Handle<Object> proto(object->GetPrototype(), isolate); | 3900 Handle<Object> proto(object->GetPrototype(), isolate); |
| 3925 if (proto->IsNull()) return value; | 3901 if (proto->IsNull()) return value; |
| 3926 ASSERT(proto->IsJSGlobalObject()); | 3902 ASSERT(proto->IsJSGlobalObject()); |
| 3927 return SetPropertyForResult(Handle<JSObject>::cast(proto), | 3903 return SetPropertyForResult(Handle<JSObject>::cast(proto), |
| 3928 lookup, name, value, attributes, strict_mode, store_mode); | 3904 lookup, name, value, attributes, strict_mode, store_mode); |
| 3929 } | 3905 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 3960 if (FLAG_harmony_observation && | 3936 if (FLAG_harmony_observation && |
| 3961 object->map()->is_observed() && lookup->IsDataProperty()) { | 3937 object->map()->is_observed() && lookup->IsDataProperty()) { |
| 3962 old_value = Object::GetProperty(object, name); | 3938 old_value = Object::GetProperty(object, name); |
| 3963 } | 3939 } |
| 3964 | 3940 |
| 3965 // This is a real property that is not read-only, or it is a | 3941 // This is a real property that is not read-only, or it is a |
| 3966 // transition or null descriptor and there are no setters in the prototypes. | 3942 // transition or null descriptor and there are no setters in the prototypes. |
| 3967 Handle<Object> result = value; | 3943 Handle<Object> result = value; |
| 3968 switch (lookup->type()) { | 3944 switch (lookup->type()) { |
| 3969 case NORMAL: | 3945 case NORMAL: |
| 3970 result = SetNormalizedProperty(handle(lookup->holder()), lookup, value); | 3946 SetNormalizedProperty(handle(lookup->holder()), lookup, value); |
| 3971 break; | 3947 break; |
| 3972 case FIELD: | 3948 case FIELD: |
| 3973 result = SetPropertyToField(lookup, name, value); | 3949 SetPropertyToField(lookup, name, value); |
| 3974 break; | 3950 break; |
| 3975 case CONSTANT: | 3951 case CONSTANT: |
| 3976 // Only replace the constant if necessary. | 3952 // Only replace the constant if necessary. |
| 3977 if (*value == lookup->GetConstant()) return value; | 3953 if (*value == lookup->GetConstant()) return value; |
| 3978 result = SetPropertyToField(lookup, name, value); | 3954 SetPropertyToField(lookup, name, value); |
| 3979 break; | 3955 break; |
| 3980 case CALLBACKS: { | 3956 case CALLBACKS: { |
| 3981 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate); | 3957 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate); |
| 3982 CALL_HEAP_FUNCTION( | 3958 return SetPropertyWithCallback(object, callback_object, name, value, |
| 3983 isolate, | 3959 handle(lookup->holder()), strict_mode); |
| 3984 object->SetPropertyWithCallback(*callback_object, *name, *value, | |
| 3985 lookup->holder(), strict_mode), | |
| 3986 Object); | |
| 3987 } | 3960 } |
| 3988 case INTERCEPTOR: | 3961 case INTERCEPTOR: |
| 3989 result = SetPropertyWithInterceptor(handle(lookup->holder()), name, value, | 3962 result = SetPropertyWithInterceptor(handle(lookup->holder()), name, value, |
| 3990 attributes, strict_mode); | 3963 attributes, strict_mode); |
| 3991 break; | 3964 break; |
| 3992 case TRANSITION: | 3965 case TRANSITION: |
| 3993 result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, | 3966 result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, |
| 3994 name, value, attributes); | 3967 name, value, attributes); |
| 3995 break; | 3968 break; |
| 3996 case HANDLER: | 3969 case HANDLER: |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4067 | 4040 |
| 4068 LookupResult lookup(isolate); | 4041 LookupResult lookup(isolate); |
| 4069 object->LocalLookup(*name, &lookup, true); | 4042 object->LocalLookup(*name, &lookup, true); |
| 4070 if (!lookup.IsFound()) { | 4043 if (!lookup.IsFound()) { |
| 4071 object->map()->LookupTransition(*object, *name, &lookup); | 4044 object->map()->LookupTransition(*object, *name, &lookup); |
| 4072 } | 4045 } |
| 4073 | 4046 |
| 4074 // Check access rights if needed. | 4047 // Check access rights if needed. |
| 4075 if (object->IsAccessCheckNeeded()) { | 4048 if (object->IsAccessCheckNeeded()) { |
| 4076 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { | 4049 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
| 4077 CALL_HEAP_FUNCTION( | 4050 return SetPropertyWithFailedAccessCheck(object, &lookup, name, value, |
| 4078 isolate, | 4051 false, kNonStrictMode); |
| 4079 object->SetPropertyWithFailedAccessCheck( | |
| 4080 &lookup, *name, *value, false, kNonStrictMode), | |
| 4081 Object); | |
| 4082 } | 4052 } |
| 4083 } | 4053 } |
| 4084 | 4054 |
| 4085 if (object->IsJSGlobalProxy()) { | 4055 if (object->IsJSGlobalProxy()) { |
| 4086 Handle<Object> proto(object->GetPrototype(), isolate); | 4056 Handle<Object> proto(object->GetPrototype(), isolate); |
| 4087 if (proto->IsNull()) return value; | 4057 if (proto->IsNull()) return value; |
| 4088 ASSERT(proto->IsJSGlobalObject()); | 4058 ASSERT(proto->IsJSGlobalObject()); |
| 4089 return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), | 4059 return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), |
| 4090 name, value, attributes, value_type, mode, extensibility_check); | 4060 name, value, attributes, value_type, mode, extensibility_check); |
| 4091 } | 4061 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 4108 if (is_observed && lookup.IsProperty()) { | 4078 if (is_observed && lookup.IsProperty()) { |
| 4109 if (lookup.IsDataProperty()) old_value = | 4079 if (lookup.IsDataProperty()) old_value = |
| 4110 Object::GetProperty(object, name); | 4080 Object::GetProperty(object, name); |
| 4111 old_attributes = lookup.GetAttributes(); | 4081 old_attributes = lookup.GetAttributes(); |
| 4112 } | 4082 } |
| 4113 | 4083 |
| 4114 // Check of IsReadOnly removed from here in clone. | 4084 // Check of IsReadOnly removed from here in clone. |
| 4115 Handle<Object> result = value; | 4085 Handle<Object> result = value; |
| 4116 switch (lookup.type()) { | 4086 switch (lookup.type()) { |
| 4117 case NORMAL: | 4087 case NORMAL: |
| 4118 result = ReplaceSlowProperty(object, name, value, attributes); | 4088 ReplaceSlowProperty(object, name, value, attributes); |
| 4119 break; | 4089 break; |
| 4120 case FIELD: | 4090 case FIELD: |
| 4121 result = SetPropertyToFieldWithAttributes( | 4091 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); |
| 4122 &lookup, name, value, attributes); | |
| 4123 break; | 4092 break; |
| 4124 case CONSTANT: | 4093 case CONSTANT: |
| 4125 // Only replace the constant if necessary. | 4094 // Only replace the constant if necessary. |
| 4126 if (lookup.GetAttributes() != attributes || | 4095 if (lookup.GetAttributes() != attributes || |
| 4127 *value != lookup.GetConstant()) { | 4096 *value != lookup.GetConstant()) { |
| 4128 result = SetPropertyToFieldWithAttributes( | 4097 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); |
| 4129 &lookup, name, value, attributes); | |
| 4130 } | 4098 } |
| 4131 break; | 4099 break; |
| 4132 case CALLBACKS: | 4100 case CALLBACKS: |
| 4133 result = ConvertAndSetLocalProperty(&lookup, name, value, attributes); | 4101 ConvertAndSetLocalProperty(&lookup, name, value, attributes); |
| 4134 break; | 4102 break; |
| 4135 case TRANSITION: | 4103 case TRANSITION: |
| 4136 result = SetPropertyUsingTransition(handle(lookup.holder()), &lookup, | 4104 result = SetPropertyUsingTransition(handle(lookup.holder()), &lookup, |
| 4137 name, value, attributes); | 4105 name, value, attributes); |
| 4138 break; | 4106 break; |
| 4139 case NONEXISTENT: | 4107 case NONEXISTENT: |
| 4140 case HANDLER: | 4108 case HANDLER: |
| 4141 case INTERCEPTOR: | 4109 case INTERCEPTOR: |
| 4142 UNREACHABLE(); | 4110 UNREACHABLE(); |
| 4143 } | 4111 } |
| 4144 | 4112 |
| 4145 if (result.is_null()) return result; | 4113 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); |
|
Yang
2013/09/17 16:39:46
You could move this check to the TRANSITION case,
Michael Starzinger
2013/09/18 16:19:55
Done.
| |
| 4146 | 4114 |
| 4147 if (is_observed) { | 4115 if (is_observed) { |
| 4148 if (lookup.IsTransition()) { | 4116 if (lookup.IsTransition()) { |
| 4149 EnqueueChangeRecord(object, "new", name, old_value); | 4117 EnqueueChangeRecord(object, "new", name, old_value); |
| 4150 } else if (old_value->IsTheHole()) { | 4118 } else if (old_value->IsTheHole()) { |
| 4151 EnqueueChangeRecord(object, "reconfigured", name, old_value); | 4119 EnqueueChangeRecord(object, "reconfigured", name, old_value); |
| 4152 } else { | 4120 } else { |
| 4153 LookupResult new_lookup(isolate); | 4121 LookupResult new_lookup(isolate); |
| 4154 object->LocalLookup(*name, &new_lookup, true); | 4122 object->LocalLookup(*name, &new_lookup, true); |
| 4155 bool value_changed = false; | 4123 bool value_changed = false; |
| (...skipping 7553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11709 return GetDeclaredAccessorProperty(receiver, | 11677 return GetDeclaredAccessorProperty(receiver, |
| 11710 DeclaredAccessorInfo::cast(structure), | 11678 DeclaredAccessorInfo::cast(structure), |
| 11711 isolate); | 11679 isolate); |
| 11712 } | 11680 } |
| 11713 | 11681 |
| 11714 UNREACHABLE(); | 11682 UNREACHABLE(); |
| 11715 return NULL; | 11683 return NULL; |
| 11716 } | 11684 } |
| 11717 | 11685 |
| 11718 | 11686 |
| 11719 MaybeObject* JSObject::SetElementWithCallback(Object* structure, | 11687 Handle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, |
| 11720 uint32_t index, | 11688 Handle<Object> structure, |
| 11721 Object* value, | 11689 uint32_t index, |
| 11722 JSObject* holder, | 11690 Handle<Object> value, |
| 11723 StrictModeFlag strict_mode) { | 11691 Handle<JSObject> holder, |
| 11724 Isolate* isolate = GetIsolate(); | 11692 StrictModeFlag strict_mode) { |
| 11725 HandleScope scope(isolate); | 11693 Isolate* isolate = object->GetIsolate(); |
| 11726 | 11694 |
| 11727 // We should never get here to initialize a const with the hole | 11695 // We should never get here to initialize a const with the hole |
| 11728 // value since a const declaration would conflict with the setter. | 11696 // value since a const declaration would conflict with the setter. |
| 11729 ASSERT(!value->IsTheHole()); | 11697 ASSERT(!value->IsTheHole()); |
| 11730 Handle<Object> value_handle(value, isolate); | |
| 11731 | 11698 |
| 11732 // To accommodate both the old and the new api we switch on the | 11699 // To accommodate both the old and the new api we switch on the |
| 11733 // data structure used to store the callbacks. Eventually foreign | 11700 // data structure used to store the callbacks. Eventually foreign |
| 11734 // callbacks should be phased out. | 11701 // callbacks should be phased out. |
| 11735 ASSERT(!structure->IsForeign()); | 11702 ASSERT(!structure->IsForeign()); |
| 11736 | 11703 |
| 11737 if (structure->IsExecutableAccessorInfo()) { | 11704 if (structure->IsExecutableAccessorInfo()) { |
| 11738 // api style callbacks | 11705 // api style callbacks |
| 11739 Handle<JSObject> self(this); | 11706 Handle<ExecutableAccessorInfo> data = |
| 11740 Handle<JSObject> holder_handle(JSObject::cast(holder)); | 11707 Handle<ExecutableAccessorInfo>::cast(structure); |
| 11741 Handle<ExecutableAccessorInfo> data( | |
| 11742 ExecutableAccessorInfo::cast(structure)); | |
| 11743 Object* call_obj = data->setter(); | 11708 Object* call_obj = data->setter(); |
| 11744 v8::AccessorSetterCallback call_fun = | 11709 v8::AccessorSetterCallback call_fun = |
| 11745 v8::ToCData<v8::AccessorSetterCallback>(call_obj); | 11710 v8::ToCData<v8::AccessorSetterCallback>(call_obj); |
| 11746 if (call_fun == NULL) return value; | 11711 if (call_fun == NULL) return value; |
| 11747 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 11712 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 11748 Handle<String> key(isolate->factory()->NumberToString(number)); | 11713 Handle<String> key(isolate->factory()->NumberToString(number)); |
| 11749 LOG(isolate, ApiNamedPropertyAccess("store", *self, *key)); | 11714 LOG(isolate, ApiNamedPropertyAccess("store", *object, *key)); |
| 11750 PropertyCallbackArguments | 11715 PropertyCallbackArguments |
| 11751 args(isolate, data->data(), *self, *holder_handle); | 11716 args(isolate, data->data(), *object, *holder); |
| 11752 args.Call(call_fun, | 11717 args.Call(call_fun, |
| 11753 v8::Utils::ToLocal(key), | 11718 v8::Utils::ToLocal(key), |
| 11754 v8::Utils::ToLocal(value_handle)); | 11719 v8::Utils::ToLocal(value)); |
| 11755 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 11720 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 11756 return *value_handle; | 11721 return value; |
| 11757 } | 11722 } |
| 11758 | 11723 |
| 11759 if (structure->IsAccessorPair()) { | 11724 if (structure->IsAccessorPair()) { |
| 11760 Handle<Object> setter(AccessorPair::cast(structure)->setter(), isolate); | 11725 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
| 11761 if (setter->IsSpecFunction()) { | 11726 if (setter->IsSpecFunction()) { |
| 11762 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 11727 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 11763 return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value); | 11728 CALL_HEAP_FUNCTION(isolate, |
| 11729 object->SetPropertyWithDefinedSetter( | |
| 11730 JSReceiver::cast(*setter), *value), | |
| 11731 Object); | |
| 11764 } else { | 11732 } else { |
| 11765 if (strict_mode == kNonStrictMode) { | 11733 if (strict_mode == kNonStrictMode) { |
| 11766 return value; | 11734 return value; |
| 11767 } | 11735 } |
| 11768 Handle<Object> holder_handle(holder, isolate); | |
| 11769 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); | 11736 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); |
| 11770 Handle<Object> args[2] = { key, holder_handle }; | 11737 Handle<Object> args[2] = { key, holder }; |
| 11771 return isolate->Throw( | 11738 Handle<Object> error = isolate->factory()->NewTypeError( |
| 11772 *isolate->factory()->NewTypeError("no_setter_in_callback", | 11739 "no_setter_in_callback", HandleVector(args, 2)); |
| 11773 HandleVector(args, 2))); | 11740 isolate->Throw(*error); |
| 11741 return Handle<Object>(); | |
| 11774 } | 11742 } |
| 11775 } | 11743 } |
| 11776 | 11744 |
| 11777 // TODO(dcarney): Handle correctly. | 11745 // TODO(dcarney): Handle correctly. |
| 11778 if (structure->IsDeclaredAccessorInfo()) return value; | 11746 if (structure->IsDeclaredAccessorInfo()) return value; |
| 11779 | 11747 |
| 11780 UNREACHABLE(); | 11748 UNREACHABLE(); |
| 11781 return NULL; | 11749 return Handle<Object>(); |
| 11782 } | 11750 } |
| 11783 | 11751 |
| 11784 | 11752 |
| 11785 bool JSObject::HasFastArgumentsElements() { | 11753 bool JSObject::HasFastArgumentsElements() { |
| 11786 Heap* heap = GetHeap(); | 11754 Heap* heap = GetHeap(); |
| 11787 if (!elements()->IsFixedArray()) return false; | 11755 if (!elements()->IsFixedArray()) return false; |
| 11788 FixedArray* elements = FixedArray::cast(this->elements()); | 11756 FixedArray* elements = FixedArray::cast(this->elements()); |
| 11789 if (elements->map() != heap->non_strict_arguments_elements_map()) { | 11757 if (elements->map() != heap->non_strict_arguments_elements_map()) { |
| 11790 return false; | 11758 return false; |
| 11791 } | 11759 } |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11968 // Insert element in the dictionary. | 11936 // Insert element in the dictionary. |
| 11969 Handle<FixedArray> elements(FixedArray::cast(this->elements())); | 11937 Handle<FixedArray> elements(FixedArray::cast(this->elements())); |
| 11970 bool is_arguments = | 11938 bool is_arguments = |
| 11971 (elements->map() == heap->non_strict_arguments_elements_map()); | 11939 (elements->map() == heap->non_strict_arguments_elements_map()); |
| 11972 Handle<SeededNumberDictionary> dictionary(is_arguments | 11940 Handle<SeededNumberDictionary> dictionary(is_arguments |
| 11973 ? SeededNumberDictionary::cast(elements->get(1)) | 11941 ? SeededNumberDictionary::cast(elements->get(1)) |
| 11974 : SeededNumberDictionary::cast(*elements)); | 11942 : SeededNumberDictionary::cast(*elements)); |
| 11975 | 11943 |
| 11976 int entry = dictionary->FindEntry(index); | 11944 int entry = dictionary->FindEntry(index); |
| 11977 if (entry != SeededNumberDictionary::kNotFound) { | 11945 if (entry != SeededNumberDictionary::kNotFound) { |
| 11978 Object* element = dictionary->ValueAt(entry); | 11946 Handle<Object> element(dictionary->ValueAt(entry), isolate); |
| 11979 PropertyDetails details = dictionary->DetailsAt(entry); | 11947 PropertyDetails details = dictionary->DetailsAt(entry); |
| 11980 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { | 11948 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { |
| 11981 return SetElementWithCallback(element, index, *value, this, strict_mode); | 11949 Handle<Object> result = SetElementWithCallback(self, element, index, |
| 11950 value, self, strict_mode); | |
| 11951 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
| 11952 return *result; | |
| 11982 } else { | 11953 } else { |
| 11983 dictionary->UpdateMaxNumberKey(index); | 11954 dictionary->UpdateMaxNumberKey(index); |
| 11984 // If a value has not been initialized we allow writing to it even if it | 11955 // If a value has not been initialized we allow writing to it even if it |
| 11985 // is read-only (a declared const that has not been initialized). If a | 11956 // is read-only (a declared const that has not been initialized). If a |
| 11986 // value is being defined we skip attribute checks completely. | 11957 // value is being defined we skip attribute checks completely. |
| 11987 if (set_mode == DEFINE_PROPERTY) { | 11958 if (set_mode == DEFINE_PROPERTY) { |
| 11988 details = PropertyDetails( | 11959 details = PropertyDetails( |
| 11989 attributes, NORMAL, details.dictionary_index()); | 11960 attributes, NORMAL, details.dictionary_index()); |
| 11990 dictionary->DetailsAtPut(entry, details); | 11961 dictionary->DetailsAtPut(entry, details); |
| 11991 } else if (details.IsReadOnly() && !element->IsTheHole()) { | 11962 } else if (details.IsReadOnly() && !element->IsTheHole()) { |
| 11992 if (strict_mode == kNonStrictMode) { | 11963 if (strict_mode == kNonStrictMode) { |
| 11993 return isolate->heap()->undefined_value(); | 11964 return isolate->heap()->undefined_value(); |
| 11994 } else { | 11965 } else { |
| 11995 Handle<Object> holder(this, isolate); | 11966 Handle<Object> holder(this, isolate); |
| 11996 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 11967 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 11997 Handle<Object> args[2] = { number, holder }; | 11968 Handle<Object> args[2] = { number, holder }; |
| 11998 Handle<Object> error = | 11969 Handle<Object> error = |
| 11999 isolate->factory()->NewTypeError("strict_read_only_property", | 11970 isolate->factory()->NewTypeError("strict_read_only_property", |
| 12000 HandleVector(args, 2)); | 11971 HandleVector(args, 2)); |
| 12001 return isolate->Throw(*error); | 11972 return isolate->Throw(*error); |
| 12002 } | 11973 } |
| 12003 } | 11974 } |
| 12004 // Elements of the arguments object in slow mode might be slow aliases. | 11975 // Elements of the arguments object in slow mode might be slow aliases. |
| 12005 if (is_arguments && element->IsAliasedArgumentsEntry()) { | 11976 if (is_arguments && element->IsAliasedArgumentsEntry()) { |
| 12006 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(element); | 11977 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*element); |
| 12007 Context* context = Context::cast(elements->get(0)); | 11978 Context* context = Context::cast(elements->get(0)); |
| 12008 int context_index = entry->aliased_context_slot(); | 11979 int context_index = entry->aliased_context_slot(); |
| 12009 ASSERT(!context->get(context_index)->IsTheHole()); | 11980 ASSERT(!context->get(context_index)->IsTheHole()); |
| 12010 context->set(context_index, *value); | 11981 context->set(context_index, *value); |
| 12011 // For elements that are still writable we keep slow aliasing. | 11982 // For elements that are still writable we keep slow aliasing. |
| 12012 if (!details.IsReadOnly()) value = handle(element, isolate); | 11983 if (!details.IsReadOnly()) value = element; |
| 12013 } | 11984 } |
| 12014 dictionary->ValueAtPut(entry, *value); | 11985 dictionary->ValueAtPut(entry, *value); |
| 12015 } | 11986 } |
| 12016 } else { | 11987 } else { |
| 12017 // Index not already used. Look for an accessor in the prototype chain. | 11988 // Index not already used. Look for an accessor in the prototype chain. |
| 12018 // Can cause GC! | 11989 // Can cause GC! |
| 12019 if (check_prototype) { | 11990 if (check_prototype) { |
| 12020 bool found; | 11991 bool found; |
| 12021 MaybeObject* result = SetElementWithCallbackSetterInPrototypes( | 11992 MaybeObject* result = SetElementWithCallbackSetterInPrototypes( |
| 12022 index, *value, &found, strict_mode); | 11993 index, *value, &found, strict_mode); |
| (...skipping 4119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16142 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16113 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16143 static const char* error_messages_[] = { | 16114 static const char* error_messages_[] = { |
| 16144 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16115 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16145 }; | 16116 }; |
| 16146 #undef ERROR_MESSAGES_TEXTS | 16117 #undef ERROR_MESSAGES_TEXTS |
| 16147 return error_messages_[reason]; | 16118 return error_messages_[reason]; |
| 16148 } | 16119 } |
| 16149 | 16120 |
| 16150 | 16121 |
| 16151 } } // namespace v8::internal | 16122 } } // namespace v8::internal |
| OLD | NEW |