ic.cc revision 8defd9ff6930b4e24729971a61cf7469daf119be
1// Copyright 2006-2009 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 "execution.h"
34#include "ic-inl.h"
35#include "runtime.h"
36#include "stub-cache.h"
37
38namespace v8 {
39namespace internal {
40
41#ifdef DEBUG
42static char TransitionMarkFromState(IC::State state) {
43  switch (state) {
44    case UNINITIALIZED: return '0';
45    case PREMONOMORPHIC: return 'P';
46    case MONOMORPHIC: return '1';
47    case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
48    case MEGAMORPHIC: return 'N';
49
50    // We never see the debugger states here, because the state is
51    // computed from the original code - not the patched code. Let
52    // these cases fall through to the unreachable code below.
53    case DEBUG_BREAK: break;
54    case DEBUG_PREPARE_STEP_IN: break;
55  }
56  UNREACHABLE();
57  return 0;
58}
59
60void IC::TraceIC(const char* type,
61                 Handle<Object> name,
62                 State old_state,
63                 Code* new_target,
64                 const char* extra_info) {
65  if (FLAG_trace_ic) {
66    State new_state = StateFrom(new_target,
67                                Heap::undefined_value(),
68                                Heap::undefined_value());
69    PrintF("[%s (%c->%c)%s", type,
70           TransitionMarkFromState(old_state),
71           TransitionMarkFromState(new_state),
72           extra_info);
73    name->Print();
74    PrintF("]\n");
75  }
76}
77#endif
78
79
80IC::IC(FrameDepth depth) {
81  // To improve the performance of the (much used) IC code, we unfold
82  // a few levels of the stack frame iteration code. This yields a
83  // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag.
84  const Address entry = Top::c_entry_fp(Top::GetCurrentThread());
85  Address* pc_address =
86      reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
87  Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
88  // If there's another JavaScript frame on the stack, we need to look
89  // one frame further down the stack to find the frame pointer and
90  // the return address stack slot.
91  if (depth == EXTRA_CALL_FRAME) {
92    const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
93    pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
94    fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
95  }
96#ifdef DEBUG
97  StackFrameIterator it;
98  for (int i = 0; i < depth + 1; i++) it.Advance();
99  StackFrame* frame = it.frame();
100  ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
101#endif
102  fp_ = fp;
103  pc_address_ = pc_address;
104}
105
106
107#ifdef ENABLE_DEBUGGER_SUPPORT
108Address IC::OriginalCodeAddress() {
109  HandleScope scope;
110  // Compute the JavaScript frame for the frame pointer of this IC
111  // structure. We need this to be able to find the function
112  // corresponding to the frame.
113  StackFrameIterator it;
114  while (it.frame()->fp() != this->fp()) it.Advance();
115  JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
116  // Find the function on the stack and both the active code for the
117  // function and the original code.
118  JSFunction* function = JSFunction::cast(frame->function());
119  Handle<SharedFunctionInfo> shared(function->shared());
120  Code* code = shared->code();
121  ASSERT(Debug::HasDebugInfo(shared));
122  Code* original_code = Debug::GetDebugInfo(shared)->original_code();
123  ASSERT(original_code->IsCode());
124  // Get the address of the call site in the active code. This is the
125  // place where the call to DebugBreakXXX is and where the IC
126  // normally would be.
127  Address addr = pc() - Assembler::kCallTargetAddressOffset;
128  // Return the address in the original code. This is the place where
129  // the call which has been overwritten by the DebugBreakXXX resides
130  // and the place where the inline cache system should look.
131  intptr_t delta =
132      original_code->instruction_start() - code->instruction_start();
133  return addr + delta;
134}
135#endif
136
137
138static bool HasNormalObjectsInPrototypeChain(LookupResult* lookup,
139                                             Object* receiver) {
140  Object* end = lookup->IsProperty() ? lookup->holder() : Heap::null_value();
141  for (Object* current = receiver;
142       current != end;
143       current = current->GetPrototype()) {
144    if (current->IsJSObject() &&
145        !JSObject::cast(current)->HasFastProperties() &&
146        !current->IsJSGlobalProxy() &&
147        !current->IsJSGlobalObject()) {
148      return true;
149    }
150  }
151
152  return false;
153}
154
155
156IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
157  IC::State state = target->ic_state();
158
159  if (state != MONOMORPHIC) return state;
160  if (receiver->IsUndefined() || receiver->IsNull()) return state;
161
162  InlineCacheHolderFlag cache_holder =
163      Code::ExtractCacheHolderFromFlags(target->flags());
164
165
166  if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
167    // The stub was generated for JSObject but called for non-JSObject.
168    // IC::GetCodeCacheMap is not applicable.
169    return MONOMORPHIC;
170  } else if (cache_holder == PROTOTYPE_MAP &&
171             receiver->GetPrototype()->IsNull()) {
172    // IC::GetCodeCacheMap is not applicable.
173    return MONOMORPHIC;
174  }
175  Map* map = IC::GetCodeCacheMap(receiver, cache_holder);
176
177  // Decide whether the inline cache failed because of changes to the
178  // receiver itself or changes to one of its prototypes.
179  //
180  // If there are changes to the receiver itself, the map of the
181  // receiver will have changed and the current target will not be in
182  // the receiver map's code cache.  Therefore, if the current target
183  // is in the receiver map's code cache, the inline cache failed due
184  // to prototype check failure.
185  int index = map->IndexInCodeCache(name, target);
186  if (index >= 0) {
187    // For keyed load/store/call, the most likely cause of cache failure is
188    // that the key has changed.  We do not distinguish between
189    // prototype and non-prototype failures for keyed access.
190    Code::Kind kind = target->kind();
191    if (kind == Code::KEYED_LOAD_IC ||
192        kind == Code::KEYED_STORE_IC ||
193        kind == Code::KEYED_CALL_IC) {
194      return MONOMORPHIC;
195    }
196
197    // Remove the target from the code cache to avoid hitting the same
198    // invalid stub again.
199    map->RemoveFromCodeCache(String::cast(name), target, index);
200
201    return MONOMORPHIC_PROTOTYPE_FAILURE;
202  }
203
204  // The builtins object is special.  It only changes when JavaScript
205  // builtins are loaded lazily.  It is important to keep inline
206  // caches for the builtins object monomorphic.  Therefore, if we get
207  // an inline cache miss for the builtins object after lazily loading
208  // JavaScript builtins, we return uninitialized as the state to
209  // force the inline cache back to monomorphic state.
210  if (receiver->IsJSBuiltinsObject()) {
211    return UNINITIALIZED;
212  }
213
214  return MONOMORPHIC;
215}
216
217
218RelocInfo::Mode IC::ComputeMode() {
219  Address addr = address();
220  Code* code = Code::cast(Heap::FindCodeObject(addr));
221  for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
222       !it.done(); it.next()) {
223    RelocInfo* info = it.rinfo();
224    if (info->pc() == addr) return info->rmode();
225  }
226  UNREACHABLE();
227  return RelocInfo::NONE;
228}
229
230
231Failure* IC::TypeError(const char* type,
232                       Handle<Object> object,
233                       Handle<Object> key) {
234  HandleScope scope;
235  Handle<Object> args[2] = { key, object };
236  Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2));
237  return Top::Throw(*error);
238}
239
240
241Failure* IC::ReferenceError(const char* type, Handle<String> name) {
242  HandleScope scope;
243  Handle<Object> error =
244      Factory::NewReferenceError(type, HandleVector(&name, 1));
245  return Top::Throw(*error);
246}
247
248
249void IC::Clear(Address address) {
250  Code* target = GetTargetAtAddress(address);
251
252  // Don't clear debug break inline cache as it will remove the break point.
253  if (target->ic_state() == DEBUG_BREAK) return;
254
255  switch (target->kind()) {
256    case Code::LOAD_IC: return LoadIC::Clear(address, target);
257    case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
258    case Code::STORE_IC: return StoreIC::Clear(address, target);
259    case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target);
260    case Code::CALL_IC: return CallIC::Clear(address, target);
261    case Code::KEYED_CALL_IC:  return KeyedCallIC::Clear(address, target);
262    case Code::BINARY_OP_IC: return;  // Clearing these is tricky and does not
263                                      // make any performance difference.
264    default: UNREACHABLE();
265  }
266}
267
268
269void CallICBase::Clear(Address address, Code* target) {
270  State state = target->ic_state();
271  if (state == UNINITIALIZED) return;
272  Code* code =
273      StubCache::FindCallInitialize(target->arguments_count(),
274                                    target->ic_in_loop(),
275                                    target->kind());
276  SetTargetAtAddress(address, code);
277}
278
279
280void KeyedLoadIC::Clear(Address address, Code* target) {
281  if (target->ic_state() == UNINITIALIZED) return;
282  // Make sure to also clear the map used in inline fast cases.  If we
283  // do not clear these maps, cached code can keep objects alive
284  // through the embedded maps.
285  ClearInlinedVersion(address);
286  SetTargetAtAddress(address, initialize_stub());
287}
288
289
290void LoadIC::Clear(Address address, Code* target) {
291  if (target->ic_state() == UNINITIALIZED) return;
292  ClearInlinedVersion(address);
293  SetTargetAtAddress(address, initialize_stub());
294}
295
296
297void StoreIC::Clear(Address address, Code* target) {
298  if (target->ic_state() == UNINITIALIZED) return;
299  SetTargetAtAddress(address, initialize_stub());
300}
301
302
303void KeyedStoreIC::Clear(Address address, Code* target) {
304  if (target->ic_state() == UNINITIALIZED) return;
305  SetTargetAtAddress(address, initialize_stub());
306}
307
308
309Code* KeyedLoadIC::external_array_stub(JSObject::ElementsKind elements_kind) {
310  switch (elements_kind) {
311    case JSObject::EXTERNAL_BYTE_ELEMENTS:
312      return Builtins::builtin(Builtins::KeyedLoadIC_ExternalByteArray);
313    case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
314      return Builtins::builtin(Builtins::KeyedLoadIC_ExternalUnsignedByteArray);
315    case JSObject::EXTERNAL_SHORT_ELEMENTS:
316      return Builtins::builtin(Builtins::KeyedLoadIC_ExternalShortArray);
317    case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
318      return Builtins::builtin(
319          Builtins::KeyedLoadIC_ExternalUnsignedShortArray);
320    case JSObject::EXTERNAL_INT_ELEMENTS:
321      return Builtins::builtin(Builtins::KeyedLoadIC_ExternalIntArray);
322    case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
323      return Builtins::builtin(Builtins::KeyedLoadIC_ExternalUnsignedIntArray);
324    case JSObject::EXTERNAL_FLOAT_ELEMENTS:
325      return Builtins::builtin(Builtins::KeyedLoadIC_ExternalFloatArray);
326    default:
327      UNREACHABLE();
328      return NULL;
329  }
330}
331
332
333Code* KeyedStoreIC::external_array_stub(JSObject::ElementsKind elements_kind) {
334  switch (elements_kind) {
335    case JSObject::EXTERNAL_BYTE_ELEMENTS:
336      return Builtins::builtin(Builtins::KeyedStoreIC_ExternalByteArray);
337    case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
338      return Builtins::builtin(
339          Builtins::KeyedStoreIC_ExternalUnsignedByteArray);
340    case JSObject::EXTERNAL_SHORT_ELEMENTS:
341      return Builtins::builtin(Builtins::KeyedStoreIC_ExternalShortArray);
342    case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
343      return Builtins::builtin(
344          Builtins::KeyedStoreIC_ExternalUnsignedShortArray);
345    case JSObject::EXTERNAL_INT_ELEMENTS:
346      return Builtins::builtin(Builtins::KeyedStoreIC_ExternalIntArray);
347    case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
348      return Builtins::builtin(Builtins::KeyedStoreIC_ExternalUnsignedIntArray);
349    case JSObject::EXTERNAL_FLOAT_ELEMENTS:
350      return Builtins::builtin(Builtins::KeyedStoreIC_ExternalFloatArray);
351    default:
352      UNREACHABLE();
353      return NULL;
354  }
355}
356
357
358static bool HasInterceptorGetter(JSObject* object) {
359  return !object->GetNamedInterceptor()->getter()->IsUndefined();
360}
361
362
363static void LookupForRead(Object* object,
364                          String* name,
365                          LookupResult* lookup) {
366  AssertNoAllocation no_gc;  // pointers must stay valid
367
368  // Skip all the objects with named interceptors, but
369  // without actual getter.
370  while (true) {
371    object->Lookup(name, lookup);
372    // Besides normal conditions (property not found or it's not
373    // an interceptor), bail out if lookup is not cacheable: we won't
374    // be able to IC it anyway and regular lookup should work fine.
375    if (!lookup->IsFound()
376        || (lookup->type() != INTERCEPTOR)
377        || !lookup->IsCacheable()) {
378      return;
379    }
380
381    JSObject* holder = lookup->holder();
382    if (HasInterceptorGetter(holder)) {
383      return;
384    }
385
386    holder->LocalLookupRealNamedProperty(name, lookup);
387    if (lookup->IsProperty()) {
388      ASSERT(lookup->type() != INTERCEPTOR);
389      return;
390    }
391
392    Object* proto = holder->GetPrototype();
393    if (proto->IsNull()) {
394      lookup->NotFound();
395      return;
396    }
397
398    object = proto;
399  }
400}
401
402
403Object* CallICBase::TryCallAsFunction(Object* object) {
404  HandleScope scope;
405  Handle<Object> target(object);
406  Handle<Object> delegate = Execution::GetFunctionDelegate(target);
407
408  if (delegate->IsJSFunction()) {
409    // Patch the receiver and use the delegate as the function to
410    // invoke. This is used for invoking objects as if they were
411    // functions.
412    const int argc = this->target()->arguments_count();
413    StackFrameLocator locator;
414    JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
415    int index = frame->ComputeExpressionsCount() - (argc + 1);
416    frame->SetExpression(index, *target);
417  }
418
419  return *delegate;
420}
421
422
423void CallICBase::ReceiverToObject(Handle<Object> object) {
424  HandleScope scope;
425  Handle<Object> receiver(object);
426
427  // Change the receiver to the result of calling ToObject on it.
428  const int argc = this->target()->arguments_count();
429  StackFrameLocator locator;
430  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
431  int index = frame->ComputeExpressionsCount() - (argc + 1);
432  frame->SetExpression(index, *Factory::ToObject(object));
433}
434
435
436Object* CallICBase::LoadFunction(State state,
437                                 Handle<Object> object,
438                                 Handle<String> name) {
439  // If the object is undefined or null it's illegal to try to get any
440  // of its properties; throw a TypeError in that case.
441  if (object->IsUndefined() || object->IsNull()) {
442    return TypeError("non_object_property_call", object, name);
443  }
444
445  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
446    ReceiverToObject(object);
447  }
448
449  // Check if the name is trivially convertible to an index and get
450  // the element if so.
451  uint32_t index;
452  if (name->AsArrayIndex(&index)) {
453    Object* result = object->GetElement(index);
454    if (result->IsJSFunction()) return result;
455
456    // Try to find a suitable function delegate for the object at hand.
457    result = TryCallAsFunction(result);
458    if (result->IsJSFunction()) return result;
459
460    // Otherwise, it will fail in the lookup step.
461  }
462
463  // Lookup the property in the object.
464  LookupResult lookup;
465  LookupForRead(*object, *name, &lookup);
466
467  if (!lookup.IsProperty()) {
468    // If the object does not have the requested property, check which
469    // exception we need to throw.
470    if (IsContextual(object)) {
471      return ReferenceError("not_defined", name);
472    }
473    return TypeError("undefined_method", object, name);
474  }
475
476  // Lookup is valid: Update inline cache and stub cache.
477  if (FLAG_use_ic) {
478    UpdateCaches(&lookup, state, object, name);
479  }
480
481  // Get the property.
482  PropertyAttributes attr;
483  Object* result = object->GetProperty(*object, &lookup, *name, &attr);
484  if (result->IsFailure()) return result;
485  if (lookup.type() == INTERCEPTOR) {
486    // If the object does not have the requested property, check which
487    // exception we need to throw.
488    if (attr == ABSENT) {
489      if (IsContextual(object)) {
490        return ReferenceError("not_defined", name);
491      }
492      return TypeError("undefined_method", object, name);
493    }
494  }
495
496  ASSERT(result != Heap::the_hole_value());
497
498  if (result->IsJSFunction()) {
499#ifdef ENABLE_DEBUGGER_SUPPORT
500    // Handle stepping into a function if step into is active.
501    if (Debug::StepInActive()) {
502      // Protect the result in a handle as the debugger can allocate and might
503      // cause GC.
504      HandleScope scope;
505      Handle<JSFunction> function(JSFunction::cast(result));
506      Debug::HandleStepIn(function, object, fp(), false);
507      return *function;
508    }
509#endif
510
511    return result;
512  }
513
514  // Try to find a suitable function delegate for the object at hand.
515  result = TryCallAsFunction(result);
516  return result->IsJSFunction() ?
517      result : TypeError("property_not_function", object, name);
518}
519
520
521void CallICBase::UpdateCaches(LookupResult* lookup,
522                              State state,
523                              Handle<Object> object,
524                              Handle<String> name) {
525  // Bail out if we didn't find a result.
526  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
527
528#ifndef V8_TARGET_ARCH_IA32
529  // Normal objects only implemented for IA32 by now.
530  if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
531#else
532  if (lookup->holder() != *object &&
533      HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) {
534    // Suppress optimization for prototype chains with slow properties objects
535    // in the middle.
536    return;
537  }
538#endif
539
540  // Compute the number of arguments.
541  int argc = target()->arguments_count();
542  InLoopFlag in_loop = target()->ic_in_loop();
543  Object* code = NULL;
544
545  if (state == UNINITIALIZED) {
546    // This is the first time we execute this inline cache.
547    // Set the target to the pre monomorphic stub to delay
548    // setting the monomorphic state.
549    code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_);
550  } else if (state == MONOMORPHIC) {
551    code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_);
552  } else {
553    // Compute monomorphic stub.
554    switch (lookup->type()) {
555      case FIELD: {
556        int index = lookup->GetFieldIndex();
557        code = StubCache::ComputeCallField(argc,
558                                           in_loop,
559                                           kind_,
560                                           *name,
561                                           *object,
562                                           lookup->holder(),
563                                           index);
564        break;
565      }
566      case CONSTANT_FUNCTION: {
567        // Get the constant function and compute the code stub for this
568        // call; used for rewriting to monomorphic state and making sure
569        // that the code stub is in the stub cache.
570        JSFunction* function = lookup->GetConstantFunction();
571        code = StubCache::ComputeCallConstant(argc,
572                                              in_loop,
573                                              kind_,
574                                              *name,
575                                              *object,
576                                              lookup->holder(),
577                                              function);
578        break;
579      }
580      case NORMAL: {
581        if (!object->IsJSObject()) return;
582        Handle<JSObject> receiver = Handle<JSObject>::cast(object);
583
584        if (lookup->holder()->IsGlobalObject()) {
585          GlobalObject* global = GlobalObject::cast(lookup->holder());
586          JSGlobalPropertyCell* cell =
587              JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
588          if (!cell->value()->IsJSFunction()) return;
589          JSFunction* function = JSFunction::cast(cell->value());
590          code = StubCache::ComputeCallGlobal(argc,
591                                              in_loop,
592                                              kind_,
593                                              *name,
594                                              *receiver,
595                                              global,
596                                              cell,
597                                              function);
598        } else {
599          // There is only one shared stub for calling normalized
600          // properties. It does not traverse the prototype chain, so the
601          // property must be found in the receiver for the stub to be
602          // applicable.
603          if (lookup->holder() != *receiver) return;
604          code = StubCache::ComputeCallNormal(argc,
605                                              in_loop,
606                                              kind_,
607                                              *name,
608                                              *receiver);
609        }
610        break;
611      }
612      case INTERCEPTOR: {
613        ASSERT(HasInterceptorGetter(lookup->holder()));
614        code = StubCache::ComputeCallInterceptor(argc,
615                                                 kind_,
616                                                 *name,
617                                                 *object,
618                                                 lookup->holder());
619        break;
620      }
621      default:
622        return;
623    }
624  }
625
626  // If we're unable to compute the stub (not enough memory left), we
627  // simply avoid updating the caches.
628  if (code == NULL || code->IsFailure()) return;
629
630  // Patch the call site depending on the state of the cache.
631  if (state == UNINITIALIZED ||
632      state == PREMONOMORPHIC ||
633      state == MONOMORPHIC ||
634      state == MONOMORPHIC_PROTOTYPE_FAILURE) {
635    set_target(Code::cast(code));
636  } else if (state == MEGAMORPHIC) {
637    // Cache code holding map should be consistent with
638    // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
639    Map* map = JSObject::cast(object->IsJSObject() ? *object :
640                              object->GetPrototype())->map();
641
642    // Update the stub cache.
643    StubCache::Set(*name, map, Code::cast(code));
644  }
645
646#ifdef DEBUG
647  TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
648      name, state, target(), in_loop ? " (in-loop)" : "");
649#endif
650}
651
652
653Object* KeyedCallIC::LoadFunction(State state,
654                                  Handle<Object> object,
655                                  Handle<Object> key) {
656  if (key->IsSymbol()) {
657    return CallICBase::LoadFunction(state, object, Handle<String>::cast(key));
658  }
659
660  if (object->IsUndefined() || object->IsNull()) {
661    return TypeError("non_object_property_call", object, key);
662  }
663
664  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
665    ReceiverToObject(object);
666  }
667
668  if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
669    int argc = target()->arguments_count();
670    InLoopFlag in_loop = target()->ic_in_loop();
671    Object* code = StubCache::ComputeCallMegamorphic(
672        argc, in_loop, Code::KEYED_CALL_IC);
673    if (!code->IsFailure()) {
674      set_target(Code::cast(code));
675#ifdef DEBUG
676      TraceIC(
677          "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : "");
678#endif
679    }
680  }
681  Object* result = Runtime::GetObjectProperty(object, key);
682  if (result->IsJSFunction()) return result;
683  result = TryCallAsFunction(result);
684  return result->IsJSFunction() ?
685      result : TypeError("property_not_function", object, key);
686}
687
688
689Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
690  // If the object is undefined or null it's illegal to try to get any
691  // of its properties; throw a TypeError in that case.
692  if (object->IsUndefined() || object->IsNull()) {
693    return TypeError("non_object_property_load", object, name);
694  }
695
696  if (FLAG_use_ic) {
697    // Use specialized code for getting the length of strings and
698    // string wrapper objects.  The length property of string wrapper
699    // objects is read-only and therefore always returns the length of
700    // the underlying string value.  See ECMA-262 15.5.5.1.
701    if ((object->IsString() || object->IsStringWrapper()) &&
702        name->Equals(Heap::length_symbol())) {
703      HandleScope scope;
704      // Get the string if we have a string wrapper object.
705      if (object->IsJSValue()) {
706        object = Handle<Object>(Handle<JSValue>::cast(object)->value());
707      }
708#ifdef DEBUG
709      if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
710#endif
711      Map* map = HeapObject::cast(*object)->map();
712      if (object->IsString()) {
713        const int offset = String::kLengthOffset;
714        PatchInlinedLoad(address(), map, offset);
715      }
716
717      Code* target = NULL;
718      target = Builtins::builtin(Builtins::LoadIC_StringLength);
719      set_target(target);
720      return Smi::FromInt(String::cast(*object)->length());
721    }
722
723    // Use specialized code for getting the length of arrays.
724    if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
725#ifdef DEBUG
726      if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
727#endif
728      Map* map = HeapObject::cast(*object)->map();
729      const int offset = JSArray::kLengthOffset;
730      PatchInlinedLoad(address(), map, offset);
731
732      Code* target = Builtins::builtin(Builtins::LoadIC_ArrayLength);
733      set_target(target);
734      return JSArray::cast(*object)->length();
735    }
736
737    // Use specialized code for getting prototype of functions.
738    if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
739        JSFunction::cast(*object)->should_have_prototype()) {
740#ifdef DEBUG
741      if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
742#endif
743      Code* target = Builtins::builtin(Builtins::LoadIC_FunctionPrototype);
744      set_target(target);
745      return Accessors::FunctionGetPrototype(*object, 0);
746    }
747  }
748
749  // Check if the name is trivially convertible to an index and get
750  // the element if so.
751  uint32_t index;
752  if (name->AsArrayIndex(&index)) return object->GetElement(index);
753
754  // Named lookup in the object.
755  LookupResult lookup;
756  LookupForRead(*object, *name, &lookup);
757
758  // If we did not find a property, check if we need to throw an exception.
759  if (!lookup.IsProperty()) {
760    if (FLAG_strict || IsContextual(object)) {
761      return ReferenceError("not_defined", name);
762    }
763    LOG(SuspectReadEvent(*name, *object));
764  }
765
766  bool can_be_inlined =
767      FLAG_use_ic &&
768      state == PREMONOMORPHIC &&
769      lookup.IsProperty() &&
770      lookup.IsCacheable() &&
771      lookup.holder() == *object &&
772      lookup.type() == FIELD &&
773      !object->IsAccessCheckNeeded();
774
775  if (can_be_inlined) {
776    Map* map = lookup.holder()->map();
777    // Property's index in the properties array.  If negative we have
778    // an inobject property.
779    int index = lookup.GetFieldIndex() - map->inobject_properties();
780    if (index < 0) {
781      // Index is an offset from the end of the object.
782      int offset = map->instance_size() + (index * kPointerSize);
783      if (PatchInlinedLoad(address(), map, offset)) {
784        set_target(megamorphic_stub());
785        return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
786#ifdef DEBUG
787        if (FLAG_trace_ic) {
788          PrintF("[LoadIC : inline patch %s]\n", *name->ToCString());
789        }
790      } else {
791        if (FLAG_trace_ic) {
792          PrintF("[LoadIC : no inline patch %s (patching failed)]\n",
793                 *name->ToCString());
794        }
795      }
796    } else {
797      if (FLAG_trace_ic) {
798        PrintF("[LoadIC : no inline patch %s (not inobject)]\n",
799               *name->ToCString());
800      }
801    }
802  } else {
803    if (FLAG_use_ic && state == PREMONOMORPHIC) {
804      if (FLAG_trace_ic) {
805        PrintF("[LoadIC : no inline patch %s (not inlinable)]\n",
806               *name->ToCString());
807#endif
808      }
809    }
810  }
811
812  // Update inline cache and stub cache.
813  if (FLAG_use_ic) {
814    UpdateCaches(&lookup, state, object, name);
815  }
816
817  PropertyAttributes attr;
818  if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
819    // Get the property.
820    Object* result = object->GetProperty(*object, &lookup, *name, &attr);
821    if (result->IsFailure()) return result;
822    // If the property is not present, check if we need to throw an
823    // exception.
824    if (attr == ABSENT && IsContextual(object)) {
825      return ReferenceError("not_defined", name);
826    }
827    return result;
828  }
829
830  // Get the property.
831  return object->GetProperty(*object, &lookup, *name, &attr);
832}
833
834
835void LoadIC::UpdateCaches(LookupResult* lookup,
836                          State state,
837                          Handle<Object> object,
838                          Handle<String> name) {
839  // Bail out if the result is not cacheable.
840  if (!lookup->IsCacheable()) return;
841
842  // Loading properties from values is not common, so don't try to
843  // deal with non-JS objects here.
844  if (!object->IsJSObject()) return;
845  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
846
847  if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
848
849  // Compute the code stub for this load.
850  Object* code = NULL;
851  if (state == UNINITIALIZED) {
852    // This is the first time we execute this inline cache.
853    // Set the target to the pre monomorphic stub to delay
854    // setting the monomorphic state.
855    code = pre_monomorphic_stub();
856  } else if (!lookup->IsProperty()) {
857    // Nonexistent property. The result is undefined.
858    code = StubCache::ComputeLoadNonexistent(*name, *receiver);
859  } else {
860    // Compute monomorphic stub.
861    switch (lookup->type()) {
862      case FIELD: {
863        code = StubCache::ComputeLoadField(*name, *receiver,
864                                           lookup->holder(),
865                                           lookup->GetFieldIndex());
866        break;
867      }
868      case CONSTANT_FUNCTION: {
869        Object* constant = lookup->GetConstantFunction();
870        code = StubCache::ComputeLoadConstant(*name, *receiver,
871                                              lookup->holder(), constant);
872        break;
873      }
874      case NORMAL: {
875        if (lookup->holder()->IsGlobalObject()) {
876          GlobalObject* global = GlobalObject::cast(lookup->holder());
877          JSGlobalPropertyCell* cell =
878              JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
879          code = StubCache::ComputeLoadGlobal(*name,
880                                              *receiver,
881                                              global,
882                                              cell,
883                                              lookup->IsDontDelete());
884        } else {
885          // There is only one shared stub for loading normalized
886          // properties. It does not traverse the prototype chain, so the
887          // property must be found in the receiver for the stub to be
888          // applicable.
889          if (lookup->holder() != *receiver) return;
890          code = StubCache::ComputeLoadNormal();
891        }
892        break;
893      }
894      case CALLBACKS: {
895        if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
896        AccessorInfo* callback =
897            AccessorInfo::cast(lookup->GetCallbackObject());
898        if (v8::ToCData<Address>(callback->getter()) == 0) return;
899        code = StubCache::ComputeLoadCallback(*name, *receiver,
900                                              lookup->holder(), callback);
901        break;
902      }
903      case INTERCEPTOR: {
904        ASSERT(HasInterceptorGetter(lookup->holder()));
905        code = StubCache::ComputeLoadInterceptor(*name, *receiver,
906                                                 lookup->holder());
907        break;
908      }
909      default:
910        return;
911    }
912  }
913
914  // If we're unable to compute the stub (not enough memory left), we
915  // simply avoid updating the caches.
916  if (code == NULL || code->IsFailure()) return;
917
918  // Patch the call site depending on the state of the cache.
919  if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
920      state == MONOMORPHIC_PROTOTYPE_FAILURE) {
921    set_target(Code::cast(code));
922  } else if (state == MONOMORPHIC) {
923    set_target(megamorphic_stub());
924  } else if (state == MEGAMORPHIC) {
925    // Cache code holding map should be consistent with
926    // GenerateMonomorphicCacheProbe.
927    Map* map = JSObject::cast(object->IsJSObject() ? *object :
928                              object->GetPrototype())->map();
929
930    StubCache::Set(*name, map, Code::cast(code));
931  }
932
933#ifdef DEBUG
934  TraceIC("LoadIC", name, state, target());
935#endif
936}
937
938
939Object* KeyedLoadIC::Load(State state,
940                          Handle<Object> object,
941                          Handle<Object> key) {
942  if (key->IsSymbol()) {
943    Handle<String> name = Handle<String>::cast(key);
944
945    // If the object is undefined or null it's illegal to try to get any
946    // of its properties; throw a TypeError in that case.
947    if (object->IsUndefined() || object->IsNull()) {
948      return TypeError("non_object_property_load", object, name);
949    }
950
951    if (FLAG_use_ic) {
952      // Use specialized code for getting the length of strings.
953      if (object->IsString() && name->Equals(Heap::length_symbol())) {
954        Handle<String> string = Handle<String>::cast(object);
955        Object* code = NULL;
956        code = StubCache::ComputeKeyedLoadStringLength(*name, *string);
957        if (code->IsFailure()) return code;
958        set_target(Code::cast(code));
959#ifdef DEBUG
960        TraceIC("KeyedLoadIC", name, state, target());
961#endif  // DEBUG
962        return Smi::FromInt(string->length());
963      }
964
965      // Use specialized code for getting the length of arrays.
966      if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
967        Handle<JSArray> array = Handle<JSArray>::cast(object);
968        Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array);
969        if (code->IsFailure()) return code;
970        set_target(Code::cast(code));
971#ifdef DEBUG
972        TraceIC("KeyedLoadIC", name, state, target());
973#endif  // DEBUG
974        return JSArray::cast(*object)->length();
975      }
976
977      // Use specialized code for getting prototype of functions.
978      if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
979        JSFunction::cast(*object)->should_have_prototype()) {
980        Handle<JSFunction> function = Handle<JSFunction>::cast(object);
981        Object* code =
982            StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function);
983        if (code->IsFailure()) return code;
984        set_target(Code::cast(code));
985#ifdef DEBUG
986        TraceIC("KeyedLoadIC", name, state, target());
987#endif  // DEBUG
988        return Accessors::FunctionGetPrototype(*object, 0);
989      }
990    }
991
992    // Check if the name is trivially convertible to an index and get
993    // the element or char if so.
994    uint32_t index = 0;
995    if (name->AsArrayIndex(&index)) {
996      HandleScope scope;
997      // Rewrite to the generic keyed load stub.
998      if (FLAG_use_ic) set_target(generic_stub());
999      return Runtime::GetElementOrCharAt(object, index);
1000    }
1001
1002    // Named lookup.
1003    LookupResult lookup;
1004    LookupForRead(*object, *name, &lookup);
1005
1006    // If we did not find a property, check if we need to throw an exception.
1007    if (!lookup.IsProperty()) {
1008      if (FLAG_strict || IsContextual(object)) {
1009        return ReferenceError("not_defined", name);
1010      }
1011    }
1012
1013    if (FLAG_use_ic) {
1014      UpdateCaches(&lookup, state, object, name);
1015    }
1016
1017    PropertyAttributes attr;
1018    if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
1019      // Get the property.
1020      Object* result = object->GetProperty(*object, &lookup, *name, &attr);
1021      if (result->IsFailure()) return result;
1022      // If the property is not present, check if we need to throw an
1023      // exception.
1024      if (attr == ABSENT && IsContextual(object)) {
1025        return ReferenceError("not_defined", name);
1026      }
1027      return result;
1028    }
1029
1030    return object->GetProperty(*object, &lookup, *name, &attr);
1031  }
1032
1033  // Do not use ICs for objects that require access checks (including
1034  // the global object).
1035  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1036
1037  if (use_ic) {
1038    Code* stub = generic_stub();
1039    if (object->IsString() && key->IsNumber()) {
1040      stub = string_stub();
1041    } else if (object->IsJSObject()) {
1042      Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1043      if (receiver->HasExternalArrayElements()) {
1044        stub = external_array_stub(receiver->GetElementsKind());
1045      } else if (receiver->HasIndexedInterceptor()) {
1046        stub = indexed_interceptor_stub();
1047      }
1048    }
1049    set_target(stub);
1050    // For JSObjects with fast elements that are not value wrappers
1051    // and that do not have indexed interceptors, we initialize the
1052    // inlined fast case (if present) by patching the inlined map
1053    // check.
1054    if (object->IsJSObject() &&
1055        !object->IsJSValue() &&
1056        !JSObject::cast(*object)->HasIndexedInterceptor() &&
1057        JSObject::cast(*object)->HasFastElements()) {
1058      Map* map = JSObject::cast(*object)->map();
1059      PatchInlinedLoad(address(), map);
1060    }
1061  }
1062
1063  // Get the property.
1064  return Runtime::GetObjectProperty(object, key);
1065}
1066
1067
1068void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
1069                               Handle<Object> object, Handle<String> name) {
1070  // Bail out if we didn't find a result.
1071  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
1072
1073  if (!object->IsJSObject()) return;
1074  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1075
1076  if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
1077
1078  // Compute the code stub for this load.
1079  Object* code = NULL;
1080
1081  if (state == UNINITIALIZED) {
1082    // This is the first time we execute this inline cache.
1083    // Set the target to the pre monomorphic stub to delay
1084    // setting the monomorphic state.
1085    code = pre_monomorphic_stub();
1086  } else {
1087    // Compute a monomorphic stub.
1088    switch (lookup->type()) {
1089      case FIELD: {
1090        code = StubCache::ComputeKeyedLoadField(*name, *receiver,
1091                                                lookup->holder(),
1092                                                lookup->GetFieldIndex());
1093        break;
1094      }
1095      case CONSTANT_FUNCTION: {
1096        Object* constant = lookup->GetConstantFunction();
1097        code = StubCache::ComputeKeyedLoadConstant(*name, *receiver,
1098                                                   lookup->holder(), constant);
1099        break;
1100      }
1101      case CALLBACKS: {
1102        if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
1103        AccessorInfo* callback =
1104            AccessorInfo::cast(lookup->GetCallbackObject());
1105        if (v8::ToCData<Address>(callback->getter()) == 0) return;
1106        code = StubCache::ComputeKeyedLoadCallback(*name, *receiver,
1107                                                   lookup->holder(), callback);
1108        break;
1109      }
1110      case INTERCEPTOR: {
1111        ASSERT(HasInterceptorGetter(lookup->holder()));
1112        code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver,
1113                                                      lookup->holder());
1114        break;
1115      }
1116      default: {
1117        // Always rewrite to the generic case so that we do not
1118        // repeatedly try to rewrite.
1119        code = generic_stub();
1120        break;
1121      }
1122    }
1123  }
1124
1125  // If we're unable to compute the stub (not enough memory left), we
1126  // simply avoid updating the caches.
1127  if (code == NULL || code->IsFailure()) return;
1128
1129  // Patch the call site depending on the state of the cache.  Make
1130  // sure to always rewrite from monomorphic to megamorphic.
1131  ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
1132  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1133    set_target(Code::cast(code));
1134  } else if (state == MONOMORPHIC) {
1135    set_target(megamorphic_stub());
1136  }
1137
1138#ifdef DEBUG
1139  TraceIC("KeyedLoadIC", name, state, target());
1140#endif
1141}
1142
1143
1144static bool StoreICableLookup(LookupResult* lookup) {
1145  // Bail out if we didn't find a result.
1146  if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false;
1147
1148  // If the property is read-only, we leave the IC in its current
1149  // state.
1150  if (lookup->IsReadOnly()) return false;
1151
1152  return true;
1153}
1154
1155
1156static bool LookupForWrite(JSObject* object,
1157                           String* name,
1158                           LookupResult* lookup) {
1159  object->LocalLookup(name, lookup);
1160  if (!StoreICableLookup(lookup)) {
1161    return false;
1162  }
1163
1164  if (lookup->type() == INTERCEPTOR) {
1165    if (object->GetNamedInterceptor()->setter()->IsUndefined()) {
1166      object->LocalLookupRealNamedProperty(name, lookup);
1167      return StoreICableLookup(lookup);
1168    }
1169  }
1170
1171  return true;
1172}
1173
1174
1175Object* StoreIC::Store(State state,
1176                       Handle<Object> object,
1177                       Handle<String> name,
1178                       Handle<Object> value) {
1179  // If the object is undefined or null it's illegal to try to set any
1180  // properties on it; throw a TypeError in that case.
1181  if (object->IsUndefined() || object->IsNull()) {
1182    return TypeError("non_object_property_store", object, name);
1183  }
1184
1185  // Ignore stores where the receiver is not a JSObject.
1186  if (!object->IsJSObject()) return *value;
1187  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1188
1189  // Check if the given name is an array index.
1190  uint32_t index;
1191  if (name->AsArrayIndex(&index)) {
1192    HandleScope scope;
1193    Handle<Object> result = SetElement(receiver, index, value);
1194    if (result.is_null()) return Failure::Exception();
1195    return *value;
1196  }
1197
1198  // Use specialized code for setting the length of arrays.
1199  if (receiver->IsJSArray()
1200      && name->Equals(Heap::length_symbol())
1201      && receiver->AllowsSetElementsLength()) {
1202#ifdef DEBUG
1203    if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
1204#endif
1205    Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength);
1206    set_target(target);
1207    return receiver->SetProperty(*name, *value, NONE);
1208  }
1209
1210  // Lookup the property locally in the receiver.
1211  if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
1212    LookupResult lookup;
1213    if (LookupForWrite(*receiver, *name, &lookup)) {
1214      UpdateCaches(&lookup, state, receiver, name, value);
1215    }
1216  }
1217
1218  // Set the property.
1219  return receiver->SetProperty(*name, *value, NONE);
1220}
1221
1222
1223void StoreIC::UpdateCaches(LookupResult* lookup,
1224                           State state,
1225                           Handle<JSObject> receiver,
1226                           Handle<String> name,
1227                           Handle<Object> value) {
1228  // Skip JSGlobalProxy.
1229  ASSERT(!receiver->IsJSGlobalProxy());
1230
1231  ASSERT(StoreICableLookup(lookup));
1232
1233  // If the property has a non-field type allowing map transitions
1234  // where there is extra room in the object, we leave the IC in its
1235  // current state.
1236  PropertyType type = lookup->type();
1237
1238  // Compute the code stub for this store; used for rewriting to
1239  // monomorphic state and making sure that the code stub is in the
1240  // stub cache.
1241  Object* code = NULL;
1242  switch (type) {
1243    case FIELD: {
1244      code = StubCache::ComputeStoreField(*name, *receiver,
1245                                          lookup->GetFieldIndex());
1246      break;
1247    }
1248    case MAP_TRANSITION: {
1249      if (lookup->GetAttributes() != NONE) return;
1250      HandleScope scope;
1251      ASSERT(type == MAP_TRANSITION);
1252      Handle<Map> transition(lookup->GetTransitionMap());
1253      int index = transition->PropertyIndexFor(*name);
1254      code = StubCache::ComputeStoreField(*name, *receiver, index, *transition);
1255      break;
1256    }
1257    case NORMAL: {
1258      if (receiver->IsGlobalObject()) {
1259        // The stub generated for the global object picks the value directly
1260        // from the property cell. So the property must be directly on the
1261        // global object.
1262        Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1263        JSGlobalPropertyCell* cell =
1264            JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
1265        code = StubCache::ComputeStoreGlobal(*name, *global, cell);
1266      } else {
1267        if (lookup->holder() != *receiver) return;
1268        code = StubCache::ComputeStoreNormal();
1269      }
1270      break;
1271    }
1272    case CALLBACKS: {
1273      if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
1274      AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1275      if (v8::ToCData<Address>(callback->setter()) == 0) return;
1276      code = StubCache::ComputeStoreCallback(*name, *receiver, callback);
1277      break;
1278    }
1279    case INTERCEPTOR: {
1280      ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
1281      code = StubCache::ComputeStoreInterceptor(*name, *receiver);
1282      break;
1283    }
1284    default:
1285      return;
1286  }
1287
1288  // If we're unable to compute the stub (not enough memory left), we
1289  // simply avoid updating the caches.
1290  if (code == NULL || code->IsFailure()) return;
1291
1292  // Patch the call site depending on the state of the cache.
1293  if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1294    set_target(Code::cast(code));
1295  } else if (state == MONOMORPHIC) {
1296    // Only move to megamorphic if the target changes.
1297    if (target() != Code::cast(code)) set_target(megamorphic_stub());
1298  } else if (state == MEGAMORPHIC) {
1299    // Update the stub cache.
1300    StubCache::Set(*name, receiver->map(), Code::cast(code));
1301  }
1302
1303#ifdef DEBUG
1304  TraceIC("StoreIC", name, state, target());
1305#endif
1306}
1307
1308
1309Object* KeyedStoreIC::Store(State state,
1310                            Handle<Object> object,
1311                            Handle<Object> key,
1312                            Handle<Object> value) {
1313  if (key->IsSymbol()) {
1314    Handle<String> name = Handle<String>::cast(key);
1315
1316    // If the object is undefined or null it's illegal to try to set any
1317    // properties on it; throw a TypeError in that case.
1318    if (object->IsUndefined() || object->IsNull()) {
1319      return TypeError("non_object_property_store", object, name);
1320    }
1321
1322    // Ignore stores where the receiver is not a JSObject.
1323    if (!object->IsJSObject()) return *value;
1324    Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1325
1326    // Check if the given name is an array index.
1327    uint32_t index;
1328    if (name->AsArrayIndex(&index)) {
1329      HandleScope scope;
1330      Handle<Object> result = SetElement(receiver, index, value);
1331      if (result.is_null()) return Failure::Exception();
1332      return *value;
1333    }
1334
1335    // Lookup the property locally in the receiver.
1336    LookupResult lookup;
1337    receiver->LocalLookup(*name, &lookup);
1338
1339    // Update inline cache and stub cache.
1340    if (FLAG_use_ic) {
1341      UpdateCaches(&lookup, state, receiver, name, value);
1342    }
1343
1344    // Set the property.
1345    return receiver->SetProperty(*name, *value, NONE);
1346  }
1347
1348  // Do not use ICs for objects that require access checks (including
1349  // the global object).
1350  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1351  ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1352
1353  if (use_ic) {
1354    Code* stub = generic_stub();
1355    if (object->IsJSObject()) {
1356      Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1357      if (receiver->HasExternalArrayElements()) {
1358        stub = external_array_stub(receiver->GetElementsKind());
1359      }
1360    }
1361    set_target(stub);
1362  }
1363
1364  // Set the property.
1365  return Runtime::SetObjectProperty(object, key, value, NONE);
1366}
1367
1368
1369void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1370                                State state,
1371                                Handle<JSObject> receiver,
1372                                Handle<String> name,
1373                                Handle<Object> value) {
1374  // Skip JSGlobalProxy.
1375  if (receiver->IsJSGlobalProxy()) return;
1376
1377  // Bail out if we didn't find a result.
1378  if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return;
1379
1380  // If the property is read-only, we leave the IC in its current
1381  // state.
1382  if (lookup->IsReadOnly()) return;
1383
1384  // If the property has a non-field type allowing map transitions
1385  // where there is extra room in the object, we leave the IC in its
1386  // current state.
1387  PropertyType type = lookup->type();
1388
1389  // Compute the code stub for this store; used for rewriting to
1390  // monomorphic state and making sure that the code stub is in the
1391  // stub cache.
1392  Object* code = NULL;
1393
1394  switch (type) {
1395    case FIELD: {
1396      code = StubCache::ComputeKeyedStoreField(*name, *receiver,
1397                                               lookup->GetFieldIndex());
1398      break;
1399    }
1400    case MAP_TRANSITION: {
1401      if (lookup->GetAttributes() == NONE) {
1402        HandleScope scope;
1403        ASSERT(type == MAP_TRANSITION);
1404        Handle<Map> transition(lookup->GetTransitionMap());
1405        int index = transition->PropertyIndexFor(*name);
1406        code = StubCache::ComputeKeyedStoreField(*name, *receiver,
1407                                                 index, *transition);
1408        break;
1409      }
1410      // fall through.
1411    }
1412    default: {
1413      // Always rewrite to the generic case so that we do not
1414      // repeatedly try to rewrite.
1415      code = generic_stub();
1416      break;
1417    }
1418  }
1419
1420  // If we're unable to compute the stub (not enough memory left), we
1421  // simply avoid updating the caches.
1422  if (code == NULL || code->IsFailure()) return;
1423
1424  // Patch the call site depending on the state of the cache.  Make
1425  // sure to always rewrite from monomorphic to megamorphic.
1426  ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
1427  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1428    set_target(Code::cast(code));
1429  } else if (state == MONOMORPHIC) {
1430    set_target(megamorphic_stub());
1431  }
1432
1433#ifdef DEBUG
1434  TraceIC("KeyedStoreIC", name, state, target());
1435#endif
1436}
1437
1438
1439// ----------------------------------------------------------------------------
1440// Static IC stub generators.
1441//
1442
1443static Object* CompileFunction(Object* result,
1444                               Handle<Object> object,
1445                               InLoopFlag in_loop) {
1446  // Compile now with optimization.
1447  HandleScope scope;
1448  Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result));
1449  if (in_loop == IN_LOOP) {
1450    CompileLazyInLoop(function, object, CLEAR_EXCEPTION);
1451  } else {
1452    CompileLazy(function, object, CLEAR_EXCEPTION);
1453  }
1454  return *function;
1455}
1456
1457
1458// Used from ic-<arch>.cc.
1459Object* CallIC_Miss(Arguments args) {
1460  NoHandleAllocation na;
1461  ASSERT(args.length() == 2);
1462  CallIC ic;
1463  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1464  Object* result =
1465      ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
1466
1467  // The first time the inline cache is updated may be the first time the
1468  // function it references gets called.  If the function was lazily compiled
1469  // then the first call will trigger a compilation.  We check for this case
1470  // and we do the compilation immediately, instead of waiting for the stub
1471  // currently attached to the JSFunction object to trigger compilation.  We
1472  // do this in the case where we know that the inline cache is inside a loop,
1473  // because then we know that we want to optimize the function.
1474  if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
1475    return result;
1476  }
1477  return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop());
1478}
1479
1480
1481// Used from ic-<arch>.cc.
1482Object* KeyedCallIC_Miss(Arguments args) {
1483  NoHandleAllocation na;
1484  ASSERT(args.length() == 2);
1485  KeyedCallIC ic;
1486  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1487  Object* result =
1488      ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
1489
1490  if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
1491    return result;
1492  }
1493  return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop());
1494}
1495
1496
1497// Used from ic-<arch>.cc.
1498Object* LoadIC_Miss(Arguments args) {
1499  NoHandleAllocation na;
1500  ASSERT(args.length() == 2);
1501  LoadIC ic;
1502  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1503  return ic.Load(state, args.at<Object>(0), args.at<String>(1));
1504}
1505
1506
1507// Used from ic-<arch>.cc
1508Object* KeyedLoadIC_Miss(Arguments args) {
1509  NoHandleAllocation na;
1510  ASSERT(args.length() == 2);
1511  KeyedLoadIC ic;
1512  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1513  return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
1514}
1515
1516
1517// Used from ic-<arch>.cc.
1518Object* StoreIC_Miss(Arguments args) {
1519  NoHandleAllocation na;
1520  ASSERT(args.length() == 3);
1521  StoreIC ic;
1522  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1523  return ic.Store(state, args.at<Object>(0), args.at<String>(1),
1524                  args.at<Object>(2));
1525}
1526
1527
1528Object* StoreIC_ArrayLength(Arguments args) {
1529  NoHandleAllocation nha;
1530
1531  ASSERT(args.length() == 2);
1532  JSObject* receiver = JSObject::cast(args[0]);
1533  Object* len = args[1];
1534
1535  Object* result = receiver->SetElementsLength(len);
1536  if (result->IsFailure()) return result;
1537  return len;
1538}
1539
1540
1541// Extend storage is called in a store inline cache when
1542// it is necessary to extend the properties array of a
1543// JSObject.
1544Object* SharedStoreIC_ExtendStorage(Arguments args) {
1545  NoHandleAllocation na;
1546  ASSERT(args.length() == 3);
1547
1548  // Convert the parameters
1549  JSObject* object = JSObject::cast(args[0]);
1550  Map* transition = Map::cast(args[1]);
1551  Object* value = args[2];
1552
1553  // Check the object has run out out property space.
1554  ASSERT(object->HasFastProperties());
1555  ASSERT(object->map()->unused_property_fields() == 0);
1556
1557  // Expand the properties array.
1558  FixedArray* old_storage = object->properties();
1559  int new_unused = transition->unused_property_fields();
1560  int new_size = old_storage->length() + new_unused + 1;
1561  Object* result = old_storage->CopySize(new_size);
1562  if (result->IsFailure()) return result;
1563  FixedArray* new_storage = FixedArray::cast(result);
1564  new_storage->set(old_storage->length(), value);
1565
1566  // Set the new property value and do the map transition.
1567  object->set_properties(new_storage);
1568  object->set_map(transition);
1569
1570  // Return the stored value.
1571  return value;
1572}
1573
1574
1575// Used from ic-<arch>.cc.
1576Object* KeyedStoreIC_Miss(Arguments args) {
1577  NoHandleAllocation na;
1578  ASSERT(args.length() == 3);
1579  KeyedStoreIC ic;
1580  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1581  return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
1582                  args.at<Object>(2));
1583}
1584
1585
1586void BinaryOpIC::patch(Code* code) {
1587  set_target(code);
1588}
1589
1590
1591const char* BinaryOpIC::GetName(TypeInfo type_info) {
1592  switch (type_info) {
1593    case DEFAULT: return "Default";
1594    case GENERIC: return "Generic";
1595    case HEAP_NUMBERS: return "HeapNumbers";
1596    case STRINGS: return "Strings";
1597    default: return "Invalid";
1598  }
1599}
1600
1601
1602BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) {
1603  switch (type_info) {
1604    // DEFAULT is mapped to UNINITIALIZED so that calls to DEFAULT stubs
1605    // are not cleared at GC.
1606    case DEFAULT: return UNINITIALIZED;
1607
1608    // Could have mapped GENERIC to MONOMORPHIC just as well but MEGAMORPHIC is
1609    // conceptually closer.
1610    case GENERIC: return MEGAMORPHIC;
1611
1612    default: return MONOMORPHIC;
1613  }
1614}
1615
1616
1617BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Object* left,
1618                                             Object* right) {
1619  if (left->IsSmi() && right->IsSmi()) {
1620    return GENERIC;
1621  }
1622
1623  if (left->IsNumber() && right->IsNumber()) {
1624    return HEAP_NUMBERS;
1625  }
1626
1627  if (left->IsString() || right->IsString()) {
1628    // Patching for fast string ADD makes sense even if only one of the
1629    // arguments is a string.
1630    return STRINGS;
1631  }
1632
1633  return GENERIC;
1634}
1635
1636
1637// defined in codegen-<arch>.cc
1638Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info);
1639
1640
1641Object* BinaryOp_Patch(Arguments args) {
1642  ASSERT(args.length() == 6);
1643
1644  Handle<Object> left = args.at<Object>(0);
1645  Handle<Object> right = args.at<Object>(1);
1646  Handle<Object> result = args.at<Object>(2);
1647  int key = Smi::cast(args[3])->value();
1648#ifdef DEBUG
1649  Token::Value op = static_cast<Token::Value>(Smi::cast(args[4])->value());
1650  BinaryOpIC::TypeInfo prev_type_info =
1651      static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[5])->value());
1652#endif  // DEBUG
1653  { HandleScope scope;
1654    BinaryOpIC::TypeInfo type_info = BinaryOpIC::GetTypeInfo(*left, *right);
1655    Handle<Code> code = GetBinaryOpStub(key, type_info);
1656    if (!code.is_null()) {
1657      BinaryOpIC ic;
1658      ic.patch(*code);
1659#ifdef DEBUG
1660      if (FLAG_trace_ic) {
1661        PrintF("[BinaryOpIC (%s->%s)#%s]\n",
1662            BinaryOpIC::GetName(prev_type_info),
1663            BinaryOpIC::GetName(type_info),
1664            Token::Name(op));
1665      }
1666#endif  // DEBUG
1667    }
1668  }
1669
1670  return *result;
1671}
1672
1673
1674static Address IC_utilities[] = {
1675#define ADDR(name) FUNCTION_ADDR(name),
1676    IC_UTIL_LIST(ADDR)
1677    NULL
1678#undef ADDR
1679};
1680
1681
1682Address IC::AddressFromUtilityId(IC::UtilityId id) {
1683  return IC_utilities[id];
1684}
1685
1686
1687} }  // namespace v8::internal
1688