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