- add third_party src.
[platform/framework/web/crosswalk.git] / src / v8 / src / ic.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "accessors.h"
31 #include "api.h"
32 #include "arguments.h"
33 #include "codegen.h"
34 #include "execution.h"
35 #include "ic-inl.h"
36 #include "runtime.h"
37 #include "stub-cache.h"
38
39 namespace v8 {
40 namespace internal {
41
42 #ifdef DEBUG
43 char IC::TransitionMarkFromState(IC::State state) {
44   switch (state) {
45     case UNINITIALIZED: return '0';
46     case PREMONOMORPHIC: return '.';
47     case MONOMORPHIC: return '1';
48     case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
49     case POLYMORPHIC: return 'P';
50     case MEGAMORPHIC: return 'N';
51     case GENERIC: return 'G';
52
53     // We never see the debugger states here, because the state is
54     // computed from the original code - not the patched code. Let
55     // these cases fall through to the unreachable code below.
56     case DEBUG_STUB: break;
57   }
58   UNREACHABLE();
59   return 0;
60 }
61
62
63 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
64   if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
65   if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
66     return ".IGNORE_OOB";
67   }
68   if (IsGrowStoreMode(mode)) return ".GROW";
69   return "";
70 }
71
72
73 void IC::TraceIC(const char* type,
74                  Handle<Object> name) {
75   if (FLAG_trace_ic) {
76     Code* new_target = raw_target();
77     State new_state = new_target->ic_state();
78     PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
79     StackFrameIterator it(isolate());
80     while (it.frame()->fp() != this->fp()) it.Advance();
81     StackFrame* raw_frame = it.frame();
82     if (raw_frame->is_internal()) {
83       Code* apply_builtin = isolate()->builtins()->builtin(
84           Builtins::kFunctionApply);
85       if (raw_frame->unchecked_code() == apply_builtin) {
86         PrintF("apply from ");
87         it.Advance();
88         raw_frame = it.frame();
89       }
90     }
91     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
92     Code::ExtraICState extra_state = new_target->extra_ic_state();
93     const char* modifier =
94         GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(extra_state));
95     PrintF(" (%c->%c%s)",
96            TransitionMarkFromState(state()),
97            TransitionMarkFromState(new_state),
98            modifier);
99     name->Print();
100     PrintF("]\n");
101   }
102 }
103
104 #define TRACE_GENERIC_IC(isolate, type, reason)                 \
105   do {                                                          \
106     if (FLAG_trace_ic) {                                        \
107       PrintF("[%s patching generic stub in ", type);            \
108       JavaScriptFrame::PrintTop(isolate, stdout, false, true);  \
109       PrintF(" (%s)]\n", reason);                               \
110     }                                                           \
111   } while (false)
112
113 #else
114 #define TRACE_GENERIC_IC(isolate, type, reason)
115 #endif  // DEBUG
116
117 #define TRACE_IC(type, name)             \
118   ASSERT((TraceIC(type, name), true))
119
120 IC::IC(FrameDepth depth, Isolate* isolate)
121     : isolate_(isolate),
122       target_set_(false) {
123   // To improve the performance of the (much used) IC code, we unfold a few
124   // levels of the stack frame iteration code. This yields a ~35% speedup when
125   // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
126   const Address entry =
127       Isolate::c_entry_fp(isolate->thread_local_top());
128   Address* pc_address =
129       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
130   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
131   // If there's another JavaScript frame on the stack or a
132   // StubFailureTrampoline, we need to look one frame further down the stack to
133   // find the frame pointer and the return address stack slot.
134   if (depth == EXTRA_CALL_FRAME) {
135     const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
136     pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
137     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
138   }
139 #ifdef DEBUG
140   StackFrameIterator it(isolate);
141   for (int i = 0; i < depth + 1; i++) it.Advance();
142   StackFrame* frame = it.frame();
143   ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
144 #endif
145   fp_ = fp;
146   pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
147   target_ = handle(raw_target(), isolate);
148   state_ = target_->ic_state();
149 }
150
151
152 #ifdef ENABLE_DEBUGGER_SUPPORT
153 Address IC::OriginalCodeAddress() const {
154   HandleScope scope(isolate());
155   // Compute the JavaScript frame for the frame pointer of this IC
156   // structure. We need this to be able to find the function
157   // corresponding to the frame.
158   StackFrameIterator it(isolate());
159   while (it.frame()->fp() != this->fp()) it.Advance();
160   JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
161   // Find the function on the stack and both the active code for the
162   // function and the original code.
163   JSFunction* function = frame->function();
164   Handle<SharedFunctionInfo> shared(function->shared(), isolate());
165   Code* code = shared->code();
166   ASSERT(Debug::HasDebugInfo(shared));
167   Code* original_code = Debug::GetDebugInfo(shared)->original_code();
168   ASSERT(original_code->IsCode());
169   // Get the address of the call site in the active code. This is the
170   // place where the call to DebugBreakXXX is and where the IC
171   // normally would be.
172   Address addr = Assembler::target_address_from_return_address(pc());
173   // Return the address in the original code. This is the place where
174   // the call which has been overwritten by the DebugBreakXXX resides
175   // and the place where the inline cache system should look.
176   intptr_t delta =
177       original_code->instruction_start() - code->instruction_start();
178   return addr + delta;
179 }
180 #endif
181
182
183 static bool HasInterceptorGetter(JSObject* object) {
184   return !object->GetNamedInterceptor()->getter()->IsUndefined();
185 }
186
187
188 static bool HasInterceptorSetter(JSObject* object) {
189   return !object->GetNamedInterceptor()->setter()->IsUndefined();
190 }
191
192
193 static void LookupForRead(Handle<Object> object,
194                           Handle<String> name,
195                           LookupResult* lookup) {
196   // Skip all the objects with named interceptors, but
197   // without actual getter.
198   while (true) {
199     object->Lookup(*name, lookup);
200     // Besides normal conditions (property not found or it's not
201     // an interceptor), bail out if lookup is not cacheable: we won't
202     // be able to IC it anyway and regular lookup should work fine.
203     if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
204       return;
205     }
206
207     Handle<JSObject> holder(lookup->holder(), lookup->isolate());
208     if (HasInterceptorGetter(*holder)) {
209       return;
210     }
211
212     holder->LocalLookupRealNamedProperty(*name, lookup);
213     if (lookup->IsFound()) {
214       ASSERT(!lookup->IsInterceptor());
215       return;
216     }
217
218     Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
219     if (proto->IsNull()) {
220       ASSERT(!lookup->IsFound());
221       return;
222     }
223
224     object = proto;
225   }
226 }
227
228
229 bool CallIC::TryUpdateExtraICState(LookupResult* lookup,
230                                    Handle<Object> object) {
231   if (!lookup->IsConstantFunction()) return false;
232   JSFunction* function = lookup->GetConstantFunction();
233   if (!function->shared()->HasBuiltinFunctionId()) return false;
234
235   // Fetch the arguments passed to the called function.
236   const int argc = target()->arguments_count();
237   Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
238   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
239   Arguments args(argc + 1,
240                  &Memory::Object_at(fp +
241                                     StandardFrameConstants::kCallerSPOffset +
242                                     argc * kPointerSize));
243   switch (function->shared()->builtin_function_id()) {
244     case kStringCharCodeAt:
245     case kStringCharAt:
246       if (object->IsString()) {
247         String* string = String::cast(*object);
248         // Check there's the right string value or wrapper in the receiver slot.
249         ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
250         // If we're in the default (fastest) state and the index is
251         // out of bounds, update the state to record this fact.
252         if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB &&
253             argc >= 1 && args[1]->IsNumber()) {
254           double index = DoubleToInteger(args.number_at(1));
255           if (index < 0 || index >= string->length()) {
256             extra_ic_state_ =
257                 StringStubState::update(extra_ic_state(),
258                                         STRING_INDEX_OUT_OF_BOUNDS);
259             return true;
260           }
261         }
262       }
263       break;
264     default:
265       return false;
266   }
267   return false;
268 }
269
270
271 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
272                                                 Handle<String> name) {
273   DisallowHeapAllocation no_gc;
274
275   if (target()->is_call_stub()) {
276     LookupResult lookup(isolate());
277     LookupForRead(receiver, name, &lookup);
278     if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) {
279       return true;
280     }
281   }
282
283   if (target()->is_keyed_stub()) {
284     // Determine whether the failure is due to a name failure.
285     if (!name->IsName()) return false;
286     Name* stub_name = target()->FindFirstName();
287     if (*name != stub_name) return false;
288   }
289
290   InlineCacheHolderFlag cache_holder =
291       Code::ExtractCacheHolderFromFlags(target()->flags());
292
293   switch (cache_holder) {
294     case OWN_MAP:
295       // The stub was generated for JSObject but called for non-JSObject.
296       // IC::GetCodeCacheHolder is not applicable.
297       if (!receiver->IsJSObject()) return false;
298       break;
299     case PROTOTYPE_MAP:
300       // IC::GetCodeCacheHolder is not applicable.
301       if (receiver->GetPrototype(isolate())->IsNull()) return false;
302       break;
303   }
304
305   Handle<Map> map(
306       IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map());
307
308   // Decide whether the inline cache failed because of changes to the
309   // receiver itself or changes to one of its prototypes.
310   //
311   // If there are changes to the receiver itself, the map of the
312   // receiver will have changed and the current target will not be in
313   // the receiver map's code cache.  Therefore, if the current target
314   // is in the receiver map's code cache, the inline cache failed due
315   // to prototype check failure.
316   int index = map->IndexInCodeCache(*name, *target());
317   if (index >= 0) {
318     map->RemoveFromCodeCache(*name, *target(), index);
319     // Handlers are stored in addition to the ICs on the map. Remove those, too.
320     TryRemoveInvalidHandlers(map, name);
321     return true;
322   }
323
324   // The stub is not in the cache. We've ruled out all other kinds of failure
325   // except for proptotype chain changes, a deprecated map, a map that's
326   // different from the one that the stub expects, elements kind changes, or a
327   // constant global property that will become mutable. Threat all those
328   // situations as prototype failures (stay monomorphic if possible).
329
330   // If the IC is shared between multiple receivers (slow dictionary mode), then
331   // the map cannot be deprecated and the stub invalidated.
332   if (cache_holder == OWN_MAP) {
333     Map* old_map = target()->FindFirstMap();
334     if (old_map == *map) return true;
335     if (old_map != NULL) {
336       if (old_map->is_deprecated()) return true;
337       if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
338                                               map->elements_kind())) {
339         return true;
340       }
341     }
342   }
343
344   if (receiver->IsGlobalObject()) {
345     LookupResult lookup(isolate());
346     GlobalObject* global = GlobalObject::cast(*receiver);
347     global->LocalLookupRealNamedProperty(*name, &lookup);
348     if (!lookup.IsFound()) return false;
349     PropertyCell* cell = global->GetPropertyCell(&lookup);
350     return cell->type()->IsConstant();
351   }
352
353   return false;
354 }
355
356
357 void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) {
358   CodeHandleList handlers;
359   target()->FindHandlers(&handlers);
360   for (int i = 0; i < handlers.length(); i++) {
361     Handle<Code> handler = handlers.at(i);
362     int index = map->IndexInCodeCache(*name, *handler);
363     if (index >= 0) {
364       map->RemoveFromCodeCache(*name, *handler, index);
365       return;
366     }
367   }
368 }
369
370
371 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
372   if (!name->IsString()) return;
373   if (state() != MONOMORPHIC) {
374     if (state() == POLYMORPHIC && receiver->IsHeapObject()) {
375       TryRemoveInvalidHandlers(
376           handle(Handle<HeapObject>::cast(receiver)->map()),
377           Handle<String>::cast(name));
378     }
379     return;
380   }
381   if (receiver->IsUndefined() || receiver->IsNull()) return;
382
383   // Remove the target from the code cache if it became invalid
384   // because of changes in the prototype chain to avoid hitting it
385   // again.
386   if (TryRemoveInvalidPrototypeDependentStub(
387           receiver, Handle<String>::cast(name))) {
388     return MarkMonomorphicPrototypeFailure();
389   }
390
391   // The builtins object is special.  It only changes when JavaScript
392   // builtins are loaded lazily.  It is important to keep inline
393   // caches for the builtins object monomorphic.  Therefore, if we get
394   // an inline cache miss for the builtins object after lazily loading
395   // JavaScript builtins, we return uninitialized as the state to
396   // force the inline cache back to monomorphic state.
397   if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED;
398 }
399
400
401 RelocInfo::Mode IC::ComputeMode() {
402   Address addr = address();
403   Code* code = Code::cast(isolate()->FindCodeObject(addr));
404   for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
405        !it.done(); it.next()) {
406     RelocInfo* info = it.rinfo();
407     if (info->pc() == addr) return info->rmode();
408   }
409   UNREACHABLE();
410   return RelocInfo::NONE32;
411 }
412
413
414 Failure* IC::TypeError(const char* type,
415                        Handle<Object> object,
416                        Handle<Object> key) {
417   HandleScope scope(isolate());
418   Handle<Object> args[2] = { key, object };
419   Handle<Object> error = isolate()->factory()->NewTypeError(
420       type, HandleVector(args, 2));
421   return isolate()->Throw(*error);
422 }
423
424
425 Failure* IC::ReferenceError(const char* type, Handle<String> name) {
426   HandleScope scope(isolate());
427   Handle<Object> error = isolate()->factory()->NewReferenceError(
428       type, HandleVector(&name, 1));
429   return isolate()->Throw(*error);
430 }
431
432
433 static int ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state) {
434   bool was_uninitialized =
435       old_state == UNINITIALIZED || old_state == PREMONOMORPHIC;
436   bool is_uninitialized =
437       new_state == UNINITIALIZED || new_state == PREMONOMORPHIC;
438   return (was_uninitialized && !is_uninitialized) ?  1 :
439          (!was_uninitialized && is_uninitialized) ? -1 : 0;
440 }
441
442
443 void IC::PostPatching(Address address, Code* target, Code* old_target) {
444   if (FLAG_type_info_threshold == 0 && !FLAG_watch_ic_patching) {
445     return;
446   }
447   Isolate* isolate = target->GetHeap()->isolate();
448   Code* host = isolate->
449       inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
450   if (host->kind() != Code::FUNCTION) return;
451
452   if (FLAG_type_info_threshold > 0 &&
453       old_target->is_inline_cache_stub() &&
454       target->is_inline_cache_stub()) {
455     int delta = ComputeTypeInfoCountDelta(old_target->ic_state(),
456                                           target->ic_state());
457     // Not all Code objects have TypeFeedbackInfo.
458     if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) {
459       TypeFeedbackInfo* info =
460           TypeFeedbackInfo::cast(host->type_feedback_info());
461       info->change_ic_with_type_info_count(delta);
462     }
463   }
464   if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
465     TypeFeedbackInfo* info =
466         TypeFeedbackInfo::cast(host->type_feedback_info());
467     info->change_own_type_change_checksum();
468   }
469   if (FLAG_watch_ic_patching) {
470     host->set_profiler_ticks(0);
471     isolate->runtime_profiler()->NotifyICChanged();
472   }
473   // TODO(2029): When an optimized function is patched, it would
474   // be nice to propagate the corresponding type information to its
475   // unoptimized version for the benefit of later inlining.
476 }
477
478
479 void IC::Clear(Isolate* isolate, Address address) {
480   Code* target = GetTargetAtAddress(address);
481
482   // Don't clear debug break inline cache as it will remove the break point.
483   if (target->is_debug_stub()) return;
484
485   switch (target->kind()) {
486     case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target);
487     case Code::KEYED_LOAD_IC:
488       return KeyedLoadIC::Clear(isolate, address, target);
489     case Code::STORE_IC: return StoreIC::Clear(isolate, address, target);
490     case Code::KEYED_STORE_IC:
491       return KeyedStoreIC::Clear(isolate, address, target);
492     case Code::CALL_IC: return CallIC::Clear(address, target);
493     case Code::KEYED_CALL_IC:  return KeyedCallIC::Clear(address, target);
494     case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target);
495     case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target);
496     case Code::BINARY_OP_IC:
497     case Code::TO_BOOLEAN_IC:
498       // Clearing these is tricky and does not
499       // make any performance difference.
500       return;
501     default: UNREACHABLE();
502   }
503 }
504
505
506 void CallICBase::Clear(Address address, Code* target) {
507   if (IsCleared(target)) return;
508   bool contextual = CallICBase::Contextual::decode(target->extra_ic_state());
509   Code* code =
510       target->GetIsolate()->stub_cache()->FindCallInitialize(
511           target->arguments_count(),
512           contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET,
513           target->kind());
514   SetTargetAtAddress(address, code);
515 }
516
517
518 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) {
519   if (IsCleared(target)) return;
520   // Make sure to also clear the map used in inline fast cases.  If we
521   // do not clear these maps, cached code can keep objects alive
522   // through the embedded maps.
523   SetTargetAtAddress(address, *pre_monomorphic_stub(isolate));
524 }
525
526
527 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) {
528   if (IsCleared(target)) return;
529   SetTargetAtAddress(address, *pre_monomorphic_stub(isolate));
530 }
531
532
533 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) {
534   if (IsCleared(target)) return;
535   SetTargetAtAddress(address,
536       *pre_monomorphic_stub(
537           isolate, Code::GetStrictMode(target->extra_ic_state())));
538 }
539
540
541 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) {
542   if (IsCleared(target)) return;
543   SetTargetAtAddress(address,
544       *pre_monomorphic_stub(
545           isolate, Code::GetStrictMode(target->extra_ic_state())));
546 }
547
548
549 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) {
550   ASSERT(target->major_key() == CodeStub::CompareIC);
551   CompareIC::State handler_state;
552   Token::Value op;
553   ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL,
554                                 &handler_state, &op);
555   // Only clear CompareICs that can retain objects.
556   if (handler_state != KNOWN_OBJECT) return;
557   SetTargetAtAddress(address, GetRawUninitialized(isolate, op));
558   PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
559 }
560
561
562 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) {
563   Handle<Object> delegate = Execution::GetFunctionDelegate(isolate(), object);
564
565   if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) {
566     // Patch the receiver and use the delegate as the function to
567     // invoke. This is used for invoking objects as if they were functions.
568     const int argc = target()->arguments_count();
569     StackFrameLocator locator(isolate());
570     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
571     int index = frame->ComputeExpressionsCount() - (argc + 1);
572     frame->SetExpression(index, *object);
573   }
574
575   return delegate;
576 }
577
578
579 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee,
580                                             Handle<Object> object) {
581   while (callee->IsJSFunctionProxy()) {
582     callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap(),
583                             isolate());
584   }
585
586   if (callee->IsJSFunction()) {
587     Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
588     if (!function->shared()->is_classic_mode() || function->IsBuiltin()) {
589       // Do not wrap receiver for strict mode functions or for builtins.
590       return;
591     }
592   }
593
594   // And only wrap string, number or boolean.
595   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
596     // Change the receiver to the result of calling ToObject on it.
597     const int argc = this->target()->arguments_count();
598     StackFrameLocator locator(isolate());
599     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
600     int index = frame->ComputeExpressionsCount() - (argc + 1);
601     frame->SetExpression(index, *isolate()->factory()->ToObject(object));
602   }
603 }
604
605
606 static bool MigrateDeprecated(Handle<Object> object) {
607   if (!object->IsJSObject()) return false;
608   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
609   if (!receiver->map()->is_deprecated()) return false;
610   JSObject::MigrateInstance(Handle<JSObject>::cast(object));
611   return true;
612 }
613
614
615 MaybeObject* CallICBase::LoadFunction(Handle<Object> object,
616                                       Handle<String> name) {
617   bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
618
619   // If the object is undefined or null it's illegal to try to get any
620   // of its properties; throw a TypeError in that case.
621   if (object->IsUndefined() || object->IsNull()) {
622     return TypeError("non_object_property_call", object, name);
623   }
624
625   // Check if the name is trivially convertible to an index and get
626   // the element if so.
627   uint32_t index;
628   if (name->AsArrayIndex(&index)) {
629     Handle<Object> result = Object::GetElement(isolate(), object, index);
630     RETURN_IF_EMPTY_HANDLE(isolate(), result);
631     if (result->IsJSFunction()) return *result;
632
633     // Try to find a suitable function delegate for the object at hand.
634     result = TryCallAsFunction(result);
635     if (result->IsJSFunction()) return *result;
636
637     // Otherwise, it will fail in the lookup step.
638   }
639
640   // Lookup the property in the object.
641   LookupResult lookup(isolate());
642   LookupForRead(object, name, &lookup);
643
644   if (!lookup.IsFound()) {
645     // If the object does not have the requested property, check which
646     // exception we need to throw.
647     return IsUndeclaredGlobal(object)
648         ? ReferenceError("not_defined", name)
649         : TypeError("undefined_method", object, name);
650   }
651
652   // Lookup is valid: Update inline cache and stub cache.
653   if (use_ic) UpdateCaches(&lookup, object, name);
654
655   // Get the property.
656   PropertyAttributes attr;
657   Handle<Object> result =
658       Object::GetProperty(object, object, &lookup, name, &attr);
659   RETURN_IF_EMPTY_HANDLE(isolate(), result);
660
661   if (lookup.IsInterceptor() && attr == ABSENT) {
662     // If the object does not have the requested property, check which
663     // exception we need to throw.
664     return IsUndeclaredGlobal(object)
665         ? ReferenceError("not_defined", name)
666         : TypeError("undefined_method", object, name);
667   }
668
669   ASSERT(!result->IsTheHole());
670
671   // Make receiver an object if the callee requires it. Strict mode or builtin
672   // functions do not wrap the receiver, non-strict functions and objects
673   // called as functions do.
674   ReceiverToObjectIfRequired(result, object);
675
676   if (result->IsJSFunction()) {
677     Handle<JSFunction> function = Handle<JSFunction>::cast(result);
678 #ifdef ENABLE_DEBUGGER_SUPPORT
679     // Handle stepping into a function if step into is active.
680     Debug* debug = isolate()->debug();
681     if (debug->StepInActive()) {
682       // Protect the result in a handle as the debugger can allocate and might
683       // cause GC.
684       debug->HandleStepIn(function, object, fp(), false);
685     }
686 #endif
687     return *function;
688   }
689
690   // Try to find a suitable function delegate for the object at hand.
691   result = TryCallAsFunction(result);
692   if (result->IsJSFunction()) return *result;
693
694   return TypeError("property_not_function", object, name);
695 }
696
697
698 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
699                                                 Handle<Object> object,
700                                                 Handle<String> name) {
701   int argc = target()->arguments_count();
702   Handle<JSObject> holder(lookup->holder(), isolate());
703   switch (lookup->type()) {
704     case FIELD: {
705       PropertyIndex index = lookup->GetFieldIndex();
706       return isolate()->stub_cache()->ComputeCallField(
707           argc, kind_, extra_ic_state(), name, object, holder, index);
708     }
709     case CONSTANT: {
710       if (!lookup->IsConstantFunction()) return Handle<Code>::null();
711       // Get the constant function and compute the code stub for this
712       // call; used for rewriting to monomorphic state and making sure
713       // that the code stub is in the stub cache.
714       Handle<JSFunction> function(lookup->GetConstantFunction(), isolate());
715       return isolate()->stub_cache()->ComputeCallConstant(
716           argc, kind_, extra_ic_state(), name, object, holder, function);
717     }
718     case NORMAL: {
719       // If we return a null handle, the IC will not be patched.
720       if (!object->IsJSObject()) return Handle<Code>::null();
721       Handle<JSObject> receiver = Handle<JSObject>::cast(object);
722
723       if (holder->IsGlobalObject()) {
724         Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
725         Handle<PropertyCell> cell(
726             global->GetPropertyCell(lookup), isolate());
727         if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
728         Handle<JSFunction> function(JSFunction::cast(cell->value()));
729         return isolate()->stub_cache()->ComputeCallGlobal(
730             argc, kind_, extra_ic_state(), name,
731             receiver, global, cell, function);
732       } else {
733         // There is only one shared stub for calling normalized
734         // properties. It does not traverse the prototype chain, so the
735         // property must be found in the receiver for the stub to be
736         // applicable.
737         if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
738         return isolate()->stub_cache()->ComputeCallNormal(
739             argc, kind_, extra_ic_state());
740       }
741       break;
742     }
743     case INTERCEPTOR:
744       ASSERT(HasInterceptorGetter(*holder));
745       return isolate()->stub_cache()->ComputeCallInterceptor(
746           argc, kind_, extra_ic_state(), name, object, holder);
747     default:
748       return Handle<Code>::null();
749   }
750 }
751
752
753 Handle<Code> CallICBase::megamorphic_stub() {
754   return isolate()->stub_cache()->ComputeCallMegamorphic(
755       target()->arguments_count(), kind_, extra_ic_state());
756 }
757
758
759 Handle<Code> CallICBase::pre_monomorphic_stub() {
760   return isolate()->stub_cache()->ComputeCallPreMonomorphic(
761       target()->arguments_count(), kind_, extra_ic_state());
762 }
763
764
765 void CallICBase::UpdateCaches(LookupResult* lookup,
766                               Handle<Object> object,
767                               Handle<String> name) {
768   // Bail out if we didn't find a result.
769   if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
770
771   // Compute the number of arguments.
772   Handle<Code> code;
773   code = state() == UNINITIALIZED
774       ? pre_monomorphic_stub()
775       : ComputeMonomorphicStub(lookup, object, name);
776
777   // If there's no appropriate stub we simply avoid updating the caches.
778   // TODO(verwaest): Install a slow fallback in this case to avoid not learning,
779   // and deopting Crankshaft code.
780   if (code.is_null()) return;
781
782   Handle<JSObject> cache_object = object->IsJSObject()
783       ? Handle<JSObject>::cast(object)
784       : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
785                          isolate());
786
787   PatchCache(cache_object, name, code);
788   TRACE_IC("CallIC", name);
789 }
790
791
792 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object,
793                                        Handle<Object> key) {
794   if (key->IsInternalizedString()) {
795     return CallICBase::LoadFunction(object, Handle<String>::cast(key));
796   }
797
798   if (object->IsUndefined() || object->IsNull()) {
799     return TypeError("non_object_property_call", object, key);
800   }
801
802   bool use_ic = MigrateDeprecated(object)
803       ? false : FLAG_use_ic && !object->IsAccessCheckNeeded();
804
805   if (use_ic && state() != MEGAMORPHIC) {
806     ASSERT(!object->IsJSGlobalProxy());
807     int argc = target()->arguments_count();
808     Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic(
809         argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
810     if (object->IsJSObject()) {
811       Handle<JSObject> receiver = Handle<JSObject>::cast(object);
812       if (receiver->elements()->map() ==
813           isolate()->heap()->non_strict_arguments_elements_map()) {
814         stub = isolate()->stub_cache()->ComputeCallArguments(argc);
815       }
816     }
817     ASSERT(!stub.is_null());
818     set_target(*stub);
819     TRACE_IC("CallIC", key);
820   }
821
822   Handle<Object> result = GetProperty(isolate(), object, key);
823   RETURN_IF_EMPTY_HANDLE(isolate(), result);
824
825   // Make receiver an object if the callee requires it. Strict mode or builtin
826   // functions do not wrap the receiver, non-strict functions and objects
827   // called as functions do.
828   ReceiverToObjectIfRequired(result, object);
829   if (result->IsJSFunction()) return *result;
830
831   result = TryCallAsFunction(result);
832   if (result->IsJSFunction()) return *result;
833
834   return TypeError("property_not_function", object, key);
835 }
836
837
838 MaybeObject* LoadIC::Load(Handle<Object> object,
839                           Handle<String> name) {
840   // If the object is undefined or null it's illegal to try to get any
841   // of its properties; throw a TypeError in that case.
842   if (object->IsUndefined() || object->IsNull()) {
843     return TypeError("non_object_property_load", object, name);
844   }
845
846   if (FLAG_use_ic) {
847     // Use specialized code for getting the length of strings and
848     // string wrapper objects.  The length property of string wrapper
849     // objects is read-only and therefore always returns the length of
850     // the underlying string value.  See ECMA-262 15.5.5.1.
851     if (object->IsStringWrapper() &&
852         name->Equals(isolate()->heap()->length_string())) {
853       Handle<Code> stub;
854       if (state() == UNINITIALIZED) {
855         stub = pre_monomorphic_stub();
856       } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) {
857         StringLengthStub string_length_stub(kind());
858         stub = string_length_stub.GetCode(isolate());
859       } else if (state() != MEGAMORPHIC) {
860         ASSERT(state() != GENERIC);
861         stub = megamorphic_stub();
862       }
863       if (!stub.is_null()) {
864         set_target(*stub);
865 #ifdef DEBUG
866         if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n");
867 #endif
868       }
869       // Get the string if we have a string wrapper object.
870       String* string = String::cast(JSValue::cast(*object)->value());
871       return Smi::FromInt(string->length());
872     }
873
874     // Use specialized code for getting prototype of functions.
875     if (object->IsJSFunction() &&
876         name->Equals(isolate()->heap()->prototype_string()) &&
877         Handle<JSFunction>::cast(object)->should_have_prototype()) {
878       Handle<Code> stub;
879       if (state() == UNINITIALIZED) {
880         stub = pre_monomorphic_stub();
881       } else if (state() == PREMONOMORPHIC) {
882         FunctionPrototypeStub function_prototype_stub(kind());
883         stub = function_prototype_stub.GetCode(isolate());
884       } else if (state() != MEGAMORPHIC) {
885         ASSERT(state() != GENERIC);
886         stub = megamorphic_stub();
887       }
888       if (!stub.is_null()) {
889         set_target(*stub);
890 #ifdef DEBUG
891         if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
892 #endif
893       }
894       return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object));
895     }
896   }
897
898   // Check if the name is trivially convertible to an index and get
899   // the element or char if so.
900   uint32_t index;
901   if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
902     // Rewrite to the generic keyed load stub.
903     if (FLAG_use_ic) set_target(*generic_stub());
904     return Runtime::GetElementOrCharAtOrFail(isolate(), object, index);
905   }
906
907   bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
908
909   // Named lookup in the object.
910   LookupResult lookup(isolate());
911   LookupForRead(object, name, &lookup);
912
913   // If we did not find a property, check if we need to throw an exception.
914   if (!lookup.IsFound()) {
915     if (IsUndeclaredGlobal(object)) {
916       return ReferenceError("not_defined", name);
917     }
918     LOG(isolate(), SuspectReadEvent(*name, *object));
919   }
920
921   // Update inline cache and stub cache.
922   if (use_ic) UpdateCaches(&lookup, object, name);
923
924   PropertyAttributes attr;
925   // Get the property.
926   Handle<Object> result =
927       Object::GetProperty(object, object, &lookup, name, &attr);
928   RETURN_IF_EMPTY_HANDLE(isolate(), result);
929   // If the property is not present, check if we need to throw an
930   // exception.
931   if ((lookup.IsInterceptor() || lookup.IsHandler()) &&
932       attr == ABSENT && IsUndeclaredGlobal(object)) {
933     return ReferenceError("not_defined", name);
934   }
935   return *result;
936 }
937
938
939 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
940                                        Handle<Map> new_receiver_map) {
941   ASSERT(!new_receiver_map.is_null());
942   for (int current = 0; current < receiver_maps->length(); ++current) {
943     if (!receiver_maps->at(current).is_null() &&
944         receiver_maps->at(current).is_identical_to(new_receiver_map)) {
945       return false;
946     }
947   }
948   receiver_maps->Add(new_receiver_map);
949   return true;
950 }
951
952
953 bool IC::UpdatePolymorphicIC(Handle<HeapObject> receiver,
954                              Handle<String> name,
955                              Handle<Code> code) {
956   if (!code->is_handler()) return false;
957
958   MapHandleList receiver_maps;
959   CodeHandleList handlers;
960
961   int number_of_valid_maps;
962   int handler_to_overwrite = -1;
963   Handle<Map> new_receiver_map(receiver->map());
964   {
965     DisallowHeapAllocation no_gc;
966     target()->FindAllMaps(&receiver_maps);
967     int number_of_maps = receiver_maps.length();
968     number_of_valid_maps = number_of_maps;
969
970     for (int i = 0; i < number_of_maps; i++) {
971       Handle<Map> map = receiver_maps.at(i);
972       // Filter out deprecated maps to ensure its instances get migrated.
973       if (map->is_deprecated()) {
974         number_of_valid_maps--;
975       // If the receiver map is already in the polymorphic IC, this indicates
976       // there was a prototoype chain failure. In that case, just overwrite the
977       // handler.
978       } else if (map.is_identical_to(new_receiver_map)) {
979         number_of_valid_maps--;
980         handler_to_overwrite = i;
981       }
982     }
983
984     if (number_of_valid_maps >= 4) return false;
985     if (number_of_maps == 0) return false;
986
987     if (!target()->FindHandlers(&handlers, receiver_maps.length())) {
988       return false;
989     }
990   }
991
992   number_of_valid_maps++;
993   if (handler_to_overwrite >= 0) {
994     handlers.Set(handler_to_overwrite, code);
995   } else {
996     receiver_maps.Add(new_receiver_map);
997     handlers.Add(code);
998   }
999
1000   Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
1001       &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode());
1002   set_target(*ic);
1003   return true;
1004 }
1005
1006
1007 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1008                              Handle<Code> handler,
1009                              Handle<String> name) {
1010   if (!handler->is_handler()) return set_target(*handler);
1011   Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
1012       receiver, handler, name, strict_mode());
1013   set_target(*ic);
1014 }
1015
1016
1017 void IC::CopyICToMegamorphicCache(Handle<String> name) {
1018   MapHandleList receiver_maps;
1019   CodeHandleList handlers;
1020   {
1021     DisallowHeapAllocation no_gc;
1022     target()->FindAllMaps(&receiver_maps);
1023     if (!target()->FindHandlers(&handlers, receiver_maps.length())) return;
1024   }
1025   for (int i = 0; i < receiver_maps.length(); i++) {
1026     UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
1027   }
1028 }
1029
1030
1031 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) {
1032   DisallowHeapAllocation no_allocation;
1033
1034   Map* current_map = target()->FindFirstMap();
1035   ElementsKind receiver_elements_kind = receiver_map->elements_kind();
1036   bool more_general_transition =
1037       IsMoreGeneralElementsKindTransition(
1038         current_map->elements_kind(), receiver_elements_kind);
1039   Map* transitioned_map = more_general_transition
1040       ? current_map->LookupElementsTransitionMap(receiver_elements_kind)
1041       : NULL;
1042
1043   return transitioned_map == receiver_map;
1044 }
1045
1046
1047 void IC::PatchCache(Handle<HeapObject> receiver,
1048                     Handle<String> name,
1049                     Handle<Code> code) {
1050   switch (state()) {
1051     case UNINITIALIZED:
1052     case PREMONOMORPHIC:
1053     case MONOMORPHIC_PROTOTYPE_FAILURE:
1054       UpdateMonomorphicIC(receiver, code, name);
1055       break;
1056     case MONOMORPHIC:
1057       // For now, call stubs are allowed to rewrite to the same stub. This
1058       // happens e.g., when the field does not contain a function.
1059       ASSERT(target()->is_call_stub() ||
1060              target()->is_keyed_call_stub() ||
1061              !target().is_identical_to(code));
1062       if (!target()->is_keyed_stub()) {
1063         bool is_same_handler = false;
1064         {
1065           DisallowHeapAllocation no_allocation;
1066           Code* old_handler = target()->FindFirstHandler();
1067           is_same_handler = old_handler == *code;
1068         }
1069         if (is_same_handler
1070             && IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
1071           UpdateMonomorphicIC(receiver, code, name);
1072           break;
1073         }
1074         if (UpdatePolymorphicIC(receiver, name, code)) {
1075           break;
1076         }
1077
1078         CopyICToMegamorphicCache(name);
1079       }
1080
1081       UpdateMegamorphicCache(receiver->map(), *name, *code);
1082       set_target(*megamorphic_stub());
1083       break;
1084     case MEGAMORPHIC:
1085       UpdateMegamorphicCache(receiver->map(), *name, *code);
1086       break;
1087     case POLYMORPHIC:
1088       if (target()->is_keyed_stub()) {
1089         // When trying to patch a polymorphic keyed stub with anything other
1090         // than another polymorphic stub, go generic.
1091         set_target(*generic_stub());
1092       } else {
1093         if (UpdatePolymorphicIC(receiver, name, code)) {
1094           break;
1095         }
1096         CopyICToMegamorphicCache(name);
1097         UpdateMegamorphicCache(receiver->map(), *name, *code);
1098         set_target(*megamorphic_stub());
1099       }
1100       break;
1101     case DEBUG_STUB:
1102       break;
1103     case GENERIC:
1104       UNREACHABLE();
1105       break;
1106   }
1107 }
1108
1109
1110 Handle<Code> LoadIC::SimpleFieldLoad(int offset,
1111                                      bool inobject,
1112                                      Representation representation) {
1113   if (kind() == Code::LOAD_IC) {
1114     LoadFieldStub stub(inobject, offset, representation);
1115     return stub.GetCode(isolate());
1116   } else {
1117     KeyedLoadFieldStub stub(inobject, offset, representation);
1118     return stub.GetCode(isolate());
1119   }
1120 }
1121
1122 void LoadIC::UpdateCaches(LookupResult* lookup,
1123                           Handle<Object> object,
1124                           Handle<String> name) {
1125   // TODO(verwaest): It would be nice to support loading fields from smis as
1126   // well. For now just fail to update the cache.
1127   if (!object->IsHeapObject()) return;
1128
1129   Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
1130
1131   Handle<Code> code;
1132   if (state() == UNINITIALIZED) {
1133     // This is the first time we execute this inline cache.
1134     // Set the target to the pre monomorphic stub to delay
1135     // setting the monomorphic state.
1136     code = pre_monomorphic_stub();
1137   } else if (!lookup->IsCacheable()) {
1138     // Bail out if the result is not cacheable.
1139     code = slow_stub();
1140   } else if (object->IsString() &&
1141              name->Equals(isolate()->heap()->length_string())) {
1142     int length_index = String::kLengthOffset / kPointerSize;
1143     code = SimpleFieldLoad(length_index);
1144   } else if (!object->IsJSObject()) {
1145     // TODO(jkummerow): It would be nice to support non-JSObjects in
1146     // ComputeLoadHandler, then we wouldn't need to go generic here.
1147     code = slow_stub();
1148   } else if (!lookup->IsProperty()) {
1149     code = kind() == Code::LOAD_IC
1150         ? isolate()->stub_cache()->ComputeLoadNonexistent(
1151               name, Handle<JSObject>::cast(receiver))
1152         : slow_stub();
1153   } else {
1154     code = ComputeHandler(lookup, Handle<JSObject>::cast(receiver), name);
1155   }
1156
1157   PatchCache(receiver, name, code);
1158   TRACE_IC("LoadIC", name);
1159 }
1160
1161
1162 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
1163   // Cache code holding map should be consistent with
1164   // GenerateMonomorphicCacheProbe.
1165   isolate()->stub_cache()->Set(name, map, code);
1166 }
1167
1168
1169 Handle<Code> IC::ComputeHandler(LookupResult* lookup,
1170                                 Handle<JSObject> receiver,
1171                                 Handle<String> name,
1172                                 Handle<Object> value) {
1173   Handle<Code> code = isolate()->stub_cache()->FindHandler(
1174       name, receiver, kind());
1175   if (!code.is_null()) return code;
1176
1177   code = CompileHandler(lookup, receiver, name, value);
1178
1179   if (code->is_handler() && code->type() != Code::NORMAL) {
1180     HeapObject::UpdateMapCodeCache(receiver, name, code);
1181   }
1182
1183   return code;
1184 }
1185
1186
1187 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
1188                                     Handle<JSObject> receiver,
1189                                     Handle<String> name,
1190                                     Handle<Object> unused) {
1191   Handle<JSObject> holder(lookup->holder());
1192   LoadStubCompiler compiler(isolate(), kind());
1193
1194   switch (lookup->type()) {
1195     case FIELD: {
1196       PropertyIndex field = lookup->GetFieldIndex();
1197       if (receiver.is_identical_to(holder)) {
1198         return SimpleFieldLoad(field.translate(holder),
1199                                field.is_inobject(holder),
1200                                lookup->representation());
1201       }
1202       return compiler.CompileLoadField(
1203           receiver, holder, name, field, lookup->representation());
1204     }
1205     case CONSTANT: {
1206       Handle<Object> constant(lookup->GetConstant(), isolate());
1207       // TODO(2803): Don't compute a stub for cons strings because they cannot
1208       // be embedded into code.
1209       if (constant->IsConsString()) break;
1210       return compiler.CompileLoadConstant(receiver, holder, name, constant);
1211     }
1212     case NORMAL:
1213       if (kind() != Code::LOAD_IC) break;
1214       if (holder->IsGlobalObject()) {
1215         Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1216         Handle<PropertyCell> cell(
1217             global->GetPropertyCell(lookup), isolate());
1218         // TODO(verwaest): Turn into a handler.
1219         return isolate()->stub_cache()->ComputeLoadGlobal(
1220             name, receiver, global, cell, lookup->IsDontDelete());
1221       }
1222       // There is only one shared stub for loading normalized
1223       // properties. It does not traverse the prototype chain, so the
1224       // property must be found in the receiver for the stub to be
1225       // applicable.
1226       if (!holder.is_identical_to(receiver)) break;
1227       return isolate()->builtins()->LoadIC_Normal();
1228     case CALLBACKS: {
1229       // Use simple field loads for some well-known callback properties.
1230       int object_offset;
1231       Handle<Map> map(receiver->map());
1232       if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
1233         PropertyIndex index =
1234             PropertyIndex::NewHeaderIndex(object_offset / kPointerSize);
1235         return compiler.CompileLoadField(
1236             receiver, receiver, name, index, Representation::Tagged());
1237       }
1238
1239       Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1240       if (callback->IsExecutableAccessorInfo()) {
1241         Handle<ExecutableAccessorInfo> info =
1242             Handle<ExecutableAccessorInfo>::cast(callback);
1243         if (v8::ToCData<Address>(info->getter()) == 0) break;
1244         if (!info->IsCompatibleReceiver(*receiver)) break;
1245         return compiler.CompileLoadCallback(receiver, holder, name, info);
1246       } else if (callback->IsAccessorPair()) {
1247         Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
1248                               isolate());
1249         if (!getter->IsJSFunction()) break;
1250         if (holder->IsGlobalObject()) break;
1251         if (!holder->HasFastProperties()) break;
1252         Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1253         CallOptimization call_optimization(function);
1254         if (call_optimization.is_simple_api_call() &&
1255             call_optimization.IsCompatibleReceiver(*receiver)) {
1256           return compiler.CompileLoadCallback(
1257               receiver, holder, name, call_optimization);
1258         }
1259         return compiler.CompileLoadViaGetter(receiver, holder, name, function);
1260       }
1261       // TODO(dcarney): Handle correctly.
1262       if (callback->IsDeclaredAccessorInfo()) break;
1263       ASSERT(callback->IsForeign());
1264       // No IC support for old-style native accessors.
1265       break;
1266     }
1267     case INTERCEPTOR:
1268       ASSERT(HasInterceptorGetter(*holder));
1269       return compiler.CompileLoadInterceptor(receiver, holder, name);
1270     default:
1271       break;
1272   }
1273
1274   return slow_stub();
1275 }
1276
1277
1278 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1279   // This helper implements a few common fast cases for converting
1280   // non-smi keys of keyed loads/stores to a smi or a string.
1281   if (key->IsHeapNumber()) {
1282     double value = Handle<HeapNumber>::cast(key)->value();
1283     if (std::isnan(value)) {
1284       key = isolate->factory()->nan_string();
1285     } else {
1286       int int_value = FastD2I(value);
1287       if (value == int_value && Smi::IsValid(int_value)) {
1288         key = Handle<Smi>(Smi::FromInt(int_value), isolate);
1289       }
1290     }
1291   } else if (key->IsUndefined()) {
1292     key = isolate->factory()->undefined_string();
1293   }
1294   return key;
1295 }
1296
1297
1298 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
1299   // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1300   // via megamorphic stubs, since they don't have a map in their relocation info
1301   // and so the stubs can't be harvested for the object needed for a map check.
1302   if (target()->type() != Code::NORMAL) {
1303     TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
1304     return generic_stub();
1305   }
1306
1307   Handle<Map> receiver_map(receiver->map(), isolate());
1308   MapHandleList target_receiver_maps;
1309   if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
1310     // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1311     // yet will do so and stay there.
1312     return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1313   }
1314
1315   if (target().is_identical_to(string_stub())) {
1316     target_receiver_maps.Add(isolate()->factory()->string_map());
1317   } else {
1318     target()->FindAllMaps(&target_receiver_maps);
1319     if (target_receiver_maps.length() == 0) {
1320       return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1321     }
1322   }
1323
1324   // The first time a receiver is seen that is a transitioned version of the
1325   // previous monomorphic receiver type, assume the new ElementsKind is the
1326   // monomorphic type. This benefits global arrays that only transition
1327   // once, and all call sites accessing them are faster if they remain
1328   // monomorphic. If this optimistic assumption is not true, the IC will
1329   // miss again and it will become polymorphic and support both the
1330   // untransitioned and transitioned maps.
1331   if (state() == MONOMORPHIC &&
1332       IsMoreGeneralElementsKindTransition(
1333           target_receiver_maps.at(0)->elements_kind(),
1334           receiver->GetElementsKind())) {
1335     return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1336   }
1337
1338   ASSERT(state() != GENERIC);
1339
1340   // Determine the list of receiver maps that this call site has seen,
1341   // adding the map that was just encountered.
1342   if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1343     // If the miss wasn't due to an unseen map, a polymorphic stub
1344     // won't help, use the generic stub.
1345     TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice");
1346     return generic_stub();
1347   }
1348
1349   // If the maximum number of receiver maps has been exceeded, use the generic
1350   // version of the IC.
1351   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1352     TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded");
1353     return generic_stub();
1354   }
1355
1356   return isolate()->stub_cache()->ComputeLoadElementPolymorphic(
1357       &target_receiver_maps);
1358 }
1359
1360
1361 MaybeObject* KeyedLoadIC::Load(Handle<Object> object,
1362                                Handle<Object> key,
1363                                ICMissMode miss_mode) {
1364   if (MigrateDeprecated(object)) {
1365     return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1366   }
1367
1368   MaybeObject* maybe_object = NULL;
1369   Handle<Code> stub = generic_stub();
1370
1371   // Check for values that can be converted into an internalized string directly
1372   // or is representable as a smi.
1373   key = TryConvertKey(key, isolate());
1374
1375   if (key->IsInternalizedString()) {
1376     maybe_object = LoadIC::Load(object, Handle<String>::cast(key));
1377     if (maybe_object->IsFailure()) return maybe_object;
1378   } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
1379     ASSERT(!object->IsJSGlobalProxy());
1380     if (miss_mode != MISS_FORCE_GENERIC) {
1381       if (object->IsString() && key->IsNumber()) {
1382         if (state() == UNINITIALIZED) stub = string_stub();
1383       } else if (object->IsJSObject()) {
1384         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1385         if (receiver->elements()->map() ==
1386             isolate()->heap()->non_strict_arguments_elements_map()) {
1387           stub = non_strict_arguments_stub();
1388         } else if (receiver->HasIndexedInterceptor()) {
1389           stub = indexed_interceptor_stub();
1390         } else if (!key->ToSmi()->IsFailure() &&
1391                    (!target().is_identical_to(non_strict_arguments_stub()))) {
1392           stub = LoadElementStub(receiver);
1393         }
1394       }
1395     }
1396   }
1397
1398   if (!is_target_set()) {
1399     if (*stub == *generic_stub()) {
1400       TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
1401     }
1402     ASSERT(!stub.is_null());
1403     set_target(*stub);
1404     TRACE_IC("LoadIC", key);
1405   }
1406
1407   if (maybe_object != NULL) return maybe_object;
1408   return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1409 }
1410
1411
1412 static bool LookupForWrite(Handle<JSObject> receiver,
1413                            Handle<String> name,
1414                            Handle<Object> value,
1415                            LookupResult* lookup,
1416                            IC* ic) {
1417   Handle<JSObject> holder = receiver;
1418   receiver->Lookup(*name, lookup);
1419   if (lookup->IsFound()) {
1420     if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false;
1421
1422     if (lookup->holder() == *receiver) {
1423       if (lookup->IsInterceptor() && !HasInterceptorSetter(*receiver)) {
1424         receiver->LocalLookupRealNamedProperty(*name, lookup);
1425         return lookup->IsFound() &&
1426             !lookup->IsReadOnly() &&
1427             lookup->CanHoldValue(value) &&
1428             lookup->IsCacheable();
1429       }
1430       return lookup->CanHoldValue(value);
1431     }
1432
1433     if (lookup->IsPropertyCallbacks()) return true;
1434
1435     // Currently normal holders in the prototype chain are not supported. They
1436     // would require a runtime positive lookup and verification that the details
1437     // have not changed.
1438     if (lookup->IsInterceptor() || lookup->IsNormal()) return false;
1439     holder = Handle<JSObject>(lookup->holder(), lookup->isolate());
1440   }
1441
1442   // While normally LookupTransition gets passed the receiver, in this case we
1443   // pass the holder of the property that we overwrite. This keeps the holder in
1444   // the LookupResult intact so we can later use it to generate a prototype
1445   // chain check. This avoids a double lookup, but requires us to pass in the
1446   // receiver when trying to fetch extra information from the transition.
1447   receiver->map()->LookupTransition(*holder, *name, lookup);
1448   if (!lookup->IsTransition()) return false;
1449   PropertyDetails target_details =
1450       lookup->GetTransitionDetails(receiver->map());
1451   if (target_details.IsReadOnly()) return false;
1452
1453   // If the value that's being stored does not fit in the field that the
1454   // instance would transition to, create a new transition that fits the value.
1455   // This has to be done before generating the IC, since that IC will embed the
1456   // transition target.
1457   // Ensure the instance and its map were migrated before trying to update the
1458   // transition target.
1459   ASSERT(!receiver->map()->is_deprecated());
1460   if (!value->FitsRepresentation(target_details.representation())) {
1461     Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map()));
1462     Map::GeneralizeRepresentation(
1463         target, target->LastAdded(),
1464         value->OptimalRepresentation(), FORCE_FIELD);
1465     // Lookup the transition again since the transition tree may have changed
1466     // entirely by the migration above.
1467     receiver->map()->LookupTransition(*holder, *name, lookup);
1468     if (!lookup->IsTransition()) return false;
1469     ic->MarkMonomorphicPrototypeFailure();
1470   }
1471   return true;
1472 }
1473
1474
1475 MaybeObject* StoreIC::Store(Handle<Object> object,
1476                             Handle<String> name,
1477                             Handle<Object> value,
1478                             JSReceiver::StoreFromKeyed store_mode) {
1479   if (MigrateDeprecated(object) || object->IsJSProxy()) {
1480     Handle<Object> result = JSReceiver::SetProperty(
1481         Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode());
1482     RETURN_IF_EMPTY_HANDLE(isolate(), result);
1483     return *result;
1484   }
1485
1486   // If the object is undefined or null it's illegal to try to set any
1487   // properties on it; throw a TypeError in that case.
1488   if (object->IsUndefined() || object->IsNull()) {
1489     return TypeError("non_object_property_store", object, name);
1490   }
1491
1492   // The length property of string values is read-only. Throw in strict mode.
1493   if (strict_mode() == kStrictMode && object->IsString() &&
1494       name->Equals(isolate()->heap()->length_string())) {
1495     return TypeError("strict_read_only_property", object, name);
1496   }
1497
1498   // Ignore other stores where the receiver is not a JSObject.
1499   // TODO(1475): Must check prototype chains of object wrappers.
1500   if (!object->IsJSObject()) return *value;
1501
1502   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1503
1504   // Check if the given name is an array index.
1505   uint32_t index;
1506   if (name->AsArrayIndex(&index)) {
1507     Handle<Object> result =
1508         JSObject::SetElement(receiver, index, value, NONE, strict_mode());
1509     RETURN_IF_EMPTY_HANDLE(isolate(), result);
1510     return *value;
1511   }
1512
1513   // Observed objects are always modified through the runtime.
1514   if (FLAG_harmony_observation && receiver->map()->is_observed()) {
1515     Handle<Object> result = JSReceiver::SetProperty(
1516         receiver, name, value, NONE, strict_mode(), store_mode);
1517     RETURN_IF_EMPTY_HANDLE(isolate(), result);
1518     return *result;
1519   }
1520
1521   // Use specialized code for setting the length of arrays with fast
1522   // properties. Slow properties might indicate redefinition of the length
1523   // property. Note that when redefined using Object.freeze, it's possible
1524   // to have fast properties but a read-only length.
1525   if (FLAG_use_ic &&
1526       receiver->IsJSArray() &&
1527       name->Equals(isolate()->heap()->length_string()) &&
1528       Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
1529       receiver->HasFastProperties() &&
1530       !receiver->map()->is_frozen()) {
1531     Handle<Code> stub =
1532         StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate());
1533     set_target(*stub);
1534     TRACE_IC("StoreIC", name);
1535     Handle<Object> result = JSReceiver::SetProperty(
1536         receiver, name, value, NONE, strict_mode(), store_mode);
1537     RETURN_IF_EMPTY_HANDLE(isolate(), result);
1538     return *result;
1539   }
1540
1541   if (receiver->IsJSGlobalProxy()) {
1542     if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) {
1543       // Generate a generic stub that goes to the runtime when we see a global
1544       // proxy as receiver.
1545       Handle<Code> stub = global_proxy_stub();
1546       set_target(*stub);
1547       TRACE_IC("StoreIC", name);
1548     }
1549     Handle<Object> result = JSReceiver::SetProperty(
1550         receiver, name, value, NONE, strict_mode(), store_mode);
1551     RETURN_IF_EMPTY_HANDLE(isolate(), result);
1552     return *result;
1553   }
1554
1555   LookupResult lookup(isolate());
1556   bool can_store = LookupForWrite(receiver, name, value, &lookup, this);
1557   if (!can_store &&
1558       strict_mode() == kStrictMode &&
1559       !(lookup.IsProperty() && lookup.IsReadOnly()) &&
1560       IsUndeclaredGlobal(object)) {
1561     // Strict mode doesn't allow setting non-existent global property.
1562     return ReferenceError("not_defined", name);
1563   }
1564   if (FLAG_use_ic) {
1565     if (state() == UNINITIALIZED) {
1566       Handle<Code> stub = pre_monomorphic_stub();
1567       set_target(*stub);
1568       TRACE_IC("StoreIC", name);
1569     } else if (can_store) {
1570       UpdateCaches(&lookup, receiver, name, value);
1571     } else if (!name->IsCacheable(isolate()) ||
1572                lookup.IsNormal() ||
1573                (lookup.IsField() && lookup.CanHoldValue(value))) {
1574       Handle<Code> stub = generic_stub();
1575       set_target(*stub);
1576     }
1577   }
1578
1579   // Set the property.
1580   Handle<Object> result = JSReceiver::SetProperty(
1581       receiver, name, value, NONE, strict_mode(), store_mode);
1582   RETURN_IF_EMPTY_HANDLE(isolate(), result);
1583   return *result;
1584 }
1585
1586
1587 void StoreIC::UpdateCaches(LookupResult* lookup,
1588                            Handle<JSObject> receiver,
1589                            Handle<String> name,
1590                            Handle<Object> value) {
1591   ASSERT(!receiver->IsJSGlobalProxy());
1592   ASSERT(lookup->IsFound());
1593
1594   // These are not cacheable, so we never see such LookupResults here.
1595   ASSERT(!lookup->IsHandler());
1596
1597   Handle<Code> code = ComputeHandler(lookup, receiver, name, value);
1598
1599   PatchCache(receiver, name, code);
1600   TRACE_IC("StoreIC", name);
1601 }
1602
1603
1604 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
1605                                      Handle<JSObject> receiver,
1606                                      Handle<String> name,
1607                                      Handle<Object> value) {
1608   Handle<JSObject> holder(lookup->holder());
1609   StoreStubCompiler compiler(isolate(), strict_mode(), kind());
1610   switch (lookup->type()) {
1611     case FIELD:
1612       return compiler.CompileStoreField(receiver, lookup, name);
1613     case TRANSITION: {
1614       // Explicitly pass in the receiver map since LookupForWrite may have
1615       // stored something else than the receiver in the holder.
1616       Handle<Map> transition(
1617           lookup->GetTransitionTarget(receiver->map()), isolate());
1618       int descriptor = transition->LastAdded();
1619
1620       DescriptorArray* target_descriptors = transition->instance_descriptors();
1621       PropertyDetails details = target_descriptors->GetDetails(descriptor);
1622
1623       if (details.type() == CALLBACKS || details.attributes() != NONE) break;
1624
1625       return compiler.CompileStoreTransition(
1626           receiver, lookup, transition, name);
1627     }
1628     case NORMAL:
1629       if (kind() == Code::KEYED_STORE_IC) break;
1630       if (receiver->IsGlobalObject()) {
1631         // The stub generated for the global object picks the value directly
1632         // from the property cell. So the property must be directly on the
1633         // global object.
1634         Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1635         Handle<PropertyCell> cell(
1636             global->GetPropertyCell(lookup), isolate());
1637         // TODO(verwaest): Turn into a handler.
1638         return isolate()->stub_cache()->ComputeStoreGlobal(
1639             name, global, cell, value, strict_mode());
1640       }
1641       ASSERT(holder.is_identical_to(receiver));
1642       return strict_mode() == kStrictMode
1643           ? isolate()->builtins()->StoreIC_Normal_Strict()
1644           : isolate()->builtins()->StoreIC_Normal();
1645     case CALLBACKS: {
1646       if (kind() == Code::KEYED_STORE_IC) break;
1647       Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1648       if (callback->IsExecutableAccessorInfo()) {
1649         Handle<ExecutableAccessorInfo> info =
1650             Handle<ExecutableAccessorInfo>::cast(callback);
1651         if (v8::ToCData<Address>(info->setter()) == 0) break;
1652         if (!holder->HasFastProperties()) break;
1653         if (!info->IsCompatibleReceiver(*receiver)) break;
1654         return compiler.CompileStoreCallback(receiver, holder, name, info);
1655       } else if (callback->IsAccessorPair()) {
1656         Handle<Object> setter(
1657             Handle<AccessorPair>::cast(callback)->setter(), isolate());
1658         if (!setter->IsJSFunction()) break;
1659         if (holder->IsGlobalObject()) break;
1660         if (!holder->HasFastProperties()) break;
1661         Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
1662         CallOptimization call_optimization(function);
1663         if (call_optimization.is_simple_api_call() &&
1664             call_optimization.IsCompatibleReceiver(*receiver)) {
1665           return compiler.CompileStoreCallback(
1666               receiver, holder, name, call_optimization);
1667         }
1668         return compiler.CompileStoreViaSetter(
1669             receiver, holder, name, Handle<JSFunction>::cast(setter));
1670       }
1671       // TODO(dcarney): Handle correctly.
1672       if (callback->IsDeclaredAccessorInfo()) break;
1673       ASSERT(callback->IsForeign());
1674       // No IC support for old-style native accessors.
1675       break;
1676     }
1677     case INTERCEPTOR:
1678       if (kind() == Code::KEYED_STORE_IC) break;
1679       ASSERT(HasInterceptorSetter(*receiver));
1680       return compiler.CompileStoreInterceptor(receiver, name);
1681     case CONSTANT:
1682       break;
1683     case NONEXISTENT:
1684     case HANDLER:
1685       UNREACHABLE();
1686       break;
1687   }
1688   return slow_stub();
1689 }
1690
1691
1692 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
1693                                             KeyedAccessStoreMode store_mode) {
1694   // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1695   // via megamorphic stubs, since they don't have a map in their relocation info
1696   // and so the stubs can't be harvested for the object needed for a map check.
1697   if (target()->type() != Code::NORMAL) {
1698     TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
1699     return generic_stub();
1700   }
1701
1702   Handle<Map> receiver_map(receiver->map(), isolate());
1703   if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
1704     // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1705     // yet will do so and stay there.
1706     Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode);
1707     store_mode = GetNonTransitioningStoreMode(store_mode);
1708     return isolate()->stub_cache()->ComputeKeyedStoreElement(
1709         monomorphic_map, strict_mode(), store_mode);
1710   }
1711
1712   MapHandleList target_receiver_maps;
1713   target()->FindAllMaps(&target_receiver_maps);
1714   if (target_receiver_maps.length() == 0) {
1715     // In the case that there is a non-map-specific IC is installed (e.g. keyed
1716     // stores into properties in dictionary mode), then there will be not
1717     // receiver maps in the target.
1718     return generic_stub();
1719   }
1720
1721   // There are several special cases where an IC that is MONOMORPHIC can still
1722   // transition to a different GetNonTransitioningStoreMode IC that handles a
1723   // superset of the original IC. Handle those here if the receiver map hasn't
1724   // changed or it has transitioned to a more general kind.
1725   KeyedAccessStoreMode old_store_mode =
1726       Code::GetKeyedAccessStoreMode(target()->extra_ic_state());
1727   Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1728   if (state() == MONOMORPHIC) {
1729       // If the "old" and "new" maps are in the same elements map family, stay
1730       // MONOMORPHIC and use the map for the most generic ElementsKind.
1731     Handle<Map> transitioned_receiver_map = receiver_map;
1732     if (IsTransitionStoreMode(store_mode)) {
1733       transitioned_receiver_map =
1734           ComputeTransitionedMap(receiver, store_mode);
1735     }
1736     if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) {
1737       // Element family is the same, use the "worst" case map.
1738       store_mode = GetNonTransitioningStoreMode(store_mode);
1739       return isolate()->stub_cache()->ComputeKeyedStoreElement(
1740           transitioned_receiver_map, strict_mode(), store_mode);
1741     } else if (*previous_receiver_map == receiver->map() &&
1742                old_store_mode == STANDARD_STORE &&
1743                (IsGrowStoreMode(store_mode) ||
1744                 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1745                 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1746       // A "normal" IC that handles stores can switch to a version that can
1747       // grow at the end of the array, handle OOB accesses or copy COW arrays
1748       // and still stay MONOMORPHIC.
1749       return isolate()->stub_cache()->ComputeKeyedStoreElement(
1750           receiver_map, strict_mode(), store_mode);
1751     }
1752   }
1753
1754   ASSERT(state() != GENERIC);
1755
1756   bool map_added =
1757       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1758
1759   if (IsTransitionStoreMode(store_mode)) {
1760     Handle<Map> transitioned_receiver_map =
1761         ComputeTransitionedMap(receiver, store_mode);
1762     map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
1763                                             transitioned_receiver_map);
1764   }
1765
1766   if (!map_added) {
1767     // If the miss wasn't due to an unseen map, a polymorphic stub
1768     // won't help, use the generic stub.
1769     TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice");
1770     return generic_stub();
1771   }
1772
1773   // If the maximum number of receiver maps has been exceeded, use the generic
1774   // version of the IC.
1775   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1776     TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded");
1777     return generic_stub();
1778   }
1779
1780   // Make sure all polymorphic handlers have the same store mode, otherwise the
1781   // generic stub must be used.
1782   store_mode = GetNonTransitioningStoreMode(store_mode);
1783   if (old_store_mode != STANDARD_STORE) {
1784     if (store_mode == STANDARD_STORE) {
1785       store_mode = old_store_mode;
1786     } else if (store_mode != old_store_mode) {
1787       TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch");
1788       return generic_stub();
1789     }
1790   }
1791
1792   // If the store mode isn't the standard mode, make sure that all polymorphic
1793   // receivers are either external arrays, or all "normal" arrays. Otherwise,
1794   // use the generic stub.
1795   if (store_mode != STANDARD_STORE) {
1796     int external_arrays = 0;
1797     for (int i = 0; i < target_receiver_maps.length(); ++i) {
1798       if (target_receiver_maps[i]->has_external_array_elements()) {
1799         external_arrays++;
1800       }
1801     }
1802     if (external_arrays != 0 &&
1803         external_arrays != target_receiver_maps.length()) {
1804       TRACE_GENERIC_IC(isolate(), "KeyedIC",
1805           "unsupported combination of external and normal arrays");
1806       return generic_stub();
1807     }
1808   }
1809
1810   return isolate()->stub_cache()->ComputeStoreElementPolymorphic(
1811       &target_receiver_maps, store_mode, strict_mode());
1812 }
1813
1814
1815 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
1816     Handle<JSObject> receiver,
1817     KeyedAccessStoreMode store_mode) {
1818   switch (store_mode) {
1819     case STORE_TRANSITION_SMI_TO_OBJECT:
1820     case STORE_TRANSITION_DOUBLE_TO_OBJECT:
1821     case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT:
1822     case STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT:
1823       return JSObject::GetElementsTransitionMap(receiver, FAST_ELEMENTS);
1824     case STORE_TRANSITION_SMI_TO_DOUBLE:
1825     case STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE:
1826       return JSObject::GetElementsTransitionMap(receiver, FAST_DOUBLE_ELEMENTS);
1827     case STORE_TRANSITION_HOLEY_SMI_TO_OBJECT:
1828     case STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
1829     case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT:
1830     case STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
1831       return JSObject::GetElementsTransitionMap(receiver,
1832                                                 FAST_HOLEY_ELEMENTS);
1833     case STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE:
1834     case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE:
1835       return JSObject::GetElementsTransitionMap(receiver,
1836                                                 FAST_HOLEY_DOUBLE_ELEMENTS);
1837     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
1838       ASSERT(receiver->map()->has_external_array_elements());
1839       // Fall through
1840     case STORE_NO_TRANSITION_HANDLE_COW:
1841     case STANDARD_STORE:
1842     case STORE_AND_GROW_NO_TRANSITION:
1843       return Handle<Map>(receiver->map(), isolate());
1844   }
1845   return Handle<Map>::null();
1846 }
1847
1848
1849 bool IsOutOfBoundsAccess(Handle<JSObject> receiver,
1850                          int index) {
1851   if (receiver->IsJSArray()) {
1852     return JSArray::cast(*receiver)->length()->IsSmi() &&
1853         index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
1854   }
1855   return index >= receiver->elements()->length();
1856 }
1857
1858
1859 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
1860                                                 Handle<Object> key,
1861                                                 Handle<Object> value) {
1862   ASSERT(!key->ToSmi()->IsFailure());
1863   Smi* smi_key = NULL;
1864   key->ToSmi()->To(&smi_key);
1865   int index = smi_key->value();
1866   bool oob_access = IsOutOfBoundsAccess(receiver, index);
1867   bool allow_growth = receiver->IsJSArray() && oob_access;
1868   if (allow_growth) {
1869     // Handle growing array in stub if necessary.
1870     if (receiver->HasFastSmiElements()) {
1871       if (value->IsHeapNumber()) {
1872         if (receiver->HasFastHoleyElements()) {
1873           return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE;
1874         } else {
1875           return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE;
1876         }
1877       }
1878       if (value->IsHeapObject()) {
1879         if (receiver->HasFastHoleyElements()) {
1880           return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT;
1881         } else {
1882           return STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT;
1883         }
1884       }
1885     } else if (receiver->HasFastDoubleElements()) {
1886       if (!value->IsSmi() && !value->IsHeapNumber()) {
1887         if (receiver->HasFastHoleyElements()) {
1888           return STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT;
1889         } else {
1890           return STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT;
1891         }
1892       }
1893     }
1894     return STORE_AND_GROW_NO_TRANSITION;
1895   } else {
1896     // Handle only in-bounds elements accesses.
1897     if (receiver->HasFastSmiElements()) {
1898       if (value->IsHeapNumber()) {
1899         if (receiver->HasFastHoleyElements()) {
1900           return STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE;
1901         } else {
1902           return STORE_TRANSITION_SMI_TO_DOUBLE;
1903         }
1904       } else if (value->IsHeapObject()) {
1905         if (receiver->HasFastHoleyElements()) {
1906           return STORE_TRANSITION_HOLEY_SMI_TO_OBJECT;
1907         } else {
1908           return STORE_TRANSITION_SMI_TO_OBJECT;
1909         }
1910       }
1911     } else if (receiver->HasFastDoubleElements()) {
1912       if (!value->IsSmi() && !value->IsHeapNumber()) {
1913         if (receiver->HasFastHoleyElements()) {
1914           return STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT;
1915         } else {
1916           return STORE_TRANSITION_DOUBLE_TO_OBJECT;
1917         }
1918       }
1919     }
1920     if (!FLAG_trace_external_array_abuse &&
1921         receiver->map()->has_external_array_elements() && oob_access) {
1922       return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
1923     }
1924     Heap* heap = receiver->GetHeap();
1925     if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
1926       return STORE_NO_TRANSITION_HANDLE_COW;
1927     } else {
1928       return STANDARD_STORE;
1929     }
1930   }
1931 }
1932
1933
1934 MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
1935                                  Handle<Object> key,
1936                                  Handle<Object> value,
1937                                  ICMissMode miss_mode) {
1938   if (MigrateDeprecated(object)) {
1939     return Runtime::SetObjectPropertyOrFail(
1940         isolate(), object , key, value, NONE, strict_mode());
1941   }
1942
1943   // Check for values that can be converted into an internalized string directly
1944   // or is representable as a smi.
1945   key = TryConvertKey(key, isolate());
1946
1947   MaybeObject* maybe_object = NULL;
1948   Handle<Code> stub = generic_stub();
1949
1950   if (key->IsInternalizedString()) {
1951     maybe_object = StoreIC::Store(object,
1952                                   Handle<String>::cast(key),
1953                                   value,
1954                                   JSReceiver::MAY_BE_STORE_FROM_KEYED);
1955     if (maybe_object->IsFailure()) return maybe_object;
1956   } else {
1957     bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() &&
1958         !(FLAG_harmony_observation && object->IsJSObject() &&
1959           JSObject::cast(*object)->map()->is_observed());
1960     if (use_ic && !object->IsSmi()) {
1961       // Don't use ICs for maps of the objects in Array's prototype chain. We
1962       // expect to be able to trap element sets to objects with those maps in
1963       // the runtime to enable optimization of element hole access.
1964       Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
1965       if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false;
1966     }
1967
1968     if (use_ic) {
1969       ASSERT(!object->IsJSGlobalProxy());
1970
1971       if (miss_mode != MISS_FORCE_GENERIC) {
1972         if (object->IsJSObject()) {
1973           Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1974           bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure();
1975           if (receiver->elements()->map() ==
1976               isolate()->heap()->non_strict_arguments_elements_map()) {
1977             stub = non_strict_arguments_stub();
1978           } else if (key_is_smi_like &&
1979                      (!target().is_identical_to(non_strict_arguments_stub()))) {
1980             KeyedAccessStoreMode store_mode =
1981                 GetStoreMode(receiver, key, value);
1982             stub = StoreElementStub(receiver, store_mode);
1983           }
1984         }
1985       }
1986     }
1987   }
1988
1989   if (!is_target_set()) {
1990     if (*stub == *generic_stub()) {
1991       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
1992     }
1993     ASSERT(!stub.is_null());
1994     set_target(*stub);
1995     TRACE_IC("StoreIC", key);
1996   }
1997
1998   if (maybe_object) return maybe_object;
1999   return Runtime::SetObjectPropertyOrFail(
2000       isolate(), object , key, value, NONE, strict_mode());
2001 }
2002
2003
2004 #undef TRACE_IC
2005
2006
2007 // ----------------------------------------------------------------------------
2008 // Static IC stub generators.
2009 //
2010
2011 // Used from ic-<arch>.cc.
2012 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
2013   HandleScope scope(isolate);
2014   ASSERT(args.length() == 2);
2015   CallIC ic(isolate);
2016   Handle<Object> receiver = args.at<Object>(0);
2017   Handle<String> key = args.at<String>(1);
2018   ic.UpdateState(receiver, key);
2019   MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2020   JSFunction* raw_function;
2021   if (!maybe_result->To(&raw_function)) return maybe_result;
2022
2023   // The first time the inline cache is updated may be the first time the
2024   // function it references gets called. If the function is lazily compiled
2025   // then the first call will trigger a compilation. We check for this case
2026   // and we do the compilation immediately, instead of waiting for the stub
2027   // currently attached to the JSFunction object to trigger compilation.
2028   if (raw_function->is_compiled()) return raw_function;
2029
2030   Handle<JSFunction> function(raw_function);
2031   JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
2032   return *function;
2033 }
2034
2035
2036 // Used from ic-<arch>.cc.
2037 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
2038   HandleScope scope(isolate);
2039   ASSERT(args.length() == 2);
2040   KeyedCallIC ic(isolate);
2041   Handle<Object> receiver = args.at<Object>(0);
2042   Handle<Object> key = args.at<Object>(1);
2043   ic.UpdateState(receiver, key);
2044   MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2045   // Result could be a function or a failure.
2046   JSFunction* raw_function = NULL;
2047   if (!maybe_result->To(&raw_function)) return maybe_result;
2048
2049   if (raw_function->is_compiled()) return raw_function;
2050
2051   Handle<JSFunction> function(raw_function, isolate);
2052   JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
2053   return *function;
2054 }
2055
2056
2057 // Used from ic-<arch>.cc.
2058 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
2059   HandleScope scope(isolate);
2060   ASSERT(args.length() == 2);
2061   LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2062   Handle<Object> receiver = args.at<Object>(0);
2063   Handle<String> key = args.at<String>(1);
2064   ic.UpdateState(receiver, key);
2065   return ic.Load(receiver, key);
2066 }
2067
2068
2069 // Used from ic-<arch>.cc
2070 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
2071   HandleScope scope(isolate);
2072   ASSERT(args.length() == 2);
2073   KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2074   Handle<Object> receiver = args.at<Object>(0);
2075   Handle<Object> key = args.at<Object>(1);
2076   ic.UpdateState(receiver, key);
2077   return ic.Load(receiver, key, MISS);
2078 }
2079
2080
2081 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) {
2082   HandleScope scope(isolate);
2083   ASSERT(args.length() == 2);
2084   KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
2085   Handle<Object> receiver = args.at<Object>(0);
2086   Handle<Object> key = args.at<Object>(1);
2087   ic.UpdateState(receiver, key);
2088   return ic.Load(receiver, key, MISS);
2089 }
2090
2091
2092 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2093   HandleScope scope(isolate);
2094   ASSERT(args.length() == 2);
2095   KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2096   Handle<Object> receiver = args.at<Object>(0);
2097   Handle<Object> key = args.at<Object>(1);
2098   ic.UpdateState(receiver, key);
2099   return ic.Load(receiver, key, MISS_FORCE_GENERIC);
2100 }
2101
2102
2103 // Used from ic-<arch>.cc.
2104 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
2105   HandleScope scope(isolate);
2106   ASSERT(args.length() == 3);
2107   StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2108   Handle<Object> receiver = args.at<Object>(0);
2109   Handle<String> key = args.at<String>(1);
2110   ic.UpdateState(receiver, key);
2111   return ic.Store(receiver, key, args.at<Object>(2));
2112 }
2113
2114
2115 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) {
2116   HandleScope scope(isolate);
2117   ASSERT(args.length() == 3);
2118   StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2119   Handle<Object> receiver = args.at<Object>(0);
2120   Handle<String> key = args.at<String>(1);
2121   ic.UpdateState(receiver, key);
2122   return ic.Store(receiver, key, args.at<Object>(2));
2123 }
2124
2125
2126 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
2127   SealHandleScope shs(isolate);
2128
2129   ASSERT(args.length() == 2);
2130   JSArray* receiver = JSArray::cast(args[0]);
2131   Object* len = args[1];
2132
2133   // The generated code should filter out non-Smis before we get here.
2134   ASSERT(len->IsSmi());
2135
2136 #ifdef DEBUG
2137   // The length property has to be a writable callback property.
2138   LookupResult debug_lookup(isolate);
2139   receiver->LocalLookup(isolate->heap()->length_string(), &debug_lookup);
2140   ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly());
2141 #endif
2142
2143   Object* result;
2144   MaybeObject* maybe_result = receiver->SetElementsLength(len);
2145   if (!maybe_result->To(&result)) return maybe_result;
2146
2147   return len;
2148 }
2149
2150
2151 // Extend storage is called in a store inline cache when
2152 // it is necessary to extend the properties array of a
2153 // JSObject.
2154 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
2155   SealHandleScope shs(isolate);
2156   ASSERT(args.length() == 3);
2157
2158   // Convert the parameters
2159   JSObject* object = JSObject::cast(args[0]);
2160   Map* transition = Map::cast(args[1]);
2161   Object* value = args[2];
2162
2163   // Check the object has run out out property space.
2164   ASSERT(object->HasFastProperties());
2165   ASSERT(object->map()->unused_property_fields() == 0);
2166
2167   // Expand the properties array.
2168   FixedArray* old_storage = object->properties();
2169   int new_unused = transition->unused_property_fields();
2170   int new_size = old_storage->length() + new_unused + 1;
2171   Object* result;
2172   MaybeObject* maybe_result = old_storage->CopySize(new_size);
2173   if (!maybe_result->ToObject(&result)) return maybe_result;
2174
2175   FixedArray* new_storage = FixedArray::cast(result);
2176
2177   Object* to_store = value;
2178
2179   if (FLAG_track_double_fields) {
2180     DescriptorArray* descriptors = transition->instance_descriptors();
2181     PropertyDetails details = descriptors->GetDetails(transition->LastAdded());
2182     if (details.representation().IsDouble()) {
2183       MaybeObject* maybe_storage =
2184           isolate->heap()->AllocateHeapNumber(value->Number());
2185       if (!maybe_storage->To(&to_store)) return maybe_storage;
2186     }
2187   }
2188
2189   new_storage->set(old_storage->length(), to_store);
2190
2191   // Set the new property value and do the map transition.
2192   object->set_properties(new_storage);
2193   object->set_map(transition);
2194
2195   // Return the stored value.
2196   return value;
2197 }
2198
2199
2200 // Used from ic-<arch>.cc.
2201 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
2202   HandleScope scope(isolate);
2203   ASSERT(args.length() == 3);
2204   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2205   Handle<Object> receiver = args.at<Object>(0);
2206   Handle<Object> key = args.at<Object>(1);
2207   ic.UpdateState(receiver, key);
2208   return ic.Store(receiver, key, args.at<Object>(2), MISS);
2209 }
2210
2211
2212 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
2213   HandleScope scope(isolate);
2214   ASSERT(args.length() == 3);
2215   KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2216   Handle<Object> receiver = args.at<Object>(0);
2217   Handle<Object> key = args.at<Object>(1);
2218   ic.UpdateState(receiver, key);
2219   return ic.Store(receiver, key, args.at<Object>(2), MISS);
2220 }
2221
2222
2223 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) {
2224   HandleScope scope(isolate);
2225   ASSERT(args.length() == 3);
2226   StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2227   Handle<Object> object = args.at<Object>(0);
2228   Handle<Object> key = args.at<Object>(1);
2229   Handle<Object> value = args.at<Object>(2);
2230   StrictModeFlag strict_mode = ic.strict_mode();
2231   return Runtime::SetObjectProperty(isolate,
2232                                     object,
2233                                     key,
2234                                     value,
2235                                     NONE,
2236                                     strict_mode);
2237 }
2238
2239
2240 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
2241   HandleScope scope(isolate);
2242   ASSERT(args.length() == 3);
2243   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2244   Handle<Object> object = args.at<Object>(0);
2245   Handle<Object> key = args.at<Object>(1);
2246   Handle<Object> value = args.at<Object>(2);
2247   StrictModeFlag strict_mode = ic.strict_mode();
2248   return Runtime::SetObjectProperty(isolate,
2249                                     object,
2250                                     key,
2251                                     value,
2252                                     NONE,
2253                                     strict_mode);
2254 }
2255
2256
2257 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2258   HandleScope scope(isolate);
2259   ASSERT(args.length() == 3);
2260   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2261   Handle<Object> receiver = args.at<Object>(0);
2262   Handle<Object> key = args.at<Object>(1);
2263   ic.UpdateState(receiver, key);
2264   return ic.Store(receiver, key, args.at<Object>(2), MISS_FORCE_GENERIC);
2265 }
2266
2267
2268 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
2269   HandleScope scope(isolate);
2270   ASSERT(args.length() == 4);
2271   KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2272   Handle<Object> value = args.at<Object>(0);
2273   Handle<Object> key = args.at<Object>(2);
2274   Handle<Object> object = args.at<Object>(3);
2275   StrictModeFlag strict_mode = ic.strict_mode();
2276   return Runtime::SetObjectProperty(isolate,
2277                                     object,
2278                                     key,
2279                                     value,
2280                                     NONE,
2281                                     strict_mode);
2282 }
2283
2284
2285 const char* BinaryOpIC::GetName(TypeInfo type_info) {
2286   switch (type_info) {
2287     case UNINITIALIZED: return "Uninitialized";
2288     case SMI: return "Smi";
2289     case INT32: return "Int32";
2290     case NUMBER: return "Number";
2291     case ODDBALL: return "Oddball";
2292     case STRING: return "String";
2293     case GENERIC: return "Generic";
2294     default: return "Invalid";
2295   }
2296 }
2297
2298
2299 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) {
2300   Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
2301   BinaryOpStub stub(extra_ic_state);
2302
2303   Handle<Type> left_type = stub.GetLeftType(isolate());
2304   Handle<Type> right_type = stub.GetRightType(isolate());
2305   bool smi_was_enabled = left_type->Maybe(Type::Smi()) &&
2306                          right_type->Maybe(Type::Smi());
2307
2308   Maybe<Handle<Object> > result = stub.Result(left, right, isolate());
2309   if (!result.has_value) return Failure::Exception();
2310
2311 #ifdef DEBUG
2312   if (FLAG_trace_ic) {
2313     char buffer[100];
2314     NoAllocationStringAllocator allocator(buffer,
2315                                         static_cast<unsigned>(sizeof(buffer)));
2316     StringStream stream(&allocator);
2317     stream.Add("[");
2318     stub.PrintName(&stream);
2319
2320     stub.UpdateStatus(left, right, result);
2321
2322     stream.Add(" => ");
2323     stub.PrintState(&stream);
2324     stream.Add(" ");
2325     stream.OutputToStdOut();
2326     PrintF(" @ %p <- ", static_cast<void*>(*stub.GetCode(isolate())));
2327     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2328     PrintF("]\n");
2329   } else {
2330     stub.UpdateStatus(left, right, result);
2331   }
2332 #else
2333   stub.UpdateStatus(left, right, result);
2334 #endif
2335
2336   Handle<Code> code = stub.GetCode(isolate());
2337   set_target(*code);
2338
2339   left_type = stub.GetLeftType(isolate());
2340   right_type = stub.GetRightType(isolate());
2341   bool enable_smi = left_type->Maybe(Type::Smi()) &&
2342                     right_type->Maybe(Type::Smi());
2343
2344   if (!smi_was_enabled && enable_smi) {
2345     PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2346   } else if (smi_was_enabled && !enable_smi) {
2347     PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK);
2348   }
2349
2350   ASSERT(result.has_value);
2351   return static_cast<MaybeObject*>(*result.value);
2352 }
2353
2354
2355 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) {
2356   HandleScope scope(isolate);
2357   Handle<Object> left = args.at<Object>(0);
2358   Handle<Object> right = args.at<Object>(1);
2359   BinaryOpIC ic(isolate);
2360   return ic.Transition(left, right);
2361 }
2362
2363
2364 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2365   ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2366   Code* code = NULL;
2367   CHECK(stub.FindCodeInCache(&code, isolate));
2368   return code;
2369 }
2370
2371
2372 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
2373   ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2374   return stub.GetCode(isolate);
2375 }
2376
2377
2378 const char* CompareIC::GetStateName(State state) {
2379   switch (state) {
2380     case UNINITIALIZED: return "UNINITIALIZED";
2381     case SMI: return "SMI";
2382     case NUMBER: return "NUMBER";
2383     case INTERNALIZED_STRING: return "INTERNALIZED_STRING";
2384     case STRING: return "STRING";
2385     case UNIQUE_NAME: return "UNIQUE_NAME";
2386     case OBJECT: return "OBJECT";
2387     case KNOWN_OBJECT: return "KNOWN_OBJECT";
2388     case GENERIC: return "GENERIC";
2389   }
2390   UNREACHABLE();
2391   return NULL;
2392 }
2393
2394
2395 Handle<Type> CompareIC::StateToType(
2396     Isolate* isolate,
2397     CompareIC::State state,
2398     Handle<Map> map) {
2399   switch (state) {
2400     case CompareIC::UNINITIALIZED:
2401       return handle(Type::None(), isolate);
2402     case CompareIC::SMI:
2403       return handle(Type::Smi(), isolate);
2404     case CompareIC::NUMBER:
2405       return handle(Type::Number(), isolate);
2406     case CompareIC::STRING:
2407       return handle(Type::String(), isolate);
2408     case CompareIC::INTERNALIZED_STRING:
2409       return handle(Type::InternalizedString(), isolate);
2410     case CompareIC::UNIQUE_NAME:
2411       return handle(Type::UniqueName(), isolate);
2412     case CompareIC::OBJECT:
2413       return handle(Type::Receiver(), isolate);
2414     case CompareIC::KNOWN_OBJECT:
2415       return handle(
2416           map.is_null() ? Type::Receiver() : Type::Class(map), isolate);
2417     case CompareIC::GENERIC:
2418       return handle(Type::Any(), isolate);
2419   }
2420   UNREACHABLE();
2421   return Handle<Type>();
2422 }
2423
2424
2425 void CompareIC::StubInfoToType(int stub_minor_key,
2426                                Handle<Type>* left_type,
2427                                Handle<Type>* right_type,
2428                                Handle<Type>* overall_type,
2429                                Handle<Map> map,
2430                                Isolate* isolate) {
2431   State left_state, right_state, handler_state;
2432   ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
2433                                 &handler_state, NULL);
2434   *left_type = StateToType(isolate, left_state);
2435   *right_type = StateToType(isolate, right_state);
2436   *overall_type = StateToType(isolate, handler_state, map);
2437 }
2438
2439
2440 CompareIC::State CompareIC::NewInputState(State old_state,
2441                                           Handle<Object> value) {
2442   switch (old_state) {
2443     case UNINITIALIZED:
2444       if (value->IsSmi()) return SMI;
2445       if (value->IsHeapNumber()) return NUMBER;
2446       if (value->IsInternalizedString()) return INTERNALIZED_STRING;
2447       if (value->IsString()) return STRING;
2448       if (value->IsSymbol()) return UNIQUE_NAME;
2449       if (value->IsJSObject()) return OBJECT;
2450       break;
2451     case SMI:
2452       if (value->IsSmi()) return SMI;
2453       if (value->IsHeapNumber()) return NUMBER;
2454       break;
2455     case NUMBER:
2456       if (value->IsNumber()) return NUMBER;
2457       break;
2458     case INTERNALIZED_STRING:
2459       if (value->IsInternalizedString()) return INTERNALIZED_STRING;
2460       if (value->IsString()) return STRING;
2461       if (value->IsSymbol()) return UNIQUE_NAME;
2462       break;
2463     case STRING:
2464       if (value->IsString()) return STRING;
2465       break;
2466     case UNIQUE_NAME:
2467       if (value->IsUniqueName()) return UNIQUE_NAME;
2468       break;
2469     case OBJECT:
2470       if (value->IsJSObject()) return OBJECT;
2471       break;
2472     case GENERIC:
2473       break;
2474     case KNOWN_OBJECT:
2475       UNREACHABLE();
2476       break;
2477   }
2478   return GENERIC;
2479 }
2480
2481
2482 CompareIC::State CompareIC::TargetState(State old_state,
2483                                         State old_left,
2484                                         State old_right,
2485                                         bool has_inlined_smi_code,
2486                                         Handle<Object> x,
2487                                         Handle<Object> y) {
2488   switch (old_state) {
2489     case UNINITIALIZED:
2490       if (x->IsSmi() && y->IsSmi()) return SMI;
2491       if (x->IsNumber() && y->IsNumber()) return NUMBER;
2492       if (Token::IsOrderedRelationalCompareOp(op_)) {
2493         // Ordered comparisons treat undefined as NaN, so the
2494         // NUMBER stub will do the right thing.
2495         if ((x->IsNumber() && y->IsUndefined()) ||
2496             (y->IsNumber() && x->IsUndefined())) {
2497           return NUMBER;
2498         }
2499       }
2500       if (x->IsInternalizedString() && y->IsInternalizedString()) {
2501         // We compare internalized strings as plain ones if we need to determine
2502         // the order in a non-equality compare.
2503         return Token::IsEqualityOp(op_) ? INTERNALIZED_STRING : STRING;
2504       }
2505       if (x->IsString() && y->IsString()) return STRING;
2506       if (!Token::IsEqualityOp(op_)) return GENERIC;
2507       if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
2508       if (x->IsJSObject() && y->IsJSObject()) {
2509         if (Handle<JSObject>::cast(x)->map() ==
2510             Handle<JSObject>::cast(y)->map()) {
2511           return KNOWN_OBJECT;
2512         } else {
2513           return OBJECT;
2514         }
2515       }
2516       return GENERIC;
2517     case SMI:
2518       return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
2519     case INTERNALIZED_STRING:
2520       ASSERT(Token::IsEqualityOp(op_));
2521       if (x->IsString() && y->IsString()) return STRING;
2522       if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
2523       return GENERIC;
2524     case NUMBER:
2525       // If the failure was due to one side changing from smi to heap number,
2526       // then keep the state (if other changed at the same time, we will get
2527       // a second miss and then go to generic).
2528       if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
2529       if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
2530       return GENERIC;
2531     case KNOWN_OBJECT:
2532       ASSERT(Token::IsEqualityOp(op_));
2533       if (x->IsJSObject() && y->IsJSObject()) return OBJECT;
2534       return GENERIC;
2535     case STRING:
2536     case UNIQUE_NAME:
2537     case OBJECT:
2538     case GENERIC:
2539       return GENERIC;
2540   }
2541   UNREACHABLE();
2542   return GENERIC;  // Make the compiler happy.
2543 }
2544
2545
2546 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
2547   HandleScope scope(isolate());
2548   State previous_left, previous_right, previous_state;
2549   ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left,
2550                                 &previous_right, &previous_state, NULL);
2551   State new_left = NewInputState(previous_left, x);
2552   State new_right = NewInputState(previous_right, y);
2553   State state = TargetState(previous_state, previous_left, previous_right,
2554                             HasInlinedSmiCode(address()), x, y);
2555   ICCompareStub stub(op_, new_left, new_right, state);
2556   if (state == KNOWN_OBJECT) {
2557     stub.set_known_map(
2558         Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate()));
2559   }
2560   set_target(*stub.GetCode(isolate()));
2561
2562 #ifdef DEBUG
2563   if (FLAG_trace_ic) {
2564     PrintF("[CompareIC in ");
2565     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2566     PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
2567            GetStateName(previous_left),
2568            GetStateName(previous_right),
2569            GetStateName(previous_state),
2570            GetStateName(new_left),
2571            GetStateName(new_right),
2572            GetStateName(state),
2573            Token::Name(op_),
2574            static_cast<void*>(*stub.GetCode(isolate())));
2575   }
2576 #endif
2577
2578   // Activate inlined smi code.
2579   if (previous_state == UNINITIALIZED) {
2580     PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2581   }
2582 }
2583
2584
2585 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
2586 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2587   HandleScope scope(isolate);
2588   ASSERT(args.length() == 3);
2589   CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2590   ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2591   return ic.raw_target();
2592 }
2593
2594
2595 void CompareNilIC::Clear(Address address, Code* target) {
2596   if (IsCleared(target)) return;
2597   Code::ExtraICState state = target->extended_extra_ic_state();
2598
2599   CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
2600   stub.ClearState();
2601
2602   Code* code = NULL;
2603   CHECK(stub.FindCodeInCache(&code, target->GetIsolate()));
2604
2605   SetTargetAtAddress(address, code);
2606 }
2607
2608
2609 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil,
2610                                             Handle<Object> object) {
2611   if (object->IsNull() || object->IsUndefined()) {
2612     return Smi::FromInt(true);
2613   }
2614   return Smi::FromInt(object->IsUndetectableObject());
2615 }
2616
2617
2618 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
2619   Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
2620
2621   CompareNilICStub stub(extra_ic_state);
2622
2623   // Extract the current supported types from the patched IC and calculate what
2624   // types must be supported as a result of the miss.
2625   bool already_monomorphic = stub.IsMonomorphic();
2626
2627   stub.UpdateStatus(object);
2628
2629   NilValue nil = stub.GetNilValue();
2630
2631   // Find or create the specialized stub to support the new set of types.
2632   Handle<Code> code;
2633   if (stub.IsMonomorphic()) {
2634     Handle<Map> monomorphic_map(already_monomorphic
2635                                 ? target()->FindFirstMap()
2636                                 : HeapObject::cast(*object)->map());
2637     code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub);
2638   } else {
2639     code = stub.GetCode(isolate());
2640   }
2641   set_target(*code);
2642   return DoCompareNilSlow(nil, object);
2643 }
2644
2645
2646 RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss) {
2647   HandleScope scope(isolate);
2648   Handle<Object> object = args.at<Object>(0);
2649   CompareNilIC ic(isolate);
2650   return ic.CompareNil(object);
2651 }
2652
2653
2654 RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
2655   UNREACHABLE();
2656   CHECK(false);
2657   return isolate->heap()->undefined_value();
2658 }
2659
2660
2661 Builtins::JavaScript BinaryOpIC::TokenToJSBuiltin(Token::Value op) {
2662   switch (op) {
2663     default:
2664       UNREACHABLE();
2665     case Token::ADD:
2666       return Builtins::ADD;
2667       break;
2668     case Token::SUB:
2669       return Builtins::SUB;
2670       break;
2671     case Token::MUL:
2672       return Builtins::MUL;
2673       break;
2674     case Token::DIV:
2675       return Builtins::DIV;
2676       break;
2677     case Token::MOD:
2678       return Builtins::MOD;
2679       break;
2680     case Token::BIT_OR:
2681       return Builtins::BIT_OR;
2682       break;
2683     case Token::BIT_AND:
2684       return Builtins::BIT_AND;
2685       break;
2686     case Token::BIT_XOR:
2687       return Builtins::BIT_XOR;
2688       break;
2689     case Token::SAR:
2690       return Builtins::SAR;
2691       break;
2692     case Token::SHR:
2693       return Builtins::SHR;
2694       break;
2695     case Token::SHL:
2696       return Builtins::SHL;
2697       break;
2698   }
2699 }
2700
2701
2702 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object,
2703                                     Code::ExtraICState extra_ic_state) {
2704   ToBooleanStub stub(extra_ic_state);
2705   bool to_boolean_value = stub.UpdateStatus(object);
2706   Handle<Code> code = stub.GetCode(isolate());
2707   set_target(*code);
2708   return Smi::FromInt(to_boolean_value ? 1 : 0);
2709 }
2710
2711
2712 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
2713   ASSERT(args.length() == 1);
2714   HandleScope scope(isolate);
2715   Handle<Object> object = args.at<Object>(0);
2716   ToBooleanIC ic(isolate);
2717   Code::ExtraICState extra_ic_state = ic.target()->extended_extra_ic_state();
2718   return ic.ToBoolean(object, extra_ic_state);
2719 }
2720
2721
2722 static const Address IC_utilities[] = {
2723 #define ADDR(name) FUNCTION_ADDR(name),
2724     IC_UTIL_LIST(ADDR)
2725     NULL
2726 #undef ADDR
2727 };
2728
2729
2730 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2731   return IC_utilities[id];
2732 }
2733
2734
2735 } }  // namespace v8::internal