// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "v8.h"

#include "accessors.h"
#include "api.h"
#include "arguments.h"
#include "codegen.h"
#include "execution.h"
#include "ic-inl.h"
#include "runtime.h"
#include "stub-cache.h"

namespace v8 {
namespace internal {

#ifdef DEBUG
static char TransitionMarkFromState(IC::State state) {
  switch (state) {
    case UNINITIALIZED: return '0';
    case PREMONOMORPHIC: return 'P';
    case MONOMORPHIC: return '1';
    case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
    case MEGAMORPHIC: return 'N';

    // We never see the debugger states here, because the state is
    // computed from the original code - not the patched code. Let
    // these cases fall through to the unreachable code below.
    case DEBUG_BREAK: break;
    case DEBUG_PREPARE_STEP_IN: break;
  }
  UNREACHABLE();
  return 0;
}

void IC::TraceIC(const char* type,
                 Handle<Object> name,
                 State old_state,
                 Code* new_target,
                 const char* extra_info) {
  if (FLAG_trace_ic) {
    State new_state = StateFrom(new_target,
                                HEAP->undefined_value(),
                                HEAP->undefined_value());
    PrintF("[%s in ", type);
    StackFrameIterator it;
    while (it.frame()->fp() != this->fp()) it.Advance();
    StackFrame* raw_frame = it.frame();
    if (raw_frame->is_internal()) {
      Isolate* isolate = new_target->GetIsolate();
      Code* apply_builtin = isolate->builtins()->builtin(
          Builtins::kFunctionApply);
      if (raw_frame->unchecked_code() == apply_builtin) {
        PrintF("apply from ");
        it.Advance();
        raw_frame = it.frame();
      }
    }
    if (raw_frame->is_java_script()) {
      JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
      Code* js_code = frame->unchecked_code();
      // Find the function on the stack and both the active code for the
      // function and the original code.
      JSFunction* function = JSFunction::cast(frame->function());
      function->PrintName();
      int code_offset = address() - js_code->instruction_start();
      PrintF("+%d", code_offset);
    } else {
      PrintF("<unknown>");
    }
    PrintF(" (%c->%c)%s",
           TransitionMarkFromState(old_state),
           TransitionMarkFromState(new_state),
           extra_info);
    name->Print();
    PrintF("]\n");
  }
}
#endif


IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
  ASSERT(isolate == Isolate::Current());
  // To improve the performance of the (much used) IC code, we unfold
  // a few levels of the stack frame iteration code. This yields a
  // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag.
  const Address entry =
      Isolate::c_entry_fp(isolate->thread_local_top());
  Address* pc_address =
      reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
  Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
  // If there's another JavaScript frame on the stack, we need to look
  // one frame further down the stack to find the frame pointer and
  // the return address stack slot.
  if (depth == EXTRA_CALL_FRAME) {
    const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
    pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
    fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
  }
#ifdef DEBUG
  StackFrameIterator it;
  for (int i = 0; i < depth + 1; i++) it.Advance();
  StackFrame* frame = it.frame();
  ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
#endif
  fp_ = fp;
  pc_address_ = pc_address;
}


#ifdef ENABLE_DEBUGGER_SUPPORT
Address IC::OriginalCodeAddress() {
  HandleScope scope;
  // Compute the JavaScript frame for the frame pointer of this IC
  // structure. We need this to be able to find the function
  // corresponding to the frame.
  StackFrameIterator it;
  while (it.frame()->fp() != this->fp()) it.Advance();
  JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
  // Find the function on the stack and both the active code for the
  // function and the original code.
  JSFunction* function = JSFunction::cast(frame->function());
  Handle<SharedFunctionInfo> shared(function->shared());
  Code* code = shared->code();
  ASSERT(Debug::HasDebugInfo(shared));
  Code* original_code = Debug::GetDebugInfo(shared)->original_code();
  ASSERT(original_code->IsCode());
  // Get the address of the call site in the active code. This is the
  // place where the call to DebugBreakXXX is and where the IC
  // normally would be.
  Address addr = pc() - Assembler::kCallTargetAddressOffset;
  // Return the address in the original code. This is the place where
  // the call which has been overwritten by the DebugBreakXXX resides
  // and the place where the inline cache system should look.
  intptr_t delta =
      original_code->instruction_start() - code->instruction_start();
  return addr + delta;
}
#endif


static bool HasNormalObjectsInPrototypeChain(Isolate* isolate,
                                             LookupResult* lookup,
                                             Object* receiver) {
  Object* end = lookup->IsProperty()
      ? lookup->holder() : isolate->heap()->null_value();
  for (Object* current = receiver;
       current != end;
       current = current->GetPrototype()) {
    if (current->IsJSObject() &&
        !JSObject::cast(current)->HasFastProperties() &&
        !current->IsJSGlobalProxy() &&
        !current->IsJSGlobalObject()) {
      return true;
    }
  }

  return false;
}


static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
                                                   Object* receiver,
                                                   Object* name) {
  InlineCacheHolderFlag cache_holder =
      Code::ExtractCacheHolderFromFlags(target->flags());

  if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
    // The stub was generated for JSObject but called for non-JSObject.
    // IC::GetCodeCacheHolder is not applicable.
    return false;
  } else if (cache_holder == PROTOTYPE_MAP &&
             receiver->GetPrototype()->IsNull()) {
    // IC::GetCodeCacheHolder is not applicable.
    return false;
  }
  Map* map = IC::GetCodeCacheHolder(receiver, cache_holder)->map();

  // Decide whether the inline cache failed because of changes to the
  // receiver itself or changes to one of its prototypes.
  //
  // If there are changes to the receiver itself, the map of the
  // receiver will have changed and the current target will not be in
  // the receiver map's code cache.  Therefore, if the current target
  // is in the receiver map's code cache, the inline cache failed due
  // to prototype check failure.
  int index = map->IndexInCodeCache(name, target);
  if (index >= 0) {
    map->RemoveFromCodeCache(String::cast(name), target, index);
    return true;
  }

  return false;
}


IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
  IC::State state = target->ic_state();

  if (state != MONOMORPHIC || !name->IsString()) return state;
  if (receiver->IsUndefined() || receiver->IsNull()) return state;

  // For keyed load/store/call, the most likely cause of cache failure is
  // that the key has changed.  We do not distinguish between
  // prototype and non-prototype failures for keyed access.
  Code::Kind kind = target->kind();
  if (kind == Code::KEYED_LOAD_IC ||
      kind == Code::KEYED_STORE_IC ||
      kind == Code::KEYED_CALL_IC) {
    return MONOMORPHIC;
  }

  // Remove the target from the code cache if it became invalid
  // because of changes in the prototype chain to avoid hitting it
  // again.
  // Call stubs handle this later to allow extra IC state
  // transitions.
  if (kind != Code::CALL_IC &&
      TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
    return MONOMORPHIC_PROTOTYPE_FAILURE;
  }

  // The builtins object is special.  It only changes when JavaScript
  // builtins are loaded lazily.  It is important to keep inline
  // caches for the builtins object monomorphic.  Therefore, if we get
  // an inline cache miss for the builtins object after lazily loading
  // JavaScript builtins, we return uninitialized as the state to
  // force the inline cache back to monomorphic state.
  if (receiver->IsJSBuiltinsObject()) {
    return UNINITIALIZED;
  }

  return MONOMORPHIC;
}


RelocInfo::Mode IC::ComputeMode() {
  Address addr = address();
  Code* code = Code::cast(isolate()->heap()->FindCodeObject(addr));
  for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
       !it.done(); it.next()) {
    RelocInfo* info = it.rinfo();
    if (info->pc() == addr) return info->rmode();
  }
  UNREACHABLE();
  return RelocInfo::NONE;
}


Failure* IC::TypeError(const char* type,
                       Handle<Object> object,
                       Handle<Object> key) {
  HandleScope scope(isolate());
  Handle<Object> args[2] = { key, object };
  Handle<Object> error = isolate()->factory()->NewTypeError(
      type, HandleVector(args, 2));
  return isolate()->Throw(*error);
}


Failure* IC::ReferenceError(const char* type, Handle<String> name) {
  HandleScope scope(isolate());
  Handle<Object> error = isolate()->factory()->NewReferenceError(
      type, HandleVector(&name, 1));
  return isolate()->Throw(*error);
}


void IC::Clear(Address address) {
  Code* target = GetTargetAtAddress(address);

  // Don't clear debug break inline cache as it will remove the break point.
  if (target->ic_state() == DEBUG_BREAK) return;

  switch (target->kind()) {
    case Code::LOAD_IC: return LoadIC::Clear(address, target);
    case Code::KEYED_LOAD_IC:
      return KeyedLoadIC::Clear(address, target);
    case Code::STORE_IC: return StoreIC::Clear(address, target);
    case Code::KEYED_STORE_IC:
      return KeyedStoreIC::Clear(address, target);
    case Code::CALL_IC: return CallIC::Clear(address, target);
    case Code::KEYED_CALL_IC:  return KeyedCallIC::Clear(address, target);
    case Code::UNARY_OP_IC:
    case Code::BINARY_OP_IC:
    case Code::COMPARE_IC:
      // Clearing these is tricky and does not
      // make any performance difference.
      return;
    default: UNREACHABLE();
  }
}


void CallICBase::Clear(Address address, Code* target) {
  bool contextual = CallICBase::Contextual::decode(target->extra_ic_state());
  State state = target->ic_state();
  if (state == UNINITIALIZED) return;
  Code* code =
      Isolate::Current()->stub_cache()->FindCallInitialize(
          target->arguments_count(),
          target->ic_in_loop(),
          contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET,
          target->kind());
  SetTargetAtAddress(address, code);
}


void KeyedLoadIC::Clear(Address address, Code* target) {
  if (target->ic_state() == UNINITIALIZED) return;
  // Make sure to also clear the map used in inline fast cases.  If we
  // do not clear these maps, cached code can keep objects alive
  // through the embedded maps.
  SetTargetAtAddress(address, initialize_stub());
}


void LoadIC::Clear(Address address, Code* target) {
  if (target->ic_state() == UNINITIALIZED) return;
  SetTargetAtAddress(address, initialize_stub());
}


void StoreIC::Clear(Address address, Code* target) {
  if (target->ic_state() == UNINITIALIZED) return;
  SetTargetAtAddress(address,
      (target->extra_ic_state() == kStrictMode)
        ? initialize_stub_strict()
        : initialize_stub());
}


void KeyedStoreIC::Clear(Address address, Code* target) {
  if (target->ic_state() == UNINITIALIZED) return;
  SetTargetAtAddress(address,
      (target->extra_ic_state() == kStrictMode)
        ? initialize_stub_strict()
        : initialize_stub());
}


static bool HasInterceptorGetter(JSObject* object) {
  return !object->GetNamedInterceptor()->getter()->IsUndefined();
}


static void LookupForRead(Object* object,
                          String* name,
                          LookupResult* lookup) {
  AssertNoAllocation no_gc;  // pointers must stay valid

  // Skip all the objects with named interceptors, but
  // without actual getter.
  while (true) {
    object->Lookup(name, lookup);
    // Besides normal conditions (property not found or it's not
    // an interceptor), bail out if lookup is not cacheable: we won't
    // be able to IC it anyway and regular lookup should work fine.
    if (!lookup->IsFound()
        || (lookup->type() != INTERCEPTOR)
        || !lookup->IsCacheable()) {
      return;
    }

    JSObject* holder = lookup->holder();
    if (HasInterceptorGetter(holder)) {
      return;
    }

    holder->LocalLookupRealNamedProperty(name, lookup);
    if (lookup->IsProperty()) {
      ASSERT(lookup->type() != INTERCEPTOR);
      return;
    }

    Object* proto = holder->GetPrototype();
    if (proto->IsNull()) {
      lookup->NotFound();
      return;
    }

    object = proto;
  }
}


Object* CallICBase::TryCallAsFunction(Object* object) {
  HandleScope scope(isolate());
  Handle<Object> target(object, isolate());
  Handle<Object> delegate = Execution::GetFunctionDelegate(target);

  if (delegate->IsJSFunction()) {
    // Patch the receiver and use the delegate as the function to
    // invoke. This is used for invoking objects as if they were
    // functions.
    const int argc = this->target()->arguments_count();
    StackFrameLocator locator;
    JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
    int index = frame->ComputeExpressionsCount() - (argc + 1);
    frame->SetExpression(index, *target);
  }

  return *delegate;
}


void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee,
                                            Handle<Object> object) {
  if (callee->IsJSFunction()) {
    Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
    if (function->shared()->strict_mode() || function->IsBuiltin()) {
      // Do not wrap receiver for strict mode functions or for builtins.
      return;
    }
  }

  // And only wrap string, number or boolean.
  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
    // Change the receiver to the result of calling ToObject on it.
    const int argc = this->target()->arguments_count();
    StackFrameLocator locator;
    JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
    int index = frame->ComputeExpressionsCount() - (argc + 1);
    frame->SetExpression(index, *isolate()->factory()->ToObject(object));
  }
}


MaybeObject* CallICBase::LoadFunction(State state,
                                      Code::ExtraICState extra_ic_state,
                                      Handle<Object> object,
                                      Handle<String> name) {
  // If the object is undefined or null it's illegal to try to get any
  // of its properties; throw a TypeError in that case.
  if (object->IsUndefined() || object->IsNull()) {
    return TypeError("non_object_property_call", object, name);
  }

  // Check if the name is trivially convertible to an index and get
  // the element if so.
  uint32_t index;
  if (name->AsArrayIndex(&index)) {
    Object* result;
    { MaybeObject* maybe_result = object->GetElement(index);
      if (!maybe_result->ToObject(&result)) return maybe_result;
    }

    if (result->IsJSFunction()) return result;

    // Try to find a suitable function delegate for the object at hand.
    result = TryCallAsFunction(result);
    if (result->IsJSFunction()) return result;

    // Otherwise, it will fail in the lookup step.
  }

  // Lookup the property in the object.
  LookupResult lookup;
  LookupForRead(*object, *name, &lookup);

  if (!lookup.IsProperty()) {
    // If the object does not have the requested property, check which
    // exception we need to throw.
    if (IsContextual(object)) {
      return ReferenceError("not_defined", name);
    }
    return TypeError("undefined_method", object, name);
  }

  // Lookup is valid: Update inline cache and stub cache.
  if (FLAG_use_ic) {
    UpdateCaches(&lookup, state, extra_ic_state, object, name);
  }

  // Get the property.
  PropertyAttributes attr;
  Object* result;
  { MaybeObject* maybe_result =
        object->GetProperty(*object, &lookup, *name, &attr);
    if (!maybe_result->ToObject(&result)) return maybe_result;
  }

  if (lookup.type() == INTERCEPTOR) {
    // If the object does not have the requested property, check which
    // exception we need to throw.
    if (attr == ABSENT) {
      if (IsContextual(object)) {
        return ReferenceError("not_defined", name);
      }
      return TypeError("undefined_method", object, name);
    }
  }

  ASSERT(!result->IsTheHole());

  HandleScope scope(isolate());
  // Wrap result in a handle because ReceiverToObjectIfRequired may allocate
  // new object and cause GC.
  Handle<Object> result_handle(result);
  // Make receiver an object if the callee requires it. Strict mode or builtin
  // functions do not wrap the receiver, non-strict functions and objects
  // called as functions do.
  ReceiverToObjectIfRequired(result_handle, object);

  if (result_handle->IsJSFunction()) {
#ifdef ENABLE_DEBUGGER_SUPPORT
    // Handle stepping into a function if step into is active.
    Debug* debug = isolate()->debug();
    if (debug->StepInActive()) {
      // Protect the result in a handle as the debugger can allocate and might
      // cause GC.
      Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate());
      debug->HandleStepIn(function, object, fp(), false);
      return *function;
    }
#endif

    return *result_handle;
  }

  // Try to find a suitable function delegate for the object at hand.
  result_handle = Handle<Object>(TryCallAsFunction(*result_handle));
  if (result_handle->IsJSFunction()) return *result_handle;

  return TypeError("property_not_function", object, name);
}


bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
                                       Handle<Object> object,
                                       Code::ExtraICState* extra_ic_state) {
  ASSERT(kind_ == Code::CALL_IC);
  if (lookup->type() != CONSTANT_FUNCTION) return false;
  JSFunction* function = lookup->GetConstantFunction();
  if (!function->shared()->HasBuiltinFunctionId()) return false;

  // Fetch the arguments passed to the called function.
  const int argc = target()->arguments_count();
  Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
  Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
  Arguments args(argc + 1,
                 &Memory::Object_at(fp +
                                    StandardFrameConstants::kCallerSPOffset +
                                    argc * kPointerSize));
  switch (function->shared()->builtin_function_id()) {
    case kStringCharCodeAt:
    case kStringCharAt:
      if (object->IsString()) {
        String* string = String::cast(*object);
        // Check there's the right string value or wrapper in the receiver slot.
        ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
        // If we're in the default (fastest) state and the index is
        // out of bounds, update the state to record this fact.
        if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB &&
            argc >= 1 && args[1]->IsNumber()) {
          double index;
          if (args[1]->IsSmi()) {
            index = Smi::cast(args[1])->value();
          } else {
            ASSERT(args[1]->IsHeapNumber());
            index = DoubleToInteger(HeapNumber::cast(args[1])->value());
          }
          if (index < 0 || index >= string->length()) {
            *extra_ic_state =
                StringStubState::update(*extra_ic_state,
                                        STRING_INDEX_OUT_OF_BOUNDS);
            return true;
          }
        }
      }
      break;
    default:
      return false;
  }
  return false;
}


MaybeObject* CallICBase::ComputeMonomorphicStub(
    LookupResult* lookup,
    State state,
    Code::ExtraICState extra_ic_state,
    Handle<Object> object,
    Handle<String> name) {
  int argc = target()->arguments_count();
  InLoopFlag in_loop = target()->ic_in_loop();
  MaybeObject* maybe_code = NULL;
  switch (lookup->type()) {
    case FIELD: {
      int index = lookup->GetFieldIndex();
      maybe_code = isolate()->stub_cache()->ComputeCallField(argc,
                                                             in_loop,
                                                             kind_,
                                                             extra_ic_state,
                                                             *name,
                                                             *object,
                                                             lookup->holder(),
                                                             index);
      break;
    }
    case CONSTANT_FUNCTION: {
      // Get the constant function and compute the code stub for this
      // call; used for rewriting to monomorphic state and making sure
      // that the code stub is in the stub cache.
      JSFunction* function = lookup->GetConstantFunction();
      maybe_code =
          isolate()->stub_cache()->ComputeCallConstant(argc,
                                                       in_loop,
                                                       kind_,
                                                       extra_ic_state,
                                                       *name,
                                                       *object,
                                                       lookup->holder(),
                                                       function);
      break;
    }
    case NORMAL: {
      if (!object->IsJSObject()) return NULL;
      Handle<JSObject> receiver = Handle<JSObject>::cast(object);

      if (lookup->holder()->IsGlobalObject()) {
        GlobalObject* global = GlobalObject::cast(lookup->holder());
        JSGlobalPropertyCell* cell =
            JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
        if (!cell->value()->IsJSFunction()) return NULL;
        JSFunction* function = JSFunction::cast(cell->value());
        maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc,
                                                                in_loop,
                                                                kind_,
                                                                extra_ic_state,
                                                                *name,
                                                                *receiver,
                                                                global,
                                                                cell,
                                                                function);
      } else {
        // There is only one shared stub for calling normalized
        // properties. It does not traverse the prototype chain, so the
        // property must be found in the receiver for the stub to be
        // applicable.
        if (lookup->holder() != *receiver) return NULL;
        maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc,
                                                                in_loop,
                                                                kind_,
                                                                extra_ic_state,
                                                                *name,
                                                                *receiver);
      }
      break;
    }
    case INTERCEPTOR: {
      ASSERT(HasInterceptorGetter(lookup->holder()));
      maybe_code = isolate()->stub_cache()->ComputeCallInterceptor(
          argc,
          kind_,
          extra_ic_state,
          *name,
          *object,
          lookup->holder());
      break;
    }
    default:
      maybe_code = NULL;
      break;
  }
  return maybe_code;
}


