Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: src/objects.cc

Issue 11365111: Object.observe: generate change records for indexed properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW
« src/elements.cc ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698