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

Side by Side Diff: src/objects.cc

Issue 183683022: Enable Object.observe by default (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 9 months 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 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 2181 matching lines...) Expand 10 before | Expand all | Expand 10 after
2192 } else { 2192 } else {
2193 // Normalize the object to prevent very large instance descriptors. 2193 // Normalize the object to prevent very large instance descriptors.
2194 // This eliminates unwanted N^2 allocation and lookup behavior. 2194 // This eliminates unwanted N^2 allocation and lookup behavior.
2195 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); 2195 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
2196 AddSlowProperty(object, name, value, attributes); 2196 AddSlowProperty(object, name, value, attributes);
2197 } 2197 }
2198 } else { 2198 } else {
2199 AddSlowProperty(object, name, value, attributes); 2199 AddSlowProperty(object, name, value, attributes);
2200 } 2200 }
2201 2201
2202 if (FLAG_harmony_observation && 2202 if (object->map()->is_observed() &&
2203 object->map()->is_observed() &&
2204 *name != isolate->heap()->hidden_string()) { 2203 *name != isolate->heap()->hidden_string()) {
2205 Handle<Object> old_value = isolate->factory()->the_hole_value(); 2204 Handle<Object> old_value = isolate->factory()->the_hole_value();
2206 EnqueueChangeRecord(object, "add", name, old_value); 2205 EnqueueChangeRecord(object, "add", name, old_value);
2207 } 2206 }
2208 2207
2209 return value; 2208 return value;
2210 } 2209 }
2211 2210
2212 2211
2213 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, 2212 void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
(...skipping 1871 matching lines...) Expand 10 before | Expand all | Expand 10 after
4085 Handle<Object> error = isolate->factory()->NewTypeError( 4084 Handle<Object> error = isolate->factory()->NewTypeError(
4086 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); 4085 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
4087 isolate->Throw(*error); 4086 isolate->Throw(*error);
4088 return Handle<Object>(); 4087 return Handle<Object>();
4089 } else { 4088 } else {
4090 return value; 4089 return value;
4091 } 4090 }
4092 } 4091 }
4093 4092
4094 Handle<Object> old_value = isolate->factory()->the_hole_value(); 4093 Handle<Object> old_value = isolate->factory()->the_hole_value();
4095 bool is_observed = FLAG_harmony_observation && 4094 bool is_observed = object->map()->is_observed() &&
4096 object->map()->is_observed() &&
4097 *name != isolate->heap()->hidden_string(); 4095 *name != isolate->heap()->hidden_string();
4098 if (is_observed && lookup->IsDataProperty()) { 4096 if (is_observed && lookup->IsDataProperty()) {
4099 old_value = Object::GetProperty(object, name); 4097 old_value = Object::GetProperty(object, name);
4100 } 4098 }
4101 4099
4102 // This is a real property that is not read-only, or it is a 4100 // This is a real property that is not read-only, or it is a
4103 // transition or null descriptor and there are no setters in the prototypes. 4101 // transition or null descriptor and there are no setters in the prototypes.
4104 Handle<Object> result = value; 4102 Handle<Object> result = value;
4105 switch (lookup->type()) { 4103 switch (lookup->type()) {
4106 case NORMAL: 4104 case NORMAL:
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
4208 object->map()->LookupTransition(*object, *name, &lookup); 4206 object->map()->LookupTransition(*object, *name, &lookup);
4209 TransitionFlag flag = lookup.IsFound() 4207 TransitionFlag flag = lookup.IsFound()
4210 ? OMIT_TRANSITION : INSERT_TRANSITION; 4208 ? OMIT_TRANSITION : INSERT_TRANSITION;
4211 // Neither properties nor transitions found. 4209 // Neither properties nor transitions found.
4212 return AddProperty(object, name, value, attributes, kNonStrictMode, 4210 return AddProperty(object, name, value, attributes, kNonStrictMode,
4213 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag); 4211 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag);
4214 } 4212 }
4215 4213
4216 Handle<Object> old_value = isolate->factory()->the_hole_value(); 4214 Handle<Object> old_value = isolate->factory()->the_hole_value();
4217 PropertyAttributes old_attributes = ABSENT; 4215 PropertyAttributes old_attributes = ABSENT;
4218 bool is_observed = FLAG_harmony_observation && 4216 bool is_observed = object->map()->is_observed() &&
4219 object->map()->is_observed() &&
4220 *name != isolate->heap()->hidden_string(); 4217 *name != isolate->heap()->hidden_string();
4221 if (is_observed && lookup.IsProperty()) { 4218 if (is_observed && lookup.IsProperty()) {
4222 if (lookup.IsDataProperty()) old_value = 4219 if (lookup.IsDataProperty()) old_value =
4223 Object::GetProperty(object, name); 4220 Object::GetProperty(object, name);
4224 old_attributes = lookup.GetAttributes(); 4221 old_attributes = lookup.GetAttributes();
4225 } 4222 }
4226 4223
4227 // Check of IsReadOnly removed from here in clone. 4224 // Check of IsReadOnly removed from here in clone.
4228 switch (lookup.type()) { 4225 switch (lookup.type()) {
4229 case NORMAL: 4226 case NORMAL:
(...skipping 961 matching lines...) Expand 10 before | Expand all | Expand 10 after
5191 5188
5192 if (object->IsJSGlobalProxy()) { 5189 if (object->IsJSGlobalProxy()) {
5193 Handle<Object> proto(object->GetPrototype(), isolate); 5190 Handle<Object> proto(object->GetPrototype(), isolate);
5194 if (proto->IsNull()) return factory->false_value(); 5191 if (proto->IsNull()) return factory->false_value();
5195 ASSERT(proto->IsJSGlobalObject()); 5192 ASSERT(proto->IsJSGlobalObject());
5196 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); 5193 return DeleteElement(Handle<JSObject>::cast(proto), index, mode);
5197 } 5194 }
5198 5195
5199 Handle<Object> old_value; 5196 Handle<Object> old_value;
5200 bool should_enqueue_change_record = false; 5197 bool should_enqueue_change_record = false;
5201 if (FLAG_harmony_observation && object->map()->is_observed()) { 5198 if (object->map()->is_observed()) {
5202 should_enqueue_change_record = HasLocalElement(object, index); 5199 should_enqueue_change_record = HasLocalElement(object, index);
5203 if (should_enqueue_change_record) { 5200 if (should_enqueue_change_record) {
5204 old_value = object->GetLocalElementAccessorPair(index) != NULL 5201 old_value = object->GetLocalElementAccessorPair(index) != NULL
5205 ? Handle<Object>::cast(factory->the_hole_value()) 5202 ? Handle<Object>::cast(factory->the_hole_value())
5206 : Object::GetElement(isolate, object, index); 5203 : Object::GetElement(isolate, object, index);
5207 } 5204 }
5208 } 5205 }
5209 5206
5210 // Skip interceptor if forcing deletion. 5207 // Skip interceptor if forcing deletion.
5211 Handle<Object> result; 5208 Handle<Object> result;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
5262 Handle<Object> args[2] = { name, object }; 5259 Handle<Object> args[2] = { name, object };
5263 Handle<Object> error = isolate->factory()->NewTypeError( 5260 Handle<Object> error = isolate->factory()->NewTypeError(
5264 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); 5261 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args)));
5265 isolate->Throw(*error); 5262 isolate->Throw(*error);
5266 return Handle<Object>(); 5263 return Handle<Object>();
5267 } 5264 }
5268 return isolate->factory()->false_value(); 5265 return isolate->factory()->false_value();
5269 } 5266 }
5270 5267
5271 Handle<Object> old_value = isolate->factory()->the_hole_value(); 5268 Handle<Object> old_value = isolate->factory()->the_hole_value();
5272 bool is_observed = FLAG_harmony_observation && 5269 bool is_observed = object->map()->is_observed() &&
5273 object->map()->is_observed() &&
5274 *name != isolate->heap()->hidden_string(); 5270 *name != isolate->heap()->hidden_string();
5275 if (is_observed && lookup.IsDataProperty()) { 5271 if (is_observed && lookup.IsDataProperty()) {
5276 old_value = Object::GetProperty(object, name); 5272 old_value = Object::GetProperty(object, name);
5277 } 5273 }
5278 Handle<Object> result; 5274 Handle<Object> result;
5279 5275
5280 // Check for interceptor. 5276 // Check for interceptor.
5281 if (lookup.IsInterceptor()) { 5277 if (lookup.IsInterceptor()) {
5282 // Skip interceptor if forcing a deletion. 5278 // Skip interceptor if forcing a deletion.
5283 if (mode == FORCE_DELETION) { 5279 if (mode == FORCE_DELETION) {
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
5499 5495
5500 // Do a map transition, other objects with this map may still 5496 // Do a map transition, other objects with this map may still
5501 // be extensible. 5497 // be extensible.
5502 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. 5498 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5503 Handle<Map> new_map = Map::Copy(handle(object->map())); 5499 Handle<Map> new_map = Map::Copy(handle(object->map()));
5504 5500
5505 new_map->set_is_extensible(false); 5501 new_map->set_is_extensible(false);
5506 object->set_map(*new_map); 5502 object->set_map(*new_map);
5507 ASSERT(!object->map()->is_extensible()); 5503 ASSERT(!object->map()->is_extensible());
5508 5504
5509 if (FLAG_harmony_observation && object->map()->is_observed()) { 5505 if (object->map()->is_observed()) {
5510 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), 5506 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5511 isolate->factory()->the_hole_value()); 5507 isolate->factory()->the_hole_value());
5512 } 5508 }
5513 return object; 5509 return object;
5514 } 5510 }
5515 5511
5516 5512
5517 template<typename Dictionary> 5513 template<typename Dictionary>
5518 static void FreezeDictionary(Dictionary* dictionary) { 5514 static void FreezeDictionary(Dictionary* dictionary) {
5519 int capacity = dictionary->Capacity(); 5515 int capacity = dictionary->Capacity();
(...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after
6356 6352
6357 // Try to flatten before operating on the string. 6353 // Try to flatten before operating on the string.
6358 if (name->IsString()) String::cast(*name)->TryFlatten(); 6354 if (name->IsString()) String::cast(*name)->TryFlatten();
6359 6355
6360 if (!object->CanSetCallback(*name)) return; 6356 if (!object->CanSetCallback(*name)) return;
6361 6357
6362 uint32_t index = 0; 6358 uint32_t index = 0;
6363 bool is_element = name->AsArrayIndex(&index); 6359 bool is_element = name->AsArrayIndex(&index);
6364 6360
6365 Handle<Object> old_value = isolate->factory()->the_hole_value(); 6361 Handle<Object> old_value = isolate->factory()->the_hole_value();
6366 bool is_observed = FLAG_harmony_observation && 6362 bool is_observed = object->map()->is_observed() &&
6367 object->map()->is_observed() &&
6368 *name != isolate->heap()->hidden_string(); 6363 *name != isolate->heap()->hidden_string();
6369 bool preexists = false; 6364 bool preexists = false;
6370 if (is_observed) { 6365 if (is_observed) {
6371 if (is_element) { 6366 if (is_element) {
6372 preexists = HasLocalElement(object, index); 6367 preexists = HasLocalElement(object, index);
6373 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { 6368 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) {
6374 old_value = Object::GetElement(isolate, object, index); 6369 old_value = Object::GetElement(isolate, object, index);
6375 } 6370 }
6376 } else { 6371 } else {
6377 LookupResult lookup(isolate); 6372 LookupResult lookup(isolate);
(...skipping 5042 matching lines...) Expand 10 before | Expand all | Expand 10 after
11420 Handle<JSFunction>(isolate->observers_end_perform_splice()), 11415 Handle<JSFunction>(isolate->observers_end_perform_splice()),
11421 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args, 11416 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
11422 &threw); 11417 &threw);
11423 ASSERT(!threw); 11418 ASSERT(!threw);
11424 } 11419 }
11425 11420
11426 11421
11427 MaybeObject* JSArray::SetElementsLength(Object* len) { 11422 MaybeObject* JSArray::SetElementsLength(Object* len) {
11428 // We should never end in here with a pixel or external array. 11423 // We should never end in here with a pixel or external array.
11429 ASSERT(AllowsSetElementsLength()); 11424 ASSERT(AllowsSetElementsLength());
11430 if (!(FLAG_harmony_observation && map()->is_observed())) 11425 if (!map()->is_observed())
11431 return GetElementsAccessor()->SetLength(this, len); 11426 return GetElementsAccessor()->SetLength(this, len);
11432 11427
11433 Isolate* isolate = GetIsolate(); 11428 Isolate* isolate = GetIsolate();
11434 HandleScope scope(isolate); 11429 HandleScope scope(isolate);
11435 Handle<JSArray> self(this); 11430 Handle<JSArray> self(this);
11436 List<uint32_t> indices; 11431 List<uint32_t> indices;
11437 List<Handle<Object> > old_values; 11432 List<Handle<Object> > old_values;
11438 Handle<Object> old_length_handle(self->length(), isolate); 11433 Handle<Object> old_length_handle(self->length(), isolate);
11439 Handle<Object> new_length_handle(len, isolate); 11434 Handle<Object> new_length_handle(len, isolate);
11440 uint32_t old_length = 0; 11435 uint32_t old_length = 0;
(...skipping 1110 matching lines...) Expand 10 before | Expand all | Expand 10 after
12551 return Handle<Object>(); 12546 return Handle<Object>();
12552 } 12547 }
12553 12548
12554 // Normalize the elements to enable attributes on the property. 12549 // Normalize the elements to enable attributes on the property.
12555 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { 12550 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
12556 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); 12551 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
12557 // Make sure that we never go back to fast case. 12552 // Make sure that we never go back to fast case.
12558 dictionary->set_requires_slow_elements(); 12553 dictionary->set_requires_slow_elements();
12559 } 12554 }
12560 12555
12561 if (!(FLAG_harmony_observation && object->map()->is_observed())) { 12556 if (!object->map()->is_observed()) {
12562 return object->HasIndexedInterceptor() 12557 return object->HasIndexedInterceptor()
12563 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, 12558 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode,
12564 check_prototype, 12559 check_prototype,
12565 set_mode) 12560 set_mode)
12566 : SetElementWithoutInterceptor(object, index, value, attributes, 12561 : SetElementWithoutInterceptor(object, index, value, attributes,
12567 strict_mode, 12562 strict_mode,
12568 check_prototype, 12563 check_prototype,
12569 set_mode); 12564 set_mode);
12570 } 12565 }
12571 12566
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
13137 13132
13138 bool JSObject::ShouldConvertToFastElements() { 13133 bool JSObject::ShouldConvertToFastElements() {
13139 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); 13134 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
13140 // If the elements are sparse, we should not go back to fast case. 13135 // If the elements are sparse, we should not go back to fast case.
13141 if (!HasDenseElements()) return false; 13136 if (!HasDenseElements()) return false;
13142 // An object requiring access checks is never allowed to have fast 13137 // An object requiring access checks is never allowed to have fast
13143 // elements. If it had fast elements we would skip security checks. 13138 // elements. If it had fast elements we would skip security checks.
13144 if (IsAccessCheckNeeded()) return false; 13139 if (IsAccessCheckNeeded()) return false;
13145 // Observed objects may not go to fast mode because they rely on map checks, 13140 // Observed objects may not go to fast mode because they rely on map checks,
13146 // and for fast element accesses we sometimes check element kinds only. 13141 // and for fast element accesses we sometimes check element kinds only.
13147 if (FLAG_harmony_observation && map()->is_observed()) return false; 13142 if (map()->is_observed()) return false;
13148 13143
13149 FixedArray* elements = FixedArray::cast(this->elements()); 13144 FixedArray* elements = FixedArray::cast(this->elements());
13150 SeededNumberDictionary* dictionary = NULL; 13145 SeededNumberDictionary* dictionary = NULL;
13151 if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) { 13146 if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
13152 dictionary = SeededNumberDictionary::cast(elements->get(1)); 13147 dictionary = SeededNumberDictionary::cast(elements->get(1));
13153 } else { 13148 } else {
13154 dictionary = SeededNumberDictionary::cast(elements); 13149 dictionary = SeededNumberDictionary::cast(elements);
13155 } 13150 }
13156 // If an element has been added at a very high index in the elements 13151 // If an element has been added at a very high index in the elements
13157 // dictionary, we cannot go back to fast case. 13152 // dictionary, we cannot go back to fast case.
(...skipping 3333 matching lines...) Expand 10 before | Expand all | Expand 10 after
16491 #define ERROR_MESSAGES_TEXTS(C, T) T, 16486 #define ERROR_MESSAGES_TEXTS(C, T) T,
16492 static const char* error_messages_[] = { 16487 static const char* error_messages_[] = {
16493 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16488 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16494 }; 16489 };
16495 #undef ERROR_MESSAGES_TEXTS 16490 #undef ERROR_MESSAGES_TEXTS
16496 return error_messages_[reason]; 16491 return error_messages_[reason];
16497 } 16492 }
16498 16493
16499 16494
16500 } } // namespace v8::internal 16495 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698