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();
|
||||
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);
|
||||
if (print_line_number) {
|
||||
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) {
|
||||
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) {
|
||||
|
@ -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;
|
||||
|
||||
|
41
src/ic.cc
41
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);
|
||||
|
26
src/ic.h
26
src/ic.h
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user