OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3295 } | 3295 } |
3296 } | 3296 } |
3297 return ABSENT; | 3297 return ABSENT; |
3298 } | 3298 } |
3299 | 3299 |
3300 | 3300 |
3301 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) { | 3301 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) { |
3302 // Check whether the name is an array index. | 3302 // Check whether the name is an array index. |
3303 uint32_t index = 0; | 3303 uint32_t index = 0; |
3304 if (IsJSObject() && name->AsArrayIndex(&index)) { | 3304 if (IsJSObject() && name->AsArrayIndex(&index)) { |
3305 if (JSObject::cast(this)->HasLocalElement(index)) return NONE; | 3305 return GetLocalElementAttribute(index); |
3306 return ABSENT; | |
3307 } | 3306 } |
3308 // Named property. | 3307 // Named property. |
3309 LookupResult lookup(GetIsolate()); | 3308 LookupResult lookup(GetIsolate()); |
3310 LocalLookup(name, &lookup); | 3309 LocalLookup(name, &lookup); |
3311 return GetPropertyAttributeForResult(this, &lookup, name, false); | 3310 return GetPropertyAttributeForResult(this, &lookup, name, false); |
3312 } | 3311 } |
3313 | 3312 |
3314 | 3313 |
3314 PropertyAttributes JSObject::GetLocalElementAttribute(uint32_t index) { | |
3315 // Check access rights if needed. | |
3316 if (IsAccessCheckNeeded()) { | |
3317 Heap* heap = GetHeap(); | |
3318 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | |
3319 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | |
3320 return ABSENT; | |
3321 } | |
3322 } | |
3323 | |
3324 if (IsJSGlobalProxy()) { | |
3325 Object* proto = GetPrototype(); | |
3326 if (proto->IsNull()) return ABSENT; | |
3327 ASSERT(proto->IsJSGlobalObject()); | |
3328 return JSReceiver::cast(proto)->GetLocalElementAttribute(index); | |
3329 } | |
3330 | |
3331 return GetElementsAccessor()->GetAttributes(this, this, index); | |
3332 } | |
3333 | |
3334 | |
3315 MaybeObject* NormalizedMapCache::Get(JSObject* obj, | 3335 MaybeObject* NormalizedMapCache::Get(JSObject* obj, |
3316 PropertyNormalizationMode mode) { | 3336 PropertyNormalizationMode mode) { |
3317 Isolate* isolate = obj->GetIsolate(); | 3337 Isolate* isolate = obj->GetIsolate(); |
3318 Map* fast = obj->map(); | 3338 Map* fast = obj->map(); |
3319 int index = fast->Hash() % kEntries; | 3339 int index = fast->Hash() % kEntries; |
3320 Object* result = get(index); | 3340 Object* result = get(index); |
3321 if (result->IsMap() && | 3341 if (result->IsMap() && |
3322 Map::cast(result)->EquivalentToForNormalization(fast, mode)) { | 3342 Map::cast(result)->EquivalentToForNormalization(fast, mode)) { |
3323 #ifdef VERIFY_HEAP | 3343 #ifdef VERIFY_HEAP |
3324 if (FLAG_verify_heap) { | 3344 if (FLAG_verify_heap) { |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4026 return isolate->heap()->false_value(); | 4046 return isolate->heap()->false_value(); |
4027 } | 4047 } |
4028 | 4048 |
4029 if (IsJSGlobalProxy()) { | 4049 if (IsJSGlobalProxy()) { |
4030 Object* proto = GetPrototype(); | 4050 Object* proto = GetPrototype(); |
4031 if (proto->IsNull()) return isolate->heap()->false_value(); | 4051 if (proto->IsNull()) return isolate->heap()->false_value(); |
4032 ASSERT(proto->IsJSGlobalObject()); | 4052 ASSERT(proto->IsJSGlobalObject()); |
4033 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); | 4053 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); |
4034 } | 4054 } |
4035 | 4055 |
4036 if (HasIndexedInterceptor()) { | 4056 // From this point on everything needs to be handlified. |
4037 // Skip interceptor if forcing deletion. | 4057 HandleScope scope(isolate); |
4038 if (mode != FORCE_DELETION) { | 4058 Handle<JSObject> self(this); |
4039 return DeleteElementWithInterceptor(index); | 4059 |
4060 Handle<String> name; | |
4061 Handle<Object> old_value(isolate->heap()->the_hole_value()); | |
4062 bool preexists = false; | |
4063 if (FLAG_harmony_observation && map()->is_observed()) { | |
4064 name = isolate->factory()->Uint32ToString(index); | |
4065 preexists = self->HasLocalElement(index); | |
4066 if (preexists) { | |
4067 // TODO(observe): only read & set old_value if it's not an accessor | |
4068 old_value = Object::GetElement(self, index); | |
4040 } | 4069 } |
4041 mode = JSReceiver::FORCE_DELETION; | |
4042 } | 4070 } |
4043 | 4071 |
4044 return GetElementsAccessor()->Delete(this, index, mode); | 4072 MaybeObject* result; |
4073 // Skip interceptor if forcing deletion. | |
4074 if (self->HasIndexedInterceptor()) { | |
Toon Verwaest
2012/11/07 10:06:52
Maybe use (self->HasIndexedInterceptor() && mode !
rossberg
2012/11/07 18:41:42
Done.
| |
4075 if (mode != FORCE_DELETION) | |
4076 result = self->DeleteElementWithInterceptor(index); | |
4077 else | |
4078 result = self->GetElementsAccessor()->Delete( | |
4079 *self, index, JSReceiver::FORCE_DELETION); | |
4080 } else { | |
4081 result = self->GetElementsAccessor()->Delete(*self, index, mode); | |
4082 } | |
4083 | |
4084 Handle<Object> hresult; | |
4085 if (!result->ToHandle(&hresult)) return result; | |
4086 | |
4087 if (FLAG_harmony_observation && map()->is_observed()) { | |
4088 if (preexists && !self->HasLocalElement(index)) | |
4089 self->EnqueueChangeRecord("deleted", name, old_value); | |
4090 } | |
4091 | |
4092 return *hresult; | |
4045 } | 4093 } |
4046 | 4094 |
4047 | 4095 |
4048 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj, | 4096 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj, |
4049 Handle<String> prop) { | 4097 Handle<String> prop) { |
4050 CALL_HEAP_FUNCTION(obj->GetIsolate(), | 4098 CALL_HEAP_FUNCTION(obj->GetIsolate(), |
4051 obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION), | 4099 obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION), |
4052 Object); | 4100 Object); |
4053 } | 4101 } |
4054 | 4102 |
(...skipping 6052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10107 } | 10155 } |
10108 } | 10156 } |
10109 CALL_HEAP_FUNCTION( | 10157 CALL_HEAP_FUNCTION( |
10110 object->GetIsolate(), | 10158 object->GetIsolate(), |
10111 object->SetElement(index, *value, attr, strict_mode, true, set_mode), | 10159 object->SetElement(index, *value, attr, strict_mode, true, set_mode), |
10112 Object); | 10160 Object); |
10113 } | 10161 } |
10114 | 10162 |
10115 | 10163 |
10116 MaybeObject* JSObject::SetElement(uint32_t index, | 10164 MaybeObject* JSObject::SetElement(uint32_t index, |
10117 Object* value, | 10165 Object* value_raw, |
10118 PropertyAttributes attributes, | 10166 PropertyAttributes attributes, |
10119 StrictModeFlag strict_mode, | 10167 StrictModeFlag strict_mode, |
10120 bool check_prototype, | 10168 bool check_prototype, |
10121 SetPropertyMode set_mode) { | 10169 SetPropertyMode set_mode) { |
10170 Isolate* isolate = GetIsolate(); | |
10171 HandleScope scope(isolate); | |
10172 Handle<JSObject> self(this); | |
10173 Handle<Object> value(value_raw); | |
10174 | |
10122 // Check access rights if needed. | 10175 // Check access rights if needed. |
10123 if (IsAccessCheckNeeded()) { | 10176 if (IsAccessCheckNeeded()) { |
10124 Heap* heap = GetHeap(); | 10177 Heap* heap = GetHeap(); |
10125 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 10178 if (!heap->isolate()->MayIndexedAccess(*self, index, v8::ACCESS_SET)) { |
10126 HandleScope scope(heap->isolate()); | 10179 heap->isolate()->ReportFailedAccessCheck(*self, v8::ACCESS_SET); |
10127 Handle<Object> value_handle(value); | 10180 return *value; |
10128 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); | |
10129 return *value_handle; | |
10130 } | 10181 } |
10131 } | 10182 } |
10132 | 10183 |
10133 if (IsJSGlobalProxy()) { | 10184 if (IsJSGlobalProxy()) { |
10134 Object* proto = GetPrototype(); | 10185 Object* proto = GetPrototype(); |
10135 if (proto->IsNull()) return value; | 10186 if (proto->IsNull()) return *value; |
10136 ASSERT(proto->IsJSGlobalObject()); | 10187 ASSERT(proto->IsJSGlobalObject()); |
10137 return JSObject::cast(proto)->SetElement(index, | 10188 return JSObject::cast(proto)->SetElement(index, |
10138 value, | 10189 *value, |
10139 attributes, | 10190 attributes, |
10140 strict_mode, | 10191 strict_mode, |
10141 check_prototype, | 10192 check_prototype, |
10142 set_mode); | 10193 set_mode); |
10143 } | 10194 } |
10144 | 10195 |
10145 // Don't allow element properties to be redefined for external arrays. | 10196 // Don't allow element properties to be redefined for external arrays. |
10146 if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) { | 10197 if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) { |
10147 Isolate* isolate = GetHeap()->isolate(); | |
10148 Handle<Object> receiver(this); | |
10149 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 10198 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
10150 Handle<Object> args[] = { receiver, number }; | 10199 Handle<Object> args[] = { self, number }; |
10151 Handle<Object> error = isolate->factory()->NewTypeError( | 10200 Handle<Object> error = isolate->factory()->NewTypeError( |
10152 "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args))); | 10201 "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args))); |
10153 return isolate->Throw(*error); | 10202 return isolate->Throw(*error); |
10154 } | 10203 } |
10155 | 10204 |
10156 // Normalize the elements to enable attributes on the property. | 10205 // Normalize the elements to enable attributes on the property. |
10157 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { | 10206 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { |
10158 SeededNumberDictionary* dictionary; | 10207 SeededNumberDictionary* dictionary; |
10159 MaybeObject* maybe_object = NormalizeElements(); | 10208 MaybeObject* maybe_object = NormalizeElements(); |
10160 if (!maybe_object->To(&dictionary)) return maybe_object; | 10209 if (!maybe_object->To(&dictionary)) return maybe_object; |
10161 // Make sure that we never go back to fast case. | 10210 // Make sure that we never go back to fast case. |
10162 dictionary->set_requires_slow_elements(); | 10211 dictionary->set_requires_slow_elements(); |
10163 } | 10212 } |
10164 | 10213 |
10165 // Check for lookup interceptor | 10214 // From here on, everything has to be handlified. |
10166 if (HasIndexedInterceptor()) { | 10215 Handle<String> name; |
10167 return SetElementWithInterceptor(index, | 10216 Handle<Object> old_value(isolate->heap()->the_hole_value()); |
10168 value, | 10217 PropertyAttributes old_attributes; |
10169 attributes, | 10218 bool preexists = false; |
10170 strict_mode, | 10219 if (FLAG_harmony_observation && map()->is_observed()) { |
10171 check_prototype, | 10220 name = isolate->factory()->Uint32ToString(index); |
10172 set_mode); | 10221 preexists = self->HasLocalElement(index); |
10222 if (preexists) { | |
10223 old_attributes = self->GetLocalPropertyAttribute(*name); | |
10224 // TODO(observe): only read & set old_value if we have a data property | |
10225 old_value = Object::GetElement(self, index); | |
10226 } | |
10173 } | 10227 } |
10174 | 10228 |
10175 return SetElementWithoutInterceptor(index, | 10229 // Check for lookup interceptor |
10176 value, | 10230 MaybeObject* result = *value; |
Toon Verwaest
2012/11/07 10:06:52
This initialization seems superfluous since it's o
rossberg
2012/11/07 18:41:42
Done.
| |
10177 attributes, | 10231 if (self->HasIndexedInterceptor()) { |
10178 strict_mode, | 10232 result = self->SetElementWithInterceptor(index, |
10179 check_prototype, | 10233 *value, |
10180 set_mode); | 10234 attributes, |
10235 strict_mode, | |
10236 check_prototype, | |
10237 set_mode); | |
10238 } else { | |
10239 result = self->SetElementWithoutInterceptor(index, | |
10240 *value, | |
10241 attributes, | |
10242 strict_mode, | |
10243 check_prototype, | |
10244 set_mode); | |
10245 } | |
10246 | |
10247 Handle<Object> hresult; | |
10248 if (!result->ToHandle(&hresult)) return result; | |
10249 | |
10250 if (FLAG_harmony_observation && map()->is_observed()) { | |
10251 PropertyAttributes new_attributes = self->GetLocalPropertyAttribute(*name); | |
10252 if (!preexists) { | |
10253 self->EnqueueChangeRecord("new", name, old_value); | |
10254 } else if (new_attributes != old_attributes || old_value->IsTheHole()) { | |
10255 self->EnqueueChangeRecord("reconfigured", name, old_value); | |
10256 } else { | |
10257 Handle<Object> newValue = Object::GetElement(self, index); | |
10258 if (!newValue->SameValue(*old_value)) | |
10259 self->EnqueueChangeRecord("updated", name, old_value); | |
10260 } | |
10261 } | |
10262 | |
10263 return *hresult; | |
10181 } | 10264 } |
10182 | 10265 |
10183 | 10266 |
10184 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 10267 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
10185 Object* value, | 10268 Object* value, |
10186 PropertyAttributes attr, | 10269 PropertyAttributes attr, |
10187 StrictModeFlag strict_mode, | 10270 StrictModeFlag strict_mode, |
10188 bool check_prototype, | 10271 bool check_prototype, |
10189 SetPropertyMode set_mode) { | 10272 SetPropertyMode set_mode) { |
10190 ASSERT(HasDictionaryElements() || | 10273 ASSERT(HasDictionaryElements() || |
(...skipping 3491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13682 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13765 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13683 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13766 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13684 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13767 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13685 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13768 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13686 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13769 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13687 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13770 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13688 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13771 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13689 } | 13772 } |
13690 | 13773 |
13691 } } // namespace v8::internal | 13774 } } // namespace v8::internal |
OLD | NEW |