Commit 6a3d1868 authored by ager@chromium.org's avatar ager@chromium.org

Revert revision 331. The propagation of monomorphic prototype failure

information does not work.  In certains situations, it will keep
alternating between unrelated monomorphic states instead of going
megamorphic.
Review URL: http://codereview.chromium.org/2959

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@338 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d6ae7d4d
...@@ -61,7 +61,7 @@ void IC::TraceIC(const char* type, ...@@ -61,7 +61,7 @@ void IC::TraceIC(const char* type,
State old_state, State old_state,
Code* new_target) { Code* new_target) {
if (FLAG_trace_ic) { if (FLAG_trace_ic) {
State new_state = new_target->ic_state(); State new_state = StateFrom(new_target, Heap::undefined_value());
PrintF("[%s (%c->%c) ", type, PrintF("[%s (%c->%c) ", type,
TransitionMarkFromState(old_state), TransitionMarkFromState(old_state),
TransitionMarkFromState(new_state)); TransitionMarkFromState(new_state));
...@@ -127,16 +127,11 @@ Address IC::OriginalCodeAddress() { ...@@ -127,16 +127,11 @@ Address IC::OriginalCodeAddress() {
} }
IC::State IC::ComputeCacheState(Code* target, Object* receiver, IC::State IC::StateFrom(Code* target, Object* receiver) {
Object* name, Object** new_target) { IC::State state = target->ic_state();
// Get the raw state from the target.
State target_state = target->ic_state();
// Assume that no new target exists in the cache. if (state != MONOMORPHIC) return state;
*new_target = Heap::undefined_value(); if (receiver->IsUndefined() || receiver->IsNull()) return state;
if (target_state != MONOMORPHIC) return target_state;
if (receiver->IsUndefined() || receiver->IsNull()) return target_state;
Map* map = GetCodeCacheMapForObject(receiver); Map* map = GetCodeCacheMapForObject(receiver);
...@@ -148,14 +143,8 @@ IC::State IC::ComputeCacheState(Code* target, Object* receiver, ...@@ -148,14 +143,8 @@ IC::State IC::ComputeCacheState(Code* target, Object* receiver,
// the receiver map's code cache. Therefore, if the current target // the receiver map's code cache. Therefore, if the current target
// is in the receiver map's code cache, the inline cache failed due // is in the receiver map's code cache, the inline cache failed due
// to prototype check failure. // to prototype check failure.
int index = -1; int index = map->IndexInCodeCache(target);
Object* code = NULL; if (index >= 0) {
if (name->IsString()) {
code = map->FindIndexInCodeCache(String::cast(name),
target->flags(),
&index);
}
if (index >= 0 && code == target) {
// For keyed load/store, the most likely cause of cache failure is // For keyed load/store, the most likely cause of cache failure is
// that the key has changed. We do not distinguish between // that the key has changed. We do not distinguish between
// prototype and non-prototype failures for keyed access. // prototype and non-prototype failures for keyed access.
...@@ -183,7 +172,6 @@ IC::State IC::ComputeCacheState(Code* target, Object* receiver, ...@@ -183,7 +172,6 @@ IC::State IC::ComputeCacheState(Code* target, Object* receiver,
return UNINITIALIZED; return UNINITIALIZED;
} }
*new_target = code;
return MONOMORPHIC; return MONOMORPHIC;
} }
...@@ -287,7 +275,8 @@ Object* CallIC::TryCallAsFunction(Object* object) { ...@@ -287,7 +275,8 @@ Object* CallIC::TryCallAsFunction(Object* object) {
} }
Object* CallIC::LoadFunction(Handle<Object> object, Object* CallIC::LoadFunction(State state,
Handle<Object> object,
Handle<String> name) { Handle<String> name) {
// If the object is undefined or null it's illegal to try to get any // If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case. // of its properties; throw a TypeError in that case.
...@@ -326,7 +315,7 @@ Object* CallIC::LoadFunction(Handle<Object> object, ...@@ -326,7 +315,7 @@ Object* CallIC::LoadFunction(Handle<Object> object,
// Lookup is valid: Update inline cache and stub cache. // Lookup is valid: Update inline cache and stub cache.
if (FLAG_use_ic && lookup.IsLoaded()) { if (FLAG_use_ic && lookup.IsLoaded()) {
UpdateCaches(&lookup, object, name); UpdateCaches(&lookup, state, object, name);
} }
if (lookup.type() == INTERCEPTOR) { if (lookup.type() == INTERCEPTOR) {
...@@ -385,6 +374,7 @@ Object* CallIC::LoadFunction(Handle<Object> object, ...@@ -385,6 +374,7 @@ Object* CallIC::LoadFunction(Handle<Object> object,
void CallIC::UpdateCaches(LookupResult* lookup, void CallIC::UpdateCaches(LookupResult* lookup,
State state,
Handle<Object> object, Handle<Object> object,
Handle<String> name) { Handle<String> name) {
ASSERT(lookup->IsLoaded()); ASSERT(lookup->IsLoaded());
...@@ -393,55 +383,52 @@ void CallIC::UpdateCaches(LookupResult* lookup, ...@@ -393,55 +383,52 @@ void CallIC::UpdateCaches(LookupResult* lookup,
// Compute the number of arguments. // Compute the number of arguments.
int argc = target()->arguments_count(); int argc = target()->arguments_count();
Object* code = NULL;
Object* code = Heap::undefined_value(); if (state == UNINITIALIZED) {
State state = ComputeCacheState(target(), *object, *name, &code); // This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay
switch (state) { // setting the monomorphic state.
case UNINITIALIZED: code = StubCache::ComputeCallPreMonomorphic(argc);
code = StubCache::ComputeCallPreMonomorphic(argc); } else if (state == MONOMORPHIC) {
break; code = StubCache::ComputeCallMegamorphic(argc);
case MONOMORPHIC: } else {
if (code->IsUndefined()) code = StubCache::ComputeCallMegamorphic(argc); // Compute monomorphic stub.
break; switch (lookup->type()) {
default: case FIELD: {
// Compute monomorphic stub. int index = lookup->GetFieldIndex();
switch (lookup->type()) { code = StubCache::ComputeCallField(argc, *name, *object,
case FIELD: { lookup->holder(), index);
int index = lookup->GetFieldIndex(); break;
code = StubCache::ComputeCallField(argc, *name, *object,
lookup->holder(), index);
break;
}
case CONSTANT_FUNCTION: {
// Get the constant function and compute the code stub for this
// call; used for rewriting to monomorphic state and making sure
// that the code stub is in the stub cache.
JSFunction* function = lookup->GetConstantFunction();
code = StubCache::ComputeCallConstant(argc, *name, *object,
lookup->holder(), function);
break;
}
case NORMAL: {
// There is only one shared stub for calling normalized
// properties. It does not traverse the prototype chain, so the
// property must be found in the receiver for the stub to be
// applicable.
if (!object->IsJSObject()) return;
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
if (lookup->holder() != *receiver) return;
code = StubCache::ComputeCallNormal(argc, *name, *receiver);
break;
}
case INTERCEPTOR: {
code = StubCache::ComputeCallInterceptor(argc, *name, *object,
lookup->holder());
break;
}
default:
return;
} }
break; case CONSTANT_FUNCTION: {
// Get the constant function and compute the code stub for this
// call; used for rewriting to monomorphic state and making sure
// that the code stub is in the stub cache.
JSFunction* function = lookup->GetConstantFunction();
code = StubCache::ComputeCallConstant(argc, *name, *object,
lookup->holder(), function);
break;
}
case NORMAL: {
// There is only one shared stub for calling normalized
// properties. It does not traverse the prototype chain, so the
// property must be found in the receiver for the stub to be
// applicable.
if (!object->IsJSObject()) return;
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
if (lookup->holder() != *receiver) return;
code = StubCache::ComputeCallNormal(argc, *name, *receiver);
break;
}
case INTERCEPTOR: {
code = StubCache::ComputeCallInterceptor(argc, *name, *object,
lookup->holder());
break;
}
default:
return;
}
} }
// If we're unable to compute the stub (not enough memory left), we // If we're unable to compute the stub (not enough memory left), we
...@@ -460,7 +447,7 @@ void CallIC::UpdateCaches(LookupResult* lookup, ...@@ -460,7 +447,7 @@ void CallIC::UpdateCaches(LookupResult* lookup,
} }
Object* LoadIC::Load(Handle<Object> object, Handle<String> name) { Object* 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 // If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case. // of its properties; throw a TypeError in that case.
if (object->IsUndefined() || object->IsNull()) { if (object->IsUndefined() || object->IsNull()) {
...@@ -533,7 +520,7 @@ Object* LoadIC::Load(Handle<Object> object, Handle<String> name) { ...@@ -533,7 +520,7 @@ Object* LoadIC::Load(Handle<Object> object, Handle<String> name) {
// Update inline cache and stub cache. // Update inline cache and stub cache.
if (FLAG_use_ic && lookup.IsLoaded()) { if (FLAG_use_ic && lookup.IsLoaded()) {
UpdateCaches(&lookup, object, name); UpdateCaches(&lookup, state, object, name);
} }
PropertyAttributes attr; PropertyAttributes attr;
...@@ -555,6 +542,7 @@ Object* LoadIC::Load(Handle<Object> object, Handle<String> name) { ...@@ -555,6 +542,7 @@ Object* LoadIC::Load(Handle<Object> object, Handle<String> name) {
void LoadIC::UpdateCaches(LookupResult* lookup, void LoadIC::UpdateCaches(LookupResult* lookup,
State state,
Handle<Object> object, Handle<Object> object,
Handle<String> name) { Handle<String> name) {
ASSERT(lookup->IsLoaded()); ASSERT(lookup->IsLoaded());
...@@ -567,15 +555,13 @@ void LoadIC::UpdateCaches(LookupResult* lookup, ...@@ -567,15 +555,13 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
Handle<JSObject> receiver = Handle<JSObject>::cast(object); Handle<JSObject> receiver = Handle<JSObject>::cast(object);
// Compute the code stub for this load. // Compute the code stub for this load.
Object* code = Heap::undefined_value(); Object* code = NULL;
State state = ComputeCacheState(target(), *object, *name, &code);
if (state == UNINITIALIZED) { if (state == UNINITIALIZED) {
// This is the first time we execute this inline cache. // This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay // Set the target to the pre monomorphic stub to delay
// setting the monomorphic state. // setting the monomorphic state.
code = pre_monomorphic_stub(); code = pre_monomorphic_stub();
} else if (state != MONOMORPHIC) { } else {
// Compute monomorphic stub. // Compute monomorphic stub.
switch (lookup->type()) { switch (lookup->type()) {
case FIELD: { case FIELD: {
...@@ -616,20 +602,18 @@ void LoadIC::UpdateCaches(LookupResult* lookup, ...@@ -616,20 +602,18 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
default: default:
return; return;
} }
// If we're unable to compute the stub (not enough memory left), we
// simply avoid updating the caches.
if (code->IsFailure()) return;
} }
// If we're unable to compute the stub (not enough memory left), we
// simply avoid updating the caches.
if (code->IsFailure()) return;
// Patch the call site depending on the state of the cache. // Patch the call site depending on the state of the cache.
if (state == UNINITIALIZED || state == PREMONOMORPHIC || if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
state == MONOMORPHIC_PROTOTYPE_FAILURE) { state == MONOMORPHIC_PROTOTYPE_FAILURE) {
set_target(Code::cast(code)); set_target(Code::cast(code));
} else if (state == MONOMORPHIC && code->IsUndefined()) {
set_target(megamorphic_stub());
} else if (state == MONOMORPHIC) { } else if (state == MONOMORPHIC) {
set_target(Code::cast(code)); set_target(megamorphic_stub());
} }
#ifdef DEBUG #ifdef DEBUG
...@@ -638,7 +622,8 @@ void LoadIC::UpdateCaches(LookupResult* lookup, ...@@ -638,7 +622,8 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
} }
Object* KeyedLoadIC::Load(Handle<Object> object, Object* KeyedLoadIC::Load(State state,
Handle<Object> object,
Handle<Object> key) { Handle<Object> key) {
if (key->IsSymbol()) { if (key->IsSymbol()) {
Handle<String> name = Handle<String>::cast(key); Handle<String> name = Handle<String>::cast(key);
...@@ -666,7 +651,7 @@ Object* KeyedLoadIC::Load(Handle<Object> object, ...@@ -666,7 +651,7 @@ Object* KeyedLoadIC::Load(Handle<Object> object,
if (code->IsFailure()) return code; if (code->IsFailure()) return code;
set_target(Code::cast(code)); set_target(Code::cast(code));
#ifdef DEBUG #ifdef DEBUG
if (FLAG_trace_ic) PrintF("[KeyedLoadIC : +#length /string]\n"); TraceIC("KeyedLoadIC", name, state, target());
#endif #endif
return Smi::FromInt(string->length()); return Smi::FromInt(string->length());
} }
...@@ -678,7 +663,7 @@ Object* KeyedLoadIC::Load(Handle<Object> object, ...@@ -678,7 +663,7 @@ Object* KeyedLoadIC::Load(Handle<Object> object,
if (code->IsFailure()) return code; if (code->IsFailure()) return code;
set_target(Code::cast(code)); set_target(Code::cast(code));
#ifdef DEBUG #ifdef DEBUG
if (FLAG_trace_ic) PrintF("[KeyedLoadIC : +#length /array]\n"); TraceIC("KeyedLoadIC", name, state, target());
#endif #endif
return JSArray::cast(*object)->length(); return JSArray::cast(*object)->length();
} }
...@@ -691,7 +676,7 @@ Object* KeyedLoadIC::Load(Handle<Object> object, ...@@ -691,7 +676,7 @@ Object* KeyedLoadIC::Load(Handle<Object> object,
if (code->IsFailure()) return code; if (code->IsFailure()) return code;
set_target(Code::cast(code)); set_target(Code::cast(code));
#ifdef DEBUG #ifdef DEBUG
if (FLAG_trace_ic) PrintF("[KeyedLoadIC : +#prototype /function]\n"); TraceIC("KeyedLoadIC", name, state, target());
#endif #endif
return Accessors::FunctionGetPrototype(*object, 0); return Accessors::FunctionGetPrototype(*object, 0);
} }
...@@ -720,7 +705,7 @@ Object* KeyedLoadIC::Load(Handle<Object> object, ...@@ -720,7 +705,7 @@ Object* KeyedLoadIC::Load(Handle<Object> object,
// Update the inline cache. // Update the inline cache.
if (FLAG_use_ic && lookup.IsLoaded()) { if (FLAG_use_ic && lookup.IsLoaded()) {
UpdateCaches(&lookup, object, name); UpdateCaches(&lookup, state, object, name);
} }
PropertyAttributes attr; PropertyAttributes attr;
...@@ -750,9 +735,8 @@ Object* KeyedLoadIC::Load(Handle<Object> object, ...@@ -750,9 +735,8 @@ Object* KeyedLoadIC::Load(Handle<Object> object,
} }
void KeyedLoadIC::UpdateCaches(LookupResult* lookup, void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
Handle<Object> object, Handle<Object> object, Handle<String> name) {
Handle<String> name) {
ASSERT(lookup->IsLoaded()); ASSERT(lookup->IsLoaded());
// Bail out if we didn't find a result. // Bail out if we didn't find a result.
if (!lookup->IsValid() || !lookup->IsCacheable()) return; if (!lookup->IsValid() || !lookup->IsCacheable()) return;
...@@ -760,11 +744,9 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, ...@@ -760,11 +744,9 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
if (!object->IsJSObject()) return; if (!object->IsJSObject()) return;
Handle<JSObject> receiver = Handle<JSObject>::cast(object); Handle<JSObject> receiver = Handle<JSObject>::cast(object);
// Compute the state of the current inline cache.
Object* code = Heap::undefined_value();
State state = ComputeCacheState(target(), *object, *name, &code);
// Compute the code stub for this load. // Compute the code stub for this load.
Object* code = NULL;
if (state == UNINITIALIZED) { if (state == UNINITIALIZED) {
// This is the first time we execute this inline cache. // This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay // Set the target to the pre monomorphic stub to delay
...@@ -827,7 +809,8 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, ...@@ -827,7 +809,8 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
} }
Object* StoreIC::Store(Handle<Object> object, Object* StoreIC::Store(State state,
Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> value) { Handle<Object> value) {
// If the object is undefined or null it's illegal to try to set any // If the object is undefined or null it's illegal to try to set any
...@@ -855,7 +838,7 @@ Object* StoreIC::Store(Handle<Object> object, ...@@ -855,7 +838,7 @@ Object* StoreIC::Store(Handle<Object> object,
// Update inline cache and stub cache. // Update inline cache and stub cache.
if (FLAG_use_ic && lookup.IsLoaded()) { if (FLAG_use_ic && lookup.IsLoaded()) {
UpdateCaches(&lookup, receiver, name, value); UpdateCaches(&lookup, state, receiver, name, value);
} }
// Set the property. // Set the property.
...@@ -864,6 +847,7 @@ Object* StoreIC::Store(Handle<Object> object, ...@@ -864,6 +847,7 @@ Object* StoreIC::Store(Handle<Object> object,
void StoreIC::UpdateCaches(LookupResult* lookup, void StoreIC::UpdateCaches(LookupResult* lookup,
State state,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<String> name, Handle<String> name,
Handle<Object> value) { Handle<Object> value) {
...@@ -880,13 +864,10 @@ void StoreIC::UpdateCaches(LookupResult* lookup, ...@@ -880,13 +864,10 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
// current state. // current state.
PropertyType type = lookup->type(); PropertyType type = lookup->type();
// Compute the state of the current inline cache.
Object* code = Heap::undefined_value();
State state = ComputeCacheState(target(), *receiver, *name, &code);
// Compute the code stub for this store; used for rewriting to // Compute the code stub for this store; used for rewriting to
// monomorphic state and making sure that the code stub is in the // monomorphic state and making sure that the code stub is in the
// stub cache. // stub cache.
Object* code = NULL;
switch (type) { switch (type) {
case FIELD: { case FIELD: {
code = StubCache::ComputeStoreField(*name, *receiver, code = StubCache::ComputeStoreField(*name, *receiver,
...@@ -936,7 +917,8 @@ void StoreIC::UpdateCaches(LookupResult* lookup, ...@@ -936,7 +917,8 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
} }
Object* KeyedStoreIC::Store(Handle<Object> object, Object* KeyedStoreIC::Store(State state,
Handle<Object> object,
Handle<Object> key, Handle<Object> key,
Handle<Object> value) { Handle<Object> value) {
if (key->IsSymbol()) { if (key->IsSymbol()) {
...@@ -967,7 +949,7 @@ Object* KeyedStoreIC::Store(Handle<Object> object, ...@@ -967,7 +949,7 @@ Object* KeyedStoreIC::Store(Handle<Object> object,
// Update inline cache and stub cache. // Update inline cache and stub cache.
if (FLAG_use_ic && lookup.IsLoaded()) { if (FLAG_use_ic && lookup.IsLoaded()) {
UpdateCaches(&lookup, receiver, name, value); UpdateCaches(&lookup, state, receiver, name, value);
} }
// Set the property. // Set the property.
...@@ -986,6 +968,7 @@ Object* KeyedStoreIC::Store(Handle<Object> object, ...@@ -986,6 +968,7 @@ Object* KeyedStoreIC::Store(Handle<Object> object,
void KeyedStoreIC::UpdateCaches(LookupResult* lookup, void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
State state,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<String> name, Handle<String> name,
Handle<Object> value) { Handle<Object> value) {
...@@ -1005,8 +988,7 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup, ...@@ -1005,8 +988,7 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
// Compute the code stub for this store; used for rewriting to // Compute the code stub for this store; used for rewriting to
// monomorphic state and making sure that the code stub is in the // monomorphic state and making sure that the code stub is in the
// stub cache. // stub cache.
Object* code = Heap::undefined_value(); Object* code = NULL;
State state = ComputeCacheState(target(), *receiver, *name, &code);
switch (type) { switch (type) {
case FIELD: { case FIELD: {
...@@ -1064,7 +1046,8 @@ Object* CallIC_Miss(Arguments args) { ...@@ -1064,7 +1046,8 @@ Object* CallIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
CallIC ic; CallIC ic;
return ic.LoadFunction(args.at<Object>(0), args.at<String>(1)); IC::State state = IC::StateFrom(ic.target(), args[0]);
return ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
} }
...@@ -1088,7 +1071,8 @@ Object* LoadIC_Miss(Arguments args) { ...@@ -1088,7 +1071,8 @@ Object* LoadIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
LoadIC ic; LoadIC ic;
return ic.Load(args.at<Object>(0), args.at<String>(1)); IC::State state = IC::StateFrom(ic.target(), args[0]);
return ic.Load(state, args.at<Object>(0), args.at<String>(1));
} }
...@@ -1107,7 +1091,8 @@ Object* KeyedLoadIC_Miss(Arguments args) { ...@@ -1107,7 +1091,8 @@ Object* KeyedLoadIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
KeyedLoadIC ic; KeyedLoadIC ic;
return ic.Load(args.at<Object>(0), args.at<Object>(1)); IC::State state = IC::StateFrom(ic.target(), args[0]);
return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
} }
...@@ -1126,7 +1111,9 @@ Object* StoreIC_Miss(Arguments args) { ...@@ -1126,7 +1111,9 @@ Object* StoreIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 3); ASSERT(args.length() == 3);
StoreIC ic; StoreIC ic;
return ic.Store(args.at<Object>(0), args.at<String>(1), args.at<Object>(2)); IC::State state = IC::StateFrom(ic.target(), args[0]);
return ic.Store(state, args.at<Object>(0), args.at<String>(1),
args.at<Object>(2));
} }
...@@ -1145,7 +1132,9 @@ Object* KeyedStoreIC_Miss(Arguments args) { ...@@ -1145,7 +1132,9 @@ Object* KeyedStoreIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 3); ASSERT(args.length() == 3);
KeyedStoreIC ic; KeyedStoreIC ic;
return ic.Store(args.at<Object>(0), args.at<Object>(1), args.at<Object>(2)); IC::State state = IC::StateFrom(ic.target(), args[0]);
return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
args.at<Object>(2));
} }
......
...@@ -81,12 +81,8 @@ class IC { ...@@ -81,12 +81,8 @@ class IC {
Code* target() { return GetTargetAtAddress(address()); } Code* target() { return GetTargetAtAddress(address()); }
inline Address address(); inline Address address();
// Compute the state of the current inline cache. If the current // Compute the current IC state based on the target stub and the receiver.
// inline cache is monomorphic, this might change the code cache in static State StateFrom(Code* target, Object* receiver);
// the receiver map and it might return a code object from the code
// cache in the receiver map that should be used as the new target.
static State ComputeCacheState(Code* target, Object* receiver,
Object* name, Object** new_target);
// Clear the inline cache to initial state. // Clear the inline cache to initial state.
static void Clear(Address address); static void Clear(Address address);
...@@ -165,7 +161,7 @@ class CallIC: public IC { ...@@ -165,7 +161,7 @@ class CallIC: public IC {
public: public:
CallIC() : IC(EXTRA_CALL_FRAME) { ASSERT(target()->is_call_stub()); } CallIC() : IC(EXTRA_CALL_FRAME) { ASSERT(target()->is_call_stub()); }
Object* LoadFunction(Handle<Object> object, Handle<String> name); Object* LoadFunction(State state, Handle<Object> object, Handle<String> name);
// Code generator routines. // Code generator routines.
...@@ -183,6 +179,7 @@ class CallIC: public IC { ...@@ -183,6 +179,7 @@ class CallIC: public IC {
// Update the inline cache and the global stub cache based on the // Update the inline cache and the global stub cache based on the
// lookup result. // lookup result.
void UpdateCaches(LookupResult* lookup, void UpdateCaches(LookupResult* lookup,
State state,
Handle<Object> object, Handle<Object> object,
Handle<String> name); Handle<String> name);
...@@ -200,7 +197,7 @@ class LoadIC: public IC { ...@@ -200,7 +197,7 @@ class LoadIC: public IC {
public: public:
LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); } LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); }
Object* Load(Handle<Object> object, Handle<String> name); Object* Load(State state, Handle<Object> object, Handle<String> name);
// Code generator routines. // Code generator routines.
static void GenerateInitialize(MacroAssembler* masm); static void GenerateInitialize(MacroAssembler* masm);
...@@ -222,6 +219,7 @@ class LoadIC: public IC { ...@@ -222,6 +219,7 @@ class LoadIC: public IC {
// Update the inline cache and the global stub cache based on the // Update the inline cache and the global stub cache based on the
// lookup result. // lookup result.
void UpdateCaches(LookupResult* lookup, void UpdateCaches(LookupResult* lookup,
State state,
Handle<Object> object, Handle<Object> object,
Handle<String> name); Handle<String> name);
...@@ -245,7 +243,7 @@ class KeyedLoadIC: public IC { ...@@ -245,7 +243,7 @@ class KeyedLoadIC: public IC {
public: public:
KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); } KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); }
Object* Load(Handle<Object> object, Handle<Object> key); Object* Load(State state, Handle<Object> object, Handle<Object> key);
// Code generator routines. // Code generator routines.
static void GenerateMiss(MacroAssembler* masm); static void GenerateMiss(MacroAssembler* masm);
...@@ -258,6 +256,7 @@ class KeyedLoadIC: public IC { ...@@ -258,6 +256,7 @@ class KeyedLoadIC: public IC {
// Update the inline cache. // Update the inline cache.
void UpdateCaches(LookupResult* lookup, void UpdateCaches(LookupResult* lookup,
State state,
Handle<Object> object, Handle<Object> object,
Handle<String> name); Handle<String> name);
...@@ -284,7 +283,8 @@ class StoreIC: public IC { ...@@ -284,7 +283,8 @@ class StoreIC: public IC {
public: public:
StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); } StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
Object* Store(Handle<Object> object, Object* Store(State state,
Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> value); Handle<Object> value);
...@@ -299,7 +299,7 @@ class StoreIC: public IC { ...@@ -299,7 +299,7 @@ class StoreIC: public IC {
// Update the inline cache and the global stub cache based on the // Update the inline cache and the global stub cache based on the
// lookup result. // lookup result.
void UpdateCaches(LookupResult* lookup, void UpdateCaches(LookupResult* lookup,
Handle<JSObject> receiver, State state, Handle<JSObject> receiver,
Handle<String> name, Handle<String> name,
Handle<Object> value); Handle<Object> value);
...@@ -320,7 +320,8 @@ class KeyedStoreIC: public IC { ...@@ -320,7 +320,8 @@ class KeyedStoreIC: public IC {
public: public:
KeyedStoreIC() : IC(NO_EXTRA_FRAME) { } KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
Object* Store(Handle<Object> object, Object* Store(State state,
Handle<Object> object,
Handle<Object> name, Handle<Object> name,
Handle<Object> value); Handle<Object> value);
...@@ -334,6 +335,7 @@ class KeyedStoreIC: public IC { ...@@ -334,6 +335,7 @@ class KeyedStoreIC: public IC {
// Update the inline cache. // Update the inline cache.
void UpdateCaches(LookupResult* lookup, void UpdateCaches(LookupResult* lookup,
State state,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<String> name, Handle<String> name,
Handle<Object> value); Handle<Object> value);
......
...@@ -2109,20 +2109,6 @@ void Map::ClearCodeCache() { ...@@ -2109,20 +2109,6 @@ void Map::ClearCodeCache() {
} }
Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
int index;
return FindIndexInCodeCache(name, flags, &index);
}
void Map::RemoveFromCodeCache(int index) {
FixedArray* array = code_cache();
ASSERT(array->length() >= index && array->get(index)->IsCode());
array->set_undefined(index - 1); // key
array->set_undefined(index); // code
}
#undef CAST_ACCESSOR #undef CAST_ACCESSOR
#undef INT_ACCESSORS #undef INT_ACCESSORS
#undef SMI_ACCESSORS #undef SMI_ACCESSORS
......
...@@ -2410,27 +2410,41 @@ Object* Map::UpdateCodeCache(String* name, Code* code) { ...@@ -2410,27 +2410,41 @@ Object* Map::UpdateCodeCache(String* name, Code* code) {
} }
Object* Map::FindIndexInCodeCache(String* name, Code::Flags flags, int* index) { Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
FixedArray* cache = code_cache(); FixedArray* cache = code_cache();
int length = cache->length(); int length = cache->length();
for (int i = 0; i < length; i += 2) { for (int i = 0; i < length; i += 2) {
Object* key = cache->get(i); Object* key = cache->get(i);
if (key->IsUndefined()) { if (key->IsUndefined()) {
continue; return key;
} }
if (name->Equals(String::cast(key))) { if (name->Equals(String::cast(key))) {
Code* code = Code::cast(cache->get(i + 1)); Code* code = Code::cast(cache->get(i + 1));
if (code->flags() == flags) { if (code->flags() == flags) return code;
*index = i + 1;
return code;
}
} }
} }
*index = -1;
return Heap::undefined_value(); return Heap::undefined_value();
} }
int Map::IndexInCodeCache(Code* code) {
FixedArray* array = code_cache();
int len = array->length();
for (int i = 0; i < len; i += 2) {
if (array->get(i + 1) == code) return i + 1;
}
return -1;
}
void Map::RemoveFromCodeCache(int index) {
FixedArray* array = code_cache();
ASSERT(array->length() >= index && array->get(index)->IsCode());
array->set_undefined(index - 1); // key
array->set_undefined(index); // code
}
void FixedArray::FixedArrayIterateBody(ObjectVisitor* v) { void FixedArray::FixedArrayIterateBody(ObjectVisitor* v) {
IteratePointers(v, kHeaderSize, kHeaderSize + length() * kPointerSize); IteratePointers(v, kHeaderSize, kHeaderSize + length() * kPointerSize);
} }
......
...@@ -2342,14 +2342,14 @@ class Map: public HeapObject { ...@@ -2342,14 +2342,14 @@ class Map: public HeapObject {
Object* UpdateCodeCache(String* name, Code* code); Object* UpdateCodeCache(String* name, Code* code);
// Returns the found code or undefined if absent. // Returns the found code or undefined if absent.
inline Object* FindInCodeCache(String* name, Code::Flags flags); Object* FindInCodeCache(String* name, Code::Flags flags);
// Returns the found code or undefined if absent. Also returns the // Returns the non-negative index of the code object if it is in the
// index at which the code was found or -1 if absent. // cache and -1 otherwise.
Object* FindIndexInCodeCache(String* name, Code::Flags flags, int* index); int IndexInCodeCache(Code* code);
// Removes a code object from the code cache at the given index. // Removes a code object from the code cache at the given index.
inline void RemoveFromCodeCache(int index); void RemoveFromCodeCache(int index);
// Dispatched behavior. // Dispatched behavior.
void MapIterateBody(ObjectVisitor* v); void MapIterateBody(ObjectVisitor* v);
......
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