Chromium Code Reviews| 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 |