• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/ic/ic.h"
6 
7 #include "src/accessors.h"
8 #include "src/api-arguments-inl.h"
9 #include "src/api.h"
10 #include "src/arguments.h"
11 #include "src/base/bits.h"
12 #include "src/codegen.h"
13 #include "src/conversions.h"
14 #include "src/execution.h"
15 #include "src/field-type.h"
16 #include "src/frames-inl.h"
17 #include "src/ic/call-optimization.h"
18 #include "src/ic/handler-compiler.h"
19 #include "src/ic/ic-compiler.h"
20 #include "src/ic/ic-inl.h"
21 #include "src/ic/stub-cache.h"
22 #include "src/isolate-inl.h"
23 #include "src/macro-assembler.h"
24 #include "src/prototype.h"
25 #include "src/runtime/runtime-utils.h"
26 #include "src/runtime/runtime.h"
27 #include "src/tracing/trace-event.h"
28 
29 namespace v8 {
30 namespace internal {
31 
TransitionMarkFromState(IC::State state)32 char IC::TransitionMarkFromState(IC::State state) {
33   switch (state) {
34     case UNINITIALIZED:
35       return '0';
36     case PREMONOMORPHIC:
37       return '.';
38     case MONOMORPHIC:
39       return '1';
40     case RECOMPUTE_HANDLER:
41       return '^';
42     case POLYMORPHIC:
43       return 'P';
44     case MEGAMORPHIC:
45       return 'N';
46     case GENERIC:
47       return 'G';
48   }
49   UNREACHABLE();
50   return 0;
51 }
52 
53 
GetTransitionMarkModifier(KeyedAccessStoreMode mode)54 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
55   if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
56   if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
57     return ".IGNORE_OOB";
58   }
59   if (IsGrowStoreMode(mode)) return ".GROW";
60   return "";
61 }
62 
63 
64 #ifdef DEBUG
65 
66 #define TRACE_GENERIC_IC(isolate, type, reason)                \
67   do {                                                         \
68     if (FLAG_trace_ic) {                                       \
69       PrintF("[%s patching generic stub in ", type);           \
70       JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
71       PrintF(" (%s)]\n", reason);                              \
72     }                                                          \
73   } while (false)
74 
75 #else
76 
77 #define TRACE_GENERIC_IC(isolate, type, reason)      \
78   do {                                               \
79     if (FLAG_trace_ic) {                             \
80       PrintF("[%s patching generic stub in ", type); \
81       PrintF("(see below) (%s)]\n", reason);         \
82     }                                                \
83   } while (false)
84 
85 #endif  // DEBUG
86 
87 
TraceIC(const char * type,Handle<Object> name)88 void IC::TraceIC(const char* type, Handle<Object> name) {
89   if (FLAG_trace_ic) {
90     if (AddressIsDeoptimizedCode()) return;
91     DCHECK(UseVector());
92     State new_state = nexus()->StateFromFeedback();
93     TraceIC(type, name, state(), new_state);
94   }
95 }
96 
97 
TraceIC(const char * type,Handle<Object> name,State old_state,State new_state)98 void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
99                  State new_state) {
100   if (FLAG_trace_ic) {
101     PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type);
102 
103     // TODO(jkummerow): Add support for "apply". The logic is roughly:
104     // marker = [fp_ + kMarkerOffset];
105     // if marker is smi and marker.value == INTERNAL and
106     //     the frame's code == builtin(Builtins::kFunctionApply):
107     // then print "apply from" and advance one frame
108 
109     Object* maybe_function =
110         Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
111     if (maybe_function->IsJSFunction()) {
112       JSFunction* function = JSFunction::cast(maybe_function);
113       JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(),
114                                               stdout, true);
115     }
116 
117     const char* modifier = "";
118     if (kind() == Code::KEYED_STORE_IC) {
119       KeyedAccessStoreMode mode =
120           casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
121       modifier = GetTransitionMarkModifier(mode);
122     }
123     void* map = nullptr;
124     if (!receiver_map().is_null()) {
125       map = reinterpret_cast<void*>(*receiver_map());
126     }
127     PrintF(" (%c->%c%s) map=%p ", TransitionMarkFromState(old_state),
128            TransitionMarkFromState(new_state), modifier, map);
129     name->ShortPrint(stdout);
130     PrintF("]\n");
131   }
132 }
133 
134 
135 #define TRACE_IC(type, name) TraceIC(type, name)
136 
137 
IC(FrameDepth depth,Isolate * isolate,FeedbackNexus * nexus)138 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
139     : isolate_(isolate),
140       vector_set_(false),
141       target_maps_set_(false),
142       nexus_(nexus) {
143   // To improve the performance of the (much used) IC code, we unfold a few
144   // levels of the stack frame iteration code. This yields a ~35% speedup when
145   // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
146   const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
147   Address* constant_pool = NULL;
148   if (FLAG_enable_embedded_constant_pool) {
149     constant_pool = reinterpret_cast<Address*>(
150         entry + ExitFrameConstants::kConstantPoolOffset);
151   }
152   Address* pc_address =
153       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
154   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
155   // If there's another JavaScript frame on the stack or a
156   // StubFailureTrampoline, we need to look one frame further down the stack to
157   // find the frame pointer and the return address stack slot.
158   if (depth == EXTRA_CALL_FRAME) {
159     if (FLAG_enable_embedded_constant_pool) {
160       constant_pool = reinterpret_cast<Address*>(
161           fp + StandardFrameConstants::kConstantPoolOffset);
162     }
163     const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
164     pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
165     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
166   }
167 #ifdef DEBUG
168   StackFrameIterator it(isolate);
169   for (int i = 0; i < depth + 1; i++) it.Advance();
170   StackFrame* frame = it.frame();
171   DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
172 #endif
173   fp_ = fp;
174   if (FLAG_enable_embedded_constant_pool) {
175     constant_pool_address_ = constant_pool;
176   }
177   pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
178   Code* target = this->target();
179   kind_ = target->kind();
180   state_ = UseVector() ? nexus->StateFromFeedback() : StateFromCode(target);
181   old_state_ = state_;
182   extra_ic_state_ = target->extra_ic_state();
183 }
184 
StateFromCode(Code * code)185 InlineCacheState IC::StateFromCode(Code* code) {
186   Isolate* isolate = code->GetIsolate();
187   switch (code->kind()) {
188     case Code::BINARY_OP_IC: {
189       BinaryOpICState state(isolate, code->extra_ic_state());
190       return state.GetICState();
191     }
192     case Code::COMPARE_IC: {
193       CompareICStub stub(isolate, code->extra_ic_state());
194       return stub.GetICState();
195     }
196     case Code::TO_BOOLEAN_IC: {
197       ToBooleanICStub stub(isolate, code->extra_ic_state());
198       return stub.GetICState();
199     }
200     default:
201       if (code->is_debug_stub()) return UNINITIALIZED;
202       UNREACHABLE();
203       return UNINITIALIZED;
204   }
205 }
206 
GetSharedFunctionInfo() const207 SharedFunctionInfo* IC::GetSharedFunctionInfo() const {
208   // Compute the JavaScript frame for the frame pointer of this IC
209   // structure. We need this to be able to find the function
210   // corresponding to the frame.
211   StackFrameIterator it(isolate());
212   while (it.frame()->fp() != this->fp()) it.Advance();
213   if (FLAG_ignition && it.frame()->type() == StackFrame::STUB) {
214     // Advance over bytecode handler frame.
215     // TODO(rmcilroy): Remove this once bytecode handlers don't need a frame.
216     it.Advance();
217   }
218   JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
219   // Find the function on the stack and both the active code for the
220   // function and the original code.
221   JSFunction* function = frame->function();
222   return function->shared();
223 }
224 
225 
GetCode() const226 Code* IC::GetCode() const {
227   HandleScope scope(isolate());
228   Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate());
229   Code* code = shared->code();
230   return code;
231 }
232 
233 
AddressIsOptimizedCode() const234 bool IC::AddressIsOptimizedCode() const {
235   Code* host =
236       isolate()->inner_pointer_to_code_cache()->GetCacheEntry(address())->code;
237   return host->kind() == Code::OPTIMIZED_FUNCTION;
238 }
239 
LookupForRead(LookupIterator * it)240 static void LookupForRead(LookupIterator* it) {
241   for (; it->IsFound(); it->Next()) {
242     switch (it->state()) {
243       case LookupIterator::NOT_FOUND:
244       case LookupIterator::TRANSITION:
245         UNREACHABLE();
246       case LookupIterator::JSPROXY:
247         return;
248       case LookupIterator::INTERCEPTOR: {
249         // If there is a getter, return; otherwise loop to perform the lookup.
250         Handle<JSObject> holder = it->GetHolder<JSObject>();
251         if (!holder->GetNamedInterceptor()->getter()->IsUndefined(
252                 it->isolate())) {
253           return;
254         }
255         break;
256       }
257       case LookupIterator::ACCESS_CHECK:
258         // PropertyHandlerCompiler::CheckPrototypes() knows how to emit
259         // access checks for global proxies.
260         if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && it->HasAccess()) {
261           break;
262         }
263         return;
264       case LookupIterator::ACCESSOR:
265       case LookupIterator::INTEGER_INDEXED_EXOTIC:
266       case LookupIterator::DATA:
267         return;
268     }
269   }
270 }
271 
ShouldRecomputeHandler(Handle<Object> receiver,Handle<String> name)272 bool IC::ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name) {
273   if (!RecomputeHandlerForName(name)) return false;
274 
275   DCHECK(UseVector());
276   maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
277 
278   // This is a contextual access, always just update the handler and stay
279   // monomorphic.
280   if (kind() == Code::LOAD_GLOBAL_IC) return true;
281 
282   // The current map wasn't handled yet. There's no reason to stay monomorphic,
283   // *unless* we're moving from a deprecated map to its replacement, or
284   // to a more general elements kind.
285   // TODO(verwaest): Check if the current map is actually what the old map
286   // would transition to.
287   if (maybe_handler_.is_null()) {
288     if (!receiver_map()->IsJSObjectMap()) return false;
289     Map* first_map = FirstTargetMap();
290     if (first_map == NULL) return false;
291     Handle<Map> old_map(first_map);
292     if (old_map->is_deprecated()) return true;
293     return IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
294                                                receiver_map()->elements_kind());
295   }
296 
297   return true;
298 }
299 
RecomputeHandlerForName(Handle<Object> name)300 bool IC::RecomputeHandlerForName(Handle<Object> name) {
301   if (is_keyed()) {
302     // Determine whether the failure is due to a name failure.
303     if (!name->IsName()) return false;
304     DCHECK(UseVector());
305     Name* stub_name = nexus()->FindFirstName();
306     if (*name != stub_name) return false;
307   }
308 
309   return true;
310 }
311 
312 
UpdateState(Handle<Object> receiver,Handle<Object> name)313 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
314   update_receiver_map(receiver);
315   if (!name->IsString()) return;
316   if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
317   if (receiver->IsUndefined(isolate()) || receiver->IsNull(isolate())) return;
318 
319   // Remove the target from the code cache if it became invalid
320   // because of changes in the prototype chain to avoid hitting it
321   // again.
322   if (ShouldRecomputeHandler(receiver, Handle<String>::cast(name))) {
323     MarkRecomputeHandler(name);
324   }
325 }
326 
327 
TypeError(MessageTemplate::Template index,Handle<Object> object,Handle<Object> key)328 MaybeHandle<Object> IC::TypeError(MessageTemplate::Template index,
329                                   Handle<Object> object, Handle<Object> key) {
330   HandleScope scope(isolate());
331   THROW_NEW_ERROR(isolate(), NewTypeError(index, key, object), Object);
332 }
333 
334 
ReferenceError(Handle<Name> name)335 MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {
336   HandleScope scope(isolate());
337   THROW_NEW_ERROR(
338       isolate(), NewReferenceError(MessageTemplate::kNotDefined, name), Object);
339 }
340 
341 
ComputeTypeInfoCountDelta(IC::State old_state,IC::State new_state,int * polymorphic_delta,int * generic_delta)342 static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state,
343                                       int* polymorphic_delta,
344                                       int* generic_delta) {
345   switch (old_state) {
346     case UNINITIALIZED:
347     case PREMONOMORPHIC:
348       if (new_state == UNINITIALIZED || new_state == PREMONOMORPHIC) break;
349       if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
350         *polymorphic_delta = 1;
351       } else if (new_state == MEGAMORPHIC || new_state == GENERIC) {
352         *generic_delta = 1;
353       }
354       break;
355     case MONOMORPHIC:
356     case POLYMORPHIC:
357       if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) break;
358       *polymorphic_delta = -1;
359       if (new_state == MEGAMORPHIC || new_state == GENERIC) {
360         *generic_delta = 1;
361       }
362       break;
363     case MEGAMORPHIC:
364     case GENERIC:
365       if (new_state == MEGAMORPHIC || new_state == GENERIC) break;
366       *generic_delta = -1;
367       if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
368         *polymorphic_delta = 1;
369       }
370       break;
371     case RECOMPUTE_HANDLER:
372       UNREACHABLE();
373   }
374 }
375 
376 // static
OnTypeFeedbackChanged(Isolate * isolate,Code * host)377 void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) {
378   if (host->kind() != Code::FUNCTION) return;
379 
380   TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
381   info->change_own_type_change_checksum();
382   host->set_profiler_ticks(0);
383   isolate->runtime_profiler()->NotifyICChanged();
384   // TODO(2029): When an optimized function is patched, it would
385   // be nice to propagate the corresponding type information to its
386   // unoptimized version for the benefit of later inlining.
387 }
388 
PostPatching(Address address,Code * target,Code * old_target)389 void IC::PostPatching(Address address, Code* target, Code* old_target) {
390   // Type vector based ICs update these statistics at a different time because
391   // they don't always patch on state change.
392   if (ICUseVector(target->kind())) return;
393 
394   DCHECK(old_target->is_inline_cache_stub());
395   DCHECK(target->is_inline_cache_stub());
396   State old_state = StateFromCode(old_target);
397   State new_state = StateFromCode(target);
398 
399   Isolate* isolate = target->GetIsolate();
400   Code* host =
401       isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
402   if (host->kind() != Code::FUNCTION) return;
403 
404   // Not all Code objects have TypeFeedbackInfo.
405   if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
406     if (FLAG_type_info_threshold > 0) {
407       int polymorphic_delta = 0;  // "Polymorphic" here includes monomorphic.
408       int generic_delta = 0;      // "Generic" here includes megamorphic.
409       ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
410                                 &generic_delta);
411       TypeFeedbackInfo* info =
412           TypeFeedbackInfo::cast(host->type_feedback_info());
413       info->change_ic_with_type_info_count(polymorphic_delta);
414       info->change_ic_generic_count(generic_delta);
415     }
416     TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
417     info->change_own_type_change_checksum();
418   }
419   host->set_profiler_ticks(0);
420   isolate->runtime_profiler()->NotifyICChanged();
421   // TODO(2029): When an optimized function is patched, it would
422   // be nice to propagate the corresponding type information to its
423   // unoptimized version for the benefit of later inlining.
424 }
425 
Clear(Isolate * isolate,Address address,Address constant_pool)426 void IC::Clear(Isolate* isolate, Address address, Address constant_pool) {
427   Code* target = GetTargetAtAddress(address, constant_pool);
428 
429   // Don't clear debug break inline cache as it will remove the break point.
430   if (target->is_debug_stub()) return;
431 
432   if (target->kind() == Code::COMPARE_IC) {
433     CompareIC::Clear(isolate, address, target, constant_pool);
434   }
435 }
436 
437 
Clear(Isolate * isolate,Code * host,KeyedLoadICNexus * nexus)438 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) {
439   if (IsCleared(nexus)) return;
440   // Make sure to also clear the map used in inline fast cases.  If we
441   // do not clear these maps, cached code can keep objects alive
442   // through the embedded maps.
443   nexus->ConfigurePremonomorphic();
444   OnTypeFeedbackChanged(isolate, host);
445 }
446 
447 
Clear(Isolate * isolate,Code * host,CallICNexus * nexus)448 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) {
449   // Determine our state.
450   Object* feedback = nexus->vector()->Get(nexus->slot());
451   State state = nexus->StateFromFeedback();
452 
453   if (state != UNINITIALIZED && !feedback->IsAllocationSite()) {
454     nexus->ConfigureUninitialized();
455     // The change in state must be processed.
456     OnTypeFeedbackChanged(isolate, host);
457   }
458 }
459 
460 
Clear(Isolate * isolate,Code * host,LoadICNexus * nexus)461 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) {
462   if (IsCleared(nexus)) return;
463   nexus->ConfigurePremonomorphic();
464   OnTypeFeedbackChanged(isolate, host);
465 }
466 
Clear(Isolate * isolate,Code * host,LoadGlobalICNexus * nexus)467 void LoadGlobalIC::Clear(Isolate* isolate, Code* host,
468                          LoadGlobalICNexus* nexus) {
469   if (IsCleared(nexus)) return;
470   nexus->ConfigureUninitialized();
471   OnTypeFeedbackChanged(isolate, host);
472 }
473 
Clear(Isolate * isolate,Code * host,StoreICNexus * nexus)474 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) {
475   if (IsCleared(nexus)) return;
476   nexus->ConfigurePremonomorphic();
477   OnTypeFeedbackChanged(isolate, host);
478 }
479 
480 
Clear(Isolate * isolate,Code * host,KeyedStoreICNexus * nexus)481 void KeyedStoreIC::Clear(Isolate* isolate, Code* host,
482                          KeyedStoreICNexus* nexus) {
483   if (IsCleared(nexus)) return;
484   nexus->ConfigurePremonomorphic();
485   OnTypeFeedbackChanged(isolate, host);
486 }
487 
488 
Clear(Isolate * isolate,Address address,Code * target,Address constant_pool)489 void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
490                       Address constant_pool) {
491   DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
492   CompareICStub stub(target->stub_key(), isolate);
493   // Only clear CompareICs that can retain objects.
494   if (stub.state() != CompareICState::KNOWN_RECEIVER) return;
495   SetTargetAtAddress(address, GetRawUninitialized(isolate, stub.op()),
496                      constant_pool);
497   PatchInlinedSmiCode(isolate, address, DISABLE_INLINED_SMI_CHECK);
498 }
499 
500 
501 // static
ChooseMegamorphicStub(Isolate * isolate,ExtraICState extra_state)502 Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate,
503                                                 ExtraICState extra_state) {
504   // TODO(ishell): remove extra_ic_state
505   if (FLAG_compiled_keyed_generic_loads) {
506     return KeyedLoadGenericStub(isolate).GetCode();
507   } else {
508     return isolate->builtins()->KeyedLoadIC_Megamorphic();
509   }
510 }
511 
512 
MigrateDeprecated(Handle<Object> object)513 static bool MigrateDeprecated(Handle<Object> object) {
514   if (!object->IsJSObject()) return false;
515   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
516   if (!receiver->map()->is_deprecated()) return false;
517   JSObject::MigrateInstance(Handle<JSObject>::cast(object));
518   return true;
519 }
520 
ConfigureVectorState(IC::State new_state,Handle<Object> key)521 void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
522   DCHECK(UseVector());
523   if (new_state == PREMONOMORPHIC) {
524     nexus()->ConfigurePremonomorphic();
525   } else if (new_state == MEGAMORPHIC) {
526     if (kind() == Code::LOAD_IC || kind() == Code::STORE_IC) {
527       nexus()->ConfigureMegamorphic();
528     } else if (kind() == Code::KEYED_LOAD_IC) {
529       KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
530       nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
531     } else {
532       DCHECK(kind() == Code::KEYED_STORE_IC);
533       KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
534       nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
535     }
536   } else {
537     UNREACHABLE();
538   }
539 
540   vector_set_ = true;
541   OnTypeFeedbackChanged(isolate(), get_host());
542 }
543 
544 
ConfigureVectorState(Handle<Name> name,Handle<Map> map,Handle<Code> handler)545 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
546                               Handle<Code> handler) {
547   DCHECK(UseVector());
548   if (kind() == Code::LOAD_IC) {
549     LoadICNexus* nexus = casted_nexus<LoadICNexus>();
550     nexus->ConfigureMonomorphic(map, handler);
551   } else if (kind() == Code::LOAD_GLOBAL_IC) {
552     LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
553     nexus->ConfigureHandlerMode(handler);
554   } else if (kind() == Code::KEYED_LOAD_IC) {
555     KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
556     nexus->ConfigureMonomorphic(name, map, handler);
557   } else if (kind() == Code::STORE_IC) {
558     StoreICNexus* nexus = casted_nexus<StoreICNexus>();
559     nexus->ConfigureMonomorphic(map, handler);
560   } else {
561     DCHECK(kind() == Code::KEYED_STORE_IC);
562     KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
563     nexus->ConfigureMonomorphic(name, map, handler);
564   }
565 
566   vector_set_ = true;
567   OnTypeFeedbackChanged(isolate(), get_host());
568 }
569 
570 
ConfigureVectorState(Handle<Name> name,MapHandleList * maps,CodeHandleList * handlers)571 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
572                               CodeHandleList* handlers) {
573   DCHECK(UseVector());
574   if (kind() == Code::LOAD_IC) {
575     LoadICNexus* nexus = casted_nexus<LoadICNexus>();
576     nexus->ConfigurePolymorphic(maps, handlers);
577   } else if (kind() == Code::KEYED_LOAD_IC) {
578     KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
579     nexus->ConfigurePolymorphic(name, maps, handlers);
580   } else if (kind() == Code::STORE_IC) {
581     StoreICNexus* nexus = casted_nexus<StoreICNexus>();
582     nexus->ConfigurePolymorphic(maps, handlers);
583   } else {
584     DCHECK(kind() == Code::KEYED_STORE_IC);
585     KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
586     nexus->ConfigurePolymorphic(name, maps, handlers);
587   }
588 
589   vector_set_ = true;
590   OnTypeFeedbackChanged(isolate(), get_host());
591 }
592 
593 
ConfigureVectorState(MapHandleList * maps,MapHandleList * transitioned_maps,CodeHandleList * handlers)594 void IC::ConfigureVectorState(MapHandleList* maps,
595                               MapHandleList* transitioned_maps,
596                               CodeHandleList* handlers) {
597   DCHECK(UseVector());
598   DCHECK(kind() == Code::KEYED_STORE_IC);
599   KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
600   nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers);
601 
602   vector_set_ = true;
603   OnTypeFeedbackChanged(isolate(), get_host());
604 }
605 
606 
Load(Handle<Object> object,Handle<Name> name)607 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
608   // If the object is undefined or null it's illegal to try to get any
609   // of its properties; throw a TypeError in that case.
610   if (object->IsUndefined(isolate()) || object->IsNull(isolate())) {
611     return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name);
612   }
613 
614   bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
615 
616   if (state() != UNINITIALIZED) {
617     JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate());
618     update_receiver_map(object);
619   }
620   // Named lookup in the object.
621   LookupIterator it(object, name);
622   LookupForRead(&it);
623 
624   if (it.IsFound() || !ShouldThrowReferenceError()) {
625     // Update inline cache and stub cache.
626     if (use_ic) UpdateCaches(&it);
627 
628     // Get the property.
629     Handle<Object> result;
630 
631     ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it),
632                                Object);
633     if (it.IsFound()) {
634       return result;
635     } else if (!ShouldThrowReferenceError()) {
636       LOG(isolate(), SuspectReadEvent(*name, *object));
637       return result;
638     }
639   }
640   return ReferenceError(name);
641 }
642 
Load(Handle<Name> name)643 MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
644   Handle<JSGlobalObject> global = isolate()->global_object();
645 
646   if (name->IsString()) {
647     // Look up in script context table.
648     Handle<String> str_name = Handle<String>::cast(name);
649     Handle<ScriptContextTable> script_contexts(
650         global->native_context()->script_context_table());
651 
652     ScriptContextTable::LookupResult lookup_result;
653     if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
654       Handle<Object> result =
655           FixedArray::get(*ScriptContextTable::GetContext(
656                               script_contexts, lookup_result.context_index),
657                           lookup_result.slot_index, isolate());
658       if (result->IsTheHole(isolate())) {
659         // Do not install stubs and stay pre-monomorphic for
660         // uninitialized accesses.
661         return ReferenceError(name);
662       }
663 
664       if (FLAG_use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) {
665         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub);
666         LoadScriptContextFieldStub stub(isolate(), &lookup_result);
667         PatchCache(name, stub.GetCode());
668         TRACE_IC("LoadGlobalIC", name);
669       }
670       return result;
671     }
672   }
673   return LoadIC::Load(global, name);
674 }
675 
AddOneReceiverMapIfMissing(MapHandleList * receiver_maps,Handle<Map> new_receiver_map)676 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
677                                        Handle<Map> new_receiver_map) {
678   DCHECK(!new_receiver_map.is_null());
679   for (int current = 0; current < receiver_maps->length(); ++current) {
680     if (!receiver_maps->at(current).is_null() &&
681         receiver_maps->at(current).is_identical_to(new_receiver_map)) {
682       return false;
683     }
684   }
685   receiver_maps->Add(new_receiver_map);
686   return true;
687 }
688 
689 
UpdatePolymorphicIC(Handle<Name> name,Handle<Code> code)690 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
691   if (!code->is_handler()) return false;
692   if (is_keyed() && state() != RECOMPUTE_HANDLER) return false;
693   Handle<Map> map = receiver_map();
694   MapHandleList maps;
695   CodeHandleList handlers;
696 
697   TargetMaps(&maps);
698   int number_of_maps = maps.length();
699   int deprecated_maps = 0;
700   int handler_to_overwrite = -1;
701 
702   for (int i = 0; i < number_of_maps; i++) {
703     Handle<Map> current_map = maps.at(i);
704     if (current_map->is_deprecated()) {
705       // Filter out deprecated maps to ensure their instances get migrated.
706       ++deprecated_maps;
707     } else if (map.is_identical_to(current_map)) {
708       // If the receiver type is already in the polymorphic IC, this indicates
709       // there was a prototoype chain failure. In that case, just overwrite the
710       // handler.
711       handler_to_overwrite = i;
712     } else if (handler_to_overwrite == -1 &&
713                IsTransitionOfMonomorphicTarget(*current_map, *map)) {
714       handler_to_overwrite = i;
715     }
716   }
717 
718   int number_of_valid_maps =
719       number_of_maps - deprecated_maps - (handler_to_overwrite != -1);
720 
721   if (number_of_valid_maps >= 4) return false;
722   if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
723     return false;
724   }
725   DCHECK(UseVector());
726   if (!nexus()->FindHandlers(&handlers, maps.length())) return false;
727 
728   number_of_valid_maps++;
729   if (number_of_valid_maps > 1 && is_keyed()) return false;
730   Handle<Code> ic;
731   if (number_of_valid_maps == 1) {
732     ConfigureVectorState(name, receiver_map(), code);
733   } else {
734     if (handler_to_overwrite >= 0) {
735       handlers.Set(handler_to_overwrite, code);
736       if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
737         maps.Set(handler_to_overwrite, map);
738       }
739     } else {
740       maps.Add(map);
741       handlers.Add(code);
742     }
743 
744     ConfigureVectorState(name, &maps, &handlers);
745   }
746 
747   return true;
748 }
749 
750 
UpdateMonomorphicIC(Handle<Code> handler,Handle<Name> name)751 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) {
752   DCHECK(handler->is_handler());
753   ConfigureVectorState(name, receiver_map(), handler);
754 }
755 
756 
CopyICToMegamorphicCache(Handle<Name> name)757 void IC::CopyICToMegamorphicCache(Handle<Name> name) {
758   MapHandleList maps;
759   CodeHandleList handlers;
760   TargetMaps(&maps);
761   if (!nexus()->FindHandlers(&handlers, maps.length())) return;
762   for (int i = 0; i < maps.length(); i++) {
763     UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i));
764   }
765 }
766 
767 
IsTransitionOfMonomorphicTarget(Map * source_map,Map * target_map)768 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
769   if (source_map == NULL) return true;
770   if (target_map == NULL) return false;
771   ElementsKind target_elements_kind = target_map->elements_kind();
772   bool more_general_transition = IsMoreGeneralElementsKindTransition(
773       source_map->elements_kind(), target_elements_kind);
774   Map* transitioned_map = nullptr;
775   if (more_general_transition) {
776     MapHandleList map_list;
777     map_list.Add(handle(target_map));
778     transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list);
779   }
780   return transitioned_map == target_map;
781 }
782 
783 
PatchCache(Handle<Name> name,Handle<Code> code)784 void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
785   switch (state()) {
786     case UNINITIALIZED:
787     case PREMONOMORPHIC:
788       UpdateMonomorphicIC(code, name);
789       break;
790     case RECOMPUTE_HANDLER:
791     case MONOMORPHIC:
792       if (kind() == Code::LOAD_GLOBAL_IC) {
793         UpdateMonomorphicIC(code, name);
794         break;
795       }
796     // Fall through.
797     case POLYMORPHIC:
798       if (!is_keyed() || state() == RECOMPUTE_HANDLER) {
799         if (UpdatePolymorphicIC(name, code)) break;
800         // For keyed stubs, we can't know whether old handlers were for the
801         // same key.
802         CopyICToMegamorphicCache(name);
803       }
804       DCHECK(UseVector());
805       ConfigureVectorState(MEGAMORPHIC, name);
806     // Fall through.
807     case MEGAMORPHIC:
808       UpdateMegamorphicCache(*receiver_map(), *name, *code);
809       // Indicate that we've handled this case.
810       DCHECK(UseVector());
811       vector_set_ = true;
812       break;
813     case GENERIC:
814       UNREACHABLE();
815       break;
816   }
817 }
818 
initialize_stub_in_optimized_code(Isolate * isolate)819 Handle<Code> LoadIC::initialize_stub_in_optimized_code(Isolate* isolate) {
820   if (FLAG_tf_load_ic_stub) {
821     return LoadICTFStub(isolate).GetCode();
822   }
823   return LoadICStub(isolate).GetCode();
824 }
825 
initialize_stub_in_optimized_code(Isolate * isolate,ExtraICState extra_state)826 Handle<Code> LoadGlobalIC::initialize_stub_in_optimized_code(
827     Isolate* isolate, ExtraICState extra_state) {
828   return LoadGlobalICStub(isolate, LoadGlobalICState(extra_state)).GetCode();
829 }
830 
initialize_stub_in_optimized_code(Isolate * isolate,ExtraICState extra_state)831 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code(
832     Isolate* isolate, ExtraICState extra_state) {
833   // TODO(ishell): remove extra_ic_state
834   return KeyedLoadICStub(isolate).GetCode();
835 }
836 
initialize_stub_in_optimized_code(Isolate * isolate,LanguageMode language_mode)837 Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code(
838     Isolate* isolate, LanguageMode language_mode) {
839   StoreICState state = StoreICState(language_mode);
840   return VectorKeyedStoreICStub(isolate, state).GetCode();
841 }
842 
843 
ChooseMegamorphicStub(Isolate * isolate,ExtraICState extra_state)844 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
845                                                  ExtraICState extra_state) {
846   LanguageMode mode = StoreICState::GetLanguageMode(extra_state);
847   return is_strict(mode)
848              ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict()
849              : isolate->builtins()->KeyedStoreIC_Megamorphic();
850 }
851 
852 
SimpleFieldLoad(FieldIndex index)853 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
854   TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
855   LoadFieldStub stub(isolate(), index);
856   return stub.GetCode();
857 }
858 
859 
IsCompatibleReceiver(LookupIterator * lookup,Handle<Map> receiver_map)860 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
861   DCHECK(lookup->state() == LookupIterator::ACCESSOR);
862   Isolate* isolate = lookup->isolate();
863   Handle<Object> accessors = lookup->GetAccessors();
864   if (accessors->IsAccessorInfo()) {
865     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
866     if (info->getter() != NULL &&
867         !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) {
868       return false;
869     }
870   } else if (accessors->IsAccessorPair()) {
871     Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
872                           isolate);
873     if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo()) {
874       return false;
875     }
876     Handle<JSObject> holder = lookup->GetHolder<JSObject>();
877     Handle<Object> receiver = lookup->GetReceiver();
878     if (holder->HasFastProperties()) {
879       if (getter->IsJSFunction()) {
880         Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
881         if (!receiver->IsJSObject() && !function->shared()->IsBuiltin() &&
882             is_sloppy(function->shared()->language_mode())) {
883           // Calling sloppy non-builtins with a value as the receiver
884           // requires boxing.
885           return false;
886         }
887       }
888       CallOptimization call_optimization(getter);
889       if (call_optimization.is_simple_api_call() &&
890           !call_optimization.IsCompatibleReceiverMap(receiver_map, holder)) {
891         return false;
892       }
893     }
894   }
895   return true;
896 }
897 
898 
UpdateCaches(LookupIterator * lookup)899 void LoadIC::UpdateCaches(LookupIterator* lookup) {
900   if (state() == UNINITIALIZED && kind() != Code::LOAD_GLOBAL_IC) {
901     // This is the first time we execute this inline cache. Set the target to
902     // the pre monomorphic stub to delay setting the monomorphic state.
903     ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
904     TRACE_IC("LoadIC", lookup->name());
905     return;
906   }
907 
908   Handle<Code> code;
909   if (lookup->state() == LookupIterator::JSPROXY ||
910       lookup->state() == LookupIterator::ACCESS_CHECK) {
911     code = slow_stub();
912   } else if (!lookup->IsFound()) {
913     if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) {
914       code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
915                                                               receiver_map());
916       // TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
917       if (code.is_null()) code = slow_stub();
918     } else {
919       code = slow_stub();
920     }
921   } else {
922     if (kind() == Code::LOAD_GLOBAL_IC &&
923         lookup->state() == LookupIterator::DATA &&
924         lookup->GetHolder<Object>()->IsJSGlobalObject()) {
925 #if DEBUG
926       Handle<Object> holder = lookup->GetHolder<Object>();
927       Handle<Object> receiver = lookup->GetReceiver();
928       DCHECK_EQ(*receiver, *holder);
929 #endif
930       // Now update the cell in the feedback vector.
931       LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
932       nexus->ConfigurePropertyCellMode(lookup->GetPropertyCell());
933       TRACE_IC("LoadGlobalIC", lookup->name());
934       return;
935     } else if (lookup->state() == LookupIterator::ACCESSOR) {
936       if (!IsCompatibleReceiver(lookup, receiver_map())) {
937         TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
938         code = slow_stub();
939       }
940     } else if (lookup->state() == LookupIterator::INTERCEPTOR) {
941       if (kind() == Code::LOAD_GLOBAL_IC) {
942         // The interceptor handler requires name but it is not passed explicitly
943         // to LoadGlobalIC and the LoadGlobalIC dispatcher also does not load
944         // it so we will just use slow stub.
945         code = slow_stub();
946       } else {
947         // Perform a lookup behind the interceptor. Copy the LookupIterator
948         // since the original iterator will be used to fetch the value.
949         LookupIterator it = *lookup;
950         it.Next();
951         LookupForRead(&it);
952         if (it.state() == LookupIterator::ACCESSOR &&
953             !IsCompatibleReceiver(&it, receiver_map())) {
954           TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
955           code = slow_stub();
956         }
957       }
958     }
959     if (code.is_null()) code = ComputeHandler(lookup);
960   }
961 
962   PatchCache(lookup->name(), code);
963   TRACE_IC("LoadIC", lookup->name());
964 }
965 
966 
UpdateMegamorphicCache(Map * map,Name * name,Code * code)967 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
968   isolate()->stub_cache()->Set(name, map, code);
969 }
970 
971 
ComputeHandler(LookupIterator * lookup,Handle<Object> value)972 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
973   // Try to find a globally shared handler stub.
974   Handle<Code> code = GetMapIndependentHandler(lookup);
975   if (!code.is_null()) return code;
976 
977   // Otherwise check the map's handler cache for a map-specific handler, and
978   // compile one if the cache comes up empty.
979   bool receiver_is_holder =
980       lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
981   CacheHolderFlag flag;
982   Handle<Map> stub_holder_map;
983   if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC ||
984       kind() == Code::KEYED_LOAD_IC) {
985     stub_holder_map = IC::GetHandlerCacheHolder(
986         receiver_map(), receiver_is_holder, isolate(), &flag);
987   } else {
988     DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
989     // Store handlers cannot be cached on prototypes.
990     flag = kCacheOnReceiver;
991     stub_holder_map = receiver_map();
992   }
993 
994   code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(),
995                                        flag);
996   // Use the cached value if it exists, and if it is different from the
997   // handler that just missed.
998   if (!code.is_null()) {
999     Handle<Code> handler;
1000     if (maybe_handler_.ToHandle(&handler)) {
1001       if (!handler.is_identical_to(code)) {
1002         TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
1003         return code;
1004       }
1005     } else {
1006       // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
1007       // In MEGAMORPHIC case, check if the handler in the megamorphic stub
1008       // cache (which just missed) is different from the cached handler.
1009       if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) {
1010         Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
1011         Code* megamorphic_cached_code =
1012             isolate()->stub_cache()->Get(*lookup->name(), map, code->flags());
1013         if (megamorphic_cached_code != *code) {
1014           TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
1015           return code;
1016         }
1017       } else {
1018         TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
1019         return code;
1020       }
1021     }
1022   }
1023 
1024   code = CompileHandler(lookup, value, flag);
1025   DCHECK(code->is_handler());
1026   DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag);
1027   Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
1028 
1029   return code;
1030 }
1031 
GetMapIndependentHandler(LookupIterator * lookup)1032 Handle<Code> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
1033   Handle<Object> receiver = lookup->GetReceiver();
1034   if (receiver->IsString() &&
1035       Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
1036     FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
1037     return SimpleFieldLoad(index);
1038   }
1039 
1040   if (receiver->IsStringWrapper() &&
1041       Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
1042     TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub);
1043     StringLengthStub string_length_stub(isolate());
1044     return string_length_stub.GetCode();
1045   }
1046 
1047   // Use specialized code for getting prototype of functions.
1048   if (receiver->IsJSFunction() &&
1049       Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) &&
1050       receiver->IsConstructor() &&
1051       !Handle<JSFunction>::cast(receiver)
1052            ->map()
1053            ->has_non_instance_prototype()) {
1054     Handle<Code> stub;
1055     TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub);
1056     FunctionPrototypeStub function_prototype_stub(isolate());
1057     return function_prototype_stub.GetCode();
1058   }
1059 
1060   Handle<Map> map = receiver_map();
1061   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1062   bool receiver_is_holder = receiver.is_identical_to(holder);
1063   switch (lookup->state()) {
1064     case LookupIterator::INTERCEPTOR:
1065       break;  // Custom-compiled handler.
1066 
1067     case LookupIterator::ACCESSOR: {
1068       // Use simple field loads for some well-known callback properties.
1069       // The method will only return true for absolute truths based on the
1070       // receiver maps.
1071       int object_offset;
1072       if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
1073                                              &object_offset)) {
1074         FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
1075         return SimpleFieldLoad(index);
1076       }
1077 
1078       if (IsCompatibleReceiver(lookup, map)) {
1079         Handle<Object> accessors = lookup->GetAccessors();
1080         if (accessors->IsAccessorPair()) {
1081           if (!holder->HasFastProperties()) {
1082             TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1083             return slow_stub();
1084           }
1085           // When debugging we need to go the slow path to flood the accessor.
1086           if (GetSharedFunctionInfo()->HasDebugInfo()) {
1087             TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1088             return slow_stub();
1089           }
1090           break;  // Custom-compiled handler.
1091         } else if (accessors->IsAccessorInfo()) {
1092           Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
1093           if (v8::ToCData<Address>(info->getter()) == nullptr) {
1094             TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1095             return slow_stub();
1096           }
1097           // Ruled out by IsCompatibleReceiver() above.
1098           DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map));
1099           if (!holder->HasFastProperties()) return slow_stub();
1100           if (receiver_is_holder) {
1101             TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterStub);
1102             int index = lookup->GetAccessorIndex();
1103             LoadApiGetterStub stub(isolate(), true, index);
1104             return stub.GetCode();
1105           }
1106           if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1107             TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1108             return slow_stub();
1109           }
1110           break;  // Custom-compiled handler.
1111         }
1112       }
1113       TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1114       return slow_stub();
1115     }
1116 
1117     case LookupIterator::DATA: {
1118       if (lookup->is_dictionary_holder()) {
1119         if (kind() != Code::LOAD_IC && kind() != Code::LOAD_GLOBAL_IC) {
1120           TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1121           return slow_stub();
1122         }
1123         if (holder->IsJSGlobalObject()) {
1124           break;  // Custom-compiled handler.
1125         }
1126         // There is only one shared stub for loading normalized
1127         // properties. It does not traverse the prototype chain, so the
1128         // property must be found in the object for the stub to be
1129         // applicable.
1130         if (!receiver_is_holder) {
1131           TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1132           return slow_stub();
1133         }
1134         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal);
1135         return isolate()->builtins()->LoadIC_Normal();
1136       }
1137 
1138       // -------------- Fields --------------
1139       if (lookup->property_details().type() == DATA) {
1140         FieldIndex field = lookup->GetFieldIndex();
1141         if (receiver_is_holder) {
1142           return SimpleFieldLoad(field);
1143         }
1144         break;  // Custom-compiled handler.
1145       }
1146 
1147       // -------------- Constant properties --------------
1148       DCHECK(lookup->property_details().type() == DATA_CONSTANT);
1149       if (receiver_is_holder) {
1150         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
1151         LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
1152         return stub.GetCode();
1153       }
1154       break;  // Custom-compiled handler.
1155     }
1156 
1157     case LookupIterator::INTEGER_INDEXED_EXOTIC:
1158       TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1159       return slow_stub();
1160     case LookupIterator::ACCESS_CHECK:
1161     case LookupIterator::JSPROXY:
1162     case LookupIterator::NOT_FOUND:
1163     case LookupIterator::TRANSITION:
1164       UNREACHABLE();
1165   }
1166 
1167   return Handle<Code>::null();
1168 }
1169 
CompileHandler(LookupIterator * lookup,Handle<Object> unused,CacheHolderFlag cache_holder)1170 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
1171                                     Handle<Object> unused,
1172                                     CacheHolderFlag cache_holder) {
1173   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1174 #ifdef DEBUG
1175   // Only used by DCHECKs below.
1176   Handle<Object> receiver = lookup->GetReceiver();
1177   bool receiver_is_holder = receiver.is_identical_to(holder);
1178 #endif
1179   // Non-map-specific handler stubs have already been selected.
1180   DCHECK(!receiver->IsString() ||
1181          !Name::Equals(isolate()->factory()->length_string(), lookup->name()));
1182   DCHECK(!receiver->IsStringWrapper() ||
1183          !Name::Equals(isolate()->factory()->length_string(), lookup->name()));
1184 
1185   DCHECK(!(
1186       receiver->IsJSFunction() &&
1187       Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) &&
1188       receiver->IsConstructor() &&
1189       !Handle<JSFunction>::cast(receiver)
1190            ->map()
1191            ->has_non_instance_prototype()));
1192 
1193   Handle<Map> map = receiver_map();
1194   switch (lookup->state()) {
1195     case LookupIterator::INTERCEPTOR: {
1196       DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
1197       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptor);
1198       NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1199       // Perform a lookup behind the interceptor. Copy the LookupIterator since
1200       // the original iterator will be used to fetch the value.
1201       LookupIterator it = *lookup;
1202       it.Next();
1203       LookupForRead(&it);
1204       return compiler.CompileLoadInterceptor(&it);
1205     }
1206 
1207     case LookupIterator::ACCESSOR: {
1208 #ifdef DEBUG
1209       int object_offset;
1210       DCHECK(!Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
1211                                                  &object_offset));
1212 #endif
1213 
1214       DCHECK(IsCompatibleReceiver(lookup, map));
1215       Handle<Object> accessors = lookup->GetAccessors();
1216       if (accessors->IsAccessorPair()) {
1217         DCHECK(holder->HasFastProperties());
1218         DCHECK(!GetSharedFunctionInfo()->HasDebugInfo());
1219         Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
1220                               isolate());
1221         CallOptimization call_optimization(getter);
1222         NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1223         if (call_optimization.is_simple_api_call()) {
1224           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
1225           int index = lookup->GetAccessorIndex();
1226           Handle<Code> code = compiler.CompileLoadCallback(
1227               lookup->name(), call_optimization, index);
1228           return code;
1229         }
1230         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter);
1231         int expected_arguments = Handle<JSFunction>::cast(getter)
1232                                      ->shared()
1233                                      ->internal_formal_parameter_count();
1234         return compiler.CompileLoadViaGetter(
1235             lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
1236       } else {
1237         DCHECK(accessors->IsAccessorInfo());
1238         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
1239         DCHECK(v8::ToCData<Address>(info->getter()) != nullptr);
1240         DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map));
1241         DCHECK(holder->HasFastProperties());
1242         DCHECK(!receiver_is_holder);
1243         DCHECK(!info->is_sloppy() || receiver->IsJSReceiver());
1244         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
1245         NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1246         Handle<Code> code = compiler.CompileLoadCallback(lookup->name(), info);
1247         return code;
1248       }
1249       UNREACHABLE();
1250     }
1251 
1252     case LookupIterator::DATA: {
1253       if (lookup->is_dictionary_holder()) {
1254         DCHECK(kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC);
1255         DCHECK(holder->IsJSGlobalObject());
1256         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal);
1257         NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1258         Handle<PropertyCell> cell = lookup->GetPropertyCell();
1259         Handle<Code> code = compiler.CompileLoadGlobal(
1260             cell, lookup->name(), lookup->IsConfigurable());
1261         return code;
1262       }
1263 
1264       // -------------- Fields --------------
1265       if (lookup->property_details().type() == DATA) {
1266         FieldIndex field = lookup->GetFieldIndex();
1267         DCHECK(!receiver_is_holder);
1268         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadField);
1269         NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1270         return compiler.CompileLoadField(lookup->name(), field);
1271       }
1272 
1273       // -------------- Constant properties --------------
1274       DCHECK(lookup->property_details().type() == DATA_CONSTANT);
1275       DCHECK(!receiver_is_holder);
1276       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstant);
1277       NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1278       return compiler.CompileLoadConstant(lookup->name(),
1279                                           lookup->GetConstantIndex());
1280     }
1281 
1282     case LookupIterator::INTEGER_INDEXED_EXOTIC:
1283     case LookupIterator::ACCESS_CHECK:
1284     case LookupIterator::JSPROXY:
1285     case LookupIterator::NOT_FOUND:
1286     case LookupIterator::TRANSITION:
1287       UNREACHABLE();
1288   }
1289   UNREACHABLE();
1290   return slow_stub();
1291 }
1292 
1293 
TryConvertKey(Handle<Object> key,Isolate * isolate)1294 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1295   // This helper implements a few common fast cases for converting
1296   // non-smi keys of keyed loads/stores to a smi or a string.
1297   if (key->IsHeapNumber()) {
1298     double value = Handle<HeapNumber>::cast(key)->value();
1299     if (std::isnan(value)) {
1300       key = isolate->factory()->nan_string();
1301     } else {
1302       int int_value = FastD2I(value);
1303       if (value == int_value && Smi::IsValid(int_value)) {
1304         key = handle(Smi::FromInt(int_value), isolate);
1305       }
1306     }
1307   } else if (key->IsUndefined(isolate)) {
1308     key = isolate->factory()->undefined_string();
1309   }
1310   return key;
1311 }
1312 
UpdateLoadElement(Handle<HeapObject> receiver)1313 void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
1314   Handle<Map> receiver_map(receiver->map(), isolate());
1315   DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE &&
1316          receiver_map->instance_type() != JS_PROXY_TYPE);  // Checked by caller.
1317   MapHandleList target_receiver_maps;
1318   TargetMaps(&target_receiver_maps);
1319 
1320   if (target_receiver_maps.length() == 0) {
1321     Handle<Code> handler =
1322         PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
1323             receiver_map, extra_ic_state());
1324     return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
1325   }
1326 
1327   for (int i = 0; i < target_receiver_maps.length(); i++) {
1328     Handle<Map> map = target_receiver_maps.at(i);
1329     if (map.is_null()) continue;
1330     if (map->instance_type() == JS_VALUE_TYPE) {
1331       TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "JSValue");
1332       return;
1333     }
1334     if (map->instance_type() == JS_PROXY_TYPE) {
1335       TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "JSProxy");
1336       return;
1337     }
1338   }
1339 
1340   // The first time a receiver is seen that is a transitioned version of the
1341   // previous monomorphic receiver type, assume the new ElementsKind is the
1342   // monomorphic type. This benefits global arrays that only transition
1343   // once, and all call sites accessing them are faster if they remain
1344   // monomorphic. If this optimistic assumption is not true, the IC will
1345   // miss again and it will become polymorphic and support both the
1346   // untransitioned and transitioned maps.
1347   if (state() == MONOMORPHIC && !receiver->IsString() &&
1348       IsMoreGeneralElementsKindTransition(
1349           target_receiver_maps.at(0)->elements_kind(),
1350           Handle<JSObject>::cast(receiver)->GetElementsKind())) {
1351     Handle<Code> handler =
1352         PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
1353             receiver_map, extra_ic_state());
1354     return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
1355   }
1356 
1357   DCHECK(state() != GENERIC);
1358 
1359   // Determine the list of receiver maps that this call site has seen,
1360   // adding the map that was just encountered.
1361   if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1362     // If the miss wasn't due to an unseen map, a polymorphic stub
1363     // won't help, use the generic stub.
1364     TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice");
1365     return;
1366   }
1367 
1368   // If the maximum number of receiver maps has been exceeded, use the generic
1369   // version of the IC.
1370   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1371     TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded");
1372     return;
1373   }
1374 
1375   CodeHandleList handlers(target_receiver_maps.length());
1376   TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement);
1377   ElementHandlerCompiler compiler(isolate());
1378   compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
1379   ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers);
1380 }
1381 
1382 
Load(Handle<Object> object,Handle<Object> key)1383 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
1384                                       Handle<Object> key) {
1385   if (MigrateDeprecated(object)) {
1386     Handle<Object> result;
1387     ASSIGN_RETURN_ON_EXCEPTION(
1388         isolate(), result, Runtime::GetObjectProperty(isolate(), object, key),
1389         Object);
1390     return result;
1391   }
1392 
1393   Handle<Object> load_handle;
1394 
1395   // Check for non-string values that can be converted into an
1396   // internalized string directly or is representable as a smi.
1397   key = TryConvertKey(key, isolate());
1398 
1399   uint32_t index;
1400   if ((key->IsInternalizedString() &&
1401        !String::cast(*key)->AsArrayIndex(&index)) ||
1402       key->IsSymbol()) {
1403     ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
1404                                LoadIC::Load(object, Handle<Name>::cast(key)),
1405                                Object);
1406   } else if (FLAG_use_ic && !object->IsAccessCheckNeeded() &&
1407              !object->IsJSValue()) {
1408     if (object->IsJSObject() || (object->IsString() && key->IsNumber())) {
1409       Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
1410       if (object->IsString() || key->IsSmi()) UpdateLoadElement(receiver);
1411     }
1412   }
1413 
1414   if (!is_vector_set()) {
1415     ConfigureVectorState(MEGAMORPHIC, key);
1416     TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
1417   }
1418   TRACE_IC("LoadIC", key);
1419 
1420   if (!load_handle.is_null()) return load_handle;
1421 
1422   Handle<Object> result;
1423   ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
1424                              Runtime::GetObjectProperty(isolate(), object, key),
1425                              Object);
1426   return result;
1427 }
1428 
1429 
LookupForWrite(LookupIterator * it,Handle<Object> value,JSReceiver::StoreFromKeyed store_mode)1430 bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
1431                              JSReceiver::StoreFromKeyed store_mode) {
1432   // Disable ICs for non-JSObjects for now.
1433   Handle<Object> object = it->GetReceiver();
1434   if (!object->IsJSObject()) return false;
1435   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1436   DCHECK(!receiver->map()->is_deprecated());
1437 
1438   for (; it->IsFound(); it->Next()) {
1439     switch (it->state()) {
1440       case LookupIterator::NOT_FOUND:
1441       case LookupIterator::TRANSITION:
1442         UNREACHABLE();
1443       case LookupIterator::JSPROXY:
1444         return false;
1445       case LookupIterator::INTERCEPTOR: {
1446         Handle<JSObject> holder = it->GetHolder<JSObject>();
1447         InterceptorInfo* info = holder->GetNamedInterceptor();
1448         if (it->HolderIsReceiverOrHiddenPrototype()) {
1449           return !info->non_masking() && receiver.is_identical_to(holder) &&
1450                  !info->setter()->IsUndefined(it->isolate());
1451         } else if (!info->getter()->IsUndefined(it->isolate()) ||
1452                    !info->query()->IsUndefined(it->isolate())) {
1453           return false;
1454         }
1455         break;
1456       }
1457       case LookupIterator::ACCESS_CHECK:
1458         if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false;
1459         break;
1460       case LookupIterator::ACCESSOR:
1461         return !it->IsReadOnly();
1462       case LookupIterator::INTEGER_INDEXED_EXOTIC:
1463         return false;
1464       case LookupIterator::DATA: {
1465         if (it->IsReadOnly()) return false;
1466         Handle<JSObject> holder = it->GetHolder<JSObject>();
1467         if (receiver.is_identical_to(holder)) {
1468           it->PrepareForDataProperty(value);
1469           // The previous receiver map might just have been deprecated,
1470           // so reload it.
1471           update_receiver_map(receiver);
1472           return true;
1473         }
1474 
1475         // Receiver != holder.
1476         if (receiver->IsJSGlobalProxy()) {
1477           PrototypeIterator iter(it->isolate(), receiver);
1478           return it->GetHolder<Object>().is_identical_to(
1479               PrototypeIterator::GetCurrent(iter));
1480         }
1481 
1482         if (it->HolderIsReceiverOrHiddenPrototype()) return false;
1483 
1484         if (it->ExtendingNonExtensible(receiver)) return false;
1485         it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
1486         return it->IsCacheableTransition();
1487       }
1488     }
1489   }
1490 
1491   receiver = it->GetStoreTarget();
1492   if (it->ExtendingNonExtensible(receiver)) return false;
1493   it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
1494   return it->IsCacheableTransition();
1495 }
1496 
1497 
Store(Handle<Object> object,Handle<Name> name,Handle<Object> value,JSReceiver::StoreFromKeyed store_mode)1498 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
1499                                    Handle<Object> value,
1500                                    JSReceiver::StoreFromKeyed store_mode) {
1501   if (object->IsJSGlobalObject() && name->IsString()) {
1502     // Look up in script context table.
1503     Handle<String> str_name = Handle<String>::cast(name);
1504     Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object);
1505     Handle<ScriptContextTable> script_contexts(
1506         global->native_context()->script_context_table());
1507 
1508     ScriptContextTable::LookupResult lookup_result;
1509     if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
1510       Handle<Context> script_context = ScriptContextTable::GetContext(
1511           script_contexts, lookup_result.context_index);
1512       if (lookup_result.mode == CONST) {
1513         return TypeError(MessageTemplate::kConstAssign, object, name);
1514       }
1515 
1516       Handle<Object> previous_value =
1517           FixedArray::get(*script_context, lookup_result.slot_index, isolate());
1518 
1519       if (previous_value->IsTheHole(isolate())) {
1520         // Do not install stubs and stay pre-monomorphic for
1521         // uninitialized accesses.
1522         return ReferenceError(name);
1523       }
1524 
1525       if (FLAG_use_ic &&
1526           StoreScriptContextFieldStub::Accepted(&lookup_result)) {
1527         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub);
1528         StoreScriptContextFieldStub stub(isolate(), &lookup_result);
1529         PatchCache(name, stub.GetCode());
1530       }
1531 
1532       script_context->set(lookup_result.slot_index, *value);
1533       return value;
1534     }
1535   }
1536 
1537   // TODO(verwaest): Let SetProperty do the migration, since storing a property
1538   // might deprecate the current map again, if value does not fit.
1539   if (MigrateDeprecated(object) || object->IsJSProxy()) {
1540     Handle<Object> result;
1541     ASSIGN_RETURN_ON_EXCEPTION(
1542         isolate(), result,
1543         Object::SetProperty(object, name, value, language_mode()), Object);
1544     return result;
1545   }
1546 
1547   // If the object is undefined or null it's illegal to try to set any
1548   // properties on it; throw a TypeError in that case.
1549   if (object->IsUndefined(isolate()) || object->IsNull(isolate())) {
1550     return TypeError(MessageTemplate::kNonObjectPropertyStore, object, name);
1551   }
1552 
1553   if (state() != UNINITIALIZED) {
1554     JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
1555   }
1556   LookupIterator it(object, name);
1557   if (FLAG_use_ic) UpdateCaches(&it, value, store_mode);
1558 
1559   MAYBE_RETURN_NULL(
1560       Object::SetProperty(&it, value, language_mode(), store_mode));
1561   return value;
1562 }
1563 
initialize_stub_in_optimized_code(Isolate * isolate,int argc,ConvertReceiverMode mode,TailCallMode tail_call_mode)1564 Handle<Code> CallIC::initialize_stub_in_optimized_code(
1565     Isolate* isolate, int argc, ConvertReceiverMode mode,
1566     TailCallMode tail_call_mode) {
1567   CallICStub stub(isolate, CallICState(argc, mode, tail_call_mode));
1568   Handle<Code> code = stub.GetCode();
1569   return code;
1570 }
1571 
initialize_stub_in_optimized_code(Isolate * isolate,LanguageMode language_mode)1572 Handle<Code> StoreIC::initialize_stub_in_optimized_code(
1573     Isolate* isolate, LanguageMode language_mode) {
1574   VectorStoreICStub stub(isolate, StoreICState(language_mode));
1575   return stub.GetCode();
1576 }
1577 
UpdateCaches(LookupIterator * lookup,Handle<Object> value,JSReceiver::StoreFromKeyed store_mode)1578 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
1579                            JSReceiver::StoreFromKeyed store_mode) {
1580   if (state() == UNINITIALIZED) {
1581     // This is the first time we execute this inline cache. Set the target to
1582     // the pre monomorphic stub to delay setting the monomorphic state.
1583     ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
1584     TRACE_IC("StoreIC", lookup->name());
1585     return;
1586   }
1587 
1588   bool use_ic = LookupForWrite(lookup, value, store_mode);
1589   if (!use_ic) {
1590     TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'");
1591   }
1592   Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub();
1593 
1594   PatchCache(lookup->name(), code);
1595   TRACE_IC("StoreIC", lookup->name());
1596 }
1597 
1598 
PropertyCellStoreHandler(Isolate * isolate,Handle<JSObject> receiver,Handle<JSGlobalObject> holder,Handle<Name> name,Handle<PropertyCell> cell,PropertyCellType type)1599 static Handle<Code> PropertyCellStoreHandler(
1600     Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder,
1601     Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) {
1602   auto constant_type = Nothing<PropertyCellConstantType>();
1603   if (type == PropertyCellType::kConstantType) {
1604     constant_type = Just(cell->GetConstantType());
1605   }
1606   StoreGlobalStub stub(isolate, type, constant_type,
1607                        receiver->IsJSGlobalProxy());
1608   auto code = stub.GetCodeCopyFromTemplate(holder, cell);
1609   // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1610   HeapObject::UpdateMapCodeCache(receiver, name, code);
1611   return code;
1612 }
1613 
GetMapIndependentHandler(LookupIterator * lookup)1614 Handle<Code> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
1615   DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
1616 
1617   // This is currently guaranteed by checks in StoreIC::Store.
1618   Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
1619   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1620   DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
1621 
1622   switch (lookup->state()) {
1623     case LookupIterator::TRANSITION: {
1624       auto store_target = lookup->GetStoreTarget();
1625       if (store_target->IsJSGlobalObject()) {
1626         break;  // Custom-compiled handler.
1627       }
1628       // Currently not handled by CompileStoreTransition.
1629       if (!holder->HasFastProperties()) {
1630         TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow");
1631         TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1632         return slow_stub();
1633       }
1634 
1635       DCHECK(lookup->IsCacheableTransition());
1636       break;  // Custom-compiled handler.
1637     }
1638 
1639     case LookupIterator::INTERCEPTOR: {
1640       DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate()));
1641       TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
1642       StoreInterceptorStub stub(isolate());
1643       return stub.GetCode();
1644     }
1645 
1646     case LookupIterator::ACCESSOR: {
1647       if (!holder->HasFastProperties()) {
1648         TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map");
1649         TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1650         return slow_stub();
1651       }
1652       Handle<Object> accessors = lookup->GetAccessors();
1653       if (accessors->IsAccessorInfo()) {
1654         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
1655         if (v8::ToCData<Address>(info->setter()) == nullptr) {
1656           TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == nullptr");
1657           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1658           return slow_stub();
1659         }
1660         if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
1661             !lookup->HolderIsReceiverOrHiddenPrototype()) {
1662           TRACE_GENERIC_IC(isolate(), "StoreIC",
1663                            "special data property in prototype chain");
1664           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1665           return slow_stub();
1666         }
1667         if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
1668                                                    receiver_map())) {
1669           TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type");
1670           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1671           return slow_stub();
1672         }
1673         if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1674           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1675           return slow_stub();
1676         }
1677         break;  // Custom-compiled handler.
1678       } else if (accessors->IsAccessorPair()) {
1679         Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
1680                               isolate());
1681         if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
1682           TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function");
1683           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1684           return slow_stub();
1685         }
1686         CallOptimization call_optimization(setter);
1687         if (call_optimization.is_simple_api_call()) {
1688           if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
1689             break;  // Custom-compiled handler.
1690           }
1691           TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver");
1692           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1693           return slow_stub();
1694         }
1695         break;  // Custom-compiled handler.
1696       }
1697       TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1698       return slow_stub();
1699     }
1700 
1701     case LookupIterator::DATA: {
1702       if (lookup->is_dictionary_holder()) {
1703         if (holder->IsJSGlobalObject()) {
1704           break;  // Custom-compiled handler.
1705         }
1706         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal);
1707         DCHECK(holder.is_identical_to(receiver));
1708         return isolate()->builtins()->StoreIC_Normal();
1709       }
1710 
1711       // -------------- Fields --------------
1712       if (lookup->property_details().type() == DATA) {
1713         bool use_stub = true;
1714         if (lookup->representation().IsHeapObject()) {
1715           // Only use a generic stub if no types need to be tracked.
1716           Handle<FieldType> field_type = lookup->GetFieldType();
1717           use_stub = !field_type->IsClass();
1718         }
1719         if (use_stub) {
1720           TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub);
1721           StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
1722                               lookup->representation());
1723           return stub.GetCode();
1724         }
1725         break;  // Custom-compiled handler.
1726       }
1727 
1728       // -------------- Constant properties --------------
1729       DCHECK(lookup->property_details().type() == DATA_CONSTANT);
1730       TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property");
1731       TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1732       return slow_stub();
1733     }
1734 
1735     case LookupIterator::INTEGER_INDEXED_EXOTIC:
1736     case LookupIterator::ACCESS_CHECK:
1737     case LookupIterator::JSPROXY:
1738     case LookupIterator::NOT_FOUND:
1739       UNREACHABLE();
1740   }
1741   return Handle<Code>::null();
1742 }
1743 
CompileHandler(LookupIterator * lookup,Handle<Object> value,CacheHolderFlag cache_holder)1744 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
1745                                      Handle<Object> value,
1746                                      CacheHolderFlag cache_holder) {
1747   DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
1748 
1749   // This is currently guaranteed by checks in StoreIC::Store.
1750   Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
1751   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1752   DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
1753 
1754   switch (lookup->state()) {
1755     case LookupIterator::TRANSITION: {
1756       auto store_target = lookup->GetStoreTarget();
1757       if (store_target->IsJSGlobalObject()) {
1758         // TODO(dcarney): this currently just deopts. Use the transition cell.
1759         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition);
1760         auto cell = isolate()->factory()->NewPropertyCell();
1761         cell->set_value(*value);
1762         auto code = PropertyCellStoreHandler(
1763             isolate(), store_target, Handle<JSGlobalObject>::cast(store_target),
1764             lookup->name(), cell, PropertyCellType::kConstant);
1765         cell->set_value(isolate()->heap()->the_hole_value());
1766         return code;
1767       }
1768       Handle<Map> transition = lookup->transition_map();
1769       // Currently not handled by CompileStoreTransition.
1770       DCHECK(holder->HasFastProperties());
1771 
1772       DCHECK(lookup->IsCacheableTransition());
1773       TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransition);
1774       NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
1775       return compiler.CompileStoreTransition(transition, lookup->name());
1776     }
1777 
1778     case LookupIterator::INTERCEPTOR:
1779       UNREACHABLE();
1780 
1781     case LookupIterator::ACCESSOR: {
1782       DCHECK(holder->HasFastProperties());
1783       Handle<Object> accessors = lookup->GetAccessors();
1784       if (accessors->IsAccessorInfo()) {
1785         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
1786         DCHECK(v8::ToCData<Address>(info->setter()) != 0);
1787         DCHECK(!AccessorInfo::cast(*accessors)->is_special_data_property() ||
1788                lookup->HolderIsReceiverOrHiddenPrototype());
1789         DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
1790                                                      receiver_map()));
1791         DCHECK(!info->is_sloppy() || receiver->IsJSReceiver());
1792         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
1793         NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
1794         Handle<Code> code = compiler.CompileStoreCallback(
1795             receiver, lookup->name(), info, language_mode());
1796         return code;
1797       } else {
1798         DCHECK(accessors->IsAccessorPair());
1799         Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
1800                               isolate());
1801         DCHECK(setter->IsJSFunction() || setter->IsFunctionTemplateInfo());
1802         CallOptimization call_optimization(setter);
1803         NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
1804         if (call_optimization.is_simple_api_call()) {
1805           DCHECK(call_optimization.IsCompatibleReceiver(receiver, holder));
1806           TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
1807           Handle<Code> code = compiler.CompileStoreCallback(
1808               receiver, lookup->name(), call_optimization,
1809               lookup->GetAccessorIndex());
1810           return code;
1811         }
1812         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
1813         int expected_arguments = JSFunction::cast(*setter)
1814                                      ->shared()
1815                                      ->internal_formal_parameter_count();
1816         return compiler.CompileStoreViaSetter(receiver, lookup->name(),
1817                                               lookup->GetAccessorIndex(),
1818                                               expected_arguments);
1819       }
1820     }
1821 
1822     case LookupIterator::DATA: {
1823       if (lookup->is_dictionary_holder()) {
1824         DCHECK(holder->IsJSGlobalObject());
1825         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal);
1826         DCHECK(holder.is_identical_to(receiver) ||
1827                receiver->map()->prototype() == *holder);
1828         auto cell = lookup->GetPropertyCell();
1829         auto updated_type =
1830             PropertyCell::UpdatedType(cell, value, lookup->property_details());
1831         auto code = PropertyCellStoreHandler(
1832             isolate(), receiver, Handle<JSGlobalObject>::cast(holder),
1833             lookup->name(), cell, updated_type);
1834         return code;
1835       }
1836 
1837       // -------------- Fields --------------
1838       if (lookup->property_details().type() == DATA) {
1839 #ifdef DEBUG
1840         bool use_stub = true;
1841         if (lookup->representation().IsHeapObject()) {
1842           // Only use a generic stub if no types need to be tracked.
1843           Handle<FieldType> field_type = lookup->GetFieldType();
1844           use_stub = !field_type->IsClass();
1845         }
1846         DCHECK(!use_stub);
1847 #endif
1848         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField);
1849         NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
1850         return compiler.CompileStoreField(lookup);
1851       }
1852 
1853       // -------------- Constant properties --------------
1854       DCHECK(lookup->property_details().type() == DATA_CONSTANT);
1855       UNREACHABLE();
1856     }
1857 
1858     case LookupIterator::INTEGER_INDEXED_EXOTIC:
1859     case LookupIterator::ACCESS_CHECK:
1860     case LookupIterator::JSPROXY:
1861     case LookupIterator::NOT_FOUND:
1862       UNREACHABLE();
1863   }
1864   UNREACHABLE();
1865   return slow_stub();
1866 }
1867 
UpdateStoreElement(Handle<Map> receiver_map,KeyedAccessStoreMode store_mode)1868 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1869                                       KeyedAccessStoreMode store_mode) {
1870   MapHandleList target_receiver_maps;
1871   TargetMaps(&target_receiver_maps);
1872   if (target_receiver_maps.length() == 0) {
1873     Handle<Map> monomorphic_map =
1874         ComputeTransitionedMap(receiver_map, store_mode);
1875     store_mode = GetNonTransitioningStoreMode(store_mode);
1876     Handle<Code> handler =
1877         PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(monomorphic_map,
1878                                                                 store_mode);
1879     return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
1880   }
1881 
1882   for (int i = 0; i < target_receiver_maps.length(); i++) {
1883     if (!target_receiver_maps.at(i).is_null() &&
1884         target_receiver_maps.at(i)->instance_type() == JS_VALUE_TYPE) {
1885       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "JSValue");
1886       return;
1887     }
1888   }
1889 
1890   // There are several special cases where an IC that is MONOMORPHIC can still
1891   // transition to a different GetNonTransitioningStoreMode IC that handles a
1892   // superset of the original IC. Handle those here if the receiver map hasn't
1893   // changed or it has transitioned to a more general kind.
1894   KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode();
1895   Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1896   if (state() == MONOMORPHIC) {
1897     Handle<Map> transitioned_receiver_map = receiver_map;
1898     if (IsTransitionStoreMode(store_mode)) {
1899       transitioned_receiver_map =
1900           ComputeTransitionedMap(receiver_map, store_mode);
1901     }
1902     if ((receiver_map.is_identical_to(previous_receiver_map) &&
1903          IsTransitionStoreMode(store_mode)) ||
1904         IsTransitionOfMonomorphicTarget(*previous_receiver_map,
1905                                         *transitioned_receiver_map)) {
1906       // If the "old" and "new" maps are in the same elements map family, or
1907       // if they at least come from the same origin for a transitioning store,
1908       // stay MONOMORPHIC and use the map for the most generic ElementsKind.
1909       store_mode = GetNonTransitioningStoreMode(store_mode);
1910       Handle<Code> handler =
1911           PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
1912               transitioned_receiver_map, store_mode);
1913       ConfigureVectorState(Handle<Name>(), transitioned_receiver_map, handler);
1914       return;
1915     }
1916     if (receiver_map.is_identical_to(previous_receiver_map) &&
1917         old_store_mode == STANDARD_STORE &&
1918         (store_mode == STORE_AND_GROW_NO_TRANSITION ||
1919          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1920          store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1921       // A "normal" IC that handles stores can switch to a version that can
1922       // grow at the end of the array, handle OOB accesses or copy COW arrays
1923       // and still stay MONOMORPHIC.
1924       Handle<Code> handler =
1925           PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(receiver_map,
1926                                                                   store_mode);
1927       return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
1928     }
1929   }
1930 
1931   DCHECK(state() != GENERIC);
1932 
1933   bool map_added =
1934       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1935 
1936   if (IsTransitionStoreMode(store_mode)) {
1937     Handle<Map> transitioned_receiver_map =
1938         ComputeTransitionedMap(receiver_map, store_mode);
1939     map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
1940                                             transitioned_receiver_map);
1941   }
1942 
1943   if (!map_added) {
1944     // If the miss wasn't due to an unseen map, a polymorphic stub
1945     // won't help, use the megamorphic stub which can handle everything.
1946     TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice");
1947     return;
1948   }
1949 
1950   // If the maximum number of receiver maps has been exceeded, use the
1951   // megamorphic version of the IC.
1952   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) return;
1953 
1954   // Make sure all polymorphic handlers have the same store mode, otherwise the
1955   // megamorphic stub must be used.
1956   store_mode = GetNonTransitioningStoreMode(store_mode);
1957   if (old_store_mode != STANDARD_STORE) {
1958     if (store_mode == STANDARD_STORE) {
1959       store_mode = old_store_mode;
1960     } else if (store_mode != old_store_mode) {
1961       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch");
1962       return;
1963     }
1964   }
1965 
1966   // If the store mode isn't the standard mode, make sure that all polymorphic
1967   // receivers are either external arrays, or all "normal" arrays. Otherwise,
1968   // use the megamorphic stub.
1969   if (store_mode != STANDARD_STORE) {
1970     int external_arrays = 0;
1971     for (int i = 0; i < target_receiver_maps.length(); ++i) {
1972       if (target_receiver_maps[i]->has_fixed_typed_array_elements()) {
1973         external_arrays++;
1974       }
1975     }
1976     if (external_arrays != 0 &&
1977         external_arrays != target_receiver_maps.length()) {
1978       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
1979                        "unsupported combination of external and normal arrays");
1980       return;
1981     }
1982   }
1983 
1984   TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_Polymorphic);
1985   MapHandleList transitioned_maps(target_receiver_maps.length());
1986   CodeHandleList handlers(target_receiver_maps.length());
1987   PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
1988       &target_receiver_maps, &transitioned_maps, &handlers, store_mode);
1989   ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers);
1990 }
1991 
1992 
ComputeTransitionedMap(Handle<Map> map,KeyedAccessStoreMode store_mode)1993 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
1994     Handle<Map> map, KeyedAccessStoreMode store_mode) {
1995   switch (store_mode) {
1996     case STORE_TRANSITION_TO_OBJECT:
1997     case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
1998       ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
1999                               ? FAST_HOLEY_ELEMENTS
2000                               : FAST_ELEMENTS;
2001       return Map::TransitionElementsTo(map, kind);
2002     }
2003     case STORE_TRANSITION_TO_DOUBLE:
2004     case STORE_AND_GROW_TRANSITION_TO_DOUBLE: {
2005       ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
2006                               ? FAST_HOLEY_DOUBLE_ELEMENTS
2007                               : FAST_DOUBLE_ELEMENTS;
2008       return Map::TransitionElementsTo(map, kind);
2009     }
2010     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
2011       DCHECK(map->has_fixed_typed_array_elements());
2012     // Fall through
2013     case STORE_NO_TRANSITION_HANDLE_COW:
2014     case STANDARD_STORE:
2015     case STORE_AND_GROW_NO_TRANSITION:
2016       return map;
2017   }
2018   UNREACHABLE();
2019   return MaybeHandle<Map>().ToHandleChecked();
2020 }
2021 
2022 
IsOutOfBoundsAccess(Handle<JSObject> receiver,uint32_t index)2023 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, uint32_t index) {
2024   uint32_t length = 0;
2025   if (receiver->IsJSArray()) {
2026     JSArray::cast(*receiver)->length()->ToArrayLength(&length);
2027   } else {
2028     length = static_cast<uint32_t>(receiver->elements()->length());
2029   }
2030   return index >= length;
2031 }
2032 
2033 
GetStoreMode(Handle<JSObject> receiver,uint32_t index,Handle<Object> value)2034 static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
2035                                          uint32_t index, Handle<Object> value) {
2036   bool oob_access = IsOutOfBoundsAccess(receiver, index);
2037   // Don't consider this a growing store if the store would send the receiver to
2038   // dictionary mode.
2039   bool allow_growth = receiver->IsJSArray() && oob_access &&
2040                       !receiver->WouldConvertToSlowElements(index);
2041   if (allow_growth) {
2042     // Handle growing array in stub if necessary.
2043     if (receiver->HasFastSmiElements()) {
2044       if (value->IsHeapNumber()) {
2045         return STORE_AND_GROW_TRANSITION_TO_DOUBLE;
2046       }
2047       if (value->IsHeapObject()) {
2048         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
2049       }
2050     } else if (receiver->HasFastDoubleElements()) {
2051       if (!value->IsSmi() && !value->IsHeapNumber()) {
2052         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
2053       }
2054     }
2055     return STORE_AND_GROW_NO_TRANSITION;
2056   } else {
2057     // Handle only in-bounds elements accesses.
2058     if (receiver->HasFastSmiElements()) {
2059       if (value->IsHeapNumber()) {
2060         return STORE_TRANSITION_TO_DOUBLE;
2061       } else if (value->IsHeapObject()) {
2062         return STORE_TRANSITION_TO_OBJECT;
2063       }
2064     } else if (receiver->HasFastDoubleElements()) {
2065       if (!value->IsSmi() && !value->IsHeapNumber()) {
2066         return STORE_TRANSITION_TO_OBJECT;
2067       }
2068     }
2069     if (!FLAG_trace_external_array_abuse &&
2070         receiver->map()->has_fixed_typed_array_elements() && oob_access) {
2071       return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
2072     }
2073     Heap* heap = receiver->GetHeap();
2074     if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
2075       return STORE_NO_TRANSITION_HANDLE_COW;
2076     } else {
2077       return STANDARD_STORE;
2078     }
2079   }
2080 }
2081 
2082 
Store(Handle<Object> object,Handle<Object> key,Handle<Object> value)2083 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
2084                                         Handle<Object> key,
2085                                         Handle<Object> value) {
2086   // TODO(verwaest): Let SetProperty do the migration, since storing a property
2087   // might deprecate the current map again, if value does not fit.
2088   if (MigrateDeprecated(object)) {
2089     Handle<Object> result;
2090     ASSIGN_RETURN_ON_EXCEPTION(
2091         isolate(), result, Runtime::SetObjectProperty(isolate(), object, key,
2092                                                       value, language_mode()),
2093         Object);
2094     return result;
2095   }
2096 
2097   // Check for non-string values that can be converted into an
2098   // internalized string directly or is representable as a smi.
2099   key = TryConvertKey(key, isolate());
2100 
2101   Handle<Object> store_handle;
2102 
2103   uint32_t index;
2104   if ((key->IsInternalizedString() &&
2105        !String::cast(*key)->AsArrayIndex(&index)) ||
2106       key->IsSymbol()) {
2107     ASSIGN_RETURN_ON_EXCEPTION(
2108         isolate(), store_handle,
2109         StoreIC::Store(object, Handle<Name>::cast(key), value,
2110                        JSReceiver::MAY_BE_STORE_FROM_KEYED),
2111         Object);
2112     if (!is_vector_set()) {
2113       ConfigureVectorState(MEGAMORPHIC, key);
2114       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
2115                        "unhandled internalized string key");
2116       TRACE_IC("StoreIC", key);
2117     }
2118     return store_handle;
2119   }
2120 
2121   bool use_ic = FLAG_use_ic && !object->IsStringWrapper() &&
2122                 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy();
2123   if (use_ic && !object->IsSmi()) {
2124     // Don't use ICs for maps of the objects in Array's prototype chain. We
2125     // expect to be able to trap element sets to objects with those maps in
2126     // the runtime to enable optimization of element hole access.
2127     Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
2128     if (heap_object->map()->IsMapInArrayPrototypeChain()) {
2129       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype");
2130       use_ic = false;
2131     }
2132   }
2133 
2134   Handle<Map> old_receiver_map;
2135   bool sloppy_arguments_elements = false;
2136   bool key_is_valid_index = false;
2137   KeyedAccessStoreMode store_mode = STANDARD_STORE;
2138   if (use_ic && object->IsJSObject()) {
2139     Handle<JSObject> receiver = Handle<JSObject>::cast(object);
2140     old_receiver_map = handle(receiver->map(), isolate());
2141     sloppy_arguments_elements =
2142         !is_sloppy(language_mode()) &&
2143         receiver->elements()->map() ==
2144             isolate()->heap()->sloppy_arguments_elements_map();
2145     if (!sloppy_arguments_elements) {
2146       key_is_valid_index = key->IsSmi() && Smi::cast(*key)->value() >= 0;
2147       if (key_is_valid_index) {
2148         uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value());
2149         store_mode = GetStoreMode(receiver, index, value);
2150       }
2151     }
2152   }
2153 
2154   DCHECK(store_handle.is_null());
2155   ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
2156                              Runtime::SetObjectProperty(isolate(), object, key,
2157                                                         value, language_mode()),
2158                              Object);
2159 
2160   if (use_ic) {
2161     if (!old_receiver_map.is_null()) {
2162       if (sloppy_arguments_elements) {
2163         TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver");
2164       } else if (key_is_valid_index) {
2165         // We should go generic if receiver isn't a dictionary, but our
2166         // prototype chain does have dictionary elements. This ensures that
2167         // other non-dictionary receivers in the polymorphic case benefit
2168         // from fast path keyed stores.
2169         if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly()) {
2170           UpdateStoreElement(old_receiver_map, store_mode);
2171         } else {
2172           TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
2173                            "dictionary or proxy prototype");
2174         }
2175       } else {
2176         TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key");
2177       }
2178     } else {
2179       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver");
2180     }
2181   }
2182 
2183   if (!is_vector_set()) {
2184     ConfigureVectorState(MEGAMORPHIC, key);
2185     TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
2186   }
2187   TRACE_IC("StoreIC", key);
2188 
2189   return store_handle;
2190 }
2191 
2192 
HandleMiss(Handle<Object> function)2193 void CallIC::HandleMiss(Handle<Object> function) {
2194   Handle<Object> name = isolate()->factory()->empty_string();
2195   CallICNexus* nexus = casted_nexus<CallICNexus>();
2196   Object* feedback = nexus->GetFeedback();
2197 
2198   // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
2199   DCHECK(!feedback->IsSmi());
2200 
2201   if (feedback->IsWeakCell() || !function->IsJSFunction() ||
2202       feedback->IsAllocationSite()) {
2203     // We are going generic.
2204     nexus->ConfigureMegamorphic();
2205   } else {
2206     DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()));
2207     Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
2208 
2209     Handle<JSFunction> array_function =
2210         Handle<JSFunction>(isolate()->native_context()->array_function());
2211     if (array_function.is_identical_to(js_function)) {
2212       // Alter the slot.
2213       nexus->ConfigureMonomorphicArray();
2214     } else if (js_function->context()->native_context() !=
2215                *isolate()->native_context()) {
2216       // Don't collect cross-native context feedback for the CallIC.
2217       // TODO(bmeurer): We should collect the SharedFunctionInfo as
2218       // feedback in this case instead.
2219       nexus->ConfigureMegamorphic();
2220     } else {
2221       nexus->ConfigureMonomorphic(js_function);
2222     }
2223   }
2224 
2225   if (function->IsJSFunction()) {
2226     Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
2227     name = handle(js_function->shared()->name(), isolate());
2228   }
2229 
2230   OnTypeFeedbackChanged(isolate(), get_host());
2231   TRACE_IC("CallIC", name);
2232 }
2233 
2234 
2235 #undef TRACE_IC
2236 
2237 
2238 // ----------------------------------------------------------------------------
2239 // Static IC stub generators.
2240 //
2241 
2242 // Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_CallIC_Miss)2243 RUNTIME_FUNCTION(Runtime_CallIC_Miss) {
2244   TimerEventScope<TimerEventIcMiss> timer(isolate);
2245   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2246   HandleScope scope(isolate);
2247   DCHECK(args.length() == 3);
2248   Handle<Object> function = args.at<Object>(0);
2249   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
2250   Handle<Smi> slot = args.at<Smi>(2);
2251   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2252   CallICNexus nexus(vector, vector_slot);
2253   CallIC ic(isolate, &nexus);
2254   ic.HandleMiss(function);
2255   return *function;
2256 }
2257 
2258 
2259 // Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_LoadIC_Miss)2260 RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
2261   TimerEventScope<TimerEventIcMiss> timer(isolate);
2262   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2263   HandleScope scope(isolate);
2264   Handle<Object> receiver = args.at<Object>(0);
2265 
2266   DCHECK_EQ(4, args.length());
2267   Handle<Smi> slot = args.at<Smi>(2);
2268   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
2269   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2270   // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
2271   // LoadIC miss handler if the handler misses. Since the vector Nexus is
2272   // set up outside the IC, handle that here.
2273   FeedbackVectorSlotKind kind = vector->GetKind(vector_slot);
2274   if (kind == FeedbackVectorSlotKind::LOAD_IC) {
2275     Handle<Name> key = args.at<Name>(1);
2276     LoadICNexus nexus(vector, vector_slot);
2277     LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2278     ic.UpdateState(receiver, key);
2279     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
2280 
2281   } else if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) {
2282     Handle<Name> key(vector->GetName(vector_slot), isolate);
2283     DCHECK_NE(*key, *isolate->factory()->empty_string());
2284     DCHECK_EQ(*isolate->global_object(), *receiver);
2285     LoadGlobalICNexus nexus(vector, vector_slot);
2286     LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2287     ic.UpdateState(receiver, key);
2288     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key));
2289 
2290   } else {
2291     Handle<Name> key = args.at<Name>(1);
2292     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, kind);
2293     KeyedLoadICNexus nexus(vector, vector_slot);
2294     KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2295     ic.UpdateState(receiver, key);
2296     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
2297   }
2298 }
2299 
2300 // Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss)2301 RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
2302   TimerEventScope<TimerEventIcMiss> timer(isolate);
2303   HandleScope scope(isolate);
2304   DCHECK_EQ(2, args.length());
2305   Handle<JSGlobalObject> global = isolate->global_object();
2306   Handle<Smi> slot = args.at<Smi>(0);
2307   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
2308   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2309   DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
2310             vector->GetKind(vector_slot));
2311   Handle<String> name(vector->GetName(vector_slot), isolate);
2312   DCHECK_NE(*name, *isolate->factory()->empty_string());
2313 
2314   LoadGlobalICNexus nexus(vector, vector_slot);
2315   LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2316   ic.UpdateState(global, name);
2317 
2318   Handle<Object> result;
2319   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(name));
2320   return *result;
2321 }
2322 
RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow)2323 RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
2324   HandleScope scope(isolate);
2325   DCHECK_EQ(2, args.length());
2326   CONVERT_SMI_ARG_CHECKED(slot, 0);
2327   CONVERT_ARG_HANDLE_CHECKED(TypeFeedbackVector, vector, 1);
2328 
2329   FeedbackVectorSlot vector_slot = vector->ToSlot(slot);
2330   DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
2331             vector->GetKind(vector_slot));
2332   Handle<String> name(vector->GetName(vector_slot), isolate);
2333   DCHECK_NE(*name, *isolate->factory()->empty_string());
2334 
2335   Handle<JSGlobalObject> global = isolate->global_object();
2336 
2337   Handle<ScriptContextTable> script_contexts(
2338       global->native_context()->script_context_table());
2339 
2340   ScriptContextTable::LookupResult lookup_result;
2341   if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) {
2342     Handle<Context> script_context = ScriptContextTable::GetContext(
2343         script_contexts, lookup_result.context_index);
2344     Handle<Object> result =
2345         FixedArray::get(*script_context, lookup_result.slot_index, isolate);
2346     if (*result == *isolate->factory()->the_hole_value()) {
2347       THROW_NEW_ERROR_RETURN_FAILURE(
2348           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
2349     }
2350     return *result;
2351   }
2352 
2353   Handle<Object> result;
2354   bool is_found = false;
2355   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2356       isolate, result,
2357       Runtime::GetObjectProperty(isolate, global, name, &is_found));
2358   if (!is_found) {
2359     LoadICNexus nexus(isolate);
2360     LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2361     // It is actually a LoadGlobalICs here but the predicate handles this case
2362     // properly.
2363     if (ic.ShouldThrowReferenceError()) {
2364       THROW_NEW_ERROR_RETURN_FAILURE(
2365           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
2366     }
2367   }
2368   return *result;
2369 }
2370 
2371 // Used from ic-<arch>.cc
RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss)2372 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
2373   TimerEventScope<TimerEventIcMiss> timer(isolate);
2374   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2375   HandleScope scope(isolate);
2376   Handle<Object> receiver = args.at<Object>(0);
2377   Handle<Object> key = args.at<Object>(1);
2378 
2379   DCHECK(args.length() == 4);
2380   Handle<Smi> slot = args.at<Smi>(2);
2381   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
2382   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2383   KeyedLoadICNexus nexus(vector, vector_slot);
2384   KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2385   ic.UpdateState(receiver, key);
2386   RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
2387 }
2388 
2389 
RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure)2390 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) {
2391   TimerEventScope<TimerEventIcMiss> timer(isolate);
2392   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2393   HandleScope scope(isolate);
2394   Handle<Object> receiver = args.at<Object>(0);
2395   Handle<Object> key = args.at<Object>(1);
2396 
2397   DCHECK(args.length() == 4);
2398   Handle<Smi> slot = args.at<Smi>(2);
2399   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
2400   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2401   KeyedLoadICNexus nexus(vector, vector_slot);
2402   KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2403   ic.UpdateState(receiver, key);
2404   RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
2405 }
2406 
2407 
2408 // Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_StoreIC_Miss)2409 RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
2410   TimerEventScope<TimerEventIcMiss> timer(isolate);
2411   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2412   HandleScope scope(isolate);
2413   Handle<Object> receiver = args.at<Object>(0);
2414   Handle<Name> key = args.at<Name>(1);
2415   Handle<Object> value = args.at<Object>(2);
2416 
2417   DCHECK(args.length() == 5 || args.length() == 6);
2418   Handle<Smi> slot = args.at<Smi>(3);
2419   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
2420   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2421   if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
2422     StoreICNexus nexus(vector, vector_slot);
2423     StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2424     ic.UpdateState(receiver, key);
2425     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
2426   } else {
2427     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
2428               vector->GetKind(vector_slot));
2429     KeyedStoreICNexus nexus(vector, vector_slot);
2430     KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2431     ic.UpdateState(receiver, key);
2432     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
2433   }
2434 }
2435 
2436 
RUNTIME_FUNCTION(Runtime_StoreIC_MissFromStubFailure)2437 RUNTIME_FUNCTION(Runtime_StoreIC_MissFromStubFailure) {
2438   TimerEventScope<TimerEventIcMiss> timer(isolate);
2439   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2440   HandleScope scope(isolate);
2441   Handle<Object> receiver = args.at<Object>(0);
2442   Handle<Name> key = args.at<Name>(1);
2443   Handle<Object> value = args.at<Object>(2);
2444 
2445   int length = args.length();
2446   DCHECK(length == 5 || length == 6);
2447   // We might have slot and vector, for a normal miss (slot(3), vector(4)).
2448   // Or, map and vector for a transitioning store miss (map(3), vector(4)).
2449   // In this case, we need to recover the slot from a virtual register.
2450   // If length == 6, then a map is included (map(3), slot(4), vector(5)).
2451   Handle<Smi> slot;
2452   Handle<TypeFeedbackVector> vector;
2453   if (length == 5) {
2454     if (args.at<Object>(3)->IsMap()) {
2455       vector = args.at<TypeFeedbackVector>(4);
2456       slot = handle(
2457           *reinterpret_cast<Smi**>(isolate->virtual_slot_register_address()),
2458           isolate);
2459     } else {
2460       vector = args.at<TypeFeedbackVector>(4);
2461       slot = args.at<Smi>(3);
2462     }
2463   } else {
2464     vector = args.at<TypeFeedbackVector>(5);
2465     slot = args.at<Smi>(4);
2466   }
2467 
2468   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2469   if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
2470     StoreICNexus nexus(vector, vector_slot);
2471     StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2472     ic.UpdateState(receiver, key);
2473     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
2474   } else {
2475     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
2476               vector->GetKind(vector_slot));
2477     KeyedStoreICNexus nexus(vector, vector_slot);
2478     KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2479     ic.UpdateState(receiver, key);
2480     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
2481   }
2482 }
2483 
2484 
2485 // Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss)2486 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
2487   TimerEventScope<TimerEventIcMiss> timer(isolate);
2488   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2489   HandleScope scope(isolate);
2490   Handle<Object> receiver = args.at<Object>(0);
2491   Handle<Object> key = args.at<Object>(1);
2492   Handle<Object> value = args.at<Object>(2);
2493 
2494   DCHECK(args.length() == 5);
2495   Handle<Smi> slot = args.at<Smi>(3);
2496   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
2497   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2498   KeyedStoreICNexus nexus(vector, vector_slot);
2499   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2500   ic.UpdateState(receiver, key);
2501   RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
2502 }
2503 
2504 
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure)2505 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure) {
2506   TimerEventScope<TimerEventIcMiss> timer(isolate);
2507   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2508   HandleScope scope(isolate);
2509   Handle<Object> receiver = args.at<Object>(0);
2510   Handle<Object> key = args.at<Object>(1);
2511   Handle<Object> value = args.at<Object>(2);
2512 
2513   DCHECK(args.length() == 5);
2514   Handle<Smi> slot = args.at<Smi>(3);
2515   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
2516   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2517   KeyedStoreICNexus nexus(vector, vector_slot);
2518   KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2519   ic.UpdateState(receiver, key);
2520   RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
2521 }
2522 
2523 
RUNTIME_FUNCTION(Runtime_StoreIC_Slow)2524 RUNTIME_FUNCTION(Runtime_StoreIC_Slow) {
2525   HandleScope scope(isolate);
2526   DCHECK(args.length() == 5);
2527   Handle<Object> object = args.at<Object>(0);
2528   Handle<Object> key = args.at<Object>(1);
2529   Handle<Object> value = args.at<Object>(2);
2530   LanguageMode language_mode;
2531   StoreICNexus nexus(isolate);
2532   StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2533   language_mode = ic.language_mode();
2534   RETURN_RESULT_OR_FAILURE(
2535       isolate,
2536       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
2537 }
2538 
2539 
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow)2540 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
2541   HandleScope scope(isolate);
2542   DCHECK(args.length() == 5);
2543   Handle<Object> object = args.at<Object>(0);
2544   Handle<Object> key = args.at<Object>(1);
2545   Handle<Object> value = args.at<Object>(2);
2546   LanguageMode language_mode;
2547   KeyedStoreICNexus nexus(isolate);
2548   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2549   language_mode = ic.language_mode();
2550   RETURN_RESULT_OR_FAILURE(
2551       isolate,
2552       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
2553 }
2554 
2555 
RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss)2556 RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
2557   TimerEventScope<TimerEventIcMiss> timer(isolate);
2558   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2559   HandleScope scope(isolate);
2560   // Length == 5 or 6, depending on whether the vector slot
2561   // is passed in a virtual register or not.
2562   DCHECK(args.length() == 5 || args.length() == 6);
2563   Handle<Object> object = args.at<Object>(0);
2564   Handle<Object> key = args.at<Object>(1);
2565   Handle<Object> value = args.at<Object>(2);
2566   Handle<Map> map = args.at<Map>(3);
2567   LanguageMode language_mode;
2568   KeyedStoreICNexus nexus(isolate);
2569   KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2570   language_mode = ic.language_mode();
2571   if (object->IsJSObject()) {
2572     JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
2573                                      map->elements_kind());
2574   }
2575   RETURN_RESULT_OR_FAILURE(
2576       isolate,
2577       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
2578 }
2579 
2580 
Transition(Handle<AllocationSite> allocation_site,Handle<Object> left,Handle<Object> right)2581 MaybeHandle<Object> BinaryOpIC::Transition(
2582     Handle<AllocationSite> allocation_site, Handle<Object> left,
2583     Handle<Object> right) {
2584   BinaryOpICState state(isolate(), extra_ic_state());
2585 
2586   // Compute the actual result using the builtin for the binary operation.
2587   Handle<Object> result;
2588   switch (state.op()) {
2589     default:
2590       UNREACHABLE();
2591     case Token::ADD:
2592       ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
2593                                  Object::Add(isolate(), left, right), Object);
2594       break;
2595     case Token::SUB:
2596       ASSIGN_RETURN_ON_EXCEPTION(
2597           isolate(), result, Object::Subtract(isolate(), left, right), Object);
2598       break;
2599     case Token::MUL:
2600       ASSIGN_RETURN_ON_EXCEPTION(
2601           isolate(), result, Object::Multiply(isolate(), left, right), Object);
2602       break;
2603     case Token::DIV:
2604       ASSIGN_RETURN_ON_EXCEPTION(
2605           isolate(), result, Object::Divide(isolate(), left, right), Object);
2606       break;
2607     case Token::MOD:
2608       ASSIGN_RETURN_ON_EXCEPTION(
2609           isolate(), result, Object::Modulus(isolate(), left, right), Object);
2610       break;
2611     case Token::BIT_OR:
2612       ASSIGN_RETURN_ON_EXCEPTION(
2613           isolate(), result, Object::BitwiseOr(isolate(), left, right), Object);
2614       break;
2615     case Token::BIT_AND:
2616       ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
2617                                  Object::BitwiseAnd(isolate(), left, right),
2618                                  Object);
2619       break;
2620     case Token::BIT_XOR:
2621       ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
2622                                  Object::BitwiseXor(isolate(), left, right),
2623                                  Object);
2624       break;
2625     case Token::SAR:
2626       ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
2627                                  Object::ShiftRight(isolate(), left, right),
2628                                  Object);
2629       break;
2630     case Token::SHR:
2631       ASSIGN_RETURN_ON_EXCEPTION(
2632           isolate(), result, Object::ShiftRightLogical(isolate(), left, right),
2633           Object);
2634       break;
2635     case Token::SHL:
2636       ASSIGN_RETURN_ON_EXCEPTION(
2637           isolate(), result, Object::ShiftLeft(isolate(), left, right), Object);
2638       break;
2639   }
2640 
2641   // Do not try to update the target if the code was marked for lazy
2642   // deoptimization. (Since we do not relocate addresses in these
2643   // code objects, an attempt to access the target could fail.)
2644   if (AddressIsDeoptimizedCode()) {
2645     return result;
2646   }
2647 
2648   // Compute the new state.
2649   BinaryOpICState old_state(isolate(), target()->extra_ic_state());
2650   state.Update(left, right, result);
2651 
2652   // Check if we have a string operation here.
2653   Handle<Code> new_target;
2654   if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) {
2655     // Setup the allocation site on-demand.
2656     if (allocation_site.is_null()) {
2657       allocation_site = isolate()->factory()->NewAllocationSite();
2658     }
2659 
2660     // Install the stub with an allocation site.
2661     BinaryOpICWithAllocationSiteStub stub(isolate(), state);
2662     new_target = stub.GetCodeCopyFromTemplate(allocation_site);
2663 
2664     // Sanity check the trampoline stub.
2665     DCHECK_EQ(*allocation_site, new_target->FindFirstAllocationSite());
2666   } else {
2667     // Install the generic stub.
2668     BinaryOpICStub stub(isolate(), state);
2669     new_target = stub.GetCode();
2670 
2671     // Sanity check the generic stub.
2672     DCHECK_NULL(new_target->FindFirstAllocationSite());
2673   }
2674   set_target(*new_target);
2675 
2676   if (FLAG_trace_ic) {
2677     OFStream os(stdout);
2678     os << "[BinaryOpIC" << old_state << " => " << state << " @ "
2679        << static_cast<void*>(*new_target) << " <- ";
2680     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2681     if (!allocation_site.is_null()) {
2682       os << " using allocation site " << static_cast<void*>(*allocation_site);
2683     }
2684     os << "]" << std::endl;
2685   }
2686 
2687   // Patch the inlined smi code as necessary.
2688   if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) {
2689     PatchInlinedSmiCode(isolate(), address(), ENABLE_INLINED_SMI_CHECK);
2690   } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) {
2691     PatchInlinedSmiCode(isolate(), address(), DISABLE_INLINED_SMI_CHECK);
2692   }
2693 
2694   return result;
2695 }
2696 
2697 
RUNTIME_FUNCTION(Runtime_BinaryOpIC_Miss)2698 RUNTIME_FUNCTION(Runtime_BinaryOpIC_Miss) {
2699   TimerEventScope<TimerEventIcMiss> timer(isolate);
2700   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2701   HandleScope scope(isolate);
2702   DCHECK_EQ(2, args.length());
2703   Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft);
2704   Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight);
2705   BinaryOpIC ic(isolate);
2706   RETURN_RESULT_OR_FAILURE(
2707       isolate, ic.Transition(Handle<AllocationSite>::null(), left, right));
2708 }
2709 
2710 
RUNTIME_FUNCTION(Runtime_BinaryOpIC_MissWithAllocationSite)2711 RUNTIME_FUNCTION(Runtime_BinaryOpIC_MissWithAllocationSite) {
2712   TimerEventScope<TimerEventIcMiss> timer(isolate);
2713   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2714   HandleScope scope(isolate);
2715   DCHECK_EQ(3, args.length());
2716   Handle<AllocationSite> allocation_site =
2717       args.at<AllocationSite>(BinaryOpWithAllocationSiteStub::kAllocationSite);
2718   Handle<Object> left = args.at<Object>(BinaryOpWithAllocationSiteStub::kLeft);
2719   Handle<Object> right =
2720       args.at<Object>(BinaryOpWithAllocationSiteStub::kRight);
2721   BinaryOpIC ic(isolate);
2722   RETURN_RESULT_OR_FAILURE(isolate,
2723                            ic.Transition(allocation_site, left, right));
2724 }
2725 
GetRawUninitialized(Isolate * isolate,Token::Value op)2726 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2727   CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED,
2728                      CompareICState::UNINITIALIZED,
2729                      CompareICState::UNINITIALIZED);
2730   Code* code = NULL;
2731   CHECK(stub.FindCodeInCache(&code));
2732   return code;
2733 }
2734 
GetUninitialized(Isolate * isolate,Token::Value op)2735 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
2736   CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED,
2737                      CompareICState::UNINITIALIZED,
2738                      CompareICState::UNINITIALIZED);
2739   return stub.GetCode();
2740 }
2741 
2742 
UpdateCaches(Handle<Object> x,Handle<Object> y)2743 Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
2744   HandleScope scope(isolate());
2745   CompareICStub old_stub(target()->stub_key(), isolate());
2746   CompareICState::State new_left =
2747       CompareICState::NewInputState(old_stub.left(), x);
2748   CompareICState::State new_right =
2749       CompareICState::NewInputState(old_stub.right(), y);
2750   CompareICState::State state = CompareICState::TargetState(
2751       isolate(), old_stub.state(), old_stub.left(), old_stub.right(), op_,
2752       HasInlinedSmiCode(address()), x, y);
2753   CompareICStub stub(isolate(), op_, new_left, new_right, state);
2754   if (state == CompareICState::KNOWN_RECEIVER) {
2755     stub.set_known_map(
2756         Handle<Map>(Handle<JSReceiver>::cast(x)->map(), isolate()));
2757   }
2758   Handle<Code> new_target = stub.GetCode();
2759   set_target(*new_target);
2760 
2761   if (FLAG_trace_ic) {
2762     PrintF("[CompareIC in ");
2763     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2764     PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
2765            CompareICState::GetStateName(old_stub.left()),
2766            CompareICState::GetStateName(old_stub.right()),
2767            CompareICState::GetStateName(old_stub.state()),
2768            CompareICState::GetStateName(new_left),
2769            CompareICState::GetStateName(new_right),
2770            CompareICState::GetStateName(state), Token::Name(op_),
2771            static_cast<void*>(*stub.GetCode()));
2772   }
2773 
2774   // Activate inlined smi code.
2775   if (old_stub.state() == CompareICState::UNINITIALIZED) {
2776     PatchInlinedSmiCode(isolate(), address(), ENABLE_INLINED_SMI_CHECK);
2777   }
2778 
2779   return *new_target;
2780 }
2781 
2782 
2783 // Used from CompareICStub::GenerateMiss in code-stubs-<arch>.cc.
RUNTIME_FUNCTION(Runtime_CompareIC_Miss)2784 RUNTIME_FUNCTION(Runtime_CompareIC_Miss) {
2785   TimerEventScope<TimerEventIcMiss> timer(isolate);
2786   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2787   HandleScope scope(isolate);
2788   DCHECK(args.length() == 3);
2789   CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2790   return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2791 }
2792 
2793 
RUNTIME_FUNCTION(Runtime_Unreachable)2794 RUNTIME_FUNCTION(Runtime_Unreachable) {
2795   UNREACHABLE();
2796   CHECK(false);
2797   return isolate->heap()->undefined_value();
2798 }
2799 
2800 
ToBoolean(Handle<Object> object)2801 Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) {
2802   ToBooleanICStub stub(isolate(), extra_ic_state());
2803   bool to_boolean_value = stub.UpdateStatus(object);
2804   Handle<Code> code = stub.GetCode();
2805   set_target(*code);
2806   return isolate()->factory()->ToBoolean(to_boolean_value);
2807 }
2808 
2809 
RUNTIME_FUNCTION(Runtime_ToBooleanIC_Miss)2810 RUNTIME_FUNCTION(Runtime_ToBooleanIC_Miss) {
2811   TimerEventScope<TimerEventIcMiss> timer(isolate);
2812   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
2813   DCHECK(args.length() == 1);
2814   HandleScope scope(isolate);
2815   Handle<Object> object = args.at<Object>(0);
2816   ToBooleanIC ic(isolate);
2817   return *ic.ToBoolean(object);
2818 }
2819 
2820 
RUNTIME_FUNCTION(Runtime_StoreCallbackProperty)2821 RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
2822   Handle<JSObject> receiver = args.at<JSObject>(0);
2823   Handle<JSObject> holder = args.at<JSObject>(1);
2824   Handle<HeapObject> callback_or_cell = args.at<HeapObject>(2);
2825   Handle<Name> name = args.at<Name>(3);
2826   Handle<Object> value = args.at<Object>(4);
2827   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 5);
2828   HandleScope scope(isolate);
2829 
2830   if (FLAG_runtime_call_stats) {
2831     RETURN_RESULT_OR_FAILURE(
2832         isolate, Runtime::SetObjectProperty(isolate, receiver, name, value,
2833                                             language_mode));
2834   }
2835 
2836   Handle<AccessorInfo> callback(
2837       callback_or_cell->IsWeakCell()
2838           ? AccessorInfo::cast(WeakCell::cast(*callback_or_cell)->value())
2839           : AccessorInfo::cast(*callback_or_cell));
2840 
2841   DCHECK(callback->IsCompatibleReceiver(*receiver));
2842 
2843   Address setter_address = v8::ToCData<Address>(callback->setter());
2844   v8::AccessorNameSetterCallback fun =
2845       FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address);
2846   DCHECK(fun != NULL);
2847 
2848   Object::ShouldThrow should_throw =
2849       is_sloppy(language_mode) ? Object::DONT_THROW : Object::THROW_ON_ERROR;
2850   PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
2851                                         *holder, should_throw);
2852   custom_args.Call(fun, name, value);
2853   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2854   return *value;
2855 }
2856 
2857 
2858 /**
2859  * Attempts to load a property with an interceptor (which must be present),
2860  * but doesn't search the prototype chain.
2861  *
2862  * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
2863  * provide any value for the given name.
2864  */
RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptorOnly)2865 RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptorOnly) {
2866   DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength);
2867   Handle<Name> name =
2868       args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
2869   Handle<Object> receiver =
2870       args.at<Object>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
2871   Handle<JSObject> holder =
2872       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
2873   HandleScope scope(isolate);
2874 
2875   if (!receiver->IsJSReceiver()) {
2876     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2877         isolate, receiver, Object::ConvertReceiver(isolate, receiver));
2878   }
2879 
2880   InterceptorInfo* interceptor = holder->GetNamedInterceptor();
2881   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
2882                                       *holder, Object::DONT_THROW);
2883 
2884   v8::GenericNamedPropertyGetterCallback getter =
2885       v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
2886           interceptor->getter());
2887   Handle<Object> result = arguments.Call(getter, name);
2888 
2889   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2890 
2891   if (!result.is_null()) return *result;
2892   return isolate->heap()->no_interceptor_result_sentinel();
2893 }
2894 
2895 
2896 /**
2897  * Loads a property with an interceptor performing post interceptor
2898  * lookup if interceptor failed.
2899  */
RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor)2900 RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
2901   HandleScope scope(isolate);
2902   DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength);
2903   Handle<Name> name =
2904       args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
2905   Handle<Object> receiver =
2906       args.at<Object>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
2907   Handle<JSObject> holder =
2908       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
2909 
2910   if (!receiver->IsJSReceiver()) {
2911     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2912         isolate, receiver, Object::ConvertReceiver(isolate, receiver));
2913   }
2914 
2915   InterceptorInfo* interceptor = holder->GetNamedInterceptor();
2916   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
2917                                       *holder, Object::DONT_THROW);
2918 
2919   v8::GenericNamedPropertyGetterCallback getter =
2920       v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
2921           interceptor->getter());
2922   Handle<Object> result = arguments.Call(getter, name);
2923 
2924   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2925 
2926   if (!result.is_null()) return *result;
2927 
2928   LookupIterator it(receiver, name, holder);
2929   // Skip any lookup work until we hit the (possibly non-masking) interceptor.
2930   while (it.state() != LookupIterator::INTERCEPTOR ||
2931          !it.GetHolder<JSObject>().is_identical_to(holder)) {
2932     DCHECK(it.state() != LookupIterator::ACCESS_CHECK || it.HasAccess());
2933     it.Next();
2934   }
2935   // Skip past the interceptor.
2936   it.Next();
2937   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
2938 
2939   if (it.IsFound()) return *result;
2940 
2941 #ifdef DEBUG
2942   LoadICNexus nexus(isolate);
2943   LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2944   // It could actually be any kind of LoadICs here but the predicate handles
2945   // all the cases properly.
2946   DCHECK(!ic.ShouldThrowReferenceError());
2947 #endif
2948 
2949   return isolate->heap()->undefined_value();
2950 }
2951 
2952 
RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor)2953 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
2954   HandleScope scope(isolate);
2955   DCHECK(args.length() == 3);
2956   StoreICNexus nexus(isolate);
2957   StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2958   Handle<JSObject> receiver = args.at<JSObject>(0);
2959   Handle<Name> name = args.at<Name>(1);
2960   Handle<Object> value = args.at<Object>(2);
2961 
2962   DCHECK(receiver->HasNamedInterceptor());
2963   InterceptorInfo* interceptor = receiver->GetNamedInterceptor();
2964   DCHECK(!interceptor->non_masking());
2965   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
2966                                       *receiver, Object::DONT_THROW);
2967 
2968   v8::GenericNamedPropertySetterCallback setter =
2969       v8::ToCData<v8::GenericNamedPropertySetterCallback>(
2970           interceptor->setter());
2971   Handle<Object> result = arguments.Call(setter, name, value);
2972   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2973   if (!result.is_null()) return *value;
2974 
2975   LookupIterator it(receiver, name, receiver);
2976   // Skip past any access check on the receiver.
2977   if (it.state() == LookupIterator::ACCESS_CHECK) {
2978     DCHECK(it.HasAccess());
2979     it.Next();
2980   }
2981   // Skip past the interceptor on the receiver.
2982   DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
2983   it.Next();
2984 
2985   MAYBE_RETURN(Object::SetProperty(&it, value, ic.language_mode(),
2986                                    JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED),
2987                isolate->heap()->exception());
2988   return *value;
2989 }
2990 
2991 
RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor)2992 RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
2993   // TODO(verwaest): This should probably get the holder and receiver as input.
2994   HandleScope scope(isolate);
2995   Handle<JSObject> receiver = args.at<JSObject>(0);
2996   DCHECK(args.smi_at(1) >= 0);
2997   uint32_t index = args.smi_at(1);
2998 
2999   InterceptorInfo* interceptor = receiver->GetIndexedInterceptor();
3000   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
3001                                       *receiver, Object::DONT_THROW);
3002 
3003   v8::IndexedPropertyGetterCallback getter =
3004       v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
3005   Handle<Object> result = arguments.Call(getter, index);
3006 
3007   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
3008 
3009   if (result.is_null()) {
3010     LookupIterator it(isolate, receiver, index, receiver);
3011     DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
3012     it.Next();
3013     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3014                                        Object::GetProperty(&it));
3015   }
3016 
3017   return *result;
3018 }
3019 
3020 
RUNTIME_FUNCTION(Runtime_LoadIC_MissFromStubFailure)3021 RUNTIME_FUNCTION(Runtime_LoadIC_MissFromStubFailure) {
3022   TimerEventScope<TimerEventIcMiss> timer(isolate);
3023   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
3024   HandleScope scope(isolate);
3025   Handle<Object> receiver = args.at<Object>(0);
3026   Handle<Name> key = args.at<Name>(1);
3027 
3028   DCHECK(args.length() == 4);
3029   Handle<Smi> slot = args.at<Smi>(2);
3030   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
3031   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
3032   // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
3033   // LoadIC miss handler if the handler misses. Since the vector Nexus is
3034   // set up outside the IC, handle that here.
3035   if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::LOAD_IC) {
3036     LoadICNexus nexus(vector, vector_slot);
3037     LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
3038     ic.UpdateState(receiver, key);
3039     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
3040   } else {
3041     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC,
3042               vector->GetKind(vector_slot));
3043     KeyedLoadICNexus nexus(vector, vector_slot);
3044     KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
3045     ic.UpdateState(receiver, key);
3046     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
3047   }
3048 }
3049 }  // namespace internal
3050 }  // namespace v8
3051