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