Commit 65a18578 authored by jochen@chromium.org's avatar jochen@chromium.org

Currently, a new isolate is created in an uninitialized state, and

several API methods will automatically initialize it. During this
uninitialized state, code event handlers and function entry handlers can
be attached to the isolate.

This CL deprecates SetFunctionEntryHook and moves the configuration of
those handlers to the Isolate factory method.

This will allow for initializing the Isolate at creation time in the
future.

Users of V8::SetFunctionEntryHook should pass the entry hook to
Isolate::New instead. V8::SetJitCodeEventHandler should either be passed
to Isolate::New as well, or (if startup events are not required) invoked
via the Isolate.

BUG=none
LOG=y
R=svenpanne@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23940 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 734fd707
...@@ -4243,6 +4243,103 @@ class V8_EXPORT HeapStatistics { ...@@ -4243,6 +4243,103 @@ class V8_EXPORT HeapStatistics {
class RetainedObjectInfo; class RetainedObjectInfo;
/**
* FunctionEntryHook is the type of the profile entry hook called at entry to
* any generated function when function-level profiling is enabled.
*
* \param function the address of the function that's being entered.
* \param return_addr_location points to a location on stack where the machine
* return address resides. This can be used to identify the caller of
* \p function, and/or modified to divert execution when \p function exits.
*
* \note the entry hook must not cause garbage collection.
*/
typedef void (*FunctionEntryHook)(uintptr_t function,
uintptr_t return_addr_location);
/**
* A JIT code event is issued each time code is added, moved or removed.
*
* \note removal events are not currently issued.
*/
struct JitCodeEvent {
enum EventType {
CODE_ADDED,
CODE_MOVED,
CODE_REMOVED,
CODE_ADD_LINE_POS_INFO,
CODE_START_LINE_INFO_RECORDING,
CODE_END_LINE_INFO_RECORDING
};
// Definition of the code position type. The "POSITION" type means the place
// in the source code which are of interest when making stack traces to
// pin-point the source location of a stack frame as close as possible.
// The "STATEMENT_POSITION" means the place at the beginning of each
// statement, and is used to indicate possible break locations.
enum PositionType { POSITION, STATEMENT_POSITION };
// Type of event.
EventType type;
// Start of the instructions.
void* code_start;
// Size of the instructions.
size_t code_len;
// Script info for CODE_ADDED event.
Handle<UnboundScript> script;
// User-defined data for *_LINE_INFO_* event. It's used to hold the source
// code line information which is returned from the
// CODE_START_LINE_INFO_RECORDING event. And it's passed to subsequent
// CODE_ADD_LINE_POS_INFO and CODE_END_LINE_INFO_RECORDING events.
void* user_data;
struct name_t {
// Name of the object associated with the code, note that the string is not
// zero-terminated.
const char* str;
// Number of chars in str.
size_t len;
};
struct line_info_t {
// PC offset
size_t offset;
// Code postion
size_t pos;
// The position type.
PositionType position_type;
};
union {
// Only valid for CODE_ADDED.
struct name_t name;
// Only valid for CODE_ADD_LINE_POS_INFO
struct line_info_t line_info;
// New location of instructions. Only valid for CODE_MOVED.
void* new_code_start;
};
};
/**
* Option flags passed to the SetJitCodeEventHandler function.
*/
enum JitCodeEventOptions {
kJitCodeEventDefault = 0,
// Generate callbacks for already existent code.
kJitCodeEventEnumExisting = 1
};
/**
* Callback function passed to SetJitCodeEventHandler.
*
* \param event code add, move or removal event.
*/
typedef void (*JitCodeEventHandler)(const JitCodeEvent* event);
/** /**
* Isolate represents an isolated instance of the V8 engine. V8 * Isolate represents an isolated instance of the V8 engine. V8
* isolates have completely separate states. Objects from one isolate * isolates have completely separate states. Objects from one isolate
...@@ -4254,6 +4351,29 @@ class RetainedObjectInfo; ...@@ -4254,6 +4351,29 @@ class RetainedObjectInfo;
*/ */
class V8_EXPORT Isolate { class V8_EXPORT Isolate {
public: public:
/**
* Initial configuration parameters for a new Isolate.
*/
struct CreateParams {
CreateParams() : entry_hook(NULL), code_event_handler(NULL) {}
/**
* The optional entry_hook allows the host application to provide the
* address of a function that's invoked on entry to every V8-generated
* function. Note that entry_hook is invoked at the very start of each
* generated function. Furthermore, if an entry_hook is given, V8 will
* always run without a context snapshot.
*/
FunctionEntryHook entry_hook;
/**
* Allows the host application to provide the address of a function that is
* notified each time code is added, moved or removed.
*/
JitCodeEventHandler code_event_handler;
};
/** /**
* Stack-allocated class which sets the isolate for all operations * Stack-allocated class which sets the isolate for all operations
* executed within a local scope. * executed within a local scope.
...@@ -4362,7 +4482,7 @@ class V8_EXPORT Isolate { ...@@ -4362,7 +4482,7 @@ class V8_EXPORT Isolate {
* When an isolate is no longer used its resources should be freed * When an isolate is no longer used its resources should be freed
* by calling Dispose(). Using the delete operator is not allowed. * by calling Dispose(). Using the delete operator is not allowed.
*/ */
static Isolate* New(); static Isolate* New(const CreateParams& params = CreateParams());
/** /**
* Returns the entered isolate for the current thread or NULL in * Returns the entered isolate for the current thread or NULL in
...@@ -4672,6 +4792,31 @@ class V8_EXPORT Isolate { ...@@ -4672,6 +4792,31 @@ class V8_EXPORT Isolate {
*/ */
int ContextDisposedNotification(); int ContextDisposedNotification();
/**
* Allows the host application to provide the address of a function that is
* notified each time code is added, moved or removed.
*
* \param options options for the JIT code event handler.
* \param event_handler the JIT code event handler, which will be invoked
* each time code is added, moved or removed.
* \note \p event_handler won't get notified of existent code.
* \note since code removal notifications are not currently issued, the
* \p event_handler may get notifications of code that overlaps earlier
* code notifications. This happens when code areas are reused, and the
* earlier overlapping code areas should therefore be discarded.
* \note the events passed to \p event_handler and the strings they point to
* are not guaranteed to live past each call. The \p event_handler must
* copy strings and other parameters it needs to keep around.
* \note the set of events declared in JitCodeEvent::EventType is expected to
* grow over time, and the JitCodeEvent structure is expected to accrue
* new members. The \p event_handler function must ignore event codes
* it does not recognize to maintain future compatibility.
* \note Use Isolate::CreateParams to get events for code executed during
* Isolate setup.
*/
void SetJitCodeEventHandler(JitCodeEventOptions options,
JitCodeEventHandler event_handler);
private: private:
template<class K, class V, class Traits> friend class PersistentValueMap; template<class K, class V, class Traits> friend class PersistentValueMap;
...@@ -4750,106 +4895,6 @@ typedef uintptr_t (*ReturnAddressLocationResolver)( ...@@ -4750,106 +4895,6 @@ typedef uintptr_t (*ReturnAddressLocationResolver)(
uintptr_t return_addr_location); uintptr_t return_addr_location);
/**
* FunctionEntryHook is the type of the profile entry hook called at entry to
* any generated function when function-level profiling is enabled.
*
* \param function the address of the function that's being entered.
* \param return_addr_location points to a location on stack where the machine
* return address resides. This can be used to identify the caller of
* \p function, and/or modified to divert execution when \p function exits.
*
* \note the entry hook must not cause garbage collection.
*/
typedef void (*FunctionEntryHook)(uintptr_t function,
uintptr_t return_addr_location);
/**
* A JIT code event is issued each time code is added, moved or removed.
*
* \note removal events are not currently issued.
*/
struct JitCodeEvent {
enum EventType {
CODE_ADDED,
CODE_MOVED,
CODE_REMOVED,
CODE_ADD_LINE_POS_INFO,
CODE_START_LINE_INFO_RECORDING,
CODE_END_LINE_INFO_RECORDING
};
// Definition of the code position type. The "POSITION" type means the place
// in the source code which are of interest when making stack traces to
// pin-point the source location of a stack frame as close as possible.
// The "STATEMENT_POSITION" means the place at the beginning of each
// statement, and is used to indicate possible break locations.
enum PositionType {
POSITION,
STATEMENT_POSITION
};
// Type of event.
EventType type;
// Start of the instructions.
void* code_start;
// Size of the instructions.
size_t code_len;
// Script info for CODE_ADDED event.
Handle<UnboundScript> script;
// User-defined data for *_LINE_INFO_* event. It's used to hold the source
// code line information which is returned from the
// CODE_START_LINE_INFO_RECORDING event. And it's passed to subsequent
// CODE_ADD_LINE_POS_INFO and CODE_END_LINE_INFO_RECORDING events.
void* user_data;
struct name_t {
// Name of the object associated with the code, note that the string is not
// zero-terminated.
const char* str;
// Number of chars in str.
size_t len;
};
struct line_info_t {
// PC offset
size_t offset;
// Code postion
size_t pos;
// The position type.
PositionType position_type;
};
union {
// Only valid for CODE_ADDED.
struct name_t name;
// Only valid for CODE_ADD_LINE_POS_INFO
struct line_info_t line_info;
// New location of instructions. Only valid for CODE_MOVED.
void* new_code_start;
};
};
/**
* Option flags passed to the SetJitCodeEventHandler function.
*/
enum JitCodeEventOptions {
kJitCodeEventDefault = 0,
// Generate callbacks for already existent code.
kJitCodeEventEnumExisting = 1
};
/**
* Callback function passed to SetJitCodeEventHandler.
*
* \param event code add, move or removal event.
*/
typedef void (*JitCodeEventHandler)(const JitCodeEvent* event);
/** /**
* Interface for iterating through all external resources in the heap. * Interface for iterating through all external resources in the heap.
*/ */
...@@ -5069,6 +5114,8 @@ class V8_EXPORT V8 { ...@@ -5069,6 +5114,8 @@ class V8_EXPORT V8 {
* \returns true on success on supported platforms, false on failure. * \returns true on success on supported platforms, false on failure.
* \note Setting an entry hook can only be done very early in an isolates * \note Setting an entry hook can only be done very early in an isolates
* lifetime, and once set, the entry hook cannot be revoked. * lifetime, and once set, the entry hook cannot be revoked.
*
* Deprecated, will be removed. Use Isolate::New(entry_hook) instead.
*/ */
static bool SetFunctionEntryHook(Isolate* isolate, static bool SetFunctionEntryHook(Isolate* isolate,
FunctionEntryHook entry_hook); FunctionEntryHook entry_hook);
...@@ -5092,6 +5139,9 @@ class V8_EXPORT V8 { ...@@ -5092,6 +5139,9 @@ class V8_EXPORT V8 {
* grow over time, and the JitCodeEvent structure is expected to accrue * grow over time, and the JitCodeEvent structure is expected to accrue
* new members. The \p event_handler function must ignore event codes * new members. The \p event_handler function must ignore event codes
* it does not recognize to maintain future compatibility. * it does not recognize to maintain future compatibility.
*
* Deprecated, will be removed. Use Isolate::SetJitCodeEventHandler or
* Isolate::CreateParams instead.
*/ */
static void SetJitCodeEventHandler(JitCodeEventOptions options, static void SetJitCodeEventHandler(JitCodeEventOptions options,
JitCodeEventHandler event_handler); JitCodeEventHandler event_handler);
......
...@@ -6662,8 +6662,16 @@ Isolate* Isolate::GetCurrent() { ...@@ -6662,8 +6662,16 @@ Isolate* Isolate::GetCurrent() {
} }
Isolate* Isolate::New() { Isolate* Isolate::New(const Isolate::CreateParams& params) {
i::Isolate* isolate = new i::Isolate(); i::Isolate* isolate = new i::Isolate();
if (params.entry_hook) {
isolate->set_function_entry_hook(params.entry_hook);
}
if (params.code_event_handler) {
isolate->InitializeLoggingAndCounters();
isolate->logger()->SetCodeEventHandler(kJitCodeEventDefault,
params.code_event_handler);
}
return reinterpret_cast<Isolate*>(isolate); return reinterpret_cast<Isolate*>(isolate);
} }
...@@ -6872,6 +6880,15 @@ int v8::Isolate::ContextDisposedNotification() { ...@@ -6872,6 +6880,15 @@ int v8::Isolate::ContextDisposedNotification() {
} }
void v8::Isolate::SetJitCodeEventHandler(JitCodeEventOptions options,
JitCodeEventHandler event_handler) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
// Ensure that logging is initialized for our isolate.
isolate->InitializeLoggingAndCounters();
isolate->logger()->SetCodeEventHandler(options, event_handler);
}
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
: str_(NULL), length_(0) { : str_(NULL), length_(0) {
i::Isolate* isolate = i::Isolate::Current(); i::Isolate* isolate = i::Isolate::Current();
......
...@@ -1612,7 +1612,16 @@ int Shell::Main(int argc, char* argv[]) { ...@@ -1612,7 +1612,16 @@ int Shell::Main(int argc, char* argv[]) {
v8::V8::SetArrayBufferAllocator(&array_buffer_allocator); v8::V8::SetArrayBufferAllocator(&array_buffer_allocator);
} }
int result = 0; int result = 0;
Isolate* isolate = Isolate::New(); Isolate::CreateParams create_params;
#if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE)
if (i::FLAG_gdbjit) {
create_params.code_event_handler = i::GDBJITInterface::EventHandler;
}
#endif
#ifdef ENABLE_VTUNE_JIT_INTERFACE
vTune::InitializeVtuneForV8(create_params);
#endif
Isolate* isolate = Isolate::New(create_params);
#ifndef V8_SHARED #ifndef V8_SHARED
v8::ResourceConstraints constraints; v8::ResourceConstraints constraints;
constraints.ConfigureDefaults(base::SysInfo::AmountOfPhysicalMemory(), constraints.ConfigureDefaults(base::SysInfo::AmountOfPhysicalMemory(),
...@@ -1624,15 +1633,6 @@ int Shell::Main(int argc, char* argv[]) { ...@@ -1624,15 +1633,6 @@ int Shell::Main(int argc, char* argv[]) {
{ {
Isolate::Scope scope(isolate); Isolate::Scope scope(isolate);
Initialize(isolate); Initialize(isolate);
#if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE)
if (i::FLAG_gdbjit) {
v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault,
i::GDBJITInterface::EventHandler);
}
#endif
#ifdef ENABLE_VTUNE_JIT_INTERFACE
vTune::InitializeVtuneForV8();
#endif
PerIsolateData data(isolate); PerIsolateData data(isolate);
InitializeDebugger(isolate); InitializeDebugger(isolate);
......
include_rules = [
"+../../../include",
]
...@@ -58,9 +58,11 @@ ...@@ -58,9 +58,11 @@
#ifndef V8_VTUNE_H_ #ifndef V8_VTUNE_H_
#define V8_VTUNE_H_ #define V8_VTUNE_H_
#include "../../../include/v8.h"
namespace vTune { namespace vTune {
void InitializeVtuneForV8(); void InitializeVtuneForV8(v8::Isolate::CreateParams& params);
} // namespace vTune } // namespace vTune
......
...@@ -271,13 +271,10 @@ void VTUNEJITInterface::event_handler(const v8::JitCodeEvent* event) { ...@@ -271,13 +271,10 @@ void VTUNEJITInterface::event_handler(const v8::JitCodeEvent* event) {
} // namespace internal } // namespace internal
void InitializeVtuneForV8() { void InitializeVtuneForV8(v8::Isolate::CreateParams& params) {
if (v8::V8::Initialize()) {
v8::V8::SetFlagsFromString("--nocompact_code_space", v8::V8::SetFlagsFromString("--nocompact_code_space",
(int)strlen("--nocompact_code_space")); (int)strlen("--nocompact_code_space"));
v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, params.code_event_handler = vTune::internal::VTUNEJITInterface::event_handler;
vTune::internal::VTUNEJITInterface::event_handler);
}
} }
} // namespace vTune } // namespace vTune
...@@ -14171,19 +14171,14 @@ void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) { ...@@ -14171,19 +14171,14 @@ void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
void SetFunctionEntryHookTest::RunTest() { void SetFunctionEntryHookTest::RunTest() {
// Work in a new isolate throughout. // Work in a new isolate throughout.
v8::Isolate* isolate = v8::Isolate::New(); v8::Isolate::CreateParams create_params;
create_params.entry_hook = EntryHook;
// Test setting the entry hook on the new isolate. create_params.code_event_handler = JitEvent;
CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook)); v8::Isolate* isolate = v8::Isolate::New(create_params);
// Replacing the hook, once set should fail.
CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
{ {
v8::Isolate::Scope scope(isolate); v8::Isolate::Scope scope(isolate);
v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
RunLoopInNewEnv(isolate); RunLoopInNewEnv(isolate);
// Check the exepected invocation counts. // Check the exepected invocation counts.
...@@ -14211,9 +14206,6 @@ void SetFunctionEntryHookTest::RunTest() { ...@@ -14211,9 +14206,6 @@ void SetFunctionEntryHookTest::RunTest() {
// We should record no invocations in this isolate. // We should record no invocations in this isolate.
CHECK_EQ(0, static_cast<int>(invocations_.size())); CHECK_EQ(0, static_cast<int>(invocations_.size()));
} }
// Since the isolate has been used, we shouldn't be able to set an entry
// hook anymore.
CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
isolate->Dispose(); isolate->Dispose();
} }
...@@ -14407,7 +14399,7 @@ UNINITIALIZED_TEST(SetJitCodeEventHandler) { ...@@ -14407,7 +14399,7 @@ UNINITIALIZED_TEST(SetJitCodeEventHandler) {
saw_bar = 0; saw_bar = 0;
move_events = 0; move_events = 0;
V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler); isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
// Generate new code objects sparsely distributed across several // Generate new code objects sparsely distributed across several
// different fragmented code-space pages. // different fragmented code-space pages.
...@@ -14431,7 +14423,7 @@ UNINITIALIZED_TEST(SetJitCodeEventHandler) { ...@@ -14431,7 +14423,7 @@ UNINITIALIZED_TEST(SetJitCodeEventHandler) {
// Force code movement. // Force code movement.
heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler"); heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL); isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
CHECK_LE(kIterations, saw_bar); CHECK_LE(kIterations, saw_bar);
CHECK_LT(0, move_events); CHECK_LT(0, move_events);
...@@ -14461,8 +14453,9 @@ UNINITIALIZED_TEST(SetJitCodeEventHandler) { ...@@ -14461,8 +14453,9 @@ UNINITIALIZED_TEST(SetJitCodeEventHandler) {
i::HashMap lineinfo(MatchPointers); i::HashMap lineinfo(MatchPointers);
jitcode_line_info = &lineinfo; jitcode_line_info = &lineinfo;
V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler); isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL); event_handler);
isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
jitcode_line_info = NULL; jitcode_line_info = NULL;
// We expect that we got some events. Note that if we could get code removal // We expect that we got some events. Note that if we could get code removal
......
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