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

Side by Side Diff: src/objects.cc

Issue 1172683003: Use the LookupIterator for SetElement and friends (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 5 years, 6 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
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 return CallTrap( 300 return CallTrap(
301 proxy, "get", isolate->derived_get_trap(), arraysize(args), args); 301 proxy, "get", isolate->derived_get_trap(), arraysize(args), args);
302 } 302 }
303 303
304 304
305 MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) { 305 MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
306 Isolate* isolate = it->isolate(); 306 Isolate* isolate = it->isolate();
307 Handle<Object> structure = it->GetAccessors(); 307 Handle<Object> structure = it->GetAccessors();
308 Handle<Object> receiver = it->GetReceiver(); 308 Handle<Object> receiver = it->GetReceiver();
309 309
310 // We should never get here to initialize a const with the hole value since a
311 // const declaration would conflict with the getter.
310 DCHECK(!structure->IsForeign()); 312 DCHECK(!structure->IsForeign());
311 // api style callbacks. 313
314 // API style callbacks.
312 if (structure->IsAccessorInfo()) { 315 if (structure->IsAccessorInfo()) {
313 Handle<JSObject> holder = it->GetHolder<JSObject>(); 316 Handle<JSObject> holder = it->GetHolder<JSObject>();
314 Handle<Name> name = it->GetName(); 317 Handle<Name> name = it->GetName();
315 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure); 318 Handle<ExecutableAccessorInfo> info =
319 Handle<ExecutableAccessorInfo>::cast(structure);
316 if (!info->IsCompatibleReceiver(*receiver)) { 320 if (!info->IsCompatibleReceiver(*receiver)) {
317 THROW_NEW_ERROR(isolate, 321 THROW_NEW_ERROR(isolate,
318 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, 322 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
319 name, receiver), 323 name, receiver),
320 Object); 324 Object);
321 } 325 }
322 326
323 Handle<ExecutableAccessorInfo> data =
324 Handle<ExecutableAccessorInfo>::cast(structure);
325 v8::AccessorNameGetterCallback call_fun = 327 v8::AccessorNameGetterCallback call_fun =
326 v8::ToCData<v8::AccessorNameGetterCallback>(data->getter()); 328 v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
327 if (call_fun == NULL) return isolate->factory()->undefined_value(); 329 if (call_fun == nullptr) return isolate->factory()->undefined_value();
328 330
329 LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name)); 331 LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
330 PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder); 332 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
331 v8::Handle<v8::Value> result = 333 v8::Handle<v8::Value> result =
332 args.Call(call_fun, v8::Utils::ToLocal(name)); 334 args.Call(call_fun, v8::Utils::ToLocal(name));
333 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 335 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
334 if (result.IsEmpty()) { 336 if (result.IsEmpty()) {
335 return isolate->factory()->undefined_value(); 337 return isolate->factory()->undefined_value();
336 } 338 }
337 Handle<Object> return_value = v8::Utils::OpenHandle(*result); 339 Handle<Object> return_value = v8::Utils::OpenHandle(*result);
338 return_value->VerifyApiCallResultType(); 340 return_value->VerifyApiCallResultType();
339 // Rebox handle before return. 341 // Rebox handle before return.
340 return handle(*return_value, isolate); 342 return handle(*return_value, isolate);
341 } 343 }
342 344
343 // __defineGetter__ callback 345 // Regular accessor.
344 Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(), 346 Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
345 isolate);
346 if (getter->IsSpecFunction()) { 347 if (getter->IsSpecFunction()) {
347 // TODO(rossberg): nicer would be to cast to some JSCallable here... 348 // TODO(rossberg): nicer would be to cast to some JSCallable here...
348 return Object::GetPropertyWithDefinedGetter( 349 return Object::GetPropertyWithDefinedGetter(
349 receiver, Handle<JSReceiver>::cast(getter)); 350 receiver, Handle<JSReceiver>::cast(getter));
350 } 351 }
351 // Getter is not a function. 352 // Getter is not a function.
352 return isolate->factory()->undefined_value(); 353 return isolate->factory()->undefined_value();
353 } 354 }
354 355
355 356
356 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate, 357 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
357 Handle<AccessorInfo> info, 358 Handle<AccessorInfo> info,
358 Handle<Map> map) { 359 Handle<Map> map) {
359 if (!info->HasExpectedReceiverType()) return true; 360 if (!info->HasExpectedReceiverType()) return true;
360 if (!map->IsJSObjectMap()) return false; 361 if (!map->IsJSObjectMap()) return false;
361 return FunctionTemplateInfo::cast(info->expected_receiver_type()) 362 return FunctionTemplateInfo::cast(info->expected_receiver_type())
362 ->IsTemplateFor(*map); 363 ->IsTemplateFor(*map);
363 } 364 }
364 365
365 366
366 MaybeHandle<Object> Object::SetPropertyWithAccessor( 367 MaybeHandle<Object> Object::SetPropertyWithAccessor(
367 Handle<Object> receiver, Handle<Name> name, Handle<Object> value, 368 LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
368 Handle<JSObject> holder, Handle<Object> structure, 369 Isolate* isolate = it->isolate();
369 LanguageMode language_mode) { 370 Handle<Object> structure = it->GetAccessors();
370 Isolate* isolate = name->GetIsolate(); 371 Handle<Object> receiver = it->GetReceiver();
371 372
372 // We should never get here to initialize a const with the hole 373 // We should never get here to initialize a const with the hole value since a
373 // value since a const declaration would conflict with the setter. 374 // const declaration would conflict with the setter.
374 DCHECK(!structure->IsForeign()); 375 DCHECK(!structure->IsForeign());
376
377 // API style callbacks.
375 if (structure->IsExecutableAccessorInfo()) { 378 if (structure->IsExecutableAccessorInfo()) {
376 // Don't call executable accessor setters with non-JSObject receivers. 379 Handle<JSObject> holder = it->GetHolder<JSObject>();
377 if (!receiver->IsJSObject()) return value; 380 Handle<Name> name = it->GetName();
378 // api style callbacks 381 Handle<ExecutableAccessorInfo> info =
379 ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure); 382 Handle<ExecutableAccessorInfo>::cast(structure);
380 if (!info->IsCompatibleReceiver(*receiver)) { 383 if (!info->IsCompatibleReceiver(*receiver)) {
381 THROW_NEW_ERROR(isolate, 384 THROW_NEW_ERROR(isolate,
382 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, 385 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
383 name, receiver), 386 name, receiver),
384 Object); 387 Object);
385 } 388 }
386 Object* call_obj = info->setter(); 389
387 v8::AccessorNameSetterCallback call_fun = 390 v8::AccessorNameSetterCallback call_fun =
388 v8::ToCData<v8::AccessorNameSetterCallback>(call_obj); 391 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter());
389 if (call_fun == NULL) return value; 392 if (call_fun == nullptr) return value;
393
390 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); 394 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
391 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder); 395 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
392 args.Call(call_fun, 396 args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
393 v8::Utils::ToLocal(name),
394 v8::Utils::ToLocal(value));
395 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 397 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
396 return value; 398 return value;
397 } 399 }
398 400
399 if (structure->IsAccessorPair()) { 401 // Regular accessor.
400 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); 402 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
401 if (setter->IsSpecFunction()) { 403 if (setter->IsSpecFunction()) {
402 // TODO(rossberg): nicer would be to cast to some JSCallable here... 404 // TODO(rossberg): nicer would be to cast to some JSCallable here...
403 return SetPropertyWithDefinedSetter( 405 return SetPropertyWithDefinedSetter(
404 receiver, Handle<JSReceiver>::cast(setter), value); 406 receiver, Handle<JSReceiver>::cast(setter), value);
405 } else {
406 if (is_sloppy(language_mode)) return value;
407 THROW_NEW_ERROR(
408 isolate,
409 NewTypeError(MessageTemplate::kNoSetterInCallback, name, holder),
410 Object);
411 }
412 } 407 }
413 408
414 UNREACHABLE(); 409 if (is_sloppy(language_mode)) return value;
415 return MaybeHandle<Object>(); 410
411 THROW_NEW_ERROR(isolate,
412 NewTypeError(MessageTemplate::kNoSetterInCallback,
413 it->GetName(), it->GetHolder<JSObject>()),
414 Object);
416 } 415 }
417 416
418 417
419 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter( 418 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
420 Handle<Object> receiver, 419 Handle<Object> receiver,
421 Handle<JSReceiver> getter) { 420 Handle<JSReceiver> getter) {
422 Isolate* isolate = getter->GetIsolate(); 421 Isolate* isolate = getter->GetIsolate();
423 422
424 // Platforms with simulators like arm/arm64 expose a funny issue. If the 423 // Platforms with simulators like arm/arm64 expose a funny issue. If the
425 // simulator has a separate JS stack pointer from the C++ stack pointer, it 424 // simulator has a separate JS stack pointer from the C++ stack pointer, it
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 } 532 }
534 } 533 }
535 return false; 534 return false;
536 } 535 }
537 536
538 537
539 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( 538 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
540 LookupIterator* it, Handle<Object> value, LanguageMode language_mode) { 539 LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
541 Handle<JSObject> checked = it->GetHolder<JSObject>(); 540 Handle<JSObject> checked = it->GetHolder<JSObject>();
542 if (FindAllCanWriteHolder(it)) { 541 if (FindAllCanWriteHolder(it)) {
543 return SetPropertyWithAccessor(it->GetReceiver(), it->GetName(), value, 542 return SetPropertyWithAccessor(it, value, language_mode);
544 it->GetHolder<JSObject>(),
545 it->GetAccessors(), language_mode);
546 } 543 }
547 544
548 it->isolate()->ReportFailedAccessCheck(checked); 545 it->isolate()->ReportFailedAccessCheck(checked);
549 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); 546 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
550 return value; 547 return value;
551 } 548 }
552 549
553 550
554 void JSObject::SetNormalizedProperty(Handle<JSObject> object, 551 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
555 Handle<Name> name, 552 Handle<Name> name,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 PropertyDetails original_details = property_dictionary->DetailsAt(entry); 587 PropertyDetails original_details = property_dictionary->DetailsAt(entry);
591 int enumeration_index = original_details.dictionary_index(); 588 int enumeration_index = original_details.dictionary_index();
592 DCHECK(enumeration_index > 0); 589 DCHECK(enumeration_index > 0);
593 details = details.set_index(enumeration_index); 590 details = details.set_index(enumeration_index);
594 property_dictionary->SetEntry(entry, name, value, details); 591 property_dictionary->SetEntry(entry, name, value, details);
595 } 592 }
596 } 593 }
597 } 594 }
598 595
599 596
600 MaybeHandle<Object> Object::SetElementWithReceiver(
601 Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
602 uint32_t index, Handle<Object> value, LanguageMode language_mode) {
603 // Iterate up the prototype chain until an element is found or the null
604 // prototype is encountered.
605 bool done = false;
606 for (PrototypeIterator iter(isolate, object,
607 object->IsJSProxy() || object->IsJSObject()
608 ? PrototypeIterator::START_AT_RECEIVER
609 : PrototypeIterator::START_AT_PROTOTYPE);
610 !iter.IsAtEnd() && !done; iter.Advance()) {
611 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
612 // TODO(dslomov): implement.
613 isolate->ThrowIllegalOperation();
614 return MaybeHandle<Object>();
615 }
616
617 Handle<JSObject> js_object =
618 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
619
620 // Check access rights if needed.
621 if (js_object->IsAccessCheckNeeded()) {
622 if (!isolate->MayAccess(js_object)) {
623 isolate->ReportFailedAccessCheck(js_object);
624 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
625 return isolate->factory()->undefined_value();
626 }
627 }
628
629 if (js_object->HasIndexedInterceptor()) {
630 LookupIterator it(isolate, receiver, index, js_object,
631 LookupIterator::OWN);
632 Maybe<PropertyAttributes> from_interceptor =
633 JSObject::GetPropertyAttributes(&it);
634 if (!from_interceptor.IsJust()) return MaybeHandle<Object>();
635 if ((from_interceptor.FromJust() & READ_ONLY) != 0) {
636 return WriteToReadOnlyElement(isolate, receiver, index, value,
637 language_mode);
638 }
639 done = from_interceptor.FromJust() != ABSENT;
640 }
641
642 if (!done &&
643 js_object->elements() != isolate->heap()->empty_fixed_array()) {
644 ElementsAccessor* accessor = js_object->GetElementsAccessor();
645 PropertyAttributes attrs = accessor->GetAttributes(js_object, index);
646 if ((attrs & READ_ONLY) != 0) {
647 return WriteToReadOnlyElement(isolate, receiver, index, value,
648 language_mode);
649 }
650 Handle<AccessorPair> pair;
651 if (accessor->GetAccessorPair(js_object, index).ToHandle(&pair)) {
652 return JSObject::SetElementWithCallback(receiver, pair, index, value,
653 js_object, language_mode);
654 } else {
655 done = attrs != ABSENT;
656 }
657 }
658 }
659
660 if (!receiver->IsJSObject()) {
661 return WriteToReadOnlyElement(isolate, receiver, index, value,
662 language_mode);
663 }
664 Handle<JSObject> target = Handle<JSObject>::cast(receiver);
665 ElementsAccessor* accessor = target->GetElementsAccessor();
666 PropertyAttributes attrs = accessor->GetAttributes(target, index);
667 if (attrs == ABSENT) {
668 return JSObject::SetElement(target, index, value, NONE, language_mode,
669 false);
670 }
671 return JSObject::SetElement(target, index, value, attrs, language_mode, false,
672 DEFINE_PROPERTY);
673 }
674
675
676 Map* Object::GetRootMap(Isolate* isolate) { 597 Map* Object::GetRootMap(Isolate* isolate) {
677 DisallowHeapAllocation no_alloc; 598 DisallowHeapAllocation no_alloc;
678 if (IsSmi()) { 599 if (IsSmi()) {
679 Context* context = isolate->context()->native_context(); 600 Context* context = isolate->context()->native_context();
680 return context->number_function()->initial_map(); 601 return context->number_function()->initial_map();
681 } 602 }
682 603
683 HeapObject* heap_object = HeapObject::cast(this); 604 HeapObject* heap_object = HeapObject::cast(this);
684 605
685 // The object is either a number, a string, a boolean, 606 // The object is either a number, a string, a boolean,
(...skipping 2344 matching lines...) Expand 10 before | Expand all | Expand 10 after
3030 Handle<Map> Map::Update(Handle<Map> map) { 2951 Handle<Map> Map::Update(Handle<Map> map) {
3031 if (!map->is_deprecated()) return map; 2952 if (!map->is_deprecated()) return map;
3032 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), 2953 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
3033 HeapType::None(map->GetIsolate()), 2954 HeapType::None(map->GetIsolate()),
3034 ALLOW_IN_DESCRIPTOR); 2955 ALLOW_IN_DESCRIPTOR);
3035 } 2956 }
3036 2957
3037 2958
3038 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it, 2959 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
3039 Handle<Object> value) { 2960 Handle<Object> value) {
3040 Handle<Name> name = it->name(); 2961 Isolate* isolate = it->isolate();
2962 // Make sure that the top context does not change when doing callbacks or
2963 // interceptor calls.
2964 AssertNoContextChange ncc(isolate);
2965
2966 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
2967 Handle<InterceptorInfo> interceptor(it->GetInterceptor());
2968 if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>();
2969
3041 Handle<JSObject> holder = it->GetHolder<JSObject>(); 2970 Handle<JSObject> holder = it->GetHolder<JSObject>();
3042 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); 2971 v8::Handle<v8::Value> result;
3043 if (interceptor->setter()->IsUndefined() || 2972 PropertyCallbackArguments args(isolate, interceptor->data(),
3044 (name->IsSymbol() && !interceptor->can_intercept_symbols())) { 2973 *it->GetReceiver(), *holder);
3045 return MaybeHandle<Object>(); 2974
2975 if (it->IsElement()) {
2976 uint32_t index = it->index();
2977 v8::IndexedPropertySetterCallback setter =
2978 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
2979 LOG(isolate,
2980 ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index));
2981 result = args.Call(setter, index, v8::Utils::ToLocal(value));
2982 } else {
2983 Handle<Name> name = it->name();
2984
2985 if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
2986 return MaybeHandle<Object>();
2987 }
2988
2989 v8::GenericNamedPropertySetterCallback setter =
2990 v8::ToCData<v8::GenericNamedPropertySetterCallback>(
2991 interceptor->setter());
2992 LOG(it->isolate(),
2993 ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
2994 result =
2995 args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
3046 } 2996 }
3047 2997
3048 LOG(it->isolate(),
3049 ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
3050 PropertyCallbackArguments args(it->isolate(), interceptor->data(), *holder,
3051 *holder);
3052 v8::GenericNamedPropertySetterCallback setter =
3053 v8::ToCData<v8::GenericNamedPropertySetterCallback>(
3054 interceptor->setter());
3055 v8::Handle<v8::Value> result =
3056 args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
3057 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); 2998 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
3058 if (!result.IsEmpty()) return value; 2999 if (result.IsEmpty()) return MaybeHandle<Object>();
3059 3000 #ifdef DEBUG
3060 return MaybeHandle<Object>(); 3001 Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
3002 result_internal->VerifyApiCallResultType();
3003 #endif
3004 return value;
3061 } 3005 }
3062 3006
3063 3007
3064 MaybeHandle<Object> Object::SetProperty(Handle<Object> object, 3008 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
3065 Handle<Name> name, Handle<Object> value, 3009 Handle<Name> name, Handle<Object> value,
3066 LanguageMode language_mode, 3010 LanguageMode language_mode,
3067 StoreFromKeyed store_mode) { 3011 StoreFromKeyed store_mode) {
3068 LookupIterator it(object, name); 3012 LookupIterator it(object, name);
3069 return SetProperty(&it, value, language_mode, store_mode); 3013 return SetProperty(&it, value, language_mode, store_mode);
3070 } 3014 }
(...skipping 10 matching lines...) Expand all
3081 3025
3082 *found = true; 3026 *found = true;
3083 3027
3084 bool done = false; 3028 bool done = false;
3085 for (; it->IsFound(); it->Next()) { 3029 for (; it->IsFound(); it->Next()) {
3086 switch (it->state()) { 3030 switch (it->state()) {
3087 case LookupIterator::NOT_FOUND: 3031 case LookupIterator::NOT_FOUND:
3088 UNREACHABLE(); 3032 UNREACHABLE();
3089 3033
3090 case LookupIterator::ACCESS_CHECK: 3034 case LookupIterator::ACCESS_CHECK:
3091 // TODO(verwaest): Remove the distinction. This is mostly bogus since we
3092 // don't know whether we'll want to fetch attributes or call a setter
3093 // until we find the property.
3094 if (it->HasAccess()) break; 3035 if (it->HasAccess()) break;
3036 // Check whether it makes sense to reuse the lookup iterator. Here it
3037 // might still call into setters up the prototype chain.
3095 return JSObject::SetPropertyWithFailedAccessCheck(it, value, 3038 return JSObject::SetPropertyWithFailedAccessCheck(it, value,
3096 language_mode); 3039 language_mode);
3097 3040
3098 case LookupIterator::JSPROXY: 3041 case LookupIterator::JSPROXY:
3099 if (it->HolderIsReceiverOrHiddenPrototype()) { 3042 if (it->HolderIsReceiverOrHiddenPrototype()) {
3100 return JSProxy::SetPropertyWithHandler( 3043 return JSProxy::SetPropertyWithHandler(
3101 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value, 3044 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value,
3102 language_mode); 3045 language_mode);
3103 } else { 3046 } else {
3104 // TODO(verwaest): Use the MaybeHandle to indicate result. 3047 // TODO(verwaest): Use the MaybeHandle to indicate result.
(...skipping 18 matching lines...) Expand all
3123 JSObject::GetPropertyAttributesWithInterceptor(it); 3066 JSObject::GetPropertyAttributesWithInterceptor(it);
3124 if (!maybe_attributes.IsJust()) return MaybeHandle<Object>(); 3067 if (!maybe_attributes.IsJust()) return MaybeHandle<Object>();
3125 done = maybe_attributes.FromJust() != ABSENT; 3068 done = maybe_attributes.FromJust() != ABSENT;
3126 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) { 3069 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) {
3127 return WriteToReadOnlyProperty(it, value, language_mode); 3070 return WriteToReadOnlyProperty(it, value, language_mode);
3128 } 3071 }
3129 } 3072 }
3130 break; 3073 break;
3131 3074
3132 case LookupIterator::ACCESSOR: { 3075 case LookupIterator::ACCESSOR: {
3133 if (it->property_details().IsReadOnly()) { 3076 if (it->IsReadOnly()) {
3134 return WriteToReadOnlyProperty(it, value, language_mode); 3077 return WriteToReadOnlyProperty(it, value, language_mode);
3135 } 3078 }
3136 Handle<Object> accessors = it->GetAccessors(); 3079 Handle<Object> accessors = it->GetAccessors();
3137 if (accessors->IsAccessorInfo() && 3080 if (accessors->IsAccessorInfo() &&
3138 !it->HolderIsReceiverOrHiddenPrototype() && 3081 !it->HolderIsReceiverOrHiddenPrototype() &&
3139 AccessorInfo::cast(*accessors)->is_special_data_property()) { 3082 AccessorInfo::cast(*accessors)->is_special_data_property()) {
3140 done = true; 3083 done = true;
3141 break; 3084 break;
3142 } 3085 }
3143 return SetPropertyWithAccessor(it->GetReceiver(), it->GetName(), value, 3086 return SetPropertyWithAccessor(it, value, language_mode);
3144 it->GetHolder<JSObject>(), accessors,
3145 language_mode);
3146 } 3087 }
3147 case LookupIterator::INTEGER_INDEXED_EXOTIC: 3088 case LookupIterator::INTEGER_INDEXED_EXOTIC:
3148 done = true; 3089 done = true;
3149 break; 3090 break;
3150 3091
3151 case LookupIterator::DATA: 3092 case LookupIterator::DATA:
3152 if (it->property_details().IsReadOnly()) { 3093 if (it->IsReadOnly()) {
3153 return WriteToReadOnlyProperty(it, value, language_mode); 3094 return WriteToReadOnlyProperty(it, value, language_mode);
3154 } 3095 }
3155 if (it->HolderIsReceiverOrHiddenPrototype()) { 3096 if (it->HolderIsReceiverOrHiddenPrototype()) {
3156 return SetDataProperty(it, value); 3097 return SetDataProperty(it, value);
3157 } 3098 }
3158 done = true; 3099 done = true;
3159 break; 3100 break;
3160 3101
3161 case LookupIterator::TRANSITION: 3102 case LookupIterator::TRANSITION:
3162 done = true; 3103 done = true;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3195 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, 3136 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
3196 Handle<Object> value, 3137 Handle<Object> value,
3197 LanguageMode language_mode, 3138 LanguageMode language_mode,
3198 StoreFromKeyed store_mode) { 3139 StoreFromKeyed store_mode) {
3199 bool found = false; 3140 bool found = false;
3200 MaybeHandle<Object> result = 3141 MaybeHandle<Object> result =
3201 SetPropertyInternal(it, value, language_mode, store_mode, &found); 3142 SetPropertyInternal(it, value, language_mode, store_mode, &found);
3202 if (found) return result; 3143 if (found) return result;
3203 3144
3204 if (!it->GetReceiver()->IsJSReceiver()) { 3145 if (!it->GetReceiver()->IsJSReceiver()) {
3205 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), it->name(), 3146 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
3206 value, language_mode); 3147 it->GetName(), value, language_mode);
3207 } 3148 }
3208 3149
3209 LookupIterator own_lookup(it->GetReceiver(), it->name(), LookupIterator::OWN); 3150 LookupIterator::Configuration c = LookupIterator::OWN;
3151 LookupIterator own_lookup =
3152 it->IsElement()
3153 ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c)
3154 : LookupIterator(it->GetReceiver(), it->name(), c);
3210 3155
3211 switch (own_lookup.state()) { 3156 for (; own_lookup.IsFound(); own_lookup.Next()) {
3212 case LookupIterator::NOT_FOUND: 3157 switch (own_lookup.state()) {
3213 return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode, 3158 case LookupIterator::ACCESS_CHECK:
3214 store_mode); 3159 if (!it->isolate()->MayAccess(own_lookup.GetHolder<JSObject>())) {
3160 return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
3161 language_mode);
3162 }
3163 break;
3215 3164
3216 case LookupIterator::INTEGER_INDEXED_EXOTIC: 3165 case LookupIterator::INTEGER_INDEXED_EXOTIC:
3217 return result; 3166 return result;
3218 3167
3219 case LookupIterator::DATA: { 3168 case LookupIterator::DATA: {
3220 PropertyDetails details = own_lookup.property_details(); 3169 PropertyDetails details = own_lookup.property_details();
3221 if (details.IsConfigurable() || !details.IsReadOnly()) { 3170 if (details.IsConfigurable() || !details.IsReadOnly()) {
3222 return JSObject::SetOwnPropertyIgnoreAttributes( 3171 return JSObject::ReconfigureAsDataProperty(&own_lookup, value,
3223 Handle<JSObject>::cast(it->GetReceiver()), it->name(), value, 3172 details.attributes());
3224 details.attributes()); 3173 }
3225 } 3174 return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
3226 return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
3227 }
3228
3229 case LookupIterator::ACCESSOR: {
3230 PropertyDetails details = own_lookup.property_details();
3231 if (details.IsConfigurable()) {
3232 return JSObject::SetOwnPropertyIgnoreAttributes(
3233 Handle<JSObject>::cast(it->GetReceiver()), it->name(), value,
3234 details.attributes());
3235 } 3175 }
3236 3176
3237 return RedefineNonconfigurableProperty(it->isolate(), it->name(), value, 3177 case LookupIterator::ACCESSOR: {
3238 language_mode); 3178 PropertyDetails details = own_lookup.property_details();
3239 } 3179 if (details.IsConfigurable()) {
3180 return JSObject::ReconfigureAsDataProperty(&own_lookup, value,
3181 details.attributes());
3182 }
3240 3183
3241 case LookupIterator::TRANSITION: 3184 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
3242 UNREACHABLE(); 3185 value, language_mode);
3243 break; 3186 }
3244 3187
3245 case LookupIterator::INTERCEPTOR: 3188 case LookupIterator::INTERCEPTOR:
3246 case LookupIterator::JSPROXY: 3189 case LookupIterator::JSPROXY: {
3247 case LookupIterator::ACCESS_CHECK: { 3190 bool found = false;
3248 bool found = false; 3191 MaybeHandle<Object> result = SetPropertyInternal(
3249 MaybeHandle<Object> result = SetPropertyInternal( 3192 &own_lookup, value, language_mode, store_mode, &found);
3250 &own_lookup, value, language_mode, store_mode, &found); 3193 if (found) return result;
3251 if (found) return result; 3194 break;
3252 return SetDataProperty(&own_lookup, value); 3195 }
3196
3197 case LookupIterator::NOT_FOUND:
3198 case LookupIterator::TRANSITION:
3199 UNREACHABLE();
3253 } 3200 }
3254 } 3201 }
3255 3202
3256 UNREACHABLE(); 3203 return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
3257 return MaybeHandle<Object>(); 3204 store_mode);
3258 } 3205 }
3259 3206
3260 3207
3261 MaybeHandle<Object> Object::WriteToReadOnlyProperty( 3208 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3262 LookupIterator* it, Handle<Object> value, LanguageMode language_mode) { 3209 LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
3263 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), it->name(), 3210 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
3264 value, language_mode); 3211 it->GetName(), value, language_mode);
3265 } 3212 }
3266 3213
3267 3214
3268 MaybeHandle<Object> Object::WriteToReadOnlyProperty( 3215 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3269 Isolate* isolate, Handle<Object> receiver, Handle<Object> name, 3216 Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
3270 Handle<Object> value, LanguageMode language_mode) { 3217 Handle<Object> value, LanguageMode language_mode) {
3271 if (is_sloppy(language_mode)) return value; 3218 if (is_sloppy(language_mode)) return value;
3272 THROW_NEW_ERROR( 3219 THROW_NEW_ERROR(
3273 isolate, 3220 isolate,
3274 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, receiver), 3221 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, receiver),
(...skipping 28 matching lines...) Expand all
3303 // have own properties. 3250 // have own properties.
3304 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 3251 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3305 3252
3306 // Store on the holder which may be hidden behind the receiver. 3253 // Store on the holder which may be hidden behind the receiver.
3307 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); 3254 DCHECK(it->HolderIsReceiverOrHiddenPrototype());
3308 3255
3309 // Old value for the observation change record. 3256 // Old value for the observation change record.
3310 // Fetch before transforming the object since the encoding may become 3257 // Fetch before transforming the object since the encoding may become
3311 // incompatible with what's cached in |it|. 3258 // incompatible with what's cached in |it|.
3312 bool is_observed = receiver->map()->is_observed() && 3259 bool is_observed = receiver->map()->is_observed() &&
3313 !it->isolate()->IsInternallyUsedPropertyName(it->name()); 3260 (it->IsElement() ||
3261 !it->isolate()->IsInternallyUsedPropertyName(it->name()));
3314 MaybeHandle<Object> maybe_old; 3262 MaybeHandle<Object> maybe_old;
3315 if (is_observed) maybe_old = it->GetDataValue(); 3263 if (is_observed) maybe_old = it->GetDataValue();
3316 3264
3265 // Convert the incoming value to a number for storing into typed arrays.
3266 if (it->IsElement() && (receiver->HasExternalArrayElements() ||
3267 receiver->HasFixedTypedArrayElements())) {
3268 if (!value->IsNumber() && !value->IsUndefined()) {
3269 ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), value,
3270 Execution::ToNumber(it->isolate(), value),
3271 Object);
3272 }
3273 }
3274
3317 // Possibly migrate to the most up-to-date map that will be able to store 3275 // Possibly migrate to the most up-to-date map that will be able to store
3318 // |value| under it->name(). 3276 // |value| under it->name().
3319 it->PrepareForDataProperty(value); 3277 it->PrepareForDataProperty(value);
3320 3278
3321 // Write the property value. 3279 // Write the property value.
3322 it->WriteDataValue(value); 3280 value = it->WriteDataValue(value);
3323 3281
3324 // Send the change record if there are observers. 3282 // Send the change record if there are observers.
3325 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) { 3283 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
3326 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( 3284 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3327 receiver, "update", it->name(), 3285 receiver, "update", it->GetName(),
3328 maybe_old.ToHandleChecked()), 3286 maybe_old.ToHandleChecked()),
3329 Object); 3287 Object);
3330 } 3288 }
3331 3289
3332 return value; 3290 return value;
3333 } 3291 }
3334 3292
3335 3293
3294 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
3295 Handle<JSArray> object) {
3296 Isolate* isolate = object->GetIsolate();
3297 HandleScope scope(isolate);
3298 Handle<Object> args[] = {object};
3299
3300 return Execution::Call(
3301 isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
3302 isolate->factory()->undefined_value(), arraysize(args), args);
3303 }
3304
3305
3306 MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
3307 Handle<JSArray> object) {
3308 Isolate* isolate = object->GetIsolate();
3309 HandleScope scope(isolate);
3310 Handle<Object> args[] = {object};
3311
3312 return Execution::Call(
3313 isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
3314 isolate->factory()->undefined_value(), arraysize(args), args);
3315 }
3316
3317
3318 MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
3319 Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
3320 uint32_t add_count) {
3321 Isolate* isolate = object->GetIsolate();
3322 HandleScope scope(isolate);
3323 Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
3324 Handle<Object> add_count_object =
3325 isolate->factory()->NewNumberFromUint(add_count);
3326
3327 Handle<Object> args[] = {object, index_object, deleted, add_count_object};
3328
3329 return Execution::Call(
3330 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
3331 isolate->factory()->undefined_value(), arraysize(args), args);
3332 }
3333
3334
3336 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, 3335 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3337 Handle<Object> value, 3336 Handle<Object> value,
3338 PropertyAttributes attributes, 3337 PropertyAttributes attributes,
3339 LanguageMode language_mode, 3338 LanguageMode language_mode,
3340 StoreFromKeyed store_mode) { 3339 StoreFromKeyed store_mode) {
3341 DCHECK(!it->GetReceiver()->IsJSProxy()); 3340 DCHECK(!it->GetReceiver()->IsJSProxy());
3342 if (!it->GetReceiver()->IsJSObject()) { 3341 if (!it->GetReceiver()->IsJSObject()) {
3343 // TODO(verwaest): Throw a TypeError with a more specific message. 3342 // TODO(verwaest): Throw a TypeError with a more specific message.
3344 return WriteToReadOnlyProperty(it, value, language_mode); 3343 return WriteToReadOnlyProperty(it, value, language_mode);
3345 } 3344 }
3346 3345
3347 if (it->state() == LookupIterator::INTEGER_INDEXED_EXOTIC) return value; 3346 if (it->state() == LookupIterator::INTEGER_INDEXED_EXOTIC) return value;
3348 3347
3349 Handle<JSObject> receiver = it->GetStoreTarget(); 3348 Handle<JSObject> receiver = it->GetStoreTarget();
3350 3349
3351 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) 3350 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3352 // instead. If the prototype is Null, the proxy is detached. 3351 // instead. If the prototype is Null, the proxy is detached.
3353 if (receiver->IsJSGlobalProxy()) return value; 3352 if (receiver->IsJSGlobalProxy()) return value;
3354 3353
3355 // Possibly migrate to the most up-to-date map that will be able to store 3354 Isolate* isolate = it->isolate();
3356 // |value| under it->name() with |attributes|. 3355
3357 it->PrepareTransitionToDataProperty(value, attributes, store_mode); 3356 if (!receiver->map()->is_extensible() &&
3358 if (it->state() != LookupIterator::TRANSITION) { 3357 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) {
3359 if (is_sloppy(language_mode)) return value; 3358 if (is_sloppy(language_mode)) return value;
3360 THROW_NEW_ERROR( 3359 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kObjectNotExtensible,
3361 it->isolate(), 3360 it->GetName()),
3362 NewTypeError(MessageTemplate::kObjectNotExtensible, it->name()), 3361 Object);
3363 Object);
3364 }
3365 it->ApplyTransitionToDataProperty();
3366
3367 // TODO(verwaest): Encapsulate dictionary handling better.
3368 if (receiver->map()->is_dictionary_map()) {
3369 // TODO(verwaest): Probably should ensure this is done beforehand.
3370 it->InternalizeName();
3371 // TODO(dcarney): just populate TransitionPropertyCell here?
3372 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3373 } else {
3374 // Write the property value.
3375 it->WriteDataValue(value);
3376 } 3362 }
3377 3363
3378 // Send the change record if there are observers. 3364 if (it->IsElement()) {
3379 if (receiver->map()->is_observed() && 3365 if (receiver->IsJSArray()) {
3380 !it->isolate()->IsInternallyUsedPropertyName(it->name())) { 3366 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
3381 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( 3367 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
3382 receiver, "add", it->name(), 3368 if (is_sloppy(language_mode)) return value;
3383 it->factory()->the_hole_value()), 3369 return JSArray::ReadOnlyLengthError(array);
3384 Object); 3370 }
3371
3372 if (FLAG_trace_external_array_abuse &&
3373 (array->HasExternalArrayElements() ||
3374 array->HasFixedTypedArrayElements())) {
3375 CheckArrayAbuse(array, "typed elements write", it->index(), true);
3376 }
3377
3378 if (FLAG_trace_js_array_abuse && !array->HasExternalArrayElements() &&
3379 !array->HasFixedTypedArrayElements()) {
3380 CheckArrayAbuse(array, "elements write", it->index(), false);
3381 }
3382 }
3383
3384 return JSObject::AddDataElement(receiver, it->index(), value, attributes);
3385 } else {
3386 // Migrate to the most up-to-date map that will be able to store |value|
3387 // under it->name() with |attributes|.
3388 it->PrepareTransitionToDataProperty(value, attributes, store_mode);
3389 DCHECK_EQ(LookupIterator::TRANSITION, it->state());
3390 it->ApplyTransitionToDataProperty();
3391
3392 // TODO(verwaest): Encapsulate dictionary handling better.
3393 if (receiver->map()->is_dictionary_map()) {
3394 // TODO(verwaest): Probably should ensure this is done beforehand.
3395 it->InternalizeName();
3396 // TODO(dcarney): just populate TransitionPropertyCell here?
3397 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3398 } else {
3399 // Write the property value.
3400 it->WriteDataValue(value);
3401 }
3402
3403 // Send the change record if there are observers.
3404 if (receiver->map()->is_observed() &&
3405 !isolate->IsInternallyUsedPropertyName(it->name())) {
3406 RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord(
3407 receiver, "add", it->name(),
3408 it->factory()->the_hole_value()),
3409 Object);
3410 }
3385 } 3411 }
3386 3412
3387 return value; 3413 return value;
3388 } 3414 }
3389 3415
3390 3416
3391 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3392 Handle<JSObject> object, uint32_t index, Handle<Object> value, bool* found,
3393 LanguageMode language_mode) {
3394 Isolate* isolate = object->GetIsolate();
3395 for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
3396 iter.Advance()) {
3397 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
3398 return JSProxy::SetPropertyViaPrototypesWithHandler(
3399 Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object,
3400 isolate->factory()->Uint32ToString(index), // name
3401 value, language_mode, found);
3402 }
3403 Handle<JSObject> js_proto =
3404 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
3405
3406 if (js_proto->IsAccessCheckNeeded()) {
3407 if (!isolate->MayAccess(js_proto)) {
3408 *found = true;
3409 isolate->ReportFailedAccessCheck(js_proto);
3410 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3411 return MaybeHandle<Object>();
3412 }
3413 }
3414
3415 if (!js_proto->HasDictionaryElements()) {
3416 continue;
3417 }
3418
3419 Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
3420 int entry = dictionary->FindEntry(index);
3421 if (entry != SeededNumberDictionary::kNotFound) {
3422 PropertyDetails details = dictionary->DetailsAt(entry);
3423 if (details.type() == ACCESSOR_CONSTANT) {
3424 *found = true;
3425 Handle<Object> structure(dictionary->ValueAt(entry), isolate);
3426 return SetElementWithCallback(object, structure, index, value, js_proto,
3427 language_mode);
3428 }
3429 }
3430 }
3431 *found = false;
3432 return isolate->factory()->the_hole_value();
3433 }
3434
3435
3436 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { 3417 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3437 // Only supports adding slack to owned descriptors. 3418 // Only supports adding slack to owned descriptors.
3438 DCHECK(map->owns_descriptors()); 3419 DCHECK(map->owns_descriptors());
3439 3420
3440 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 3421 Handle<DescriptorArray> descriptors(map->instance_descriptors());
3441 int old_size = map->NumberOfOwnDescriptors(); 3422 int old_size = map->NumberOfOwnDescriptors();
3442 if (slack <= descriptors->NumberOfSlackDescriptors()) return; 3423 if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3443 3424
3444 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( 3425 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3445 descriptors, old_size, slack); 3426 descriptors, old_size, slack);
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after
4137 DCHECK(maybe.IsJust()); 4118 DCHECK(maybe.IsJust());
4138 DCHECK(!it.IsFound()); 4119 DCHECK(!it.IsFound());
4139 DCHECK(object->map()->is_extensible() || 4120 DCHECK(object->map()->is_extensible() ||
4140 it.isolate()->IsInternallyUsedPropertyName(name)); 4121 it.isolate()->IsInternallyUsedPropertyName(name));
4141 #endif 4122 #endif
4142 AddDataProperty(&it, value, attributes, STRICT, 4123 AddDataProperty(&it, value, attributes, STRICT,
4143 CERTAINLY_NOT_STORE_FROM_KEYED).Check(); 4124 CERTAINLY_NOT_STORE_FROM_KEYED).Check();
4144 } 4125 }
4145 4126
4146 4127
4128 // static
4129 void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) {
4130 info->set_setter(*v8::FromCData(info->GetIsolate(), nullptr));
4131 }
4132
4133
4134 MaybeHandle<Object> JSObject::ReconfigureAsDataProperty(
4135 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes) {
4136 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
4137 bool is_observed = object->map()->is_observed() &&
4138 (it->IsElement() ||
4139 !it->isolate()->IsInternallyUsedPropertyName(it->name()));
4140
4141 switch (it->state()) {
4142 case LookupIterator::INTERCEPTOR:
4143 case LookupIterator::JSPROXY:
4144 case LookupIterator::NOT_FOUND:
4145 case LookupIterator::TRANSITION:
4146 case LookupIterator::ACCESS_CHECK:
4147 UNREACHABLE();
4148
4149 case LookupIterator::INTEGER_INDEXED_EXOTIC:
4150 return value;
4151
4152 case LookupIterator::ACCESSOR: {
4153 PropertyDetails details = it->property_details();
4154 // Ensure the context isn't changed after calling into accessors.
4155 AssertNoContextChange ncc(it->isolate());
4156
4157 Handle<Object> accessors = it->GetAccessors();
4158
4159 // Special handling for ExecutableAccessorInfo, which behaves like a
4160 // data property.
4161 if (accessors->IsExecutableAccessorInfo()) {
4162 Handle<Object> result;
4163 ASSIGN_RETURN_ON_EXCEPTION(
4164 it->isolate(), result,
4165 JSObject::SetPropertyWithAccessor(it, value, STRICT), Object);
4166 DCHECK(result->SameValue(*value));
4167
4168 if (details.attributes() == attributes) return value;
4169
4170 // Reconfigure the accessor if attributes mismatch.
4171 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4172 it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4173 new_data->set_property_attributes(attributes);
4174 // By clearing the setter we don't have to introduce a lookup to
4175 // the setter, simply make it unavailable to reflect the
4176 // attributes.
4177 if (attributes & READ_ONLY) {
4178 ExecutableAccessorInfo::ClearSetter(new_data);
4179 }
4180
4181 if (it->IsElement()) {
4182 SetElementCallback(object, it->index(), new_data, attributes);
4183 } else {
4184 SetPropertyCallback(object, it->name(), new_data, attributes);
4185 }
4186 if (is_observed) {
4187 RETURN_ON_EXCEPTION(
4188 it->isolate(),
4189 EnqueueChangeRecord(object, "reconfigure", it->GetName(),
4190 it->factory()->the_hole_value()),
4191 Object);
4192 }
4193 return value;
4194 }
4195
4196 it->ReconfigureDataProperty(value, attributes);
4197 it->WriteDataValue(value);
4198
4199 if (is_observed) {
4200 RETURN_ON_EXCEPTION(
4201 it->isolate(),
4202 EnqueueChangeRecord(object, "reconfigure", it->GetName(),
4203 it->factory()->the_hole_value()),
4204 Object);
4205 }
4206
4207 return value;
4208 }
4209
4210 case LookupIterator::DATA: {
4211 PropertyDetails details = it->property_details();
4212 Handle<Object> old_value = it->factory()->the_hole_value();
4213 // Regular property update if the attributes match.
4214 if (details.attributes() == attributes) {
4215 return SetDataProperty(it, value);
4216 }
4217
4218 // Special case: properties of typed arrays cannot be reconfigured to
4219 // non-writable nor to non-enumerable.
4220 if (it->IsElement() && (object->HasExternalArrayElements() ||
4221 object->HasFixedTypedArrayElements())) {
4222 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4223 value, STRICT);
4224 }
4225
4226 // Reconfigure the data property if the attributes mismatch.
4227 if (is_observed) old_value = it->GetDataValue();
4228
4229 it->ReconfigureDataProperty(value, attributes);
4230 it->WriteDataValue(value);
4231
4232 if (is_observed) {
4233 if (old_value->SameValue(*value)) {
4234 old_value = it->factory()->the_hole_value();
4235 }
4236 RETURN_ON_EXCEPTION(it->isolate(),
4237 EnqueueChangeRecord(object, "reconfigure",
4238 it->GetName(), old_value),
4239 Object);
4240 }
4241 }
4242 }
4243
4244 return value;
4245 }
4246
4247
4147 // Reconfigures a property to a data property with attributes, even if it is not 4248 // Reconfigures a property to a data property with attributes, even if it is not
4148 // reconfigurable. 4249 // reconfigurable.
4149 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( 4250 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4150 Handle<JSObject> object, 4251 Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
4151 Handle<Name> name, 4252 PropertyAttributes attributes) {
4152 Handle<Object> value,
4153 PropertyAttributes attributes,
4154 ExecutableAccessorInfoHandling handling) {
4155 DCHECK(!value->IsTheHole()); 4253 DCHECK(!value->IsTheHole());
4156 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 4254 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4157 bool is_observed = object->map()->is_observed() && 4255 if (it.state() == LookupIterator::ACCESS_CHECK) {
4158 !it.isolate()->IsInternallyUsedPropertyName(name); 4256 if (!it.isolate()->MayAccess(object)) {
4159 for (; it.IsFound(); it.Next()) { 4257 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4160 switch (it.state()) { 4258 }
4161 case LookupIterator::INTEGER_INDEXED_EXOTIC: 4259 it.Next();
4162 return value; 4260 }
4163 4261
4164 case LookupIterator::INTERCEPTOR: 4262 if (it.IsFound()) {
4165 case LookupIterator::JSPROXY: 4263 return ReconfigureAsDataProperty(&it, value, attributes);
4166 case LookupIterator::NOT_FOUND:
4167 case LookupIterator::TRANSITION:
4168 UNREACHABLE();
4169
4170 case LookupIterator::ACCESS_CHECK:
4171 if (!it.isolate()->MayAccess(object)) {
4172 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4173 }
4174 break;
4175
4176 case LookupIterator::ACCESSOR: {
4177 PropertyDetails details = it.property_details();
4178 // Ensure the context isn't changed after calling into accessors.
4179 AssertNoContextChange ncc(it.isolate());
4180
4181 Handle<Object> accessors = it.GetAccessors();
4182
4183 // Special handling for ExecutableAccessorInfo, which behaves like a
4184 // data property.
4185 if (handling == DONT_FORCE_FIELD &&
4186 accessors->IsExecutableAccessorInfo()) {
4187 Handle<Object> result;
4188 ASSIGN_RETURN_ON_EXCEPTION(
4189 it.isolate(), result,
4190 JSObject::SetPropertyWithAccessor(it.GetReceiver(), it.name(),
4191 value, it.GetHolder<JSObject>(),
4192 accessors, STRICT),
4193 Object);
4194 DCHECK(result->SameValue(*value));
4195
4196 if (details.attributes() == attributes) {
4197 return value;
4198 }
4199
4200 // Reconfigure the accessor if attributes mismatch.
4201 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4202 it.isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4203 new_data->set_property_attributes(attributes);
4204 // By clearing the setter we don't have to introduce a lookup to
4205 // the setter, simply make it unavailable to reflect the
4206 // attributes.
4207 if (attributes & READ_ONLY) {
4208 ExecutableAccessorInfo::ClearSetter(new_data);
4209 }
4210 SetPropertyCallback(object, name, new_data, attributes);
4211 if (is_observed) {
4212 RETURN_ON_EXCEPTION(
4213 it.isolate(),
4214 EnqueueChangeRecord(object, "reconfigure", name,
4215 it.isolate()->factory()->the_hole_value()),
4216 Object);
4217 }
4218 return value;
4219 }
4220
4221 it.ReconfigureDataProperty(value, attributes);
4222 it.WriteDataValue(value);
4223
4224 if (is_observed) {
4225 RETURN_ON_EXCEPTION(
4226 it.isolate(),
4227 EnqueueChangeRecord(object, "reconfigure", name,
4228 it.isolate()->factory()->the_hole_value()),
4229 Object);
4230 }
4231
4232 return value;
4233 }
4234
4235 case LookupIterator::DATA: {
4236 PropertyDetails details = it.property_details();
4237 Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
4238 // Regular property update if the attributes match.
4239 if (details.attributes() == attributes) {
4240 return SetDataProperty(&it, value);
4241 }
4242 // Reconfigure the data property if the attributes mismatch.
4243 if (is_observed) old_value = it.GetDataValue();
4244
4245 it.ReconfigureDataProperty(value, attributes);
4246 it.WriteDataValue(value);
4247
4248 if (is_observed) {
4249 if (old_value->SameValue(*value)) {
4250 old_value = it.isolate()->factory()->the_hole_value();
4251 }
4252 RETURN_ON_EXCEPTION(
4253 it.isolate(),
4254 EnqueueChangeRecord(object, "reconfigure", name, old_value),
4255 Object);
4256 }
4257
4258 return value;
4259 }
4260 }
4261 } 4264 }
4262 4265
4263 return AddDataProperty(&it, value, attributes, STRICT, 4266 return AddDataProperty(&it, value, attributes, STRICT,
4264 CERTAINLY_NOT_STORE_FROM_KEYED); 4267 CERTAINLY_NOT_STORE_FROM_KEYED);
4265 } 4268 }
4266 4269
4267 4270
4271 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
4272 Handle<JSObject> object, uint32_t index, Handle<Object> value,
4273 PropertyAttributes attributes) {
4274 DCHECK(!object->HasExternalArrayElements());
4275 Isolate* isolate = object->GetIsolate();
4276 LookupIterator it(isolate, object, index,
4277 LookupIterator::OWN_SKIP_INTERCEPTOR);
4278 if (it.state() == LookupIterator::ACCESS_CHECK) {
4279 if (!isolate->MayAccess(object)) {
4280 return SetPropertyWithFailedAccessCheck(&it, value, STRICT);
4281 }
4282 it.Next();
4283 }
4284
4285 if (it.IsFound()) {
4286 return ReconfigureAsDataProperty(&it, value, attributes);
4287 }
4288
4289 return AddDataProperty(&it, value, attributes, STRICT,
4290 MAY_BE_STORE_FROM_KEYED);
4291 }
4292
4293
4268 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( 4294 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4269 LookupIterator* it) { 4295 LookupIterator* it) {
4270 Isolate* isolate = it->isolate(); 4296 Isolate* isolate = it->isolate();
4271 // Make sure that the top context does not change when doing 4297 // Make sure that the top context does not change when doing
4272 // callbacks or interceptor calls. 4298 // callbacks or interceptor calls.
4273 AssertNoContextChange ncc(isolate); 4299 AssertNoContextChange ncc(isolate);
4274 HandleScope scope(isolate); 4300 HandleScope scope(isolate);
4275 4301
4276 Handle<JSObject> holder = it->GetHolder<JSObject>(); 4302 Handle<JSObject> holder = it->GetHolder<JSObject>();
4277 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); 4303 Handle<InterceptorInfo> interceptor(it->GetInterceptor());
(...skipping 2869 matching lines...) Expand 10 before | Expand all | Expand 10 after
7147 case ACCESSOR: 7173 case ACCESSOR:
7148 case ACCESSOR_CONSTANT: 7174 case ACCESSOR_CONSTANT:
7149 return false; 7175 return false;
7150 } 7176 }
7151 7177
7152 UNREACHABLE(); 7178 UNREACHABLE();
7153 return false; 7179 return false;
7154 } 7180 }
7155 7181
7156 7182
7183 // static
7184 Handle<Map> Map::PrepareForDataElement(Handle<Map> map, Handle<Object> value) {
7185 ElementsKind kind = map->elements_kind();
7186 bool holey = IsHoleyElementsKind(kind);
7187
7188 switch (kind) {
7189 case FAST_SMI_ELEMENTS:
7190 case FAST_HOLEY_SMI_ELEMENTS:
7191 if (value->IsSmi()) return map;
7192 kind = value->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS;
7193 break;
7194
7195 case FAST_DOUBLE_ELEMENTS:
7196 case FAST_HOLEY_DOUBLE_ELEMENTS:
7197 if (value->IsNumber()) return map;
7198 kind = FAST_ELEMENTS;
7199 break;
7200
7201 case FAST_ELEMENTS:
7202 case FAST_HOLEY_ELEMENTS:
7203 case DICTIONARY_ELEMENTS:
7204 case SLOPPY_ARGUMENTS_ELEMENTS:
7205 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
7206 case EXTERNAL_##TYPE##_ELEMENTS: \
7207 case TYPE##_ELEMENTS:
7208
7209 TYPED_ARRAYS(TYPED_ARRAY_CASE)
7210 #undef TYPED_ARRAY_CASE
7211 return map;
7212 }
7213
7214 if (holey) kind = GetHoleyElementsKind(kind);
7215 return Map::AsElementsKind(map, kind);
7216 }
7217
7218
7219 // static
7157 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, 7220 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
7158 Handle<Object> value) { 7221 Handle<Object> value) {
7159 // Dictionaries can store any property value. 7222 // Dictionaries can store any property value.
7160 if (map->is_dictionary_map()) return map; 7223 if (map->is_dictionary_map()) return map;
7161 7224
7162 // Migrate to the newest map before storing the property. 7225 // Migrate to the newest map before storing the property.
7163 map = Update(map); 7226 map = Update(map);
7164 7227
7165 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 7228 Handle<DescriptorArray> descriptors(map->instance_descriptors());
7166 7229
(...skipping 4722 matching lines...) Expand 10 before | Expand all | Expand 10 after
11889 if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) { 11952 if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
11890 value = Handle<Object>::cast(isolate->factory()->the_hole_value()); 11953 value = Handle<Object>::cast(isolate->factory()->the_hole_value());
11891 } else { 11954 } else {
11892 value = Object::GetElement(isolate, object, index).ToHandleChecked(); 11955 value = Object::GetElement(isolate, object, index).ToHandleChecked();
11893 } 11956 }
11894 old_values->Add(value); 11957 old_values->Add(value);
11895 indices->Add(index); 11958 indices->Add(index);
11896 return true; 11959 return true;
11897 } 11960 }
11898 11961
11899 MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
11900 Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
11901 uint32_t add_count) {
11902 Isolate* isolate = object->GetIsolate();
11903 HandleScope scope(isolate);
11904 Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
11905 Handle<Object> add_count_object =
11906 isolate->factory()->NewNumberFromUint(add_count);
11907
11908 Handle<Object> args[] =
11909 { object, index_object, deleted, add_count_object };
11910
11911 return Execution::Call(
11912 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
11913 isolate->factory()->undefined_value(), arraysize(args), args);
11914 }
11915
11916
11917 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
11918 Handle<JSArray> object) {
11919 Isolate* isolate = object->GetIsolate();
11920 HandleScope scope(isolate);
11921 Handle<Object> args[] = { object };
11922
11923 return Execution::Call(
11924 isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
11925 isolate->factory()->undefined_value(), arraysize(args), args);
11926 }
11927
11928
11929 MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
11930 Handle<JSArray> object) {
11931 Isolate* isolate = object->GetIsolate();
11932 HandleScope scope(isolate);
11933 Handle<Object> args[] = { object };
11934
11935 return Execution::Call(
11936 isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
11937 isolate->factory()->undefined_value(), arraysize(args), args);
11938 }
11939
11940
11941 MaybeHandle<Object> JSArray::SetElementsLength( 11962 MaybeHandle<Object> JSArray::SetElementsLength(
11942 Handle<JSArray> array, 11963 Handle<JSArray> array,
11943 Handle<Object> new_length_handle) { 11964 Handle<Object> new_length_handle) {
11944 if (array->HasFastElements() && 11965 if (array->HasFastElements() &&
11945 SetElementsLengthWouldNormalize(array->GetHeap(), new_length_handle)) { 11966 SetElementsLengthWouldNormalize(array->GetHeap(), new_length_handle)) {
11946 NormalizeElements(array); 11967 NormalizeElements(array);
11947 } 11968 }
11948 11969
11949 // We should never end in here with a pixel or external array. 11970 // We should never end in here with a pixel or external array.
11950 DCHECK(array->AllowsSetElementsLength()); 11971 DCHECK(array->AllowsSetElementsLength());
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
12015 12036
12016 uint32_t index = Min(old_length, new_length); 12037 uint32_t index = Min(old_length, new_length);
12017 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; 12038 uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
12018 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; 12039 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
12019 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); 12040 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12020 if (delete_count > 0) { 12041 if (delete_count > 0) {
12021 for (int i = indices.length() - 1; i >= 0; i--) { 12042 for (int i = indices.length() - 1; i >= 0; i--) {
12022 // Skip deletions where the property was an accessor, leaving holes 12043 // Skip deletions where the property was an accessor, leaving holes
12023 // in the array of old values. 12044 // in the array of old values.
12024 if (old_values[i]->IsTheHole()) continue; 12045 if (old_values[i]->IsTheHole()) continue;
12025 JSObject::SetOwnElement(deleted, indices[i] - index, old_values[i], 12046 JSObject::AddDataElement(deleted, indices[i] - index, old_values[i], NONE)
12026 SLOPPY).Assert(); 12047 .Assert();
12027 } 12048 }
12028 12049
12029 RETURN_ON_EXCEPTION( 12050 SetProperty(deleted, isolate->factory()->length_string(),
12030 isolate, 12051 isolate->factory()->NewNumberFromUint(delete_count),
12031 SetProperty(deleted, isolate->factory()->length_string(), 12052 STRICT).Assert();
12032 isolate->factory()->NewNumberFromUint(delete_count),
12033 STRICT),
12034 Object);
12035 } 12053 }
12036 12054
12037 RETURN_ON_EXCEPTION( 12055 RETURN_ON_EXCEPTION(
12038 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object); 12056 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
12039 12057
12040 return hresult; 12058 return hresult;
12041 } 12059 }
12042 12060
12043 12061
12044 // static 12062 // static
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
12449 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); 12467 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
12450 } 12468 }
12451 12469
12452 // Check for lookup interceptor. 12470 // Check for lookup interceptor.
12453 if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>(); 12471 if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>();
12454 12472
12455 return object->GetElementsAccessor()->GetAccessorPair(object, index); 12473 return object->GetElementsAccessor()->GetAccessorPair(object, index);
12456 } 12474 }
12457 12475
12458 12476
12459 MaybeHandle<Object> JSObject::SetElementWithInterceptor(
12460 Handle<JSObject> object, uint32_t index, Handle<Object> value,
12461 PropertyAttributes attributes, LanguageMode language_mode,
12462 bool check_prototype, SetPropertyMode set_mode) {
12463 Isolate* isolate = object->GetIsolate();
12464
12465 // Make sure that the top context does not change when doing
12466 // callbacks or interceptor calls.
12467 AssertNoContextChange ncc(isolate);
12468
12469 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
12470 if (!interceptor->setter()->IsUndefined()) {
12471 v8::IndexedPropertySetterCallback setter =
12472 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
12473 LOG(isolate,
12474 ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
12475 PropertyCallbackArguments args(isolate, interceptor->data(), *object,
12476 *object);
12477 v8::Handle<v8::Value> result =
12478 args.Call(setter, index, v8::Utils::ToLocal(value));
12479 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12480 if (!result.IsEmpty()) return value;
12481 }
12482
12483 return SetElementWithoutInterceptor(object, index, value, attributes,
12484 language_mode, check_prototype, set_mode);
12485 }
12486
12487
12488 MaybeHandle<Object> JSObject::SetElementWithCallback(
12489 Handle<Object> object, Handle<Object> structure, uint32_t index,
12490 Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) {
12491 Isolate* isolate = holder->GetIsolate();
12492
12493 // We should never get here to initialize a const with the hole
12494 // value since a const declaration would conflict with the setter.
12495 DCHECK(!value->IsTheHole());
12496 DCHECK(!structure->IsForeign());
12497 if (structure->IsExecutableAccessorInfo()) {
12498 // api style callbacks
12499 Handle<ExecutableAccessorInfo> data =
12500 Handle<ExecutableAccessorInfo>::cast(structure);
12501 Object* call_obj = data->setter();
12502 v8::AccessorNameSetterCallback call_fun =
12503 v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
12504 if (call_fun == NULL) return value;
12505 Handle<String> key(isolate->factory()->Uint32ToString(index));
12506 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *key));
12507 PropertyCallbackArguments
12508 args(isolate, data->data(), *object, *holder);
12509 args.Call(call_fun,
12510 v8::Utils::ToLocal(key),
12511 v8::Utils::ToLocal(value));
12512 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12513 return value;
12514 }
12515
12516 if (structure->IsAccessorPair()) {
12517 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
12518 if (setter->IsSpecFunction()) {
12519 // TODO(rossberg): nicer would be to cast to some JSCallable here...
12520 return SetPropertyWithDefinedSetter(
12521 object, Handle<JSReceiver>::cast(setter), value);
12522 } else {
12523 if (is_sloppy(language_mode)) return value;
12524 Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
12525 THROW_NEW_ERROR(
12526 isolate,
12527 NewTypeError(MessageTemplate::kNoSetterInCallback, key, holder),
12528 Object);
12529 }
12530 }
12531
12532 UNREACHABLE();
12533 return MaybeHandle<Object>();
12534 }
12535
12536
12537 bool JSObject::HasFastArgumentsElements() { 12477 bool JSObject::HasFastArgumentsElements() {
12538 Heap* heap = GetHeap(); 12478 Heap* heap = GetHeap();
12539 if (!elements()->IsFixedArray()) return false; 12479 if (!elements()->IsFixedArray()) return false;
12540 FixedArray* elements = FixedArray::cast(this->elements()); 12480 FixedArray* elements = FixedArray::cast(this->elements());
12541 if (elements->map() != heap->sloppy_arguments_elements_map()) { 12481 if (elements->map() != heap->sloppy_arguments_elements_map()) {
12542 return false; 12482 return false;
12543 } 12483 }
12544 FixedArray* arguments = FixedArray::cast(elements->get(1)); 12484 FixedArray* arguments = FixedArray::cast(elements->get(1));
12545 return !arguments->IsDictionary(); 12485 return !arguments->IsDictionary();
12546 } 12486 }
12547 12487
12548 12488
12549 bool JSObject::HasDictionaryArgumentsElements() { 12489 bool JSObject::HasDictionaryArgumentsElements() {
12550 Heap* heap = GetHeap(); 12490 Heap* heap = GetHeap();
12551 if (!elements()->IsFixedArray()) return false; 12491 if (!elements()->IsFixedArray()) return false;
12552 FixedArray* elements = FixedArray::cast(this->elements()); 12492 FixedArray* elements = FixedArray::cast(this->elements());
12553 if (elements->map() != heap->sloppy_arguments_elements_map()) { 12493 if (elements->map() != heap->sloppy_arguments_elements_map()) {
12554 return false; 12494 return false;
12555 } 12495 }
12556 FixedArray* arguments = FixedArray::cast(elements->get(1)); 12496 FixedArray* arguments = FixedArray::cast(elements->get(1));
12557 return arguments->IsDictionary(); 12497 return arguments->IsDictionary();
12558 } 12498 }
12559 12499
12560 12500
12561 // Adding n elements in fast case is O(n*n). 12501 void JSObject::SetFastElement(Handle<JSObject> object, uint32_t index,
12562 // Note: revisit design to have dual undefined values to capture absent 12502 Handle<Object> value) {
12563 // elements.
12564 MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
12565 uint32_t index,
12566 Handle<Object> value,
12567 LanguageMode language_mode,
12568 bool check_prototype) {
12569 DCHECK(object->HasFastSmiOrObjectElements() || 12503 DCHECK(object->HasFastSmiOrObjectElements() ||
12570 object->HasFastArgumentsElements()); 12504 object->HasFastArgumentsElements());
12571 12505
12572 Isolate* isolate = object->GetIsolate(); 12506 Isolate* isolate = object->GetIsolate();
12573 12507
12574 // Array optimizations rely on the prototype lookups of Array objects always 12508 // Array optimizations rely on the prototype lookups of Array objects always
12575 // returning undefined. If there is a store to the initial prototype object, 12509 // returning undefined. If there is a store to the initial prototype object,
12576 // make sure all of these optimizations are invalidated. 12510 // make sure all of these optimizations are invalidated.
12577 isolate->UpdateArrayProtectorOnSetElement(object); 12511 isolate->UpdateArrayProtectorOnSetElement(object);
12578 12512
12579 Handle<FixedArray> backing_store(FixedArray::cast(object->elements())); 12513 Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12580 if (backing_store->map() == 12514 if (object->HasSloppyArgumentsElements()) {
12581 isolate->heap()->sloppy_arguments_elements_map()) {
12582 backing_store = handle(FixedArray::cast(backing_store->get(1))); 12515 backing_store = handle(FixedArray::cast(backing_store->get(1)));
12583 } else { 12516 } else {
12584 backing_store = EnsureWritableFastElements(object); 12517 backing_store = EnsureWritableFastElements(object);
12585 } 12518 }
12586 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); 12519 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12587 12520
12588 if (check_prototype &&
12589 (index >= capacity || backing_store->get(index)->IsTheHole())) {
12590 bool found;
12591 MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12592 object, index, value, &found, language_mode);
12593 if (found) return result;
12594 }
12595
12596 uint32_t new_capacity = capacity; 12521 uint32_t new_capacity = capacity;
12597 // Check if the length property of this object needs to be updated. 12522 // Check if the length property of this object needs to be updated.
12598 uint32_t array_length = 0; 12523 uint32_t array_length = 0;
12599 bool must_update_array_length = false; 12524 bool must_update_array_length = false;
12600 bool introduces_holes = true; 12525 bool introduces_holes = true;
12601 if (object->IsJSArray()) { 12526 if (object->IsJSArray()) {
12602 CHECK( 12527 CHECK(
12603 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length)); 12528 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length));
12604 introduces_holes = index > array_length; 12529 introduces_holes = index > array_length;
12605 if (index >= array_length) { 12530 if (index >= array_length) {
(...skipping 20 matching lines...) Expand all
12626 bool convert_to_slow = true; 12551 bool convert_to_slow = true;
12627 if ((index - capacity) < kMaxGap) { 12552 if ((index - capacity) < kMaxGap) {
12628 new_capacity = NewElementsCapacity(index + 1); 12553 new_capacity = NewElementsCapacity(index + 1);
12629 DCHECK(new_capacity > index); 12554 DCHECK(new_capacity > index);
12630 if (!object->ShouldConvertToSlowElements(new_capacity)) { 12555 if (!object->ShouldConvertToSlowElements(new_capacity)) {
12631 convert_to_slow = false; 12556 convert_to_slow = false;
12632 } 12557 }
12633 } 12558 }
12634 if (convert_to_slow) { 12559 if (convert_to_slow) {
12635 NormalizeElements(object); 12560 NormalizeElements(object);
12636 return SetDictionaryElement(object, index, value, NONE, language_mode, 12561 SetDictionaryElement(object, index, value, NONE);
12637 check_prototype); 12562 return;
12638 } 12563 }
12639 } 12564 }
12640 // Convert to fast double elements if appropriate. 12565 // Convert to fast double elements if appropriate.
12641 if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { 12566 if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12642 // Consider fixing the boilerplate as well if we have one. 12567 // Consider fixing the boilerplate as well if we have one.
12643 ElementsKind to_kind = IsHoleyElementsKind(elements_kind) 12568 ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
12644 ? FAST_HOLEY_DOUBLE_ELEMENTS 12569 ? FAST_HOLEY_DOUBLE_ELEMENTS
12645 : FAST_DOUBLE_ELEMENTS; 12570 : FAST_DOUBLE_ELEMENTS;
12646 12571
12647 UpdateAllocationSite(object, to_kind); 12572 UpdateAllocationSite(object, to_kind);
12648 12573
12649 SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length); 12574 SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12650 FixedDoubleArray::cast(object->elements())->set(index, value->Number()); 12575 FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12651 JSObject::ValidateElements(object); 12576 JSObject::ValidateElements(object);
12652 return value; 12577 return;
12653 } 12578 }
12654 // Change elements kind from Smi-only to generic FAST if necessary. 12579 // Change elements kind from Smi-only to generic FAST if necessary.
12655 if (object->HasFastSmiElements() && !value->IsSmi()) { 12580 if (object->HasFastSmiElements() && !value->IsSmi()) {
12656 ElementsKind kind = object->HasFastHoleyElements() 12581 ElementsKind kind = object->HasFastHoleyElements()
12657 ? FAST_HOLEY_ELEMENTS 12582 ? FAST_HOLEY_ELEMENTS
12658 : FAST_ELEMENTS; 12583 : FAST_ELEMENTS;
12659 12584
12660 UpdateAllocationSite(object, kind); 12585 UpdateAllocationSite(object, kind);
12661 Handle<Map> new_map = GetElementsTransitionMap(object, kind); 12586 Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12662 JSObject::MigrateToMap(object, new_map); 12587 JSObject::MigrateToMap(object, new_map);
12663 DCHECK(IsFastObjectElementsKind(object->GetElementsKind())); 12588 DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12664 } 12589 }
12665 // Increase backing store capacity if that's been decided previously. 12590 // Increase backing store capacity if that's been decided previously.
12666 if (new_capacity != capacity) { 12591 if (new_capacity != capacity) {
12667 SetFastElementsCapacitySmiMode smi_mode = 12592 SetFastElementsCapacitySmiMode smi_mode =
12668 value->IsSmi() && object->HasFastSmiElements() 12593 value->IsSmi() && object->HasFastSmiElements()
12669 ? kAllowSmiElements 12594 ? kAllowSmiElements
12670 : kDontAllowSmiElements; 12595 : kDontAllowSmiElements;
12671 Handle<FixedArray> new_elements = 12596 Handle<FixedArray> new_elements =
12672 SetFastElementsCapacityAndLength(object, new_capacity, array_length, 12597 SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12673 smi_mode); 12598 smi_mode);
12674 new_elements->set(index, *value); 12599 new_elements->set(index, *value);
12675 JSObject::ValidateElements(object); 12600 JSObject::ValidateElements(object);
12676 return value; 12601 return;
12677 } 12602 }
12678 12603
12679 // Finally, set the new element and length. 12604 // Finally, set the new element and length.
12680 DCHECK(object->elements()->IsFixedArray()); 12605 DCHECK(object->elements()->IsFixedArray());
12681 backing_store->set(index, *value); 12606 backing_store->set(index, *value);
12682 if (must_update_array_length) { 12607 if (must_update_array_length) {
12683 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); 12608 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12684 } 12609 }
12685 return value;
12686 } 12610 }
12687 12611
12688 12612
12689 MaybeHandle<Object> JSObject::SetDictionaryElement( 12613 void JSObject::SetSloppyArgumentsElement(Handle<JSObject> object,
12690 Handle<JSObject> object, uint32_t index, Handle<Object> value, 12614 uint32_t index, Handle<Object> value,
12691 PropertyAttributes attributes, LanguageMode language_mode, 12615 PropertyAttributes attributes) {
12692 bool check_prototype, SetPropertyMode set_mode) { 12616 // TODO(verwaest): Handle with the elements accessor.
12693 DCHECK(object->HasDictionaryElements() || 12617 Isolate* isolate = object->GetIsolate();
12694 object->HasDictionaryArgumentsElements()); 12618
12619 DCHECK(object->HasSloppyArgumentsElements());
12620
12621 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
12622 uint32_t length = parameter_map->length();
12623 Handle<Object> probe =
12624 index < length - 2
12625 ? Handle<Object>(parameter_map->get(index + 2), isolate)
12626 : Handle<Object>();
12627 if (!probe.is_null() && !probe->IsTheHole()) {
12628 Handle<Context> context(Context::cast(parameter_map->get(0)));
12629 int context_index = Handle<Smi>::cast(probe)->value();
12630 DCHECK(!context->get(context_index)->IsTheHole());
12631 context->set(context_index, *value);
12632
12633 if (attributes == NONE) return;
12634
12635 // Redefining attributes of an aliased element destroys fast aliasing.
12636 parameter_map->set_the_hole(index + 2);
12637 // For elements that are still writable we re-establish slow aliasing.
12638 if ((attributes & READ_ONLY) == 0) {
12639 value = Handle<Object>::cast(
12640 isolate->factory()->NewAliasedArgumentsEntry(context_index));
12641 }
12642 }
12643
12644 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
12645 if (arguments->IsDictionary()) {
12646 SetDictionaryElement(object, index, value, attributes);
12647 } else {
12648 SetFastElement(object, index, value);
12649 }
12650 }
12651
12652
12653 void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index,
12654 Handle<Object> value,
12655 PropertyAttributes attributes) {
12656 // TODO(verwaest): Handle with the elements accessor.
12695 Isolate* isolate = object->GetIsolate(); 12657 Isolate* isolate = object->GetIsolate();
12696 12658
12697 // Insert element in the dictionary. 12659 // Insert element in the dictionary.
12698 Handle<FixedArray> elements(FixedArray::cast(object->elements())); 12660 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12699 bool is_arguments = 12661 bool is_arguments =
12700 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); 12662 (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12663
12664 DCHECK(object->HasDictionaryElements() ||
12665 object->HasDictionaryArgumentsElements());
12666
12701 Handle<SeededNumberDictionary> dictionary(is_arguments 12667 Handle<SeededNumberDictionary> dictionary(is_arguments
12702 ? SeededNumberDictionary::cast(elements->get(1)) 12668 ? SeededNumberDictionary::cast(elements->get(1))
12703 : SeededNumberDictionary::cast(*elements)); 12669 : SeededNumberDictionary::cast(*elements));
12704 12670
12705 int entry = dictionary->FindEntry(index); 12671 int entry = dictionary->FindEntry(index);
12706 if (entry != SeededNumberDictionary::kNotFound) { 12672 if (entry != SeededNumberDictionary::kNotFound) {
12707 Handle<Object> element(dictionary->ValueAt(entry), isolate); 12673 Handle<Object> element(dictionary->ValueAt(entry), isolate);
12708 PropertyDetails details = dictionary->DetailsAt(entry); 12674 PropertyDetails details = dictionary->DetailsAt(entry);
12709 if (details.type() == ACCESSOR_CONSTANT && set_mode == SET_PROPERTY) { 12675 DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
12710 return SetElementWithCallback(object, element, index, value, object, 12676 element->IsTheHole());
12711 language_mode); 12677 dictionary->UpdateMaxNumberKey(index);
12712 } else if (set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
12713 details.kind() == kAccessor) {
12714 return RedefineNonconfigurableProperty(
12715 isolate, isolate->factory()->NewNumberFromUint(index),
12716 isolate->factory()->undefined_value(), language_mode);
12717 12678
12718 } else if ((set_mode == DEFINE_PROPERTY && !details.IsConfigurable() && 12679 details = PropertyDetails(attributes, DATA, details.dictionary_index(),
12719 details.IsReadOnly()) || 12680 PropertyCellType::kNoCell);
12720 (set_mode == SET_PROPERTY && details.IsReadOnly() && 12681 dictionary->DetailsAtPut(entry, details);
12721 !element->IsTheHole())) {
12722 // If a value has not been initialized we allow writing to it even if it
12723 // is read-only (a declared const that has not been initialized).
12724 return WriteToReadOnlyProperty(
12725 isolate, object, isolate->factory()->NewNumberFromUint(index),
12726 isolate->factory()->undefined_value(), language_mode);
12727 } else {
12728 DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
12729 element->IsTheHole());
12730 dictionary->UpdateMaxNumberKey(index);
12731 if (set_mode == DEFINE_PROPERTY) {
12732 details = PropertyDetails(attributes, DATA, details.dictionary_index(),
12733 PropertyCellType::kNoCell);
12734 dictionary->DetailsAtPut(entry, details);
12735 }
12736 12682
12737 // Elements of the arguments object in slow mode might be slow aliases. 12683 // Elements of the arguments object in slow mode might be slow aliases.
12738 if (is_arguments && element->IsAliasedArgumentsEntry()) { 12684 if (is_arguments && element->IsAliasedArgumentsEntry()) {
12739 Handle<AliasedArgumentsEntry> entry = 12685 Handle<AliasedArgumentsEntry> entry =
12740 Handle<AliasedArgumentsEntry>::cast(element); 12686 Handle<AliasedArgumentsEntry>::cast(element);
12741 Handle<Context> context(Context::cast(elements->get(0))); 12687 Handle<Context> context(Context::cast(elements->get(0)));
12742 int context_index = entry->aliased_context_slot(); 12688 int context_index = entry->aliased_context_slot();
12743 DCHECK(!context->get(context_index)->IsTheHole()); 12689 DCHECK(!context->get(context_index)->IsTheHole());
12744 context->set(context_index, *value); 12690 context->set(context_index, *value);
12745 // For elements that are still writable we keep slow aliasing. 12691 // For elements that are still writable we keep slow aliasing.
12746 if (!details.IsReadOnly()) value = element; 12692 if (!details.IsReadOnly()) value = element;
12747 }
12748 dictionary->ValueAtPut(entry, *value);
12749 } 12693 }
12694 dictionary->ValueAtPut(entry, *value);
12750 } else { 12695 } else {
12751 // Index not already used. Look for an accessor in the prototype chain. 12696 DCHECK(object->map()->is_extensible());
12752 // Can cause GC!
12753 if (check_prototype) {
12754 bool found;
12755 MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12756 object, index, value, &found, language_mode);
12757 if (found) return result;
12758 }
12759
12760 // When we set the is_extensible flag to false we always force the
12761 // element into dictionary mode (and force them to stay there).
12762 if (!object->map()->is_extensible()) {
12763 if (is_sloppy(language_mode)) {
12764 return isolate->factory()->undefined_value();
12765 } else {
12766 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12767 Handle<String> name = isolate->factory()->NumberToString(number);
12768 THROW_NEW_ERROR(
12769 isolate, NewTypeError(MessageTemplate::kObjectNotExtensible, name),
12770 Object);
12771 }
12772 }
12773
12774 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); 12697 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
12775 Handle<SeededNumberDictionary> new_dictionary = 12698 Handle<SeededNumberDictionary> new_dictionary =
12776 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, 12699 SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
12777 details); 12700 details);
12778 if (*dictionary != *new_dictionary) { 12701 if (*dictionary != *new_dictionary) {
12779 if (is_arguments) { 12702 if (is_arguments) {
12780 elements->set(1, *new_dictionary); 12703 elements->set(1, *new_dictionary);
12781 } else { 12704 } else {
12782 object->set_elements(*new_dictionary); 12705 object->set_elements(*new_dictionary);
12783 } 12706 }
(...skipping 30 matching lines...) Expand all
12814 } 12737 }
12815 JSObject::ValidateElements(object); 12738 JSObject::ValidateElements(object);
12816 #ifdef DEBUG 12739 #ifdef DEBUG
12817 if (FLAG_trace_normalization) { 12740 if (FLAG_trace_normalization) {
12818 OFStream os(stdout); 12741 OFStream os(stdout);
12819 os << "Object elements are fast case again:\n"; 12742 os << "Object elements are fast case again:\n";
12820 object->Print(os); 12743 object->Print(os);
12821 } 12744 }
12822 #endif 12745 #endif
12823 } 12746 }
12824 return value;
12825 } 12747 }
12826 12748
12827 MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object, 12749 void JSObject::SetFastDoubleElement(Handle<JSObject> object, uint32_t index,
12828 uint32_t index, 12750 Handle<Object> value) {
12829 Handle<Object> value,
12830 LanguageMode language_mode,
12831 bool check_prototype) {
12832 DCHECK(object->HasFastDoubleElements()); 12751 DCHECK(object->HasFastDoubleElements());
12833 12752
12834 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); 12753 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12835 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); 12754 uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
12755 uint32_t length = elms_length;
12836 12756
12837 // If storing to an element that isn't in the array, pass the store request
12838 // up the prototype chain before storing in the receiver's elements.
12839 if (check_prototype &&
12840 (index >= elms_length ||
12841 Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
12842 bool found;
12843 MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12844 object, index, value, &found, language_mode);
12845 if (found) return result;
12846 }
12847
12848 // If the value object is not a heap number, switch to fast elements and try
12849 // again.
12850 bool value_is_smi = value->IsSmi();
12851 bool introduces_holes = true; 12757 bool introduces_holes = true;
12852 uint32_t length = elms_length;
12853 if (object->IsJSArray()) { 12758 if (object->IsJSArray()) {
12759 // In case of JSArray, the length does not equal the capacity.
12854 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length)); 12760 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length));
12855 introduces_holes = index > length; 12761 introduces_holes = index > length;
12856 } else { 12762 } else {
12857 introduces_holes = index >= elms_length; 12763 introduces_holes = index >= elms_length;
12858 } 12764 }
12859 12765
12766 // If the value object is not a heap number, switch to fast elements and try
12767 // again.
12860 if (!value->IsNumber()) { 12768 if (!value->IsNumber()) {
12861 SetFastElementsCapacityAndLength(object, elms_length, length, 12769 SetFastElementsCapacityAndLength(object, elms_length, length,
12862 kDontAllowSmiElements); 12770 kDontAllowSmiElements);
12863 Handle<Object> result; 12771 SetFastElement(object, index, value);
12864 ASSIGN_RETURN_ON_EXCEPTION( 12772 return;
12865 object->GetIsolate(), result,
12866 SetFastElement(object, index, value, language_mode, check_prototype),
12867 Object);
12868 JSObject::ValidateElements(object);
12869 return result;
12870 } 12773 }
12871 12774
12872 double double_value = value_is_smi
12873 ? static_cast<double>(Handle<Smi>::cast(value)->value())
12874 : Handle<HeapNumber>::cast(value)->value();
12875
12876 // If the array is growing, and it's not growth by a single element at the 12775 // If the array is growing, and it's not growth by a single element at the
12877 // end, make sure that the ElementsKind is HOLEY. 12776 // end, make sure that the ElementsKind is HOLEY.
12878 ElementsKind elements_kind = object->GetElementsKind(); 12777 ElementsKind elements_kind = object->GetElementsKind();
12879 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { 12778 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
12880 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); 12779 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12881 TransitionElementsKind(object, transitioned_kind); 12780 TransitionElementsKind(object, transitioned_kind);
12882 } 12781 }
12883 12782
12884 // Check whether there is extra space in the fixed array. 12783 // Check whether there is extra space in the fixed array.
12885 if (index < elms_length) { 12784 if (index < elms_length) {
12886 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); 12785 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
12887 elms->set(index, double_value); 12786 elms->set(index, value->Number());
12888 if (object->IsJSArray()) { 12787 if (object->IsJSArray()) {
12889 // Update the length of the array if needed. 12788 // Update the length of the array if needed.
12890 uint32_t array_length = 0; 12789 uint32_t array_length = 0;
12891 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength( 12790 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(
12892 &array_length)); 12791 &array_length));
12893 if (index >= array_length) { 12792 if (index >= array_length) {
12894 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1)); 12793 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12895 } 12794 }
12896 } 12795 }
12897 return value; 12796 return;
12898 } 12797 }
12899 12798
12900 // Allow gap in fast case. 12799 // Allow gap in fast case.
12901 if ((index - elms_length) < kMaxGap) { 12800 if ((index - elms_length) < kMaxGap) {
12902 // Try allocating extra space. 12801 // Try allocating extra space.
12903 int new_capacity = NewElementsCapacity(index+1); 12802 int new_capacity = NewElementsCapacity(index+1);
12904 if (!object->ShouldConvertToSlowElements(new_capacity)) { 12803 if (!object->ShouldConvertToSlowElements(new_capacity)) {
12905 DCHECK(static_cast<uint32_t>(new_capacity) > index); 12804 DCHECK(static_cast<uint32_t>(new_capacity) > index);
12906 SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1); 12805 SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
12907 FixedDoubleArray::cast(object->elements())->set(index, double_value); 12806 FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12908 JSObject::ValidateElements(object); 12807 JSObject::ValidateElements(object);
12909 return value; 12808 return;
12910 } 12809 }
12911 } 12810 }
12912 12811
12913 // Otherwise default to slow case. 12812 // Otherwise default to slow case.
12914 DCHECK(object->HasFastDoubleElements()); 12813 DCHECK(object->HasFastDoubleElements());
12915 DCHECK(object->map()->has_fast_double_elements()); 12814 DCHECK(object->map()->has_fast_double_elements());
12916 DCHECK(object->elements()->IsFixedDoubleArray() || 12815 DCHECK(object->elements()->IsFixedDoubleArray() ||
12917 object->elements()->length() == 0); 12816 object->elements()->length() == 0);
12918 12817
12919 NormalizeElements(object); 12818 NormalizeElements(object);
12920 DCHECK(object->HasDictionaryElements()); 12819 DCHECK(object->HasDictionaryElements());
12921 return SetElement(object, index, value, NONE, language_mode, check_prototype); 12820 SetDictionaryElement(object, index, value, NONE);
12922 } 12821 }
12923 12822
12924 12823
12824 // static
12925 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, 12825 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12926 uint32_t index, Handle<Object> value, 12826 uint32_t index, Handle<Object> value,
12927 PropertyAttributes attributes,
12928 LanguageMode language_mode) { 12827 LanguageMode language_mode) {
12929 if (object->IsJSProxy()) { 12828 Isolate* isolate = object->GetIsolate();
12930 return JSProxy::SetElementWithHandler(Handle<JSProxy>::cast(object), object, 12829 LookupIterator it(isolate, object, index);
12931 index, value, language_mode); 12830 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED);
12932 }
12933 return JSObject::SetElement(Handle<JSObject>::cast(object), index, value,
12934 attributes, language_mode);
12935 } 12831 }
12936 12832
12937 12833
12938 MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object, 12834 // static
12939 uint32_t index, 12835 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> receiver,
12940 Handle<Object> value, 12836 uint32_t index,
12941 PropertyAttributes attributes, 12837 Handle<Object> value,
12942 LanguageMode language_mode) { 12838 PropertyAttributes attributes) {
12943 DCHECK(!object->HasExternalArrayElements()); 12839 DCHECK(receiver->map()->is_extensible());
12944 return JSObject::SetElement(object, index, value, attributes, language_mode,
12945 false);
12946 }
12947 12840
12841 Isolate* isolate = receiver->GetIsolate();
12948 12842
12949 MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object, 12843 // TODO(verwaest): Use ElementAccessor.
12950 uint32_t index, Handle<Object> value, 12844 Handle<Object> old_length_handle;
12951 PropertyAttributes attributes, 12845 if (receiver->IsJSArray() && receiver->map()->is_observed()) {
12952 LanguageMode language_mode, 12846 old_length_handle = handle(JSArray::cast(*receiver)->length(), isolate);
12953 bool check_prototype,
12954 SetPropertyMode set_mode) {
12955 Isolate* isolate = object->GetIsolate();
12956
12957 if (object->HasExternalArrayElements() ||
12958 object->HasFixedTypedArrayElements()) {
12959 if (!value->IsNumber() && !value->IsUndefined()) {
12960 ASSIGN_RETURN_ON_EXCEPTION(
12961 isolate, value,
12962 Execution::ToNumber(isolate, value), Object);
12963 }
12964 } 12847 }
12965 12848
12966 // Check access rights if needed. 12849 if (attributes != NONE) {
12967 if (object->IsAccessCheckNeeded()) { 12850 Handle<SeededNumberDictionary> d = JSObject::NormalizeElements(receiver);
12968 if (!isolate->MayAccess(object)) { 12851 // TODO(verwaest): Move this into NormalizeElements.
12969 isolate->ReportFailedAccessCheck(object); 12852 d->set_requires_slow_elements();
12970 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12971 return value;
12972 }
12973 } 12853 }
12974 12854
12975 if (object->IsJSGlobalProxy()) { 12855 Handle<Object> result = value;
12976 PrototypeIterator iter(isolate, object); 12856
12977 if (iter.IsAtEnd()) return value; 12857 switch (receiver->GetElementsKind()) {
12978 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); 12858 case FAST_SMI_ELEMENTS:
12979 return SetElement( 12859 case FAST_ELEMENTS:
12980 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, 12860 case FAST_HOLEY_SMI_ELEMENTS:
12981 value, attributes, language_mode, check_prototype, set_mode); 12861 case FAST_HOLEY_ELEMENTS:
12862 SetFastElement(receiver, index, value);
12863 break;
12864 case FAST_DOUBLE_ELEMENTS:
12865 case FAST_HOLEY_DOUBLE_ELEMENTS:
12866 SetFastDoubleElement(receiver, index, value);
12867 break;
12868
12869 case DICTIONARY_ELEMENTS:
12870 SetDictionaryElement(receiver, index, value, attributes);
12871 break;
12872 case SLOPPY_ARGUMENTS_ELEMENTS:
12873 SetSloppyArgumentsElement(receiver, index, value, attributes);
12874 break;
12875
12876 // Elements cannot be added to typed arrays.
12877 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
12878 case EXTERNAL_##TYPE##_ELEMENTS: \
12879 case TYPE##_ELEMENTS:
12880
12881 TYPED_ARRAYS(TYPED_ARRAY_CASE)
12882
12883 #undef TYPED_ARRAY_CASE
12884 UNREACHABLE();
12885 break;
12982 } 12886 }
12983 12887
12984 // Don't allow element properties to be redefined for external arrays. 12888 if (!old_length_handle.is_null() &&
12985 if ((object->HasExternalArrayElements() || 12889 !old_length_handle->SameValue(
12986 object->HasFixedTypedArrayElements()) && 12890 Handle<JSArray>::cast(receiver)->length())) {
12987 set_mode == DEFINE_PROPERTY) { 12891 // |old_length_handle| is kept null above unless the receiver is observed.
12988 THROW_NEW_ERROR( 12892 DCHECK(receiver->map()->is_observed());
12989 isolate, NewTypeError(MessageTemplate::kRedefineExternalArray), Object); 12893 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
12990 } 12894 Handle<String> name = isolate->factory()->Uint32ToString(index);
12895 Handle<Object> new_length_handle(array->length(), isolate);
12896 uint32_t old_length = 0;
12897 uint32_t new_length = 0;
12898 CHECK(old_length_handle->ToArrayLength(&old_length));
12899 CHECK(new_length_handle->ToArrayLength(&new_length));
12991 12900
12992 // Normalize the elements to enable attributes on the property. 12901 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
12993 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
12994 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
12995 // Make sure that we never go back to fast case.
12996 dictionary->set_requires_slow_elements();
12997 }
12998
12999 if (!object->map()->is_observed()) {
13000 return object->HasIndexedInterceptor()
13001 ? SetElementWithInterceptor(object, index, value, attributes,
13002 language_mode, check_prototype,
13003 set_mode)
13004 : SetElementWithoutInterceptor(object, index, value, attributes,
13005 language_mode, check_prototype,
13006 set_mode);
13007 }
13008
13009 Maybe<PropertyAttributes> maybe =
13010 JSReceiver::GetOwnElementAttributes(object, index);
13011 if (!maybe.IsJust()) return MaybeHandle<Object>();
13012 PropertyAttributes old_attributes = maybe.FromJust();
13013
13014 Handle<Object> old_value = isolate->factory()->the_hole_value();
13015 Handle<Object> old_length_handle;
13016 Handle<Object> new_length_handle;
13017
13018 if (old_attributes != ABSENT) {
13019 if (GetOwnElementAccessorPair(object, index).is_null()) {
13020 old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
13021 }
13022 } else if (object->IsJSArray()) {
13023 // Store old array length in case adding an element grows the array.
13024 old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13025 isolate);
13026 }
13027
13028 // Check for lookup interceptor
13029 Handle<Object> result;
13030 ASSIGN_RETURN_ON_EXCEPTION(
13031 isolate, result,
13032 object->HasIndexedInterceptor()
13033 ? SetElementWithInterceptor(object, index, value, attributes,
13034 language_mode, check_prototype, set_mode)
13035 : SetElementWithoutInterceptor(object, index, value, attributes,
13036 language_mode, check_prototype,
13037 set_mode),
13038 Object);
13039
13040 Handle<String> name = isolate->factory()->Uint32ToString(index);
13041 maybe = GetOwnElementAttributes(object, index);
13042 if (!maybe.IsJust()) return MaybeHandle<Object>();
13043 PropertyAttributes new_attributes = maybe.FromJust();
13044
13045 if (old_attributes == ABSENT) {
13046 if (object->IsJSArray() &&
13047 !old_length_handle->SameValue(
13048 Handle<JSArray>::cast(object)->length())) {
13049 new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13050 isolate);
13051 uint32_t old_length = 0;
13052 uint32_t new_length = 0;
13053 CHECK(old_length_handle->ToArrayLength(&old_length));
13054 CHECK(new_length_handle->ToArrayLength(&new_length));
13055
13056 RETURN_ON_EXCEPTION(
13057 isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object);
13058 RETURN_ON_EXCEPTION(
13059 isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
13060 RETURN_ON_EXCEPTION(
13061 isolate, EnqueueChangeRecord(object, "update",
13062 isolate->factory()->length_string(),
13063 old_length_handle),
13064 Object);
13065 RETURN_ON_EXCEPTION(
13066 isolate, EndPerformSplice(Handle<JSArray>::cast(object)), Object);
13067 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
13068 RETURN_ON_EXCEPTION(
13069 isolate,
13070 EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length,
13071 deleted, new_length - old_length),
13072 Object);
13073 } else {
13074 RETURN_ON_EXCEPTION(
13075 isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
13076 }
13077 } else if (old_value->IsTheHole()) {
13078 RETURN_ON_EXCEPTION( 12902 RETURN_ON_EXCEPTION(
13079 isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value), 12903 isolate, JSObject::EnqueueChangeRecord(
12904 array, "add", name, isolate->factory()->the_hole_value()),
13080 Object); 12905 Object);
13081 } else { 12906 RETURN_ON_EXCEPTION(
13082 Handle<Object> new_value = 12907 isolate, JSObject::EnqueueChangeRecord(
13083 Object::GetElement(isolate, object, index).ToHandleChecked(); 12908 array, "update", isolate->factory()->length_string(),
13084 bool value_changed = !old_value->SameValue(*new_value); 12909 old_length_handle),
13085 if (old_attributes != new_attributes) { 12910 Object);
13086 if (!value_changed) old_value = isolate->factory()->the_hole_value(); 12911 RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
13087 RETURN_ON_EXCEPTION( 12912 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
13088 isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value), 12913 RETURN_ON_EXCEPTION(isolate, EnqueueSpliceRecord(array, old_length, deleted,
13089 Object); 12914 new_length - old_length),
13090 } else if (value_changed) { 12915 Object);
13091 RETURN_ON_EXCEPTION( 12916 } else if (receiver->map()->is_observed()) {
13092 isolate, EnqueueChangeRecord(object, "update", name, old_value), 12917 Handle<String> name = isolate->factory()->Uint32ToString(index);
13093 Object); 12918 RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord(
13094 } 12919 receiver, "add", name,
12920 isolate->factory()->the_hole_value()),
12921 Object);
13095 } 12922 }
13096 12923
13097 return result; 12924 return result;
13098 } 12925 }
13099 12926
13100 12927
13101 MaybeHandle<Object> JSObject::SetElementWithoutInterceptor(
13102 Handle<JSObject> object, uint32_t index, Handle<Object> value,
13103 PropertyAttributes attributes, LanguageMode language_mode,
13104 bool check_prototype, SetPropertyMode set_mode) {
13105 DCHECK(object->HasDictionaryElements() ||
13106 object->HasDictionaryArgumentsElements() ||
13107 (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
13108 Isolate* isolate = object->GetIsolate();
13109 if (FLAG_trace_external_array_abuse &&
13110 IsExternalArrayElementsKind(object->GetElementsKind())) {
13111 CheckArrayAbuse(object, "external elements write", index);
13112 }
13113 if (FLAG_trace_js_array_abuse &&
13114 !IsExternalArrayElementsKind(object->GetElementsKind())) {
13115 if (object->IsJSArray()) {
13116 CheckArrayAbuse(object, "elements write", index, true);
13117 }
13118 }
13119 if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
13120 Handle<JSArray>::cast(object), index)) {
13121 if (is_sloppy(language_mode)) {
13122 return value;
13123 } else {
13124 return JSArray::ReadOnlyLengthError(Handle<JSArray>::cast(object));
13125 }
13126 }
13127 switch (object->GetElementsKind()) {
13128 case FAST_SMI_ELEMENTS:
13129 case FAST_ELEMENTS:
13130 case FAST_HOLEY_SMI_ELEMENTS:
13131 case FAST_HOLEY_ELEMENTS:
13132 return SetFastElement(object, index, value, language_mode,
13133 check_prototype);
13134 case FAST_DOUBLE_ELEMENTS:
13135 case FAST_HOLEY_DOUBLE_ELEMENTS:
13136 return SetFastDoubleElement(object, index, value, language_mode,
13137 check_prototype);
13138
13139 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
13140 case EXTERNAL_##TYPE##_ELEMENTS: { \
13141 Handle<External##Type##Array> array( \
13142 External##Type##Array::cast(object->elements())); \
13143 return External##Type##Array::SetValue(object, array, index, value); \
13144 } \
13145 case TYPE##_ELEMENTS: { \
13146 Handle<Fixed##Type##Array> array( \
13147 Fixed##Type##Array::cast(object->elements())); \
13148 return Fixed##Type##Array::SetValue(object, array, index, value); \
13149 }
13150
13151 TYPED_ARRAYS(TYPED_ARRAY_CASE)
13152
13153 #undef TYPED_ARRAY_CASE
13154
13155 case DICTIONARY_ELEMENTS:
13156 return SetDictionaryElement(object, index, value, attributes,
13157 language_mode, check_prototype, set_mode);
13158 case SLOPPY_ARGUMENTS_ELEMENTS: {
13159 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
13160 uint32_t length = parameter_map->length();
13161 Handle<Object> probe = index < length - 2 ?
13162 Handle<Object>(parameter_map->get(index + 2), isolate) :
13163 Handle<Object>();
13164 if (!probe.is_null() && !probe->IsTheHole()) {
13165 Handle<Context> context(Context::cast(parameter_map->get(0)));
13166 int context_index = Handle<Smi>::cast(probe)->value();
13167 DCHECK(!context->get(context_index)->IsTheHole());
13168 context->set(context_index, *value);
13169 // Redefining attributes of an aliased element destroys fast aliasing.
13170 if (set_mode == SET_PROPERTY || attributes == NONE) return value;
13171 parameter_map->set_the_hole(index + 2);
13172 // For elements that are still writable we re-establish slow aliasing.
13173 if ((attributes & READ_ONLY) == 0) {
13174 value = Handle<Object>::cast(
13175 isolate->factory()->NewAliasedArgumentsEntry(context_index));
13176 }
13177 }
13178 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
13179 if (arguments->IsDictionary()) {
13180 return SetDictionaryElement(object, index, value, attributes,
13181 language_mode, check_prototype, set_mode);
13182 } else {
13183 return SetFastElement(object, index, value, language_mode,
13184 check_prototype);
13185 }
13186 }
13187 }
13188 // All possible cases have been handled above. Add a return to avoid the
13189 // complaints from the compiler.
13190 UNREACHABLE();
13191 return isolate->factory()->null_value();
13192 }
13193
13194
13195 const double AllocationSite::kPretenureRatio = 0.85; 12928 const double AllocationSite::kPretenureRatio = 0.85;
13196 12929
13197 12930
13198 void AllocationSite::ResetPretenureDecision() { 12931 void AllocationSite::ResetPretenureDecision() {
13199 set_pretenure_decision(kUndecided); 12932 set_pretenure_decision(kUndecided);
13200 set_memento_found_count(0); 12933 set_memento_found_count(0);
13201 set_memento_create_count(0); 12934 set_memento_create_count(0);
13202 } 12935 }
13203 12936
13204 12937
(...skipping 1767 matching lines...) Expand 10 before | Expand all | Expand 10 after
14972 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE) 14705 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
14973 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE 14706 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
14974 14707
14975 default: 14708 default:
14976 UNREACHABLE(); 14709 UNREACHABLE();
14977 return 0; 14710 return 0;
14978 } 14711 }
14979 } 14712 }
14980 14713
14981 14714
14715 Handle<Object> FixedArray::SetValue(Handle<JSObject> holder,
14716 Handle<FixedArray> array, uint32_t index,
14717 Handle<Object> value) {
14718 array->set(index, *value);
14719 return value;
14720 }
14721
14722
14723 Handle<Object> FixedDoubleArray::SetValue(Handle<JSObject> holder,
14724 Handle<FixedDoubleArray> array,
14725 uint32_t index,
14726 Handle<Object> value) {
14727 array->set(index, value->Number());
14728 return value;
14729 }
14730
14731
14982 Handle<Object> ExternalUint8ClampedArray::SetValue( 14732 Handle<Object> ExternalUint8ClampedArray::SetValue(
14983 Handle<JSObject> holder, Handle<ExternalUint8ClampedArray> array, 14733 Handle<JSObject> holder, Handle<ExternalUint8ClampedArray> array,
14984 uint32_t index, Handle<Object> value) { 14734 uint32_t index, Handle<Object> value) {
14985 uint8_t clamped_value = 0; 14735 uint8_t clamped_value = 0;
14986 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(holder); 14736 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(holder);
14987 if (!view->WasNeutered()) { 14737 if (!view->WasNeutered()) {
14988 if (index < static_cast<uint32_t>(array->length())) { 14738 if (index < static_cast<uint32_t>(array->length())) {
14989 if (value->IsSmi()) { 14739 if (value->IsSmi()) {
14990 int int_value = Handle<Smi>::cast(value)->value(); 14740 int int_value = Handle<Smi>::cast(value)->value();
14991 if (int_value < 0) { 14741 if (int_value < 0) {
(...skipping 1983 matching lines...) Expand 10 before | Expand all | Expand 10 after
16975 Handle<Object> new_value) { 16725 Handle<Object> new_value) {
16976 if (cell->value() != *new_value) { 16726 if (cell->value() != *new_value) {
16977 cell->set_value(*new_value); 16727 cell->set_value(*new_value);
16978 Isolate* isolate = cell->GetIsolate(); 16728 Isolate* isolate = cell->GetIsolate();
16979 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16729 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16980 isolate, DependentCode::kPropertyCellChangedGroup); 16730 isolate, DependentCode::kPropertyCellChangedGroup);
16981 } 16731 }
16982 } 16732 }
16983 } // namespace internal 16733 } // namespace internal
16984 } // namespace v8 16734 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698