#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
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();
}
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());
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);
}
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);
} 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);
}
// TODO(dcarney): Handle correctly.
DCHECK(accessors->IsDeclaredAccessorInfo());
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "declared accessor info");
break;
}
// -------------- Constant properties --------------
DCHECK(lookup->property_details().type() == CONSTANT);
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property");
break;
}
// 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();
}
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();
}
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();
}
}
}
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();
}
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;
}
// 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) {
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()))) {
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");
}
}
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);