Index: src/ic.cc |
diff --git a/src/ic.cc b/src/ic.cc |
index 2c6d55b93fce474d6c9452de3705604f09fcc05a..7f867143f0622cf920e0a25591a703fae084b643 100644 |
--- a/src/ic.cc |
+++ b/src/ic.cc |
@@ -40,13 +40,13 @@ namespace v8 { |
namespace internal { |
#ifdef DEBUG |
-static char TransitionMarkFromState(IC::State state) { |
+char IC::TransitionMarkFromState(IC::State state) { |
switch (state) { |
case UNINITIALIZED: return '0'; |
case PREMONOMORPHIC: return 'P'; |
case MONOMORPHIC: return '1'; |
case MONOMORPHIC_PROTOTYPE_FAILURE: return '^'; |
- case MEGAMORPHIC: return 'N'; |
+ case MEGAMORPHIC: return IsGeneric() ? 'G' : 'N'; |
// We never see the debugger states here, because the state is |
// computed from the original code - not the patched code. Let |
@@ -80,19 +80,7 @@ void IC::TraceIC(const char* type, |
raw_frame = it.frame(); |
} |
} |
- if (raw_frame->is_java_script()) { |
- JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); |
- Code* js_code = frame->unchecked_code(); |
- // Find the function on the stack and both the active code for the |
- // function and the original code. |
- JSFunction* function = JSFunction::cast(frame->function()); |
- function->PrintName(); |
- int code_offset = |
- static_cast<int>(address() - js_code->instruction_start()); |
- PrintF("+%d", code_offset); |
- } else { |
- PrintF("<unknown>"); |
- } |
+ JavaScriptFrame::PrintTop(stdout, false, true); |
PrintF(" (%c->%c)", |
TransitionMarkFromState(old_state), |
TransitionMarkFromState(new_state)); |
@@ -100,13 +88,23 @@ void IC::TraceIC(const char* type, |
PrintF("]\n"); |
} |
} |
-#endif // DEBUG |
+#define TRACE_GENERIC_IC(type, reason) \ |
+ do { \ |
+ if (FLAG_trace_ic) { \ |
+ PrintF("[%s patching generic stub in ", type); \ |
+ JavaScriptFrame::PrintTop(stdout, false, true); \ |
+ PrintF(" (%s)]\n", reason); \ |
+ } \ |
+ } while (false) |
+ |
+#else |
+#define TRACE_GENERIC_IC(type, reason) |
+#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) { |
ASSERT(isolate == Isolate::Current()); |
// To improve the performance of the (much used) IC code, we unfold |
@@ -137,7 +135,7 @@ IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
#ifdef ENABLE_DEBUGGER_SUPPORT |
-Address IC::OriginalCodeAddress() { |
+Address IC::OriginalCodeAddress() const { |
HandleScope scope; |
// Compute the JavaScript frame for the frame pointer of this IC |
// structure. We need this to be able to find the function |
@@ -1123,6 +1121,8 @@ MaybeObject* KeyedLoadIC::Load(State state, |
stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub); |
} |
} |
+ } else { |
+ TRACE_GENERIC_IC("KeyedLoadIC", "force generic"); |
} |
if (!stub.is_null()) set_target(*stub); |
} |
@@ -1473,6 +1473,7 @@ Handle<Code> KeyedIC::ComputeStub(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() != NORMAL) { |
+ TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type"); |
return generic_stub; |
} |
@@ -1494,12 +1495,14 @@ Handle<Code> KeyedIC::ComputeStub(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("KeyedIC", "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("KeyedIC", "max polymorph exceeded"); |
return generic_stub; |
} |
@@ -1685,6 +1688,8 @@ MaybeObject* KeyedStoreIC::Store(State state, |
} |
stub = ComputeStub(receiver, stub_kind, strict_mode, stub); |
} |
+ } else { |
+ TRACE_GENERIC_IC("KeyedStoreIC", "force generic"); |
} |
} |
if (!stub.is_null()) set_target(*stub); |