Commit 400b8b8c authored by verwaest@chromium.org's avatar verwaest@chromium.org

Slight cleanup of UpdateCache code.

Review URL: https://chromiumcodereview.appspot.com/11737033

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13328 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent eb9a22cc
......@@ -712,7 +712,6 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
// Compute the number of arguments.
int argc = target()->arguments_count();
bool had_proto_failure = false;
Handle<Code> code;
if (state == UNINITIALIZED) {
// This is the first time we execute this inline cache.
......@@ -729,7 +728,7 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
TryRemoveInvalidPrototypeDependentStub(target(),
*object,
*name)) {
had_proto_failure = true;
state = MONOMORPHIC_PROTOTYPE_FAILURE;
code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
object, name);
} else {
......@@ -745,22 +744,36 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
if (code.is_null()) return;
// Patch the call site depending on the state of the cache.
if (state == UNINITIALIZED ||
state == PREMONOMORPHIC ||
state == MONOMORPHIC ||
state == MONOMORPHIC_PROTOTYPE_FAILURE) {
set_target(*code);
} else if (state == MEGAMORPHIC) {
// Cache code holding map should be consistent with
// 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()));
// Update the stub cache.
isolate()->stub_cache()->Set(*name, cache_object->map(), *code);
}
if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
switch (state) {
case UNINITIALIZED:
case MONOMORPHIC_PROTOTYPE_FAILURE:
case PREMONOMORPHIC:
set_target(*code);
break;
case MONOMORPHIC:
if (code->ic_state() != MONOMORPHIC) {
Map* map = target()->FindFirstMap();
if (map != NULL) {
isolate()->stub_cache()->Set(*name, map, target());
}
}
set_target(*code);
break;
case MEGAMORPHIC: {
// Cache code holding map should be consistent with
// 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()));
// Update the stub cache.
isolate()->stub_cache()->Set(*name, cache_object->map(), *code);
break;
}
case DEBUG_BREAK:
case DEBUG_PREPARE_STEP_IN:
break;
}
TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
name, state, target());
}
......@@ -1024,25 +1037,34 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
}
// Patch the call site depending on the state of the cache.
if (state == UNINITIALIZED ||
state == PREMONOMORPHIC ||
state == MONOMORPHIC_PROTOTYPE_FAILURE) {
set_target(*code);
} else if (state == MONOMORPHIC) {
// We are transitioning from monomorphic to megamorphic case.
// Place the current monomorphic stub and stub compiled for
// the receiver into stub cache.
Map* map = target()->FindFirstMap();
if (map != NULL) {
isolate()->stub_cache()->Set(*name, map, target());
}
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
switch (state) {
case UNINITIALIZED:
case PREMONOMORPHIC:
case MONOMORPHIC_PROTOTYPE_FAILURE:
set_target(*code);
break;
case MONOMORPHIC:
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.
Map* map = target()->FindFirstMap();
if (map != NULL) {
isolate()->stub_cache()->Set(*name, map, target());
}
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
set_target(*megamorphic_stub());
} else if (state == MEGAMORPHIC) {
// Cache code holding map should be consistent with
// GenerateMonomorphicCacheProbe.
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
set_target(*megamorphic_stub());
}
break;
case MEGAMORPHIC:
// Cache code holding map should be consistent with
// GenerateMonomorphicCacheProbe.
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
break;
case DEBUG_BREAK:
case DEBUG_PREPARE_STEP_IN:
break;
}
TRACE_IC("LoadIC", name, state, target());
......@@ -1296,13 +1318,25 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
}
}
// Patch the call site depending on the state of the cache. Make
// sure to always rewrite from monomorphic to megamorphic.
ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
set_target(*code);
} else if (state == MONOMORPHIC) {
set_target(*megamorphic_stub());
// Patch the call site depending on the state of the cache.
switch (state) {
case UNINITIALIZED:
case PREMONOMORPHIC:
set_target(*code);
break;
case MONOMORPHIC:
// Only move to megamorphic if the target changes.
if (target() != *code) {
set_target(*megamorphic_stub());
}
break;
case MEGAMORPHIC:
case DEBUG_BREAK:
case DEBUG_PREPARE_STEP_IN:
break;
case MONOMORPHIC_PROTOTYPE_FAILURE:
UNREACHABLE();
break;
}
TRACE_IC("KeyedLoadIC", name, state, target());
......@@ -1547,18 +1581,35 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
}
// Patch the call site depending on the state of the cache.
if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
set_target(*code);
} else if (state == MONOMORPHIC) {
// Only move to megamorphic if the target changes.
if (target() != *code) {
set_target((strict_mode == kStrictMode)
? megamorphic_stub_strict()
: megamorphic_stub());
}
} else if (state == MEGAMORPHIC) {
// Update the stub cache.
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
switch (state) {
case UNINITIALIZED:
case PREMONOMORPHIC:
case MONOMORPHIC_PROTOTYPE_FAILURE:
set_target(*code);
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.
Map* map = target()->FindFirstMap();
if (map != NULL) {
isolate()->stub_cache()->Set(*name, map, target());
}
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
set_target((strict_mode == kStrictMode)
? megamorphic_stub_strict()
: megamorphic_stub());
}
break;
case MEGAMORPHIC:
// Update the stub cache.
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
break;
case DEBUG_BREAK:
case DEBUG_PREPARE_STEP_IN:
break;
}
TRACE_IC("StoreIC", name, state, target());
......@@ -1585,18 +1636,28 @@ void KeyedIC::GetReceiverMapsForStub(Handle<Code> 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()) {
if (stub->ic_state() == MONOMORPHIC) {
result->Add(Handle<Map>(stub->FindFirstMap()));
} else {
ASSERT(stub->ic_state() == MEGAMORPHIC);
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));
switch (stub->ic_state()) {
case MONOMORPHIC:
result->Add(Handle<Map>(stub->FindFirstMap()));
break;
case MEGAMORPHIC: {
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 UNINITIALIZED:
case PREMONOMORPHIC:
case MONOMORPHIC_PROTOTYPE_FAILURE:
case DEBUG_BREAK:
case DEBUG_PREPARE_STEP_IN:
UNREACHABLE();
break;
}
}
}
......@@ -2024,15 +2085,27 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
ASSERT(!code.is_null());
// Patch the call site depending on the state of the cache. Make
// sure to always rewrite from monomorphic to megamorphic.
ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
set_target(*code);
} else if (state == MONOMORPHIC) {
set_target((strict_mode == kStrictMode)
? *megamorphic_stub_strict()
: *megamorphic_stub());
// Patch the call site depending on the state of the cache.
switch (state) {
case UNINITIALIZED:
case PREMONOMORPHIC:
set_target(*code);
break;
case MONOMORPHIC:
// Only move to megamorphic if the target changes.
if (target() != *code) {
set_target((strict_mode == kStrictMode)
? *megamorphic_stub_strict()
: *megamorphic_stub());
}
break;
case MEGAMORPHIC:
case DEBUG_BREAK:
case DEBUG_PREPARE_STEP_IN:
break;
case MONOMORPHIC_PROTOTYPE_FAILURE:
UNREACHABLE();
break;
}
TRACE_IC("KeyedStoreIC", name, state, target());
......@@ -2057,13 +2130,12 @@ RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
extra_ic_state,
args.at<Object>(0),
args.at<String>(1));
// Result could be a function or a failure.
JSFunction* raw_function = NULL;
JSFunction* raw_function;
if (!maybe_result->To(&raw_function)) return maybe_result;
// The first time the inline cache is updated may be the first time the
// function it references gets called. If the function is lazily compiled
// then the first call will trigger a compilation. We check for this case
// function it references gets called. If the function is lazily compiled
// then the first call will trigger a compilation. We check for this case
// and we do the compilation immediately, instead of waiting for the stub
// currently attached to the JSFunction object to trigger compilation.
if (raw_function->is_compiled()) return raw_function;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment