OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <iomanip> | 5 #include <iomanip> |
6 #include <sstream> | 6 #include <sstream> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 6220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6231 } | 6231 } |
6232 | 6232 |
6233 // If we only want own properties we bail out after the first | 6233 // If we only want own properties we bail out after the first |
6234 // iteration. | 6234 // iteration. |
6235 if (type == OWN_ONLY) break; | 6235 if (type == OWN_ONLY) break; |
6236 } | 6236 } |
6237 return content; | 6237 return content; |
6238 } | 6238 } |
6239 | 6239 |
6240 | 6240 |
6241 // Try to update an accessor in an elements dictionary. Return true if the | |
6242 // update succeeded, and false otherwise. | |
6243 static bool UpdateGetterSetterInDictionary( | |
6244 SeededNumberDictionary* dictionary, | |
6245 uint32_t index, | |
6246 Object* getter, | |
6247 Object* setter, | |
6248 PropertyAttributes attributes) { | |
6249 int entry = dictionary->FindEntry(index); | |
6250 if (entry != SeededNumberDictionary::kNotFound) { | |
6251 Object* result = dictionary->ValueAt(entry); | |
6252 PropertyDetails details = dictionary->DetailsAt(entry); | |
6253 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { | |
6254 DCHECK(details.IsConfigurable()); | |
6255 if (details.attributes() != attributes) { | |
6256 dictionary->DetailsAtPut( | |
6257 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index, | |
6258 PropertyCellType::kNoCell)); | |
6259 } | |
6260 AccessorPair::cast(result)->SetComponents(getter, setter); | |
6261 return true; | |
6262 } | |
6263 } | |
6264 return false; | |
6265 } | |
6266 | |
6267 | |
6268 void JSObject::DefineElementAccessor(Handle<JSObject> object, | |
6269 uint32_t index, | |
6270 Handle<Object> getter, | |
6271 Handle<Object> setter, | |
6272 PropertyAttributes attributes) { | |
6273 switch (object->GetElementsKind()) { | |
6274 case FAST_SMI_ELEMENTS: | |
6275 case FAST_ELEMENTS: | |
6276 case FAST_DOUBLE_ELEMENTS: | |
6277 case FAST_HOLEY_SMI_ELEMENTS: | |
6278 case FAST_HOLEY_ELEMENTS: | |
6279 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
6280 break; | |
6281 | |
6282 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | |
6283 case EXTERNAL_##TYPE##_ELEMENTS: \ | |
6284 case TYPE##_ELEMENTS: \ | |
6285 | |
6286 TYPED_ARRAYS(TYPED_ARRAY_CASE) | |
6287 #undef TYPED_ARRAY_CASE | |
6288 // Ignore getters and setters on pixel and external array elements. | |
6289 return; | |
6290 | |
6291 case DICTIONARY_ELEMENTS: | |
6292 if (UpdateGetterSetterInDictionary(object->element_dictionary(), | |
6293 index, | |
6294 *getter, | |
6295 *setter, | |
6296 attributes)) { | |
6297 return; | |
6298 } | |
6299 break; | |
6300 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: | |
6301 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { | |
6302 // Ascertain whether we have read-only properties or an existing | |
6303 // getter/setter pair in an arguments elements dictionary backing | |
6304 // store. | |
6305 FixedArray* parameter_map = FixedArray::cast(object->elements()); | |
6306 uint32_t length = parameter_map->length(); | |
6307 Object* probe = | |
6308 index < (length - 2) ? parameter_map->get(index + 2) : NULL; | |
6309 if (probe == NULL || probe->IsTheHole()) { | |
6310 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | |
6311 if (arguments->IsDictionary()) { | |
6312 SeededNumberDictionary* dictionary = | |
6313 SeededNumberDictionary::cast(arguments); | |
6314 if (UpdateGetterSetterInDictionary(dictionary, | |
6315 index, | |
6316 *getter, | |
6317 *setter, | |
6318 attributes)) { | |
6319 return; | |
6320 } | |
6321 } | |
6322 } | |
6323 break; | |
6324 } | |
6325 } | |
6326 | |
6327 Isolate* isolate = object->GetIsolate(); | |
6328 Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair(); | |
6329 accessors->SetComponents(*getter, *setter); | |
6330 | |
6331 SetElementCallback(object, index, accessors, attributes); | |
6332 } | |
6333 | |
6334 | |
6335 bool Map::DictionaryElementsInPrototypeChainOnly() { | 6241 bool Map::DictionaryElementsInPrototypeChainOnly() { |
6336 if (IsDictionaryElementsKind(elements_kind())) { | 6242 if (IsDictionaryElementsKind(elements_kind())) { |
6337 return false; | 6243 return false; |
6338 } | 6244 } |
6339 | 6245 |
6340 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { | 6246 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { |
6341 // Be conservative, don't walk into proxies. | 6247 // Be conservative, don't walk into proxies. |
6342 if (iter.GetCurrent()->IsJSProxy()) return true; | 6248 if (iter.GetCurrent()->IsJSProxy()) return true; |
6343 // String wrappers have non-configurable, non-writable elements. | 6249 // String wrappers have non-configurable, non-writable elements. |
6344 if (iter.GetCurrent()->IsStringWrapper()) return true; | 6250 if (iter.GetCurrent()->IsStringWrapper()) return true; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6432 | 6338 |
6433 if (it.state() == LookupIterator::ACCESS_CHECK) { | 6339 if (it.state() == LookupIterator::ACCESS_CHECK) { |
6434 if (!it.HasAccess()) { | 6340 if (!it.HasAccess()) { |
6435 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()); | 6341 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()); |
6436 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 6342 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
6437 return isolate->factory()->undefined_value(); | 6343 return isolate->factory()->undefined_value(); |
6438 } | 6344 } |
6439 it.Next(); | 6345 it.Next(); |
6440 } | 6346 } |
6441 | 6347 |
| 6348 // Ignore accessors on typed arrays. |
| 6349 if (it.IsElement() && (object->HasFixedTypedArrayElements() || |
| 6350 object->HasExternalArrayElements())) { |
| 6351 return it.factory()->undefined_value(); |
| 6352 } |
| 6353 |
6442 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6354 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
6443 bool is_observed = object->map()->is_observed() && | 6355 bool is_observed = object->map()->is_observed() && |
6444 !isolate->IsInternallyUsedPropertyName(name); | 6356 !isolate->IsInternallyUsedPropertyName(name); |
6445 bool preexists = false; | 6357 bool preexists = false; |
6446 if (is_observed) { | 6358 if (is_observed) { |
6447 CHECK(GetPropertyAttributes(&it).IsJust()); | 6359 CHECK(GetPropertyAttributes(&it).IsJust()); |
6448 preexists = it.IsFound(); | 6360 preexists = it.IsFound(); |
6449 if (preexists && (it.state() == LookupIterator::DATA || | 6361 if (preexists && (it.state() == LookupIterator::DATA || |
6450 it.GetAccessors()->IsAccessorInfo())) { | 6362 it.GetAccessors()->IsAccessorInfo())) { |
6451 old_value = GetProperty(&it).ToHandleChecked(); | 6363 old_value = GetProperty(&it).ToHandleChecked(); |
6452 } | 6364 } |
6453 } | 6365 } |
6454 | 6366 |
6455 if (it.IsElement()) { | 6367 DCHECK(getter->IsSpecFunction() || getter->IsUndefined() || getter->IsNull()); |
6456 DefineElementAccessor(it.GetStoreTarget(), it.index(), getter, setter, | 6368 DCHECK(setter->IsSpecFunction() || setter->IsUndefined() || setter->IsNull()); |
6457 attributes); | 6369 // At least one of the accessors needs to be a new value. |
6458 } else { | 6370 DCHECK(!getter->IsNull() || !setter->IsNull()); |
6459 DCHECK(getter->IsSpecFunction() || getter->IsUndefined() || | 6371 if (!getter->IsNull()) { |
6460 getter->IsNull()); | 6372 it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes); |
6461 DCHECK(setter->IsSpecFunction() || setter->IsUndefined() || | 6373 } |
6462 setter->IsNull()); | 6374 if (!setter->IsNull()) { |
6463 // At least one of the accessors needs to be a new value. | 6375 it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes); |
6464 DCHECK(!getter->IsNull() || !setter->IsNull()); | |
6465 if (!getter->IsNull()) { | |
6466 it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes); | |
6467 } | |
6468 if (!setter->IsNull()) { | |
6469 it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes); | |
6470 } | |
6471 } | 6376 } |
6472 | 6377 |
6473 if (is_observed) { | 6378 if (is_observed) { |
6474 const char* type = preexists ? "reconfigure" : "add"; | 6379 const char* type = preexists ? "reconfigure" : "add"; |
6475 RETURN_ON_EXCEPTION( | 6380 RETURN_ON_EXCEPTION( |
6476 isolate, EnqueueChangeRecord(object, type, name, old_value), Object); | 6381 isolate, EnqueueChangeRecord(object, type, name, old_value), Object); |
6477 } | 6382 } |
6478 | 6383 |
6479 return isolate->factory()->undefined_value(); | 6384 return isolate->factory()->undefined_value(); |
6480 } | 6385 } |
(...skipping 9634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16115 Handle<Object> new_value) { | 16020 Handle<Object> new_value) { |
16116 if (cell->value() != *new_value) { | 16021 if (cell->value() != *new_value) { |
16117 cell->set_value(*new_value); | 16022 cell->set_value(*new_value); |
16118 Isolate* isolate = cell->GetIsolate(); | 16023 Isolate* isolate = cell->GetIsolate(); |
16119 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16024 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
16120 isolate, DependentCode::kPropertyCellChangedGroup); | 16025 isolate, DependentCode::kPropertyCellChangedGroup); |
16121 } | 16026 } |
16122 } | 16027 } |
16123 } // namespace internal | 16028 } // namespace internal |
16124 } // namespace v8 | 16029 } // namespace v8 |
OLD | NEW |