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 2181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |