Index: src/ic/ic.cc |
diff --git a/src/ic/ic.cc b/src/ic/ic.cc |
index fc364e152b9e8dca3b0e31633591054d172bcbd5..50c9d72605e30231eca4901f00108aaac8ca84d9 100644 |
--- a/src/ic/ic.cc |
+++ b/src/ic/ic.cc |
@@ -76,7 +76,13 @@ const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { |
#else |
-#define TRACE_GENERIC_IC(isolate, type, reason) |
+#define TRACE_GENERIC_IC(isolate, type, reason) \ |
+ do { \ |
+ if (FLAG_trace_ic) { \ |
+ PrintF("[%s patching generic stub in ", type); \ |
+ PrintF("(see below) (%s)]\n", reason); \ |
+ } \ |
+ } while (false) |
#endif // DEBUG |
@@ -1140,14 +1146,14 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { |
if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
// If the miss wasn't due to an unseen map, a polymorphic stub |
// won't help, use the generic stub. |
- TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); |
+ TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); |
return generic_stub(); |
} |
// If the maximum number of receiver maps has been exceeded, use the generic |
// version of the IC. |
if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
- TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); |
+ TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
return generic_stub(); |
} |
@@ -1371,9 +1377,11 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, |
return; |
} |
- Handle<Code> code = LookupForWrite(lookup, value, store_mode) |
- ? ComputeHandler(lookup, value) |
- : slow_stub(); |
+ bool use_ic = LookupForWrite(lookup, value, store_mode); |
+ if (!use_ic) { |
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); |
+ } |
+ Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); |
PatchCache(lookup->name(), code); |
TRACE_IC("StoreIC", lookup->name()); |
@@ -1394,7 +1402,10 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, |
case LookupIterator::TRANSITION: { |
Handle<Map> transition = lookup->transition_map(); |
// Currently not handled by CompileStoreTransition. |
- if (!holder->HasFastProperties()) break; |
+ if (!holder->HasFastProperties()) { |
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow"); |
+ break; |
+ } |
DCHECK(lookup->IsCacheableTransition()); |
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
@@ -1408,14 +1419,21 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, |
} |
case LookupIterator::ACCESSOR: { |
- if (!holder->HasFastProperties()) break; |
+ if (!holder->HasFastProperties()) { |
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map"); |
+ break; |
+ } |
Handle<Object> accessors = lookup->GetAccessors(); |
if (accessors->IsExecutableAccessorInfo()) { |
Handle<ExecutableAccessorInfo> info = |
Handle<ExecutableAccessorInfo>::cast(accessors); |
- if (v8::ToCData<Address>(info->setter()) == 0) break; |
+ if (v8::ToCData<Address>(info->setter()) == 0) { |
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0"); |
+ break; |
+ } |
if (!ExecutableAccessorInfo::IsCompatibleReceiverType( |
isolate(), info, receiver_type())) { |
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); |
break; |
} |
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
@@ -1423,7 +1441,10 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, |
} else if (accessors->IsAccessorPair()) { |
Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), |
isolate()); |
- if (!setter->IsJSFunction()) break; |
+ if (!setter->IsJSFunction()) { |
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function"); |
+ break; |
+ } |
Handle<JSFunction> function = Handle<JSFunction>::cast(setter); |
CallOptimization call_optimization(function); |
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
@@ -1437,6 +1458,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, |
} |
// TODO(dcarney): Handle correctly. |
DCHECK(accessors->IsDeclaredAccessorInfo()); |
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "declared accessor info"); |
break; |
} |
@@ -1477,6 +1499,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, |
// -------------- Constant properties -------------- |
DCHECK(lookup->property_details().type() == CONSTANT); |
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); |
break; |
} |
@@ -1495,7 +1518,7 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
// via megamorphic stubs, since they don't have a map in their relocation info |
// and so the stubs can't be harvested for the object needed for a map check. |
if (target()->type() != Code::NORMAL) { |
- TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type"); |
return generic_stub(); |
} |
@@ -1561,14 +1584,14 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
if (!map_added) { |
// If the miss wasn't due to an unseen map, a polymorphic stub |
// won't help, use the generic stub. |
- TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice"); |
return generic_stub(); |
} |
// If the maximum number of receiver maps has been exceeded, use the generic |
// version of the IC. |
if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
- TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "max polymorph exceeded"); |
return generic_stub(); |
} |
@@ -1579,7 +1602,7 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
if (store_mode == STANDARD_STORE) { |
store_mode = old_store_mode; |
} else if (store_mode != old_store_mode) { |
- TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch"); |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch"); |
return generic_stub(); |
} |
} |
@@ -1597,7 +1620,7 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
} |
if (external_arrays != 0 && |
external_arrays != target_receiver_maps.length()) { |
- TRACE_GENERIC_IC(isolate(), "KeyedIC", |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
"unsupported combination of external and normal arrays"); |
return generic_stub(); |
} |
@@ -1752,8 +1775,12 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, |
StoreIC::Store(object, Handle<String>::cast(key), value, |
JSReceiver::MAY_BE_STORE_FROM_KEYED), |
Object); |
- TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
- set_target(*stub); |
+ if (!is_target_set()) { |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
+ "unhandled internalized string key"); |
+ TRACE_IC("StoreIC", key); |
+ set_target(*stub); |
+ } |
return store_handle; |
} |
@@ -1766,7 +1793,10 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, |
// expect to be able to trap element sets to objects with those maps in |
// the runtime to enable optimization of element hole access. |
Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
- if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; |
+ if (heap_object->map()->IsMapInArrayPrototypeChain()) { |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype"); |
+ use_ic = false; |
+ } |
} |
if (use_ic) { |
@@ -1779,6 +1809,8 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, |
isolate()->heap()->sloppy_arguments_elements_map()) { |
if (strict_mode() == SLOPPY) { |
stub = sloppy_arguments_stub(); |
+ } else { |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); |
} |
} else if (key_is_smi_like && |
!(target().is_identical_to(sloppy_arguments_stub()))) { |
@@ -1789,8 +1821,14 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, |
if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { |
KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); |
stub = StoreElementStub(receiver, store_mode); |
+ } else { |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype"); |
} |
+ } else { |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); |
} |
+ } else { |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); |
} |
} |
@@ -1807,6 +1845,9 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, |
if (*stub == generic) { |
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
} |
+ if (*stub == *slow_stub()) { |
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); |
+ } |
DCHECK(!stub.is_null()); |
set_target(*stub); |
TRACE_IC("StoreIC", key); |