7 #include "src/accessors.h" 8 #include "src/api-arguments-inl.h" 10 #include "src/arguments-inl.h" 11 #include "src/ast/ast.h" 12 #include "src/base/bits.h" 13 #include "src/code-factory.h" 14 #include "src/conversions.h" 15 #include "src/execution.h" 16 #include "src/field-type.h" 17 #include "src/frames-inl.h" 18 #include "src/handles-inl.h" 19 #include "src/ic/call-optimization.h" 20 #include "src/ic/handler-configuration-inl.h" 21 #include "src/ic/ic-inl.h" 22 #include "src/ic/ic-stats.h" 23 #include "src/ic/stub-cache.h" 24 #include "src/isolate-inl.h" 25 #include "src/macro-assembler.h" 26 #include "src/objects/api-callbacks.h" 27 #include "src/objects/data-handler-inl.h" 28 #include "src/objects/hash-table-inl.h" 29 #include "src/objects/js-array-inl.h" 30 #include "src/objects/module-inl.h" 31 #include "src/prototype.h" 32 #include "src/runtime-profiler.h" 33 #include "src/runtime/runtime-utils.h" 34 #include "src/runtime/runtime.h" 35 #include "src/tracing/trace-event.h" 36 #include "src/tracing/tracing-category-observer.h" 41 char IC::TransitionMarkFromState(IC::State state) {
49 case RECOMPUTE_HANDLER:
63 const char* GetModifier(KeyedAccessLoadMode mode) {
64 if (mode == LOAD_IGNORE_OUT_OF_BOUNDS)
return ".IGNORE_OOB";
68 const char* GetModifier(KeyedAccessStoreMode mode) {
70 case STORE_NO_TRANSITION_HANDLE_COW:
72 case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW:
74 case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
79 DCHECK(!IsCOWHandlingStoreMode(mode));
80 return IsGrowStoreMode(mode) ?
".GROW" :
"";
85 void IC::TraceIC(
const char* type, Handle<Object> name) {
87 if (AddressIsDeoptimizedCode())
return;
88 State new_state = nexus()->StateFromFeedback();
89 TraceIC(type, name, state(), new_state);
93 void IC::TraceIC(
const char* type, Handle<Object> name, State old_state,
95 if (V8_LIKELY(!FLAG_ic_stats))
return;
98 if (!receiver_map().is_null()) {
99 map = *receiver_map();
102 const char* modifier =
"";
103 if (IsKeyedLoadIC()) {
104 KeyedAccessLoadMode mode = nexus()->GetKeyedAccessLoadMode();
105 modifier = GetModifier(mode);
106 }
else if (IsKeyedStoreIC() || IsStoreInArrayLiteralICKind(kind())) {
107 KeyedAccessStoreMode mode = nexus()->GetKeyedAccessStoreMode();
108 modifier = GetModifier(mode);
111 bool keyed_prefix = is_keyed() && !IsStoreInArrayLiteralICKind(kind());
113 if (!(FLAG_ic_stats &
114 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING)) {
115 LOG(isolate(), ICEvent(type, keyed_prefix, map, *name,
116 TransitionMarkFromState(old_state),
117 TransitionMarkFromState(new_state), modifier,
122 ICStats::instance()->Begin();
123 ICInfo& ic_info = ICStats::instance()->Current();
124 ic_info.type = keyed_prefix ?
"Keyed" :
"";
125 ic_info.type += type;
127 Object* maybe_function =
128 Memory<Object*>(fp_ + JavaScriptFrameConstants::kFunctionOffset);
129 DCHECK(maybe_function->IsJSFunction());
130 JSFunction*
function = JSFunction::cast(maybe_function);
132 if (function->IsInterpreted()) {
133 code_offset = InterpretedFrame::GetBytecodeOffset(fp());
135 code_offset =
static_cast<int>(pc() -
function->code()->InstructionStart());
137 JavaScriptFrame::CollectFunctionAndOffsetForICStats(
138 function, function->abstract_code(), code_offset);
141 ic_info.state.reserve(17);
143 ic_info.state += TransitionMarkFromState(old_state);
144 ic_info.state +=
"->";
145 ic_info.state += TransitionMarkFromState(new_state);
146 ic_info.state += modifier;
147 ic_info.state +=
")";
148 ic_info.map =
reinterpret_cast<void*
>(map.ptr());
149 if (!map.is_null()) {
150 ic_info.is_dictionary_map = map->is_dictionary_map();
151 ic_info.number_of_own_descriptors = map->NumberOfOwnDescriptors();
152 ic_info.instance_type = std::to_string(map->instance_type());
155 ICStats::instance()->End();
158 IC::IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot)
161 kind_(FeedbackSlotKind::kInvalid),
162 target_maps_set_(false),
163 slow_stub_reason_(nullptr),
164 nexus_(vector, slot) {
168 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
169 Address* constant_pool =
nullptr;
170 if (FLAG_enable_embedded_constant_pool) {
171 constant_pool =
reinterpret_cast<Address*
>(
172 entry + ExitFrameConstants::kConstantPoolOffset);
174 Address* pc_address =
175 reinterpret_cast<Address*
>(entry + ExitFrameConstants::kCallerPCOffset);
176 Address fp = Memory<Address>(entry + ExitFrameConstants::kCallerFPOffset);
178 StackFrameIterator it(isolate);
179 for (
int i = 0;
i < 1;
i++) it.Advance();
180 StackFrame* frame = it.frame();
181 DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
188 intptr_t frame_marker =
189 Memory<intptr_t>(fp + TypedFrameConstants::kFrameTypeOffset);
190 if (frame_marker == StackFrame::TypeToMarker(StackFrame::STUB)) {
191 fp = Memory<Address>(fp + TypedFrameConstants::kCallerFPOffset);
194 if (FLAG_enable_embedded_constant_pool) {
195 constant_pool_address_ = constant_pool;
197 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
198 kind_ = nexus_.kind();
199 state_ = nexus_.StateFromFeedback();
203 JSFunction* IC::GetHostFunction()
const {
207 StackFrameIterator it(isolate());
208 while (it.frame()->fp() != this->fp()) it.Advance();
209 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
212 return frame->function();
215 static void LookupForRead(Isolate* isolate, LookupIterator* it) {
216 for (; it->IsFound(); it->Next()) {
217 switch (it->state()) {
218 case LookupIterator::NOT_FOUND:
219 case LookupIterator::TRANSITION:
221 case LookupIterator::JSPROXY:
223 case LookupIterator::INTERCEPTOR: {
225 Handle<JSObject> holder = it->GetHolder<JSObject>();
226 if (!holder->GetNamedInterceptor()->getter()->IsUndefined(isolate)) {
231 case LookupIterator::ACCESS_CHECK:
233 if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && it->HasAccess()) {
237 case LookupIterator::ACCESSOR:
238 case LookupIterator::INTEGER_INDEXED_EXOTIC:
239 case LookupIterator::DATA:
245 bool IC::ShouldRecomputeHandler(Handle<String> name) {
246 if (!RecomputeHandlerForName(name))
return false;
250 if (IsGlobalIC())
return true;
252 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
259 if (maybe_handler_.is_null()) {
260 if (!receiver_map()->IsJSObjectMap())
return false;
261 Map first_map = FirstTargetMap();
262 if (first_map.is_null())
return false;
263 Handle<Map> old_map(first_map, isolate());
264 if (old_map->is_deprecated())
return true;
265 return IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
266 receiver_map()->elements_kind());
272 bool IC::RecomputeHandlerForName(Handle<Object> name) {
275 if (!name->IsName())
return false;
276 Name stub_name = nexus()->FindFirstName();
277 if (*name != stub_name)
return false;
284 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
285 update_receiver_map(receiver);
286 if (!name->IsString())
return;
287 if (state() != MONOMORPHIC && state() != POLYMORPHIC)
return;
288 if (receiver->IsNullOrUndefined(isolate()))
return;
293 if (ShouldRecomputeHandler(Handle<String>::cast(name))) {
294 MarkRecomputeHandler(name);
298 MaybeHandle<Object> IC::TypeError(MessageTemplate index, Handle<Object>
object,
299 Handle<Object> key) {
300 HandleScope scope(isolate());
301 THROW_NEW_ERROR(isolate(), NewTypeError(index, key,
object), Object);
305 MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {
306 HandleScope scope(isolate());
308 isolate(), NewReferenceError(MessageTemplate::kNotDefined, name), Object);
312 void IC::OnFeedbackChanged(Isolate* isolate, FeedbackNexus* nexus,
313 JSFunction* host_function,
const char* reason) {
314 FeedbackVector* vector = nexus->vector();
315 FeedbackSlot slot = nexus->slot();
316 OnFeedbackChanged(isolate, vector, slot, host_function, reason);
320 void IC::OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
321 FeedbackSlot slot, JSFunction* host_function,
322 const char* reason) {
323 if (FLAG_trace_opt_verbose) {
327 if (vector->profiler_ticks() != 0) {
328 PrintF(
"[resetting ticks for ");
329 host_function->ShortPrint();
330 PrintF(
" due from %d due to IC change: %s]\n", vector->profiler_ticks(),
334 vector->set_profiler_ticks(0);
336 #ifdef V8_TRACE_FEEDBACK_UPDATES 337 if (FLAG_trace_feedback_updates) {
338 int slot_count = vector->metadata()->slot_count();
341 if (slot.IsInvalid()) {
342 os <<
"[Feedback slots in ";
344 os <<
"[Feedback slot " << slot.ToInt() <<
"/" << slot_count <<
" in ";
346 vector->shared_function_info()->ShortPrint(os);
347 if (slot.IsInvalid()) {
350 os <<
" updated to ";
351 vector->FeedbackSlotPrint(os, slot);
354 os << reason <<
"]" << std::endl;
358 isolate->runtime_profiler()->NotifyICChanged();
364 static bool MigrateDeprecated(Handle<Object>
object) {
365 if (!object->IsJSObject())
return false;
366 Handle<JSObject> receiver = Handle<JSObject>::cast(
object);
367 if (!receiver->map()->is_deprecated())
return false;
368 JSObject::MigrateInstance(Handle<JSObject>::cast(
object));
372 bool IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
373 DCHECK_EQ(MEGAMORPHIC, new_state);
374 DCHECK_IMPLIES(!is_keyed(), key->IsName());
379 nexus()->ConfigureMegamorphic(key->IsName() ? PROPERTY : ELEMENT);
381 OnFeedbackChanged(isolate(), nexus(), GetHostFunction(),
"Megamorphic");
385 void IC::ConfigureVectorState(Handle<Map> map) {
386 nexus()->ConfigurePremonomorphic(map);
388 OnFeedbackChanged(isolate(), nexus(), GetHostFunction(),
"Premonomorphic");
391 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
392 Handle<Object> handler) {
393 ConfigureVectorState(name, map, MaybeObjectHandle(handler));
396 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
397 const MaybeObjectHandle& handler) {
399 nexus()->ConfigureHandlerMode(handler);
402 if (!is_keyed()) name = Handle<Name>::null();
403 nexus()->ConfigureMonomorphic(name, map, handler);
407 OnFeedbackChanged(isolate(), nexus(), GetHostFunction(),
408 IsLoadGlobalIC() ?
"LoadGlobal" :
"Monomorphic");
411 void IC::ConfigureVectorState(Handle<Name> name, MapHandles
const& maps,
412 MaybeObjectHandles* handlers) {
413 DCHECK(!IsGlobalIC());
415 if (!is_keyed()) name = Handle<Name>::null();
416 nexus()->ConfigurePolymorphic(name, maps, handlers);
419 OnFeedbackChanged(isolate(), nexus(), GetHostFunction(),
"Polymorphic");
422 MaybeHandle<Object> LoadIC::Load(Handle<Object>
object, Handle<Name> name) {
425 if (object->IsNullOrUndefined(isolate())) {
426 if (FLAG_use_ic && state() != PREMONOMORPHIC) {
428 TRACE_HANDLER_STATS(isolate(), LoadIC_NonReceiver);
429 update_receiver_map(
object);
430 PatchCache(name, slow_stub());
431 TraceIC(
"LoadIC", name);
434 if (*name == ReadOnlyRoots(isolate()).iterator_symbol()) {
435 return Runtime::ThrowIteratorError(isolate(),
object);
437 return TypeError(MessageTemplate::kNonObjectPropertyLoad,
object, name);
440 bool use_ic = MigrateDeprecated(
object) ? false : FLAG_use_ic;
442 if (state() != UNINITIALIZED) {
443 JSObject::MakePrototypesFast(
object, kStartAtReceiver, isolate());
444 update_receiver_map(
object);
447 LookupIterator it(isolate(),
object, name);
448 LookupForRead(isolate(), &it);
450 if (name->IsPrivate()) {
451 if (name->IsPrivateName() && !it.IsFound()) {
452 return TypeError(MessageTemplate::kInvalidPrivateFieldAccess,
object,
458 if (object->IsJSProxy()) {
463 if (it.IsFound() || !ShouldThrowReferenceError()) {
465 if (use_ic) UpdateCaches(&it);
468 Handle<Object> result;
470 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it),
474 }
else if (!ShouldThrowReferenceError()) {
475 LOG(isolate(), SuspectReadEvent(*name, *
object));
479 return ReferenceError(name);
482 MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
483 Handle<JSGlobalObject> global = isolate()->global_object();
485 if (name->IsString()) {
487 Handle<String> str_name = Handle<String>::cast(name);
488 Handle<ScriptContextTable> script_contexts(
489 global->native_context()->script_context_table(), isolate());
491 ScriptContextTable::LookupResult lookup_result;
492 if (ScriptContextTable::Lookup(isolate(), script_contexts, str_name,
494 Handle<Context> script_context = ScriptContextTable::GetContext(
495 isolate(), script_contexts, lookup_result.context_index);
497 Handle<Object> result(script_context->get(lookup_result.slot_index),
500 if (result->IsTheHole(isolate())) {
503 return ReferenceError(name);
507 if (nexus()->ConfigureLexicalVarMode(lookup_result.context_index,
508 lookup_result.slot_index)) {
509 TRACE_HANDLER_STATS(isolate(), LoadGlobalIC_LoadScriptContextField);
512 TRACE_HANDLER_STATS(isolate(), LoadGlobalIC_SlowStub);
513 PatchCache(name, slow_stub());
515 TraceIC(
"LoadGlobalIC", name);
520 return LoadIC::Load(global, name);
523 static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps,
524 Handle<Map> new_receiver_map) {
525 DCHECK(!new_receiver_map.is_null());
526 for (Handle<Map> map : *receiver_maps) {
527 if (!map.is_null() && map.is_identical_to(new_receiver_map)) {
531 receiver_maps->push_back(new_receiver_map);
535 bool IC::UpdatePolymorphicIC(Handle<Name> name,
536 const MaybeObjectHandle& handler) {
537 DCHECK(IsHandler(*handler));
538 if (is_keyed() && state() != RECOMPUTE_HANDLER) {
539 if (nexus()->FindFirstName() != *name)
return false;
541 Handle<Map> map = receiver_map();
543 MaybeObjectHandles handlers;
546 int number_of_maps =
static_cast<int>(maps.size());
547 int deprecated_maps = 0;
548 int handler_to_overwrite = -1;
549 if (!nexus()->FindHandlers(&handlers, number_of_maps))
return false;
551 for (
int i = 0;
i < number_of_maps;
i++) {
552 Handle<Map> current_map = maps.at(
i);
553 if (current_map->is_deprecated()) {
556 }
else if (map.is_identical_to(current_map)) {
562 if (handler.is_identical_to(handlers[
i]) &&
563 state() != RECOMPUTE_HANDLER) {
569 handler_to_overwrite =
i;
570 }
else if (handler_to_overwrite == -1 &&
571 IsTransitionOfMonomorphicTarget(*current_map, *map)) {
572 handler_to_overwrite =
i;
576 int number_of_valid_maps =
577 number_of_maps - deprecated_maps - (handler_to_overwrite != -1);
579 if (number_of_valid_maps >= kMaxPolymorphicMapCount)
return false;
580 if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
584 number_of_valid_maps++;
585 if (number_of_valid_maps == 1) {
586 ConfigureVectorState(name, receiver_map(), handler);
588 if (is_keyed() && nexus()->FindFirstName() != *name)
return false;
589 if (handler_to_overwrite >= 0) {
590 handlers[handler_to_overwrite] = handler;
591 if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
592 maps[handler_to_overwrite] = map;
596 handlers.push_back(handler);
599 ConfigureVectorState(name, maps, &handlers);
605 void IC::UpdateMonomorphicIC(
const MaybeObjectHandle& handler,
607 DCHECK(IsHandler(*handler));
608 ConfigureVectorState(name, receiver_map(), handler);
612 void IC::CopyICToMegamorphicCache(Handle<Name> name) {
614 MaybeObjectHandles handlers;
616 if (!nexus()->FindHandlers(&handlers, static_cast<int>(maps.size())))
return;
617 for (
int i = 0; i < static_cast<int>(maps.size());
i++) {
618 UpdateMegamorphicCache(maps.at(
i), name, handlers.at(
i));
622 bool IC::IsTransitionOfMonomorphicTarget(Map source_map, Map target_map) {
623 if (source_map.is_null())
return true;
624 if (target_map.is_null())
return false;
625 if (source_map->is_abandoned_prototype_map())
return false;
626 ElementsKind target_elements_kind = target_map->elements_kind();
627 bool more_general_transition = IsMoreGeneralElementsKindTransition(
628 source_map->elements_kind(), target_elements_kind);
629 Map transitioned_map;
630 if (more_general_transition) {
632 map_list.push_back(handle(target_map, isolate_));
634 source_map->FindElementsKindTransitionedMap(isolate(), map_list);
636 return transitioned_map == target_map;
639 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
640 PatchCache(name, MaybeObjectHandle(handler));
643 void IC::PatchCache(Handle<Name> name,
const MaybeObjectHandle& handler) {
644 DCHECK(IsHandler(*handler));
646 DCHECK(IsAnyLoad() || IsAnyStore());
650 UpdateMonomorphicIC(handler, name);
652 case RECOMPUTE_HANDLER:
655 UpdateMonomorphicIC(handler, name);
660 if (UpdatePolymorphicIC(name, handler))
break;
661 if (!is_keyed() || state() == RECOMPUTE_HANDLER) {
662 CopyICToMegamorphicCache(name);
664 ConfigureVectorState(MEGAMORPHIC, name);
667 UpdateMegamorphicCache(receiver_map(), name, handler);
677 void LoadIC::UpdateCaches(LookupIterator* lookup) {
678 if (state() == UNINITIALIZED && !IsLoadGlobalIC()) {
681 TRACE_HANDLER_STATS(isolate(), LoadIC_Premonomorphic);
682 ConfigureVectorState(receiver_map());
683 TraceIC(
"LoadIC", lookup->name());
688 if (lookup->state() == LookupIterator::ACCESS_CHECK) {
690 }
else if (!lookup->IsFound()) {
691 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
692 Handle<Smi> smi_handler = LoadHandler::LoadNonExistent(isolate());
693 code = LoadHandler::LoadFullChain(
694 isolate(), receiver_map(),
695 MaybeObjectHandle(isolate()->factory()->null_value()), smi_handler);
697 if (IsLoadGlobalIC()) {
698 if (lookup->TryLookupCachedProperty()) {
699 DCHECK_EQ(LookupIterator::DATA, lookup->state());
701 if (lookup->state() == LookupIterator::DATA &&
702 lookup->GetReceiver().is_identical_to(lookup->GetHolder<Object>())) {
703 DCHECK(lookup->GetReceiver()->IsJSGlobalObject());
705 nexus()->ConfigurePropertyCellMode(lookup->GetPropertyCell());
706 TraceIC(
"LoadGlobalIC", lookup->name());
710 code = ComputeHandler(lookup);
713 PatchCache(lookup->name(), code);
714 TraceIC(
"LoadIC", lookup->name());
717 StubCache* IC::stub_cache() {
719 return isolate()->load_stub_cache();
721 DCHECK(IsAnyStore());
722 return isolate()->store_stub_cache();
726 void IC::UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name,
727 const MaybeObjectHandle& handler) {
728 stub_cache()->Set(*name, *map, *handler);
731 void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
732 DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state());
733 if (V8_LIKELY(!FLAG_runtime_stats))
return;
735 TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Accessor);
737 DCHECK(IsAnyStore());
738 TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Accessor);
742 Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
743 Handle<Object> receiver = lookup->GetReceiver();
744 ReadOnlyRoots roots(isolate());
745 if (receiver->IsString() && *lookup->name() == roots.length_string()) {
746 TRACE_HANDLER_STATS(isolate(), LoadIC_StringLength);
747 return BUILTIN_CODE(isolate(), LoadIC_StringLength);
750 if (receiver->IsStringWrapper() && *lookup->name() == roots.length_string()) {
751 TRACE_HANDLER_STATS(isolate(), LoadIC_StringWrapperLength);
752 return BUILTIN_CODE(isolate(), LoadIC_StringWrapperLength);
756 if (receiver->IsJSFunction() && *lookup->name() == roots.prototype_string() &&
757 !JSFunction::cast(*receiver)->PrototypeRequiresRuntimeLookup()) {
759 TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub);
760 return BUILTIN_CODE(isolate(), LoadIC_FunctionPrototype);
763 Handle<Map> map = receiver_map();
764 Handle<JSObject> holder;
765 bool receiver_is_holder;
766 if (lookup->state() != LookupIterator::JSPROXY) {
767 holder = lookup->GetHolder<JSObject>();
768 receiver_is_holder = receiver.is_identical_to(holder);
771 switch (lookup->state()) {
772 case LookupIterator::INTERCEPTOR: {
773 Handle<Smi> smi_handler = LoadHandler::LoadInterceptor(isolate());
775 if (holder->GetNamedInterceptor()->non_masking()) {
776 MaybeObjectHandle holder_ref(isolate()->factory()->null_value());
777 if (!receiver_is_holder || IsLoadGlobalIC()) {
778 holder_ref = MaybeObjectHandle::Weak(holder);
780 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonMaskingInterceptorDH);
781 return LoadHandler::LoadFullChain(isolate(), map, holder_ref,
785 if (receiver_is_holder) {
786 DCHECK(map->has_named_interceptor());
787 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptorDH);
791 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptorFromPrototypeDH);
792 return LoadHandler::LoadFromPrototype(isolate(), map, holder,
796 case LookupIterator::ACCESSOR: {
801 if (Accessors::IsJSObjectFieldAccessor(isolate(), map, lookup->name(),
803 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
804 return LoadHandler::LoadField(isolate(), index);
806 if (holder->IsJSModuleNamespace()) {
807 Handle<ObjectHashTable> exports(
808 Handle<JSModuleNamespace>::cast(holder)->module()->exports(),
810 int entry = exports->FindEntry(roots, lookup->name(),
811 Smi::ToInt(lookup->name()->GetHash()));
813 DCHECK_NE(entry, ObjectHashTable::kNotFound);
814 int index = ObjectHashTable::EntryToValueIndex(entry);
815 return LoadHandler::LoadModuleExport(isolate(), index);
818 Handle<Object> accessors = lookup->GetAccessors();
819 if (accessors->IsAccessorPair()) {
820 if (lookup->TryLookupCachedProperty()) {
821 DCHECK_EQ(LookupIterator::DATA, lookup->state());
822 return ComputeHandler(lookup);
825 Handle<Object> getter(AccessorPair::cast(*accessors)->getter(),
827 if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo()) {
828 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
832 if (getter->IsFunctionTemplateInfo() &&
833 FunctionTemplateInfo::cast(*getter)->BreakAtEntry()) {
835 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
839 Handle<Smi> smi_handler;
841 CallOptimization call_optimization(isolate(), getter);
842 if (call_optimization.is_simple_api_call()) {
843 if (!call_optimization.IsCompatibleReceiverMap(map, holder) ||
844 !holder->HasFastProperties()) {
845 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
849 CallOptimization::HolderLookup holder_lookup;
850 call_optimization.LookupHolderOfExpectedType(map, &holder_lookup);
852 smi_handler = LoadHandler::LoadApiGetter(
853 isolate(), holder_lookup == CallOptimization::kHolderIsReceiver);
855 Handle<Context> context(
856 call_optimization.GetAccessorContext(holder->map()), isolate());
858 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterFromPrototypeDH);
859 return LoadHandler::LoadFromPrototype(
860 isolate(), map, holder, smi_handler,
861 MaybeObjectHandle::Weak(call_optimization.api_call_info()),
862 MaybeObjectHandle::Weak(context));
865 if (holder->HasFastProperties()) {
867 LoadHandler::LoadAccessor(isolate(), lookup->GetAccessorIndex());
869 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorDH);
870 if (receiver_is_holder)
return smi_handler;
871 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorFromPrototypeDH);
872 }
else if (holder->IsJSGlobalObject()) {
873 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
874 smi_handler = LoadHandler::LoadGlobal(isolate());
875 return LoadHandler::LoadFromPrototype(
876 isolate(), map, holder, smi_handler,
877 MaybeObjectHandle::Weak(lookup->GetPropertyCell()));
879 smi_handler = LoadHandler::LoadNormal(isolate());
881 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
882 if (receiver_is_holder)
return smi_handler;
883 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
886 return LoadHandler::LoadFromPrototype(isolate(), map, holder,
890 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
892 if (v8::ToCData<Address>(info->getter()) == kNullAddress ||
893 !AccessorInfo::IsCompatibleReceiverMap(info, map) ||
894 !holder->HasFastProperties() ||
895 (info->is_sloppy() && !receiver->IsJSReceiver())) {
896 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
900 Handle<Smi> smi_handler = LoadHandler::LoadNativeDataProperty(
901 isolate(), lookup->GetAccessorIndex());
902 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNativeDataPropertyDH);
903 if (receiver_is_holder)
return smi_handler;
904 TRACE_HANDLER_STATS(isolate(),
905 LoadIC_LoadNativeDataPropertyFromPrototypeDH);
906 return LoadHandler::LoadFromPrototype(isolate(), map, holder,
910 case LookupIterator::DATA: {
911 DCHECK_EQ(kData, lookup->property_details().kind());
912 Handle<Smi> smi_handler;
913 if (lookup->is_dictionary_holder()) {
914 if (holder->IsJSGlobalObject()) {
917 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalDH);
918 smi_handler = LoadHandler::LoadGlobal(isolate());
919 return LoadHandler::LoadFromPrototype(
920 isolate(), map, holder, smi_handler,
921 MaybeObjectHandle::Weak(lookup->GetPropertyCell()));
924 smi_handler = LoadHandler::LoadNormal(isolate());
925 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
926 if (receiver_is_holder)
return smi_handler;
927 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
929 }
else if (lookup->property_details().location() == kField) {
930 FieldIndex field = lookup->GetFieldIndex();
931 smi_handler = LoadHandler::LoadField(isolate(), field);
932 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
933 if (receiver_is_holder)
return smi_handler;
934 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
936 DCHECK_EQ(kDescriptor, lookup->property_details().location());
938 LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex());
939 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
940 if (receiver_is_holder)
return smi_handler;
941 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
943 return LoadHandler::LoadFromPrototype(isolate(), map, holder,
946 case LookupIterator::INTEGER_INDEXED_EXOTIC:
947 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadIntegerIndexedExoticDH);
948 return LoadHandler::LoadNonExistent(isolate());
949 case LookupIterator::JSPROXY: {
950 Handle<JSProxy> holder_proxy = lookup->GetHolder<JSProxy>();
951 bool receiver_is_holder_proxy = receiver.is_identical_to(holder_proxy);
952 Handle<Smi> smi_handler = LoadHandler::LoadProxy(isolate());
953 if (receiver_is_holder_proxy) {
956 return LoadHandler::LoadFromPrototype(isolate(), map, holder_proxy,
959 case LookupIterator::ACCESS_CHECK:
960 case LookupIterator::NOT_FOUND:
961 case LookupIterator::TRANSITION:
965 return Handle<Code>::null();
968 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
971 if (key->IsHeapNumber()) {
972 double value = Handle<HeapNumber>::cast(key)->value();
973 if (std::isnan(value)) {
974 key = isolate->factory()->NaN_string();
978 if (value <= Smi::kMaxValue && value >= Smi::kMinValue) {
979 int int_value = FastD2I(value);
980 if (value == int_value) {
981 key = handle(Smi::FromInt(int_value), isolate);
985 }
else if (key->IsString()) {
986 key = isolate->factory()->InternalizeString(Handle<String>::cast(key));
991 bool KeyedLoadIC::CanChangeToAllowOutOfBounds(Handle<Map> receiver_map) {
992 const MaybeObjectHandle& handler = nexus()->FindHandlerForMap(receiver_map);
993 if (handler.is_null())
return false;
994 return LoadHandler::GetKeyedAccessLoadMode(*handler) == STANDARD_LOAD;
997 void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver,
998 KeyedAccessLoadMode load_mode) {
999 Handle<Map> receiver_map(receiver->map(), isolate());
1000 DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE);
1001 MapHandles target_receiver_maps;
1002 TargetMaps(&target_receiver_maps);
1004 if (target_receiver_maps.empty()) {
1005 Handle<Object> handler = LoadElementHandler(receiver_map, load_mode);
1006 return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
1009 for (Handle<Map> map : target_receiver_maps) {
1010 if (map.is_null())
continue;
1011 if (map->instance_type() == JS_VALUE_TYPE) {
1012 set_slow_stub_reason(
"JSValue");
1015 if (map->instance_type() == JS_PROXY_TYPE) {
1016 set_slow_stub_reason(
"JSProxy");
1028 if (state() == MONOMORPHIC && !receiver->IsString() &&
1029 !receiver->IsJSProxy() &&
1030 IsMoreGeneralElementsKindTransition(
1031 target_receiver_maps.at(0)->elements_kind(),
1032 Handle<JSObject>::cast(receiver)->GetElementsKind())) {
1033 Handle<Object> handler = LoadElementHandler(receiver_map, load_mode);
1034 return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
1037 DCHECK(state() != GENERIC);
1041 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1045 if (load_mode != LOAD_IGNORE_OUT_OF_BOUNDS ||
1046 !CanChangeToAllowOutOfBounds(receiver_map)) {
1049 set_slow_stub_reason(
"same map added twice");
1056 if (target_receiver_maps.size() > kMaxKeyedPolymorphism) {
1057 set_slow_stub_reason(
"max polymorph exceeded");
1061 MaybeObjectHandles handlers;
1062 handlers.reserve(target_receiver_maps.size());
1063 LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers, load_mode);
1064 DCHECK_LE(1, target_receiver_maps.size());
1065 if (target_receiver_maps.size() == 1) {
1066 ConfigureVectorState(Handle<Name>(), target_receiver_maps[0], handlers[0]);
1068 ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
1072 Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map,
1073 KeyedAccessLoadMode load_mode) {
1074 if (receiver_map->has_indexed_interceptor() &&
1075 !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(
1077 !receiver_map->GetIndexedInterceptor()->non_masking()) {
1079 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub);
1080 return BUILTIN_CODE(isolate(), LoadIndexedInterceptorIC);
1082 InstanceType instance_type = receiver_map->instance_type();
1083 if (instance_type < FIRST_NONSTRING_TYPE) {
1084 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedStringDH);
1085 return LoadHandler::LoadIndexedString(isolate(), load_mode);
1087 if (instance_type < FIRST_JS_RECEIVER_TYPE) {
1088 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_SlowStub);
1089 return BUILTIN_CODE(isolate(), KeyedLoadIC_Slow);
1091 if (instance_type == JS_PROXY_TYPE) {
1092 return LoadHandler::LoadProxy(isolate());
1095 ElementsKind elements_kind = receiver_map->elements_kind();
1096 if (IsSloppyArgumentsElementsKind(elements_kind)) {
1098 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_KeyedLoadSloppyArgumentsStub);
1099 return BUILTIN_CODE(isolate(), KeyedLoadIC_SloppyArguments);
1101 bool is_js_array = instance_type == JS_ARRAY_TYPE;
1102 if (elements_kind == DICTIONARY_ELEMENTS) {
1103 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
1104 return LoadHandler::LoadElement(isolate(), elements_kind,
false,
1105 is_js_array, load_mode);
1107 DCHECK(IsFastElementsKind(elements_kind) ||
1108 IsFixedTypedArrayElementsKind(elements_kind));
1110 bool convert_hole_to_undefined =
1111 is_js_array && elements_kind == HOLEY_ELEMENTS &&
1113 isolate()->raw_native_context()->GetInitialJSArrayMap(elements_kind);
1114 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
1115 return LoadHandler::LoadElement(isolate(), elements_kind,
1116 convert_hole_to_undefined, is_js_array,
1120 void KeyedLoadIC::LoadElementPolymorphicHandlers(
1121 MapHandles* receiver_maps, MaybeObjectHandles* handlers,
1122 KeyedAccessLoadMode load_mode) {
1124 receiver_maps->erase(
1126 receiver_maps->begin(), receiver_maps->end(),
1127 [](
const Handle<Map>& map) {
return map->is_deprecated(); }),
1128 receiver_maps->end());
1130 for (Handle<Map> receiver_map : *receiver_maps) {
1134 if (receiver_map->is_stable()) {
1135 Map tmap = receiver_map->FindElementsKindTransitionedMap(isolate(),
1137 if (!tmap.is_null()) {
1138 receiver_map->NotifyLeafMapLayoutChange(isolate());
1141 handlers->push_back(
1142 MaybeObjectHandle(LoadElementHandler(receiver_map, load_mode)));
1148 bool ConvertKeyToIndex(Handle<Object> receiver, Handle<Object> key,
1150 if (!FLAG_use_ic)
return false;
1151 if (receiver->IsAccessCheckNeeded() || receiver->IsJSValue())
return false;
1155 if (receiver->IsJSReceiver() || receiver->IsString()) {
1156 if (key->ToArrayIndex(index))
return true;
1162 if (receiver->IsJSTypedArray()) {
1163 int32_t signed_index;
1164 if (key->ToInt32(&signed_index)) {
1165 *index = bit_cast<
uint32_t>(signed_index);
1172 bool IsOutOfBoundsAccess(Handle<Object> receiver,
uint32_t index) {
1174 if (receiver->IsJSArray()) {
1175 JSArray::cast(*receiver)->length()->ToArrayLength(&length);
1176 }
else if (receiver->IsString()) {
1177 length = String::cast(*receiver)->length();
1178 }
else if (receiver->IsJSObject()) {
1179 length = JSObject::cast(*receiver)->elements()->length();
1183 return index >= length;
1186 KeyedAccessLoadMode GetLoadMode(Isolate* isolate, Handle<Object> receiver,
1188 if (IsOutOfBoundsAccess(receiver, index)) {
1189 if (receiver->IsJSTypedArray()) {
1191 return LOAD_IGNORE_OUT_OF_BOUNDS;
1195 if (isolate->IsNoElementsProtectorIntact()) {
1196 if (receiver->IsString()) {
1198 return LOAD_IGNORE_OUT_OF_BOUNDS;
1200 if (receiver->IsJSObject()) {
1205 Handle<Object> receiver_prototype(
1206 JSObject::cast(*receiver)->map()->prototype(), isolate);
1207 if (isolate->IsInAnyContext(*receiver_prototype,
1208 Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
1209 isolate->IsInAnyContext(*receiver_prototype,
1210 Context::INITIAL_OBJECT_PROTOTYPE_INDEX)) {
1211 return LOAD_IGNORE_OUT_OF_BOUNDS;
1216 return STANDARD_LOAD;
1221 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object>
object,
1222 Handle<Object> key) {
1223 if (MigrateDeprecated(
object)) {
1224 Handle<Object> result;
1225 ASSIGN_RETURN_ON_EXCEPTION(
1226 isolate(), result, Runtime::GetObjectProperty(isolate(),
object, key),
1231 Handle<Object> load_handle;
1235 key = TryConvertKey(key, isolate());
1238 if ((key->IsInternalizedString() &&
1239 !String::cast(*key)->AsArrayIndex(&index)) ||
1241 ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
1242 LoadIC::Load(
object, Handle<Name>::cast(key)),
1244 }
else if (ConvertKeyToIndex(
object, key, &index)) {
1245 KeyedAccessLoadMode load_mode = GetLoadMode(isolate(),
object, index);
1246 UpdateLoadElement(Handle<HeapObject>::cast(
object), load_mode);
1247 if (is_vector_set()) {
1248 TraceIC(
"LoadIC", key);
1252 if (vector_needs_update()) {
1253 ConfigureVectorState(MEGAMORPHIC, key);
1254 TraceIC(
"LoadIC", key);
1257 if (!load_handle.is_null())
return load_handle;
1259 Handle<Object> result;
1260 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
1261 Runtime::GetObjectProperty(isolate(),
object, key),
1266 bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
1267 StoreOrigin store_origin) {
1269 Handle<Object>
object = it->GetReceiver();
1270 if (object->IsJSProxy())
return true;
1271 if (!object->IsJSObject())
return false;
1272 Handle<JSObject> receiver = Handle<JSObject>::cast(
object);
1273 DCHECK(!receiver->map()->is_deprecated());
1275 if (it->state() != LookupIterator::TRANSITION) {
1276 for (; it->IsFound(); it->Next()) {
1277 switch (it->state()) {
1278 case LookupIterator::NOT_FOUND:
1279 case LookupIterator::TRANSITION:
1281 case LookupIterator::JSPROXY:
1283 case LookupIterator::INTERCEPTOR: {
1284 Handle<JSObject> holder = it->GetHolder<JSObject>();
1285 InterceptorInfo* info = holder->GetNamedInterceptor();
1286 if (it->HolderIsReceiverOrHiddenPrototype()) {
1287 return !info->non_masking() && receiver.is_identical_to(holder) &&
1288 !info->setter()->IsUndefined(isolate());
1289 }
else if (!info->getter()->IsUndefined(isolate()) ||
1290 !info->query()->IsUndefined(isolate())) {
1295 case LookupIterator::ACCESS_CHECK:
1296 if (it->GetHolder<JSObject>()->IsAccessCheckNeeded())
return false;
1298 case LookupIterator::ACCESSOR:
1299 return !it->IsReadOnly();
1300 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1302 case LookupIterator::DATA: {
1303 if (it->IsReadOnly())
return false;
1304 Handle<JSObject> holder = it->GetHolder<JSObject>();
1305 if (receiver.is_identical_to(holder)) {
1306 it->PrepareForDataProperty(value);
1309 update_receiver_map(receiver);
1314 if (receiver->IsJSGlobalProxy()) {
1315 PrototypeIterator iter(isolate(), receiver);
1316 return it->GetHolder<Object>().is_identical_to(
1317 PrototypeIterator::GetCurrent(iter));
1320 if (it->HolderIsReceiverOrHiddenPrototype())
return false;
1322 if (it->ExtendingNonExtensible(receiver))
return false;
1323 it->PrepareTransitionToDataProperty(receiver, value, NONE,
1325 return it->IsCacheableTransition();
1331 receiver = it->GetStoreTarget<JSObject>();
1332 if (it->ExtendingNonExtensible(receiver))
return false;
1333 it->PrepareTransitionToDataProperty(receiver, value, NONE, store_origin);
1334 return it->IsCacheableTransition();
1337 MaybeHandle<Object> StoreGlobalIC::Store(Handle<Name> name,
1338 Handle<Object> value) {
1339 DCHECK(name->IsString());
1342 Handle<String> str_name = Handle<String>::cast(name);
1343 Handle<JSGlobalObject> global = isolate()->global_object();
1344 Handle<ScriptContextTable> script_contexts(
1345 global->native_context()->script_context_table(), isolate());
1347 ScriptContextTable::LookupResult lookup_result;
1348 if (ScriptContextTable::Lookup(isolate(), script_contexts, str_name,
1350 Handle<Context> script_context = ScriptContextTable::GetContext(
1351 isolate(), script_contexts, lookup_result.context_index);
1352 if (lookup_result.mode == VariableMode::kConst) {
1353 return TypeError(MessageTemplate::kConstAssign, global, name);
1356 Handle<Object> previous_value(script_context->get(lookup_result.slot_index),
1359 if (previous_value->IsTheHole(isolate())) {
1362 return ReferenceError(name);
1366 if (nexus()->ConfigureLexicalVarMode(lookup_result.context_index,
1367 lookup_result.slot_index)) {
1368 TRACE_HANDLER_STATS(isolate(), StoreGlobalIC_StoreScriptContextField);
1371 TRACE_HANDLER_STATS(isolate(), StoreGlobalIC_SlowStub);
1372 PatchCache(name, slow_stub());
1374 TraceIC(
"StoreGlobalIC", name);
1377 script_context->set(lookup_result.slot_index, *value);
1381 return StoreIC::Store(global, name, value);
1384 MaybeHandle<Object> StoreIC::Store(Handle<Object>
object, Handle<Name> name,
1385 Handle<Object> value,
1386 StoreOrigin store_origin) {
1389 if (MigrateDeprecated(
object)) {
1390 Handle<Object> result;
1391 ASSIGN_RETURN_ON_EXCEPTION(
1393 Object::SetProperty(isolate(),
object, name, value, language_mode()),
1400 if (object->IsNullOrUndefined(isolate())) {
1401 if (FLAG_use_ic && state() != PREMONOMORPHIC) {
1403 TRACE_HANDLER_STATS(isolate(), StoreIC_NonReceiver);
1404 update_receiver_map(
object);
1405 PatchCache(name, slow_stub());
1406 TraceIC(
"StoreIC", name);
1408 return TypeError(MessageTemplate::kNonObjectPropertyStore,
object, name);
1411 if (state() != UNINITIALIZED) {
1412 JSObject::MakePrototypesFast(
object, kStartAtPrototype, isolate());
1414 LookupIterator it(isolate(),
object, name);
1415 bool use_ic = FLAG_use_ic;
1417 if (name->IsPrivate()) {
1418 if (name->IsPrivateName() && !it.IsFound()) {
1419 return TypeError(MessageTemplate::kInvalidPrivateFieldAccess,
object,
1425 if (object->IsJSProxy()) {
1429 if (use_ic) UpdateCaches(&it, value, store_origin);
1432 Object::SetProperty(&it, value, language_mode(), store_origin));
1436 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
1437 StoreOrigin store_origin) {
1438 if (state() == UNINITIALIZED && !IsStoreGlobalIC()) {
1441 TRACE_HANDLER_STATS(isolate(), StoreIC_Premonomorphic);
1442 ConfigureVectorState(receiver_map());
1443 TraceIC(
"StoreIC", lookup->name());
1447 MaybeObjectHandle handler;
1448 if (LookupForWrite(lookup, value, store_origin)) {
1449 if (IsStoreGlobalIC()) {
1450 if (lookup->state() == LookupIterator::DATA &&
1451 lookup->GetReceiver().is_identical_to(lookup->GetHolder<Object>())) {
1452 DCHECK(lookup->GetReceiver()->IsJSGlobalObject());
1454 nexus()->ConfigurePropertyCellMode(lookup->GetPropertyCell());
1455 TraceIC(
"StoreGlobalIC", lookup->name());
1459 handler = ComputeHandler(lookup);
1461 set_slow_stub_reason(
"LookupForWrite said 'false'");
1463 handler = MaybeObjectHandle(slow_stub());
1466 PatchCache(lookup->name(), handler);
1467 TraceIC(
"StoreIC", lookup->name());
1470 MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
1471 switch (lookup->state()) {
1472 case LookupIterator::TRANSITION: {
1473 Handle<JSObject> store_target = lookup->GetStoreTarget<JSObject>();
1474 if (store_target->IsJSGlobalObject()) {
1475 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransitionDH);
1477 if (receiver_map()->IsJSGlobalObject()) {
1478 DCHECK(IsStoreGlobalIC());
1480 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1481 DCHECK_EQ(*lookup->GetReceiver(), *holder);
1482 DCHECK_EQ(*store_target, *holder);
1484 return StoreHandler::StoreGlobal(lookup->transition_cell());
1487 Handle<Smi> smi_handler = StoreHandler::StoreGlobalProxy(isolate());
1488 Handle<Object> handler = StoreHandler::StoreThroughPrototype(
1489 isolate(), receiver_map(), store_target, smi_handler,
1490 MaybeObjectHandle::Weak(lookup->transition_cell()));
1491 return MaybeObjectHandle(handler);
1494 DCHECK_IMPLIES(!lookup->transition_map()->is_dictionary_map(),
1495 !receiver_map()->is_dictionary_map());
1497 DCHECK(lookup->IsCacheableTransition());
1499 return StoreHandler::StoreTransition(isolate(), lookup->transition_map());
1502 case LookupIterator::INTERCEPTOR: {
1503 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1506 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate()));
1508 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
1509 return MaybeObjectHandle(BUILTIN_CODE(isolate(), StoreInterceptorIC));
1512 case LookupIterator::ACCESSOR: {
1514 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
1515 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1516 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
1518 if (!holder->HasFastProperties()) {
1519 set_slow_stub_reason(
"accessor on slow map");
1520 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1521 return MaybeObjectHandle(slow_stub());
1523 Handle<Object> accessors = lookup->GetAccessors();
1524 if (accessors->IsAccessorInfo()) {
1525 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
1526 if (v8::ToCData<Address>(info->setter()) == kNullAddress) {
1527 set_slow_stub_reason(
"setter == kNullAddress");
1528 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1529 return MaybeObjectHandle(slow_stub());
1531 if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
1532 !lookup->HolderIsReceiverOrHiddenPrototype()) {
1533 set_slow_stub_reason(
"special data property in prototype chain");
1534 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1535 return MaybeObjectHandle(slow_stub());
1537 if (!AccessorInfo::IsCompatibleReceiverMap(info, receiver_map())) {
1538 set_slow_stub_reason(
"incompatible receiver type");
1539 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1540 return MaybeObjectHandle(slow_stub());
1543 Handle<Smi> smi_handler = StoreHandler::StoreNativeDataProperty(
1544 isolate(), lookup->GetAccessorIndex());
1545 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNativeDataPropertyDH);
1546 if (receiver.is_identical_to(holder)) {
1547 return MaybeObjectHandle(smi_handler);
1549 TRACE_HANDLER_STATS(isolate(),
1550 StoreIC_StoreNativeDataPropertyOnPrototypeDH);
1551 return MaybeObjectHandle(StoreHandler::StoreThroughPrototype(
1552 isolate(), receiver_map(), holder, smi_handler));
1554 }
else if (accessors->IsAccessorPair()) {
1555 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
1557 if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
1558 set_slow_stub_reason(
"setter not a function");
1559 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1560 return MaybeObjectHandle(slow_stub());
1563 if (setter->IsFunctionTemplateInfo() &&
1564 FunctionTemplateInfo::cast(*setter)->BreakAtEntry()) {
1566 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1567 return MaybeObjectHandle(slow_stub());
1570 CallOptimization call_optimization(isolate(), setter);
1571 if (call_optimization.is_simple_api_call()) {
1572 if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
1573 CallOptimization::HolderLookup holder_lookup;
1574 call_optimization.LookupHolderOfExpectedType(receiver_map(),
1577 Handle<Smi> smi_handler = StoreHandler::StoreApiSetter(
1579 holder_lookup == CallOptimization::kHolderIsReceiver);
1581 Handle<Context> context(
1582 call_optimization.GetAccessorContext(holder->map()), isolate());
1583 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreApiSetterOnPrototypeDH);
1584 return MaybeObjectHandle(StoreHandler::StoreThroughPrototype(
1585 isolate(), receiver_map(), holder, smi_handler,
1586 MaybeObjectHandle::Weak(call_optimization.api_call_info()),
1587 MaybeObjectHandle::Weak(context)));
1589 set_slow_stub_reason(
"incompatible receiver");
1590 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1591 return MaybeObjectHandle(slow_stub());
1592 }
else if (setter->IsFunctionTemplateInfo()) {
1593 set_slow_stub_reason(
"setter non-simple template");
1594 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1595 return MaybeObjectHandle(slow_stub());
1598 Handle<Smi> smi_handler =
1599 StoreHandler::StoreAccessor(isolate(), lookup->GetAccessorIndex());
1601 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorDH);
1602 if (receiver.is_identical_to(holder)) {
1603 return MaybeObjectHandle(smi_handler);
1605 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorOnPrototypeDH);
1607 return MaybeObjectHandle(StoreHandler::StoreThroughPrototype(
1608 isolate(), receiver_map(), holder, smi_handler));
1610 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1611 return MaybeObjectHandle(slow_stub());
1614 case LookupIterator::DATA: {
1616 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
1618 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1619 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
1621 DCHECK_EQ(kData, lookup->property_details().kind());
1622 if (lookup->is_dictionary_holder()) {
1623 if (holder->IsJSGlobalObject()) {
1624 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalDH);
1625 return MaybeObjectHandle(
1626 StoreHandler::StoreGlobal(lookup->GetPropertyCell()));
1628 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
1629 DCHECK(holder.is_identical_to(receiver));
1630 return MaybeObjectHandle(StoreHandler::StoreNormal(isolate()));
1634 if (lookup->property_details().location() == kField) {
1635 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldDH);
1636 int descriptor = lookup->GetFieldDescriptorIndex();
1637 FieldIndex index = lookup->GetFieldIndex();
1638 PropertyConstness constness = lookup->constness();
1639 if (constness == PropertyConstness::kConst &&
1640 IsStoreOwnICKind(nexus()->kind())) {
1644 constness = PropertyConstness::kMutable;
1646 return MaybeObjectHandle(StoreHandler::StoreField(
1647 isolate(), descriptor, index, constness, lookup->representation()));
1651 DCHECK_EQ(kDescriptor, lookup->property_details().location());
1652 set_slow_stub_reason(
"constant property");
1653 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1654 return MaybeObjectHandle(slow_stub());
1656 case LookupIterator::JSPROXY: {
1657 Handle<JSReceiver> receiver =
1658 Handle<JSReceiver>::cast(lookup->GetReceiver());
1659 Handle<JSProxy> holder = lookup->GetHolder<JSProxy>();
1660 return MaybeObjectHandle(StoreHandler::StoreProxy(
1661 isolate(), receiver_map(), holder, receiver));
1664 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1665 case LookupIterator::ACCESS_CHECK:
1666 case LookupIterator::NOT_FOUND:
1669 return MaybeObjectHandle();
1672 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1673 KeyedAccessStoreMode store_mode,
1674 bool receiver_was_cow) {
1675 MapHandles target_receiver_maps;
1676 TargetMaps(&target_receiver_maps);
1677 if (target_receiver_maps.empty()) {
1678 Handle<Map> monomorphic_map =
1679 ComputeTransitionedMap(receiver_map, store_mode);
1680 store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow);
1681 Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode);
1682 return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
1685 for (Handle<Map> map : target_receiver_maps) {
1686 if (!map.is_null() && map->instance_type() == JS_VALUE_TYPE) {
1687 DCHECK(!IsStoreInArrayLiteralICKind(kind()));
1688 set_slow_stub_reason(
"JSValue");
1697 KeyedAccessStoreMode old_store_mode;
1698 old_store_mode = GetKeyedAccessStoreMode();
1699 Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1700 if (state() == MONOMORPHIC) {
1701 Handle<Map> transitioned_receiver_map = receiver_map;
1702 if (IsTransitionStoreMode(store_mode)) {
1703 transitioned_receiver_map =
1704 ComputeTransitionedMap(receiver_map, store_mode);
1706 if ((receiver_map.is_identical_to(previous_receiver_map) &&
1707 IsTransitionStoreMode(store_mode)) ||
1708 IsTransitionOfMonomorphicTarget(*previous_receiver_map,
1709 *transitioned_receiver_map)) {
1713 store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow);
1714 Handle<Object> handler =
1715 StoreElementHandler(transitioned_receiver_map, store_mode);
1716 ConfigureVectorState(Handle<Name>(), transitioned_receiver_map, handler);
1719 if (receiver_map.is_identical_to(previous_receiver_map) &&
1720 old_store_mode == STANDARD_STORE &&
1721 (store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW ||
1722 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1723 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1727 Handle<Object> handler = StoreElementHandler(receiver_map, store_mode);
1728 return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
1732 DCHECK(state() != GENERIC);
1735 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1737 if (IsTransitionStoreMode(store_mode)) {
1738 Handle<Map> transitioned_receiver_map =
1739 ComputeTransitionedMap(receiver_map, store_mode);
1740 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
1741 transitioned_receiver_map);
1747 set_slow_stub_reason(
"same map added twice");
1753 if (target_receiver_maps.size() > kMaxKeyedPolymorphism)
return;
1757 store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow);
1758 if (old_store_mode != STANDARD_STORE) {
1759 if (store_mode == STANDARD_STORE) {
1760 store_mode = old_store_mode;
1761 }
else if (store_mode != old_store_mode) {
1762 set_slow_stub_reason(
"store mode mismatch");
1770 if (store_mode != STANDARD_STORE) {
1771 size_t external_arrays = 0;
1772 for (Handle<Map> map : target_receiver_maps) {
1773 if (map->has_fixed_typed_array_elements()) {
1774 DCHECK(!IsStoreInArrayLiteralICKind(kind()));
1778 if (external_arrays != 0 &&
1779 external_arrays != target_receiver_maps.size()) {
1780 DCHECK(!IsStoreInArrayLiteralICKind(kind()));
1781 set_slow_stub_reason(
1782 "unsupported combination of external and normal arrays");
1787 MaybeObjectHandles handlers;
1788 handlers.reserve(target_receiver_maps.size());
1789 StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode);
1790 if (target_receiver_maps.size() == 0) {
1794 ConfigureVectorState(receiver_map);
1795 }
else if (target_receiver_maps.size() == 1) {
1796 ConfigureVectorState(Handle<Name>(), target_receiver_maps[0], handlers[0]);
1798 ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
1803 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
1804 Handle<Map> map, KeyedAccessStoreMode store_mode) {
1805 switch (store_mode) {
1806 case STORE_TRANSITION_TO_OBJECT:
1807 case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
1808 ElementsKind kind = IsHoleyElementsKind(map->elements_kind())
1811 return Map::TransitionElementsTo(isolate(), map, kind);
1813 case STORE_TRANSITION_TO_DOUBLE:
1814 case STORE_AND_GROW_TRANSITION_TO_DOUBLE: {
1815 ElementsKind kind = IsHoleyElementsKind(map->elements_kind())
1816 ? HOLEY_DOUBLE_ELEMENTS
1817 : PACKED_DOUBLE_ELEMENTS;
1818 return Map::TransitionElementsTo(isolate(), map, kind);
1820 case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
1821 DCHECK(map->has_fixed_typed_array_elements());
1823 case STORE_NO_TRANSITION_HANDLE_COW:
1824 case STANDARD_STORE:
1825 case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW:
1831 Handle<Object> KeyedStoreIC::StoreElementHandler(
1832 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
1833 DCHECK(store_mode == STANDARD_STORE ||
1834 store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW ||
1835 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1836 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
1838 receiver_map->DictionaryElementsInPrototypeChainOnly(isolate()),
1839 IsStoreInArrayLiteralICKind(kind()));
1841 if (receiver_map->IsJSProxyMap()) {
1842 return StoreHandler::StoreProxy(isolate());
1847 if (receiver_map->has_sloppy_arguments_elements()) {
1849 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
1851 CodeFactory::KeyedStoreIC_SloppyArguments(isolate(), store_mode).code();
1852 }
else if (receiver_map->has_fast_elements() ||
1853 receiver_map->has_fixed_typed_array_elements()) {
1854 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
1855 code = CodeFactory::StoreFastElementIC(isolate(), store_mode).code();
1856 if (receiver_map->has_fixed_typed_array_elements())
return code;
1857 }
else if (IsStoreInArrayLiteralICKind(kind())) {
1859 TRACE_HANDLER_STATS(isolate(), StoreInArrayLiteralIC_SlowStub);
1861 CodeFactory::StoreInArrayLiteralIC_Slow(isolate(), store_mode).code();
1864 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
1865 DCHECK_EQ(DICTIONARY_ELEMENTS, receiver_map->elements_kind());
1866 code = CodeFactory::KeyedStoreIC_Slow(isolate(), store_mode).code();
1869 if (IsStoreInArrayLiteralICKind(kind()))
return code;
1871 Handle<Object> validity_cell =
1872 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
1873 if (validity_cell->IsSmi()) {
1877 Handle<StoreHandler> handler = isolate()->factory()->NewStoreHandler(0);
1878 handler->set_validity_cell(*validity_cell);
1879 handler->set_smi_handler(*code);
1883 void KeyedStoreIC::StoreElementPolymorphicHandlers(
1884 MapHandles* receiver_maps, MaybeObjectHandles* handlers,
1885 KeyedAccessStoreMode store_mode) {
1886 DCHECK(store_mode == STANDARD_STORE ||
1887 store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW ||
1888 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1889 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
1892 receiver_maps->erase(
1894 receiver_maps->begin(), receiver_maps->end(),
1895 [](
const Handle<Map>& map) {
return map->is_deprecated(); }),
1896 receiver_maps->end());
1898 for (Handle<Map> receiver_map : *receiver_maps) {
1899 Handle<Object> handler;
1900 Handle<Map> transition;
1902 if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE ||
1903 receiver_map->DictionaryElementsInPrototypeChainOnly(isolate())) {
1906 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub);
1907 handler = slow_stub();
1911 Map tmap = receiver_map->FindElementsKindTransitionedMap(
1912 isolate(), *receiver_maps);
1913 if (!tmap.is_null()) {
1914 if (receiver_map->is_stable()) {
1915 receiver_map->NotifyLeafMapLayoutChange(isolate());
1917 transition = handle(tmap, isolate());
1926 if (!transition.is_null()) {
1927 TRACE_HANDLER_STATS(isolate(),
1928 KeyedStoreIC_ElementsTransitionAndStoreStub);
1929 handler = StoreHandler::StoreElementTransition(isolate(), receiver_map,
1930 transition, store_mode);
1932 handler = StoreElementHandler(receiver_map, store_mode);
1935 DCHECK(!handler.is_null());
1936 handlers->push_back(MaybeObjectHandle(handler));
1941 static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
1942 uint32_t index, Handle<Object> value) {
1943 bool oob_access = IsOutOfBoundsAccess(receiver, index);
1946 bool allow_growth = receiver->IsJSArray() && oob_access &&
1947 !receiver->WouldConvertToSlowElements(index);
1950 if (receiver->HasSmiElements()) {
1951 if (value->IsHeapNumber()) {
1952 return STORE_AND_GROW_TRANSITION_TO_DOUBLE;
1954 if (value->IsHeapObject()) {
1955 return STORE_AND_GROW_TRANSITION_TO_OBJECT;
1957 }
else if (receiver->HasDoubleElements()) {
1958 if (!value->IsSmi() && !value->IsHeapNumber()) {
1959 return STORE_AND_GROW_TRANSITION_TO_OBJECT;
1962 return STORE_AND_GROW_NO_TRANSITION_HANDLE_COW;
1965 if (receiver->HasSmiElements()) {
1966 if (value->IsHeapNumber()) {
1967 return STORE_TRANSITION_TO_DOUBLE;
1968 }
else if (value->IsHeapObject()) {
1969 return STORE_TRANSITION_TO_OBJECT;
1971 }
else if (receiver->HasDoubleElements()) {
1972 if (!value->IsSmi() && !value->IsHeapNumber()) {
1973 return STORE_TRANSITION_TO_OBJECT;
1976 if (!FLAG_trace_external_array_abuse &&
1977 receiver->map()->has_fixed_typed_array_elements() && oob_access) {
1978 return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
1980 return receiver->elements()->IsCowArray() ? STORE_NO_TRANSITION_HANDLE_COW
1986 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object>
object,
1988 Handle<Object> value) {
1991 if (MigrateDeprecated(
object)) {
1992 Handle<Object> result;
1993 ASSIGN_RETURN_ON_EXCEPTION(
1995 Runtime::SetObjectProperty(isolate(),
object, key, value,
1996 language_mode(), StoreOrigin::kMaybeKeyed),
2003 key = TryConvertKey(key, isolate());
2005 Handle<Object> store_handle;
2008 if ((key->IsInternalizedString() &&
2009 !String::cast(*key)->AsArrayIndex(&index)) ||
2011 ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
2012 StoreIC::Store(
object, Handle<Name>::cast(key),
2013 value, StoreOrigin::kMaybeKeyed),
2015 if (vector_needs_update()) {
2016 if (ConfigureVectorState(MEGAMORPHIC, key)) {
2017 set_slow_stub_reason(
"unhandled internalized string key");
2018 TraceIC(
"StoreIC", key);
2021 return store_handle;
2024 JSObject::MakePrototypesFast(
object, kStartAtPrototype, isolate());
2026 bool use_ic = FLAG_use_ic && !
object->IsStringWrapper() &&
2027 !
object->IsAccessCheckNeeded() && !
object->IsJSGlobalProxy();
2028 if (use_ic && !object->IsSmi()) {
2032 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(
object);
2033 if (heap_object->map()->IsMapInArrayPrototypeChain(isolate())) {
2034 set_slow_stub_reason(
"map in array prototype");
2039 Handle<Map> old_receiver_map;
2040 bool is_arguments =
false;
2041 bool key_is_valid_index =
false;
2042 KeyedAccessStoreMode store_mode = STANDARD_STORE;
2043 if (use_ic && object->IsJSReceiver()) {
2044 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(
object);
2045 old_receiver_map = handle(receiver->map(), isolate());
2046 is_arguments = receiver->IsJSArgumentsObject();
2047 bool is_proxy = receiver->IsJSProxy();
2053 key_is_valid_index =
2054 key->IsSmi() && (Smi::ToInt(*key) >= 0 ||
object->IsJSTypedArray());
2055 if (!is_arguments && !is_proxy) {
2056 if (key_is_valid_index) {
2058 Handle<JSObject> receiver_object = Handle<JSObject>::cast(
object);
2059 store_mode = GetStoreMode(receiver_object, index, value);
2064 DCHECK(store_handle.is_null());
2065 bool receiver_was_cow =
2066 object->IsJSArray() &&
2067 Handle<JSArray>::cast(
object)->elements()->IsCowArray();
2068 ASSIGN_RETURN_ON_EXCEPTION(
2069 isolate(), store_handle,
2070 Runtime::SetObjectProperty(isolate(),
object, key, value, language_mode(),
2071 StoreOrigin::kMaybeKeyed),
2075 if (!old_receiver_map.is_null()) {
2077 set_slow_stub_reason(
"arguments receiver");
2078 }
else if (key_is_valid_index) {
2079 if (old_receiver_map->is_abandoned_prototype_map()) {
2080 set_slow_stub_reason(
"receiver with prototype map");
2081 }
else if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly(
2087 UpdateStoreElement(old_receiver_map, store_mode, receiver_was_cow);
2089 set_slow_stub_reason(
"dictionary or proxy prototype");
2092 set_slow_stub_reason(
"non-smi-like key");
2095 set_slow_stub_reason(
"non-JSObject receiver");
2099 if (vector_needs_update()) {
2100 ConfigureVectorState(MEGAMORPHIC, key);
2102 TraceIC(
"StoreIC", key);
2104 return store_handle;
2108 void StoreOwnElement(Isolate* isolate, Handle<JSArray> array,
2109 Handle<Object> index, Handle<Object> value) {
2110 DCHECK(index->IsNumber());
2111 bool success =
false;
2112 LookupIterator it = LookupIterator::PropertyOrElement(
2113 isolate, array, index, &success, LookupIterator::OWN);
2116 CHECK(JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE,
2122 void StoreInArrayLiteralIC::Store(Handle<JSArray> array, Handle<Object> index,
2123 Handle<Object> value) {
2124 DCHECK(!array->map()->IsMapInArrayPrototypeChain(isolate()));
2125 DCHECK(index->IsNumber());
2127 if (!FLAG_use_ic || MigrateDeprecated(array)) {
2128 StoreOwnElement(isolate(), array, index, value);
2129 TraceIC(
"StoreInArrayLiteralIC", index);
2135 KeyedAccessStoreMode store_mode = STANDARD_STORE;
2136 if (index->IsSmi()) {
2137 DCHECK_GE(Smi::ToInt(*index), 0);
2139 store_mode = GetStoreMode(array, index32, value);
2142 Handle<Map> old_array_map(array->map(), isolate());
2143 bool array_was_cow = array->elements()->IsCowArray();
2144 StoreOwnElement(isolate(), array, index, value);
2146 if (index->IsSmi()) {
2147 DCHECK(!old_array_map->is_abandoned_prototype_map());
2148 UpdateStoreElement(old_array_map, store_mode, array_was_cow);
2150 set_slow_stub_reason(
"index out of Smi range");
2153 if (vector_needs_update()) {
2154 ConfigureVectorState(MEGAMORPHIC, index);
2156 TraceIC(
"StoreInArrayLiteralIC", index);
2163 RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
2164 HandleScope scope(isolate);
2165 DCHECK_EQ(4, args.length());
2167 Handle<Object> receiver = args.at(0);
2168 Handle<Name> key = args.at<Name>(1);
2169 Handle<Smi> slot = args.at<Smi>(2);
2170 Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
2171 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2175 FeedbackSlotKind kind = vector->GetKind(vector_slot);
2176 if (IsLoadICKind(kind)) {
2177 LoadIC ic(isolate, vector, vector_slot);
2178 ic.UpdateState(receiver, key);
2179 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
2181 }
else if (IsLoadGlobalICKind(kind)) {
2182 DCHECK_EQ(isolate->native_context()->global_proxy(), *receiver);
2183 receiver = isolate->global_object();
2184 LoadGlobalIC ic(isolate, vector, vector_slot);
2185 ic.UpdateState(receiver, key);
2186 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key));
2189 DCHECK(IsKeyedLoadICKind(kind));
2190 KeyedLoadIC ic(isolate, vector, vector_slot);
2191 ic.UpdateState(receiver, key);
2192 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
2196 RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
2197 HandleScope scope(isolate);
2198 DCHECK_EQ(3, args.length());
2200 Handle<JSGlobalObject> global = isolate->global_object();
2201 Handle<String> name = args.at<String>(0);
2202 Handle<Smi> slot = args.at<Smi>(1);
2203 Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
2204 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2206 LoadGlobalIC ic(isolate, vector, vector_slot);
2207 ic.UpdateState(global, name);
2209 Handle<Object> result;
2210 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(name));
2214 RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
2215 HandleScope scope(isolate);
2216 DCHECK_EQ(3, args.length());
2217 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2219 Handle<Context> native_context = isolate->native_context();
2220 Handle<ScriptContextTable> script_contexts(
2221 native_context->script_context_table(), isolate);
2223 ScriptContextTable::LookupResult lookup_result;
2224 if (ScriptContextTable::Lookup(isolate, script_contexts, name,
2226 Handle<Context> script_context = ScriptContextTable::GetContext(
2227 isolate, script_contexts, lookup_result.context_index);
2228 Handle<Object> result(script_context->get(lookup_result.slot_index),
2230 if (*result == ReadOnlyRoots(isolate).the_hole_value()) {
2231 THROW_NEW_ERROR_RETURN_FAILURE(
2232 isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
2237 Handle<JSGlobalObject> global(native_context->global_object(), isolate);
2238 Handle<Object> result;
2239 bool is_found =
false;
2240 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2242 Runtime::GetObjectProperty(isolate, global, name, &is_found));
2244 Handle<Smi> slot = args.at<Smi>(1);
2245 Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
2246 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2247 FeedbackSlotKind kind = vector->GetKind(vector_slot);
2250 if (LoadIC::ShouldThrowReferenceError(kind)) {
2251 THROW_NEW_ERROR_RETURN_FAILURE(
2252 isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
2258 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
2259 HandleScope scope(isolate);
2260 DCHECK_EQ(4, args.length());
2262 Handle<Object> receiver = args.at(0);
2263 Handle<Object> key = args.at(1);
2264 Handle<Smi> slot = args.at<Smi>(2);
2265 Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
2266 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2267 KeyedLoadIC ic(isolate, vector, vector_slot);
2268 ic.UpdateState(receiver, key);
2269 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
2272 RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
2273 HandleScope scope(isolate);
2274 DCHECK_EQ(5, args.length());
2276 Handle<Object> value = args.at(0);
2277 Handle<Smi> slot = args.at<Smi>(1);
2278 Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
2279 Handle<Object> receiver = args.at(3);
2280 Handle<Name> key = args.at<Name>(4);
2281 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2282 FeedbackSlotKind kind = vector->GetKind(vector_slot);
2283 if (IsStoreICKind(kind) || IsStoreOwnICKind(kind)) {
2284 StoreIC ic(isolate, vector, vector_slot);
2285 ic.UpdateState(receiver, key);
2286 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
2287 }
else if (IsStoreGlobalICKind(kind)) {
2288 DCHECK_EQ(isolate->native_context()->global_proxy(), *receiver);
2289 receiver = isolate->global_object();
2290 StoreGlobalIC ic(isolate, vector, vector_slot);
2291 ic.UpdateState(receiver, key);
2292 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(key, value));
2294 DCHECK(IsKeyedStoreICKind(kind));
2295 KeyedStoreIC ic(isolate, vector, vector_slot);
2296 ic.UpdateState(receiver, key);
2297 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
2301 RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Miss) {
2302 HandleScope scope(isolate);
2303 DCHECK_EQ(4, args.length());
2305 Handle<Object> value = args.at(0);
2306 Handle<Smi> slot = args.at<Smi>(1);
2307 Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
2308 Handle<Name> key = args.at<Name>(3);
2309 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2310 StoreGlobalIC ic(isolate, vector, vector_slot);
2311 Handle<JSGlobalObject> global = isolate->global_object();
2312 ic.UpdateState(global, key);
2313 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(key, value));
2316 RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Slow) {
2317 HandleScope scope(isolate);
2318 DCHECK_EQ(5, args.length());
2320 Handle<Object> value = args.at(0);
2321 Handle<Smi> slot = args.at<Smi>(1);
2322 Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
2323 CONVERT_ARG_HANDLE_CHECKED(String, name, 4);
2327 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2328 FeedbackSlotKind slot_kind = vector->GetKind(vector_slot);
2329 DCHECK(IsStoreGlobalICKind(slot_kind));
2330 Handle<Object> receiver = args.at(3);
2331 DCHECK(receiver->IsJSGlobalProxy());
2335 Handle<JSGlobalObject> global = isolate->global_object();
2336 Handle<Context> native_context = isolate->native_context();
2337 Handle<ScriptContextTable> script_contexts(
2338 native_context->script_context_table(), isolate);
2340 ScriptContextTable::LookupResult lookup_result;
2341 if (ScriptContextTable::Lookup(isolate, script_contexts, name,
2343 Handle<Context> script_context = ScriptContextTable::GetContext(
2344 isolate, script_contexts, lookup_result.context_index);
2345 if (lookup_result.mode == VariableMode::kConst) {
2346 THROW_NEW_ERROR_RETURN_FAILURE(
2347 isolate, NewTypeError(MessageTemplate::kConstAssign, global, name));
2350 Handle<Object> previous_value(script_context->get(lookup_result.slot_index),
2353 if (previous_value->IsTheHole(isolate)) {
2354 THROW_NEW_ERROR_RETURN_FAILURE(
2355 isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
2358 script_context->set(lookup_result.slot_index, *value);
2362 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2363 LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
2364 RETURN_RESULT_OR_FAILURE(
2366 Runtime::SetObjectProperty(isolate, global, name, value, language_mode,
2367 StoreOrigin::kMaybeKeyed));
2370 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
2371 HandleScope scope(isolate);
2372 DCHECK_EQ(5, args.length());
2374 Handle<Object> value = args.at(0);
2375 Handle<Smi> slot = args.at<Smi>(1);
2376 Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
2377 Handle<Object> receiver = args.at(3);
2378 Handle<Object> key = args.at(4);
2379 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2380 FeedbackSlotKind kind = vector->GetKind(vector_slot);
2384 if (IsKeyedStoreICKind(kind)) {
2385 KeyedStoreIC ic(isolate, vector, vector_slot);
2386 ic.UpdateState(receiver, key);
2387 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
2389 DCHECK(IsStoreInArrayLiteralICKind(kind));
2390 DCHECK(receiver->IsJSArray());
2391 DCHECK(key->IsNumber());
2392 StoreInArrayLiteralIC ic(isolate, vector, vector_slot);
2393 ic.UpdateState(receiver, key);
2394 ic.Store(Handle<JSArray>::cast(receiver), key, value);
2399 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
2400 HandleScope scope(isolate);
2401 DCHECK_EQ(5, args.length());
2403 Handle<Object> value = args.at(0);
2404 Handle<Smi> slot = args.at<Smi>(1);
2405 Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
2406 Handle<Object>
object = args.at(3);
2407 Handle<Object> key = args.at(4);
2408 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2409 FeedbackSlotKind kind = vector->GetKind(vector_slot);
2410 DCHECK(IsStoreICKind(kind) || IsKeyedStoreICKind(kind));
2411 LanguageMode language_mode = GetLanguageModeFromSlotKind(kind);
2412 RETURN_RESULT_OR_FAILURE(
2414 Runtime::SetObjectProperty(isolate,
object, key, value, language_mode,
2415 StoreOrigin::kMaybeKeyed));
2418 RUNTIME_FUNCTION(Runtime_StoreInArrayLiteralIC_Slow) {
2419 HandleScope scope(isolate);
2420 DCHECK_EQ(3, args.length());
2422 Handle<Object> value = args.at(0);
2423 Handle<Object> array = args.at(1);
2424 Handle<Object> index = args.at(2);
2425 StoreOwnElement(isolate, Handle<JSArray>::cast(array), index, value);
2429 RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
2430 HandleScope scope(isolate);
2431 DCHECK_EQ(6, args.length());
2433 Handle<Object>
object = args.at(0);
2434 Handle<Object> key = args.at(1);
2435 Handle<Object> value = args.at(2);
2436 Handle<Map> map = args.at<Map>(3);
2437 Handle<Smi> slot = args.at<Smi>(4);
2438 Handle<FeedbackVector> vector = args.at<FeedbackVector>(5);
2439 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2440 FeedbackSlotKind kind = vector->GetKind(vector_slot);
2442 if (object->IsJSObject()) {
2443 JSObject::TransitionElementsKind(Handle<JSObject>::cast(
object),
2444 map->elements_kind());
2447 if (IsStoreInArrayLiteralICKind(kind)) {
2448 StoreOwnElement(isolate, Handle<JSArray>::cast(
object), key, value);
2451 DCHECK(IsKeyedStoreICKind(kind) || IsStoreICKind(kind));
2452 LanguageMode language_mode = GetLanguageModeFromSlotKind(kind);
2453 RETURN_RESULT_OR_FAILURE(
2455 Runtime::SetObjectProperty(isolate,
object, key, value, language_mode,
2456 StoreOrigin::kMaybeKeyed));
2460 static bool CanFastCloneObject(Handle<Map> map) {
2461 DisallowHeapAllocation no_gc;
2462 if (map->IsNullOrUndefinedMap())
return true;
2463 if (!map->IsJSObjectMap() ||
2464 !IsSmiOrObjectElementsKind(map->elements_kind()) ||
2465 !map->OnlyHasSimpleProperties()) {
2469 DescriptorArray* descriptors = map->instance_descriptors();
2470 for (
int i = 0;
i < map->NumberOfOwnDescriptors();
i++) {
2471 PropertyDetails details = descriptors->GetDetails(
i);
2472 Name key = descriptors->GetKey(
i);
2473 if (details.kind() != kData || !details.IsEnumerable() ||
2474 key->IsPrivateName()) {
2482 static Handle<Map> FastCloneObjectMap(Isolate* isolate,
2483 Handle<HeapObject> source,
int flags) {
2484 Handle<Map> source_map(source->map(), isolate);
2485 SLOW_DCHECK(source->IsNullOrUndefined() || CanFastCloneObject(source_map));
2486 Handle<JSFunction> constructor(isolate->native_context()->object_function(),
2488 DCHECK(constructor->has_initial_map());
2489 Handle<Map> initial_map(constructor->initial_map(), isolate);
2490 Handle<Map> map = initial_map;
2492 if (source_map->IsJSObjectMap() && source_map->GetInObjectProperties() !=
2493 initial_map->GetInObjectProperties()) {
2494 int inobject_properties = source_map->GetInObjectProperties();
2496 JSObject::kHeaderSize + kPointerSize * inobject_properties;
2497 int unused = source_map->UnusedInObjectProperties();
2498 DCHECK(instance_size <= JSObject::kMaxInstanceSize);
2499 map = Map::CopyInitialMap(isolate, map, instance_size, inobject_properties,
2503 if (flags & ObjectLiteral::kHasNullPrototype) {
2504 if (map.is_identical_to(initial_map)) {
2505 map = Map::Copy(isolate, map,
"ObjectWithNullProto");
2507 Map::SetPrototype(isolate, map, isolate->factory()->null_value());
2510 if (source->IsNullOrUndefined() || !source_map->NumberOfOwnDescriptors()) {
2514 if (map.is_identical_to(initial_map)) {
2515 map = Map::Copy(isolate, map,
"InitializeClonedDescriptors");
2518 Handle<DescriptorArray> source_descriptors(source_map->instance_descriptors(),
2520 int size = source_map->NumberOfOwnDescriptors();
2522 Handle<DescriptorArray> descriptors = DescriptorArray::CopyForFastObjectClone(
2523 isolate, source_descriptors, size, slack);
2524 Handle<LayoutDescriptor> layout =
2525 LayoutDescriptor::New(isolate, map, descriptors, size);
2526 map->InitializeDescriptors(*descriptors, *layout);
2527 map->CopyUnusedPropertyFieldsAdjustedForInstanceSize(*source_map);
2530 map->set_may_have_interesting_symbols(
2531 source_map->may_have_interesting_symbols());
2536 static MaybeHandle<JSObject> CloneObjectSlowPath(Isolate* isolate,
2537 Handle<HeapObject> source,
2539 Handle<JSObject> new_object;
2540 if (flags & ObjectLiteral::kHasNullPrototype) {
2541 new_object = isolate->factory()->NewJSObjectWithNullProto();
2543 Handle<JSFunction> constructor(isolate->native_context()->object_function(),
2545 new_object = isolate->factory()->NewJSObject(constructor);
2548 if (source->IsNullOrUndefined()) {
2552 MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(isolate, new_object, source,
2554 MaybeHandle<JSObject>());
2558 RUNTIME_FUNCTION(Runtime_CloneObjectIC_Miss) {
2559 HandleScope scope(isolate);
2560 DCHECK_EQ(4, args.length());
2561 Handle<HeapObject> source = args.at<HeapObject>(0);
2562 int flags = args.smi_at(1);
2564 MigrateDeprecated(source);
2566 FeedbackSlot slot = FeedbackVector::ToSlot(args.smi_at(2));
2567 Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
2569 FeedbackNexus nexus(vector, slot);
2570 Handle<Map> source_map(source->map(), isolate);
2572 if (!CanFastCloneObject(source_map) || nexus.IsMegamorphic()) {
2574 nexus.ConfigureMegamorphic();
2575 RETURN_RESULT_OR_FAILURE(isolate,
2576 CloneObjectSlowPath(isolate, source, flags));
2579 Handle<Map> result_map = FastCloneObjectMap(isolate, source, flags);
2580 nexus.ConfigureCloneObject(source_map, result_map);
2585 RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
2586 Handle<JSObject> receiver = args.at<JSObject>(0);
2587 Handle<JSObject> holder = args.at<JSObject>(1);
2588 Handle<AccessorInfo> info = args.at<AccessorInfo>(2);
2589 Handle<Name> name = args.at<Name>(3);
2590 Handle<Object> value = args.at(4);
2591 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 5);
2592 HandleScope scope(isolate);
2594 if (V8_UNLIKELY(FLAG_runtime_stats)) {
2595 RETURN_RESULT_OR_FAILURE(
2597 Runtime::SetObjectProperty(isolate, receiver, name, value,
2598 language_mode, StoreOrigin::kMaybeKeyed));
2601 DCHECK(info->IsCompatibleReceiver(*receiver));
2603 ShouldThrow should_throw =
2604 is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
2605 PropertyCallbackArguments arguments(isolate, info->data(), *receiver, *holder,
2607 arguments.CallAccessorSetter(info, name, value);
2608 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2612 RUNTIME_FUNCTION(Runtime_LoadCallbackProperty) {
2613 Handle<JSObject> receiver = args.at<JSObject>(0);
2614 Handle<JSObject> holder = args.at<JSObject>(1);
2615 Handle<AccessorInfo> info = args.at<AccessorInfo>(2);
2616 Handle<Name> name = args.at<Name>(3);
2617 HandleScope scope(isolate);
2619 DCHECK(info->IsCompatibleReceiver(*receiver));
2621 PropertyCallbackArguments custom_args(isolate, info->data(), *receiver,
2622 *holder, kThrowOnError);
2623 Handle<Object> result = custom_args.CallAccessorGetter(info, name);
2624 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2625 if (result.is_null())
return ReadOnlyRoots(isolate).undefined_value();
2629 RUNTIME_FUNCTION(Runtime_LoadAccessorProperty) {
2630 HandleScope scope(isolate);
2631 DCHECK_EQ(args.length(), 3);
2632 Handle<JSObject> receiver = args.at<JSObject>(0);
2633 int handler_kind = args.smi_at(1);
2634 Handle<CallHandlerInfo> call_handler_info = args.at<CallHandlerInfo>(2);
2636 Object* holder = *receiver;
2637 if (handler_kind == LoadHandler::kApiGetterHolderIsPrototype) {
2638 holder = receiver->map()->prototype();
2640 DCHECK_EQ(handler_kind, LoadHandler::kApiGetter);
2644 FunctionCallbackArguments custom(isolate, call_handler_info->data(),
2645 *receiver, holder,
nullptr,
nullptr, 0);
2646 Handle<Object> result_handle = custom.Call(*call_handler_info);
2647 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2648 if (result_handle.is_null())
return ReadOnlyRoots(isolate).undefined_value();
2649 return *result_handle;
2656 RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
2657 HandleScope scope(isolate);
2658 DCHECK_EQ(5, args.length());
2659 Handle<Name> name = args.at<Name>(0);
2660 Handle<Object> receiver = args.at(1);
2661 Handle<JSObject> holder = args.at<JSObject>(2);
2663 if (!receiver->IsJSReceiver()) {
2664 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2665 isolate, receiver, Object::ConvertReceiver(isolate, receiver));
2668 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor(), isolate);
2669 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
2670 *holder, kDontThrow);
2671 Handle<Object> result = arguments.CallNamedGetter(interceptor, name);
2673 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2675 if (!result.is_null())
return *result;
2677 LookupIterator it(receiver, name, holder);
2679 while (it.state() != LookupIterator::INTERCEPTOR ||
2680 !it.GetHolder<JSObject>().is_identical_to(holder)) {
2681 DCHECK(it.state() != LookupIterator::ACCESS_CHECK || it.HasAccess());
2686 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
2688 if (it.IsFound())
return *result;
2690 Handle<Smi> slot = args.at<Smi>(3);
2691 Handle<FeedbackVector> vector = args.at<FeedbackVector>(4);
2692 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2693 FeedbackSlotKind slot_kind = vector->GetKind(vector_slot);
2696 if (!LoadIC::ShouldThrowReferenceError(slot_kind)) {
2697 return ReadOnlyRoots(isolate).undefined_value();
2701 THROW_NEW_ERROR_RETURN_FAILURE(
2702 isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name()));
2706 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
2707 HandleScope scope(isolate);
2708 DCHECK_EQ(5, args.length());
2710 Handle<Object> value = args.at(0);
2711 Handle<Smi> slot = args.at<Smi>(1);
2712 Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
2713 Handle<JSObject> receiver = args.at<JSObject>(3);
2714 Handle<Name> name = args.at<Name>(4);
2715 FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
2716 LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
2720 Handle<JSObject> interceptor_holder = receiver;
2721 if (receiver->IsJSGlobalProxy()) {
2722 FeedbackSlotKind kind = vector->GetKind(vector_slot);
2723 if (IsStoreGlobalICKind(kind)) {
2724 interceptor_holder = Handle<JSObject>::cast(isolate->global_object());
2727 DCHECK(interceptor_holder->HasNamedInterceptor());
2728 Handle<InterceptorInfo> interceptor(interceptor_holder->GetNamedInterceptor(),
2731 DCHECK(!interceptor->non_masking());
2732 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
2733 *receiver, kDontThrow);
2735 Handle<Object> result = arguments.CallNamedSetter(interceptor, name, value);
2736 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2737 if (!result.is_null())
return *value;
2739 LookupIterator it(receiver, name, receiver);
2741 if (it.state() == LookupIterator::ACCESS_CHECK) {
2742 DCHECK(it.HasAccess());
2746 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
2750 Object::SetProperty(&it, value, language_mode, StoreOrigin::kNamed),
2751 ReadOnlyRoots(isolate).exception());
2756 RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
2758 HandleScope scope(isolate);
2759 Handle<JSObject> receiver = args.at<JSObject>(0);
2760 DCHECK_GE(args.smi_at(1), 0);
2763 Handle<InterceptorInfo> interceptor(receiver->GetIndexedInterceptor(),
2765 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
2766 *receiver, kDontThrow);
2767 Handle<Object> result = arguments.CallIndexedGetter(interceptor, index);
2769 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2771 if (result.is_null()) {
2772 LookupIterator it(isolate, receiver, index, receiver);
2773 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
2775 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2776 Object::GetProperty(&it));