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:
parent
a0c8ea00db
commit
5bcb4d30ed
@ -723,12 +723,17 @@ void JavaScriptFrame::PrintTop(FILE* file,
|
|||||||
JavaScriptFrame* frame = it.frame();
|
JavaScriptFrame* frame = it.frame();
|
||||||
if (frame->IsConstructor()) PrintF(file, "new ");
|
if (frame->IsConstructor()) PrintF(file, "new ");
|
||||||
// function name
|
// function name
|
||||||
Object* fun = frame->function();
|
Object* maybe_fun = frame->function();
|
||||||
if (fun->IsJSFunction()) {
|
if (maybe_fun->IsJSFunction()) {
|
||||||
SharedFunctionInfo* shared = JSFunction::cast(fun)->shared();
|
JSFunction* fun = JSFunction::cast(maybe_fun);
|
||||||
shared->DebugName()->ShortPrint(file);
|
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) {
|
if (print_line_number) {
|
||||||
Address pc = frame->pc();
|
|
||||||
Code* code = Code::cast(
|
Code* code = Code::cast(
|
||||||
v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
|
v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
|
||||||
int source_pos = code->SourcePosition(pc);
|
int source_pos = code->SourcePosition(pc);
|
||||||
@ -751,7 +756,7 @@ void JavaScriptFrame::PrintTop(FILE* file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fun->ShortPrint(file);
|
PrintF("<unknown>");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print_args) {
|
if (print_args) {
|
||||||
|
@ -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
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
@ -36,7 +36,7 @@ namespace v8 {
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
|
||||||
Address IC::address() {
|
Address IC::address() const {
|
||||||
// Get the address of the call.
|
// Get the address of the call.
|
||||||
Address result = pc() - Assembler::kCallTargetAddressOffset;
|
Address result = pc() - Assembler::kCallTargetAddressOffset;
|
||||||
|
|
||||||
|
41
src/ic.cc
41
src/ic.cc
@ -40,13 +40,13 @@ namespace v8 {
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static char TransitionMarkFromState(IC::State state) {
|
char IC::TransitionMarkFromState(IC::State state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case UNINITIALIZED: return '0';
|
case UNINITIALIZED: return '0';
|
||||||
case PREMONOMORPHIC: return 'P';
|
case PREMONOMORPHIC: return 'P';
|
||||||
case MONOMORPHIC: return '1';
|
case MONOMORPHIC: return '1';
|
||||||
case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
|
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
|
// We never see the debugger states here, because the state is
|
||||||
// computed from the original code - not the patched code. Let
|
// computed from the original code - not the patched code. Let
|
||||||
@ -80,19 +80,7 @@ void IC::TraceIC(const char* type,
|
|||||||
raw_frame = it.frame();
|
raw_frame = it.frame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (raw_frame->is_java_script()) {
|
JavaScriptFrame::PrintTop(stdout, false, true);
|
||||||
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>");
|
|
||||||
}
|
|
||||||
PrintF(" (%c->%c)",
|
PrintF(" (%c->%c)",
|
||||||
TransitionMarkFromState(old_state),
|
TransitionMarkFromState(old_state),
|
||||||
TransitionMarkFromState(new_state));
|
TransitionMarkFromState(new_state));
|
||||||
@ -100,13 +88,23 @@ void IC::TraceIC(const char* type,
|
|||||||
PrintF("]\n");
|
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) \
|
#define TRACE_IC(type, name, old_state, new_target) \
|
||||||
ASSERT((TraceIC(type, name, old_state, new_target), true))
|
ASSERT((TraceIC(type, name, old_state, new_target), true))
|
||||||
|
|
||||||
|
|
||||||
IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
|
IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
|
||||||
ASSERT(isolate == Isolate::Current());
|
ASSERT(isolate == Isolate::Current());
|
||||||
// To improve the performance of the (much used) IC code, we unfold
|
// 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
|
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||||
Address IC::OriginalCodeAddress() {
|
Address IC::OriginalCodeAddress() const {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
// Compute the JavaScript frame for the frame pointer of this IC
|
// Compute the JavaScript frame for the frame pointer of this IC
|
||||||
// structure. We need this to be able to find the function
|
// 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);
|
stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
TRACE_GENERIC_IC("KeyedLoadIC", "force generic");
|
||||||
}
|
}
|
||||||
if (!stub.is_null()) set_target(*stub);
|
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
|
// 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.
|
// and so the stubs can't be harvested for the object needed for a map check.
|
||||||
if (target()->type() != NORMAL) {
|
if (target()->type() != NORMAL) {
|
||||||
|
TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type");
|
||||||
return generic_stub;
|
return generic_stub;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1494,12 +1495,14 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
|
|||||||
if (!map_added) {
|
if (!map_added) {
|
||||||
// If the miss wasn't due to an unseen map, a polymorphic stub
|
// If the miss wasn't due to an unseen map, a polymorphic stub
|
||||||
// won't help, use the generic stub.
|
// won't help, use the generic stub.
|
||||||
|
TRACE_GENERIC_IC("KeyedIC", "same map added twice");
|
||||||
return generic_stub;
|
return generic_stub;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the maximum number of receiver maps has been exceeded, use the generic
|
// If the maximum number of receiver maps has been exceeded, use the generic
|
||||||
// version of the IC.
|
// version of the IC.
|
||||||
if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
|
if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
|
||||||
|
TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded");
|
||||||
return generic_stub;
|
return generic_stub;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1685,6 +1688,8 @@ MaybeObject* KeyedStoreIC::Store(State state,
|
|||||||
}
|
}
|
||||||
stub = ComputeStub(receiver, stub_kind, strict_mode, stub);
|
stub = ComputeStub(receiver, stub_kind, strict_mode, stub);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
TRACE_GENERIC_IC("KeyedStoreIC", "force generic");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!stub.is_null()) set_target(*stub);
|
if (!stub.is_null()) set_target(*stub);
|
||||||
|
26
src/ic.h
26
src/ic.h
@ -91,10 +91,13 @@ class IC {
|
|||||||
// Construct the IC structure with the given number of extra
|
// Construct the IC structure with the given number of extra
|
||||||
// JavaScript frames on the stack.
|
// JavaScript frames on the stack.
|
||||||
IC(FrameDepth depth, Isolate* isolate);
|
IC(FrameDepth depth, Isolate* isolate);
|
||||||
|
virtual ~IC() {}
|
||||||
|
|
||||||
// Get the call-site target; used for determining the state.
|
// Get the call-site target; used for determining the state.
|
||||||
Code* target() { return GetTargetAtAddress(address()); }
|
Code* target() const { return GetTargetAtAddress(address()); }
|
||||||
inline Address address();
|
inline Address address() const;
|
||||||
|
|
||||||
|
virtual bool IsGeneric() const { return false; }
|
||||||
|
|
||||||
// Compute the current IC state based on the target stub, receiver and name.
|
// Compute the current IC state based on the target stub, receiver and name.
|
||||||
static State StateFrom(Code* target, Object* receiver, Object* name);
|
static State StateFrom(Code* target, Object* receiver, Object* name);
|
||||||
@ -139,13 +142,15 @@ class IC {
|
|||||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||||
// Computes the address in the original code when the code running is
|
// Computes the address in the original code when the code running is
|
||||||
// containing break points (calls to DebugBreakXXX builtins).
|
// containing break points (calls to DebugBreakXXX builtins).
|
||||||
Address OriginalCodeAddress();
|
Address OriginalCodeAddress() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set the call-site target.
|
// Set the call-site target.
|
||||||
void set_target(Code* code) { SetTargetAtAddress(address(), code); }
|
void set_target(Code* code) { SetTargetAtAddress(address(), code); }
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
char TransitionMarkFromState(IC::State state);
|
||||||
|
|
||||||
void TraceIC(const char* type,
|
void TraceIC(const char* type,
|
||||||
Handle<Object> name,
|
Handle<Object> name,
|
||||||
State old_state,
|
State old_state,
|
||||||
@ -452,6 +457,10 @@ class KeyedLoadIC: public KeyedIC {
|
|||||||
bool is_js_array,
|
bool is_js_array,
|
||||||
ElementsKind elements_kind);
|
ElementsKind elements_kind);
|
||||||
|
|
||||||
|
virtual bool IsGeneric() const {
|
||||||
|
return target() == *generic_stub();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
|
virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
|
||||||
|
|
||||||
@ -477,7 +486,7 @@ class KeyedLoadIC: public KeyedIC {
|
|||||||
Handle<Code> megamorphic_stub() {
|
Handle<Code> megamorphic_stub() {
|
||||||
return isolate()->builtins()->KeyedLoadIC_Generic();
|
return isolate()->builtins()->KeyedLoadIC_Generic();
|
||||||
}
|
}
|
||||||
Handle<Code> generic_stub() {
|
Handle<Code> generic_stub() const {
|
||||||
return isolate()->builtins()->KeyedLoadIC_Generic();
|
return isolate()->builtins()->KeyedLoadIC_Generic();
|
||||||
}
|
}
|
||||||
Handle<Code> pre_monomorphic_stub() {
|
Handle<Code> pre_monomorphic_stub() {
|
||||||
@ -595,6 +604,11 @@ class KeyedStoreIC: public KeyedIC {
|
|||||||
bool is_js_array,
|
bool is_js_array,
|
||||||
ElementsKind elements_kind);
|
ElementsKind elements_kind);
|
||||||
|
|
||||||
|
virtual bool IsGeneric() const {
|
||||||
|
return target() == *generic_stub() ||
|
||||||
|
target() == *generic_stub_strict();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
|
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
|
||||||
|
|
||||||
@ -632,10 +646,10 @@ class KeyedStoreIC: public KeyedIC {
|
|||||||
Handle<Code> megamorphic_stub_strict() {
|
Handle<Code> megamorphic_stub_strict() {
|
||||||
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
|
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
|
||||||
}
|
}
|
||||||
Handle<Code> generic_stub() {
|
Handle<Code> generic_stub() const {
|
||||||
return isolate()->builtins()->KeyedStoreIC_Generic();
|
return isolate()->builtins()->KeyedStoreIC_Generic();
|
||||||
}
|
}
|
||||||
Handle<Code> generic_stub_strict() {
|
Handle<Code> generic_stub_strict() const {
|
||||||
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
|
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
|
||||||
}
|
}
|
||||||
Handle<Code> non_strict_arguments_stub() {
|
Handle<Code> non_strict_arguments_stub() {
|
||||||
|
Loading…
Reference in New Issue
Block a user