void CallICBase::UpdateCaches(LookupResult* lookup,
                              State state,
                              Code::ExtraICState extra_ic_state,
                              Handle<Object> object,
                              Handle<String> name) {
  // Bail out if we didn't find a result.
  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;

  if (lookup->holder() != *object &&
      HasNormalObjectsInPrototypeChain(
          isolate(), lookup, object->GetPrototype())) {
    // Suppress optimization for prototype chains with slow properties objects
    // in the middle.
    return;
  }

  // Compute the number of arguments.
  int argc = target()->arguments_count();
  InLoopFlag in_loop = target()->ic_in_loop();
  MaybeObject* maybe_code = NULL;
  bool had_proto_failure = false;
  if (state == UNINITIALIZED) {
    // This is the first time we execute this inline cache.
    // Set the target to the pre monomorphic stub to delay
    // setting the monomorphic state.
    maybe_code =
        isolate()->stub_cache()->ComputeCallPreMonomorphic(argc,
                                                           in_loop,
                                                           kind_,
                                                           extra_ic_state);
  } else if (state == MONOMORPHIC) {
    if (kind_ == Code::CALL_IC &&
        TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
      maybe_code = ComputeMonomorphicStub(lookup,
                                          state,
                                          extra_ic_state,
                                          object,
                                          name);
    } else if (kind_ == Code::CALL_IC &&
               TryRemoveInvalidPrototypeDependentStub(target(),
                                                      *object,
                                                      *name)) {
      had_proto_failure = true;
      maybe_code = ComputeMonomorphicStub(lookup,
                                          state,
                                          extra_ic_state,
                                          object,
                                          name);
    } else {
      maybe_code =
          isolate()->stub_cache()->ComputeCallMegamorphic(argc,
                                                          in_loop,
                                                          kind_,
                                                          extra_ic_state);
    }
  } else {
    maybe_code = ComputeMonomorphicStub(lookup,
                                        state,
                                        extra_ic_state,
                                        object,
                                        name);
  }

  // If we're unable to compute the stub (not enough memory left), we
  // simply avoid updating the caches.
  Object* code;
  if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;

  // Patch the call site depending on the state of the cache.
  if (state == UNINITIALIZED ||
      state == PREMONOMORPHIC ||
      state == MONOMORPHIC ||
      state == MONOMORPHIC_PROTOTYPE_FAILURE) {
    set_target(Code::cast(code));
  } else if (state == MEGAMORPHIC) {
    // Cache code holding map should be consistent with
    // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
    Map* map = JSObject::cast(object->IsJSObject() ? *object :
                              object->GetPrototype())->map();

    // Update the stub cache.
    isolate()->stub_cache()->Set(*name, map, Code::cast(code));
  }

  USE(had_proto_failure);
#ifdef DEBUG
  if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
  TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
      name, state, target(), in_loop ? " (in-loop)" : "");
#endif
}


MaybeObject* KeyedCallIC::LoadFunction(State state,
                                       Handle<Object> object,
                                       Handle<Object> key) {
  if (key->IsSymbol()) {
    return CallICBase::LoadFunction(state,
                                    Code::kNoExtraICState,
                                    object,
                                    Handle<String>::cast(key));
  }

  if (object->IsUndefined() || object->IsNull()) {
    return TypeError("non_object_property_call", object, key);
  }

  if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
    int argc = target()->arguments_count();
    InLoopFlag in_loop = target()->ic_in_loop();
    MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(
        argc, in_loop, Code::KEYED_CALL_IC, Code::kNoExtraICState);
    Object* code;
    if (maybe_code->ToObject(&code)) {
      set_target(Code::cast(code));
#ifdef DEBUG
      TraceIC(
          "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : "");
#endif
    }
  }

  HandleScope scope(isolate());
  Handle<Object> result = GetProperty(object, key);
  RETURN_IF_EMPTY_HANDLE(isolate(), result);

  // Make receiver an object if the callee requires it. Strict mode or builtin
  // functions do not wrap the receiver, non-strict functions and objects
  // called as functions do.
  ReceiverToObjectIfRequired(result, object);

  if (result->IsJSFunction()) return *result;
  result = Handle<Object>(TryCallAsFunction(*result));
  if (result->IsJSFunction()) return *result;

  return TypeError("property_not_function", object, key);
}


#ifdef DEBUG
#define TRACE_IC_NAMED(msg, name) \
  if (FLAG_trace_ic) PrintF(msg, *(name)->ToCString())
#else
#define TRACE_IC_NAMED(msg, name)
#endif


MaybeObject* LoadIC::Load(State state,
                          Handle<Object> object,
                          Handle<String> name) {
  // If the object is undefined or null it's illegal to try to get any
  // of its properties; throw a TypeError in that case.
  if (object->IsUndefined() || object->IsNull()) {
    return TypeError("non_object_property_load", object, name);
  }

  if (FLAG_use_ic) {
    Code* non_monomorphic_stub =
        (state == UNINITIALIZED) ? pre_monomorphic_stub() : megamorphic_stub();

    // Use specialized code for getting the length of strings and
    // string wrapper objects.  The length property of string wrapper
    // objects is read-only and therefore always returns the length of
    // the underlying string value.  See ECMA-262 15.5.5.1.
    if ((object->IsString() || object->IsStringWrapper()) &&
        name->Equals(isolate()->heap()->length_symbol())) {
      HandleScope scope(isolate());
#ifdef DEBUG
      if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
#endif
      if (state == PREMONOMORPHIC) {
        if (object->IsString()) {
          set_target(isolate()->builtins()->builtin(
              Builtins::kLoadIC_StringLength));
        } else {
          set_target(isolate()->builtins()->builtin(
              Builtins::kLoadIC_StringWrapperLength));
        }
      } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
        set_target(isolate()->builtins()->builtin(
            Builtins::kLoadIC_StringWrapperLength));
      } else {
        set_target(non_monomorphic_stub);
      }
      // Get the string if we have a string wrapper object.
      if (object->IsJSValue()) {
        object = Handle<Object>(Handle<JSValue>::cast(object)->value(),
                                isolate());
      }
      return Smi::FromInt(String::cast(*object)->length());
    }

    // Use specialized code for getting the length of arrays.
    if (object->IsJSArray() &&
        name->Equals(isolate()->heap()->length_symbol())) {
#ifdef DEBUG
      if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
#endif
      if (state == PREMONOMORPHIC) {
        set_target(isolate()->builtins()->builtin(
            Builtins::kLoadIC_ArrayLength));
      } else {
        set_target(non_monomorphic_stub);
      }
      return JSArray::cast(*object)->length();
    }

    // Use specialized code for getting prototype of functions.
    if (object->IsJSFunction() &&
        name->Equals(isolate()->heap()->prototype_symbol()) &&
        JSFunction::cast(*object)->should_have_prototype()) {
#ifdef DEBUG
      if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
#endif
      if (state == PREMONOMORPHIC) {
        set_target(isolate()->builtins()->builtin(
            Builtins::kLoadIC_FunctionPrototype));
      } else {
        set_target(non_monomorphic_stub);
      }
      return Accessors::FunctionGetPrototype(*object, 0);
    }
  }

  // Check if the name is trivially convertible to an index and get
  // the element if so.
  uint32_t index;
  if (name->AsArrayIndex(&index)) return object->GetElement(index);

  // Named lookup in the object.
  LookupResult lookup;
  LookupForRead(*object, *name, &lookup);

  // If we did not find a property, check if we need to throw an exception.
  if (!lookup.IsProperty()) {
    if (FLAG_strict || IsContextual(object)) {
      return ReferenceError("not_defined", name);
    }
    LOG(isolate(), SuspectReadEvent(*name, *object));
  }

  // Update inline cache and stub cache.
  if (FLAG_use_ic) {
    UpdateCaches(&lookup, state, object, name);
  }

  PropertyAttributes attr;
  if (lookup.IsProperty() &&
      (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
    // Get the property.
    Object* result;
    { MaybeObject* maybe_result =
          object->GetProperty(*object, &lookup, *name, &attr);
      if (!maybe_result->ToObject(&result)) return maybe_result;
    }
    // If the property is not present, check if we need to throw an
    // exception.
    if (attr == ABSENT && IsContextual(object)) {
      return ReferenceError("not_defined", name);
    }
    return result;
  }

  // Get the property.
  return object->GetProperty(*object, &lookup, *name, &attr);
}


