Index: src/ic.cc |
diff --git a/src/ic.cc b/src/ic.cc |
index 9742e5ef8486ad4943872993a60c729b8cbf97ef..54b4db8711e9cfc4505cab0350272dd82151390c 100644 |
--- a/src/ic.cc |
+++ b/src/ic.cc |
@@ -100,7 +100,11 @@ void IC::TraceIC(const char* type, |
PrintF("]\n"); |
} |
} |
-#endif |
+#endif // DEBUG |
+ |
+ |
+#define TRACE_IC(type, name, old_state, new_target) \ |
+ ASSERT((TraceIC(type, name, old_state, new_target), true)) |
IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
@@ -578,89 +582,57 @@ bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, |
} |
-MaybeObject* CallICBase::ComputeMonomorphicStub( |
- LookupResult* lookup, |
- State state, |
- Code::ExtraICState extra_ic_state, |
- Handle<Object> object, |
- Handle<String> name) { |
+Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, |
+ State state, |
+ Code::ExtraICState extra_state, |
+ Handle<Object> object, |
+ Handle<String> name) { |
int argc = target()->arguments_count(); |
- MaybeObject* maybe_code = NULL; |
+ Handle<JSObject> holder(lookup->holder()); |
switch (lookup->type()) { |
case FIELD: { |
int index = lookup->GetFieldIndex(); |
- maybe_code = isolate()->stub_cache()->ComputeCallField(argc, |
- kind_, |
- extra_ic_state, |
- *name, |
- *object, |
- lookup->holder(), |
- index); |
- break; |
+ return isolate()->stub_cache()->ComputeCallField( |
+ argc, kind_, extra_state, name, object, holder, index); |
} |
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(); |
- maybe_code = |
- isolate()->stub_cache()->ComputeCallConstant(argc, |
- kind_, |
- extra_ic_state, |
- *name, |
- *object, |
- lookup->holder(), |
- function); |
- break; |
+ Handle<JSFunction> function(lookup->GetConstantFunction()); |
+ return isolate()->stub_cache()->ComputeCallConstant( |
+ argc, kind_, extra_state, name, object, holder, function); |
} |
case NORMAL: { |
- if (!object->IsJSObject()) return NULL; |
+ // If we return a null handle, the IC will not be patched. |
+ if (!object->IsJSObject()) return Handle<Code>::null(); |
Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
- if (lookup->holder()->IsGlobalObject()) { |
- GlobalObject* global = GlobalObject::cast(lookup->holder()); |
- JSGlobalPropertyCell* cell = |
- JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); |
- if (!cell->value()->IsJSFunction()) return NULL; |
- JSFunction* function = JSFunction::cast(cell->value()); |
- maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, |
- kind_, |
- extra_ic_state, |
- *name, |
- *receiver, |
- global, |
- cell, |
- function); |
+ if (holder->IsGlobalObject()) { |
+ Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
+ Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); |
+ if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); |
+ Handle<JSFunction> function(JSFunction::cast(cell->value())); |
+ return isolate()->stub_cache()->ComputeCallGlobal( |
+ argc, kind_, extra_state, name, receiver, global, cell, function); |
} else { |
// 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 (lookup->holder() != *receiver) return NULL; |
- maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, |
- kind_, |
- extra_ic_state, |
- *name, |
- *receiver); |
+ if (!holder.is_identical_to(receiver)) return Handle<Code>::null(); |
+ return isolate()->stub_cache()->ComputeCallNormal( |
+ argc, kind_, extra_state); |
} |
break; |
} |
- case INTERCEPTOR: { |
- ASSERT(HasInterceptorGetter(lookup->holder())); |
- maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( |
- argc, |
- kind_, |
- extra_ic_state, |
- *name, |
- *object, |
- lookup->holder()); |
- break; |
- } |
+ case INTERCEPTOR: |
+ ASSERT(HasInterceptorGetter(*holder)); |
+ return isolate()->stub_cache()->ComputeCallInterceptor( |
+ argc, kind_, extra_state, name, object, holder); |
default: |
- maybe_code = NULL; |
- break; |
+ return Handle<Code>::null(); |
} |
- return maybe_code; |
} |
@@ -682,75 +654,57 @@ void CallICBase::UpdateCaches(LookupResult* lookup, |
// Compute the number of arguments. |
int argc = target()->arguments_count(); |
- MaybeObject* maybe_code = NULL; |
bool had_proto_failure = false; |
+ Handle<Code> code; |
if (state == UNINITIALIZED) { |
// This is the first time we execute this inline cache. |
// Set the target to the pre monomorphic stub to delay |
// setting the monomorphic state. |
- maybe_code = |
- isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, |
- kind_, |
- extra_ic_state); |
+ code = isolate()->stub_cache()->ComputeCallPreMonomorphic( |
+ argc, kind_, extra_ic_state); |
} else if (state == MONOMORPHIC) { |
if (kind_ == Code::CALL_IC && |
TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
- maybe_code = ComputeMonomorphicStub(lookup, |
- state, |
- extra_ic_state, |
- object, |
- name); |
+ code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
+ object, name); |
} else if (kind_ == Code::CALL_IC && |
TryRemoveInvalidPrototypeDependentStub(target(), |
*object, |
*name)) { |
had_proto_failure = true; |
- maybe_code = ComputeMonomorphicStub(lookup, |
- state, |
- extra_ic_state, |
- object, |
- name); |
+ code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
+ object, name); |
} else { |
- maybe_code = |
- isolate()->stub_cache()->ComputeCallMegamorphic(argc, |
- kind_, |
- extra_ic_state); |
+ code = isolate()->stub_cache()->ComputeCallMegamorphic( |
+ argc, kind_, extra_ic_state); |
} |
} else { |
- maybe_code = ComputeMonomorphicStub(lookup, |
- state, |
- extra_ic_state, |
- object, |
- name); |
+ code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
+ object, name); |
} |
- // If we're unable to compute the stub (not enough memory left), we |
- // simply avoid updating the caches. |
- Object* code; |
- if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; |
+ // If there's no appropriate stub we simply avoid updating the caches. |
+ 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::cast(code)); |
+ 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. |
- Map* map = JSObject::cast(object->IsJSObject() ? *object : |
- object->GetPrototype())->map(); |
- |
+ 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, map, Code::cast(code)); |
+ isolate()->stub_cache()->Set(*name, cache_object->map(), *code); |
} |
- USE(had_proto_failure); |
-#ifdef DEBUG |
if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; |
- TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
- name, state, target()); |
-#endif |
+ TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
+ name, state, target()); |
} |
@@ -774,25 +728,15 @@ MaybeObject* KeyedCallIC::LoadFunction(State state, |
isolate()->factory()->non_strict_arguments_elements_map(); |
if (object->IsJSObject() && |
Handle<JSObject>::cast(object)->elements()->map() == *map) { |
- MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( |
+ Handle<Code> code = isolate()->stub_cache()->ComputeCallArguments( |
argc, Code::KEYED_CALL_IC); |
- Code* code = NULL; |
- if (maybe_code->To(&code)) { |
- set_target(code); |
-#ifdef DEBUG |
- TraceIC("KeyedCallIC", key, state, target()); |
-#endif |
- } |
+ set_target(*code); |
+ TRACE_IC("KeyedCallIC", key, state, target()); |
} else if (!object->IsAccessCheckNeeded()) { |
- MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( |
+ Handle<Code> code = isolate()->stub_cache()->ComputeCallMegamorphic( |
argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
- Code* code; |
- if (maybe_code->To(&code)) { |
- set_target(code); |
-#ifdef DEBUG |
- TraceIC("KeyedCallIC", key, state, target()); |
-#endif |
- } |
+ set_target(*code); |
+ TRACE_IC("KeyedCallIC", key, state, target()); |
} |
} |
@@ -1023,9 +967,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup, |
isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
} |
-#ifdef DEBUG |
- TraceIC("LoadIC", name, state, target()); |
-#endif |
+ TRACE_IC("LoadIC", name, state, target()); |
} |
@@ -1096,9 +1038,7 @@ MaybeObject* KeyedLoadIC::Load(State state, |
string); |
ASSERT(!code.is_null()); |
set_target(*code); |
-#ifdef DEBUG |
- TraceIC("KeyedLoadIC", name, state, target()); |
-#endif // DEBUG |
+ TRACE_IC("KeyedLoadIC", name, state, target()); |
return Smi::FromInt(string->length()); |
} |
@@ -1110,9 +1050,7 @@ MaybeObject* KeyedLoadIC::Load(State state, |
isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array); |
ASSERT(!code.is_null()); |
set_target(*code); |
-#ifdef DEBUG |
- TraceIC("KeyedLoadIC", name, state, target()); |
-#endif // DEBUG |
+ TRACE_IC("KeyedLoadIC", name, state, target()); |
return array->length(); |
} |
@@ -1126,9 +1064,7 @@ MaybeObject* KeyedLoadIC::Load(State state, |
name, function); |
ASSERT(!code.is_null()); |
set_target(*code); |
-#ifdef DEBUG |
- TraceIC("KeyedLoadIC", name, state, target()); |
-#endif // DEBUG |
+ TRACE_IC("KeyedLoadIC", name, state, target()); |
return Accessors::FunctionGetPrototype(*object, 0); |
} |
} |
@@ -1198,9 +1134,7 @@ MaybeObject* KeyedLoadIC::Load(State state, |
if (!stub.is_null()) set_target(*stub); |
} |
-#ifdef DEBUG |
- TraceIC("KeyedLoadIC", key, state, target()); |
-#endif // DEBUG |
+ TRACE_IC("KeyedLoadIC", key, state, target()); |
// Get the property. |
return Runtime::GetObjectProperty(isolate(), object, key); |
@@ -1273,9 +1207,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, |
set_target(*megamorphic_stub()); |
} |
-#ifdef DEBUG |
- TraceIC("KeyedLoadIC", name, state, target()); |
-#endif |
+ TRACE_IC("KeyedLoadIC", name, state, target()); |
} |
@@ -1390,9 +1322,7 @@ MaybeObject* StoreIC::Store(State state, |
: global_proxy_stub(); |
if (target() != *stub) { |
set_target(*stub); |
-#ifdef DEBUG |
- TraceIC("StoreIC", name, state, target()); |
-#endif |
+ TRACE_IC("StoreIC", name, state, target()); |
} |
} |
@@ -1486,9 +1416,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup, |
isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
} |
-#ifdef DEBUG |
- TraceIC("StoreIC", name, state, target()); |
-#endif |
+ TRACE_IC("StoreIC", name, state, target()); |
} |
@@ -1797,9 +1725,7 @@ MaybeObject* KeyedStoreIC::Store(State state, |
if (stub != NULL) set_target(stub); |
} |
-#ifdef DEBUG |
- TraceIC("KeyedStoreIC", key, state, target()); |
-#endif |
+ TRACE_IC("KeyedStoreIC", key, state, target()); |
// Set the property. |
return Runtime::SetObjectProperty( |
@@ -1877,12 +1803,13 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup, |
: megamorphic_stub()); |
} |
-#ifdef DEBUG |
- TraceIC("KeyedStoreIC", name, state, target()); |
-#endif |
+ TRACE_IC("KeyedStoreIC", name, state, target()); |
} |
+#undef TRACE_IC |
+ |
+ |
// ---------------------------------------------------------------------------- |
// Static IC stub generators. |
// |