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 5820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5831 PropertyDetails(attributes, CALLBACKS, index)); | 5831 PropertyDetails(attributes, CALLBACKS, index)); |
| 5832 } | 5832 } |
| 5833 AccessorPair::cast(result)->SetComponents(getter, setter); | 5833 AccessorPair::cast(result)->SetComponents(getter, setter); |
| 5834 return true; | 5834 return true; |
| 5835 } | 5835 } |
| 5836 } | 5836 } |
| 5837 return false; | 5837 return false; |
| 5838 } | 5838 } |
| 5839 | 5839 |
| 5840 | 5840 |
| 5841 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, | 5841 void JSObject::DefineElementAccessor(Handle<JSObject> object, |
| 5842 Object* getter, | 5842 uint32_t index, |
| 5843 Object* setter, | 5843 Handle<Object> getter, |
| 5844 PropertyAttributes attributes) { | 5844 Handle<Object> setter, |
| 5845 switch (GetElementsKind()) { | 5845 PropertyAttributes attributes) { |
| 5846 switch (object->GetElementsKind()) { | |
| 5846 case FAST_SMI_ELEMENTS: | 5847 case FAST_SMI_ELEMENTS: |
| 5847 case FAST_ELEMENTS: | 5848 case FAST_ELEMENTS: |
| 5848 case FAST_DOUBLE_ELEMENTS: | 5849 case FAST_DOUBLE_ELEMENTS: |
| 5849 case FAST_HOLEY_SMI_ELEMENTS: | 5850 case FAST_HOLEY_SMI_ELEMENTS: |
| 5850 case FAST_HOLEY_ELEMENTS: | 5851 case FAST_HOLEY_ELEMENTS: |
| 5851 case FAST_HOLEY_DOUBLE_ELEMENTS: | 5852 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 5852 break; | 5853 break; |
| 5853 case EXTERNAL_PIXEL_ELEMENTS: | 5854 case EXTERNAL_PIXEL_ELEMENTS: |
| 5854 case EXTERNAL_BYTE_ELEMENTS: | 5855 case EXTERNAL_BYTE_ELEMENTS: |
| 5855 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 5856 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 5856 case EXTERNAL_SHORT_ELEMENTS: | 5857 case EXTERNAL_SHORT_ELEMENTS: |
| 5857 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 5858 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 5858 case EXTERNAL_INT_ELEMENTS: | 5859 case EXTERNAL_INT_ELEMENTS: |
| 5859 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 5860 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 5860 case EXTERNAL_FLOAT_ELEMENTS: | 5861 case EXTERNAL_FLOAT_ELEMENTS: |
| 5861 case EXTERNAL_DOUBLE_ELEMENTS: | 5862 case EXTERNAL_DOUBLE_ELEMENTS: |
| 5862 // Ignore getters and setters on pixel and external array elements. | 5863 // Ignore getters and setters on pixel and external array elements. |
| 5863 return GetHeap()->undefined_value(); | 5864 return; |
| 5864 case DICTIONARY_ELEMENTS: | 5865 case DICTIONARY_ELEMENTS: |
| 5865 if (UpdateGetterSetterInDictionary(element_dictionary(), | 5866 if (UpdateGetterSetterInDictionary(object->element_dictionary(), |
| 5866 index, | 5867 index, |
| 5867 getter, | 5868 *getter, |
| 5868 setter, | 5869 *setter, |
| 5869 attributes)) { | 5870 attributes)) { |
| 5870 return GetHeap()->undefined_value(); | 5871 return; |
| 5871 } | 5872 } |
| 5872 break; | 5873 break; |
| 5873 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 5874 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 5874 // Ascertain whether we have read-only properties or an existing | 5875 // Ascertain whether we have read-only properties or an existing |
| 5875 // getter/setter pair in an arguments elements dictionary backing | 5876 // getter/setter pair in an arguments elements dictionary backing |
| 5876 // store. | 5877 // store. |
| 5877 FixedArray* parameter_map = FixedArray::cast(elements()); | 5878 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
| 5878 uint32_t length = parameter_map->length(); | 5879 uint32_t length = parameter_map->length(); |
| 5879 Object* probe = | 5880 Object* probe = |
| 5880 index < (length - 2) ? parameter_map->get(index + 2) : NULL; | 5881 index < (length - 2) ? parameter_map->get(index + 2) : NULL; |
| 5881 if (probe == NULL || probe->IsTheHole()) { | 5882 if (probe == NULL || probe->IsTheHole()) { |
| 5882 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 5883 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 5883 if (arguments->IsDictionary()) { | 5884 if (arguments->IsDictionary()) { |
| 5884 SeededNumberDictionary* dictionary = | 5885 SeededNumberDictionary* dictionary = |
| 5885 SeededNumberDictionary::cast(arguments); | 5886 SeededNumberDictionary::cast(arguments); |
| 5886 if (UpdateGetterSetterInDictionary(dictionary, | 5887 if (UpdateGetterSetterInDictionary(dictionary, |
| 5887 index, | 5888 index, |
| 5888 getter, | 5889 *getter, |
| 5889 setter, | 5890 *setter, |
| 5890 attributes)) { | 5891 attributes)) { |
| 5891 return GetHeap()->undefined_value(); | 5892 return; |
| 5892 } | 5893 } |
| 5893 } | 5894 } |
| 5894 } | 5895 } |
| 5895 break; | 5896 break; |
| 5896 } | 5897 } |
| 5897 } | 5898 } |
| 5898 | 5899 |
| 5899 AccessorPair* accessors; | 5900 Isolate* isolate = object->GetIsolate(); |
| 5900 { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair(); | 5901 Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair(); |
| 5901 if (!maybe_accessors->To(&accessors)) return maybe_accessors; | 5902 accessors->SetComponents(*getter, *setter); |
| 5902 } | |
| 5903 accessors->SetComponents(getter, setter); | |
| 5904 | 5903 |
| 5905 return SetElementCallback(index, accessors, attributes); | 5904 CALL_HEAP_FUNCTION_VOID( |
| 5905 isolate, object->SetElementCallback(index, *accessors, attributes)); | |
| 5906 } | 5906 } |
| 5907 | 5907 |
| 5908 | 5908 |
| 5909 MaybeObject* JSObject::CreateAccessorPairFor(Name* name) { | 5909 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object, |
| 5910 LookupResult result(GetHeap()->isolate()); | 5910 Handle<Name> name) { |
| 5911 LocalLookupRealNamedProperty(name, &result); | 5911 Isolate* isolate = object->GetIsolate(); |
| 5912 LookupResult result(isolate); | |
| 5913 object->LocalLookupRealNamedProperty(*name, &result); | |
| 5912 if (result.IsPropertyCallbacks()) { | 5914 if (result.IsPropertyCallbacks()) { |
| 5913 // Note that the result can actually have IsDontDelete() == true when we | 5915 // Note that the result can actually have IsDontDelete() == true when we |
| 5914 // e.g. have to fall back to the slow case while adding a setter after | 5916 // e.g. have to fall back to the slow case while adding a setter after |
| 5915 // successfully reusing a map transition for a getter. Nevertheless, this is | 5917 // successfully reusing a map transition for a getter. Nevertheless, this is |
| 5916 // OK, because the assertion only holds for the whole addition of both | 5918 // OK, because the assertion only holds for the whole addition of both |
| 5917 // accessors, not for the addition of each part. See first comment in | 5919 // accessors, not for the addition of each part. See first comment in |
| 5918 // DefinePropertyAccessor below. | 5920 // DefinePropertyAccessor below. |
| 5919 Object* obj = result.GetCallbackObject(); | 5921 Object* obj = result.GetCallbackObject(); |
| 5920 if (obj->IsAccessorPair()) { | 5922 if (obj->IsAccessorPair()) { |
| 5921 return AccessorPair::cast(obj)->Copy(); | 5923 return AccessorPair::Copy(Handle<AccessorPair>(AccessorPair::cast(obj))); |
|
rossberg
2013/07/02 12:20:47
Use handle() and pass isolate.
Michael Starzinger
2013/07/02 15:50:23
Done.
| |
| 5922 } | 5924 } |
| 5923 } | 5925 } |
| 5924 return GetHeap()->AllocateAccessorPair(); | 5926 return isolate->factory()->NewAccessorPair(); |
| 5925 } | 5927 } |
| 5926 | 5928 |
| 5927 | 5929 |
| 5928 MaybeObject* JSObject::DefinePropertyAccessor(Name* name, | 5930 void JSObject::DefinePropertyAccessor(Handle<JSObject> object, |
| 5929 Object* getter, | 5931 Handle<Name> name, |
| 5930 Object* setter, | 5932 Handle<Object> getter, |
| 5931 PropertyAttributes attributes) { | 5933 Handle<Object> setter, |
| 5934 PropertyAttributes attributes) { | |
| 5932 // We could assert that the property is configurable here, but we would need | 5935 // We could assert that the property is configurable here, but we would need |
| 5933 // to do a lookup, which seems to be a bit of overkill. | 5936 // to do a lookup, which seems to be a bit of overkill. |
| 5934 Heap* heap = GetHeap(); | 5937 Factory* factory = object->GetIsolate()->factory(); |
| 5935 bool only_attribute_changes = getter->IsNull() && setter->IsNull(); | 5938 bool only_attribute_changes = getter->IsNull() && setter->IsNull(); |
| 5936 if (HasFastProperties() && !only_attribute_changes && | 5939 if (object->HasFastProperties() && !only_attribute_changes && |
| 5937 (map()->NumberOfOwnDescriptors() < | 5940 (object->map()->NumberOfOwnDescriptors() < |
| 5938 DescriptorArray::kMaxNumberOfDescriptors)) { | 5941 DescriptorArray::kMaxNumberOfDescriptors)) { |
| 5939 MaybeObject* getterOk = heap->undefined_value(); | 5942 Handle<Object> getterOk = getter->IsNull() |
| 5940 if (!getter->IsNull()) { | 5943 ? Handle<Object>(factory->undefined_value()) |
|
rossberg
2013/07/02 12:20:47
Pass isolate. Though actually, isn't the construct
Michael Starzinger
2013/07/02 15:50:23
Done. As discussed offline: Returning an object he
| |
| 5941 getterOk = DefineFastAccessor(name, ACCESSOR_GETTER, getter, attributes); | 5944 : DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes); |
| 5942 if (getterOk->IsFailure()) return getterOk; | |
| 5943 } | |
| 5944 | 5945 |
| 5945 MaybeObject* setterOk = heap->undefined_value(); | 5946 Handle<Object> setterOk = getterOk->IsNull() || setter->IsNull() |
| 5946 if (getterOk != heap->null_value() && !setter->IsNull()) { | 5947 ? Handle<Object>(factory->undefined_value()) |
|
rossberg
2013/07/02 12:20:47
Same here
Michael Starzinger
2013/07/02 15:50:23
Likewise.
| |
| 5947 setterOk = DefineFastAccessor(name, ACCESSOR_SETTER, setter, attributes); | 5948 : DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes); |
| 5948 if (setterOk->IsFailure()) return setterOk; | |
| 5949 } | |
| 5950 | 5949 |
| 5951 if (getterOk != heap->null_value() && setterOk != heap->null_value()) { | 5950 if (!getterOk->IsNull() && !setterOk->IsNull()) { |
| 5952 return heap->undefined_value(); | 5951 return; |
| 5953 } | 5952 } |
| 5954 } | 5953 } |
| 5955 | 5954 |
| 5956 AccessorPair* accessors; | 5955 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); |
| 5957 MaybeObject* maybe_accessors = CreateAccessorPairFor(name); | 5956 accessors->SetComponents(*getter, *setter); |
| 5958 if (!maybe_accessors->To(&accessors)) return maybe_accessors; | |
| 5959 | 5957 |
| 5960 accessors->SetComponents(getter, setter); | 5958 CALL_HEAP_FUNCTION_VOID( |
| 5961 return SetPropertyCallback(name, accessors, attributes); | 5959 object->GetIsolate(), |
| 5960 object->SetPropertyCallback(*name, *accessors, attributes)); | |
| 5962 } | 5961 } |
| 5963 | 5962 |
| 5964 | 5963 |
| 5965 bool JSObject::CanSetCallback(Name* name) { | 5964 bool JSObject::CanSetCallback(Name* name) { |
| 5966 ASSERT(!IsAccessCheckNeeded() || | 5965 ASSERT(!IsAccessCheckNeeded() || |
| 5967 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 5966 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
| 5968 | 5967 |
| 5969 // Check if there is an API defined callback object which prohibits | 5968 // Check if there is an API defined callback object which prohibits |
| 5970 // callback overwriting in this object or its prototype chain. | 5969 // callback overwriting in this object or its prototype chain. |
| 5971 // This mechanism is needed for instance in a browser setting, where | 5970 // This mechanism is needed for instance in a browser setting, where |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6053 | 6052 |
| 6054 return GetHeap()->undefined_value(); | 6053 return GetHeap()->undefined_value(); |
| 6055 } | 6054 } |
| 6056 | 6055 |
| 6057 | 6056 |
| 6058 void JSObject::DefineAccessor(Handle<JSObject> object, | 6057 void JSObject::DefineAccessor(Handle<JSObject> object, |
| 6059 Handle<Name> name, | 6058 Handle<Name> name, |
| 6060 Handle<Object> getter, | 6059 Handle<Object> getter, |
| 6061 Handle<Object> setter, | 6060 Handle<Object> setter, |
| 6062 PropertyAttributes attributes) { | 6061 PropertyAttributes attributes) { |
| 6063 CALL_HEAP_FUNCTION_VOID( | 6062 Isolate* isolate = object->GetIsolate(); |
| 6064 object->GetIsolate(), | |
| 6065 object->DefineAccessor(*name, *getter, *setter, attributes)); | |
| 6066 } | |
| 6067 | |
| 6068 MaybeObject* JSObject::DefineAccessor(Name* name_raw, | |
| 6069 Object* getter_raw, | |
| 6070 Object* setter_raw, | |
| 6071 PropertyAttributes attributes) { | |
| 6072 Isolate* isolate = GetIsolate(); | |
| 6073 // Check access rights if needed. | 6063 // Check access rights if needed. |
| 6074 if (IsAccessCheckNeeded() && | 6064 if (object->IsAccessCheckNeeded() && |
| 6075 !isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { | 6065 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
| 6076 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 6066 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); |
| 6077 return isolate->heap()->undefined_value(); | 6067 return; |
| 6078 } | 6068 } |
| 6079 | 6069 |
| 6080 if (IsJSGlobalProxy()) { | 6070 if (object->IsJSGlobalProxy()) { |
| 6081 Object* proto = GetPrototype(); | 6071 Handle<Object> proto(object->GetPrototype(), isolate); |
| 6082 if (proto->IsNull()) return this; | 6072 if (proto->IsNull()) return; |
| 6083 ASSERT(proto->IsJSGlobalObject()); | 6073 ASSERT(proto->IsJSGlobalObject()); |
| 6084 return JSObject::cast(proto)->DefineAccessor( | 6074 DefineAccessor( |
| 6085 name_raw, getter_raw, setter_raw, attributes); | 6075 Handle<JSObject>::cast(proto), name, getter, setter, attributes); |
| 6076 return; | |
| 6086 } | 6077 } |
| 6087 | 6078 |
| 6088 // Make sure that the top context does not change when doing callbacks or | 6079 // Make sure that the top context does not change when doing callbacks or |
| 6089 // interceptor calls. | 6080 // interceptor calls. |
| 6090 AssertNoContextChange ncc; | 6081 AssertNoContextChange ncc; |
| 6091 | 6082 |
| 6092 // Try to flatten before operating on the string. | 6083 // Try to flatten before operating on the string. |
| 6093 if (name_raw->IsString()) String::cast(name_raw)->TryFlatten(); | 6084 if (name->IsString()) String::cast(*name)->TryFlatten(); |
| 6094 | 6085 |
| 6095 if (!CanSetCallback(name_raw)) return isolate->heap()->undefined_value(); | 6086 if (!object->CanSetCallback(*name)) return; |
| 6096 | |
| 6097 // From this point on everything needs to be handlified. | |
|
rossberg
2013/07/02 12:20:47
Glad this goes away...
| |
| 6098 HandleScope scope(isolate); | |
| 6099 Handle<JSObject> self(this); | |
| 6100 Handle<Name> name(name_raw); | |
| 6101 Handle<Object> getter(getter_raw, isolate); | |
| 6102 Handle<Object> setter(setter_raw, isolate); | |
| 6103 | 6087 |
| 6104 uint32_t index = 0; | 6088 uint32_t index = 0; |
| 6105 bool is_element = name->AsArrayIndex(&index); | 6089 bool is_element = name->AsArrayIndex(&index); |
| 6106 | 6090 |
| 6107 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6091 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 6108 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); | 6092 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); |
| 6109 bool preexists = false; | 6093 bool preexists = false; |
| 6110 if (is_observed) { | 6094 if (is_observed) { |
| 6111 if (is_element) { | 6095 if (is_element) { |
| 6112 preexists = HasLocalElement(index); | 6096 preexists = object->HasLocalElement(index); |
| 6113 if (preexists && self->GetLocalElementAccessorPair(index) == NULL) { | 6097 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { |
| 6114 old_value = Object::GetElement(self, index); | 6098 old_value = Object::GetElement(object, index); |
| 6115 } | 6099 } |
| 6116 } else { | 6100 } else { |
| 6117 LookupResult lookup(isolate); | 6101 LookupResult lookup(isolate); |
| 6118 LocalLookup(*name, &lookup, true); | 6102 object->LocalLookup(*name, &lookup, true); |
| 6119 preexists = lookup.IsProperty(); | 6103 preexists = lookup.IsProperty(); |
| 6120 if (preexists && lookup.IsDataProperty()) { | 6104 if (preexists && lookup.IsDataProperty()) { |
| 6121 old_value = Object::GetProperty(self, name); | 6105 old_value = Object::GetProperty(object, name); |
| 6122 } | 6106 } |
| 6123 } | 6107 } |
| 6124 } | 6108 } |
| 6125 | 6109 |
| 6126 MaybeObject* result = is_element ? | 6110 if (is_element) { |
| 6127 self->DefineElementAccessor(index, *getter, *setter, attributes) : | 6111 DefineElementAccessor(object, index, getter, setter, attributes); |
| 6128 self->DefinePropertyAccessor(*name, *getter, *setter, attributes); | 6112 } else { |
| 6129 | 6113 DefinePropertyAccessor(object, name, getter, setter, attributes); |
| 6130 Handle<Object> hresult; | 6114 } |
| 6131 if (!result->ToHandle(&hresult, isolate)) return result; | |
| 6132 | 6115 |
| 6133 if (is_observed) { | 6116 if (is_observed) { |
| 6134 const char* type = preexists ? "reconfigured" : "new"; | 6117 const char* type = preexists ? "reconfigured" : "new"; |
| 6135 EnqueueChangeRecord(self, type, name, old_value); | 6118 EnqueueChangeRecord(object, type, name, old_value); |
| 6136 } | 6119 } |
| 6137 | |
| 6138 return *hresult; | |
| 6139 } | 6120 } |
| 6140 | 6121 |
| 6141 | 6122 |
| 6142 static MaybeObject* TryAccessorTransition(JSObject* self, | 6123 static MaybeObject* TryAccessorTransition(JSObject* self, |
| 6143 Map* transitioned_map, | 6124 Map* transitioned_map, |
| 6144 int target_descriptor, | 6125 int target_descriptor, |
| 6145 AccessorComponent component, | 6126 AccessorComponent component, |
| 6146 Object* accessor, | 6127 Object* accessor, |
| 6147 PropertyAttributes attributes) { | 6128 PropertyAttributes attributes) { |
| 6148 DescriptorArray* descs = transitioned_map->instance_descriptors(); | 6129 DescriptorArray* descs = transitioned_map->instance_descriptors(); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 6161 self->set_map(transitioned_map); | 6142 self->set_map(transitioned_map); |
| 6162 return self; | 6143 return self; |
| 6163 } | 6144 } |
| 6164 | 6145 |
| 6165 // If either not the same accessor, or not the same attributes, fall back to | 6146 // If either not the same accessor, or not the same attributes, fall back to |
| 6166 // the slow case. | 6147 // the slow case. |
| 6167 return self->GetHeap()->null_value(); | 6148 return self->GetHeap()->null_value(); |
| 6168 } | 6149 } |
| 6169 | 6150 |
| 6170 | 6151 |
| 6171 MaybeObject* JSObject::DefineFastAccessor(Name* name, | 6152 static MaybeObject* CopyInsertDescriptor(Map* map, |
| 6172 AccessorComponent component, | 6153 Name* name, |
| 6173 Object* accessor, | 6154 AccessorPair* accessors, |
| 6174 PropertyAttributes attributes) { | 6155 PropertyAttributes attributes) { |
| 6156 CallbacksDescriptor new_accessors_desc(name, accessors, attributes); | |
| 6157 return map->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION); | |
| 6158 } | |
| 6159 | |
| 6160 | |
| 6161 static Handle<Map> CopyInsertDescriptor(Handle<Map> map, | |
| 6162 Handle<Name> name, | |
| 6163 Handle<AccessorPair> accessors, | |
| 6164 PropertyAttributes attributes) { | |
| 6165 CALL_HEAP_FUNCTION(map->GetIsolate(), | |
| 6166 CopyInsertDescriptor(*map, *name, *accessors, attributes), | |
| 6167 Map); | |
| 6168 } | |
| 6169 | |
| 6170 | |
| 6171 Handle<Object> JSObject::DefineFastAccessor(Handle<JSObject> object, | |
| 6172 Handle<Name> name, | |
| 6173 AccessorComponent component, | |
| 6174 Handle<Object> accessor, | |
| 6175 PropertyAttributes attributes) { | |
| 6175 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); | 6176 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); |
| 6176 LookupResult result(GetIsolate()); | 6177 Isolate* isolate = object->GetIsolate(); |
| 6177 LocalLookup(name, &result); | 6178 LookupResult result(isolate); |
| 6179 object->LocalLookup(*name, &result); | |
| 6178 | 6180 |
| 6179 if (result.IsFound() && !result.IsPropertyCallbacks()) { | 6181 if (result.IsFound() && !result.IsPropertyCallbacks()) { |
| 6180 return GetHeap()->null_value(); | 6182 return isolate->factory()->null_value(); |
| 6181 } | 6183 } |
| 6182 | 6184 |
| 6183 // Return success if the same accessor with the same attributes already exist. | 6185 // Return success if the same accessor with the same attributes already exist. |
| 6184 AccessorPair* source_accessors = NULL; | 6186 AccessorPair* source_accessors = NULL; |
| 6185 if (result.IsPropertyCallbacks()) { | 6187 if (result.IsPropertyCallbacks()) { |
| 6186 Object* callback_value = result.GetCallbackObject(); | 6188 Object* callback_value = result.GetCallbackObject(); |
| 6187 if (callback_value->IsAccessorPair()) { | 6189 if (callback_value->IsAccessorPair()) { |
| 6188 source_accessors = AccessorPair::cast(callback_value); | 6190 source_accessors = AccessorPair::cast(callback_value); |
| 6189 Object* entry = source_accessors->get(component); | 6191 Object* entry = source_accessors->get(component); |
| 6190 if (entry == accessor && result.GetAttributes() == attributes) { | 6192 if (entry == *accessor && result.GetAttributes() == attributes) { |
| 6191 return this; | 6193 return object; |
| 6192 } | 6194 } |
| 6193 } else { | 6195 } else { |
| 6194 return GetHeap()->null_value(); | 6196 return isolate->factory()->null_value(); |
| 6195 } | 6197 } |
| 6196 | 6198 |
| 6197 int descriptor_number = result.GetDescriptorIndex(); | 6199 int descriptor_number = result.GetDescriptorIndex(); |
| 6198 | 6200 |
| 6199 map()->LookupTransition(this, name, &result); | 6201 object->map()->LookupTransition(*object, *name, &result); |
| 6200 | 6202 |
| 6201 if (result.IsFound()) { | 6203 if (result.IsFound()) { |
| 6202 Map* target = result.GetTransitionTarget(); | 6204 Map* target = result.GetTransitionTarget(); |
| 6203 ASSERT(target->NumberOfOwnDescriptors() == | 6205 ASSERT(target->NumberOfOwnDescriptors() == |
| 6204 map()->NumberOfOwnDescriptors()); | 6206 object->map()->NumberOfOwnDescriptors()); |
| 6205 // This works since descriptors are sorted in order of addition. | 6207 // This works since descriptors are sorted in order of addition. |
| 6206 ASSERT(map()->instance_descriptors()->GetKey(descriptor_number) == name); | 6208 ASSERT(object->map()->instance_descriptors()-> |
| 6207 return TryAccessorTransition( | 6209 GetKey(descriptor_number) == *name); |
| 6208 this, target, descriptor_number, component, accessor, attributes); | 6210 CALL_HEAP_FUNCTION( |
| 6211 isolate, | |
| 6212 TryAccessorTransition(*object, target, descriptor_number, | |
| 6213 component, *accessor, attributes), | |
| 6214 Object); | |
| 6209 } | 6215 } |
| 6210 } else { | 6216 } else { |
| 6211 // If not, lookup a transition. | 6217 // If not, lookup a transition. |
| 6212 map()->LookupTransition(this, name, &result); | 6218 object->map()->LookupTransition(*object, *name, &result); |
| 6213 | 6219 |
| 6214 // If there is a transition, try to follow it. | 6220 // If there is a transition, try to follow it. |
| 6215 if (result.IsFound()) { | 6221 if (result.IsFound()) { |
| 6216 Map* target = result.GetTransitionTarget(); | 6222 Map* target = result.GetTransitionTarget(); |
| 6217 int descriptor_number = target->LastAdded(); | 6223 int descriptor_number = target->LastAdded(); |
| 6218 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) | 6224 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) |
| 6219 ->Equals(name)); | 6225 ->Equals(*name)); |
| 6220 return TryAccessorTransition( | 6226 CALL_HEAP_FUNCTION( |
| 6221 this, target, descriptor_number, component, accessor, attributes); | 6227 isolate, |
| 6228 TryAccessorTransition(*object, target, descriptor_number, | |
| 6229 component, *accessor, attributes), | |
| 6230 Object); | |
| 6222 } | 6231 } |
| 6223 } | 6232 } |
| 6224 | 6233 |
| 6225 // If there is no transition yet, add a transition to the a new accessor pair | 6234 // If there is no transition yet, add a transition to the a new accessor pair |
| 6226 // containing the accessor. | 6235 // containing the accessor. Allocate a new pair if there were no source |
| 6227 AccessorPair* accessors; | 6236 // accessors. Otherwise, copy the pair and modify the accessor. |
| 6228 MaybeObject* maybe_accessors; | 6237 Handle<AccessorPair> accessors = source_accessors != NULL |
| 6229 | 6238 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) |
|
rossberg
2013/07/02 12:20:47
Pass isolate
Michael Starzinger
2013/07/02 15:50:23
As discussed offline: Not needed here.
| |
| 6230 // Allocate a new pair if there were no source accessors. Otherwise, copy the | 6239 : isolate->factory()->NewAccessorPair(); |
| 6231 // pair and modify the accessor. | 6240 accessors->set(component, *accessor); |
| 6232 if (source_accessors != NULL) { | 6241 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), |
| 6233 maybe_accessors = source_accessors->Copy(); | 6242 name, accessors, attributes); |
| 6234 } else { | 6243 object->set_map(*new_map); |
| 6235 maybe_accessors = GetHeap()->AllocateAccessorPair(); | 6244 return object; |
| 6236 } | |
| 6237 if (!maybe_accessors->To(&accessors)) return maybe_accessors; | |
| 6238 accessors->set(component, accessor); | |
| 6239 | |
| 6240 CallbacksDescriptor new_accessors_desc(name, accessors, attributes); | |
| 6241 | |
| 6242 Map* new_map; | |
| 6243 MaybeObject* maybe_new_map = | |
| 6244 map()->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION); | |
| 6245 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 6246 | |
| 6247 set_map(new_map); | |
| 6248 return this; | |
| 6249 } | 6245 } |
| 6250 | 6246 |
| 6251 | 6247 |
| 6252 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { | 6248 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { |
| 6253 Isolate* isolate = GetIsolate(); | 6249 Isolate* isolate = GetIsolate(); |
| 6254 Name* name = Name::cast(info->name()); | 6250 Name* name = Name::cast(info->name()); |
| 6255 // Check access rights if needed. | 6251 // Check access rights if needed. |
| 6256 if (IsAccessCheckNeeded() && | 6252 if (IsAccessCheckNeeded() && |
| 6257 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 6253 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 6258 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 6254 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| (...skipping 1559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7818 } | 7814 } |
| 7819 if (child_hash <= parent_hash) break; | 7815 if (child_hash <= parent_hash) break; |
| 7820 SwapSortedKeys(parent_index, child_index); | 7816 SwapSortedKeys(parent_index, child_index); |
| 7821 parent_index = child_index; | 7817 parent_index = child_index; |
| 7822 } | 7818 } |
| 7823 } | 7819 } |
| 7824 ASSERT(IsSortedNoDuplicates()); | 7820 ASSERT(IsSortedNoDuplicates()); |
| 7825 } | 7821 } |
| 7826 | 7822 |
| 7827 | 7823 |
| 7828 MaybeObject* AccessorPair::Copy() { | 7824 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) { |
| 7829 Heap* heap = GetHeap(); | 7825 Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair(); |
| 7830 AccessorPair* copy; | 7826 copy->set_getter(pair->getter()); |
| 7831 MaybeObject* maybe_copy = heap->AllocateAccessorPair(); | 7827 copy->set_setter(pair->setter()); |
| 7832 if (!maybe_copy->To(©)) return maybe_copy; | |
| 7833 | |
| 7834 copy->set_getter(getter()); | |
| 7835 copy->set_setter(setter()); | |
| 7836 return copy; | 7828 return copy; |
| 7837 } | 7829 } |
| 7838 | 7830 |
| 7839 | 7831 |
| 7840 Object* AccessorPair::GetComponent(AccessorComponent component) { | 7832 Object* AccessorPair::GetComponent(AccessorComponent component) { |
| 7841 Object* accessor = get(component); | 7833 Object* accessor = get(component); |
| 7842 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; | 7834 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; |
| 7843 } | 7835 } |
| 7844 | 7836 |
| 7845 | 7837 |
| (...skipping 7976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15822 | 15814 |
| 15823 void PropertyCell::AddDependentCode(Handle<Code> code) { | 15815 void PropertyCell::AddDependentCode(Handle<Code> code) { |
| 15824 Handle<DependentCode> codes = DependentCode::Insert( | 15816 Handle<DependentCode> codes = DependentCode::Insert( |
| 15825 Handle<DependentCode>(dependent_code()), | 15817 Handle<DependentCode>(dependent_code()), |
| 15826 DependentCode::kPropertyCellChangedGroup, code); | 15818 DependentCode::kPropertyCellChangedGroup, code); |
| 15827 if (*codes != dependent_code()) set_dependent_code(*codes); | 15819 if (*codes != dependent_code()) set_dependent_code(*codes); |
| 15828 } | 15820 } |
| 15829 | 15821 |
| 15830 | 15822 |
| 15831 } } // namespace v8::internal | 15823 } } // namespace v8::internal |
| OLD | NEW |