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

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: Update reconfigure data property for sloppy arguments 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
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()) {
Igor Sheludko 2015/06/11 13:44:25 IsExecutableAccessorInfo()?
Toon Verwaest 2015/06/11 14:26:50 It's in a weird state since it's the only subclass
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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3123 JSObject::GetPropertyAttributesWithInterceptor(it); 3067 JSObject::GetPropertyAttributesWithInterceptor(it);
3124 if (!maybe_attributes.IsJust()) return MaybeHandle<Object>(); 3068 if (!maybe_attributes.IsJust()) return MaybeHandle<Object>();
3125 done = maybe_attributes.FromJust() != ABSENT; 3069 done = maybe_attributes.FromJust() != ABSENT;
3126 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) { 3070 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) {
3127 return WriteToReadOnlyProperty(it, value, language_mode); 3071 return WriteToReadOnlyProperty(it, value, language_mode);
3128 } 3072 }
3129 } 3073 }
3130 break; 3074 break;
3131 3075
3132 case LookupIterator::ACCESSOR: { 3076 case LookupIterator::ACCESSOR: {
3133 if (it->property_details().IsReadOnly()) { 3077 if (it->IsReadOnly()) {
3134 return WriteToReadOnlyProperty(it, value, language_mode); 3078 return WriteToReadOnlyProperty(it, value, language_mode);
3135 } 3079 }
3136 Handle<Object> accessors = it->GetAccessors(); 3080 Handle<Object> accessors = it->GetAccessors();
3137 if (accessors->IsAccessorInfo() && 3081 if (accessors->IsAccessorInfo() &&
3138 !it->HolderIsReceiverOrHiddenPrototype() && 3082 !it->HolderIsReceiverOrHiddenPrototype() &&
3139 AccessorInfo::cast(*accessors)->is_special_data_property()) { 3083 AccessorInfo::cast(*accessors)->is_special_data_property()) {
3140 done = true; 3084 done = true;
3141 break; 3085 break;
3142 } 3086 }
3143 return SetPropertyWithAccessor(it->GetReceiver(), it->GetName(), value, 3087 return SetPropertyWithAccessor(it, value, language_mode);
3144 it->GetHolder<JSObject>(), accessors,
3145 language_mode);
3146 } 3088 }
3147 case LookupIterator::INTEGER_INDEXED_EXOTIC: 3089 case LookupIterator::INTEGER_INDEXED_EXOTIC:
3148 done = true; 3090 done = true;
3149 break; 3091 break;
3150 3092
3151 case LookupIterator::DATA: 3093 case LookupIterator::DATA:
3152 if (it->property_details().IsReadOnly()) { 3094 if (it->IsReadOnly()) {
3153 return WriteToReadOnlyProperty(it, value, language_mode); 3095 return WriteToReadOnlyProperty(it, value, language_mode);
3154 } 3096 }
3155 if (it->HolderIsReceiverOrHiddenPrototype()) { 3097 if (it->HolderIsReceiverOrHiddenPrototype()) {
3156 return SetDataProperty(it, value); 3098 return SetDataProperty(it, value);
3157 } 3099 }
3158 done = true; 3100 done = true;
3159 break; 3101 break;
3160 3102
3161 case LookupIterator::TRANSITION: 3103 case LookupIterator::TRANSITION:
3162 done = true; 3104 done = true;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3195 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, 3137 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
3196 Handle<Object> value, 3138 Handle<Object> value,
3197 LanguageMode language_mode, 3139 LanguageMode language_mode,
3198 StoreFromKeyed store_mode) { 3140 StoreFromKeyed store_mode) {
3199 bool found = false; 3141 bool found = false;
3200 MaybeHandle<Object> result = 3142 MaybeHandle<Object> result =
3201 SetPropertyInternal(it, value, language_mode, store_mode, &found); 3143 SetPropertyInternal(it, value, language_mode, store_mode, &found);
3202 if (found) return result; 3144 if (found) return result;
3203 3145
3204 if (!it->GetReceiver()->IsJSReceiver()) { 3146 if (!it->GetReceiver()->IsJSReceiver()) {
3205 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), it->name(), 3147 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
3206 value, language_mode); 3148 it->GetName(), value, language_mode);
3207 } 3149 }
3208 3150
3209 LookupIterator own_lookup(it->GetReceiver(), it->name(), LookupIterator::OWN); 3151 LookupIterator::Configuration c = LookupIterator::OWN;
3152 LookupIterator own_lookup =
3153 it->IsElement()
3154 ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c)
3155 : LookupIterator(it->GetReceiver(), it->name(), c);
3210 3156
3211 switch (own_lookup.state()) { 3157 for (; own_lookup.IsFound(); own_lookup.Next()) {
3212 case LookupIterator::NOT_FOUND: 3158 switch (own_lookup.state()) {
3213 return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode, 3159 case LookupIterator::ACCESS_CHECK:
3214 store_mode); 3160 if (!it->isolate()->MayAccess(own_lookup.GetHolder<JSObject>())) {
3161 return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
3162 language_mode);
3163 }
3164 break;
3215 3165
3216 case LookupIterator::INTEGER_INDEXED_EXOTIC: 3166 case LookupIterator::INTEGER_INDEXED_EXOTIC:
3217 return result; 3167 return result;
3218 3168
3219 case LookupIterator::DATA: { 3169 case LookupIterator::DATA: {
3220 PropertyDetails details = own_lookup.property_details(); 3170 PropertyDetails details = own_lookup.property_details();
3221 if (details.IsConfigurable() || !details.IsReadOnly()) { 3171 if (details.IsConfigurable() || !details.IsReadOnly()) {
3222 return JSObject::SetOwnPropertyIgnoreAttributes( 3172 return JSObject::ReconfigureAsDataProperty(&own_lookup, value,
3223 Handle<JSObject>::cast(it->GetReceiver()), it->name(), value, 3173 details.attributes());
3224 details.attributes()); 3174 }
3225 } 3175 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 } 3176 }
3236 3177
3237 return RedefineNonconfigurableProperty(it->isolate(), it->name(), value, 3178 case LookupIterator::ACCESSOR: {
3238 language_mode); 3179 PropertyDetails details = own_lookup.property_details();
3239 } 3180 if (details.IsConfigurable()) {
3181 return JSObject::ReconfigureAsDataProperty(&own_lookup, value,
3182 details.attributes());
3183 }
3240 3184
3241 case LookupIterator::TRANSITION: 3185 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
3242 UNREACHABLE(); 3186 value, language_mode);
3243 break; 3187 }
3244 3188
3245 case LookupIterator::INTERCEPTOR: 3189 case LookupIterator::INTERCEPTOR:
3246 case LookupIterator::JSPROXY: 3190 case LookupIterator::JSPROXY: {
3247 case LookupIterator::ACCESS_CHECK: { 3191 bool found = false;
3248 bool found = false; 3192 MaybeHandle<Object> result = SetPropertyInternal(
3249 MaybeHandle<Object> result = SetPropertyInternal( 3193 &own_lookup, value, language_mode, store_mode, &found);
3250 &own_lookup, value, language_mode, store_mode, &found); 3194 if (found) return result;
Igor Sheludko 2015/06/11 13:44:25 Missing break; ?
Toon Verwaest 2015/06/11 14:26:50 Done.
3251 if (found) return result; 3195 }
3252 return SetDataProperty(&own_lookup, value); 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()) {
Igor Sheludko 2015/06/11 13:44:25 You dropped CheckArrayAbuse() calls. Was it done i
Toon Verwaest 2015/06/11 14:26:50 Done.
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
3373 return JSObject::AddDataElement(receiver, it->index(), value, attributes);
3374 } else {
3375 // Migrate to the most up-to-date map that will be able to store |value|
3376 // under it->name() with |attributes|.
3377 it->PrepareTransitionToDataProperty(value, attributes, store_mode);
3378 DCHECK_EQ(LookupIterator::TRANSITION, it->state());
3379 it->ApplyTransitionToDataProperty();
3380
3381 // TODO(verwaest): Encapsulate dictionary handling better.
3382 if (receiver->map()->is_dictionary_map()) {
3383 // TODO(verwaest): Probably should ensure this is done beforehand.
3384 it->InternalizeName();
3385 // TODO(dcarney): just populate TransitionPropertyCell here?
3386 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3387 } else {
3388 // Write the property value.
3389 it->WriteDataValue(value);
3390 }
3391
3392 // Send the change record if there are observers.
3393 if (receiver->map()->is_observed() &&
3394 !isolate->IsInternallyUsedPropertyName(it->name())) {
3395 RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord(
3396 receiver, "add", it->name(),
3397 it->factory()->the_hole_value()),
3398 Object);
3399 }
3385 } 3400 }
3386 3401
3387 return value; 3402 return value;
3388 } 3403 }
3389 3404
3390 3405
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) { 3406 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3437 // Only supports adding slack to owned descriptors. 3407 // Only supports adding slack to owned descriptors.
3438 DCHECK(map->owns_descriptors()); 3408 DCHECK(map->owns_descriptors());
3439 3409
3440 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 3410 Handle<DescriptorArray> descriptors(map->instance_descriptors());
3441 int old_size = map->NumberOfOwnDescriptors(); 3411 int old_size = map->NumberOfOwnDescriptors();
3442 if (slack <= descriptors->NumberOfSlackDescriptors()) return; 3412 if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3443 3413
3444 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( 3414 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3445 descriptors, old_size, slack); 3415 descriptors, old_size, slack);
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after
4137 DCHECK(maybe.IsJust()); 4107 DCHECK(maybe.IsJust());
4138 DCHECK(!it.IsFound()); 4108 DCHECK(!it.IsFound());
4139 DCHECK(object->map()->is_extensible() || 4109 DCHECK(object->map()->is_extensible() ||
4140 it.isolate()->IsInternallyUsedPropertyName(name)); 4110 it.isolate()->IsInternallyUsedPropertyName(name));
4141 #endif 4111 #endif
4142 AddDataProperty(&it, value, attributes, STRICT, 4112 AddDataProperty(&it, value, attributes, STRICT,
4143 CERTAINLY_NOT_STORE_FROM_KEYED).Check(); 4113 CERTAINLY_NOT_STORE_FROM_KEYED).Check();
4144 } 4114 }
4145 4115
4146 4116
4117 // static
4118 void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) {
4119 info->set_setter(*v8::FromCData(info->GetIsolate(), nullptr));
4120 }
4121
4122
4123 MaybeHandle<Object> JSObject::ReconfigureAsDataProperty(
4124 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes) {
4125 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
4126 bool is_observed = object->map()->is_observed() &&
4127 (it->IsElement() ||
4128 !it->isolate()->IsInternallyUsedPropertyName(it->name()));
4129
4130 switch (it->state()) {
4131 case LookupIterator::INTERCEPTOR:
4132 case LookupIterator::JSPROXY:
4133 case LookupIterator::NOT_FOUND:
4134 case LookupIterator::TRANSITION:
4135 case LookupIterator::ACCESS_CHECK:
4136 UNREACHABLE();
4137
4138 case LookupIterator::INTEGER_INDEXED_EXOTIC:
4139 return value;
4140
4141 case LookupIterator::ACCESSOR: {
4142 PropertyDetails details = it->property_details();
4143 // Ensure the context isn't changed after calling into accessors.
4144 AssertNoContextChange ncc(it->isolate());
4145
4146 Handle<Object> accessors = it->GetAccessors();
4147
4148 // Special handling for ExecutableAccessorInfo, which behaves like a
4149 // data property.
4150 if (accessors->IsExecutableAccessorInfo()) {
4151 Handle<Object> result;
4152 ASSIGN_RETURN_ON_EXCEPTION(
4153 it->isolate(), result,
4154 JSObject::SetPropertyWithAccessor(it, value, STRICT), Object);
4155 DCHECK(result->SameValue(*value));
4156
4157 if (details.attributes() == attributes) return value;
4158
4159 // Reconfigure the accessor if attributes mismatch.
4160 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4161 it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4162 new_data->set_property_attributes(attributes);
4163 // By clearing the setter we don't have to introduce a lookup to
4164 // the setter, simply make it unavailable to reflect the
4165 // attributes.
4166 if (attributes & READ_ONLY) {
4167 ExecutableAccessorInfo::ClearSetter(new_data);
4168 }
4169
4170 if (it->IsElement()) {
4171 SetElementCallback(object, it->index(), new_data, attributes);
4172 } else {
4173 SetPropertyCallback(object, it->name(), new_data, attributes);
4174 }
4175 if (is_observed) {
4176 RETURN_ON_EXCEPTION(
4177 it->isolate(),
4178 EnqueueChangeRecord(object, "reconfigure", it->GetName(),
4179 it->factory()->the_hole_value()),
4180 Object);
4181 }
4182 return value;
4183 }
4184
4185 it->ReconfigureDataProperty(value, attributes);
4186 it->WriteDataValue(value);
4187
4188 if (is_observed) {
4189 RETURN_ON_EXCEPTION(
4190 it->isolate(),
4191 EnqueueChangeRecord(object, "reconfigure", it->GetName(),
4192 it->factory()->the_hole_value()),
4193 Object);
4194 }
4195
4196 return value;
4197 }
4198
4199 case LookupIterator::DATA: {
4200 PropertyDetails details = it->property_details();
4201 Handle<Object> old_value = it->factory()->the_hole_value();
4202 // Regular property update if the attributes match.
4203 if (details.attributes() == attributes) {
4204 return SetDataProperty(it, value);
4205 }
4206
4207 // Special case: properties of typed arrays cannot be reconfigured to
4208 // non-writable nor to non-enumerable.
4209 if (it->IsElement() && (object->HasExternalArrayElements() ||
4210 object->HasFixedTypedArrayElements())) {
4211 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4212 value, STRICT);
4213 }
4214
4215 // Reconfigure the data property if the attributes mismatch.
4216 if (is_observed) old_value = it->GetDataValue();
4217
4218 it->ReconfigureDataProperty(value, attributes);
4219 it->WriteDataValue(value);
4220
4221 if (is_observed) {
4222 if (old_value->SameValue(*value)) {
4223 old_value = it->factory()->the_hole_value();
4224 }
4225 RETURN_ON_EXCEPTION(it->isolate(),
4226 EnqueueChangeRecord(object, "reconfigure",
4227 it->GetName(), old_value),
4228 Object);
4229 }
4230 }
4231 }
4232
4233 return value;
4234 }
4235
4236
4147 // Reconfigures a property to a data property with attributes, even if it is not 4237 // Reconfigures a property to a data property with attributes, even if it is not
4148 // reconfigurable. 4238 // reconfigurable.
4149 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( 4239 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4150 Handle<JSObject> object, 4240 Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
4151 Handle<Name> name, 4241 PropertyAttributes attributes) {
4152 Handle<Object> value,
4153 PropertyAttributes attributes,
4154 ExecutableAccessorInfoHandling handling) {
4155 DCHECK(!value->IsTheHole()); 4242 DCHECK(!value->IsTheHole());
4156 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 4243 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4157 bool is_observed = object->map()->is_observed() && 4244 if (it.state() == LookupIterator::ACCESS_CHECK) {
4158 !it.isolate()->IsInternallyUsedPropertyName(name); 4245 if (!it.isolate()->MayAccess(object)) {
4159 for (; it.IsFound(); it.Next()) { 4246 // TODO(verwaest): Check whether this makes sense.
4160 switch (it.state()) { 4247 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4161 case LookupIterator::INTEGER_INDEXED_EXOTIC: 4248 }
4162 return value; 4249 it.Next();
4250 }
4163 4251
4164 case LookupIterator::INTERCEPTOR: 4252 if (it.IsFound()) {
4165 case LookupIterator::JSPROXY: 4253 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 } 4254 }
4262 4255
4263 return AddDataProperty(&it, value, attributes, STRICT, 4256 return AddDataProperty(&it, value, attributes, STRICT,
4264 CERTAINLY_NOT_STORE_FROM_KEYED); 4257 CERTAINLY_NOT_STORE_FROM_KEYED);
4265 } 4258 }
4266 4259
4267 4260
4261 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
4262 Handle<JSObject> object, uint32_t index, Handle<Object> value,
4263 PropertyAttributes attributes) {
4264 DCHECK(!object->HasExternalArrayElements());
4265 Isolate* isolate = object->GetIsolate();
4266 LookupIterator it(isolate, object, index,
4267 LookupIterator::OWN_SKIP_INTERCEPTOR);
4268 if (it.state() == LookupIterator::ACCESS_CHECK) {
4269 if (!isolate->MayAccess(object)) {
4270 // TODO(verwaest): Check whether this makes sense.
4271 return SetPropertyWithFailedAccessCheck(&it, value, STRICT);
4272 }
4273 it.Next();
4274 }
4275
4276 if (it.IsFound()) {
4277 return ReconfigureAsDataProperty(&it, value, attributes);
4278 }
4279
4280 return AddDataProperty(&it, value, attributes, STRICT,
4281 MAY_BE_STORE_FROM_KEYED);
4282 }
4283
4284
4268 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( 4285 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4269 LookupIterator* it) { 4286 LookupIterator* it) {
4270 Isolate* isolate = it->isolate(); 4287 Isolate* isolate = it->isolate();
4271 // Make sure that the top context does not change when doing 4288 // Make sure that the top context does not change when doing
4272 // callbacks or interceptor calls. 4289 // callbacks or interceptor calls.
4273 AssertNoContextChange ncc(isolate); 4290 AssertNoContextChange ncc(isolate);
4274 HandleScope scope(isolate); 4291 HandleScope scope(isolate);
4275 4292
4276 Handle<JSObject> holder = it->GetHolder<JSObject>(); 4293 Handle<JSObject> holder = it->GetHolder<JSObject>();
4277 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); 4294 Handle<InterceptorInfo> interceptor(it->GetInterceptor());
(...skipping 2869 matching lines...) Expand 10 before | Expand all | Expand 10 after
7147 case ACCESSOR: 7164 case ACCESSOR:
7148 case ACCESSOR_CONSTANT: 7165 case ACCESSOR_CONSTANT:
7149 return false; 7166 return false;
7150 } 7167 }
7151 7168
7152 UNREACHABLE(); 7169 UNREACHABLE();
7153 return false; 7170 return false;
7154 } 7171 }
7155 7172
7156 7173
7174 // static
7175 Handle<Map> Map::PrepareForDataElement(Handle<Map> map, Handle<Object> value) {
7176 ElementsKind kind = map->elements_kind();
7177 bool holey = IsHoleyElementsKind(kind);
7178
7179 switch (kind) {
7180 case FAST_SMI_ELEMENTS:
7181 case FAST_HOLEY_SMI_ELEMENTS:
7182 if (value->IsSmi()) return map;
7183 kind = value->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS;
7184 break;
7185
7186 case FAST_DOUBLE_ELEMENTS:
7187 case FAST_HOLEY_DOUBLE_ELEMENTS:
7188 if (value->IsNumber()) return map;
7189 kind = FAST_ELEMENTS;
7190 break;
7191
7192 case FAST_ELEMENTS:
7193 case FAST_HOLEY_ELEMENTS:
7194 case DICTIONARY_ELEMENTS:
7195 case SLOPPY_ARGUMENTS_ELEMENTS:
7196 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
7197 case EXTERNAL_##TYPE##_ELEMENTS: \
7198 case TYPE##_ELEMENTS:
7199
7200 TYPED_ARRAYS(TYPED_ARRAY_CASE)
7201 #undef TYPED_ARRAY_CASE
7202 return map;
7203 }
7204
7205 if (holey) kind = GetHoleyElementsKind(kind);
7206 return Map::AsElementsKind(map, kind);
7207 }
7208
7209
7210 // static
7157 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, 7211 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
7158 Handle<Object> value) { 7212 Handle<Object> value) {
7159 // Dictionaries can store any property value. 7213 // Dictionaries can store any property value.
7160 if (map->is_dictionary_map()) return map; 7214 if (map->is_dictionary_map()) return map;
7161 7215
7162 // Migrate to the newest map before storing the property. 7216 // Migrate to the newest map before storing the property.
7163 map = Update(map); 7217 map = Update(map);
7164 7218
7165 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 7219 Handle<DescriptorArray> descriptors(map->instance_descriptors());
7166 7220
(...skipping 4721 matching lines...) Expand 10 before | Expand all | Expand 10 after
11888 if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) { 11942 if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
11889 value = Handle<Object>::cast(isolate->factory()->the_hole_value()); 11943 value = Handle<Object>::cast(isolate->factory()->the_hole_value());
11890 } else { 11944 } else {
11891 value = Object::GetElement(isolate, object, index).ToHandleChecked(); 11945 value = Object::GetElement(isolate, object, index).ToHandleChecked();
11892 } 11946 }
11893 old_values->Add(value); 11947 old_values->Add(value);
11894 indices->Add(index); 11948 indices->Add(index);
11895 return true; 11949 return true;
11896 } 11950 }
11897 11951
11898 MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
11899 Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
11900 uint32_t add_count) {
11901 Isolate* isolate = object->GetIsolate();
11902 HandleScope scope(isolate);
11903 Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
11904 Handle<Object> add_count_object =
11905 isolate->factory()->NewNumberFromUint(add_count);
11906
11907 Handle<Object> args[] =
11908 { object, index_object, deleted, add_count_object };
11909
11910 return Execution::Call(
11911 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
11912 isolate->factory()->undefined_value(), arraysize(args), args);
11913 }
11914
11915
11916 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
11917 Handle<JSArray> object) {
11918 Isolate* isolate = object->GetIsolate();
11919 HandleScope scope(isolate);
11920 Handle<Object> args[] = { object };
11921
11922 return Execution::Call(
11923 isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
11924 isolate->factory()->undefined_value(), arraysize(args), args);
11925 }
11926
11927
11928 MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
11929 Handle<JSArray> object) {
11930 Isolate* isolate = object->GetIsolate();
11931 HandleScope scope(isolate);
11932 Handle<Object> args[] = { object };
11933
11934 return Execution::Call(
11935 isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
11936 isolate->factory()->undefined_value(), arraysize(args), args);
11937 }
11938
11939
11940 MaybeHandle<Object> JSArray::SetElementsLength( 11952 MaybeHandle<Object> JSArray::SetElementsLength(
11941 Handle<JSArray> array, 11953 Handle<JSArray> array,
11942 Handle<Object> new_length_handle) { 11954 Handle<Object> new_length_handle) {
11943 if (array->HasFastElements() && 11955 if (array->HasFastElements() &&
11944 SetElementsLengthWouldNormalize(array->GetHeap(), new_length_handle)) { 11956 SetElementsLengthWouldNormalize(array->GetHeap(), new_length_handle)) {
11945 NormalizeElements(array); 11957 NormalizeElements(array);
11946 } 11958 }
11947 11959
11948 // We should never end in here with a pixel or external array. 11960 // We should never end in here with a pixel or external array.
11949 DCHECK(array->AllowsSetElementsLength()); 11961 DCHECK(array->AllowsSetElementsLength());
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
12014 12026
12015 uint32_t index = Min(old_length, new_length); 12027 uint32_t index = Min(old_length, new_length);
12016 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; 12028 uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
12017 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; 12029 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
12018 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); 12030 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12019 if (delete_count > 0) { 12031 if (delete_count > 0) {
12020 for (int i = indices.length() - 1; i >= 0; i--) { 12032 for (int i = indices.length() - 1; i >= 0; i--) {
12021 // Skip deletions where the property was an accessor, leaving holes 12033 // Skip deletions where the property was an accessor, leaving holes
12022 // in the array of old values. 12034 // in the array of old values.
12023 if (old_values[i]->IsTheHole()) continue; 12035 if (old_values[i]->IsTheHole()) continue;
12024 JSObject::SetOwnElement(deleted, indices[i] - index, old_values[i], 12036 JSObject::AddDataElement(deleted, indices[i] - index, old_values[i], NONE)
12025 SLOPPY).Assert(); 12037 .Assert();
12026 } 12038 }
12027 12039
12028 RETURN_ON_EXCEPTION( 12040 SetProperty(deleted, isolate->factory()->length_string(),
12029 isolate, 12041 isolate->factory()->NewNumberFromUint(delete_count),
12030 SetProperty(deleted, isolate->factory()->length_string(), 12042 STRICT).Assert();
12031 isolate->factory()->NewNumberFromUint(delete_count),
12032 STRICT),
12033 Object);
12034 } 12043 }
12035 12044
12036 RETURN_ON_EXCEPTION( 12045 RETURN_ON_EXCEPTION(
12037 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object); 12046 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
12038 12047
12039 return hresult; 12048 return hresult;
12040 } 12049 }
12041 12050
12042 12051
12043 // static 12052 // static
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
12448 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); 12457 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
12449 } 12458 }
12450 12459
12451 // Check for lookup interceptor. 12460 // Check for lookup interceptor.
12452 if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>(); 12461 if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>();
12453 12462
12454 return object->GetElementsAccessor()->GetAccessorPair(object, index); 12463 return object->GetElementsAccessor()->GetAccessorPair(object, index);
12455 } 12464 }
12456 12465
12457 12466
12458 MaybeHandle<Object> JSObject::SetElementWithInterceptor(
12459 Handle<JSObject> object, uint32_t index, Handle<Object> value,
12460 PropertyAttributes attributes, LanguageMode language_mode,
12461 bool check_prototype, SetPropertyMode set_mode) {
12462 Isolate* isolate = object->GetIsolate();
12463
12464 // Make sure that the top context does not change when doing
12465 // callbacks or interceptor calls.
12466 AssertNoContextChange ncc(isolate);
12467
12468 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
12469 if (!interceptor->setter()->IsUndefined()) {
12470 v8::IndexedPropertySetterCallback setter =
12471 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
12472 LOG(isolate,
12473 ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
12474 PropertyCallbackArguments args(isolate, interceptor->data(), *object,
12475 *object);
12476 v8::Handle<v8::Value> result =
12477 args.Call(setter, index, v8::Utils::ToLocal(value));
12478 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12479 if (!result.IsEmpty()) return value;
12480 }
12481
12482 return SetElementWithoutInterceptor(object, index, value, attributes,
12483 language_mode, check_prototype, set_mode);
12484 }
12485
12486
12487 MaybeHandle<Object> JSObject::SetElementWithCallback(
12488 Handle<Object> object, Handle<Object> structure, uint32_t index,
12489 Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) {
12490 Isolate* isolate = holder->GetIsolate();
12491
12492 // We should never get here to initialize a const with the hole
12493 // value since a const declaration would conflict with the setter.
12494 DCHECK(!value->IsTheHole());
12495 DCHECK(!structure->IsForeign());
12496 if (structure->IsExecutableAccessorInfo()) {
12497 // api style callbacks
12498 Handle<ExecutableAccessorInfo> data =
12499 Handle<ExecutableAccessorInfo>::cast(structure);
12500 Object* call_obj = data->setter();
12501 v8::AccessorNameSetterCallback call_fun =
12502 v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
12503 if (call_fun == NULL) return value;
12504 Handle<String> key(isolate->factory()->Uint32ToString(index));
12505 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *key));
12506 PropertyCallbackArguments
12507 args(isolate, data->data(), *object, *holder);
12508 args.Call(call_fun,
12509 v8::Utils::ToLocal(key),
12510 v8::Utils::ToLocal(value));
12511 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12512 return value;
12513 }
12514
12515 if (structure->IsAccessorPair()) {
12516 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
12517 if (setter->IsSpecFunction()) {
12518 // TODO(rossberg): nicer would be to cast to some JSCallable here...
12519 return SetPropertyWithDefinedSetter(
12520 object, Handle<JSReceiver>::cast(setter), value);
12521 } else {
12522 if (is_sloppy(language_mode)) return value;
12523 Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
12524 THROW_NEW_ERROR(
12525 isolate,
12526 NewTypeError(MessageTemplate::kNoSetterInCallback, key, holder),
12527 Object);
12528 }
12529 }
12530
12531 UNREACHABLE();
12532 return MaybeHandle<Object>();
12533 }
12534
12535
12536 bool JSObject::HasFastArgumentsElements() { 12467 bool JSObject::HasFastArgumentsElements() {
12537 Heap* heap = GetHeap(); 12468 Heap* heap = GetHeap();
12538 if (!elements()->IsFixedArray()) return false; 12469 if (!elements()->IsFixedArray()) return false;
12539 FixedArray* elements = FixedArray::cast(this->elements()); 12470 FixedArray* elements = FixedArray::cast(this->elements());
12540 if (elements->map() != heap->sloppy_arguments_elements_map()) { 12471 if (elements->map() != heap->sloppy_arguments_elements_map()) {
12541 return false; 12472 return false;
12542 } 12473 }
12543 FixedArray* arguments = FixedArray::cast(elements->get(1)); 12474 FixedArray* arguments = FixedArray::cast(elements->get(1));
12544 return !arguments->IsDictionary(); 12475 return !arguments->IsDictionary();
12545 } 12476 }
12546 12477
12547 12478
12548 bool JSObject::HasDictionaryArgumentsElements() { 12479 bool JSObject::HasDictionaryArgumentsElements() {
12549 Heap* heap = GetHeap(); 12480 Heap* heap = GetHeap();
12550 if (!elements()->IsFixedArray()) return false; 12481 if (!elements()->IsFixedArray()) return false;
12551 FixedArray* elements = FixedArray::cast(this->elements()); 12482 FixedArray* elements = FixedArray::cast(this->elements());
12552 if (elements->map() != heap->sloppy_arguments_elements_map()) { 12483 if (elements->map() != heap->sloppy_arguments_elements_map()) {
12553 return false; 12484 return false;
12554 } 12485 }
12555 FixedArray* arguments = FixedArray::cast(elements->get(1)); 12486 FixedArray* arguments = FixedArray::cast(elements->get(1));
12556 return arguments->IsDictionary(); 12487 return arguments->IsDictionary();
12557 } 12488 }
12558 12489
12559 12490
12560 // Adding n elements in fast case is O(n*n). 12491 void JSObject::SetFastElement(Handle<JSObject> object, uint32_t index,
12561 // Note: revisit design to have dual undefined values to capture absent 12492 Handle<Object> value) {
12562 // elements.
12563 MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
12564 uint32_t index,
12565 Handle<Object> value,
12566 LanguageMode language_mode,
12567 bool check_prototype) {
12568 DCHECK(object->HasFastSmiOrObjectElements() || 12493 DCHECK(object->HasFastSmiOrObjectElements() ||
12569 object->HasFastArgumentsElements()); 12494 object->HasFastArgumentsElements());
12570 12495
12571 Isolate* isolate = object->GetIsolate(); 12496 Isolate* isolate = object->GetIsolate();
12572 12497
12573 // Array optimizations rely on the prototype lookups of Array objects always 12498 // Array optimizations rely on the prototype lookups of Array objects always
12574 // returning undefined. If there is a store to the initial prototype object, 12499 // returning undefined. If there is a store to the initial prototype object,
12575 // make sure all of these optimizations are invalidated. 12500 // make sure all of these optimizations are invalidated.
12576 isolate->UpdateArrayProtectorOnSetElement(object); 12501 isolate->UpdateArrayProtectorOnSetElement(object);
12577 12502
12578 Handle<FixedArray> backing_store(FixedArray::cast(object->elements())); 12503 Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12579 if (backing_store->map() == 12504 if (object->HasSloppyArgumentsElements()) {
12580 isolate->heap()->sloppy_arguments_elements_map()) {
12581 backing_store = handle(FixedArray::cast(backing_store->get(1))); 12505 backing_store = handle(FixedArray::cast(backing_store->get(1)));
12582 } else { 12506 } else {
12583 backing_store = EnsureWritableFastElements(object); 12507 backing_store = EnsureWritableFastElements(object);
12584 } 12508 }
12585 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); 12509 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12586 12510
12587 if (check_prototype &&
12588 (index >= capacity || backing_store->get(index)->IsTheHole())) {
12589 bool found;
12590 MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12591 object, index, value, &found, language_mode);
12592 if (found) return result;
12593 }
12594
12595 uint32_t new_capacity = capacity; 12511 uint32_t new_capacity = capacity;
12596 // Check if the length property of this object needs to be updated. 12512 // Check if the length property of this object needs to be updated.
12597 uint32_t array_length = 0; 12513 uint32_t array_length = 0;
12598 bool must_update_array_length = false; 12514 bool must_update_array_length = false;
12599 bool introduces_holes = true; 12515 bool introduces_holes = true;
12600 if (object->IsJSArray()) { 12516 if (object->IsJSArray()) {
12601 CHECK( 12517 CHECK(
12602 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length)); 12518 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length));
12603 introduces_holes = index > array_length; 12519 introduces_holes = index > array_length;
12604 if (index >= array_length) { 12520 if (index >= array_length) {
(...skipping 20 matching lines...) Expand all
12625 bool convert_to_slow = true; 12541 bool convert_to_slow = true;
12626 if ((index - capacity) < kMaxGap) { 12542 if ((index - capacity) < kMaxGap) {
12627 new_capacity = NewElementsCapacity(index + 1); 12543 new_capacity = NewElementsCapacity(index + 1);
12628 DCHECK(new_capacity > index); 12544 DCHECK(new_capacity > index);
12629 if (!object->ShouldConvertToSlowElements(new_capacity)) { 12545 if (!object->ShouldConvertToSlowElements(new_capacity)) {
12630 convert_to_slow = false; 12546 convert_to_slow = false;
12631 } 12547 }
12632 } 12548 }
12633 if (convert_to_slow) { 12549 if (convert_to_slow) {
12634 NormalizeElements(object); 12550 NormalizeElements(object);
12635 return SetDictionaryElement(object, index, value, NONE, language_mode, 12551 SetDictionaryElement(object, index, value, NONE);
12636 check_prototype); 12552 return;
12637 } 12553 }
12638 } 12554 }
12639 // Convert to fast double elements if appropriate. 12555 // Convert to fast double elements if appropriate.
12640 if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { 12556 if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12641 // Consider fixing the boilerplate as well if we have one. 12557 // Consider fixing the boilerplate as well if we have one.
12642 ElementsKind to_kind = IsHoleyElementsKind(elements_kind) 12558 ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
12643 ? FAST_HOLEY_DOUBLE_ELEMENTS 12559 ? FAST_HOLEY_DOUBLE_ELEMENTS
12644 : FAST_DOUBLE_ELEMENTS; 12560 : FAST_DOUBLE_ELEMENTS;
12645 12561
12646 UpdateAllocationSite(object, to_kind); 12562 UpdateAllocationSite(object, to_kind);
12647 12563
12648 SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length); 12564 SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12649 FixedDoubleArray::cast(object->elements())->set(index, value->Number()); 12565 FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12650 JSObject::ValidateElements(object); 12566 JSObject::ValidateElements(object);
12651 return value; 12567 return;
12652 } 12568 }
12653 // Change elements kind from Smi-only to generic FAST if necessary. 12569 // Change elements kind from Smi-only to generic FAST if necessary.
12654 if (object->HasFastSmiElements() && !value->IsSmi()) { 12570 if (object->HasFastSmiElements() && !value->IsSmi()) {
12655 ElementsKind kind = object->HasFastHoleyElements() 12571 ElementsKind kind = object->HasFastHoleyElements()
12656 ? FAST_HOLEY_ELEMENTS 12572 ? FAST_HOLEY_ELEMENTS
12657 : FAST_ELEMENTS; 12573 : FAST_ELEMENTS;
12658 12574
12659 UpdateAllocationSite(object, kind); 12575 UpdateAllocationSite(object, kind);
12660 Handle<Map> new_map = GetElementsTransitionMap(object, kind); 12576 Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12661 JSObject::MigrateToMap(object, new_map); 12577 JSObject::MigrateToMap(object, new_map);
12662 DCHECK(IsFastObjectElementsKind(object->GetElementsKind())); 12578 DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12663 } 12579 }
12664 // Increase backing store capacity if that's been decided previously. 12580 // Increase backing store capacity if that's been decided previously.
12665 if (new_capacity != capacity) { 12581 if (new_capacity != capacity) {
12666 SetFastElementsCapacitySmiMode smi_mode = 12582 SetFastElementsCapacitySmiMode smi_mode =
12667 value->IsSmi() && object->HasFastSmiElements() 12583 value->IsSmi() && object->HasFastSmiElements()
12668 ? kAllowSmiElements 12584 ? kAllowSmiElements
12669 : kDontAllowSmiElements; 12585 : kDontAllowSmiElements;
12670 Handle<FixedArray> new_elements = 12586 Handle<FixedArray> new_elements =
12671 SetFastElementsCapacityAndLength(object, new_capacity, array_length, 12587 SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12672 smi_mode); 12588 smi_mode);
12673 new_elements->set(index, *value); 12589 new_elements->set(index, *value);
12674 JSObject::ValidateElements(object); 12590 JSObject::ValidateElements(object);
12675 return value; 12591 return;
12676 } 12592 }
12677 12593
12678 // Finally, set the new element and length. 12594 // Finally, set the new element and length.
12679 DCHECK(object->elements()->IsFixedArray()); 12595 DCHECK(object->elements()->IsFixedArray());
12680 backing_store->set(index, *value); 12596 backing_store->set(index, *value);
12681 if (must_update_array_length) { 12597 if (must_update_array_length) {
12682 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); 12598 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12683 } 12599 }
12684 return value;
12685 } 12600 }
12686 12601
12687 12602
12688 MaybeHandle<Object> JSObject::SetDictionaryElement( 12603 void JSObject::SetSloppyArgumentsElements(Handle<JSObject> object,
12689 Handle<JSObject> object, uint32_t index, Handle<Object> value, 12604 uint32_t index, Handle<Object> value,
12690 PropertyAttributes attributes, LanguageMode language_mode, 12605 PropertyAttributes attributes) {
12691 bool check_prototype, SetPropertyMode set_mode) { 12606 // TODO(verwaest): Handle with the elements accessor.
12692 DCHECK(object->HasDictionaryElements() || 12607 Isolate* isolate = object->GetIsolate();
12693 object->HasDictionaryArgumentsElements()); 12608
12609 DCHECK(object->HasSloppyArgumentsElements());
12610
12611 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
12612 uint32_t length = parameter_map->length();
12613 Handle<Object> probe =
12614 index < length - 2
12615 ? Handle<Object>(parameter_map->get(index + 2), isolate)
12616 : Handle<Object>();
12617 if (!probe.is_null() && !probe->IsTheHole()) {
12618 Handle<Context> context(Context::cast(parameter_map->get(0)));
12619 int context_index = Handle<Smi>::cast(probe)->value();
12620 DCHECK(!context->get(context_index)->IsTheHole());
12621 context->set(context_index, *value);
12622
12623 if (attributes == NONE) return;
12624
12625 // Redefining attributes of an aliased element destroys fast aliasing.
12626 parameter_map->set_the_hole(index + 2);
12627 // For elements that are still writable we re-establish slow aliasing.
12628 if ((attributes & READ_ONLY) == 0) {
12629 value = Handle<Object>::cast(
12630 isolate->factory()->NewAliasedArgumentsEntry(context_index));
12631 }
12632 }
12633
12634 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
12635 if (arguments->IsDictionary()) {
12636 SetDictionaryElement(object, index, value, attributes);
12637 } else {
12638 SetFastElement(object, index, value);
12639 }
12640 }
12641
12642
12643 void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index,
12644 Handle<Object> value,
12645 PropertyAttributes attributes) {
12646 // TODO(verwaest): Handle with the elements accessor.
12694 Isolate* isolate = object->GetIsolate(); 12647 Isolate* isolate = object->GetIsolate();
12695 12648
12696 // Insert element in the dictionary. 12649 // Insert element in the dictionary.
12697 Handle<FixedArray> elements(FixedArray::cast(object->elements())); 12650 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12698 bool is_arguments = 12651 bool is_arguments =
12699 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); 12652 (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12653
12654 DCHECK(object->HasDictionaryElements() ||
12655 object->HasDictionaryArgumentsElements());
12656
12700 Handle<SeededNumberDictionary> dictionary(is_arguments 12657 Handle<SeededNumberDictionary> dictionary(is_arguments
12701 ? SeededNumberDictionary::cast(elements->get(1)) 12658 ? SeededNumberDictionary::cast(elements->get(1))
12702 : SeededNumberDictionary::cast(*elements)); 12659 : SeededNumberDictionary::cast(*elements));
12703 12660
12704 int entry = dictionary->FindEntry(index); 12661 int entry = dictionary->FindEntry(index);
12705 if (entry != SeededNumberDictionary::kNotFound) { 12662 if (entry != SeededNumberDictionary::kNotFound) {
12706 Handle<Object> element(dictionary->ValueAt(entry), isolate); 12663 Handle<Object> element(dictionary->ValueAt(entry), isolate);
12707 PropertyDetails details = dictionary->DetailsAt(entry); 12664 PropertyDetails details = dictionary->DetailsAt(entry);
12708 if (details.type() == ACCESSOR_CONSTANT && set_mode == SET_PROPERTY) { 12665 DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
12709 return SetElementWithCallback(object, element, index, value, object, 12666 element->IsTheHole());
12710 language_mode); 12667 dictionary->UpdateMaxNumberKey(index);
12711 } else if (set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
12712 details.kind() == kAccessor) {
12713 return RedefineNonconfigurableProperty(
12714 isolate, isolate->factory()->NewNumberFromUint(index),
12715 isolate->factory()->undefined_value(), language_mode);
12716 12668
12717 } else if ((set_mode == DEFINE_PROPERTY && !details.IsConfigurable() && 12669 details = PropertyDetails(attributes, DATA, details.dictionary_index(),
12718 details.IsReadOnly()) || 12670 PropertyCellType::kNoCell);
12719 (set_mode == SET_PROPERTY && details.IsReadOnly() && 12671 dictionary->DetailsAtPut(entry, details);
12720 !element->IsTheHole())) {
12721 // If a value has not been initialized we allow writing to it even if it
12722 // is read-only (a declared const that has not been initialized).
12723 return WriteToReadOnlyProperty(
12724 isolate, object, isolate->factory()->NewNumberFromUint(index),
12725 isolate->factory()->undefined_value(), language_mode);
12726 } else {
12727 DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
12728 element->IsTheHole());
12729 dictionary->UpdateMaxNumberKey(index);
12730 if (set_mode == DEFINE_PROPERTY) {
12731 details = PropertyDetails(attributes, DATA, details.dictionary_index(),
12732 PropertyCellType::kNoCell);
12733 dictionary->DetailsAtPut(entry, details);
12734 }
12735 12672
12736 // Elements of the arguments object in slow mode might be slow aliases. 12673 // Elements of the arguments object in slow mode might be slow aliases.
12737 if (is_arguments && element->IsAliasedArgumentsEntry()) { 12674 if (is_arguments && element->IsAliasedArgumentsEntry()) {
12738 Handle<AliasedArgumentsEntry> entry = 12675 Handle<AliasedArgumentsEntry> entry =
12739 Handle<AliasedArgumentsEntry>::cast(element); 12676 Handle<AliasedArgumentsEntry>::cast(element);
12740 Handle<Context> context(Context::cast(elements->get(0))); 12677 Handle<Context> context(Context::cast(elements->get(0)));
12741 int context_index = entry->aliased_context_slot(); 12678 int context_index = entry->aliased_context_slot();
12742 DCHECK(!context->get(context_index)->IsTheHole()); 12679 DCHECK(!context->get(context_index)->IsTheHole());
12743 context->set(context_index, *value); 12680 context->set(context_index, *value);
12744 // For elements that are still writable we keep slow aliasing. 12681 // For elements that are still writable we keep slow aliasing.
12745 if (!details.IsReadOnly()) value = element; 12682 if (!details.IsReadOnly()) value = element;
12746 }
12747 dictionary->ValueAtPut(entry, *value);
12748 } 12683 }
12684 dictionary->ValueAtPut(entry, *value);
12749 } else { 12685 } else {
12750 // Index not already used. Look for an accessor in the prototype chain. 12686 DCHECK(object->map()->is_extensible());
12751 // Can cause GC!
12752 if (check_prototype) {
12753 bool found;
12754 MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12755 object, index, value, &found, language_mode);
12756 if (found) return result;
12757 }
12758
12759 // When we set the is_extensible flag to false we always force the
12760 // element into dictionary mode (and force them to stay there).
12761 if (!object->map()->is_extensible()) {
12762 if (is_sloppy(language_mode)) {
12763 return isolate->factory()->undefined_value();
12764 } else {
12765 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12766 Handle<String> name = isolate->factory()->NumberToString(number);
12767 THROW_NEW_ERROR(
12768 isolate, NewTypeError(MessageTemplate::kObjectNotExtensible, name),
12769 Object);
12770 }
12771 }
12772
12773 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); 12687 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
12774 Handle<SeededNumberDictionary> new_dictionary = 12688 Handle<SeededNumberDictionary> new_dictionary =
12775 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, 12689 SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
12776 details); 12690 details);
12777 if (*dictionary != *new_dictionary) { 12691 if (*dictionary != *new_dictionary) {
12778 if (is_arguments) { 12692 if (is_arguments) {
12779 elements->set(1, *new_dictionary); 12693 elements->set(1, *new_dictionary);
12780 } else { 12694 } else {
12781 object->set_elements(*new_dictionary); 12695 object->set_elements(*new_dictionary);
12782 } 12696 }
(...skipping 30 matching lines...) Expand all
12813 } 12727 }
12814 JSObject::ValidateElements(object); 12728 JSObject::ValidateElements(object);
12815 #ifdef DEBUG 12729 #ifdef DEBUG
12816 if (FLAG_trace_normalization) { 12730 if (FLAG_trace_normalization) {
12817 OFStream os(stdout); 12731 OFStream os(stdout);
12818 os << "Object elements are fast case again:\n"; 12732 os << "Object elements are fast case again:\n";
12819 object->Print(os); 12733 object->Print(os);
12820 } 12734 }
12821 #endif 12735 #endif
12822 } 12736 }
12823 return value;
12824 } 12737 }
12825 12738
12826 MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object, 12739 void JSObject::SetFastDoubleElement(Handle<JSObject> object, uint32_t index,
12827 uint32_t index, 12740 Handle<Object> value) {
12828 Handle<Object> value,
12829 LanguageMode language_mode,
12830 bool check_prototype) {
12831 DCHECK(object->HasFastDoubleElements()); 12741 DCHECK(object->HasFastDoubleElements());
12832 12742
12833 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); 12743 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12834 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); 12744 uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
12745 uint32_t length = elms_length;
12835 12746
12836 // If storing to an element that isn't in the array, pass the store request
12837 // up the prototype chain before storing in the receiver's elements.
12838 if (check_prototype &&
12839 (index >= elms_length ||
12840 Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
12841 bool found;
12842 MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12843 object, index, value, &found, language_mode);
12844 if (found) return result;
12845 }
12846
12847 // If the value object is not a heap number, switch to fast elements and try
12848 // again.
12849 bool value_is_smi = value->IsSmi();
12850 bool introduces_holes = true; 12747 bool introduces_holes = true;
12851 uint32_t length = elms_length;
12852 if (object->IsJSArray()) { 12748 if (object->IsJSArray()) {
12749 // In case of JSArray, the length does not equal the capacity.
12853 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length)); 12750 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length));
12854 introduces_holes = index > length; 12751 introduces_holes = index > length;
12855 } else { 12752 } else {
12856 introduces_holes = index >= elms_length; 12753 introduces_holes = index >= elms_length;
12857 } 12754 }
12858 12755
12756 // If the value object is not a heap number, switch to fast elements and try
12757 // again.
12859 if (!value->IsNumber()) { 12758 if (!value->IsNumber()) {
12860 SetFastElementsCapacityAndLength(object, elms_length, length, 12759 SetFastElementsCapacityAndLength(object, elms_length, length,
12861 kDontAllowSmiElements); 12760 kDontAllowSmiElements);
12862 Handle<Object> result; 12761 SetFastElement(object, index, value);
12863 ASSIGN_RETURN_ON_EXCEPTION( 12762 return;
12864 object->GetIsolate(), result,
12865 SetFastElement(object, index, value, language_mode, check_prototype),
12866 Object);
12867 JSObject::ValidateElements(object);
12868 return result;
12869 } 12763 }
12870 12764
12871 double double_value = value_is_smi
12872 ? static_cast<double>(Handle<Smi>::cast(value)->value())
12873 : Handle<HeapNumber>::cast(value)->value();
12874
12875 // If the array is growing, and it's not growth by a single element at the 12765 // If the array is growing, and it's not growth by a single element at the
12876 // end, make sure that the ElementsKind is HOLEY. 12766 // end, make sure that the ElementsKind is HOLEY.
12877 ElementsKind elements_kind = object->GetElementsKind(); 12767 ElementsKind elements_kind = object->GetElementsKind();
12878 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { 12768 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
12879 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); 12769 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12880 TransitionElementsKind(object, transitioned_kind); 12770 TransitionElementsKind(object, transitioned_kind);
12881 } 12771 }
12882 12772
12883 // Check whether there is extra space in the fixed array. 12773 // Check whether there is extra space in the fixed array.
12884 if (index < elms_length) { 12774 if (index < elms_length) {
12885 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); 12775 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
12886 elms->set(index, double_value); 12776 elms->set(index, value->Number());
12887 if (object->IsJSArray()) { 12777 if (object->IsJSArray()) {
12888 // Update the length of the array if needed. 12778 // Update the length of the array if needed.
12889 uint32_t array_length = 0; 12779 uint32_t array_length = 0;
12890 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength( 12780 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(
12891 &array_length)); 12781 &array_length));
12892 if (index >= array_length) { 12782 if (index >= array_length) {
12893 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1)); 12783 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12894 } 12784 }
12895 } 12785 }
12896 return value; 12786 return;
12897 } 12787 }
12898 12788
12899 // Allow gap in fast case. 12789 // Allow gap in fast case.
12900 if ((index - elms_length) < kMaxGap) { 12790 if ((index - elms_length) < kMaxGap) {
12901 // Try allocating extra space. 12791 // Try allocating extra space.
12902 int new_capacity = NewElementsCapacity(index+1); 12792 int new_capacity = NewElementsCapacity(index+1);
12903 if (!object->ShouldConvertToSlowElements(new_capacity)) { 12793 if (!object->ShouldConvertToSlowElements(new_capacity)) {
12904 DCHECK(static_cast<uint32_t>(new_capacity) > index); 12794 DCHECK(static_cast<uint32_t>(new_capacity) > index);
12905 SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1); 12795 SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
12906 FixedDoubleArray::cast(object->elements())->set(index, double_value); 12796 FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12907 JSObject::ValidateElements(object); 12797 JSObject::ValidateElements(object);
12908 return value; 12798 return;
12909 } 12799 }
12910 } 12800 }
12911 12801
12912 // Otherwise default to slow case. 12802 // Otherwise default to slow case.
12913 DCHECK(object->HasFastDoubleElements()); 12803 DCHECK(object->HasFastDoubleElements());
12914 DCHECK(object->map()->has_fast_double_elements()); 12804 DCHECK(object->map()->has_fast_double_elements());
12915 DCHECK(object->elements()->IsFixedDoubleArray() || 12805 DCHECK(object->elements()->IsFixedDoubleArray() ||
12916 object->elements()->length() == 0); 12806 object->elements()->length() == 0);
12917 12807
12918 NormalizeElements(object); 12808 NormalizeElements(object);
12919 DCHECK(object->HasDictionaryElements()); 12809 DCHECK(object->HasDictionaryElements());
12920 return SetElement(object, index, value, NONE, language_mode, check_prototype); 12810 SetDictionaryElement(object, index, value, NONE);
12811 return;
Igor Sheludko 2015/06/11 13:44:25 nit: Do we need return; here?
Toon Verwaest 2015/06/11 14:26:50 Done.
12921 } 12812 }
12922 12813
12923 12814
12815 // static
12924 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, 12816 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12925 uint32_t index, Handle<Object> value, 12817 uint32_t index, Handle<Object> value,
12926 PropertyAttributes attributes,
12927 LanguageMode language_mode) { 12818 LanguageMode language_mode) {
12928 if (object->IsJSProxy()) { 12819 Isolate* isolate = object->GetIsolate();
12929 return JSProxy::SetElementWithHandler(Handle<JSProxy>::cast(object), object, 12820 LookupIterator it(isolate, object, index);
12930 index, value, language_mode); 12821 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED);
12931 }
12932 return JSObject::SetElement(Handle<JSObject>::cast(object), index, value,
12933 attributes, language_mode);
12934 } 12822 }
12935 12823
12936 12824
12937 MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object, 12825 // static
12938 uint32_t index, 12826 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> receiver,
12939 Handle<Object> value, 12827 uint32_t index,
12940 PropertyAttributes attributes, 12828 Handle<Object> value,
12941 LanguageMode language_mode) { 12829 PropertyAttributes attributes) {
12942 DCHECK(!object->HasExternalArrayElements()); 12830 DCHECK(receiver->map()->is_extensible());
12943 return JSObject::SetElement(object, index, value, attributes, language_mode,
12944 false);
12945 }
12946 12831
12832 Isolate* isolate = receiver->GetIsolate();
12947 12833
12948 MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object, 12834 // TODO(verwaest): Use ElementAccessor.
12949 uint32_t index, Handle<Object> value, 12835 Handle<Object> old_length_handle;
12950 PropertyAttributes attributes, 12836 if (receiver->IsJSArray() && receiver->map()->is_observed()) {
12951 LanguageMode language_mode, 12837 old_length_handle = handle(JSArray::cast(*receiver)->length(), isolate);
12952 bool check_prototype,
12953 SetPropertyMode set_mode) {
12954 Isolate* isolate = object->GetIsolate();
12955
12956 if (object->HasExternalArrayElements() ||
12957 object->HasFixedTypedArrayElements()) {
12958 if (!value->IsNumber() && !value->IsUndefined()) {
12959 ASSIGN_RETURN_ON_EXCEPTION(
12960 isolate, value,
12961 Execution::ToNumber(isolate, value), Object);
12962 }
12963 } 12838 }
12964 12839
12965 // Check access rights if needed. 12840 if (attributes != NONE) {
12966 if (object->IsAccessCheckNeeded()) { 12841 Handle<SeededNumberDictionary> d = JSObject::NormalizeElements(receiver);
12967 if (!isolate->MayAccess(object)) { 12842 // TODO(verwaest): Move this into NormalizeElements.
12968 isolate->ReportFailedAccessCheck(object); 12843 d->set_requires_slow_elements();
12969 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12970 return value;
12971 }
12972 } 12844 }
12973 12845
12974 if (object->IsJSGlobalProxy()) { 12846 Handle<Object> result = value;
12975 PrototypeIterator iter(isolate, object); 12847
12976 if (iter.IsAtEnd()) return value; 12848 switch (receiver->GetElementsKind()) {
12977 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); 12849 case FAST_SMI_ELEMENTS:
12978 return SetElement( 12850 case FAST_ELEMENTS:
12979 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, 12851 case FAST_HOLEY_SMI_ELEMENTS:
12980 value, attributes, language_mode, check_prototype, set_mode); 12852 case FAST_HOLEY_ELEMENTS:
12853 SetFastElement(receiver, index, value);
12854 break;
12855 case FAST_DOUBLE_ELEMENTS:
12856 case FAST_HOLEY_DOUBLE_ELEMENTS:
12857 SetFastDoubleElement(receiver, index, value);
12858 break;
12859
12860 case DICTIONARY_ELEMENTS:
12861 SetDictionaryElement(receiver, index, value, attributes);
12862 break;
12863 case SLOPPY_ARGUMENTS_ELEMENTS:
12864 SetSloppyArgumentsElements(receiver, index, value, attributes);
12865 break;
12866
12867 // Elements cannot be added to typed arrays.
12868 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
12869 case EXTERNAL_##TYPE##_ELEMENTS: \
12870 case TYPE##_ELEMENTS:
12871
12872 TYPED_ARRAYS(TYPED_ARRAY_CASE)
12873
12874 #undef TYPED_ARRAY_CASE
12875 UNREACHABLE();
12876 break;
12981 } 12877 }
12982 12878
12983 // Don't allow element properties to be redefined for external arrays. 12879 if (!old_length_handle.is_null() &&
12984 if ((object->HasExternalArrayElements() || 12880 !old_length_handle->SameValue(
12985 object->HasFixedTypedArrayElements()) && 12881 Handle<JSArray>::cast(receiver)->length())) {
Igor Sheludko 2015/06/11 13:44:25 What about adding DCHECK(receiver->map()->is_obser
Toon Verwaest 2015/06/11 14:26:50 Done.
12986 set_mode == DEFINE_PROPERTY) { 12882 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
12987 THROW_NEW_ERROR( 12883 Handle<String> name = isolate->factory()->Uint32ToString(index);
12988 isolate, NewTypeError(MessageTemplate::kRedefineExternalArray), Object); 12884 Handle<Object> new_length_handle(array->length(), isolate);
12989 } 12885 uint32_t old_length = 0;
12886 uint32_t new_length = 0;
12887 CHECK(old_length_handle->ToArrayLength(&old_length));
12888 CHECK(new_length_handle->ToArrayLength(&new_length));
12990 12889
12991 // Normalize the elements to enable attributes on the property. 12890 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
12992 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
12993 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
12994 // Make sure that we never go back to fast case.
12995 dictionary->set_requires_slow_elements();
12996 }
12997
12998 if (!object->map()->is_observed()) {
12999 return object->HasIndexedInterceptor()
13000 ? SetElementWithInterceptor(object, index, value, attributes,
13001 language_mode, check_prototype,
13002 set_mode)
13003 : SetElementWithoutInterceptor(object, index, value, attributes,
13004 language_mode, check_prototype,
13005 set_mode);
13006 }
13007
13008 Maybe<PropertyAttributes> maybe =
13009 JSReceiver::GetOwnElementAttributes(object, index);
13010 if (!maybe.IsJust()) return MaybeHandle<Object>();
13011 PropertyAttributes old_attributes = maybe.FromJust();
13012
13013 Handle<Object> old_value = isolate->factory()->the_hole_value();
13014 Handle<Object> old_length_handle;
13015 Handle<Object> new_length_handle;
13016
13017 if (old_attributes != ABSENT) {
13018 if (GetOwnElementAccessorPair(object, index).is_null()) {
13019 old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
13020 }
13021 } else if (object->IsJSArray()) {
13022 // Store old array length in case adding an element grows the array.
13023 old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13024 isolate);
13025 }
13026
13027 // Check for lookup interceptor
13028 Handle<Object> result;
13029 ASSIGN_RETURN_ON_EXCEPTION(
13030 isolate, result,
13031 object->HasIndexedInterceptor()
13032 ? SetElementWithInterceptor(object, index, value, attributes,
13033 language_mode, check_prototype, set_mode)
13034 : SetElementWithoutInterceptor(object, index, value, attributes,
13035 language_mode, check_prototype,
13036 set_mode),
13037 Object);
13038
13039 Handle<String> name = isolate->factory()->Uint32ToString(index);
13040 maybe = GetOwnElementAttributes(object, index);
13041 if (!maybe.IsJust()) return MaybeHandle<Object>();
13042 PropertyAttributes new_attributes = maybe.FromJust();
13043
13044 if (old_attributes == ABSENT) {
13045 if (object->IsJSArray() &&
13046 !old_length_handle->SameValue(
13047 Handle<JSArray>::cast(object)->length())) {
13048 new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13049 isolate);
13050 uint32_t old_length = 0;
13051 uint32_t new_length = 0;
13052 CHECK(old_length_handle->ToArrayLength(&old_length));
13053 CHECK(new_length_handle->ToArrayLength(&new_length));
13054
13055 RETURN_ON_EXCEPTION(
13056 isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object);
13057 RETURN_ON_EXCEPTION(
13058 isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
13059 RETURN_ON_EXCEPTION(
13060 isolate, EnqueueChangeRecord(object, "update",
13061 isolate->factory()->length_string(),
13062 old_length_handle),
13063 Object);
13064 RETURN_ON_EXCEPTION(
13065 isolate, EndPerformSplice(Handle<JSArray>::cast(object)), Object);
13066 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
13067 RETURN_ON_EXCEPTION(
13068 isolate,
13069 EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length,
13070 deleted, new_length - old_length),
13071 Object);
13072 } else {
13073 RETURN_ON_EXCEPTION(
13074 isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
13075 }
13076 } else if (old_value->IsTheHole()) {
13077 RETURN_ON_EXCEPTION( 12891 RETURN_ON_EXCEPTION(
13078 isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value), 12892 isolate, JSObject::EnqueueChangeRecord(
12893 array, "add", name, isolate->factory()->the_hole_value()),
13079 Object); 12894 Object);
13080 } else { 12895 RETURN_ON_EXCEPTION(
13081 Handle<Object> new_value = 12896 isolate, JSObject::EnqueueChangeRecord(
13082 Object::GetElement(isolate, object, index).ToHandleChecked(); 12897 array, "update", isolate->factory()->length_string(),
13083 bool value_changed = !old_value->SameValue(*new_value); 12898 old_length_handle),
13084 if (old_attributes != new_attributes) { 12899 Object);
13085 if (!value_changed) old_value = isolate->factory()->the_hole_value(); 12900 RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
13086 RETURN_ON_EXCEPTION( 12901 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
13087 isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value), 12902 RETURN_ON_EXCEPTION(isolate, EnqueueSpliceRecord(array, old_length, deleted,
13088 Object); 12903 new_length - old_length),
13089 } else if (value_changed) { 12904 Object);
13090 RETURN_ON_EXCEPTION( 12905 } else if (receiver->map()->is_observed()) {
13091 isolate, EnqueueChangeRecord(object, "update", name, old_value), 12906 Handle<String> name = isolate->factory()->Uint32ToString(index);
13092 Object); 12907 RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord(
13093 } 12908 receiver, "add", name,
12909 isolate->factory()->the_hole_value()),
12910 Object);
13094 } 12911 }
13095 12912
13096 return result; 12913 return result;
13097 } 12914 }
13098 12915
13099 12916
13100 MaybeHandle<Object> JSObject::SetElementWithoutInterceptor(
13101 Handle<JSObject> object, uint32_t index, Handle<Object> value,
13102 PropertyAttributes attributes, LanguageMode language_mode,
13103 bool check_prototype, SetPropertyMode set_mode) {
13104 DCHECK(object->HasDictionaryElements() ||
13105 object->HasDictionaryArgumentsElements() ||
13106 (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
13107 Isolate* isolate = object->GetIsolate();
13108 if (FLAG_trace_external_array_abuse &&
13109 IsExternalArrayElementsKind(object->GetElementsKind())) {
13110 CheckArrayAbuse(object, "external elements write", index);
13111 }
13112 if (FLAG_trace_js_array_abuse &&
13113 !IsExternalArrayElementsKind(object->GetElementsKind())) {
13114 if (object->IsJSArray()) {
13115 CheckArrayAbuse(object, "elements write", index, true);
13116 }
13117 }
13118 if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
13119 Handle<JSArray>::cast(object), index)) {
13120 if (is_sloppy(language_mode)) {
13121 return value;
13122 } else {
13123 return JSArray::ReadOnlyLengthError(Handle<JSArray>::cast(object));
13124 }
13125 }
13126 switch (object->GetElementsKind()) {
13127 case FAST_SMI_ELEMENTS:
13128 case FAST_ELEMENTS:
13129 case FAST_HOLEY_SMI_ELEMENTS:
13130 case FAST_HOLEY_ELEMENTS:
13131 return SetFastElement(object, index, value, language_mode,
13132 check_prototype);
13133 case FAST_DOUBLE_ELEMENTS:
13134 case FAST_HOLEY_DOUBLE_ELEMENTS:
13135 return SetFastDoubleElement(object, index, value, language_mode,
13136 check_prototype);
13137
13138 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
13139 case EXTERNAL_##TYPE##_ELEMENTS: { \
13140 Handle<External##Type##Array> array( \
13141 External##Type##Array::cast(object->elements())); \
13142 return External##Type##Array::SetValue(object, array, index, value); \
13143 } \
13144 case TYPE##_ELEMENTS: { \
13145 Handle<Fixed##Type##Array> array( \
13146 Fixed##Type##Array::cast(object->elements())); \
13147 return Fixed##Type##Array::SetValue(object, array, index, value); \
13148 }
13149
13150 TYPED_ARRAYS(TYPED_ARRAY_CASE)
13151
13152 #undef TYPED_ARRAY_CASE
13153
13154 case DICTIONARY_ELEMENTS:
13155 return SetDictionaryElement(object, index, value, attributes,
13156 language_mode, check_prototype, set_mode);
13157 case SLOPPY_ARGUMENTS_ELEMENTS: {
13158 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
13159 uint32_t length = parameter_map->length();
13160 Handle<Object> probe = index < length - 2 ?
13161 Handle<Object>(parameter_map->get(index + 2), isolate) :
13162 Handle<Object>();
13163 if (!probe.is_null() && !probe->IsTheHole()) {
13164 Handle<Context> context(Context::cast(parameter_map->get(0)));
13165 int context_index = Handle<Smi>::cast(probe)->value();
13166 DCHECK(!context->get(context_index)->IsTheHole());
13167 context->set(context_index, *value);
13168 // Redefining attributes of an aliased element destroys fast aliasing.
13169 if (set_mode == SET_PROPERTY || attributes == NONE) return value;
13170 parameter_map->set_the_hole(index + 2);
13171 // For elements that are still writable we re-establish slow aliasing.
13172 if ((attributes & READ_ONLY) == 0) {
13173 value = Handle<Object>::cast(
13174 isolate->factory()->NewAliasedArgumentsEntry(context_index));
13175 }
13176 }
13177 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
13178 if (arguments->IsDictionary()) {
13179 return SetDictionaryElement(object, index, value, attributes,
13180 language_mode, check_prototype, set_mode);
13181 } else {
13182 return SetFastElement(object, index, value, language_mode,
13183 check_prototype);
13184 }
13185 }
13186 }
13187 // All possible cases have been handled above. Add a return to avoid the
13188 // complaints from the compiler.
13189 UNREACHABLE();
13190 return isolate->factory()->null_value();
13191 }
13192
13193
13194 const double AllocationSite::kPretenureRatio = 0.85; 12917 const double AllocationSite::kPretenureRatio = 0.85;
13195 12918
13196 12919
13197 void AllocationSite::ResetPretenureDecision() { 12920 void AllocationSite::ResetPretenureDecision() {
13198 set_pretenure_decision(kUndecided); 12921 set_pretenure_decision(kUndecided);
13199 set_memento_found_count(0); 12922 set_memento_found_count(0);
13200 set_memento_create_count(0); 12923 set_memento_create_count(0);
13201 } 12924 }
13202 12925
13203 12926
(...skipping 1767 matching lines...) Expand 10 before | Expand all | Expand 10 after
14971 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE) 14694 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
14972 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE 14695 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
14973 14696
14974 default: 14697 default:
14975 UNREACHABLE(); 14698 UNREACHABLE();
14976 return 0; 14699 return 0;
14977 } 14700 }
14978 } 14701 }
14979 14702
14980 14703
14704 Handle<Object> FixedArray::SetValue(Handle<JSObject> holder,
14705 Handle<FixedArray> array, uint32_t index,
14706 Handle<Object> value) {
14707 array->set(index, *value);
14708 return value;
14709 }
14710
14711
14712 Handle<Object> FixedDoubleArray::SetValue(Handle<JSObject> holder,
14713 Handle<FixedDoubleArray> array,
14714 uint32_t index,
14715 Handle<Object> value) {
14716 array->set(index, value->Number());
14717 return value;
14718 }
14719
14720
14981 Handle<Object> ExternalUint8ClampedArray::SetValue( 14721 Handle<Object> ExternalUint8ClampedArray::SetValue(
14982 Handle<JSObject> holder, Handle<ExternalUint8ClampedArray> array, 14722 Handle<JSObject> holder, Handle<ExternalUint8ClampedArray> array,
14983 uint32_t index, Handle<Object> value) { 14723 uint32_t index, Handle<Object> value) {
14984 uint8_t clamped_value = 0; 14724 uint8_t clamped_value = 0;
14985 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(holder); 14725 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(holder);
14986 if (!view->WasNeutered()) { 14726 if (!view->WasNeutered()) {
14987 if (index < static_cast<uint32_t>(array->length())) { 14727 if (index < static_cast<uint32_t>(array->length())) {
14988 if (value->IsSmi()) { 14728 if (value->IsSmi()) {
14989 int int_value = Handle<Smi>::cast(value)->value(); 14729 int int_value = Handle<Smi>::cast(value)->value();
14990 if (int_value < 0) { 14730 if (int_value < 0) {
(...skipping 1983 matching lines...) Expand 10 before | Expand all | Expand 10 after
16974 Handle<Object> new_value) { 16714 Handle<Object> new_value) {
16975 if (cell->value() != *new_value) { 16715 if (cell->value() != *new_value) {
16976 cell->set_value(*new_value); 16716 cell->set_value(*new_value);
16977 Isolate* isolate = cell->GetIsolate(); 16717 Isolate* isolate = cell->GetIsolate();
16978 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16718 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16979 isolate, DependentCode::kPropertyCellChangedGroup); 16719 isolate, DependentCode::kPropertyCellChangedGroup);
16980 } 16720 }
16981 } 16721 }
16982 } // namespace internal 16722 } // namespace internal
16983 } // namespace v8 16723 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698