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

Unified Diff: src/ic.cc

Issue 12340112: Polymorphism support for load IC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Added ARM port, introduced GenerateTailCall Created 7 years, 10 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/log.h » ('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 b330038c704a50d8e744835ab8394cc3ba030615..7fdf6be31fbe5f36f53a22182371963d5e212be1 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -935,6 +935,71 @@ MaybeObject* LoadIC::Load(State state,
}
+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;
+}
+
+
+bool IC::UpdatePolymorphicIC(State state,
+ StrictModeFlag strict_mode,
+ Handle<JSObject> receiver,
+ Handle<String> name,
+ Handle<Code> code) {
+ if (code->type() == Code::NORMAL) return false;
+ if (target()->ic_state() == MONOMORPHIC &&
+ target()->type() == Code::NORMAL) {
+ return false;
+ }
+ MapHandleList receiver_maps;
+ CodeHandleList handlers;
+ target()->FindAllMaps(&receiver_maps);
+ int number_of_maps = receiver_maps.length();
+ if (number_of_maps == 0 || number_of_maps >= 4) return false;
+
+ target()->FindAllCode(&handlers, receiver_maps.length());
+
+ if (!AddOneReceiverMapIfMissing(&receiver_maps,
+ Handle<Map>(receiver->map()))) {
+ return false;
+ }
+
+ handlers.Add(code);
+ Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
+ &receiver_maps, &handlers, name);
+ set_target(*ic);
+ return true;
+}
+
+
+void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
+ Handle<Code> handler,
+ Handle<String> name) {
+ if (handler->type() == Code::NORMAL) return set_target(*handler);
+ Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
+ receiver, handler, name);
+ set_target(*ic);
+}
+
+
+void KeyedLoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
+ Handle<Code> handler,
+ Handle<String> name) {
+ if (handler->type() == Code::NORMAL) return set_target(*handler);
+ Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedMonomorphicIC(
+ receiver, handler, name);
+ set_target(*ic);
+}
+
+
void IC::PatchCache(State state,
StrictModeFlag strict_mode,
Handle<JSObject> receiver,
@@ -944,14 +1009,18 @@ void IC::PatchCache(State state,
case UNINITIALIZED:
case PREMONOMORPHIC:
case MONOMORPHIC_PROTOTYPE_FAILURE:
- set_target(*code);
+ UpdateMonomorphicIC(receiver, code, name);
break;
case MONOMORPHIC:
// Only move to megamorphic if the target changes.
if (target() != *code) {
- // We are transitioning from monomorphic to megamorphic case.
- // Place the current monomorphic stub and stub compiled for
- // the receiver into stub cache.
+ if (target()->is_load_stub()) {
+ if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) {
+ break;
+ }
+ }
+ // We are transitioning from monomorphic to megamorphic case. Place the
+ // stub compiled for the receiver into stub cache.
Map* map = target()->FindFirstMap();
if (map != NULL) {
UpdateMegamorphicCache(map, *name, target());
@@ -967,14 +1036,26 @@ void IC::PatchCache(State state,
UpdateMegamorphicCache(receiver->map(), *name, *code);
break;
case POLYMORPHIC:
- // When trying to patch a polymorphic stub with anything other than
- // another polymorphic stub, go generic.
- // TODO(verwaest): Currently we always go generic since no polymorphic
- // stubs enter this code path. Replace with proper updating once named
- // load/store can also be polymorphic.
- set_target((strict_mode == kStrictMode)
- ? *generic_stub_strict()
- : *generic_stub());
+ if (target()->is_load_stub()) {
+ if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) {
+ break;
+ }
+ MapHandleList receiver_maps;
+ CodeHandleList handlers;
+ target()->FindAllMaps(&receiver_maps);
+ target()->FindAllCode(&handlers, receiver_maps.length());
+ for (int i = 0; i < receiver_maps.length(); i++) {
+ UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
+ }
+ UpdateMegamorphicCache(receiver->map(), *name, *code);
+ set_target(*megamorphic_stub());
+ } else {
+ // When trying to patch a polymorphic keyed load/store element stub
+ // with anything other than another polymorphic stub, go generic.
+ set_target((strict_mode == kStrictMode)
+ ? *generic_stub_strict()
+ : *generic_stub());
+ }
break;
case DEBUG_STUB:
break;
@@ -985,6 +1066,42 @@ void IC::PatchCache(State state,
}
+static void GetReceiverMapsForStub(Handle<Code> stub,
+ MapHandleList* result) {
+ ASSERT(stub->is_inline_cache_stub());
+ switch (stub->ic_state()) {
+ case MONOMORPHIC: {
+ Map* map = stub->FindFirstMap();
+ if (map != NULL) {
+ result->Add(Handle<Map>(map));
+ }
+ 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(), stub->GetIsolate());
+ if (object->IsString()) break;
+ ASSERT(object->IsMap());
+ AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
+ }
+ break;
+ }
+ case MEGAMORPHIC:
+ break;
+ case UNINITIALIZED:
+ case PREMONOMORPHIC:
+ case MONOMORPHIC_PROTOTYPE_FAILURE:
+ case GENERIC:
+ case DEBUG_STUB:
+ UNREACHABLE();
+ break;
+ }
+}
+
+
void LoadIC::UpdateCaches(LookupResult* lookup,
State state,
Handle<Object> object,
@@ -1004,7 +1121,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
// setting the monomorphic state.
code = pre_monomorphic_stub();
} else {
- code = ComputeLoadMonomorphic(lookup, receiver, name);
+ code = ComputeLoadHandler(lookup, receiver, name);
if (code.is_null()) return;
}
@@ -1020,9 +1137,9 @@ void IC::UpdateMegamorphicCache(Map* map, String* name, Code* code) {
}
-Handle<Code> LoadIC::ComputeLoadMonomorphic(LookupResult* lookup,
- Handle<JSObject> receiver,
- Handle<String> name) {
+Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
+ Handle<JSObject> receiver,
+ Handle<String> name) {
if (!lookup->IsProperty()) {
// Nonexistent property. The result is undefined.
return isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
@@ -1051,7 +1168,7 @@ Handle<Code> LoadIC::ComputeLoadMonomorphic(LookupResult* lookup,
// property must be found in the receiver for the stub to be
// applicable.
if (!holder.is_identical_to(receiver)) break;
- return isolate()->stub_cache()->ComputeLoadNormal();
+ return isolate()->stub_cache()->ComputeLoadNormal(name, receiver);
case CALLBACKS: {
Handle<Object> callback(lookup->GetCallbackObject(), isolate());
if (callback->IsExecutableAccessorInfo()) {
@@ -1107,56 +1224,6 @@ 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());
- ASSERT(stub->is_keyed_load_stub() || stub->is_keyed_store_stub());
- switch (stub->ic_state()) {
- case MONOMORPHIC: {
- Map* map = stub->FindFirstMap();
- if (map != NULL) {
- result->Add(Handle<Map>(map));
- }
- 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(), stub->GetIsolate());
- ASSERT(object->IsMap());
- AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
- }
- break;
- }
- case MEGAMORPHIC:
- break;
- case UNINITIALIZED:
- case PREMONOMORPHIC:
- case MONOMORPHIC_PROTOTYPE_FAILURE:
- case GENERIC:
- case DEBUG_STUB:
- UNREACHABLE();
- break;
- }
-}
-
-
Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
State ic_state = target()->ic_state();
@@ -1268,9 +1335,9 @@ MaybeObject* KeyedLoadIC::Load(State state,
}
-Handle<Code> KeyedLoadIC::ComputeLoadMonomorphic(LookupResult* lookup,
- Handle<JSObject> receiver,
- Handle<String> name) {
+Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
+ Handle<JSObject> receiver,
+ Handle<String> name) {
// Bail out if we didn't find a result.
if (!lookup->IsProperty()) return Handle<Code>::null();
« no previous file with comments | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698