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

Unified Diff: src/stub-cache.cc

Issue 400523007: Cache IC handlers on the prototype's map if possible (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: addressed comment Created 6 years, 5 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/stub-cache.h ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/stub-cache.cc
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 0c9f4512326eaef114b11cbbf97b7564d5bdeea2..bc12dc836b5e8c64aefe4bcfd858ba9d1ad38036 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -33,13 +33,13 @@ void StubCache::Initialize() {
}
-Code* StubCache::Set(Name* name, Map* map, Code* code) {
- // Get the flags from the code.
- Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
+static Code::Flags CommonStubCacheChecks(Name* name, Map* map,
+ Code::Flags flags, Heap* heap) {
+ flags = Code::RemoveTypeAndHolderFromFlags(flags);
// Validate that the name does not move on scavenge, and that we
// can use identity checks instead of structural equality checks.
- ASSERT(!heap()->InNewSpace(name));
+ ASSERT(!heap->InNewSpace(name));
ASSERT(name->IsUniqueName());
// The state bits are not important to the hash function because
@@ -49,8 +49,16 @@ Code* StubCache::Set(Name* name, Map* map, Code* code) {
ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
- // Make sure that the code type is not included in the hash.
+ // Make sure that the code type and cache holder are not included in the hash.
ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
+ ASSERT(Code::ExtractCacheHolderFromFlags(flags) == 0);
+
+ return flags;
+}
+
+
+Code* StubCache::Set(Name* name, Map* map, Code* code) {
+ Code::Flags flags = CommonStubCacheChecks(name, map, code->flags(), heap());
// Compute the primary entry.
int primary_offset = PrimaryOffset(name, flags, map);
@@ -61,7 +69,8 @@ Code* StubCache::Set(Name* name, Map* map, Code* code) {
// secondary cache before overwriting it.
if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
Map* old_map = primary->map;
- Code::Flags old_flags = Code::RemoveTypeFromFlags(old_code->flags());
+ Code::Flags old_flags =
+ Code::RemoveTypeAndHolderFromFlags(old_code->flags());
int seed = PrimaryOffset(primary->key, old_flags, old_map);
int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
Entry* secondary = entry(secondary_, secondary_offset);
@@ -77,11 +86,25 @@ Code* StubCache::Set(Name* name, Map* map, Code* code) {
}
-Handle<Code> StubCache::FindIC(Handle<Name> name,
- Handle<Map> stub_holder,
- Code::Kind kind,
- ExtraICState extra_state,
- InlineCacheHolderFlag cache_holder) {
+Code* StubCache::Get(Name* name, Map* map, Code::Flags flags) {
+ flags = CommonStubCacheChecks(name, map, flags, heap());
+ int primary_offset = PrimaryOffset(name, flags, map);
+ Entry* primary = entry(primary_, primary_offset);
+ if (primary->key == name && primary->map == map) {
+ return primary->value;
+ }
+ int secondary_offset = SecondaryOffset(name, flags, primary_offset);
+ Entry* secondary = entry(secondary_, secondary_offset);
+ if (secondary->key == name && secondary->map == map) {
+ return secondary->value;
+ }
+ return NULL;
+}
+
+
+Handle<Code> StubCache::FindIC(Handle<Name> name, Handle<Map> stub_holder,
+ Code::Kind kind, ExtraICState extra_state,
+ CacheHolderFlag cache_holder) {
Code::Flags flags = Code::ComputeMonomorphicFlags(
kind, extra_state, cache_holder);
Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_);
@@ -90,10 +113,9 @@ Handle<Code> StubCache::FindIC(Handle<Name> name,
}
-Handle<Code> StubCache::FindHandler(Handle<Name> name,
- Handle<Map> stub_holder,
+Handle<Code> StubCache::FindHandler(Handle<Name> name, Handle<Map> stub_holder,
Code::Kind kind,
- InlineCacheHolderFlag cache_holder,
+ CacheHolderFlag cache_holder,
Code::StubType type) {
Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder);
@@ -109,16 +131,15 @@ Handle<Code> StubCache::ComputeMonomorphicIC(
Handle<HeapType> type,
Handle<Code> handler,
ExtraICState extra_ic_state) {
- InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type);
+ CacheHolderFlag flag;
+ Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate(), &flag);
- Handle<Map> stub_holder;
Handle<Code> ic;
// There are multiple string maps that all use the same prototype. That
// prototype cannot hold multiple handlers, one for each of the string maps,
// for a single name. Hence, turn off caching of the IC.
bool can_be_cached = !type->Is(HeapType::String());
if (can_be_cached) {
- stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate());
ic = FindIC(name, stub_holder, kind, extra_ic_state, flag);
if (!ic.is_null()) return ic;
}
@@ -147,36 +168,45 @@ Handle<Code> StubCache::ComputeMonomorphicIC(
Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
Handle<HeapType> type) {
- InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type);
- Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate());
+ Handle<Map> receiver_map = IC::TypeToMap(*type, isolate());
+ if (receiver_map->prototype()->IsNull()) {
+ // TODO(jkummerow/verwaest): If there is no prototype and the property
+ // is nonexistent, introduce a builtin to handle this (fast properties
+ // -> return undefined, dictionary properties -> do negative lookup).
+ return Handle<Code>();
+ }
+ CacheHolderFlag flag;
+ Handle<Map> stub_holder_map =
+ IC::GetHandlerCacheHolder(*type, false, isolate(), &flag);
+
// If no dictionary mode objects are present in the prototype chain, the load
// nonexistent IC stub can be shared for all names for a given map and we use
// the empty string for the map cache in that case. If there are dictionary
// mode objects involved, we need to do negative lookups in the stub and
// therefore the stub will be specific to the name.
- Handle<Map> current_map = stub_holder;
- Handle<Name> cache_name = current_map->is_dictionary_map()
- ? name : Handle<Name>::cast(isolate()->factory()->nonexistent_symbol());
- Handle<Object> next(current_map->prototype(), isolate());
- Handle<JSObject> last = Handle<JSObject>::null();
- while (!next->IsNull()) {
- last = Handle<JSObject>::cast(next);
- next = handle(current_map->prototype(), isolate());
- current_map = handle(Handle<HeapObject>::cast(next)->map());
+ Handle<Name> cache_name =
+ receiver_map->is_dictionary_map()
+ ? name
+ : Handle<Name>::cast(isolate()->factory()->nonexistent_symbol());
+ Handle<Map> current_map = stub_holder_map;
+ Handle<JSObject> last(JSObject::cast(receiver_map->prototype()));
+ while (true) {
if (current_map->is_dictionary_map()) cache_name = name;
+ if (current_map->prototype()->IsNull()) break;
+ last = handle(JSObject::cast(current_map->prototype()));
+ current_map = handle(last->map());
}
-
// Compile the stub that is either shared for all names or
// name specific if there are global objects involved.
- Handle<Code> handler = FindHandler(
- cache_name, stub_holder, Code::LOAD_IC, flag, Code::FAST);
+ Handle<Code> handler =
+ FindHandler(cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST);
if (!handler.is_null()) {
return handler;
}
LoadStubCompiler compiler(isolate_, kNoExtraICState, flag);
handler = compiler.CompileLoadNonexistent(type, last, cache_name);
- Map::UpdateCodeCache(stub_holder, cache_name, handler);
+ Map::UpdateCodeCache(stub_holder_map, cache_name, handler);
return handler;
}
@@ -203,8 +233,8 @@ Handle<Code> StubCache::ComputeKeyedStoreElement(
KeyedAccessStoreMode store_mode) {
ExtraICState extra_state =
KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode);
- Code::Flags flags = Code::ComputeMonomorphicFlags(
- Code::KEYED_STORE_IC, extra_state);
+ Code::Flags flags =
+ Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state);
ASSERT(store_mode == STANDARD_STORE ||
store_mode == STORE_AND_GROW_NO_TRANSITION ||
« no previous file with comments | « src/stub-cache.h ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698