void LoadIC::UpdateCaches(LookupResult* lookup,
                          State state,
                          Handle<Object> object,
                          Handle<String> name) {
  // Bail out if the result is not cacheable.
  if (!lookup->IsCacheable()) return;

  // Loading properties from values is not common, so don't try to
  // deal with non-JS objects here.
  if (!object->IsJSObject()) return;
  Handle<JSObject> receiver = Handle<JSObject>::cast(object);

  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;

  // Compute the code stub for this load.
  MaybeObject* maybe_code = NULL;
  Object* code;
  if (state == UNINITIALIZED) {
    // This is the first time we execute this inline cache.
    // Set the target to the pre monomorphic stub to delay
    // setting the monomorphic state.
    maybe_code = pre_monomorphic_stub();
  } else if (!lookup->IsProperty()) {
    // Nonexistent property. The result is undefined.
    maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name,
                                                                 *receiver);
  } else {
    // Compute monomorphic stub.
    switch (lookup->type()) {
      case FIELD: {
        maybe_code = isolate()->stub_cache()->ComputeLoadField(
            *name,
            *receiver,
            lookup->holder(),
            lookup->GetFieldIndex());
        break;
      }
      case CONSTANT_FUNCTION: {
        Object* constant = lookup->GetConstantFunction();
        maybe_code = isolate()->stub_cache()->ComputeLoadConstant(
            *name, *receiver, lookup->holder(), constant);
        break;
      }
      case NORMAL: {
        if (lookup->holder()->IsGlobalObject()) {
          GlobalObject* global = GlobalObject::cast(lookup->holder());
          JSGlobalPropertyCell* cell =
              JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
          maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name,
                                                    *receiver,
                                                    global,
                                                    cell,
                                                    lookup->IsDontDelete());
        } else {
          // There is only one shared stub for loading normalized
          // properties. It does not traverse the prototype chain, so the
          // property must be found in the receiver for the stub to be
          // applicable.
          if (lookup->holder() != *receiver) return;
          maybe_code = isolate()->stub_cache()->ComputeLoadNormal();
        }
        break;
      }
      case CALLBACKS: {
        if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
        AccessorInfo* callback =
            AccessorInfo::cast(lookup->GetCallbackObject());
        if (v8::ToCData<Address>(callback->getter()) == 0) return;
        maybe_code = isolate()->stub_cache()->ComputeLoadCallback(
            *name, *receiver, lookup->holder(), callback);
        break;
      }
      case INTERCEPTOR: {
        ASSERT(HasInterceptorGetter(lookup->holder()));
        maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor(
            *name, *receiver, lookup->holder());
        break;
      }
      default:
        return;
    }
  }

  // If we're unable to compute the stub (not enough memory left), we
  // simply avoid updating the caches.
  if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;

  // Patch the call site depending on the state of the cache.
  if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
      state == MONOMORPHIC_PROTOTYPE_FAILURE) {
    set_target(Code::cast(code));
  } else if (state == MONOMORPHIC) {
    set_target(megamorphic_stub());
  } else if (state == MEGAMORPHIC) {
    // Cache code holding map should be consistent with
    // GenerateMonomorphicCacheProbe.
    Map* map = JSObject::cast(object->IsJSObject() ? *object :
                              object->GetPrototype())->map();

    isolate()->stub_cache()->Set(*name, map, Code::cast(code));
  }

#ifdef DEBUG
  TraceIC("LoadIC", name, state, target());
#endif
}


String* KeyedLoadIC::GetStubNameForCache(IC::State ic_state) {
  if (ic_state == MONOMORPHIC) {
    return isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol();
  } else {
    ASSERT(ic_state == MEGAMORPHIC);
    return isolate()->heap()->KeyedLoadSpecializedPolymorphic_symbol();
  }
}


MaybeObject* KeyedLoadIC::GetFastElementStubWithoutMapCheck(
    bool is_js_array) {
  return KeyedLoadFastElementStub().TryGetCode();
}


MaybeObject* KeyedLoadIC::GetExternalArrayStubWithoutMapCheck(
    ExternalArrayType array_type) {
  return KeyedLoadExternalArrayStub(array_type).TryGetCode();
}


MaybeObject* KeyedLoadIC::ConstructMegamorphicStub(
    MapList* receiver_maps,
    CodeList* targets,
    StrictModeFlag strict_mode) {
  Object* object;
  KeyedLoadStubCompiler compiler;
  MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps,
                                                            targets);
  if (!maybe_code->ToObject(&object)) return maybe_code;
  isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
  PROFILE(isolate(), CodeCreateEvent(
      Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG,
      Code::cast(object), 0));
  return object;
}


MaybeObject* KeyedLoadIC::Load(State state,
                               Handle<Object> object,
                               Handle<Object> key,
                               bool force_generic_stub) {
  // Check for values that can be converted into a symbol.
  // TODO(1295): Remove this code.
  HandleScope scope(isolate());
  if (key->IsHeapNumber() &&
      isnan(HeapNumber::cast(*key)->value())) {
    key = isolate()->factory()->nan_symbol();
  } else if (key->IsUndefined()) {
    key = isolate()->factory()->undefined_symbol();
  }

  if (key->IsSymbol()) {
    Handle<String> name = Handle<String>::cast(key);

    // If the object is undefined or null it's illegal to try to get any
    // of its properties; throw a TypeError in that case.
    if (object->IsUndefined() || object->IsNull()) {
      return TypeError("non_object_property_load", object, name);
    }

    if (FLAG_use_ic) {
      // TODO(1073): don't ignore the current stub state.

      // Use specialized code for getting the length of strings.
      if (object->IsString() &&
          name->Equals(isolate()->heap()->length_symbol())) {
        Handle<String> string = Handle<String>::cast(object);
        Object* code = NULL;
        { MaybeObject* maybe_code =
              isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name,
                                                                    *string);
          if (!maybe_code->ToObject(&code)) return maybe_code;
        }
        set_target(Code::cast(code));
#ifdef DEBUG
        TraceIC("KeyedLoadIC", name, state, target());
#endif  // DEBUG
        return Smi::FromInt(string->length());
      }

      // Use specialized code for getting the length of arrays.
      if (object->IsJSArray() &&
          name->Equals(isolate()->heap()->length_symbol())) {
        Handle<JSArray> array = Handle<JSArray>::cast(object);
        Object* code;
        { MaybeObject* maybe_code =
              isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name,
                                                                   *array);
          if (!maybe_code->ToObject(&code)) return maybe_code;
        }
        set_target(Code::cast(code));
#ifdef DEBUG
        TraceIC("KeyedLoadIC", name, state, target());
#endif  // DEBUG
        return JSArray::cast(*object)->length();
      }

      // Use specialized code for getting prototype of functions.
      if (object->IsJSFunction() &&
          name->Equals(isolate()->heap()->prototype_symbol()) &&
        JSFunction::cast(*object)->should_have_prototype()) {
        Handle<JSFunction> function = Handle<JSFunction>::cast(object);
        Object* code;
        { MaybeObject* maybe_code =
              isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
                  *name, *function);
          if (!maybe_code->ToObject(&code)) return maybe_code;
        }
        set_target(Code::cast(code));
#ifdef DEBUG
        TraceIC("KeyedLoadIC", name, state, target());
#endif  // DEBUG
        return Accessors::FunctionGetPrototype(*object, 0);
      }
    }

    // Check if the name is trivially convertible to an index and get
    // the element or char if so.
    uint32_t index = 0;
    if (name->AsArrayIndex(&index)) {
      HandleScope scope(isolate());
      // Rewrite to the generic keyed load stub.
      if (FLAG_use_ic) set_target(generic_stub());
      return Runtime::GetElementOrCharAt(isolate(), object, index);
    }

    // Named lookup.
    LookupResult lookup;
    LookupForRead(*object, *name, &lookup);

    // If we did not find a property, check if we need to throw an exception.
    if (!lookup.IsProperty()) {
      if (FLAG_strict || IsContextual(object)) {
        return ReferenceError("not_defined", name);
      }
    }

    if (FLAG_use_ic) {
      UpdateCaches(&lookup, state, object, name);
    }

    PropertyAttributes attr;
    if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
      // Get the property.
      Object* result;
      { MaybeObject* maybe_result =
            object->GetProperty(*object, &lookup, *name, &attr);
        if (!maybe_result->ToObject(&result)) return maybe_result;
      }
      // If the property is not present, check if we need to throw an
      // exception.
      if (attr == ABSENT && IsContextual(object)) {
        return ReferenceError("not_defined", name);
      }
      return result;
    }

    return object->GetProperty(*object, &lookup, *name, &attr);
  }

  // Do not use ICs for objects that require access checks (including
  // the global object).
  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();

  if (use_ic) {
    Code* stub = generic_stub();
    if (!force_generic_stub) {
      if (object->IsString() && key->IsNumber()) {
        if (state == UNINITIALIZED) {
          stub = string_stub();
        }
      } else if (object->IsJSObject()) {
        JSObject* receiver = JSObject::cast(*object);
        if (receiver->HasIndexedInterceptor()) {
          stub = indexed_interceptor_stub();
        } else if (key->IsSmi()) {
          MaybeObject* maybe_stub = ComputeStub(receiver,
                                                false,
                                                kNonStrictMode,
                                                stub);
          stub = maybe_stub->IsFailure() ?
              NULL : Code::cast(maybe_stub->ToObjectUnchecked());
        }
      }
    }
    if (stub != NULL) set_target(stub);
  }

#ifdef DEBUG
  TraceIC("KeyedLoadIC", key, state, target());
#endif  // DEBUG

  // Get the property.
  return Runtime::GetObjectProperty(isolate(), object, key);
}


