Adding support for reporting addresses of JIT compiled code to OProfile.

Please be warned that current gHardy versions have OProfile 0.9.3
which doesn't have JIT API. You need to install OProfile 0.9.4
with a 32-bit version of opagent library. Instructions are on the
internal Wiki page: http://wiki/Main/V8UsingOProfile

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


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1426 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 86254f6a
......@@ -68,6 +68,9 @@ LIBRARY_FLAGS = {
'wordsize:64': {
'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32']
},
'prof:oprofile': {
'CPPDEFINES': ['ENABLE_OPROFILE_AGENT']
}
},
'msvc': {
......@@ -249,6 +252,10 @@ SAMPLE_FLAGS = {
},
'mode:debug': {
'CCFLAGS': ['-g', '-O0']
},
'prof:oprofile': {
'LIBPATH': ['/usr/lib32', '/usr/lib32/oprofile'],
'LIBS': ['opagent']
}
},
'msvc': {
......@@ -362,7 +369,7 @@ SIMPLE_OPTIONS = {
'help': 'build using snapshots for faster start-up'
},
'prof': {
'values': ['on', 'off'],
'values': ['on', 'off', 'oprofile'],
'default': 'off',
'help': 'enable profiling of build target'
},
......@@ -435,6 +442,8 @@ def VerifyOptions(env):
return False
if env['os'] == 'win32' and env['library'] == 'shared' and env['prof'] == 'on':
Abort("Profiling on windows only supported for static library.")
if env['prof'] == 'oprofile' and env['os'] != 'linux':
Abort("OProfile is only supported on Linux.")
for (name, option) in SIMPLE_OPTIONS.iteritems():
if (not option.get('default')) and (name not in ARGUMENTS):
message = ("A value for option %s must be specified (%s)." %
......
......@@ -67,7 +67,7 @@ SOURCES = {
],
'simulator:arm': ['simulator-arm.cc'],
'os:freebsd': ['platform-freebsd.cc'],
'os:linux': ['platform-linux.cc'],
'os:linux': ['platform-linux.cc', 'oprofile-agent.cc'],
'os:macos': ['platform-macos.cc'],
'os:nullos': ['platform-nullos.cc'],
'os:win32': ['platform-win32.cc'],
......
......@@ -35,6 +35,7 @@
#include "scopes.h"
#include "rewriter.h"
#include "usage-analyzer.h"
#include "oprofile-agent.h"
namespace v8 { namespace internal {
......@@ -123,16 +124,20 @@ static Handle<JSFunction> MakeFunction(bool is_global,
return Handle<JSFunction>::null();
}
#ifdef ENABLE_LOGGING_AND_PROFILING
#if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
// Log the code generation for the script. Check explicit whether logging is
// to avoid allocating when not required.
if (Logger::is_enabled()) {
if (Logger::is_enabled() || OProfileAgent::is_enabled()) {
if (script->name()->IsString()) {
SmartPointer<char> data =
String::cast(script->name())->ToCString(DISALLOW_NULLS);
LOG(CodeCreateEvent(is_eval ? "Eval" : "Script", *code, *data));
OProfileAgent::CreateNativeCodeRegion(*data, code->address(),
code->ExecutableSize());
} else {
LOG(CodeCreateEvent(is_eval ? "Eval" : "Script", *code, ""));
OProfileAgent::CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
code->address(), code->ExecutableSize());
}
}
#endif
......@@ -306,11 +311,11 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
return false;
}
#ifdef ENABLE_LOGGING_AND_PROFILING
#if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
// Log the code generation. If source information is available include script
// name and line number. Check explicit whether logging is enabled as finding
// the line number is not for free.
if (Logger::is_enabled()) {
if (Logger::is_enabled() || OProfileAgent::is_enabled()) {
if (script->name()->IsString()) {
int line_num = script->GetLineNumber(start_position);
if (line_num > 0) {
......@@ -318,8 +323,14 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
}
LOG(CodeCreateEvent("LazyCompile", *code, *lit->name(),
String::cast(script->name()), line_num));
OProfileAgent::CreateNativeCodeRegion(*lit->name(),
String::cast(script->name()),
line_num, code->address(),
code->ExecutableSize());
} else {
LOG(CodeCreateEvent("LazyCompile", *code, *lit->name()));
OProfileAgent::CreateNativeCodeRegion(*lit->name(), code->address(),
code->ExecutableSize());
}
}
#endif
......
......@@ -334,6 +334,8 @@ DEFINE_bool(log_regexp, false, "Log regular expression execution.")
DEFINE_bool(sliding_state_window, false,
"Update sliding state window counters.")
DEFINE_string(logfile, "v8.log", "Specify the name of the log file.")
DEFINE_bool(oprofile, false,
"Enable JIT agent for OProfile.")
//
// Disassembler only flags
......
......@@ -711,24 +711,13 @@ void Logger::DeleteEvent(const char* name, void* object) {
}
#ifdef ENABLE_LOGGING_AND_PROFILING
int Logger::CodeObjectSize(Code* code) {
// Check that the assumptions about the layout of the code object holds.
ASSERT_EQ(reinterpret_cast<unsigned int>(code->instruction_start()) -
reinterpret_cast<unsigned int>(code->address()),
Code::kHeaderSize);
return code->instruction_size() + Code::kHeaderSize;
}
#endif
void Logger::CodeCreateEvent(const char* tag, Code* code, const char* comment) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
LogMessageBuilder msg;
msg.Append("code-creation,%s,0x%x,%d,\"", tag,
reinterpret_cast<unsigned int>(code->address()),
CodeObjectSize(code));
code->ExecutableSize());
for (const char* p = comment; *p != '\0'; p++) {
if (*p == '"') {
msg.Append('\\');
......@@ -750,7 +739,7 @@ void Logger::CodeCreateEvent(const char* tag, Code* code, String* name) {
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("code-creation,%s,0x%x,%d,\"%s\"\n", tag,
reinterpret_cast<unsigned int>(code->address()),
CodeObjectSize(code), *str);
code->ExecutableSize(), *str);
msg.WriteToLogFile();
#endif
}
......@@ -767,7 +756,7 @@ void Logger::CodeCreateEvent(const char* tag, Code* code, String* name,
source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("code-creation,%s,0x%x,%d,\"%s %s:%d\"\n", tag,
reinterpret_cast<unsigned int>(code->address()),
CodeObjectSize(code),
code->ExecutableSize(),
*str, *sourcestr, line);
msg.WriteToLogFile();
#endif
......@@ -780,7 +769,7 @@ void Logger::CodeCreateEvent(const char* tag, Code* code, int args_count) {
LogMessageBuilder msg;
msg.Append("code-creation,%s,0x%x,%d,\"args_count: %d\"\n", tag,
reinterpret_cast<unsigned int>(code->address()),
CodeObjectSize(code),
code->ExecutableSize(),
args_count);
msg.WriteToLogFile();
#endif
......
......@@ -215,10 +215,6 @@ class Logger {
private:
// Calculate the size of the code object to report for log events. This takes
// the layout of the code object into account.
static int CodeObjectSize(Code* code);
// Emits the source code of a regexp. Used by regexp events.
static void LogRegExpSource(Handle<JSRegExp> regexp);
......@@ -268,6 +264,8 @@ class Logger {
friend class Profiler;
friend class SlidingStateWindow;
friend class VMState;
#else
static bool is_enabled() { return false; }
#endif
};
......
......@@ -2258,6 +2258,16 @@ class Code: public HeapObject {
return RoundUp(kHeaderSize + body_size + sinfo_size, kCodeAlignment);
}
// Calculate the size of the code object to report for log events. This takes
// the layout of the code object into account.
int ExecutableSize() {
// Check that the assumptions about the layout of the code object holds.
ASSERT_EQ(reinterpret_cast<unsigned int>(instruction_start()) -
reinterpret_cast<unsigned int>(address()),
Code::kHeaderSize);
return instruction_size() + Code::kHeaderSize;
}
// Locating source position.
int SourcePosition(Address pc);
int SourceStatementPosition(Address pc);
......
// Copyright 2006-2009 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:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h"
#include "oprofile-agent.h"
namespace v8 { namespace internal {
#ifdef ENABLE_OPROFILE_AGENT
op_agent_t OProfileAgent::handle_ = NULL;
#endif
bool OProfileAgent::Initialize() {
#ifdef ENABLE_OPROFILE_AGENT
if (FLAG_oprofile) {
if (handle_ != NULL) return false;
// Disable code moving by GC.
FLAG_always_compact = false;
FLAG_never_compact = true;
handle_ = op_open_agent();
return (handle_ != NULL);
} else {
return true;
}
#else
return true;
#endif
}
void OProfileAgent::TearDown() {
#ifdef ENABLE_OPROFILE_AGENT
if (handle_ != NULL) {
op_close_agent(handle_);
}
#endif
}
void OProfileAgent::CreateNativeCodeRegion(const char* name,
const void* ptr, unsigned int size) {
#ifdef ENABLE_OPROFILE_AGENT
if (handle_ == NULL) return;
op_write_native_code(handle_, name, (uint64_t)ptr, ptr, size);
#endif
}
void OProfileAgent::CreateNativeCodeRegion(String* name,
const void* ptr, unsigned int size) {
#ifdef ENABLE_OPROFILE_AGENT
if (handle_ != NULL) {
const char* func_name;
SmartPointer<char> str =
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
func_name = name->length() > 0 ? *str : "<anonymous>";
CreateNativeCodeRegion(func_name, ptr, size);
}
#endif
}
void OProfileAgent::CreateNativeCodeRegion(String* name, String* source,
int line_num, const void* ptr, unsigned int size) {
#ifdef ENABLE_OPROFILE_AGENT
if (handle_ != NULL) {
Vector<char> buf = Vector<char>::New(OProfileAgent::kFormattingBufSize);
const char* func_name;
SmartPointer<char> str =
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
func_name = name->length() > 0 ? *str : "<anonymous>";
SmartPointer<char> source_str =
source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
if (v8::internal::OS::SNPrintF(buf, "%s %s:%d",
func_name, *source_str, line_num) != -1) {
CreateNativeCodeRegion(buf.start(), ptr, size);
} else {
CreateNativeCodeRegion("<script/func name too long>", ptr, size);
}
}
#endif
}
} }
// Copyright 2006-2009 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:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_OPROFILE_AGENT_H_
#define V8_OPROFILE_AGENT_H_
#include <stdlib.h>
#include "globals.h"
#ifdef ENABLE_OPROFILE_AGENT
// opagent.h uses uint64_t type, which can be missing in
// system headers (they have __uint64_t), but is defined
// in V8's headers.
#include <opagent.h> // NOLINT
#endif
namespace v8 { namespace internal {
class OProfileAgent {
public:
static bool Initialize();
static void TearDown();
static void CreateNativeCodeRegion(const char* name,
const void* ptr, unsigned int size);
static void CreateNativeCodeRegion(String* name,
const void* ptr, unsigned int size);
static void CreateNativeCodeRegion(String* name, String* source, int line_num,
const void* ptr, unsigned int size);
#ifdef ENABLE_OPROFILE_AGENT
static bool is_enabled() { return handle_ != NULL; }
private:
static op_agent_t handle_;
// Size of the buffer that is used for composing code areas names.
static const int kFormattingBufSize = 256;
#else
static bool is_enabled() { return false; }
#endif
};
} }
#endif // V8_OPROFILE_AGENT_H_
......@@ -31,6 +31,7 @@
#include "debug.h"
#include "serialize.h"
#include "stub-cache.h"
#include "oprofile-agent.h"
namespace v8 { namespace internal {
......@@ -85,6 +86,8 @@ bool V8::Initialize(Deserializer *des) {
// objects in place for creating the code object used for probing.
CPU::Setup();
OProfileAgent::Initialize();
return true;
}
......@@ -93,6 +96,8 @@ void V8::TearDown() {
if (HasBeenDisposed()) return;
if (!HasBeenSetup()) return;
OProfileAgent::TearDown();
if (FLAG_preemption) {
v8::Locker locker;
v8::Locker::StopPreemption();
......
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