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