Improve TraceIC logging

Explicitly log generic stub transitions and the reason that they are happening.

R=jkummerow@chromium.org
BUG=none
TEST=none

Review URL: http://codereview.chromium.org/8803013

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10165 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
danno@chromium.org 2011-12-05 21:54:45 +00:00
parent a0c8ea00db
commit 5bcb4d30ed
4 changed files with 56 additions and 32 deletions

View File

@ -723,12 +723,17 @@ void JavaScriptFrame::PrintTop(FILE* file,
JavaScriptFrame* frame = it.frame();
if (frame->IsConstructor()) PrintF(file, "new ");
// function name
Object* fun = frame->function();
if (fun->IsJSFunction()) {
SharedFunctionInfo* shared = JSFunction::cast(fun)->shared();
shared->DebugName()->ShortPrint(file);
Object* maybe_fun = frame->function();
if (maybe_fun->IsJSFunction()) {
JSFunction* fun = JSFunction::cast(maybe_fun);
fun->PrintName();
Code* js_code = frame->unchecked_code();
Address pc = frame->pc();
int code_offset =
static_cast<int>(pc - js_code->instruction_start());
PrintF("+%d", code_offset);
SharedFunctionInfo* shared = fun->shared();
if (print_line_number) {
Address pc = frame->pc();
Code* code = Code::cast(
v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
int source_pos = code->SourcePosition(pc);
@ -751,7 +756,7 @@ void JavaScriptFrame::PrintTop(FILE* file,
}
}
} else {
fun->ShortPrint(file);
PrintF("<unknown>");
}
if (print_args) {

View File

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -36,7 +36,7 @@ namespace v8 {
namespace internal {
Address IC::address() {
Address IC::address() const {
// Get the address of the call.
Address result = pc() - Assembler::kCallTargetAddressOffset;

View File

@ -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);

View File

@ -91,10 +91,13 @@ class IC {
// Construct the IC structure with the given number of extra
// JavaScript frames on the stack.
IC(FrameDepth depth, Isolate* isolate);
virtual ~IC() {}
// Get the call-site target; used for determining the state.
Code* target() { return GetTargetAtAddress(address()); }
inline Address address();
Code* target() const { return GetTargetAtAddress(address()); }
inline Address address() const;
virtual bool IsGeneric() const { return false; }
// Compute the current IC state based on the target stub, receiver and name.
static State StateFrom(Code* target, Object* receiver, Object* name);
@ -139,13 +142,15 @@ class IC {
#ifdef ENABLE_DEBUGGER_SUPPORT
// Computes the address in the original code when the code running is
// containing break points (calls to DebugBreakXXX builtins).
Address OriginalCodeAddress();
Address OriginalCodeAddress() const;
#endif
// Set the call-site target.
void set_target(Code* code) { SetTargetAtAddress(address(), code); }
#ifdef DEBUG
char TransitionMarkFromState(IC::State state);
void TraceIC(const char* type,
Handle<Object> name,
State old_state,
@ -452,6 +457,10 @@ class KeyedLoadIC: public KeyedIC {
bool is_js_array,
ElementsKind elements_kind);
virtual bool IsGeneric() const {
return target() == *generic_stub();
}
protected:
virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
@ -477,7 +486,7 @@ class KeyedLoadIC: public KeyedIC {
Handle<Code> megamorphic_stub() {
return isolate()->builtins()->KeyedLoadIC_Generic();
}
Handle<Code> generic_stub() {
Handle<Code> generic_stub() const {
return isolate()->builtins()->KeyedLoadIC_Generic();
}
Handle<Code> pre_monomorphic_stub() {
@ -595,6 +604,11 @@ class KeyedStoreIC: public KeyedIC {
bool is_js_array,
ElementsKind elements_kind);
virtual bool IsGeneric() const {
return target() == *generic_stub() ||
target() == *generic_stub_strict();
}
protected:
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
@ -632,10 +646,10 @@ class KeyedStoreIC: public KeyedIC {
Handle<Code> megamorphic_stub_strict() {
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
}
Handle<Code> generic_stub() {
Handle<Code> generic_stub() const {
return isolate()->builtins()->KeyedStoreIC_Generic();
}
Handle<Code> generic_stub_strict() {
Handle<Code> generic_stub_strict() const {
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
}
Handle<Code> non_strict_arguments_stub() {