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