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 2163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2174 } else { | 2174 } else { |
2175 // Normalize the object to prevent very large instance descriptors. | 2175 // Normalize the object to prevent very large instance descriptors. |
2176 // This eliminates unwanted N^2 allocation and lookup behavior. | 2176 // This eliminates unwanted N^2 allocation and lookup behavior. |
2177 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 2177 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
2178 AddSlowProperty(object, name, value, attributes); | 2178 AddSlowProperty(object, name, value, attributes); |
2179 } | 2179 } |
2180 } else { | 2180 } else { |
2181 AddSlowProperty(object, name, value, attributes); | 2181 AddSlowProperty(object, name, value, attributes); |
2182 } | 2182 } |
2183 | 2183 |
2184 if (FLAG_harmony_observation && | 2184 if (object->map()->is_observed() && |
2185 object->map()->is_observed() && | |
2186 *name != isolate->heap()->hidden_string()) { | 2185 *name != isolate->heap()->hidden_string()) { |
2187 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 2186 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
2188 EnqueueChangeRecord(object, "add", name, old_value); | 2187 EnqueueChangeRecord(object, "add", name, old_value); |
2189 } | 2188 } |
2190 | 2189 |
2191 return value; | 2190 return value; |
2192 } | 2191 } |
2193 | 2192 |
2194 | 2193 |
2195 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 2194 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
(...skipping 1877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4073 Handle<Object> error = isolate->factory()->NewTypeError( | 4072 Handle<Object> error = isolate->factory()->NewTypeError( |
4074 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 4073 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
4075 isolate->Throw(*error); | 4074 isolate->Throw(*error); |
4076 return Handle<Object>(); | 4075 return Handle<Object>(); |
4077 } else { | 4076 } else { |
4078 return value; | 4077 return value; |
4079 } | 4078 } |
4080 } | 4079 } |
4081 | 4080 |
4082 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 4081 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
4083 bool is_observed = FLAG_harmony_observation && | 4082 bool is_observed = object->map()->is_observed() && |
4084 object->map()->is_observed() && | |
4085 *name != isolate->heap()->hidden_string(); | 4083 *name != isolate->heap()->hidden_string(); |
4086 if (is_observed && lookup->IsDataProperty()) { | 4084 if (is_observed && lookup->IsDataProperty()) { |
4087 old_value = Object::GetProperty(object, name); | 4085 old_value = Object::GetProperty(object, name); |
4088 } | 4086 } |
4089 | 4087 |
4090 // This is a real property that is not read-only, or it is a | 4088 // This is a real property that is not read-only, or it is a |
4091 // transition or null descriptor and there are no setters in the prototypes. | 4089 // transition or null descriptor and there are no setters in the prototypes. |
4092 Handle<Object> result = value; | 4090 Handle<Object> result = value; |
4093 switch (lookup->type()) { | 4091 switch (lookup->type()) { |
4094 case NORMAL: | 4092 case NORMAL: |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4196 object->map()->LookupTransition(*object, *name, &lookup); | 4194 object->map()->LookupTransition(*object, *name, &lookup); |
4197 TransitionFlag flag = lookup.IsFound() | 4195 TransitionFlag flag = lookup.IsFound() |
4198 ? OMIT_TRANSITION : INSERT_TRANSITION; | 4196 ? OMIT_TRANSITION : INSERT_TRANSITION; |
4199 // Neither properties nor transitions found. | 4197 // Neither properties nor transitions found. |
4200 return AddProperty(object, name, value, attributes, SLOPPY, | 4198 return AddProperty(object, name, value, attributes, SLOPPY, |
4201 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag); | 4199 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag); |
4202 } | 4200 } |
4203 | 4201 |
4204 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 4202 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
4205 PropertyAttributes old_attributes = ABSENT; | 4203 PropertyAttributes old_attributes = ABSENT; |
4206 bool is_observed = FLAG_harmony_observation && | 4204 bool is_observed = object->map()->is_observed() && |
4207 object->map()->is_observed() && | |
4208 *name != isolate->heap()->hidden_string(); | 4205 *name != isolate->heap()->hidden_string(); |
4209 if (is_observed && lookup.IsProperty()) { | 4206 if (is_observed && lookup.IsProperty()) { |
4210 if (lookup.IsDataProperty()) old_value = | 4207 if (lookup.IsDataProperty()) old_value = |
4211 Object::GetProperty(object, name); | 4208 Object::GetProperty(object, name); |
4212 old_attributes = lookup.GetAttributes(); | 4209 old_attributes = lookup.GetAttributes(); |
4213 } | 4210 } |
4214 | 4211 |
4215 // Check of IsReadOnly removed from here in clone. | 4212 // Check of IsReadOnly removed from here in clone. |
4216 switch (lookup.type()) { | 4213 switch (lookup.type()) { |
4217 case NORMAL: | 4214 case NORMAL: |
(...skipping 962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5180 | 5177 |
5181 if (object->IsJSGlobalProxy()) { | 5178 if (object->IsJSGlobalProxy()) { |
5182 Handle<Object> proto(object->GetPrototype(), isolate); | 5179 Handle<Object> proto(object->GetPrototype(), isolate); |
5183 if (proto->IsNull()) return factory->false_value(); | 5180 if (proto->IsNull()) return factory->false_value(); |
5184 ASSERT(proto->IsJSGlobalObject()); | 5181 ASSERT(proto->IsJSGlobalObject()); |
5185 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); | 5182 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); |
5186 } | 5183 } |
5187 | 5184 |
5188 Handle<Object> old_value; | 5185 Handle<Object> old_value; |
5189 bool should_enqueue_change_record = false; | 5186 bool should_enqueue_change_record = false; |
5190 if (FLAG_harmony_observation && object->map()->is_observed()) { | 5187 if (object->map()->is_observed()) { |
5191 should_enqueue_change_record = HasLocalElement(object, index); | 5188 should_enqueue_change_record = HasLocalElement(object, index); |
5192 if (should_enqueue_change_record) { | 5189 if (should_enqueue_change_record) { |
5193 old_value = object->GetLocalElementAccessorPair(index) != NULL | 5190 old_value = object->GetLocalElementAccessorPair(index) != NULL |
5194 ? Handle<Object>::cast(factory->the_hole_value()) | 5191 ? Handle<Object>::cast(factory->the_hole_value()) |
5195 : Object::GetElement(isolate, object, index); | 5192 : Object::GetElement(isolate, object, index); |
5196 } | 5193 } |
5197 } | 5194 } |
5198 | 5195 |
5199 // Skip interceptor if forcing deletion. | 5196 // Skip interceptor if forcing deletion. |
5200 Handle<Object> result; | 5197 Handle<Object> result; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5251 Handle<Object> args[2] = { name, object }; | 5248 Handle<Object> args[2] = { name, object }; |
5252 Handle<Object> error = isolate->factory()->NewTypeError( | 5249 Handle<Object> error = isolate->factory()->NewTypeError( |
5253 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); | 5250 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); |
5254 isolate->Throw(*error); | 5251 isolate->Throw(*error); |
5255 return Handle<Object>(); | 5252 return Handle<Object>(); |
5256 } | 5253 } |
5257 return isolate->factory()->false_value(); | 5254 return isolate->factory()->false_value(); |
5258 } | 5255 } |
5259 | 5256 |
5260 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 5257 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
5261 bool is_observed = FLAG_harmony_observation && | 5258 bool is_observed = object->map()->is_observed() && |
5262 object->map()->is_observed() && | |
5263 *name != isolate->heap()->hidden_string(); | 5259 *name != isolate->heap()->hidden_string(); |
5264 if (is_observed && lookup.IsDataProperty()) { | 5260 if (is_observed && lookup.IsDataProperty()) { |
5265 old_value = Object::GetProperty(object, name); | 5261 old_value = Object::GetProperty(object, name); |
5266 } | 5262 } |
5267 Handle<Object> result; | 5263 Handle<Object> result; |
5268 | 5264 |
5269 // Check for interceptor. | 5265 // Check for interceptor. |
5270 if (lookup.IsInterceptor()) { | 5266 if (lookup.IsInterceptor()) { |
5271 // Skip interceptor if forcing a deletion. | 5267 // Skip interceptor if forcing a deletion. |
5272 if (mode == FORCE_DELETION) { | 5268 if (mode == FORCE_DELETION) { |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5488 | 5484 |
5489 // Do a map transition, other objects with this map may still | 5485 // Do a map transition, other objects with this map may still |
5490 // be extensible. | 5486 // be extensible. |
5491 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5487 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
5492 Handle<Map> new_map = Map::Copy(handle(object->map())); | 5488 Handle<Map> new_map = Map::Copy(handle(object->map())); |
5493 | 5489 |
5494 new_map->set_is_extensible(false); | 5490 new_map->set_is_extensible(false); |
5495 JSObject::MigrateToMap(object, new_map); | 5491 JSObject::MigrateToMap(object, new_map); |
5496 ASSERT(!object->map()->is_extensible()); | 5492 ASSERT(!object->map()->is_extensible()); |
5497 | 5493 |
5498 if (FLAG_harmony_observation && object->map()->is_observed()) { | 5494 if (object->map()->is_observed()) { |
5499 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), | 5495 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), |
5500 isolate->factory()->the_hole_value()); | 5496 isolate->factory()->the_hole_value()); |
5501 } | 5497 } |
5502 return object; | 5498 return object; |
5503 } | 5499 } |
5504 | 5500 |
5505 | 5501 |
5506 template<typename Dictionary> | 5502 template<typename Dictionary> |
5507 static void FreezeDictionary(Dictionary* dictionary) { | 5503 static void FreezeDictionary(Dictionary* dictionary) { |
5508 int capacity = dictionary->Capacity(); | 5504 int capacity = dictionary->Capacity(); |
(...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6346 | 6342 |
6347 // Try to flatten before operating on the string. | 6343 // Try to flatten before operating on the string. |
6348 if (name->IsString()) String::cast(*name)->TryFlatten(); | 6344 if (name->IsString()) String::cast(*name)->TryFlatten(); |
6349 | 6345 |
6350 if (!JSObject::CanSetCallback(object, name)) return; | 6346 if (!JSObject::CanSetCallback(object, name)) return; |
6351 | 6347 |
6352 uint32_t index = 0; | 6348 uint32_t index = 0; |
6353 bool is_element = name->AsArrayIndex(&index); | 6349 bool is_element = name->AsArrayIndex(&index); |
6354 | 6350 |
6355 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6351 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
6356 bool is_observed = FLAG_harmony_observation && | 6352 bool is_observed = object->map()->is_observed() && |
6357 object->map()->is_observed() && | |
6358 *name != isolate->heap()->hidden_string(); | 6353 *name != isolate->heap()->hidden_string(); |
6359 bool preexists = false; | 6354 bool preexists = false; |
6360 if (is_observed) { | 6355 if (is_observed) { |
6361 if (is_element) { | 6356 if (is_element) { |
6362 preexists = HasLocalElement(object, index); | 6357 preexists = HasLocalElement(object, index); |
6363 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { | 6358 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { |
6364 old_value = Object::GetElement(isolate, object, index); | 6359 old_value = Object::GetElement(isolate, object, index); |
6365 } | 6360 } |
6366 } else { | 6361 } else { |
6367 LookupResult lookup(isolate); | 6362 LookupResult lookup(isolate); |
(...skipping 5040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11408 Handle<JSFunction>(isolate->observers_end_perform_splice()), | 11403 Handle<JSFunction>(isolate->observers_end_perform_splice()), |
11409 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args, | 11404 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args, |
11410 &threw); | 11405 &threw); |
11411 ASSERT(!threw); | 11406 ASSERT(!threw); |
11412 } | 11407 } |
11413 | 11408 |
11414 | 11409 |
11415 MaybeObject* JSArray::SetElementsLength(Object* len) { | 11410 MaybeObject* JSArray::SetElementsLength(Object* len) { |
11416 // We should never end in here with a pixel or external array. | 11411 // We should never end in here with a pixel or external array. |
11417 ASSERT(AllowsSetElementsLength()); | 11412 ASSERT(AllowsSetElementsLength()); |
11418 if (!(FLAG_harmony_observation && map()->is_observed())) | 11413 if (!map()->is_observed()) |
11419 return GetElementsAccessor()->SetLength(this, len); | 11414 return GetElementsAccessor()->SetLength(this, len); |
11420 | 11415 |
11421 Isolate* isolate = GetIsolate(); | 11416 Isolate* isolate = GetIsolate(); |
11422 HandleScope scope(isolate); | 11417 HandleScope scope(isolate); |
11423 Handle<JSArray> self(this); | 11418 Handle<JSArray> self(this); |
11424 List<uint32_t> indices; | 11419 List<uint32_t> indices; |
11425 List<Handle<Object> > old_values; | 11420 List<Handle<Object> > old_values; |
11426 Handle<Object> old_length_handle(self->length(), isolate); | 11421 Handle<Object> old_length_handle(self->length(), isolate); |
11427 Handle<Object> new_length_handle(len, isolate); | 11422 Handle<Object> new_length_handle(len, isolate); |
11428 uint32_t old_length = 0; | 11423 uint32_t old_length = 0; |
(...skipping 1108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12537 return Handle<Object>(); | 12532 return Handle<Object>(); |
12538 } | 12533 } |
12539 | 12534 |
12540 // Normalize the elements to enable attributes on the property. | 12535 // Normalize the elements to enable attributes on the property. |
12541 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { | 12536 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { |
12542 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 12537 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
12543 // Make sure that we never go back to fast case. | 12538 // Make sure that we never go back to fast case. |
12544 dictionary->set_requires_slow_elements(); | 12539 dictionary->set_requires_slow_elements(); |
12545 } | 12540 } |
12546 | 12541 |
12547 if (!(FLAG_harmony_observation && object->map()->is_observed())) { | 12542 if (!object->map()->is_observed()) { |
12548 return object->HasIndexedInterceptor() | 12543 return object->HasIndexedInterceptor() |
12549 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, | 12544 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, |
12550 check_prototype, | 12545 check_prototype, |
12551 set_mode) | 12546 set_mode) |
12552 : SetElementWithoutInterceptor(object, index, value, attributes, | 12547 : SetElementWithoutInterceptor(object, index, value, attributes, |
12553 strict_mode, | 12548 strict_mode, |
12554 check_prototype, | 12549 check_prototype, |
12555 set_mode); | 12550 set_mode); |
12556 } | 12551 } |
12557 | 12552 |
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13139 | 13134 |
13140 bool JSObject::ShouldConvertToFastElements() { | 13135 bool JSObject::ShouldConvertToFastElements() { |
13141 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 13136 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
13142 // If the elements are sparse, we should not go back to fast case. | 13137 // If the elements are sparse, we should not go back to fast case. |
13143 if (!HasDenseElements()) return false; | 13138 if (!HasDenseElements()) return false; |
13144 // An object requiring access checks is never allowed to have fast | 13139 // An object requiring access checks is never allowed to have fast |
13145 // elements. If it had fast elements we would skip security checks. | 13140 // elements. If it had fast elements we would skip security checks. |
13146 if (IsAccessCheckNeeded()) return false; | 13141 if (IsAccessCheckNeeded()) return false; |
13147 // Observed objects may not go to fast mode because they rely on map checks, | 13142 // Observed objects may not go to fast mode because they rely on map checks, |
13148 // and for fast element accesses we sometimes check element kinds only. | 13143 // and for fast element accesses we sometimes check element kinds only. |
13149 if (FLAG_harmony_observation && map()->is_observed()) return false; | 13144 if (map()->is_observed()) return false; |
13150 | 13145 |
13151 FixedArray* elements = FixedArray::cast(this->elements()); | 13146 FixedArray* elements = FixedArray::cast(this->elements()); |
13152 SeededNumberDictionary* dictionary = NULL; | 13147 SeededNumberDictionary* dictionary = NULL; |
13153 if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) { | 13148 if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) { |
13154 dictionary = SeededNumberDictionary::cast(elements->get(1)); | 13149 dictionary = SeededNumberDictionary::cast(elements->get(1)); |
13155 } else { | 13150 } else { |
13156 dictionary = SeededNumberDictionary::cast(elements); | 13151 dictionary = SeededNumberDictionary::cast(elements); |
13157 } | 13152 } |
13158 // If an element has been added at a very high index in the elements | 13153 // If an element has been added at a very high index in the elements |
13159 // dictionary, we cannot go back to fast case. | 13154 // dictionary, we cannot go back to fast case. |
(...skipping 3320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16480 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16475 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16481 static const char* error_messages_[] = { | 16476 static const char* error_messages_[] = { |
16482 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16477 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16483 }; | 16478 }; |
16484 #undef ERROR_MESSAGES_TEXTS | 16479 #undef ERROR_MESSAGES_TEXTS |
16485 return error_messages_[reason]; | 16480 return error_messages_[reason]; |
16486 } | 16481 } |
16487 | 16482 |
16488 | 16483 |
16489 } } // namespace v8::internal | 16484 } } // namespace v8::internal |
OLD | NEW |