void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
                               Handle<Object> object, Handle<String> name) {
  // Bail out if we didn't find a result.
  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;

  if (!object->IsJSObject()) return;
  Handle<JSObject> receiver = Handle<JSObject>::cast(object);

  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;

  // Compute the code stub for this load.
  MaybeObject* maybe_code = NULL;
  Object* code;

  if (state == UNINITIALIZED) {
    // This is the first time we execute this inline cache.
    // Set the target to the pre monomorphic stub to delay
    // setting the monomorphic state.
    maybe_code = pre_monomorphic_stub();
  } else {
    // Compute a monomorphic stub.
    switch (lookup->type()) {
      case FIELD: {
        maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField(
            *name, *receiver, lookup->holder(), lookup->GetFieldIndex());
        break;
      }
      case CONSTANT_FUNCTION: {
        Object* constant = lookup->GetConstantFunction();
        maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
            *name, *receiver, lookup->holder(), constant);
        break;
      }
      case CALLBACKS: {
        if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
        AccessorInfo* callback =
            AccessorInfo::cast(lookup->GetCallbackObject());
        if (v8::ToCData<Address>(callback->getter()) == 0) return;
        maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
            *name, *receiver, lookup->holder(), callback);
        break;
      }
      case INTERCEPTOR: {
        ASSERT(HasInterceptorGetter(lookup->holder()));
        maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
            *name, *receiver, lookup->holder());
        break;
      }
      default: {
        // Always rewrite to the generic case so that we do not
        // repeatedly try to rewrite.
        maybe_code = generic_stub();
        break;
      }
    }
  }

  // If we're unable to compute the stub (not enough memory left), we
  // simply avoid updating the caches.
  if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;

  // Patch the call site depending on the state of the cache.  Make
  // sure to always rewrite from monomorphic to megamorphic.
  ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
    set_target(Code::cast(code));
  } else if (state == MONOMORPHIC) {
    set_target(megamorphic_stub());
  }

#ifdef DEBUG
  TraceIC("KeyedLoadIC", name, state, target());
#endif
}


static bool StoreICableLookup(LookupResult* lookup) {
  // Bail out if we didn't find a result.
  if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false;

  // If the property is read-only, we leave the IC in its current
  // state.
  if (lookup->IsReadOnly()) return false;

  return true;
}


static bool LookupForWrite(JSObject* object,
                           String* name,
                           LookupResult* lookup) {
  object->LocalLookup(name, lookup);
  if (!StoreICableLookup(lookup)) {
    return false;
  }

  if (lookup->type() == INTERCEPTOR) {
    if (object->GetNamedInterceptor()->setter()->IsUndefined()) {
      object->LocalLookupRealNamedProperty(name, lookup);
      return StoreICableLookup(lookup);
    }
  }

  return true;
}


MaybeObject* StoreIC::Store(State state,
                            StrictModeFlag strict_mode,
                            Handle<Object> object,
                            Handle<String> name,
                            Handle<Object> value) {
  // If the object is undefined or null it's illegal to try to set any
  // properties on it; throw a TypeError in that case.
  if (object->IsUndefined() || object->IsNull()) {
    return TypeError("non_object_property_store", object, name);
  }

  if (!object->IsJSObject()) {
    // The length property of string values is read-only. Throw in strict mode.
    if (strict_mode == kStrictMode && object->IsString() &&
        name->Equals(isolate()->heap()->length_symbol())) {
      return TypeError("strict_read_only_property", object, name);
    }
    // Ignore stores where the receiver is not a JSObject.
    return *value;
  }

  Handle<JSObject> receiver = Handle<JSObject>::cast(object);

  // Check if the given name is an array index.
  uint32_t index;
  if (name->AsArrayIndex(&index)) {
    HandleScope scope(isolate());
    Handle<Object> result = SetElement(receiver, index, value, strict_mode);
    if (result.is_null()) return Failure::Exception();
    return *value;
  }

  // Use specialized code for setting the length of arrays.
  if (receiver->IsJSArray()
      && name->Equals(isolate()->heap()->length_symbol())
      && receiver->AllowsSetElementsLength()) {
#ifdef DEBUG
    if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
#endif
    Builtins::Name target = (strict_mode == kStrictMode)
        ? Builtins::kStoreIC_ArrayLength_Strict
        : Builtins::kStoreIC_ArrayLength;
    set_target(isolate()->builtins()->builtin(target));
    return receiver->SetProperty(*name, *value, NONE, strict_mode);
  }

  // Lookup the property locally in the receiver.
  if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
    LookupResult lookup;

    if (LookupForWrite(*receiver, *name, &lookup)) {
      // Generate a stub for this store.
      UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
    } else {
      // Strict mode doesn't allow setting non-existent global property
      // or an assignment to a read only property.
      if (strict_mode == kStrictMode) {
        if (lookup.IsFound() && lookup.IsReadOnly()) {
          return TypeError("strict_read_only_property", object, name);
        } else if (IsContextual(object)) {
          return ReferenceError("not_defined", name);
        }
      }
    }
  }

  if (receiver->IsJSGlobalProxy()) {
    // Generate a generic stub that goes to the runtime when we see a global
    // proxy as receiver.
    Code* stub = (strict_mode == kStrictMode)
        ? global_proxy_stub_strict()
        : global_proxy_stub();
    if (target() != stub) {
      set_target(stub);
#ifdef DEBUG
      TraceIC("StoreIC", name, state, target());
#endif
    }
  }

  // Set the property.
  return receiver->SetProperty(*name, *value, NONE, strict_mode);
}


void StoreIC::UpdateCaches(LookupResult* lookup,
                           State state,
                           StrictModeFlag strict_mode,
                           Handle<JSObject> receiver,
                           Handle<String> name,
                           Handle<Object> value) {
  // Skip JSGlobalProxy.
  ASSERT(!receiver->IsJSGlobalProxy());

  ASSERT(StoreICableLookup(lookup));

  // If the property has a non-field type allowing map transitions
  // where there is extra room in the object, we leave the IC in its
  // current state.
  PropertyType type = lookup->type();

  // Compute the code stub for this store; used for rewriting to
  // monomorphic state and making sure that the code stub is in the
  // stub cache.
  MaybeObject* maybe_code = NULL;
  Object* code = NULL;
  switch (type) {
    case FIELD: {
      maybe_code = isolate()->stub_cache()->ComputeStoreField(
          *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
      break;
    }
    case MAP_TRANSITION: {
      if (lookup->GetAttributes() != NONE) return;
      HandleScope scope(isolate());
      ASSERT(type == MAP_TRANSITION);
      Handle<Map> transition(lookup->GetTransitionMap());
      int index = transition->PropertyIndexFor(*name);
      maybe_code = isolate()->stub_cache()->ComputeStoreField(
          *name, *receiver, index, *transition, strict_mode);
      break;
    }
    case NORMAL: {
      if (receiver->IsGlobalObject()) {
        // The stub generated for the global object picks the value directly
        // from the property cell. So the property must be directly on the
        // global object.
        Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
        JSGlobalPropertyCell* cell =
            JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
        maybe_code = isolate()->stub_cache()->ComputeStoreGlobal(
            *name, *global, cell, strict_mode);
      } else {
        if (lookup->holder() != *receiver) return;
        maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
      }
      break;
    }
    case CALLBACKS: {
      if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
      AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
      if (v8::ToCData<Address>(callback->setter()) == 0) return;
      maybe_code = isolate()->stub_cache()->ComputeStoreCallback(
          *name, *receiver, callback, strict_mode);
      break;
    }
    case INTERCEPTOR: {
      ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
      maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor(
          *name, *receiver, strict_mode);
      break;
    }
    default:
      return;
  }

  // If we're unable to compute the stub (not enough memory left), we
  // simply avoid updating the caches.
  if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;

  // Patch the call site depending on the state of the cache.
  if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
    set_target(Code::cast(code));
  } else if (state == MONOMORPHIC) {
    // Only move to megamorphic if the target changes.
    if (target() != Code::cast(code)) {
      set_target((strict_mode == kStrictMode)
                   ? megamorphic_stub_strict()
                   : megamorphic_stub());
    }
  } else if (state == MEGAMORPHIC) {
    // Update the stub cache.
    isolate()->stub_cache()->Set(*name,
                                 receiver->map(),
                                 Code::cast(code));
  }

#ifdef DEBUG
  TraceIC("StoreIC", name, state, target());
#endif
}


static bool AddOneReceiverMapIfMissing(MapList* receiver_maps,
                                       Map* new_receiver_map) {
  for (int current = 0; current < receiver_maps->length(); ++current) {
    if (receiver_maps->at(current) == new_receiver_map) {
      return false;
    }
  }
  receiver_maps->Add(new_receiver_map);
  return true;
}


void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) {
  ASSERT(stub->is_inline_cache_stub());
  if (stub == string_stub()) {
    return result->Add(isolate()->heap()->string_map());
  } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
    if (stub->ic_state() == MONOMORPHIC) {
      result->Add(Map::cast(stub->FindFirstMap()));
    } else {
      ASSERT(stub->ic_state() == MEGAMORPHIC);
      AssertNoAllocation no_allocation;
      int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
      for (RelocIterator it(stub, mask); !it.done(); it.next()) {
        RelocInfo* info = it.rinfo();
        Object* object = info->target_object();
        ASSERT(object->IsMap());
        result->Add(Map::cast(object));
      }
    }
  }
}


MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
                                  bool is_store,
                                  StrictModeFlag strict_mode,
                                  Code* generic_stub) {
  State ic_state = target()->ic_state();
  Code* monomorphic_stub;
  // Always compute the MONOMORPHIC stub, even if the MEGAMORPHIC stub ends up
  // being used. This is necessary because the megamorphic stub needs to have
  // access to more information than what is stored in the receiver map in some
  // cases (external arrays need the array type from the MONOMORPHIC stub).
  MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver,
                                                   is_store,
                                                   strict_mode,
                                                   generic_stub);
  if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;

  if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
    return monomorphic_stub;
  }
  ASSERT(target() != generic_stub);

  // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
  // via megamorphic stubs, since they don't have a map in their relocation info
  // and so the stubs can't be harvested for the object needed for a map check.
  if (target()->type() != NORMAL) {
    return generic_stub;
  }

  // Determine the list of receiver maps that this call site has seen,
  // adding the map that was just encountered.
  MapList target_receiver_maps;
  GetReceiverMapsForStub(target(), &target_receiver_maps);
  if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map())) {
    // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub
    // won't help, use the generic stub.
    return generic_stub;
  }

  // TODO(1385): Currently MEGAMORPHIC stubs are cached in the receiver map stub
  // cache, but that can put receiver types together from unrelated call sites
  // into the same stub--they always handle the union of all receiver maps seen
  // at all call sites involving the receiver map. This is only an
  // approximation: ideally, there would be a global cache that mapped sets of
  // receiver maps to MEGAMORPHIC stubs. The complexity of the MEGAMORPHIC stub
  // computation also leads to direct manipulation of the stub cache from the IC
  // code, which the global cache solution would avoid.
  Code::Kind kind = this->kind();
  Code::Flags flags = Code::ComputeFlags(kind,
                                         NOT_IN_LOOP,
                                         MEGAMORPHIC,
                                         strict_mode);
  String* megamorphic_name = GetStubNameForCache(MEGAMORPHIC);
  Object* maybe_cached_stub = receiver->map()->FindInCodeCache(megamorphic_name,
                                                               flags);

  // Create a set of all receiver maps that have been seen at the IC call site
  // and those seen by the MEGAMORPHIC cached stub, if that's the stub that's
  // been selected.
  MapList receiver_maps;
  if (!maybe_cached_stub->IsUndefined()) {
    GetReceiverMapsForStub(Code::cast(maybe_cached_stub), &receiver_maps);
  }
  bool added_map = false;
  for (int i = 0; i < target_receiver_maps.length(); ++i) {
    if (AddOneReceiverMapIfMissing(&receiver_maps,
                                   target_receiver_maps.at(i))) {
      added_map = true;
    }
  }
  ASSERT(receiver_maps.length() > 0);

  // If the maximum number of receiver maps has been exceeded, use the Generic
  // version of the IC.
  if (receiver_maps.length() > KeyedIC::kMaxKeyedPolymorphism) {
    return generic_stub;
  }

  // If no maps have been seen at the call site that aren't in the cached
  // stub, then use it.
  if (!added_map) {
    ASSERT(!maybe_cached_stub->IsUndefined());
    ASSERT(maybe_cached_stub->IsCode());
    return Code::cast(maybe_cached_stub);
  }

  // Lookup all of the receiver maps in the cache, they should all already
  // have MONOMORPHIC stubs.
  CodeList handler_ics(KeyedIC::kMaxKeyedPolymorphism);
  for (int current = 0; current < receiver_maps.length(); ++current) {
    Map* receiver_map(receiver_maps.at(current));
    MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
        receiver_map,
        strict_mode,
        generic_stub);
    Code* cached_stub;
    if (!maybe_cached_stub->To(&cached_stub)) {
      return maybe_cached_stub;
    }
    handler_ics.Add(cached_stub);
  }

  Code* stub;
  // Build the MEGAMORPHIC stub.
  maybe_stub = ConstructMegamorphicStub(&receiver_maps,
                                        &handler_ics,
                                        strict_mode);
  if (!maybe_stub->To(&stub)) return maybe_stub;

  MaybeObject* maybe_update = receiver->UpdateMapCodeCache(
      megamorphic_name,
      stub);
  if (maybe_update->IsFailure()) return maybe_update;
  return stub;
}


MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
    Map* receiver_map,
    StrictModeFlag strict_mode,
    Code* generic_stub) {
  if ((receiver_map->instance_type() & kNotStringTag) == 0) {
    ASSERT(string_stub() != NULL);
    return string_stub();
  } else if (receiver_map->has_external_array_elements()) {
    // Determine the array type from the default MONOMORPHIC already generated
    // stub. There is no other way to determine the type of the external array
    // directly from the receiver type.
    Code::Kind kind = this->kind();
    Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
                                                      NORMAL,
                                                      strict_mode);
    String* monomorphic_name = GetStubNameForCache(MONOMORPHIC);
    Object* maybe_default_stub = receiver_map->FindInCodeCache(monomorphic_name,
                                                               flags);
    if (maybe_default_stub->IsUndefined()) {
      return generic_stub;
    }
    Code* default_stub = Code::cast(maybe_default_stub);
    return GetExternalArrayStubWithoutMapCheck(
        default_stub->external_array_type());
  } else if (receiver_map->has_fast_elements()) {
    bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
    return GetFastElementStubWithoutMapCheck(is_js_array);
  } else {
    return generic_stub;
  }
}


MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
                                             bool is_store,
                                             StrictModeFlag strict_mode,
                                             Code* generic_stub) {
  Code* result = NULL;
  if (receiver->HasExternalArrayElements()) {
    MaybeObject* maybe_stub =
        isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
            receiver, is_store, strict_mode);
    if (!maybe_stub->To(&result)) return maybe_stub;
  } else if (receiver->map()->has_fast_elements()) {
    MaybeObject* maybe_stub =
        isolate()->stub_cache()->ComputeKeyedLoadOrStoreFastElement(
            receiver, is_store, strict_mode);
    if (!maybe_stub->To(&result)) return maybe_stub;
  } else {
    result = generic_stub;
  }
  return result;
}


String* KeyedStoreIC::GetStubNameForCache(IC::State ic_state) {
  if (ic_state == MONOMORPHIC) {
    return isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol();
  } else {
    ASSERT(ic_state == MEGAMORPHIC);
    return isolate()->heap()->KeyedStoreSpecializedPolymorphic_symbol();
  }
}


MaybeObject* KeyedStoreIC::GetFastElementStubWithoutMapCheck(
    bool is_js_array) {
  return KeyedStoreFastElementStub(is_js_array).TryGetCode();
}


MaybeObject* KeyedStoreIC::GetExternalArrayStubWithoutMapCheck(
    ExternalArrayType array_type) {
  return KeyedStoreExternalArrayStub(array_type).TryGetCode();
}


MaybeObject* KeyedStoreIC::ConstructMegamorphicStub(
    MapList* receiver_maps,
    CodeList* targets,
    StrictModeFlag strict_mode) {
  Object* object;
  KeyedStoreStubCompiler compiler(strict_mode);
  MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps,
                                                             targets);
  if (!maybe_code->ToObject(&object)) return maybe_code;
  isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
  PROFILE(isolate(), CodeCreateEvent(
      Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG,
      Code::cast(object), 0));
  return object;
}


MaybeObject* KeyedStoreIC::Store(State state,
                                 StrictModeFlag strict_mode,
                                 Handle<Object> object,
                                 Handle<Object> key,
                                 Handle<Object> value,
                                 bool force_generic) {
  if (key->IsSymbol()) {
    Handle<String> name = Handle<String>::cast(key);

    // If the object is undefined or null it's illegal to try to set any
    // properties on it; throw a TypeError in that case.
    if (object->IsUndefined() || object->IsNull()) {
      return TypeError("non_object_property_store", object, name);
    }

    // Ignore stores where the receiver is not a JSObject.
    if (!object->IsJSObject()) return *value;
    Handle<JSObject> receiver = Handle<JSObject>::cast(object);

    // Check if the given name is an array index.
    uint32_t index;
    if (name->AsArrayIndex(&index)) {
      HandleScope scope(isolate());
      Handle<Object> result = SetElement(receiver, index, value, strict_mode);
      if (result.is_null()) return Failure::Exception();
      return *value;
    }

    // Lookup the property locally in the receiver.
    LookupResult lookup;
    receiver->LocalLookup(*name, &lookup);

    // Update inline cache and stub cache.
    if (FLAG_use_ic) {
      UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
    }

    // Set the property.
    return receiver->SetProperty(*name, *value, NONE, strict_mode);
  }

  // Do not use ICs for objects that require access checks (including
  // the global object).
  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
  ASSERT(!(use_ic && object->IsJSGlobalProxy()));

  if (use_ic) {
    Code* stub = (strict_mode == kStrictMode)
        ? generic_stub_strict()
        : generic_stub();
    if (!force_generic) {
      if (object->IsJSObject() && key->IsSmi()) {
        JSObject* receiver = JSObject::cast(*object);
        MaybeObject* maybe_stub = ComputeStub(receiver,
                                              true,
                                              strict_mode,
                                              stub);
        stub = maybe_stub->IsFailure() ?
            NULL : Code::cast(maybe_stub->ToObjectUnchecked());
      }
    }
    if (stub != NULL) set_target(stub);
  }

#ifdef DEBUG
  TraceIC("KeyedStoreIC", key, state, target());
#endif

  // Set the property.
  return Runtime::SetObjectProperty(
      isolate(), object , key, value, NONE, strict_mode);
}


