--trace-ic: much faster and available in Release mode.

Also add IC tracing to a path where it was missing.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/368833003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22268 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a0dadc8b
...@@ -536,6 +536,7 @@ DEFINE_BOOL(use_idle_notification, true, ...@@ -536,6 +536,7 @@ DEFINE_BOOL(use_idle_notification, true,
"Use idle notification to reduce memory footprint.") "Use idle notification to reduce memory footprint.")
// ic.cc // ic.cc
DEFINE_BOOL(use_ic, true, "use inline caching") DEFINE_BOOL(use_ic, true, "use inline caching")
DEFINE_BOOL(trace_ic, false, "trace inline cache state transitions")
// macro-assembler-ia32.cc // macro-assembler-ia32.cc
DEFINE_BOOL(native_code_counters, false, DEFINE_BOOL(native_code_counters, false,
...@@ -724,9 +725,6 @@ DEFINE_BOOL(verify_native_context_separation, false, ...@@ -724,9 +725,6 @@ DEFINE_BOOL(verify_native_context_separation, false,
DEFINE_BOOL(print_handles, false, "report handles after GC") DEFINE_BOOL(print_handles, false, "report handles after GC")
DEFINE_BOOL(print_global_handles, false, "report global handles after GC") DEFINE_BOOL(print_global_handles, false, "report global handles after GC")
// ic.cc
DEFINE_BOOL(trace_ic, false, "trace inline cache state transitions")
// interface.cc // interface.cc
DEFINE_BOOL(print_interfaces, false, "print interfaces") DEFINE_BOOL(print_interfaces, false, "print interfaces")
DEFINE_BOOL(print_interface_details, false, "print interface inference details") DEFINE_BOOL(print_interface_details, false, "print interface inference details")
......
...@@ -777,28 +777,15 @@ void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { ...@@ -777,28 +777,15 @@ void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
} }
void JavaScriptFrame::PrintTop(Isolate* isolate, void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
FILE* file, Address pc, FILE* file,
bool print_args,
bool print_line_number) { bool print_line_number) {
// constructor calls PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
DisallowHeapAllocation no_allocation; function->PrintName(file);
JavaScriptFrameIterator it(isolate); int code_offset = static_cast<int>(pc - code->instruction_start());
while (!it.done()) { PrintF(file, "+%d", code_offset);
if (it.frame()->is_java_script()) {
JavaScriptFrame* frame = it.frame();
if (frame->IsConstructor()) PrintF(file, "new ");
// function name
JSFunction* fun = frame->function();
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) {
Code* code = Code::cast(isolate->FindCodeObject(pc)); SharedFunctionInfo* shared = function->shared();
int source_pos = code->SourcePosition(pc); int source_pos = code->SourcePosition(pc);
Object* maybe_script = shared->script(); Object* maybe_script = shared->script();
if (maybe_script->IsScript()) { if (maybe_script->IsScript()) {
...@@ -808,8 +795,7 @@ void JavaScriptFrame::PrintTop(Isolate* isolate, ...@@ -808,8 +795,7 @@ void JavaScriptFrame::PrintTop(Isolate* isolate,
if (script_name_raw->IsString()) { if (script_name_raw->IsString()) {
String* script_name = String::cast(script->name()); String* script_name = String::cast(script->name());
SmartArrayPointer<char> c_script_name = SmartArrayPointer<char> c_script_name =
script_name->ToCString(DISALLOW_NULLS, script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ROBUST_STRING_TRAVERSAL);
PrintF(file, " at %s:%d", c_script_name.get(), line); PrintF(file, " at %s:%d", c_script_name.get(), line);
} else { } else {
PrintF(file, " at <unknown>:%d", line); PrintF(file, " at <unknown>:%d", line);
...@@ -818,7 +804,20 @@ void JavaScriptFrame::PrintTop(Isolate* isolate, ...@@ -818,7 +804,20 @@ void JavaScriptFrame::PrintTop(Isolate* isolate,
PrintF(file, " at <unknown>:<unknown>"); PrintF(file, " at <unknown>:<unknown>");
} }
} }
}
void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
bool print_line_number) {
// constructor calls
DisallowHeapAllocation no_allocation;
JavaScriptFrameIterator it(isolate);
while (!it.done()) {
if (it.frame()->is_java_script()) {
JavaScriptFrame* frame = it.frame();
if (frame->IsConstructor()) PrintF(file, "new ");
PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
frame->pc(), file, print_line_number);
if (print_args) { if (print_args) {
// function arguments // function arguments
// (we are intentionally only printing the actually // (we are intentionally only printing the actually
......
...@@ -614,9 +614,11 @@ class JavaScriptFrame: public StandardFrame { ...@@ -614,9 +614,11 @@ class JavaScriptFrame: public StandardFrame {
return static_cast<JavaScriptFrame*>(frame); return static_cast<JavaScriptFrame*>(frame);
} }
static void PrintTop(Isolate* isolate, static void PrintFunctionAndOffset(JSFunction* function, Code* code,
FILE* file, Address pc, FILE* file,
bool print_args, bool print_line_number);
static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
bool print_line_number); bool print_line_number);
protected: protected:
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
#ifdef DEBUG
char IC::TransitionMarkFromState(IC::State state) { char IC::TransitionMarkFromState(IC::State state) {
switch (state) { switch (state) {
case UNINITIALIZED: return '0'; case UNINITIALIZED: return '0';
...@@ -48,25 +47,43 @@ const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { ...@@ -48,25 +47,43 @@ const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
} }
void IC::TraceIC(const char* type, #ifdef DEBUG
Handle<Object> name) {
#define TRACE_GENERIC_IC(isolate, type, reason) \
do { \
if (FLAG_trace_ic) { \
PrintF("[%s patching generic stub in ", type); \
JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
PrintF(" (%s)]\n", reason); \
} \
} while (false)
#else
#define TRACE_GENERIC_IC(isolate, type, reason)
#endif // DEBUG
void IC::TraceIC(const char* type, Handle<Object> name) {
if (FLAG_trace_ic) { if (FLAG_trace_ic) {
Code* new_target = raw_target(); Code* new_target = raw_target();
State new_state = new_target->ic_state(); State new_state = new_target->ic_state();
PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type); PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
StackFrameIterator it(isolate());
while (it.frame()->fp() != this->fp()) it.Advance(); // TODO(jkummerow): Add support for "apply". The logic is roughly:
StackFrame* raw_frame = it.frame(); // marker = [fp_ + kMarkerOffset];
if (raw_frame->is_internal()) { // if marker is smi and marker.value == INTERNAL and
Code* apply_builtin = isolate()->builtins()->builtin( // the frame's code == builtin(Builtins::kFunctionApply):
Builtins::kFunctionApply); // then print "apply from" and advance one frame
if (raw_frame->unchecked_code() == apply_builtin) {
PrintF("apply from "); Object* maybe_function =
it.Advance(); Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
raw_frame = it.frame(); if (maybe_function->IsJSFunction()) {
} JSFunction* function = JSFunction::cast(maybe_function);
JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(),
stdout, true);
} }
JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
ExtraICState extra_state = new_target->extra_ic_state(); ExtraICState extra_state = new_target->extra_ic_state();
const char* modifier = ""; const char* modifier = "";
if (new_target->kind() == Code::KEYED_STORE_IC) { if (new_target->kind() == Code::KEYED_STORE_IC) {
...@@ -83,21 +100,8 @@ void IC::TraceIC(const char* type, ...@@ -83,21 +100,8 @@ void IC::TraceIC(const char* type,
} }
} }
#define TRACE_GENERIC_IC(isolate, type, reason) \ #define TRACE_IC(type, name) TraceIC(type, name)
do { \
if (FLAG_trace_ic) { \
PrintF("[%s patching generic stub in ", type); \
JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
PrintF(" (%s)]\n", reason); \
} \
} while (false)
#else
#define TRACE_GENERIC_IC(isolate, type, reason)
#endif // DEBUG
#define TRACE_IC(type, name) \
ASSERT((TraceIC(type, name), true))
IC::IC(FrameDepth depth, Isolate* isolate) IC::IC(FrameDepth depth, Isolate* isolate)
: isolate_(isolate), : isolate_(isolate),
...@@ -616,7 +620,11 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<String> name) { ...@@ -616,7 +620,11 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<String> name) {
uint32_t index; uint32_t index;
if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
// Rewrite to the generic keyed load stub. // Rewrite to the generic keyed load stub.
if (FLAG_use_ic) set_target(*generic_stub()); if (FLAG_use_ic) {
set_target(*generic_stub());
TRACE_IC("LoadIC", name);
TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
}
Handle<Object> result; Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION( ASSIGN_RETURN_ON_EXCEPTION(
isolate(), isolate(),
......
...@@ -170,11 +170,8 @@ class IC { ...@@ -170,11 +170,8 @@ class IC {
bool is_target_set() { return target_set_; } bool is_target_set() { return target_set_; }
#ifdef DEBUG
char TransitionMarkFromState(IC::State state); char TransitionMarkFromState(IC::State state);
void TraceIC(const char* type, Handle<Object> name); void TraceIC(const char* type, Handle<Object> name);
#endif
MaybeHandle<Object> TypeError(const char* type, MaybeHandle<Object> TypeError(const char* type,
Handle<Object> object, Handle<Object> object,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment