| Index: src/ic.cc
|
| diff --git a/src/ic.cc b/src/ic.cc
|
| index b90436ae42c5f38feed72cf4d44be0d6f6b8b04f..b7598784b67d666c63afd102e06deb7b710d403d 100644
|
| --- a/src/ic.cc
|
| +++ b/src/ic.cc
|
| @@ -830,9 +830,9 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
|
| }
|
|
|
|
|
| -MaybeObject* IC::Load(State state,
|
| - Handle<Object> object,
|
| - Handle<String> name) {
|
| +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()) {
|
| @@ -1086,42 +1086,6 @@ void LoadIC::UpdateLoadCaches(LookupResult* lookup,
|
| }
|
|
|
|
|
| -Handle<Code> KeyedLoadIC::GetElementStubWithoutMapCheck(
|
| - bool is_js_array,
|
| - ElementsKind elements_kind,
|
| - KeyedAccessGrowMode grow_mode) {
|
| - ASSERT(grow_mode == DO_NOT_ALLOW_JSARRAY_GROWTH);
|
| - if (IsFastElementsKind(elements_kind) ||
|
| - IsExternalArrayElementsKind(elements_kind)) {
|
| - return KeyedLoadFastElementStub(is_js_array, elements_kind).GetCode();
|
| - } else {
|
| - ASSERT(elements_kind == DICTIONARY_ELEMENTS);
|
| - return KeyedLoadDictionaryElementStub().GetCode();
|
| - }
|
| -}
|
| -
|
| -
|
| -Handle<Code> KeyedLoadIC::ComputePolymorphicStub(
|
| - MapHandleList* receiver_maps,
|
| - StrictModeFlag strict_mode,
|
| - KeyedAccessGrowMode growth_mode) {
|
| - CodeHandleList handler_ics(receiver_maps->length());
|
| - for (int i = 0; i < receiver_maps->length(); ++i) {
|
| - Handle<Map> receiver_map = receiver_maps->at(i);
|
| - Handle<Code> cached_stub = ComputeMonomorphicStubWithoutMapCheck(
|
| - receiver_map, strict_mode, growth_mode);
|
| - handler_ics.Add(cached_stub);
|
| - }
|
| - KeyedLoadStubCompiler compiler(isolate());
|
| - Handle<Code> code = compiler.CompileLoadPolymorphic(
|
| - receiver_maps, &handler_ics);
|
| - isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG, *code, 0));
|
| - return code;
|
| -}
|
| -
|
| -
|
| static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
|
| // This helper implements a few common fast cases for converting
|
| // non-smi keys of keyed loads/stores to a smi or a string.
|
| @@ -1142,6 +1106,115 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
|
| }
|
|
|
|
|
| +static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
|
| + Handle<Map> new_receiver_map) {
|
| + ASSERT(!new_receiver_map.is_null());
|
| + for (int current = 0; current < receiver_maps->length(); ++current) {
|
| + if (!receiver_maps->at(current).is_null() &&
|
| + receiver_maps->at(current).is_identical_to(new_receiver_map)) {
|
| + return false;
|
| + }
|
| + }
|
| + receiver_maps->Add(new_receiver_map);
|
| + return true;
|
| +}
|
| +
|
| +
|
| +static void GetReceiverMapsForStub(Handle<Code> stub,
|
| + MapHandleList* result) {
|
| + ASSERT(stub->is_inline_cache_stub());
|
| + if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
|
| + switch (stub->ic_state()) {
|
| + case MONOMORPHIC:
|
| + result->Add(Handle<Map>(stub->FindFirstMap()));
|
| + break;
|
| + case POLYMORPHIC: {
|
| + AssertNoAllocation no_allocation;
|
| + int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
|
| + for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
|
| + RelocInfo* info = it.rinfo();
|
| + Handle<Object> object(info->target_object());
|
| + ASSERT(object->IsMap());
|
| + AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
|
| + }
|
| + break;
|
| + }
|
| + case MEGAMORPHIC:
|
| + case GENERIC:
|
| + break;
|
| + case UNINITIALIZED:
|
| + case PREMONOMORPHIC:
|
| + case MONOMORPHIC_PROTOTYPE_FAILURE:
|
| + case DEBUG_STUB:
|
| + UNREACHABLE();
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
|
| + State ic_state = target()->ic_state();
|
| +
|
| + // 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() != Code::NORMAL) {
|
| + TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type");
|
| + return generic_stub();
|
| + }
|
| +
|
| + Handle<Map> receiver_map(receiver->map());
|
| + MapHandleList target_receiver_maps;
|
| + 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.
|
| + return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
|
| + }
|
| +
|
| + if (target() == *string_stub()) {
|
| + target_receiver_maps.Add(isolate()->factory()->string_map());
|
| + } else {
|
| + GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
|
| + }
|
| +
|
| + // The first time a receiver is seen that is a transitioned version of the
|
| + // previous monomorphic receiver type, assume the new ElementsKind is the
|
| + // monomorphic type. This benefits global arrays that only transition
|
| + // once, and all call sites accessing them are faster if they remain
|
| + // monomorphic. If this optimistic assumption is not true, the IC will
|
| + // miss again and it will become polymorphic and support both the
|
| + // untransitioned and transitioned maps.
|
| + if (ic_state == MONOMORPHIC &&
|
| + IsMoreGeneralElementsKindTransition(
|
| + target_receiver_maps.at(0)->elements_kind(),
|
| + receiver->GetElementsKind())) {
|
| + return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
|
| + }
|
| +
|
| + ASSERT(target() != *generic_stub());
|
| +
|
| + // Determine the list of receiver maps that this call site has seen,
|
| + // adding the map that was just encountered.
|
| + if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
|
| + // If the miss wasn't due to an unseen map, a polymorphic stub
|
| + // won't help, use the generic stub.
|
| + TRACE_GENERIC_IC("KeyedIC", "same map added twice");
|
| + return generic_stub();
|
| + }
|
| +
|
| + // If the maximum number of receiver maps has been exceeded, use the generic
|
| + // version of the IC.
|
| + if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
|
| + TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded");
|
| + return generic_stub();
|
| + }
|
| +
|
| + return isolate()->stub_cache()->ComputeLoadElementPolymorphic(
|
| + &target_receiver_maps);
|
| +}
|
| +
|
| +
|
| MaybeObject* KeyedLoadIC::Load(State state,
|
| Handle<Object> object,
|
| Handle<Object> key,
|
| @@ -1151,7 +1224,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
| key = TryConvertKey(key, isolate());
|
|
|
| if (key->IsSymbol()) {
|
| - return IC::Load(state, object, Handle<String>::cast(key));
|
| + return LoadIC::Load(state, object, Handle<String>::cast(key));
|
| }
|
|
|
| // Do not use ICs for objects that require access checks (including
|
| @@ -1173,7 +1246,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
| } else if (receiver->HasIndexedInterceptor()) {
|
| stub = indexed_interceptor_stub();
|
| } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
|
| - stub = ComputeStub(receiver, KeyedIC::LOAD, kNonStrictMode, stub);
|
| + stub = LoadElementStub(receiver);
|
| }
|
| }
|
| } else {
|
| @@ -1311,12 +1384,12 @@ static bool LookupForWrite(Handle<JSObject> receiver,
|
| }
|
|
|
|
|
| -MaybeObject* IC::Store(State state,
|
| - StrictModeFlag strict_mode,
|
| - Handle<Object> object,
|
| - Handle<String> name,
|
| - Handle<Object> value,
|
| - JSReceiver::StoreFromKeyed store_mode) {
|
| +MaybeObject* StoreIC::Store(State state,
|
| + StrictModeFlag strict_mode,
|
| + Handle<Object> object,
|
| + Handle<String> name,
|
| + Handle<Object> value,
|
| + JSReceiver::StoreFromKeyed store_mode) {
|
| // Handle proxies.
|
| if (object->IsJSProxy()) {
|
| return JSProxy::cast(*object)->
|
| @@ -1537,59 +1610,9 @@ void StoreIC::UpdateStoreCaches(LookupResult* lookup,
|
| }
|
|
|
|
|
| -static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
|
| - Handle<Map> new_receiver_map) {
|
| - ASSERT(!new_receiver_map.is_null());
|
| - for (int current = 0; current < receiver_maps->length(); ++current) {
|
| - if (!receiver_maps->at(current).is_null() &&
|
| - receiver_maps->at(current).is_identical_to(new_receiver_map)) {
|
| - return false;
|
| - }
|
| - }
|
| - receiver_maps->Add(new_receiver_map);
|
| - return true;
|
| -}
|
| -
|
| -
|
| -void KeyedIC::GetReceiverMapsForStub(Handle<Code> stub,
|
| - MapHandleList* result) {
|
| - ASSERT(stub->is_inline_cache_stub());
|
| - if (!string_stub().is_null() && stub.is_identical_to(string_stub())) {
|
| - return result->Add(isolate()->factory()->string_map());
|
| - } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
|
| - switch (stub->ic_state()) {
|
| - case MONOMORPHIC:
|
| - result->Add(Handle<Map>(stub->FindFirstMap()));
|
| - break;
|
| - case POLYMORPHIC: {
|
| - AssertNoAllocation no_allocation;
|
| - int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
|
| - for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
|
| - RelocInfo* info = it.rinfo();
|
| - Handle<Object> object(info->target_object());
|
| - ASSERT(object->IsMap());
|
| - AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
|
| - }
|
| - break;
|
| - }
|
| - case MEGAMORPHIC:
|
| - case GENERIC:
|
| - break;
|
| - case UNINITIALIZED:
|
| - case PREMONOMORPHIC:
|
| - case MONOMORPHIC_PROTOTYPE_FAILURE:
|
| - case DEBUG_STUB:
|
| - UNREACHABLE();
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| -Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
|
| - StubKind stub_kind,
|
| - StrictModeFlag strict_mode,
|
| - Handle<Code> generic_stub) {
|
| +Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
|
| + StubKind stub_kind,
|
| + StrictModeFlag strict_mode) {
|
| State ic_state = target()->ic_state();
|
| KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind)
|
| ? ALLOW_JSARRAY_GROWTH
|
| @@ -1600,65 +1623,61 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
|
| // and so the stubs can't be harvested for the object needed for a map check.
|
| if (target()->type() != Code::NORMAL) {
|
| TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type");
|
| - return generic_stub;
|
| + return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
|
| }
|
|
|
| - bool monomorphic = false;
|
| - bool is_transition_stub = IsTransitionStubKind(stub_kind);
|
| Handle<Map> receiver_map(receiver->map());
|
| - Handle<Map> monomorphic_map = receiver_map;
|
| MapHandleList target_receiver_maps;
|
| 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.
|
| - monomorphic = true;
|
| - } else {
|
| - GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
|
| - if (ic_state == MONOMORPHIC && (is_transition_stub || stub_kind == LOAD)) {
|
| - // The first time a receiver is seen that is a transitioned version of the
|
| - // previous monomorphic receiver type, assume the new ElementsKind is the
|
| - // monomorphic type. This benefits global arrays that only transition
|
| - // once, and all call sites accessing them are faster if they remain
|
| - // monomorphic. If this optimistic assumption is not true, the IC will
|
| - // miss again and it will become polymorphic and support both the
|
| - // untransitioned and transitioned maps.
|
| - monomorphic = IsMoreGeneralElementsKindTransition(
|
| + stub_kind = GetNoTransitionStubKind(stub_kind);
|
| + return isolate()->stub_cache()->ComputeKeyedStoreElement(
|
| + receiver_map, stub_kind, strict_mode, grow_mode);
|
| + }
|
| +
|
| + GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
|
| + // The first time a receiver is seen that is a transitioned version of the
|
| + // previous monomorphic receiver type, assume the new ElementsKind is the
|
| + // monomorphic type. This benefits global arrays that only transition
|
| + // once, and all call sites accessing them are faster if they remain
|
| + // monomorphic. If this optimistic assumption is not true, the IC will
|
| + // miss again and it will become polymorphic and support both the
|
| + // untransitioned and transitioned maps.
|
| + if (ic_state == MONOMORPHIC &&
|
| + IsTransitionStubKind(stub_kind) &&
|
| + IsMoreGeneralElementsKindTransition(
|
| target_receiver_maps.at(0)->elements_kind(),
|
| - receiver->GetElementsKind());
|
| - }
|
| + receiver->GetElementsKind())) {
|
| + Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, stub_kind);
|
| + ASSERT(*monomorphic_map != *receiver_map);
|
| + stub_kind = GetNoTransitionStubKind(stub_kind);
|
| + return isolate()->stub_cache()->ComputeKeyedStoreElement(
|
| + monomorphic_map, stub_kind, strict_mode, grow_mode);
|
| }
|
|
|
| - if (monomorphic) {
|
| - if (is_transition_stub) {
|
| - monomorphic_map = ComputeTransitionedMap(receiver, stub_kind);
|
| - ASSERT(*monomorphic_map != *receiver_map);
|
| - stub_kind = GetNoTransitionStubKind(stub_kind);
|
| - }
|
| - return ComputeMonomorphicStub(
|
| - monomorphic_map, stub_kind, strict_mode, generic_stub);
|
| - }
|
| - ASSERT(target() != *generic_stub);
|
| + ASSERT(target() != *generic_stub() && target() != *generic_stub_strict());
|
|
|
| - // Determine the list of receiver maps that this call site has seen,
|
| - // adding the map that was just encountered.
|
| bool map_added =
|
| AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
|
| +
|
| if (IsTransitionStubKind(stub_kind)) {
|
| Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind);
|
| map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map);
|
| }
|
| +
|
| if (!map_added) {
|
| // If the miss wasn't due to an unseen map, a polymorphic stub
|
| // won't help, use the generic stub.
|
| TRACE_GENERIC_IC("KeyedIC", "same map added twice");
|
| - return generic_stub;
|
| + return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
|
| }
|
|
|
| // If the maximum number of receiver maps has been exceeded, use the generic
|
| // version of the IC.
|
| if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
|
| TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded");
|
| - return generic_stub;
|
| + return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
|
| }
|
|
|
| if ((Code::GetKeyedAccessGrowMode(target()->extra_ic_state()) ==
|
| @@ -1666,81 +1685,34 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
|
| grow_mode = ALLOW_JSARRAY_GROWTH;
|
| }
|
|
|
| - Handle<PolymorphicCodeCache> cache =
|
| - isolate()->factory()->polymorphic_code_cache();
|
| - Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode,
|
| - strict_mode);
|
| - Code::Flags flags = Code::ComputeFlags(kind(), POLYMORPHIC, extra_state);
|
| - Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags);
|
| - if (probe->IsCode()) return Handle<Code>::cast(probe);
|
| -
|
| - Handle<Code> stub =
|
| - ComputePolymorphicStub(&target_receiver_maps, strict_mode, grow_mode);
|
| - PolymorphicCodeCache::Update(cache, &target_receiver_maps, flags, stub);
|
| - return stub;
|
| -}
|
| -
|
| -
|
| -Handle<Code> KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
|
| - Handle<Map> receiver_map,
|
| - StrictModeFlag strict_mode,
|
| - KeyedAccessGrowMode grow_mode) {
|
| - if ((receiver_map->instance_type() & kNotStringTag) == 0) {
|
| - ASSERT(!string_stub().is_null());
|
| - return string_stub();
|
| - } else {
|
| - ASSERT(receiver_map->has_dictionary_elements() ||
|
| - receiver_map->has_fast_smi_or_object_elements() ||
|
| - receiver_map->has_fast_double_elements() ||
|
| - receiver_map->has_external_array_elements());
|
| - bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
| - return GetElementStubWithoutMapCheck(is_js_array,
|
| - receiver_map->elements_kind(),
|
| - grow_mode);
|
| - }
|
| -}
|
| -
|
| -
|
| -Handle<Code> KeyedIC::ComputeMonomorphicStub(Handle<Map> receiver_map,
|
| - StubKind stub_kind,
|
| - StrictModeFlag strict_mode,
|
| - Handle<Code> generic_stub) {
|
| - ElementsKind elements_kind = receiver_map->elements_kind();
|
| - if (IsFastElementsKind(elements_kind) ||
|
| - IsExternalArrayElementsKind(elements_kind) ||
|
| - IsDictionaryElementsKind(elements_kind)) {
|
| - return isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement(
|
| - receiver_map, stub_kind, strict_mode);
|
| - } else {
|
| - return generic_stub;
|
| - }
|
| + return isolate()->stub_cache()->ComputeStoreElementPolymorphic(
|
| + &target_receiver_maps, grow_mode, strict_mode);
|
| }
|
|
|
|
|
| -Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver,
|
| - StubKind stub_kind) {
|
| +Handle<Map> KeyedStoreIC::ComputeTransitionedMap(Handle<JSObject> receiver,
|
| + StubKind stub_kind) {
|
| switch (stub_kind) {
|
| - case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT:
|
| - case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT:
|
| - case KeyedIC::STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT:
|
| - case KeyedIC::STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT:
|
| + case STORE_TRANSITION_SMI_TO_OBJECT:
|
| + case STORE_TRANSITION_DOUBLE_TO_OBJECT:
|
| + case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT:
|
| + case STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT:
|
| return JSObject::GetElementsTransitionMap(receiver, FAST_ELEMENTS);
|
| - case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE:
|
| - case KeyedIC::STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE:
|
| + case STORE_TRANSITION_SMI_TO_DOUBLE:
|
| + case STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE:
|
| return JSObject::GetElementsTransitionMap(receiver, FAST_DOUBLE_ELEMENTS);
|
| - case KeyedIC::STORE_TRANSITION_HOLEY_SMI_TO_OBJECT:
|
| - case KeyedIC::STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
|
| - case KeyedIC::STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT:
|
| - case KeyedIC::STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
|
| + case STORE_TRANSITION_HOLEY_SMI_TO_OBJECT:
|
| + case STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
|
| + case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT:
|
| + case STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
|
| return JSObject::GetElementsTransitionMap(receiver,
|
| FAST_HOLEY_ELEMENTS);
|
| - case KeyedIC::STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE:
|
| - case KeyedIC::STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE:
|
| + case STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE:
|
| + case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE:
|
| return JSObject::GetElementsTransitionMap(receiver,
|
| FAST_HOLEY_DOUBLE_ELEMENTS);
|
| - case KeyedIC::LOAD:
|
| - case KeyedIC::STORE_NO_TRANSITION:
|
| - case KeyedIC::STORE_AND_GROW_NO_TRANSITION:
|
| + case STORE_NO_TRANSITION:
|
| + case STORE_AND_GROW_NO_TRANSITION:
|
| UNREACHABLE();
|
| break;
|
| }
|
| @@ -1748,60 +1720,9 @@ Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver,
|
| }
|
|
|
|
|
| -Handle<Code> KeyedStoreIC::GetElementStubWithoutMapCheck(
|
| - bool is_js_array,
|
| - ElementsKind elements_kind,
|
| - KeyedAccessGrowMode grow_mode) {
|
| - return KeyedStoreElementStub(is_js_array, elements_kind, grow_mode).GetCode();
|
| -}
|
| -
|
| -
|
| -Handle<Code> KeyedStoreIC::ComputePolymorphicStub(
|
| - MapHandleList* receiver_maps,
|
| - StrictModeFlag strict_mode,
|
| - KeyedAccessGrowMode grow_mode) {
|
| - // Collect MONOMORPHIC stubs for all target_receiver_maps.
|
| - CodeHandleList handler_ics(receiver_maps->length());
|
| - MapHandleList transitioned_maps(receiver_maps->length());
|
| - for (int i = 0; i < receiver_maps->length(); ++i) {
|
| - Handle<Map> receiver_map(receiver_maps->at(i));
|
| - Handle<Code> cached_stub;
|
| - Handle<Map> transitioned_map =
|
| - receiver_map->FindTransitionedMap(receiver_maps);
|
| -
|
| - // TODO(mvstanton): The code below is doing pessimistic elements
|
| - // transitions. I would like to stop doing that and rely on Allocation Site
|
| - // Tracking to do a better job of ensuring the data types are what they need
|
| - // to be. Not all the elements are in place yet, pessimistic elements
|
| - // transitions are still important for performance.
|
| - if (!transitioned_map.is_null()) {
|
| - cached_stub = ElementsTransitionAndStoreStub(
|
| - receiver_map->elements_kind(), // original elements_kind
|
| - transitioned_map->elements_kind(),
|
| - receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array
|
| - strict_mode, grow_mode).GetCode();
|
| - } else {
|
| - cached_stub = ComputeMonomorphicStubWithoutMapCheck(receiver_map,
|
| - strict_mode,
|
| - grow_mode);
|
| - }
|
| - ASSERT(!cached_stub.is_null());
|
| - handler_ics.Add(cached_stub);
|
| - transitioned_maps.Add(transitioned_map);
|
| - }
|
| - KeyedStoreStubCompiler compiler(isolate(), strict_mode, grow_mode);
|
| - Handle<Code> code = compiler.CompileStorePolymorphic(
|
| - receiver_maps, &handler_ics, &transitioned_maps);
|
| - isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
|
| - PROFILE(isolate(),
|
| - CodeCreateEvent(Logger::KEYED_STORE_POLYMORPHIC_IC_TAG, *code, 0));
|
| - return code;
|
| -}
|
| -
|
| -
|
| -KeyedIC::StubKind KeyedStoreIC::GetStubKind(Handle<JSObject> receiver,
|
| - Handle<Object> key,
|
| - Handle<Object> value) {
|
| +KeyedStoreIC::StubKind KeyedStoreIC::GetStubKind(Handle<JSObject> receiver,
|
| + Handle<Object> key,
|
| + Handle<Object> value) {
|
| ASSERT(key->IsSmi());
|
| int index = Smi::cast(*key)->value();
|
| bool allow_growth = receiver->IsJSArray() &&
|
| @@ -1877,12 +1798,12 @@ MaybeObject* KeyedStoreIC::Store(State state,
|
|
|
| if (key->IsSymbol()) {
|
| Handle<String> name = Handle<String>::cast(key);
|
| - return IC::Store(state,
|
| - strict_mode,
|
| - object,
|
| - name,
|
| - value,
|
| - JSReceiver::MAY_BE_STORE_FROM_KEYED);
|
| + return StoreIC::Store(state,
|
| + strict_mode,
|
| + object,
|
| + name,
|
| + value,
|
| + JSReceiver::MAY_BE_STORE_FROM_KEYED);
|
| }
|
|
|
| // Do not use ICs for objects that require access checks (including
|
| @@ -1904,7 +1825,7 @@ MaybeObject* KeyedStoreIC::Store(State state,
|
| } else if (miss_mode != MISS_FORCE_GENERIC) {
|
| if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
|
| StubKind stub_kind = GetStubKind(receiver, key, value);
|
| - stub = ComputeStub(receiver, stub_kind, strict_mode, stub);
|
| + stub = StoreElementStub(receiver, stub_kind, strict_mode);
|
| }
|
| } else {
|
| TRACE_GENERIC_IC("KeyedStoreIC", "force generic");
|
|
|