Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Unified Diff: src/ic.cc

Issue 8166017: Track elements_kind transitions in KeyedStoreICs. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix nits Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ic.h ('k') | src/objects.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ic.cc
diff --git a/src/ic.cc b/src/ic.cc
index 50b1cde888d769b675d6eee89d5a27819d77c1c0..92c2681a2ffbbb938669155852d993df8359e054 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1243,7 +1243,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
stub = indexed_interceptor_stub();
} else if (key->IsSmi() && (target() != non_strict_arguments_stub())) {
MaybeObject* maybe_stub = ComputeStub(receiver,
- false,
+ LOAD,
kNonStrictMode,
stub);
stub = maybe_stub->IsFailure() ?
@@ -1593,14 +1593,15 @@ void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) {
MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
- bool is_store,
+ StubKind stub_kind,
StrictModeFlag strict_mode,
Code* generic_stub) {
State ic_state = target()->ic_state();
- if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
+ if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) &&
+ !IsTransitionStubKind(stub_kind)) {
Code* monomorphic_stub;
MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver,
- is_store,
+ stub_kind,
strict_mode,
generic_stub);
if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
@@ -1619,8 +1620,17 @@ MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
// 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 (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
+ target_receiver_maps.Add(receiver->map());
+ } else {
+ GetReceiverMapsForStub(target(), &target_receiver_maps);
+ }
+ Map* new_map = receiver->map();
+ if (IsTransitionStubKind(stub_kind)) {
+ MaybeObject* maybe_map = ComputeTransitionedMap(receiver, stub_kind);
+ if (!maybe_map->To(&new_map)) return maybe_map;
+ }
+ if (!AddOneReceiverMapIfMissing(&target_receiver_maps, new_map)) {
// If the miss wasn't due to an unseen map, a MEGAMORPHIC stub
// won't help, use the generic stub.
return generic_stub;
@@ -1642,21 +1652,14 @@ MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
ASSERT(maybe_cached_stub->IsCode());
return Code::cast(maybe_cached_stub);
}
- // Collect MONOMORPHIC stubs for all target_receiver_maps.
- CodeList handler_ics(target_receiver_maps.length());
- for (int i = 0; i < target_receiver_maps.length(); ++i) {
- Map* receiver_map(target_receiver_maps.at(i));
- MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
- receiver_map, strict_mode);
- Code* cached_stub;
- if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
- handler_ics.Add(cached_stub);
+ MaybeObject* maybe_stub = NULL;
+ if (IsTransitionStubKind(stub_kind)) {
+ maybe_stub = ComputePolymorphicStubWithTransition(
+ receiver, &target_receiver_maps, new_map, strict_mode);
+ } else {
+ maybe_stub = ComputePolymorphicStub(&target_receiver_maps, strict_mode);
}
- // Build the MEGAMORPHIC stub.
Code* stub;
- MaybeObject* maybe_stub = ConstructMegamorphicStub(&target_receiver_maps,
- &handler_ics,
- strict_mode);
if (!maybe_stub->To(&stub)) return maybe_stub;
MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub);
if (maybe_update->IsFailure()) return maybe_update;
@@ -1684,7 +1687,7 @@ MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
- bool is_store,
+ StubKind stub_kind,
StrictModeFlag strict_mode,
Code* generic_stub) {
Code* result = NULL;
@@ -1695,7 +1698,7 @@ MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
receiver->HasDictionaryElements()) {
MaybeObject* maybe_stub =
isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement(
- receiver, is_store, strict_mode);
+ receiver, stub_kind, strict_mode);
if (!maybe_stub->To(&result)) return maybe_stub;
} else {
result = generic_stub;
@@ -1704,6 +1707,60 @@ MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
}
+MaybeObject* KeyedIC::ComputePolymorphicStubWithTransition(
+ JSObject* receiver,
+ MapList* receiver_maps,
+ Map* new_map,
+ StrictModeFlag strict_mode) {
+ Map* existing_transitionable_map = NULL;
+ for (int i = 0; i < receiver_maps->length(); ++i) {
+ Map* map = receiver_maps->at(i);
+ if (map != receiver->map() && map != new_map) {
+ existing_transitionable_map = map;
+ break;
+ }
+ }
+ KeyedStoreStubCompiler compiler(strict_mode);
+ return compiler.CompileStoreElementWithTransition(
+ new_map,
+ receiver->map(),
+ existing_transitionable_map);
+}
+
+
+MaybeObject* KeyedIC::ComputePolymorphicStub(
+ MapList* receiver_maps,
+ StrictModeFlag strict_mode) {
+ // Collect MONOMORPHIC stubs for all target_receiver_maps.
+ CodeList handler_ics(receiver_maps->length());
+ for (int i = 0; i < receiver_maps->length(); ++i) {
+ Map* receiver_map(receiver_maps->at(i));
+ MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
+ receiver_map, strict_mode);
+ Code* cached_stub;
+ if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
+ handler_ics.Add(cached_stub);
+ }
+ // Build the MEGAMORPHIC stub.
+ return ConstructMegamorphicStub(receiver_maps, &handler_ics, strict_mode);
+}
+
+
+MaybeObject* KeyedIC::ComputeTransitionedMap(JSObject* receiver,
+ StubKind stub_kind) {
+ switch (stub_kind) {
+ case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT:
+ case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT:
+ return receiver->GetElementsTransitionMap(FAST_ELEMENTS);
+ case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE:
+ return receiver->GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS);
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
MaybeObject* KeyedStoreIC::GetElementStubWithoutMapCheck(
bool is_js_array,
ElementsKind elements_kind) {
@@ -1786,9 +1843,21 @@ MaybeObject* KeyedStoreIC::Store(State state,
stub = non_strict_arguments_stub();
} else if (!force_generic) {
if (key->IsSmi() && (target() != non_strict_arguments_stub())) {
+ StubKind stub_kind = STORE_NO_TRANSITION;
+ if (receiver->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) {
+ if (value->IsHeapNumber()) {
+ stub_kind = STORE_TRANSITION_SMI_TO_DOUBLE;
+ } else if (value->IsHeapObject()) {
+ stub_kind = STORE_TRANSITION_SMI_TO_OBJECT;
+ }
+ } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) {
+ if (!value->IsSmi() && !value->IsHeapNumber()) {
+ stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT;
+ }
+ }
HandleScope scope(isolate());
MaybeObject* maybe_stub = ComputeStub(receiver,
- true,
+ stub_kind,
strict_mode,
stub);
stub = maybe_stub->IsFailure() ?
« no previous file with comments | « src/ic.h ('k') | src/objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698