diff options
Diffstat (limited to 'deps/v8/src/ic.cc')
-rw-r--r-- | deps/v8/src/ic.cc | 271 |
1 files changed, 167 insertions, 104 deletions
diff --git a/deps/v8/src/ic.cc b/deps/v8/src/ic.cc index da2211b7b..515c6f71a 100644 --- a/deps/v8/src/ic.cc +++ b/deps/v8/src/ic.cc @@ -160,7 +160,7 @@ Address IC::OriginalCodeAddress() const { // 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()); + Handle<SharedFunctionInfo> shared(function->shared(), isolate()); Code* code = shared->code(); ASSERT(Debug::HasDebugInfo(shared)); Code* original_code = Debug::GetDebugInfo(shared)->original_code(); @@ -190,7 +190,7 @@ static bool TryRemoveInvalidPrototypeDependentStub(Code* target, // The stub was generated for JSObject but called for non-JSObject. // IC::GetCodeCacheHolder is not applicable. return false; - } else if (cache_holder == DELEGATE_MAP && + } else if (cache_holder == PROTOTYPE_MAP && receiver->GetPrototype(isolate)->IsNull()) { // IC::GetCodeCacheHolder is not applicable. return false; @@ -435,7 +435,7 @@ static void LookupForRead(Handle<Object> object, return; } - Handle<JSObject> holder(lookup->holder()); + Handle<JSObject> holder(lookup->holder(), lookup->isolate()); if (HasInterceptorGetter(*holder)) { return; } @@ -446,7 +446,7 @@ static void LookupForRead(Handle<Object> object, return; } - Handle<Object> proto(holder->GetPrototype(), name->GetIsolate()); + Handle<Object> proto(holder->GetPrototype(), lookup->isolate()); if (proto->IsNull()) { ASSERT(!lookup->IsFound()); return; @@ -636,7 +636,7 @@ Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, Handle<Object> object, Handle<String> name) { int argc = target()->arguments_count(); - Handle<JSObject> holder(lookup->holder()); + Handle<JSObject> holder(lookup->holder(), isolate()); switch (lookup->type()) { case FIELD: { PropertyIndex index = lookup->GetFieldIndex(); @@ -647,7 +647,7 @@ Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, // 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. - Handle<JSFunction> function(lookup->GetConstantFunction()); + Handle<JSFunction> function(lookup->GetConstantFunction(), isolate()); return isolate()->stub_cache()->ComputeCallConstant( argc, kind_, extra_state, name, object, holder, function); } @@ -658,7 +658,8 @@ Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, if (holder->IsGlobalObject()) { Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); - Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); + Handle<JSGlobalPropertyCell> cell( + global->GetPropertyCell(lookup), isolate()); if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); Handle<JSFunction> function(JSFunction::cast(cell->value())); return isolate()->stub_cache()->ComputeCallGlobal( @@ -746,7 +747,8 @@ void CallICBase::UpdateCaches(LookupResult* lookup, // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. Handle<JSObject> cache_object = object->IsJSObject() ? Handle<JSObject>::cast(object) - : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))); + : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), + isolate()); // Update the stub cache. UpdateMegamorphicCache(cache_object->map(), *name, *code); break; @@ -855,28 +857,6 @@ MaybeObject* LoadIC::Load(State state, return Smi::FromInt(String::cast(*string)->length()); } - // Use specialized code for getting the length of arrays. - if (object->IsJSArray() && - name->Equals(isolate()->heap()->length_string())) { - Handle<Code> stub; - if (state == UNINITIALIZED) { - stub = pre_monomorphic_stub(); - } else if (state == PREMONOMORPHIC) { - ArrayLengthStub array_length_stub(kind()); - stub = array_length_stub.GetCode(isolate()); - } else if (state != MEGAMORPHIC) { - ASSERT(state != GENERIC); - stub = megamorphic_stub(); - } - if (!stub.is_null()) { - set_target(*stub); -#ifdef DEBUG - if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); -#endif - } - return JSArray::cast(*object)->length(); - } - // Use specialized code for getting prototype of functions. if (object->IsJSFunction() && name->Equals(isolate()->heap()->prototype_string()) && @@ -1035,6 +1015,22 @@ void IC::CopyICToMegamorphicCache(Handle<String> name) { } +bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { + AssertNoAllocation no_allocation; + + Map* current_map = target()->FindFirstMap(); + ElementsKind receiver_elements_kind = receiver_map->elements_kind(); + bool more_general_transition = + IsMoreGeneralElementsKindTransition( + current_map->elements_kind(), receiver_elements_kind); + Map* transitioned_map = more_general_transition + ? current_map->LookupElementsTransitionMap(receiver_elements_kind) + : NULL; + + return transitioned_map == receiver_map; +} + + // Since GC may have been invoked, by the time PatchCache is called, |state| is // not necessarily equal to target()->state(). void IC::PatchCache(State state, @@ -1052,6 +1048,17 @@ void IC::PatchCache(State state, // Only move to megamorphic if the target changes. if (target() != *code) { if (target()->is_load_stub()) { + bool is_same_handler = false; + { + AssertNoAllocation no_allocation; + Code* old_handler = target()->FindFirstCode(); + is_same_handler = old_handler == *code; + } + if (is_same_handler + && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { + UpdateMonomorphicIC(receiver, code, name); + break; + } if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) { break; } @@ -1196,7 +1203,8 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup, case NORMAL: if (holder->IsGlobalObject()) { Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); - Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); + Handle<JSGlobalPropertyCell> cell( + global->GetPropertyCell(lookup), isolate()); return isolate()->stub_cache()->ComputeLoadGlobal( name, receiver, global, cell, lookup->IsDontDelete()); } @@ -1223,6 +1231,12 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup, if (!holder->HasFastProperties()) break; return isolate()->stub_cache()->ComputeLoadViaGetter( name, receiver, holder, Handle<JSFunction>::cast(getter)); + } else if (receiver->IsJSArray() && + name->Equals(isolate()->heap()->length_string())) { + PropertyIndex lengthIndex = + PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize); + return isolate()->stub_cache()->ComputeLoadField( + name, receiver, holder, lengthIndex); } // TODO(dcarney): Handle correctly. if (callback->IsDeclaredAccessorInfo()) break; @@ -1272,7 +1286,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { return generic_stub(); } - Handle<Map> receiver_map(receiver->map()); + Handle<Map> receiver_map(receiver->map(), isolate()); MapHandleList target_receiver_maps; if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { // Optimistically assume that ICs that haven't reached the MONOMORPHIC state @@ -1283,7 +1297,8 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { if (target() == *string_stub()) { target_receiver_maps.Add(isolate()->factory()->string_map()); } else { - GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps); + GetReceiverMapsForStub(Handle<Code>(target(), isolate()), + &target_receiver_maps); if (target_receiver_maps.length() == 0) { return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); } @@ -1355,7 +1370,8 @@ MaybeObject* KeyedLoadIC::Load(State state, stub = non_strict_arguments_stub(); } else if (receiver->HasIndexedInterceptor()) { stub = indexed_interceptor_stub(); - } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { + } else if (!key->ToSmi()->IsFailure() && + (target() != *non_strict_arguments_stub())) { stub = LoadElementStub(receiver); } } @@ -1379,13 +1395,13 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, if (!lookup->IsProperty()) return Handle<Code>::null(); // Compute a monomorphic stub. - Handle<JSObject> holder(lookup->holder()); + Handle<JSObject> holder(lookup->holder(), isolate()); switch (lookup->type()) { case FIELD: return isolate()->stub_cache()->ComputeKeyedLoadField( name, receiver, holder, lookup->GetFieldIndex()); case CONSTANT_FUNCTION: { - Handle<JSFunction> constant(lookup->GetConstantFunction()); + Handle<JSFunction> constant(lookup->GetConstantFunction(), isolate()); return isolate()->stub_cache()->ComputeKeyedLoadConstant( name, receiver, holder, constant); } @@ -1413,41 +1429,42 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, } -static bool StoreICableLookup(LookupResult* lookup) { - // Bail out if we didn't find a result. - if (!lookup->IsFound()) return false; - - // Bail out if inline caching is not allowed. - if (!lookup->IsCacheable()) return false; - - // If the property is read-only, we leave the IC in its current state. - if (lookup->IsTransition()) { - return !lookup->GetTransitionDetails().IsReadOnly(); - } - return !lookup->IsReadOnly(); -} - - static bool LookupForWrite(Handle<JSObject> receiver, Handle<String> name, LookupResult* lookup) { - receiver->LocalLookup(*name, lookup); - if (!lookup->IsFound()) { - receiver->map()->LookupTransition(*receiver, *name, lookup); - } - if (!StoreICableLookup(lookup)) { - // 2nd chance: There can be accessors somewhere in the prototype chain. - receiver->Lookup(*name, lookup); - return lookup->IsPropertyCallbacks() && StoreICableLookup(lookup); - } + Handle<JSObject> holder = receiver; + receiver->Lookup(*name, lookup); + if (lookup->IsFound()) { + if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; + + if (lookup->holder() == *receiver) { + if (lookup->IsInterceptor() && + receiver->GetNamedInterceptor()->setter()->IsUndefined()) { + receiver->LocalLookupRealNamedProperty(*name, lookup); + return lookup->IsFound() && + !lookup->IsReadOnly() && + lookup->IsCacheable(); + } + return true; + } - if (lookup->IsInterceptor() && - receiver->GetNamedInterceptor()->setter()->IsUndefined()) { - receiver->LocalLookupRealNamedProperty(*name, lookup); - return StoreICableLookup(lookup); + if (lookup->IsPropertyCallbacks()) return true; + + // Currently normal holders in the prototype chain are not supported. They + // would require a runtime positive lookup and verification that the details + // have not changed. + if (lookup->IsInterceptor() || lookup->IsNormal()) return false; + holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); } - return true; + // While normally LookupTransition gets passed the receiver, in this case we + // pass the holder of the property that we overwrite. This keeps the holder in + // the LookupResult intact so we can later use it to generate a prototype + // chain check. This avoids a double lookup, but requires us to pass in the + // receiver when trying to fetch extra information from the transition. + receiver->map()->LookupTransition(*holder, *name, lookup); + return lookup->IsTransition() && + !lookup->GetTransitionDetails(receiver->map()).IsReadOnly(); } @@ -1547,7 +1564,6 @@ void StoreIC::UpdateCaches(LookupResult* lookup, Handle<String> name, Handle<Object> value) { ASSERT(!receiver->IsJSGlobalProxy()); - ASSERT(StoreICableLookup(lookup)); ASSERT(lookup->IsFound()); // These are not cacheable, so we never see such LookupResults here. @@ -1570,19 +1586,19 @@ Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, switch (lookup->type()) { case FIELD: return isolate()->stub_cache()->ComputeStoreField( - name, receiver, lookup->GetFieldIndex().field_index(), - Handle<Map>::null(), strict_mode); + name, receiver, lookup, Handle<Map>::null(), strict_mode); 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); - Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); + Handle<JSGlobalPropertyCell> cell( + global->GetPropertyCell(lookup), isolate()); return isolate()->stub_cache()->ComputeStoreGlobal( name, global, cell, strict_mode); } - if (!holder.is_identical_to(receiver)) break; + ASSERT(holder.is_identical_to(receiver)); return isolate()->stub_cache()->ComputeStoreNormal(strict_mode); case CALLBACKS: { Handle<Object> callback(lookup->GetCallbackObject(), isolate()); @@ -1595,8 +1611,8 @@ Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, return isolate()->stub_cache()->ComputeStoreCallback( name, receiver, holder, info, strict_mode); } else if (callback->IsAccessorPair()) { - Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter(), - isolate()); + Handle<Object> setter( + Handle<AccessorPair>::cast(callback)->setter(), isolate()); if (!setter->IsJSFunction()) break; if (holder->IsGlobalObject()) break; if (!holder->HasFastProperties()) break; @@ -1617,7 +1633,10 @@ Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, case CONSTANT_FUNCTION: break; case TRANSITION: { - Handle<Map> transition(lookup->GetTransitionTarget()); + // Explicitly pass in the receiver map since LookupForWrite may have + // stored something else than the receiver in the holder. + Handle<Map> transition( + lookup->GetTransitionTarget(receiver->map()), isolate()); int descriptor = transition->LastAdded(); DescriptorArray* target_descriptors = transition->instance_descriptors(); @@ -1625,9 +1644,8 @@ Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, if (details.type() != FIELD || details.attributes() != NONE) break; - int field_index = target_descriptors->GetFieldIndex(descriptor); return isolate()->stub_cache()->ComputeStoreField( - name, receiver, field_index, transition, strict_mode); + name, receiver, lookup, transition, strict_mode); } case NONEXISTENT: case HANDLER: @@ -1649,7 +1667,8 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); } - if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW || + if (!FLAG_compiled_keyed_stores && + (store_mode == STORE_NO_TRANSITION_HANDLE_COW || store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS)) { // TODO(danno): We'll soon handle MONOMORPHIC ICs that also support // copying COW arrays and silently ignoring some OOB stores into external @@ -1661,7 +1680,7 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, } State ic_state = target()->ic_state(); - Handle<Map> receiver_map(receiver->map()); + Handle<Map> receiver_map(receiver->map(), isolate()); if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { // Optimistically assume that ICs that haven't reached the MONOMORPHIC state // yet will do so and stay there. @@ -1697,24 +1716,18 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, transitioned_receiver_map = ComputeTransitionedMap(receiver, store_mode); } - ElementsKind transitioned_kind = - transitioned_receiver_map->elements_kind(); - bool more_general_transition = - IsMoreGeneralElementsKindTransition( - previous_receiver_map->elements_kind(), - transitioned_kind); - Map* transitioned_previous_map = more_general_transition - ? previous_receiver_map->LookupElementsTransitionMap(transitioned_kind) - : NULL; - if (transitioned_previous_map == *transitioned_receiver_map) { + if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { // Element family is the same, use the "worst" case map. store_mode = GetNonTransitioningStoreMode(store_mode); return isolate()->stub_cache()->ComputeKeyedStoreElement( transitioned_receiver_map, strict_mode, store_mode); } else if (*previous_receiver_map == receiver->map()) { - if (IsGrowStoreMode(store_mode)) { + if (IsGrowStoreMode(store_mode) || + store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || + store_mode == STORE_NO_TRANSITION_HANDLE_COW) { // A "normal" IC that handles stores can switch to a version that can - // grow at the end of the array and still stay MONOMORPHIC. + // grow at the end of the array, handle OOB accesses or copy COW arrays + // and still stay MONOMORPHIC. return isolate()->stub_cache()->ComputeKeyedStoreElement( receiver_map, strict_mode, store_mode); } @@ -1761,6 +1774,26 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, } } + // If the store mode isn't the standard mode, make sure that all polymorphic + // receivers are either external arrays, or all "normal" arrays. Otherwise, + // use the generic stub. + if (store_mode != STANDARD_STORE) { + int external_arrays = 0; + for (int i = 0; i < target_receiver_maps.length(); ++i) { + if (target_receiver_maps[i]->has_external_array_elements()) { + external_arrays++; + } + } + if (external_arrays != 0 && + external_arrays != target_receiver_maps.length()) { + TRACE_GENERIC_IC(isolate(), "KeyedIC", + "unsupported combination of external and normal arrays"); + return strict_mode == kStrictMode + ? generic_stub_strict() + : generic_stub(); + } + } + return isolate()->stub_cache()->ComputeStoreElementPolymorphic( &target_receiver_maps, store_mode, strict_mode); } @@ -1794,7 +1827,7 @@ Handle<Map> KeyedStoreIC::ComputeTransitionedMap( case STORE_NO_TRANSITION_HANDLE_COW: case STANDARD_STORE: case STORE_AND_GROW_NO_TRANSITION: - return Handle<Map>(receiver->map()); + return Handle<Map>(receiver->map(), isolate()); } return Handle<Map>::null(); } @@ -1813,8 +1846,10 @@ bool IsOutOfBoundsAccess(Handle<JSObject> receiver, KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver, Handle<Object> key, Handle<Object> value) { - ASSERT(key->IsSmi()); - int index = Smi::cast(*key)->value(); + ASSERT(!key->ToSmi()->IsFailure()); + Smi* smi_key = NULL; + key->ToSmi()->To(&smi_key); + int index = smi_key->value(); bool oob_access = IsOutOfBoundsAccess(receiver, index); bool allow_growth = receiver->IsJSArray() && oob_access; if (allow_growth) { @@ -1872,6 +1907,10 @@ KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver, if (!FLAG_trace_external_array_abuse && receiver->map()->has_external_array_elements() && oob_access) { return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS; + } + Heap* heap = receiver->GetHeap(); + if (receiver->elements()->map() == heap->fixed_cow_array_map()) { + return STORE_NO_TRANSITION_HANDLE_COW; } else { return STANDARD_STORE; } @@ -1910,13 +1949,20 @@ MaybeObject* KeyedStoreIC::Store(State state, if (miss_mode != MISS_FORCE_GENERIC) { if (object->IsJSObject()) { Handle<JSObject> receiver = Handle<JSObject>::cast(object); + bool key_is_smi_like = key->IsSmi() || + (FLAG_compiled_keyed_stores && !key->ToSmi()->IsFailure()); if (receiver->elements()->map() == isolate()->heap()->non_strict_arguments_elements_map()) { stub = non_strict_arguments_stub(); - } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { + } else if (key_is_smi_like && + (target() != *non_strict_arguments_stub())) { KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); stub = StoreElementStub(receiver, store_mode, strict_mode); + } else { + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); } + } else { + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); } } else { TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); @@ -1941,19 +1987,20 @@ Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, switch (lookup->type()) { case FIELD: return isolate()->stub_cache()->ComputeKeyedStoreField( - name, receiver, lookup->GetFieldIndex().field_index(), - Handle<Map>::null(), strict_mode); + name, receiver, lookup, Handle<Map>::null(), strict_mode); case TRANSITION: { - Handle<Map> transition(lookup->GetTransitionTarget()); + // Explicitly pass in the receiver map since LookupForWrite may have + // stored something else than the receiver in the holder. + Handle<Map> transition( + lookup->GetTransitionTarget(receiver->map()), isolate()); int descriptor = transition->LastAdded(); DescriptorArray* target_descriptors = transition->instance_descriptors(); PropertyDetails details = target_descriptors->GetDetails(descriptor); if (details.type() == FIELD && details.attributes() == NONE) { - int field_index = target_descriptors->GetFieldIndex(descriptor); return isolate()->stub_cache()->ComputeKeyedStoreField( - name, receiver, field_index, transition, strict_mode); + name, receiver, lookup, transition, strict_mode); } // fall through. } @@ -2023,7 +2070,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { if (raw_function->is_compiled()) return raw_function; - Handle<JSFunction> function(raw_function); + Handle<JSFunction> function(raw_function, isolate); JSFunction::CompileLazy(function, CLEAR_EXCEPTION); return *function; } @@ -2074,7 +2121,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { HandleScope scope(isolate); ASSERT(args.length() == 3); - StoreIC ic(isolate); + StoreIC ic(IC::NO_EXTRA_FRAME, 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, @@ -2150,7 +2197,22 @@ RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) { RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { HandleScope scope(isolate); ASSERT(args.length() == 3); - KeyedStoreIC ic(isolate); + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, 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, + Code::GetStrictMode(extra_ic_state), + args.at<Object>(0), + args.at<Object>(1), + args.at<Object>(2), + MISS); +} + + +RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { + HandleScope scope(isolate); + ASSERT(args.length() == 3); + KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, 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, @@ -2165,7 +2227,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { NoHandleAllocation na(isolate); ASSERT(args.length() == 3); - KeyedStoreIC ic(isolate); + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, 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); @@ -2183,7 +2245,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { HandleScope scope(isolate); ASSERT(args.length() == 3); - KeyedStoreIC ic(isolate); + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, 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, @@ -2668,7 +2730,8 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { HasInlinedSmiCode(address()), x, y); ICCompareStub stub(op_, new_left, new_right, state); if (state == KNOWN_OBJECT) { - stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); + stub.set_known_map( + Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); } set_target(*stub.GetCode(isolate())); |