void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
                                State state,
                                StrictModeFlag strict_mode,
                                Handle<JSObject> receiver,
                                Handle<String> name,
                                Handle<Object> value) {
  // Skip JSGlobalProxy.
  if (receiver->IsJSGlobalProxy()) return;

  // Bail out if we didn't find a result.
  if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return;

  // If the property is read-only, we leave the IC in its current
  // state.
  if (lookup->IsReadOnly()) return;

  // If the property has a non-field type allowing map transitions
  // where there is extra room in the object, we leave the IC in its
  // current state.
  PropertyType type = lookup->type();

  // Compute the code stub for this store; used for rewriting to
  // monomorphic state and making sure that the code stub is in the
  // stub cache.
  MaybeObject* maybe_code = NULL;
  Object* code = NULL;

  switch (type) {
    case FIELD: {
      maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
          *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
      break;
    }
    case MAP_TRANSITION: {
      if (lookup->GetAttributes() == NONE) {
        HandleScope scope(isolate());
        ASSERT(type == MAP_TRANSITION);
        Handle<Map> transition(lookup->GetTransitionMap());
        int index = transition->PropertyIndexFor(*name);
        maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
            *name, *receiver, index, *transition, strict_mode);
        break;
      }
      // fall through.
    }
    default: {
      // Always rewrite to the generic case so that we do not
      // repeatedly try to rewrite.
      maybe_code = (strict_mode == kStrictMode)
          ? generic_stub_strict()
          : generic_stub();
      break;
    }
  }

  // If we're unable to compute the stub (not enough memory left), we
  // simply avoid updating the caches.
  if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;

  // Patch the call site depending on the state of the cache.  Make
  // sure to always rewrite from monomorphic to megamorphic.
  ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
    set_target(Code::cast(code));
  } else if (state == MONOMORPHIC) {
    set_target((strict_mode == kStrictMode)
                 ? megamorphic_stub_strict()
                 : megamorphic_stub());
  }

#ifdef DEBUG
  TraceIC("KeyedStoreIC", name, state, target());
#endif
}


// ----------------------------------------------------------------------------
// Static IC stub generators.
//

static JSFunction* CompileFunction(Isolate* isolate,
                                   JSFunction* function,
                                   InLoopFlag in_loop) {
  // Compile now with optimization.
  HandleScope scope(isolate);
  Handle<JSFunction> function_handle(function, isolate);
  if (in_loop == IN_LOOP) {
    CompileLazyInLoop(function_handle, CLEAR_EXCEPTION);
  } else {
    CompileLazy(function_handle, CLEAR_EXCEPTION);
  }
  return *function_handle;
}


// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
  NoHandleAllocation na;
  ASSERT(args.length() == 2);
  CallIC ic(isolate);
  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
  MaybeObject* maybe_result = ic.LoadFunction(state,
                                              extra_ic_state,
                                              args.at<Object>(0),
                                              args.at<String>(1));
  Object* result;
  if (!maybe_result->ToObject(&result)) return maybe_result;

  // The first time the inline cache is updated may be the first time the
  // function it references gets called.  If the function was lazily compiled
  // then the first call will trigger a compilation.  We check for this case
  // and we do the compilation immediately, instead of waiting for the stub
  // currently attached to the JSFunction object to trigger compilation.  We
  // do this in the case where we know that the inline cache is inside a loop,
  // because then we know that we want to optimize the function.
  if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
    return result;
  }
  return CompileFunction(isolate,
                         JSFunction::cast(result),
                         ic.target()->ic_in_loop());
}


// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
  NoHandleAllocation na;
  ASSERT(args.length() == 2);
  KeyedCallIC ic(isolate);
  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
  Object* result;
  { MaybeObject* maybe_result =
      ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
    if (!maybe_result->ToObject(&result)) return maybe_result;
  }

  if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
    return result;
  }
  return CompileFunction(isolate,
                         JSFunction::cast(result),
                         ic.target()->ic_in_loop());
}


// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
  NoHandleAllocation na;
  ASSERT(args.length() == 2);
  LoadIC ic(isolate);
  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
  return ic.Load(state, args.at<Object>(0), args.at<String>(1));
}


// Used from ic-<arch>.cc
RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
  NoHandleAllocation na;
  ASSERT(args.length() == 2);
  KeyedLoadIC ic(isolate);
  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
  return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false);
}


RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
  NoHandleAllocation na;
  ASSERT(args.length() == 2);
  KeyedLoadIC ic(isolate);
  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
  return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true);
}


// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
  NoHandleAllocation na;
  ASSERT(args.length() == 3);
  StoreIC ic(isolate);
  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
  return ic.Store(state,
                  static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
                  args.at<Object>(0),
                  args.at<String>(1),
                  args.at<Object>(2));
}


RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
  NoHandleAllocation nha;

  ASSERT(args.length() == 2);
  JSObject* receiver = JSObject::cast(args[0]);
  Object* len = args[1];

  // The generated code should filter out non-Smis before we get here.
  ASSERT(len->IsSmi());

  Object* result;
  { MaybeObject* maybe_result = receiver->SetElementsLength(len);
    if (!maybe_result->ToObject(&result)) return maybe_result;
  }
  return len;
}


// Extend storage is called in a store inline cache when
// it is necessary to extend the properties array of a
// JSObject.
RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
  NoHandleAllocation na;
  ASSERT(args.length() == 3);

  // Convert the parameters
  JSObject* object = JSObject::cast(args[0]);
  Map* transition = Map::cast(args[1]);
  Object* value = args[2];

  // Check the object has run out out property space.
  ASSERT(object->HasFastProperties());
  ASSERT(object->map()->unused_property_fields() == 0);

  // Expand the properties array.
  FixedArray* old_storage = object->properties();
  int new_unused = transition->unused_property_fields();
  int new_size = old_storage->length() + new_unused + 1;
  Object* result;
  { MaybeObject* maybe_result = old_storage->CopySize(new_size);
    if (!maybe_result->ToObject(&result)) return maybe_result;
  }
  FixedArray* new_storage = FixedArray::cast(result);
  new_storage->set(old_storage->length(), value);

  // Set the new property value and do the map transition.
  object->set_properties(new_storage);
  object->set_map(transition);

  // Return the stored value.
  return value;
}


// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
  NoHandleAllocation na;
  ASSERT(args.length() == 3);
  KeyedStoreIC ic(isolate);
  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
  return ic.Store(state,
                  static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
                  args.at<Object>(0),
                  args.at<Object>(1),
                  args.at<Object>(2),
                  false);
}


RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
  NoHandleAllocation na;
  ASSERT(args.length() == 3);
  KeyedStoreIC ic(isolate);
  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
  Handle<Object> object = args.at<Object>(0);
  Handle<Object> key = args.at<Object>(1);
  Handle<Object> value = args.at<Object>(2);
  StrictModeFlag strict_mode =
      static_cast<StrictModeFlag>(extra_ic_state & kStrictMode);
  return Runtime::SetObjectProperty(isolate,
                                    object,
                                    key,
                                    value,
                                    NONE,
                                    strict_mode);
}


RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
  NoHandleAllocation na;
  ASSERT(args.length() == 3);
  KeyedStoreIC ic(isolate);
  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
  return ic.Store(state,
                  static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
                  args.at<Object>(0),
                  args.at<Object>(1),
                  args.at<Object>(2),
                  true);
}


void UnaryOpIC::patch(Code* code) {
  set_target(code);
}


const char* UnaryOpIC::GetName(TypeInfo type_info) {
  switch (type_info) {
    case UNINITIALIZED: return "Uninitialized";
    case SMI: return "Smi";
    case HEAP_NUMBER: return "HeapNumbers";
    case GENERIC: return "Generic";
    default: return "Invalid";
  }
}


UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) {
  switch (type_info) {
    case UNINITIALIZED:
      return ::v8::internal::UNINITIALIZED;
    case SMI:
    case HEAP_NUMBER:
      return MONOMORPHIC;
    case GENERIC:
      return MEGAMORPHIC;
  }
  UNREACHABLE();
  return ::v8::internal::UNINITIALIZED;
}

UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) {
  ::v8::internal::TypeInfo operand_type =
      ::v8::internal::TypeInfo::TypeFromValue(operand);
  if (operand_type.IsSmi()) {
    return SMI;
  } else if (operand_type.IsNumber()) {
    return HEAP_NUMBER;
  } else {
    return GENERIC;
  }
}


UnaryOpIC::TypeInfo UnaryOpIC::ComputeNewType(
    UnaryOpIC::TypeInfo current_type,
    UnaryOpIC::TypeInfo previous_type) {
  switch (previous_type) {
    case UnaryOpIC::UNINITIALIZED:
      return current_type;
    case UnaryOpIC::SMI:
      return (current_type == UnaryOpIC::GENERIC)
          ? UnaryOpIC::GENERIC
          : UnaryOpIC::HEAP_NUMBER;
    case UnaryOpIC::HEAP_NUMBER:
      return UnaryOpIC::GENERIC;
    case UnaryOpIC::GENERIC:
      // We should never do patching if we are in GENERIC state.
      UNREACHABLE();
      return UnaryOpIC::GENERIC;
  }
  UNREACHABLE();
  return UnaryOpIC::GENERIC;
}


void BinaryOpIC::patch(Code* code) {
  set_target(code);
}


const char* BinaryOpIC::GetName(TypeInfo type_info) {
  switch (type_info) {
    case UNINITIALIZED: return "Uninitialized";
    case SMI: return "SMI";
    case INT32: return "Int32s";
    case HEAP_NUMBER: return "HeapNumbers";
    case ODDBALL: return "Oddball";
    case BOTH_STRING: return "BothStrings";
    case STRING: return "Strings";
    case GENERIC: return "Generic";
    default: return "Invalid";
  }
}


BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) {
  switch (type_info) {
    case UNINITIALIZED:
      return ::v8::internal::UNINITIALIZED;
    case SMI:
    case INT32:
    case HEAP_NUMBER:
    case ODDBALL:
    case BOTH_STRING:
    case STRING:
      return MONOMORPHIC;
    case GENERIC:
      return MEGAMORPHIC;
  }
  UNREACHABLE();
  return ::v8::internal::UNINITIALIZED;
}


