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