BinaryOpIC::TypeInfo BinaryOpIC::JoinTypes(BinaryOpIC::TypeInfo x,
                                           BinaryOpIC::TypeInfo y) {
  if (x == UNINITIALIZED) return y;
  if (y == UNINITIALIZED) return x;
  if (x == y) return x;
  if (x == BOTH_STRING && y == STRING) return STRING;
  if (x == STRING && y == BOTH_STRING) return STRING;
  if (x == STRING || x == BOTH_STRING || y == STRING || y == BOTH_STRING) {
    return GENERIC;
  }
  if (x > y) return x;
  return y;
}


BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Handle<Object> left,
                                             Handle<Object> right) {
  ::v8::internal::TypeInfo left_type =
      ::v8::internal::TypeInfo::TypeFromValue(left);
  ::v8::internal::TypeInfo right_type =
      ::v8::internal::TypeInfo::TypeFromValue(right);

  if (left_type.IsSmi() && right_type.IsSmi()) {
    return SMI;
  }

  if (left_type.IsInteger32() && right_type.IsInteger32()) {
    // Platforms with 32-bit Smis have no distinct INT32 type.
    if (kSmiValueSize == 32) return SMI;
    return INT32;
  }

  if (left_type.IsNumber() && right_type.IsNumber()) {
    return HEAP_NUMBER;
  }

  // Patching for fast string ADD makes sense even if only one of the
  // arguments is a string.
  if (left_type.IsString())  {
    return right_type.IsString() ? BOTH_STRING : STRING;
  } else if (right_type.IsString()) {
    return STRING;
  }

  // Check for oddball objects.
  if (left->IsUndefined() && right->IsNumber()) return ODDBALL;
  if (left->IsNumber() && right->IsUndefined()) return ODDBALL;

  return GENERIC;
}


// defined in code-stubs-<arch>.cc
// Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info);


RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) {
  ASSERT(args.length() == 4);

  HandleScope scope(isolate);
  Handle<Object> operand = args.at<Object>(0);
  int key = Smi::cast(args[1])->value();
  Token::Value op = static_cast<Token::Value>(Smi::cast(args[2])->value());
  UnaryOpIC::TypeInfo previous_type =
      static_cast<UnaryOpIC::TypeInfo>(Smi::cast(args[3])->value());

  UnaryOpIC::TypeInfo type = UnaryOpIC::GetTypeInfo(operand);
  type = UnaryOpIC::ComputeNewType(type, previous_type);

  Handle<Code> code = GetUnaryOpStub(key, type);
  if (!code.is_null()) {
    if (FLAG_trace_ic) {
      PrintF("[UnaryOpIC (%s->%s)#%s]\n",
             UnaryOpIC::GetName(previous_type),
             UnaryOpIC::GetName(type),
             Token::Name(op));
    }
    UnaryOpIC ic(isolate);
    ic.patch(*code);
  }

  Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
      isolate->thread_local_top()->context_->builtins(), isolate);
  Object* builtin = NULL;  // Initialization calms down the compiler.
  switch (op) {
    case Token::SUB:
      builtin = builtins->javascript_builtin(Builtins::UNARY_MINUS);
      break;
    case Token::BIT_NOT:
      builtin = builtins->javascript_builtin(Builtins::BIT_NOT);
      break;
    default:
      UNREACHABLE();
  }

  Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);

  bool caught_exception;
  Handle<Object> result = Execution::Call(builtin_function, operand, 0, NULL,
                                          &caught_exception);
  if (caught_exception) {
    return Failure::Exception();
  }
  return *result;
}

// defined in code-stubs-<arch>.cc
// Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
Handle<Code> GetBinaryOpStub(int key,
                             BinaryOpIC::TypeInfo type_info,
                             BinaryOpIC::TypeInfo result_type);


RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
  ASSERT(args.length() == 5);

  HandleScope scope(isolate);
  Handle<Object> left = args.at<Object>(0);
  Handle<Object> right = args.at<Object>(1);
  int key = Smi::cast(args[2])->value();
  Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value());
  BinaryOpIC::TypeInfo previous_type =
      static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value());

  BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(left, right);
  type = BinaryOpIC::JoinTypes(type, previous_type);
  BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED;
  if ((type == BinaryOpIC::STRING || type == BinaryOpIC::BOTH_STRING) &&
      op != Token::ADD) {
    type = BinaryOpIC::GENERIC;
  }
  if (type == BinaryOpIC::SMI && previous_type == BinaryOpIC::SMI) {
    if (op == Token::DIV ||
        op == Token::MUL ||
        op == Token::SHR ||
        kSmiValueSize == 32) {
      // Arithmetic on two Smi inputs has yielded a heap number.
      // That is the only way to get here from the Smi stub.
      // With 32-bit Smis, all overflows give heap numbers, but with
      // 31-bit Smis, most operations overflow to int32 results.
      result_type = BinaryOpIC::HEAP_NUMBER;
    } else {
      // Other operations on SMIs that overflow yield int32s.
      result_type = BinaryOpIC::INT32;
    }
  }
  if (type == BinaryOpIC::INT32 && previous_type == BinaryOpIC::INT32) {
    // We must be here because an operation on two INT32 types overflowed.
    result_type = BinaryOpIC::HEAP_NUMBER;
  }

  Handle<Code> code = GetBinaryOpStub(key, type, result_type);
  if (!code.is_null()) {
    if (FLAG_trace_ic) {
      PrintF("[BinaryOpIC (%s->(%s->%s))#%s]\n",
             BinaryOpIC::GetName(previous_type),
             BinaryOpIC::GetName(type),
             BinaryOpIC::GetName(result_type),
             Token::Name(op));
    }
    BinaryOpIC ic(isolate);
    ic.patch(*code);

    // Activate inlined smi code.
    if (previous_type == BinaryOpIC::UNINITIALIZED) {
      PatchInlinedSmiCode(ic.address());
    }
  }

  Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
      isolate->thread_local_top()->context_->builtins(), isolate);
  Object* builtin = NULL;  // Initialization calms down the compiler.
  switch (op) {
    case Token::ADD:
      builtin = builtins->javascript_builtin(Builtins::ADD);
      break;
    case Token::SUB:
      builtin = builtins->javascript_builtin(Builtins::SUB);
      break;
    case Token::MUL:
      builtin = builtins->javascript_builtin(Builtins::MUL);
      break;
    case Token::DIV:
      builtin = builtins->javascript_builtin(Builtins::DIV);
      break;
    case Token::MOD:
      builtin = builtins->javascript_builtin(Builtins::MOD);
      break;
    case Token::BIT_AND:
      builtin = builtins->javascript_builtin(Builtins::BIT_AND);
      break;
    case Token::BIT_OR:
      builtin = builtins->javascript_builtin(Builtins::BIT_OR);
      break;
    case Token::BIT_XOR:
      builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
      break;
    case Token::SHR:
      builtin = builtins->javascript_builtin(Builtins::SHR);
      break;
    case Token::SAR:
      builtin = builtins->javascript_builtin(Builtins::SAR);
      break;
    case Token::SHL:
      builtin = builtins->javascript_builtin(Builtins::SHL);
      break;
    default:
      UNREACHABLE();
  }

  Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);

  bool caught_exception;
  Object** builtin_args[] = { right.location() };
  Handle<Object> result = Execution::Call(builtin_function,
                                          left,
                                          ARRAY_SIZE(builtin_args),
                                          builtin_args,
                                          &caught_exception);
  if (caught_exception) {
    return Failure::Exception();
  }
  return *result;
}


Handle<Code> CompareIC::GetUninitialized(Token::Value op) {
  ICCompareStub stub(op, UNINITIALIZED);
  return stub.GetCode();
}


CompareIC::State CompareIC::ComputeState(Code* target) {
  int key = target->major_key();
  if (key == CodeStub::Compare) return GENERIC;
  ASSERT(key == CodeStub::CompareIC);
  return static_cast<State>(target->compare_state());
}


const char* CompareIC::GetStateName(State state) {
  switch (state) {
    case UNINITIALIZED: return "UNINITIALIZED";
    case SMIS: return "SMIS";
    case HEAP_NUMBERS: return "HEAP_NUMBERS";
    case OBJECTS: return "OBJECTS";
    case SYMBOLS: return "SYMBOLS";
    case STRINGS: return "STRINGS";
    case GENERIC: return "GENERIC";
    default:
      UNREACHABLE();
      return NULL;
  }
}


CompareIC::State CompareIC::TargetState(State state,
                                        bool has_inlined_smi_code,
                                        Handle<Object> x,
                                        Handle<Object> y) {
  if (!has_inlined_smi_code && state != UNINITIALIZED && state != SYMBOLS) {
    return GENERIC;
  }
  if (state == UNINITIALIZED && x->IsSmi() && y->IsSmi()) return SMIS;
  if ((state == UNINITIALIZED || (state == SMIS && has_inlined_smi_code)) &&
      x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS;
  if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC;
  if (state == UNINITIALIZED &&
      x->IsSymbol() && y->IsSymbol()) return SYMBOLS;
  if ((state == UNINITIALIZED || state == SYMBOLS) &&
      x->IsString() && y->IsString()) return STRINGS;
  if (state == UNINITIALIZED &&
      x->IsJSObject() && y->IsJSObject()) return OBJECTS;
  return GENERIC;
}


// Used from ic_<arch>.cc.
RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
  NoHandleAllocation na;
  ASSERT(args.length() == 3);
  CompareIC ic(isolate, static_cast<Token::Value>(Smi::cast(args[2])->value()));
  ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
  return ic.target();
}


static const Address IC_utilities[] = {
#define ADDR(name) FUNCTION_ADDR(name),
    IC_UTIL_LIST(ADDR)
    NULL
#undef ADDR
};


Address IC::AddressFromUtilityId(IC::UtilityId id) {
  return IC_utilities[id];
}


} }  // namespace v8::internal
