add v8 prebuilt for mac
This commit is contained in:
parent
0884b4fb1b
commit
5b656c362f
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_LIBPLATFORM_LIBPLATFORM_EXPORT_H_
|
||||
#define V8_LIBPLATFORM_LIBPLATFORM_EXPORT_H_
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#ifdef BUILDING_V8_PLATFORM_SHARED
|
||||
#define V8_PLATFORM_EXPORT __declspec(dllexport)
|
||||
#elif USING_V8_PLATFORM_SHARED
|
||||
#define V8_PLATFORM_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define V8_PLATFORM_EXPORT
|
||||
#endif // BUILDING_V8_PLATFORM_SHARED
|
||||
|
||||
#else // defined(_WIN32)
|
||||
|
||||
// Setup for Linux shared library export.
|
||||
#ifdef BUILDING_V8_PLATFORM_SHARED
|
||||
#define V8_PLATFORM_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define V8_PLATFORM_EXPORT
|
||||
#endif
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#endif // V8_LIBPLATFORM_LIBPLATFORM_EXPORT_H_
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_LIBPLATFORM_LIBPLATFORM_H_
|
||||
#define V8_LIBPLATFORM_LIBPLATFORM_H_
|
||||
|
||||
#include "libplatform/libplatform-export.h"
|
||||
#include "libplatform/v8-tracing.h"
|
||||
#include "v8-platform.h" // NOLINT(build/include)
|
||||
|
||||
namespace v8 {
|
||||
namespace platform {
|
||||
|
||||
enum class IdleTaskSupport { kDisabled, kEnabled };
|
||||
enum class InProcessStackDumping { kDisabled, kEnabled };
|
||||
|
||||
enum class MessageLoopBehavior : bool {
|
||||
kDoNotWait = false,
|
||||
kWaitForWork = true
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a new instance of the default v8::Platform implementation.
|
||||
*
|
||||
* The caller will take ownership of the returned pointer. |thread_pool_size|
|
||||
* is the number of worker threads to allocate for background jobs. If a value
|
||||
* of zero is passed, a suitable default based on the current number of
|
||||
* processors online will be chosen.
|
||||
* If |idle_task_support| is enabled then the platform will accept idle
|
||||
* tasks (IdleTasksEnabled will return true) and will rely on the embedder
|
||||
* calling v8::platform::RunIdleTasks to process the idle tasks.
|
||||
*/
|
||||
V8_PLATFORM_EXPORT v8::Platform* CreateDefaultPlatform(
|
||||
int thread_pool_size = 0,
|
||||
IdleTaskSupport idle_task_support = IdleTaskSupport::kDisabled,
|
||||
InProcessStackDumping in_process_stack_dumping =
|
||||
InProcessStackDumping::kEnabled);
|
||||
|
||||
/**
|
||||
* Pumps the message loop for the given isolate.
|
||||
*
|
||||
* The caller has to make sure that this is called from the right thread.
|
||||
* Returns true if a task was executed, and false otherwise. Unless requested
|
||||
* through the |behavior| parameter, this call does not block if no task is
|
||||
* pending. The |platform| has to be created using |CreateDefaultPlatform|.
|
||||
*/
|
||||
V8_PLATFORM_EXPORT bool PumpMessageLoop(
|
||||
v8::Platform* platform, v8::Isolate* isolate,
|
||||
MessageLoopBehavior behavior = MessageLoopBehavior::kDoNotWait);
|
||||
|
||||
V8_PLATFORM_EXPORT void EnsureEventLoopInitialized(v8::Platform* platform,
|
||||
v8::Isolate* isolate);
|
||||
|
||||
/**
|
||||
* Runs pending idle tasks for at most |idle_time_in_seconds| seconds.
|
||||
*
|
||||
* The caller has to make sure that this is called from the right thread.
|
||||
* This call does not block if no task is pending. The |platform| has to be
|
||||
* created using |CreateDefaultPlatform|.
|
||||
*/
|
||||
V8_PLATFORM_EXPORT void RunIdleTasks(v8::Platform* platform,
|
||||
v8::Isolate* isolate,
|
||||
double idle_time_in_seconds);
|
||||
|
||||
/**
|
||||
* Attempts to set the tracing controller for the given platform.
|
||||
*
|
||||
* The |platform| has to be created using |CreateDefaultPlatform|.
|
||||
*/
|
||||
V8_PLATFORM_EXPORT void SetTracingController(
|
||||
v8::Platform* platform,
|
||||
v8::platform::tracing::TracingController* tracing_controller);
|
||||
|
||||
} // namespace platform
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_LIBPLATFORM_LIBPLATFORM_H_
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_LIBPLATFORM_V8_TRACING_H_
|
||||
#define V8_LIBPLATFORM_V8_TRACING_H_
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "libplatform/libplatform-export.h"
|
||||
#include "v8-platform.h" // NOLINT(build/include)
|
||||
|
||||
namespace v8 {
|
||||
|
||||
namespace base {
|
||||
class Mutex;
|
||||
} // namespace base
|
||||
|
||||
namespace platform {
|
||||
namespace tracing {
|
||||
|
||||
const int kTraceMaxNumArgs = 2;
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceObject {
|
||||
public:
|
||||
union ArgValue {
|
||||
bool as_bool;
|
||||
uint64_t as_uint;
|
||||
int64_t as_int;
|
||||
double as_double;
|
||||
const void* as_pointer;
|
||||
const char* as_string;
|
||||
};
|
||||
|
||||
TraceObject() {}
|
||||
~TraceObject();
|
||||
void Initialize(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values,
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
|
||||
unsigned int flags);
|
||||
void UpdateDuration();
|
||||
void InitializeForTesting(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values,
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
|
||||
unsigned int flags, int pid, int tid, int64_t ts, int64_t tts,
|
||||
uint64_t duration, uint64_t cpu_duration);
|
||||
|
||||
int pid() const { return pid_; }
|
||||
int tid() const { return tid_; }
|
||||
char phase() const { return phase_; }
|
||||
const uint8_t* category_enabled_flag() const {
|
||||
return category_enabled_flag_;
|
||||
}
|
||||
const char* name() const { return name_; }
|
||||
const char* scope() const { return scope_; }
|
||||
uint64_t id() const { return id_; }
|
||||
uint64_t bind_id() const { return bind_id_; }
|
||||
int num_args() const { return num_args_; }
|
||||
const char** arg_names() { return arg_names_; }
|
||||
uint8_t* arg_types() { return arg_types_; }
|
||||
ArgValue* arg_values() { return arg_values_; }
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables() {
|
||||
return arg_convertables_;
|
||||
}
|
||||
unsigned int flags() const { return flags_; }
|
||||
int64_t ts() { return ts_; }
|
||||
int64_t tts() { return tts_; }
|
||||
uint64_t duration() { return duration_; }
|
||||
uint64_t cpu_duration() { return cpu_duration_; }
|
||||
|
||||
private:
|
||||
int pid_;
|
||||
int tid_;
|
||||
char phase_;
|
||||
const char* name_;
|
||||
const char* scope_;
|
||||
const uint8_t* category_enabled_flag_;
|
||||
uint64_t id_;
|
||||
uint64_t bind_id_;
|
||||
int num_args_ = 0;
|
||||
const char* arg_names_[kTraceMaxNumArgs];
|
||||
uint8_t arg_types_[kTraceMaxNumArgs];
|
||||
ArgValue arg_values_[kTraceMaxNumArgs];
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>
|
||||
arg_convertables_[kTraceMaxNumArgs];
|
||||
char* parameter_copy_storage_ = nullptr;
|
||||
unsigned int flags_;
|
||||
int64_t ts_;
|
||||
int64_t tts_;
|
||||
uint64_t duration_;
|
||||
uint64_t cpu_duration_;
|
||||
|
||||
// Disallow copy and assign
|
||||
TraceObject(const TraceObject&) = delete;
|
||||
void operator=(const TraceObject&) = delete;
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceWriter {
|
||||
public:
|
||||
TraceWriter() {}
|
||||
virtual ~TraceWriter() {}
|
||||
virtual void AppendTraceEvent(TraceObject* trace_event) = 0;
|
||||
virtual void Flush() = 0;
|
||||
|
||||
static TraceWriter* CreateJSONTraceWriter(std::ostream& stream);
|
||||
|
||||
private:
|
||||
// Disallow copy and assign
|
||||
TraceWriter(const TraceWriter&) = delete;
|
||||
void operator=(const TraceWriter&) = delete;
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceBufferChunk {
|
||||
public:
|
||||
explicit TraceBufferChunk(uint32_t seq);
|
||||
|
||||
void Reset(uint32_t new_seq);
|
||||
bool IsFull() const { return next_free_ == kChunkSize; }
|
||||
TraceObject* AddTraceEvent(size_t* event_index);
|
||||
TraceObject* GetEventAt(size_t index) { return &chunk_[index]; }
|
||||
|
||||
uint32_t seq() const { return seq_; }
|
||||
size_t size() const { return next_free_; }
|
||||
|
||||
static const size_t kChunkSize = 64;
|
||||
|
||||
private:
|
||||
size_t next_free_ = 0;
|
||||
TraceObject chunk_[kChunkSize];
|
||||
uint32_t seq_;
|
||||
|
||||
// Disallow copy and assign
|
||||
TraceBufferChunk(const TraceBufferChunk&) = delete;
|
||||
void operator=(const TraceBufferChunk&) = delete;
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceBuffer {
|
||||
public:
|
||||
TraceBuffer() {}
|
||||
virtual ~TraceBuffer() {}
|
||||
|
||||
virtual TraceObject* AddTraceEvent(uint64_t* handle) = 0;
|
||||
virtual TraceObject* GetEventByHandle(uint64_t handle) = 0;
|
||||
virtual bool Flush() = 0;
|
||||
|
||||
static const size_t kRingBufferChunks = 1024;
|
||||
|
||||
static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks,
|
||||
TraceWriter* trace_writer);
|
||||
|
||||
private:
|
||||
// Disallow copy and assign
|
||||
TraceBuffer(const TraceBuffer&) = delete;
|
||||
void operator=(const TraceBuffer&) = delete;
|
||||
};
|
||||
|
||||
// Options determines how the trace buffer stores data.
|
||||
enum TraceRecordMode {
|
||||
// Record until the trace buffer is full.
|
||||
RECORD_UNTIL_FULL,
|
||||
|
||||
// Record until the user ends the trace. The trace buffer is a fixed size
|
||||
// and we use it as a ring buffer during recording.
|
||||
RECORD_CONTINUOUSLY,
|
||||
|
||||
// Record until the trace buffer is full, but with a huge buffer size.
|
||||
RECORD_AS_MUCH_AS_POSSIBLE,
|
||||
|
||||
// Echo to console. Events are discarded.
|
||||
ECHO_TO_CONSOLE,
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceConfig {
|
||||
public:
|
||||
typedef std::vector<std::string> StringList;
|
||||
|
||||
static TraceConfig* CreateDefaultTraceConfig();
|
||||
|
||||
TraceConfig() : enable_systrace_(false), enable_argument_filter_(false) {}
|
||||
TraceRecordMode GetTraceRecordMode() const { return record_mode_; }
|
||||
bool IsSystraceEnabled() const { return enable_systrace_; }
|
||||
bool IsArgumentFilterEnabled() const { return enable_argument_filter_; }
|
||||
|
||||
void SetTraceRecordMode(TraceRecordMode mode) { record_mode_ = mode; }
|
||||
void EnableSystrace() { enable_systrace_ = true; }
|
||||
void EnableArgumentFilter() { enable_argument_filter_ = true; }
|
||||
|
||||
void AddIncludedCategory(const char* included_category);
|
||||
|
||||
bool IsCategoryGroupEnabled(const char* category_group) const;
|
||||
|
||||
private:
|
||||
TraceRecordMode record_mode_;
|
||||
bool enable_systrace_ : 1;
|
||||
bool enable_argument_filter_ : 1;
|
||||
StringList included_categories_;
|
||||
|
||||
// Disallow copy and assign
|
||||
TraceConfig(const TraceConfig&) = delete;
|
||||
void operator=(const TraceConfig&) = delete;
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TracingController {
|
||||
public:
|
||||
enum Mode { DISABLED = 0, RECORDING_MODE };
|
||||
|
||||
// The pointer returned from GetCategoryGroupEnabledInternal() points to a
|
||||
// value with zero or more of the following bits. Used in this class only.
|
||||
// The TRACE_EVENT macros should only use the value as a bool.
|
||||
// These values must be in sync with macro values in TraceEvent.h in Blink.
|
||||
enum CategoryGroupEnabledFlags {
|
||||
// Category group enabled for the recording mode.
|
||||
ENABLED_FOR_RECORDING = 1 << 0,
|
||||
// Category group enabled by SetEventCallbackEnabled().
|
||||
ENABLED_FOR_EVENT_CALLBACK = 1 << 2,
|
||||
// Category group enabled to export events to ETW.
|
||||
ENABLED_FOR_ETW_EXPORT = 1 << 3
|
||||
};
|
||||
|
||||
TracingController();
|
||||
~TracingController();
|
||||
void Initialize(TraceBuffer* trace_buffer);
|
||||
const uint8_t* GetCategoryGroupEnabled(const char* category_group);
|
||||
static const char* GetCategoryGroupName(const uint8_t* category_enabled_flag);
|
||||
uint64_t AddTraceEvent(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values,
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
|
||||
unsigned int flags);
|
||||
void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
|
||||
const char* name, uint64_t handle);
|
||||
|
||||
void StartTracing(TraceConfig* trace_config);
|
||||
void StopTracing();
|
||||
|
||||
void AddTraceStateObserver(Platform::TraceStateObserver* observer);
|
||||
void RemoveTraceStateObserver(Platform::TraceStateObserver* observer);
|
||||
|
||||
private:
|
||||
const uint8_t* GetCategoryGroupEnabledInternal(const char* category_group);
|
||||
void UpdateCategoryGroupEnabledFlag(size_t category_index);
|
||||
void UpdateCategoryGroupEnabledFlags();
|
||||
|
||||
std::unique_ptr<TraceBuffer> trace_buffer_;
|
||||
std::unique_ptr<TraceConfig> trace_config_;
|
||||
std::unique_ptr<base::Mutex> mutex_;
|
||||
std::unordered_set<Platform::TraceStateObserver*> observers_;
|
||||
Mode mode_ = DISABLED;
|
||||
|
||||
// Disallow copy and assign
|
||||
TracingController(const TracingController&) = delete;
|
||||
void operator=(const TracingController&) = delete;
|
||||
};
|
||||
|
||||
} // namespace tracing
|
||||
} // namespace platform
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_LIBPLATFORM_V8_TRACING_H_
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_DEBUG_H_
|
||||
#define V8_V8_DEBUG_H_
|
||||
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
|
||||
/**
|
||||
* ATTENTION: The debugger API exposed by this file is deprecated and will be
|
||||
* removed by the end of 2017. Please use the V8 inspector declared
|
||||
* in include/v8-inspector.h instead.
|
||||
*/
|
||||
namespace v8 {
|
||||
|
||||
// Debug events which can occur in the V8 JavaScript engine.
|
||||
enum DebugEvent {
|
||||
Break = 1,
|
||||
Exception = 2,
|
||||
AfterCompile = 3,
|
||||
CompileError = 4,
|
||||
AsyncTaskEvent = 5,
|
||||
};
|
||||
|
||||
class V8_EXPORT Debug {
|
||||
public:
|
||||
/**
|
||||
* A client object passed to the v8 debugger whose ownership will be taken by
|
||||
* it. v8 is always responsible for deleting the object.
|
||||
*/
|
||||
class ClientData {
|
||||
public:
|
||||
virtual ~ClientData() {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A message object passed to the debug message handler.
|
||||
*/
|
||||
class Message {
|
||||
public:
|
||||
/**
|
||||
* Check type of message.
|
||||
*/
|
||||
virtual bool IsEvent() const = 0;
|
||||
virtual bool IsResponse() const = 0;
|
||||
virtual DebugEvent GetEvent() const = 0;
|
||||
|
||||
/**
|
||||
* Indicate whether this is a response to a continue command which will
|
||||
* start the VM running after this is processed.
|
||||
*/
|
||||
virtual bool WillStartRunning() const = 0;
|
||||
|
||||
/**
|
||||
* Access to execution state and event data. Don't store these cross
|
||||
* callbacks as their content becomes invalid. These objects are from the
|
||||
* debugger event that started the debug message loop.
|
||||
*/
|
||||
virtual Local<Object> GetExecutionState() const = 0;
|
||||
virtual Local<Object> GetEventData() const = 0;
|
||||
|
||||
/**
|
||||
* Get the debugger protocol JSON.
|
||||
*/
|
||||
virtual Local<String> GetJSON() const = 0;
|
||||
|
||||
/**
|
||||
* Get the context active when the debug event happened. Note this is not
|
||||
* the current active context as the JavaScript part of the debugger is
|
||||
* running in its own context which is entered at this point.
|
||||
*/
|
||||
virtual Local<Context> GetEventContext() const = 0;
|
||||
|
||||
/**
|
||||
* Client data passed with the corresponding request if any. This is the
|
||||
* client_data data value passed into Debug::SendCommand along with the
|
||||
* request that led to the message or NULL if the message is an event. The
|
||||
* debugger takes ownership of the data and will delete it even if there is
|
||||
* no message handler.
|
||||
*/
|
||||
virtual ClientData* GetClientData() const = 0;
|
||||
|
||||
virtual Isolate* GetIsolate() const = 0;
|
||||
|
||||
virtual ~Message() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* An event details object passed to the debug event listener.
|
||||
*/
|
||||
class EventDetails {
|
||||
public:
|
||||
/**
|
||||
* Event type.
|
||||
*/
|
||||
virtual DebugEvent GetEvent() const = 0;
|
||||
|
||||
/**
|
||||
* Access to execution state and event data of the debug event. Don't store
|
||||
* these cross callbacks as their content becomes invalid.
|
||||
*/
|
||||
virtual Local<Object> GetExecutionState() const = 0;
|
||||
virtual Local<Object> GetEventData() const = 0;
|
||||
|
||||
/**
|
||||
* Get the context active when the debug event happened. Note this is not
|
||||
* the current active context as the JavaScript part of the debugger is
|
||||
* running in its own context which is entered at this point.
|
||||
*/
|
||||
virtual Local<Context> GetEventContext() const = 0;
|
||||
|
||||
/**
|
||||
* Client data passed with the corresponding callback when it was
|
||||
* registered.
|
||||
*/
|
||||
virtual Local<Value> GetCallbackData() const = 0;
|
||||
|
||||
/**
|
||||
* This is now a dummy that returns nullptr.
|
||||
*/
|
||||
virtual ClientData* GetClientData() const = 0;
|
||||
|
||||
virtual Isolate* GetIsolate() const = 0;
|
||||
|
||||
virtual ~EventDetails() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Debug event callback function.
|
||||
*
|
||||
* \param event_details object providing information about the debug event
|
||||
*
|
||||
* A EventCallback does not take possession of the event data,
|
||||
* and must not rely on the data persisting after the handler returns.
|
||||
*/
|
||||
typedef void (*EventCallback)(const EventDetails& event_details);
|
||||
|
||||
/**
|
||||
* This is now a no-op.
|
||||
*/
|
||||
typedef void (*MessageHandler)(const Message& message);
|
||||
|
||||
V8_DEPRECATED("No longer supported", static bool SetDebugEventListener(
|
||||
Isolate* isolate, EventCallback that,
|
||||
Local<Value> data = Local<Value>()));
|
||||
|
||||
// Schedule a debugger break to happen when JavaScript code is run
|
||||
// in the given isolate.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void DebugBreak(Isolate* isolate));
|
||||
|
||||
// Remove scheduled debugger break in given isolate if it has not
|
||||
// happened yet.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void CancelDebugBreak(Isolate* isolate));
|
||||
|
||||
// Check if a debugger break is scheduled in the given isolate.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static bool CheckDebugBreak(Isolate* isolate));
|
||||
|
||||
// This is now a no-op.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void SetMessageHandler(Isolate* isolate,
|
||||
MessageHandler handler));
|
||||
|
||||
// This is now a no-op.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void SendCommand(Isolate* isolate,
|
||||
const uint16_t* command, int length,
|
||||
ClientData* client_data = NULL));
|
||||
|
||||
/**
|
||||
* Run a JavaScript function in the debugger.
|
||||
* \param fun the function to call
|
||||
* \param data passed as second argument to the function
|
||||
* With this call the debugger is entered and the function specified is called
|
||||
* with the execution state as the first argument. This makes it possible to
|
||||
* get access to information otherwise not available during normal JavaScript
|
||||
* execution e.g. details on stack frames. Receiver of the function call will
|
||||
* be the debugger context global object, however this is a subject to change.
|
||||
* The following example shows a JavaScript function which when passed to
|
||||
* v8::Debug::Call will return the current line of JavaScript execution.
|
||||
*
|
||||
* \code
|
||||
* function frame_source_line(exec_state) {
|
||||
* return exec_state.frame(0).sourceLine();
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static MaybeLocal<Value> Call(
|
||||
Local<Context> context, v8::Local<v8::Function> fun,
|
||||
Local<Value> data = Local<Value>()));
|
||||
|
||||
// This is now a no-op.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void ProcessDebugMessages(Isolate* isolate));
|
||||
|
||||
/**
|
||||
* Debugger is running in its own context which is entered while debugger
|
||||
* messages are being dispatched. This is an explicit getter for this
|
||||
* debugger context. Note that the content of the debugger context is subject
|
||||
* to change. The Context exists only when the debugger is active, i.e. at
|
||||
* least one DebugEventListener or MessageHandler is set.
|
||||
*/
|
||||
V8_DEPRECATED("Use v8-inspector",
|
||||
static Local<Context> GetDebugContext(Isolate* isolate));
|
||||
|
||||
/**
|
||||
* While in the debug context, this method returns the top-most non-debug
|
||||
* context, if it exists.
|
||||
*/
|
||||
V8_DEPRECATED(
|
||||
"No longer supported",
|
||||
static MaybeLocal<Context> GetDebuggedContext(Isolate* isolate));
|
||||
|
||||
/**
|
||||
* Enable/disable LiveEdit functionality for the given Isolate
|
||||
* (default Isolate if not provided). V8 will abort if LiveEdit is
|
||||
* unexpectedly used. LiveEdit is enabled by default.
|
||||
*/
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void SetLiveEditEnabled(Isolate* isolate, bool enable));
|
||||
|
||||
/**
|
||||
* Returns array of internal properties specific to the value type. Result has
|
||||
* the following format: [<name>, <value>,...,<name>, <value>]. Result array
|
||||
* will be allocated in the current context.
|
||||
*/
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static MaybeLocal<Array> GetInternalProperties(
|
||||
Isolate* isolate, Local<Value> value));
|
||||
|
||||
/**
|
||||
* Defines if the ES2015 tail call elimination feature is enabled or not.
|
||||
* The change of this flag triggers deoptimization of all functions that
|
||||
* contain calls at tail position.
|
||||
*/
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static bool IsTailCallEliminationEnabled(Isolate* isolate));
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void SetTailCallEliminationEnabled(Isolate* isolate,
|
||||
bool enabled));
|
||||
};
|
||||
|
||||
|
||||
} // namespace v8
|
||||
|
||||
|
||||
#undef EXPORT
|
||||
|
||||
|
||||
#endif // V8_V8_DEBUG_H_
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_INSPECTOR_PROTOCOL_H_
|
||||
#define V8_V8_INSPECTOR_PROTOCOL_H_
|
||||
|
||||
#include "inspector/Debugger.h" // NOLINT(build/include)
|
||||
#include "inspector/Runtime.h" // NOLINT(build/include)
|
||||
#include "inspector/Schema.h" // NOLINT(build/include)
|
||||
#include "v8-inspector.h" // NOLINT(build/include)
|
||||
|
||||
#endif // V8_V8_INSPECTOR_PROTOCOL_H_
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_INSPECTOR_H_
|
||||
#define V8_V8_INSPECTOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cctype>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
|
||||
namespace v8_inspector {
|
||||
|
||||
namespace protocol {
|
||||
namespace Debugger {
|
||||
namespace API {
|
||||
class SearchMatch;
|
||||
}
|
||||
}
|
||||
namespace Runtime {
|
||||
namespace API {
|
||||
class RemoteObject;
|
||||
class StackTrace;
|
||||
}
|
||||
}
|
||||
namespace Schema {
|
||||
namespace API {
|
||||
class Domain;
|
||||
}
|
||||
}
|
||||
} // namespace protocol
|
||||
|
||||
class V8_EXPORT StringView {
|
||||
public:
|
||||
StringView() : m_is8Bit(true), m_length(0), m_characters8(nullptr) {}
|
||||
|
||||
StringView(const uint8_t* characters, size_t length)
|
||||
: m_is8Bit(true), m_length(length), m_characters8(characters) {}
|
||||
|
||||
StringView(const uint16_t* characters, size_t length)
|
||||
: m_is8Bit(false), m_length(length), m_characters16(characters) {}
|
||||
|
||||
bool is8Bit() const { return m_is8Bit; }
|
||||
size_t length() const { return m_length; }
|
||||
|
||||
// TODO(dgozman): add DCHECK(m_is8Bit) to accessors once platform can be used
|
||||
// here.
|
||||
const uint8_t* characters8() const { return m_characters8; }
|
||||
const uint16_t* characters16() const { return m_characters16; }
|
||||
|
||||
private:
|
||||
bool m_is8Bit;
|
||||
size_t m_length;
|
||||
union {
|
||||
const uint8_t* m_characters8;
|
||||
const uint16_t* m_characters16;
|
||||
};
|
||||
};
|
||||
|
||||
class V8_EXPORT StringBuffer {
|
||||
public:
|
||||
virtual ~StringBuffer() {}
|
||||
virtual const StringView& string() = 0;
|
||||
// This method copies contents.
|
||||
static std::unique_ptr<StringBuffer> create(const StringView&);
|
||||
};
|
||||
|
||||
class V8_EXPORT V8ContextInfo {
|
||||
public:
|
||||
V8ContextInfo(v8::Local<v8::Context> context, int contextGroupId,
|
||||
const StringView& humanReadableName)
|
||||
: context(context),
|
||||
contextGroupId(contextGroupId),
|
||||
humanReadableName(humanReadableName),
|
||||
hasMemoryOnConsole(false) {}
|
||||
|
||||
v8::Local<v8::Context> context;
|
||||
// Each v8::Context is a part of a group. The group id must be non-zero.
|
||||
int contextGroupId;
|
||||
StringView humanReadableName;
|
||||
StringView origin;
|
||||
StringView auxData;
|
||||
bool hasMemoryOnConsole;
|
||||
|
||||
static int executionContextId(v8::Local<v8::Context> context);
|
||||
|
||||
private:
|
||||
// Disallow copying and allocating this one.
|
||||
enum NotNullTagEnum { NotNullLiteral };
|
||||
void* operator new(size_t) = delete;
|
||||
void* operator new(size_t, NotNullTagEnum, void*) = delete;
|
||||
void* operator new(size_t, void*) = delete;
|
||||
V8ContextInfo(const V8ContextInfo&) = delete;
|
||||
V8ContextInfo& operator=(const V8ContextInfo&) = delete;
|
||||
};
|
||||
|
||||
class V8_EXPORT V8StackTrace {
|
||||
public:
|
||||
virtual bool isEmpty() const = 0;
|
||||
virtual StringView topSourceURL() const = 0;
|
||||
virtual int topLineNumber() const = 0;
|
||||
virtual int topColumnNumber() const = 0;
|
||||
virtual StringView topScriptId() const = 0;
|
||||
virtual StringView topFunctionName() const = 0;
|
||||
|
||||
virtual ~V8StackTrace() {}
|
||||
virtual std::unique_ptr<protocol::Runtime::API::StackTrace>
|
||||
buildInspectorObject() const = 0;
|
||||
virtual std::unique_ptr<StringBuffer> toString() const = 0;
|
||||
|
||||
// Safe to pass between threads, drops async chain.
|
||||
virtual std::unique_ptr<V8StackTrace> clone() = 0;
|
||||
};
|
||||
|
||||
class V8_EXPORT V8InspectorSession {
|
||||
public:
|
||||
virtual ~V8InspectorSession() {}
|
||||
|
||||
// Cross-context inspectable values (DOM nodes in different worlds, etc.).
|
||||
class V8_EXPORT Inspectable {
|
||||
public:
|
||||
virtual v8::Local<v8::Value> get(v8::Local<v8::Context>) = 0;
|
||||
virtual ~Inspectable() {}
|
||||
};
|
||||
virtual void addInspectedObject(std::unique_ptr<Inspectable>) = 0;
|
||||
|
||||
// Dispatching protocol messages.
|
||||
static bool canDispatchMethod(const StringView& method);
|
||||
virtual void dispatchProtocolMessage(const StringView& message) = 0;
|
||||
virtual std::unique_ptr<StringBuffer> stateJSON() = 0;
|
||||
virtual std::vector<std::unique_ptr<protocol::Schema::API::Domain>>
|
||||
supportedDomains() = 0;
|
||||
|
||||
// Debugger actions.
|
||||
virtual void schedulePauseOnNextStatement(const StringView& breakReason,
|
||||
const StringView& breakDetails) = 0;
|
||||
virtual void cancelPauseOnNextStatement() = 0;
|
||||
virtual void breakProgram(const StringView& breakReason,
|
||||
const StringView& breakDetails) = 0;
|
||||
virtual void setSkipAllPauses(bool) = 0;
|
||||
virtual void resume() = 0;
|
||||
virtual void stepOver() = 0;
|
||||
virtual std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>>
|
||||
searchInTextByLines(const StringView& text, const StringView& query,
|
||||
bool caseSensitive, bool isRegex) = 0;
|
||||
|
||||
// Remote objects.
|
||||
virtual std::unique_ptr<protocol::Runtime::API::RemoteObject> wrapObject(
|
||||
v8::Local<v8::Context>, v8::Local<v8::Value>,
|
||||
const StringView& groupName) = 0;
|
||||
virtual bool unwrapObject(std::unique_ptr<StringBuffer>* error,
|
||||
const StringView& objectId, v8::Local<v8::Value>*,
|
||||
v8::Local<v8::Context>*,
|
||||
std::unique_ptr<StringBuffer>* objectGroup) = 0;
|
||||
virtual void releaseObjectGroup(const StringView&) = 0;
|
||||
};
|
||||
|
||||
class V8_EXPORT V8InspectorClient {
|
||||
public:
|
||||
virtual ~V8InspectorClient() {}
|
||||
|
||||
virtual void runMessageLoopOnPause(int contextGroupId) {}
|
||||
virtual void quitMessageLoopOnPause() {}
|
||||
virtual void runIfWaitingForDebugger(int contextGroupId) {}
|
||||
|
||||
virtual void muteMetrics(int contextGroupId) {}
|
||||
virtual void unmuteMetrics(int contextGroupId) {}
|
||||
|
||||
virtual void beginUserGesture() {}
|
||||
virtual void endUserGesture() {}
|
||||
|
||||
virtual std::unique_ptr<StringBuffer> valueSubtype(v8::Local<v8::Value>) {
|
||||
return nullptr;
|
||||
}
|
||||
virtual bool formatAccessorsAsProperties(v8::Local<v8::Value>) {
|
||||
return false;
|
||||
}
|
||||
virtual bool isInspectableHeapObject(v8::Local<v8::Object>) { return true; }
|
||||
|
||||
virtual v8::Local<v8::Context> ensureDefaultContextInGroup(
|
||||
int contextGroupId) {
|
||||
return v8::Local<v8::Context>();
|
||||
}
|
||||
virtual void beginEnsureAllContextsInGroup(int contextGroupId) {}
|
||||
virtual void endEnsureAllContextsInGroup(int contextGroupId) {}
|
||||
|
||||
virtual void installAdditionalCommandLineAPI(v8::Local<v8::Context>,
|
||||
v8::Local<v8::Object>) {}
|
||||
virtual void consoleAPIMessage(int contextGroupId,
|
||||
v8::Isolate::MessageErrorLevel level,
|
||||
const StringView& message,
|
||||
const StringView& url, unsigned lineNumber,
|
||||
unsigned columnNumber, V8StackTrace*) {}
|
||||
virtual v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*,
|
||||
v8::Local<v8::Context>) {
|
||||
return v8::MaybeLocal<v8::Value>();
|
||||
}
|
||||
|
||||
virtual void consoleTime(const StringView& title) {}
|
||||
virtual void consoleTimeEnd(const StringView& title) {}
|
||||
virtual void consoleTimeStamp(const StringView& title) {}
|
||||
virtual void consoleClear(int contextGroupId) {}
|
||||
virtual double currentTimeMS() { return 0; }
|
||||
typedef void (*TimerCallback)(void*);
|
||||
virtual void startRepeatingTimer(double, TimerCallback, void* data) {}
|
||||
virtual void cancelTimer(void* data) {}
|
||||
|
||||
// TODO(dgozman): this was added to support service worker shadow page. We
|
||||
// should not connect at all.
|
||||
virtual bool canExecuteScripts(int contextGroupId) { return true; }
|
||||
};
|
||||
|
||||
class V8_EXPORT V8Inspector {
|
||||
public:
|
||||
static std::unique_ptr<V8Inspector> create(v8::Isolate*, V8InspectorClient*);
|
||||
virtual ~V8Inspector() {}
|
||||
|
||||
// Contexts instrumentation.
|
||||
virtual void contextCreated(const V8ContextInfo&) = 0;
|
||||
virtual void contextDestroyed(v8::Local<v8::Context>) = 0;
|
||||
virtual void resetContextGroup(int contextGroupId) = 0;
|
||||
|
||||
// Various instrumentation.
|
||||
virtual void idleStarted() = 0;
|
||||
virtual void idleFinished() = 0;
|
||||
|
||||
// Async stack traces instrumentation.
|
||||
virtual void asyncTaskScheduled(const StringView& taskName, void* task,
|
||||
bool recurring) = 0;
|
||||
virtual void asyncTaskCanceled(void* task) = 0;
|
||||
virtual void asyncTaskStarted(void* task) = 0;
|
||||
virtual void asyncTaskFinished(void* task) = 0;
|
||||
virtual void allAsyncTasksCanceled() = 0;
|
||||
|
||||
// Exceptions instrumentation.
|
||||
virtual unsigned exceptionThrown(
|
||||
v8::Local<v8::Context>, const StringView& message,
|
||||
v8::Local<v8::Value> exception, const StringView& detailedMessage,
|
||||
const StringView& url, unsigned lineNumber, unsigned columnNumber,
|
||||
std::unique_ptr<V8StackTrace>, int scriptId) = 0;
|
||||
virtual void exceptionRevoked(v8::Local<v8::Context>, unsigned exceptionId,
|
||||
const StringView& message) = 0;
|
||||
|
||||
// Connection.
|
||||
class V8_EXPORT Channel {
|
||||
public:
|
||||
virtual ~Channel() {}
|
||||
virtual void sendResponse(int callId,
|
||||
std::unique_ptr<StringBuffer> message) = 0;
|
||||
virtual void sendNotification(std::unique_ptr<StringBuffer> message) = 0;
|
||||
virtual void flushProtocolNotifications() = 0;
|
||||
};
|
||||
virtual std::unique_ptr<V8InspectorSession> connect(
|
||||
int contextGroupId, Channel*, const StringView& state) = 0;
|
||||
|
||||
// API methods.
|
||||
virtual std::unique_ptr<V8StackTrace> createStackTrace(
|
||||
v8::Local<v8::StackTrace>) = 0;
|
||||
virtual std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) = 0;
|
||||
};
|
||||
|
||||
} // namespace v8_inspector
|
||||
|
||||
#endif // V8_V8_INSPECTOR_H_
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_PLATFORM_H_
|
||||
#define V8_V8_PLATFORM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace v8 {
|
||||
|
||||
class Isolate;
|
||||
|
||||
/**
|
||||
* A Task represents a unit of work.
|
||||
*/
|
||||
class Task {
|
||||
public:
|
||||
virtual ~Task() = default;
|
||||
|
||||
virtual void Run() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* An IdleTask represents a unit of work to be performed in idle time.
|
||||
* The Run method is invoked with an argument that specifies the deadline in
|
||||
* seconds returned by MonotonicallyIncreasingTime().
|
||||
* The idle task is expected to complete by this deadline.
|
||||
*/
|
||||
class IdleTask {
|
||||
public:
|
||||
virtual ~IdleTask() = default;
|
||||
virtual void Run(double deadline_in_seconds) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* The interface represents complex arguments to trace events.
|
||||
*/
|
||||
class ConvertableToTraceFormat {
|
||||
public:
|
||||
virtual ~ConvertableToTraceFormat() = default;
|
||||
|
||||
/**
|
||||
* Append the class info to the provided |out| string. The appended
|
||||
* data must be a valid JSON object. Strings must be properly quoted, and
|
||||
* escaped. There is no processing applied to the content after it is
|
||||
* appended.
|
||||
*/
|
||||
virtual void AppendAsTraceFormat(std::string* out) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* V8 Platform abstraction layer.
|
||||
*
|
||||
* The embedder has to provide an implementation of this interface before
|
||||
* initializing the rest of V8.
|
||||
*/
|
||||
class Platform {
|
||||
public:
|
||||
/**
|
||||
* This enum is used to indicate whether a task is potentially long running,
|
||||
* or causes a long wait. The embedder might want to use this hint to decide
|
||||
* whether to execute the task on a dedicated thread.
|
||||
*/
|
||||
enum ExpectedRuntime {
|
||||
kShortRunningTask,
|
||||
kLongRunningTask
|
||||
};
|
||||
|
||||
virtual ~Platform() = default;
|
||||
|
||||
/**
|
||||
* Gets the number of threads that are used to execute background tasks. Is
|
||||
* used to estimate the number of tasks a work package should be split into.
|
||||
* A return value of 0 means that there are no background threads available.
|
||||
* Note that a value of 0 won't prohibit V8 from posting tasks using
|
||||
* |CallOnBackgroundThread|.
|
||||
*/
|
||||
virtual size_t NumberOfAvailableBackgroundThreads() { return 0; }
|
||||
|
||||
/**
|
||||
* Schedules a task to be invoked on a background thread. |expected_runtime|
|
||||
* indicates that the task will run a long time. The Platform implementation
|
||||
* takes ownership of |task|. There is no guarantee about order of execution
|
||||
* of tasks wrt order of scheduling, nor is there a guarantee about the
|
||||
* thread the task will be run on.
|
||||
*/
|
||||
virtual void CallOnBackgroundThread(Task* task,
|
||||
ExpectedRuntime expected_runtime) = 0;
|
||||
|
||||
/**
|
||||
* Schedules a task to be invoked on a foreground thread wrt a specific
|
||||
* |isolate|. Tasks posted for the same isolate should be execute in order of
|
||||
* scheduling. The definition of "foreground" is opaque to V8.
|
||||
*/
|
||||
virtual void CallOnForegroundThread(Isolate* isolate, Task* task) = 0;
|
||||
|
||||
/**
|
||||
* Schedules a task to be invoked on a foreground thread wrt a specific
|
||||
* |isolate| after the given number of seconds |delay_in_seconds|.
|
||||
* Tasks posted for the same isolate should be execute in order of
|
||||
* scheduling. The definition of "foreground" is opaque to V8.
|
||||
*/
|
||||
virtual void CallDelayedOnForegroundThread(Isolate* isolate, Task* task,
|
||||
double delay_in_seconds) = 0;
|
||||
|
||||
/**
|
||||
* Schedules a task to be invoked on a foreground thread wrt a specific
|
||||
* |isolate| when the embedder is idle.
|
||||
* Requires that SupportsIdleTasks(isolate) is true.
|
||||
* Idle tasks may be reordered relative to other task types and may be
|
||||
* starved for an arbitrarily long time if no idle time is available.
|
||||
* The definition of "foreground" is opaque to V8.
|
||||
*/
|
||||
virtual void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) {
|
||||
// TODO(ulan): Make this function abstract after V8 roll in Chromium.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if idle tasks are enabled for the given |isolate|.
|
||||
*/
|
||||
virtual bool IdleTasksEnabled(Isolate* isolate) {
|
||||
// TODO(ulan): Make this function abstract after V8 roll in Chromium.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Monotonically increasing time in seconds from an arbitrary fixed point in
|
||||
* the past. This function is expected to return at least
|
||||
* millisecond-precision values. For this reason,
|
||||
* it is recommended that the fixed point be no further in the past than
|
||||
* the epoch.
|
||||
**/
|
||||
virtual double MonotonicallyIncreasingTime() = 0;
|
||||
|
||||
/**
|
||||
* Called by TRACE_EVENT* macros, don't call this directly.
|
||||
* The name parameter is a category group for example:
|
||||
* TRACE_EVENT0("v8,parse", "V8.Parse")
|
||||
* The pointer returned points to a value with zero or more of the bits
|
||||
* defined in CategoryGroupEnabledFlags.
|
||||
**/
|
||||
virtual const uint8_t* GetCategoryGroupEnabled(const char* name) {
|
||||
static uint8_t no = 0;
|
||||
return &no;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the category group name of the given category_enabled_flag pointer.
|
||||
* Usually used while serliazing TRACE_EVENTs.
|
||||
**/
|
||||
virtual const char* GetCategoryGroupName(
|
||||
const uint8_t* category_enabled_flag) {
|
||||
static const char dummy[] = "dummy";
|
||||
return dummy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a trace event to the platform tracing system. This function call is
|
||||
* usually the result of a TRACE_* macro from trace_event_common.h when
|
||||
* tracing and the category of the particular trace are enabled. It is not
|
||||
* advisable to call this function on its own; it is really only meant to be
|
||||
* used by the trace macros. The returned handle can be used by
|
||||
* UpdateTraceEventDuration to update the duration of COMPLETE events.
|
||||
*/
|
||||
virtual uint64_t AddTraceEvent(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values, unsigned int flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a trace event to the platform tracing system. This function call is
|
||||
* usually the result of a TRACE_* macro from trace_event_common.h when
|
||||
* tracing and the category of the particular trace are enabled. It is not
|
||||
* advisable to call this function on its own; it is really only meant to be
|
||||
* used by the trace macros. The returned handle can be used by
|
||||
* UpdateTraceEventDuration to update the duration of COMPLETE events.
|
||||
*/
|
||||
virtual uint64_t AddTraceEvent(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values,
|
||||
std::unique_ptr<ConvertableToTraceFormat>* arg_convertables,
|
||||
unsigned int flags) {
|
||||
return AddTraceEvent(phase, category_enabled_flag, name, scope, id, bind_id,
|
||||
num_args, arg_names, arg_types, arg_values, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the duration field of a COMPLETE trace event. It must be called with
|
||||
* the handle returned from AddTraceEvent().
|
||||
**/
|
||||
virtual void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
|
||||
const char* name, uint64_t handle) {}
|
||||
|
||||
class TraceStateObserver {
|
||||
public:
|
||||
virtual ~TraceStateObserver() = default;
|
||||
virtual void OnTraceEnabled() = 0;
|
||||
virtual void OnTraceDisabled() = 0;
|
||||
};
|
||||
|
||||
/** Adds tracing state change observer. */
|
||||
virtual void AddTraceStateObserver(TraceStateObserver*) {}
|
||||
|
||||
/** Removes tracing state change observer. */
|
||||
virtual void RemoveTraceStateObserver(TraceStateObserver*) {}
|
||||
|
||||
typedef void (*StackTracePrinter)();
|
||||
|
||||
/**
|
||||
* Returns a function pointer that print a stack trace of the current stack
|
||||
* on invocation. Disables printing of the stack trace if nullptr.
|
||||
*/
|
||||
virtual StackTracePrinter GetStackTracePrinter() { return nullptr; }
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_V8_PLATFORM_H_
|
||||
|
|
@ -0,0 +1,912 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_PROFILER_H_
|
||||
#define V8_V8_PROFILER_H_
|
||||
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
|
||||
/**
|
||||
* Profiler support for the V8 JavaScript engine.
|
||||
*/
|
||||
namespace v8 {
|
||||
|
||||
class HeapGraphNode;
|
||||
struct HeapStatsUpdate;
|
||||
|
||||
typedef uint32_t SnapshotObjectId;
|
||||
|
||||
|
||||
struct CpuProfileDeoptFrame {
|
||||
int script_id;
|
||||
size_t position;
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#ifdef V8_OS_WIN
|
||||
template class V8_EXPORT std::vector<v8::CpuProfileDeoptFrame>;
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
|
||||
struct V8_EXPORT CpuProfileDeoptInfo {
|
||||
/** A pointer to a static string owned by v8. */
|
||||
const char* deopt_reason;
|
||||
std::vector<CpuProfileDeoptFrame> stack;
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#ifdef V8_OS_WIN
|
||||
template class V8_EXPORT std::vector<v8::CpuProfileDeoptInfo>;
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
|
||||
/**
|
||||
* TracingCpuProfiler monitors tracing being enabled/disabled
|
||||
* and emits CpuProfile trace events once v8.cpu_profiler tracing category
|
||||
* is enabled. It has no overhead unless the category is enabled.
|
||||
*/
|
||||
class V8_EXPORT TracingCpuProfiler {
|
||||
public:
|
||||
static std::unique_ptr<TracingCpuProfiler> Create(Isolate*);
|
||||
virtual ~TracingCpuProfiler() = default;
|
||||
|
||||
protected:
|
||||
TracingCpuProfiler() = default;
|
||||
};
|
||||
|
||||
// TickSample captures the information collected for each sample.
|
||||
struct TickSample {
|
||||
// Internal profiling (with --prof + tools/$OS-tick-processor) wants to
|
||||
// include the runtime function we're calling. Externally exposed tick
|
||||
// samples don't care.
|
||||
enum RecordCEntryFrame { kIncludeCEntryFrame, kSkipCEntryFrame };
|
||||
|
||||
TickSample()
|
||||
: state(OTHER),
|
||||
pc(nullptr),
|
||||
external_callback_entry(nullptr),
|
||||
frames_count(0),
|
||||
has_external_callback(false),
|
||||
update_stats(true) {}
|
||||
|
||||
/**
|
||||
* Initialize a tick sample from the isolate.
|
||||
* \param isolate The isolate.
|
||||
* \param state Execution state.
|
||||
* \param record_c_entry_frame Include or skip the runtime function.
|
||||
* \param update_stats Whether update the sample to the aggregated stats.
|
||||
* \param use_simulator_reg_state When set to true and V8 is running under a
|
||||
* simulator, the method will use the simulator
|
||||
* register state rather than the one provided
|
||||
* with |state| argument. Otherwise the method
|
||||
* will use provided register |state| as is.
|
||||
*/
|
||||
void Init(Isolate* isolate, const v8::RegisterState& state,
|
||||
RecordCEntryFrame record_c_entry_frame, bool update_stats,
|
||||
bool use_simulator_reg_state = true);
|
||||
/**
|
||||
* Get a call stack sample from the isolate.
|
||||
* \param isolate The isolate.
|
||||
* \param state Register state.
|
||||
* \param record_c_entry_frame Include or skip the runtime function.
|
||||
* \param frames Caller allocated buffer to store stack frames.
|
||||
* \param frames_limit Maximum number of frames to capture. The buffer must
|
||||
* be large enough to hold the number of frames.
|
||||
* \param sample_info The sample info is filled up by the function
|
||||
* provides number of actual captured stack frames and
|
||||
* the current VM state.
|
||||
* \param use_simulator_reg_state When set to true and V8 is running under a
|
||||
* simulator, the method will use the simulator
|
||||
* register state rather than the one provided
|
||||
* with |state| argument. Otherwise the method
|
||||
* will use provided register |state| as is.
|
||||
* \note GetStackSample is thread and signal safe and should only be called
|
||||
* when the JS thread is paused or interrupted.
|
||||
* Otherwise the behavior is undefined.
|
||||
*/
|
||||
static bool GetStackSample(Isolate* isolate, v8::RegisterState* state,
|
||||
RecordCEntryFrame record_c_entry_frame,
|
||||
void** frames, size_t frames_limit,
|
||||
v8::SampleInfo* sample_info,
|
||||
bool use_simulator_reg_state = true);
|
||||
StateTag state; // The state of the VM.
|
||||
void* pc; // Instruction pointer.
|
||||
union {
|
||||
void* tos; // Top stack value (*sp).
|
||||
void* external_callback_entry;
|
||||
};
|
||||
static const unsigned kMaxFramesCountLog2 = 8;
|
||||
static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
|
||||
void* stack[kMaxFramesCount]; // Call stack.
|
||||
unsigned frames_count : kMaxFramesCountLog2; // Number of captured frames.
|
||||
bool has_external_callback : 1;
|
||||
bool update_stats : 1; // Whether the sample should update aggregated stats.
|
||||
};
|
||||
|
||||
/**
|
||||
* CpuProfileNode represents a node in a call graph.
|
||||
*/
|
||||
class V8_EXPORT CpuProfileNode {
|
||||
public:
|
||||
struct LineTick {
|
||||
/** The 1-based number of the source line where the function originates. */
|
||||
int line;
|
||||
|
||||
/** The count of samples associated with the source line. */
|
||||
unsigned int hit_count;
|
||||
};
|
||||
|
||||
/** Returns function name (empty string for anonymous functions.) */
|
||||
Local<String> GetFunctionName() const;
|
||||
|
||||
/**
|
||||
* Returns function name (empty string for anonymous functions.)
|
||||
* The string ownership is *not* passed to the caller. It stays valid until
|
||||
* profile is deleted. The function is thread safe.
|
||||
*/
|
||||
const char* GetFunctionNameStr() const;
|
||||
|
||||
/** Returns id of the script where function is located. */
|
||||
int GetScriptId() const;
|
||||
|
||||
/** Returns resource name for script from where the function originates. */
|
||||
Local<String> GetScriptResourceName() const;
|
||||
|
||||
/**
|
||||
* Returns resource name for script from where the function originates.
|
||||
* The string ownership is *not* passed to the caller. It stays valid until
|
||||
* profile is deleted. The function is thread safe.
|
||||
*/
|
||||
const char* GetScriptResourceNameStr() const;
|
||||
|
||||
/**
|
||||
* Returns the number, 1-based, of the line where the function originates.
|
||||
* kNoLineNumberInfo if no line number information is available.
|
||||
*/
|
||||
int GetLineNumber() const;
|
||||
|
||||
/**
|
||||
* Returns 1-based number of the column where the function originates.
|
||||
* kNoColumnNumberInfo if no column number information is available.
|
||||
*/
|
||||
int GetColumnNumber() const;
|
||||
|
||||
/**
|
||||
* Returns the number of the function's source lines that collect the samples.
|
||||
*/
|
||||
unsigned int GetHitLineCount() const;
|
||||
|
||||
/** Returns the set of source lines that collect the samples.
|
||||
* The caller allocates buffer and responsible for releasing it.
|
||||
* True if all available entries are copied, otherwise false.
|
||||
* The function copies nothing if buffer is not large enough.
|
||||
*/
|
||||
bool GetLineTicks(LineTick* entries, unsigned int length) const;
|
||||
|
||||
/** Returns bailout reason for the function
|
||||
* if the optimization was disabled for it.
|
||||
*/
|
||||
const char* GetBailoutReason() const;
|
||||
|
||||
/**
|
||||
* Returns the count of samples where the function was currently executing.
|
||||
*/
|
||||
unsigned GetHitCount() const;
|
||||
|
||||
/** Returns function entry UID. */
|
||||
V8_DEPRECATE_SOON(
|
||||
"Use GetScriptId, GetLineNumber, and GetColumnNumber instead.",
|
||||
unsigned GetCallUid() const);
|
||||
|
||||
/** Returns id of the node. The id is unique within the tree */
|
||||
unsigned GetNodeId() const;
|
||||
|
||||
/** Returns child nodes count of the node. */
|
||||
int GetChildrenCount() const;
|
||||
|
||||
/** Retrieves a child node by index. */
|
||||
const CpuProfileNode* GetChild(int index) const;
|
||||
|
||||
/** Retrieves deopt infos for the node. */
|
||||
const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const;
|
||||
|
||||
static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
|
||||
static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* CpuProfile contains a CPU profile in a form of top-down call tree
|
||||
* (from main() down to functions that do all the work).
|
||||
*/
|
||||
class V8_EXPORT CpuProfile {
|
||||
public:
|
||||
/** Returns CPU profile title. */
|
||||
Local<String> GetTitle() const;
|
||||
|
||||
/** Returns the root node of the top down call tree. */
|
||||
const CpuProfileNode* GetTopDownRoot() const;
|
||||
|
||||
/**
|
||||
* Returns number of samples recorded. The samples are not recorded unless
|
||||
* |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
|
||||
*/
|
||||
int GetSamplesCount() const;
|
||||
|
||||
/**
|
||||
* Returns profile node corresponding to the top frame the sample at
|
||||
* the given index.
|
||||
*/
|
||||
const CpuProfileNode* GetSample(int index) const;
|
||||
|
||||
/**
|
||||
* Returns the timestamp of the sample. The timestamp is the number of
|
||||
* microseconds since some unspecified starting point.
|
||||
* The point is equal to the starting point used by GetStartTime.
|
||||
*/
|
||||
int64_t GetSampleTimestamp(int index) const;
|
||||
|
||||
/**
|
||||
* Returns time when the profile recording was started (in microseconds)
|
||||
* since some unspecified starting point.
|
||||
*/
|
||||
int64_t GetStartTime() const;
|
||||
|
||||
/**
|
||||
* Returns time when the profile recording was stopped (in microseconds)
|
||||
* since some unspecified starting point.
|
||||
* The point is equal to the starting point used by GetStartTime.
|
||||
*/
|
||||
int64_t GetEndTime() const;
|
||||
|
||||
/**
|
||||
* Deletes the profile and removes it from CpuProfiler's list.
|
||||
* All pointers to nodes previously returned become invalid.
|
||||
*/
|
||||
void Delete();
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for controlling CPU profiling. Instance of the
|
||||
* profiler can be created using v8::CpuProfiler::New method.
|
||||
*/
|
||||
class V8_EXPORT CpuProfiler {
|
||||
public:
|
||||
/**
|
||||
* Creates a new CPU profiler for the |isolate|. The isolate must be
|
||||
* initialized. The profiler object must be disposed after use by calling
|
||||
* |Dispose| method.
|
||||
*/
|
||||
static CpuProfiler* New(Isolate* isolate);
|
||||
|
||||
/**
|
||||
* Disposes the CPU profiler object.
|
||||
*/
|
||||
void Dispose();
|
||||
|
||||
/**
|
||||
* Changes default CPU profiler sampling interval to the specified number
|
||||
* of microseconds. Default interval is 1000us. This method must be called
|
||||
* when there are no profiles being recorded.
|
||||
*/
|
||||
void SetSamplingInterval(int us);
|
||||
|
||||
/**
|
||||
* Starts collecting CPU profile. Title may be an empty string. It
|
||||
* is allowed to have several profiles being collected at
|
||||
* once. Attempts to start collecting several profiles with the same
|
||||
* title are silently ignored. While collecting a profile, functions
|
||||
* from all security contexts are included in it. The token-based
|
||||
* filtering is only performed when querying for a profile.
|
||||
*
|
||||
* |record_samples| parameter controls whether individual samples should
|
||||
* be recorded in addition to the aggregated tree.
|
||||
*/
|
||||
void StartProfiling(Local<String> title, bool record_samples = false);
|
||||
|
||||
/**
|
||||
* Stops collecting CPU profile with a given title and returns it.
|
||||
* If the title given is empty, finishes the last profile started.
|
||||
*/
|
||||
CpuProfile* StopProfiling(Local<String> title);
|
||||
|
||||
/**
|
||||
* Force collection of a sample. Must be called on the VM thread.
|
||||
* Recording the forced sample does not contribute to the aggregated
|
||||
* profile statistics.
|
||||
*/
|
||||
void CollectSample();
|
||||
|
||||
/**
|
||||
* Tells the profiler whether the embedder is idle.
|
||||
*/
|
||||
void SetIdle(bool is_idle);
|
||||
|
||||
private:
|
||||
CpuProfiler();
|
||||
~CpuProfiler();
|
||||
CpuProfiler(const CpuProfiler&);
|
||||
CpuProfiler& operator=(const CpuProfiler&);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HeapSnapshotEdge represents a directed connection between heap
|
||||
* graph nodes: from retainers to retained nodes.
|
||||
*/
|
||||
class V8_EXPORT HeapGraphEdge {
|
||||
public:
|
||||
enum Type {
|
||||
kContextVariable = 0, // A variable from a function context.
|
||||
kElement = 1, // An element of an array.
|
||||
kProperty = 2, // A named object property.
|
||||
kInternal = 3, // A link that can't be accessed from JS,
|
||||
// thus, its name isn't a real property name
|
||||
// (e.g. parts of a ConsString).
|
||||
kHidden = 4, // A link that is needed for proper sizes
|
||||
// calculation, but may be hidden from user.
|
||||
kShortcut = 5, // A link that must not be followed during
|
||||
// sizes calculation.
|
||||
kWeak = 6 // A weak reference (ignored by the GC).
|
||||
};
|
||||
|
||||
/** Returns edge type (see HeapGraphEdge::Type). */
|
||||
Type GetType() const;
|
||||
|
||||
/**
|
||||
* Returns edge name. This can be a variable name, an element index, or
|
||||
* a property name.
|
||||
*/
|
||||
Local<Value> GetName() const;
|
||||
|
||||
/** Returns origin node. */
|
||||
const HeapGraphNode* GetFromNode() const;
|
||||
|
||||
/** Returns destination node. */
|
||||
const HeapGraphNode* GetToNode() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HeapGraphNode represents a node in a heap graph.
|
||||
*/
|
||||
class V8_EXPORT HeapGraphNode {
|
||||
public:
|
||||
enum Type {
|
||||
kHidden = 0, // Hidden node, may be filtered when shown to user.
|
||||
kArray = 1, // An array of elements.
|
||||
kString = 2, // A string.
|
||||
kObject = 3, // A JS object (except for arrays and strings).
|
||||
kCode = 4, // Compiled code.
|
||||
kClosure = 5, // Function closure.
|
||||
kRegExp = 6, // RegExp.
|
||||
kHeapNumber = 7, // Number stored in the heap.
|
||||
kNative = 8, // Native object (not from V8 heap).
|
||||
kSynthetic = 9, // Synthetic object, usualy used for grouping
|
||||
// snapshot items together.
|
||||
kConsString = 10, // Concatenated string. A pair of pointers to strings.
|
||||
kSlicedString = 11, // Sliced string. A fragment of another string.
|
||||
kSymbol = 12 // A Symbol (ES6).
|
||||
};
|
||||
|
||||
/** Returns node type (see HeapGraphNode::Type). */
|
||||
Type GetType() const;
|
||||
|
||||
/**
|
||||
* Returns node name. Depending on node's type this can be the name
|
||||
* of the constructor (for objects), the name of the function (for
|
||||
* closures), string value, or an empty string (for compiled code).
|
||||
*/
|
||||
Local<String> GetName() const;
|
||||
|
||||
/**
|
||||
* Returns node id. For the same heap object, the id remains the same
|
||||
* across all snapshots.
|
||||
*/
|
||||
SnapshotObjectId GetId() const;
|
||||
|
||||
/** Returns node's own size, in bytes. */
|
||||
size_t GetShallowSize() const;
|
||||
|
||||
/** Returns child nodes count of the node. */
|
||||
int GetChildrenCount() const;
|
||||
|
||||
/** Retrieves a child by index. */
|
||||
const HeapGraphEdge* GetChild(int index) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An interface for exporting data from V8, using "push" model.
|
||||
*/
|
||||
class V8_EXPORT OutputStream { // NOLINT
|
||||
public:
|
||||
enum WriteResult {
|
||||
kContinue = 0,
|
||||
kAbort = 1
|
||||
};
|
||||
virtual ~OutputStream() {}
|
||||
/** Notify about the end of stream. */
|
||||
virtual void EndOfStream() = 0;
|
||||
/** Get preferred output chunk size. Called only once. */
|
||||
virtual int GetChunkSize() { return 1024; }
|
||||
/**
|
||||
* Writes the next chunk of snapshot data into the stream. Writing
|
||||
* can be stopped by returning kAbort as function result. EndOfStream
|
||||
* will not be called in case writing was aborted.
|
||||
*/
|
||||
virtual WriteResult WriteAsciiChunk(char* data, int size) = 0;
|
||||
/**
|
||||
* Writes the next chunk of heap stats data into the stream. Writing
|
||||
* can be stopped by returning kAbort as function result. EndOfStream
|
||||
* will not be called in case writing was aborted.
|
||||
*/
|
||||
virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) {
|
||||
return kAbort;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HeapSnapshots record the state of the JS heap at some moment.
|
||||
*/
|
||||
class V8_EXPORT HeapSnapshot {
|
||||
public:
|
||||
enum SerializationFormat {
|
||||
kJSON = 0 // See format description near 'Serialize' method.
|
||||
};
|
||||
|
||||
/** Returns the root node of the heap graph. */
|
||||
const HeapGraphNode* GetRoot() const;
|
||||
|
||||
/** Returns a node by its id. */
|
||||
const HeapGraphNode* GetNodeById(SnapshotObjectId id) const;
|
||||
|
||||
/** Returns total nodes count in the snapshot. */
|
||||
int GetNodesCount() const;
|
||||
|
||||
/** Returns a node by index. */
|
||||
const HeapGraphNode* GetNode(int index) const;
|
||||
|
||||
/** Returns a max seen JS object Id. */
|
||||
SnapshotObjectId GetMaxSnapshotJSObjectId() const;
|
||||
|
||||
/**
|
||||
* Deletes the snapshot and removes it from HeapProfiler's list.
|
||||
* All pointers to nodes, edges and paths previously returned become
|
||||
* invalid.
|
||||
*/
|
||||
void Delete();
|
||||
|
||||
/**
|
||||
* Prepare a serialized representation of the snapshot. The result
|
||||
* is written into the stream provided in chunks of specified size.
|
||||
* The total length of the serialized snapshot is unknown in
|
||||
* advance, it can be roughly equal to JS heap size (that means,
|
||||
* it can be really big - tens of megabytes).
|
||||
*
|
||||
* For the JSON format, heap contents are represented as an object
|
||||
* with the following structure:
|
||||
*
|
||||
* {
|
||||
* snapshot: {
|
||||
* title: "...",
|
||||
* uid: nnn,
|
||||
* meta: { meta-info },
|
||||
* node_count: nnn,
|
||||
* edge_count: nnn
|
||||
* },
|
||||
* nodes: [nodes array],
|
||||
* edges: [edges array],
|
||||
* strings: [strings array]
|
||||
* }
|
||||
*
|
||||
* Nodes reference strings, other nodes, and edges by their indexes
|
||||
* in corresponding arrays.
|
||||
*/
|
||||
void Serialize(OutputStream* stream,
|
||||
SerializationFormat format = kJSON) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An interface for reporting progress and controlling long-running
|
||||
* activities.
|
||||
*/
|
||||
class V8_EXPORT ActivityControl { // NOLINT
|
||||
public:
|
||||
enum ControlOption {
|
||||
kContinue = 0,
|
||||
kAbort = 1
|
||||
};
|
||||
virtual ~ActivityControl() {}
|
||||
/**
|
||||
* Notify about current progress. The activity can be stopped by
|
||||
* returning kAbort as the callback result.
|
||||
*/
|
||||
virtual ControlOption ReportProgressValue(int done, int total) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* AllocationProfile is a sampled profile of allocations done by the program.
|
||||
* This is structured as a call-graph.
|
||||
*/
|
||||
class V8_EXPORT AllocationProfile {
|
||||
public:
|
||||
struct Allocation {
|
||||
/**
|
||||
* Size of the sampled allocation object.
|
||||
*/
|
||||
size_t size;
|
||||
|
||||
/**
|
||||
* The number of objects of such size that were sampled.
|
||||
*/
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a node in the call-graph.
|
||||
*/
|
||||
struct Node {
|
||||
/**
|
||||
* Name of the function. May be empty for anonymous functions or if the
|
||||
* script corresponding to this function has been unloaded.
|
||||
*/
|
||||
Local<String> name;
|
||||
|
||||
/**
|
||||
* Name of the script containing the function. May be empty if the script
|
||||
* name is not available, or if the script has been unloaded.
|
||||
*/
|
||||
Local<String> script_name;
|
||||
|
||||
/**
|
||||
* id of the script where the function is located. May be equal to
|
||||
* v8::UnboundScript::kNoScriptId in cases where the script doesn't exist.
|
||||
*/
|
||||
int script_id;
|
||||
|
||||
/**
|
||||
* Start position of the function in the script.
|
||||
*/
|
||||
int start_position;
|
||||
|
||||
/**
|
||||
* 1-indexed line number where the function starts. May be
|
||||
* kNoLineNumberInfo if no line number information is available.
|
||||
*/
|
||||
int line_number;
|
||||
|
||||
/**
|
||||
* 1-indexed column number where the function starts. May be
|
||||
* kNoColumnNumberInfo if no line number information is available.
|
||||
*/
|
||||
int column_number;
|
||||
|
||||
/**
|
||||
* List of callees called from this node for which we have sampled
|
||||
* allocations. The lifetime of the children is scoped to the containing
|
||||
* AllocationProfile.
|
||||
*/
|
||||
std::vector<Node*> children;
|
||||
|
||||
/**
|
||||
* List of self allocations done by this node in the call-graph.
|
||||
*/
|
||||
std::vector<Allocation> allocations;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the root node of the call-graph. The root node corresponds to an
|
||||
* empty JS call-stack. The lifetime of the returned Node* is scoped to the
|
||||
* containing AllocationProfile.
|
||||
*/
|
||||
virtual Node* GetRootNode() = 0;
|
||||
|
||||
virtual ~AllocationProfile() {}
|
||||
|
||||
static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
|
||||
static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Interface for controlling heap profiling. Instance of the
|
||||
* profiler can be retrieved using v8::Isolate::GetHeapProfiler.
|
||||
*/
|
||||
class V8_EXPORT HeapProfiler {
|
||||
public:
|
||||
enum SamplingFlags {
|
||||
kSamplingNoFlags = 0,
|
||||
kSamplingForceGC = 1 << 0,
|
||||
};
|
||||
|
||||
typedef std::unordered_set<const v8::PersistentBase<v8::Value>*>
|
||||
RetainerChildren;
|
||||
typedef std::vector<std::pair<v8::RetainedObjectInfo*, RetainerChildren>>
|
||||
RetainerGroups;
|
||||
typedef std::vector<std::pair<const v8::PersistentBase<v8::Value>*,
|
||||
const v8::PersistentBase<v8::Value>*>>
|
||||
RetainerEdges;
|
||||
|
||||
struct RetainerInfos {
|
||||
RetainerGroups groups;
|
||||
RetainerEdges edges;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback function invoked to retrieve all RetainerInfos from the embedder.
|
||||
*/
|
||||
typedef RetainerInfos (*GetRetainerInfosCallback)(v8::Isolate* isolate);
|
||||
|
||||
/**
|
||||
* Callback function invoked for obtaining RetainedObjectInfo for
|
||||
* the given JavaScript wrapper object. It is prohibited to enter V8
|
||||
* while the callback is running: only getters on the handle and
|
||||
* GetPointerFromInternalField on the objects are allowed.
|
||||
*/
|
||||
typedef RetainedObjectInfo* (*WrapperInfoCallback)(uint16_t class_id,
|
||||
Local<Value> wrapper);
|
||||
|
||||
/** Returns the number of snapshots taken. */
|
||||
int GetSnapshotCount();
|
||||
|
||||
/** Returns a snapshot by index. */
|
||||
const HeapSnapshot* GetHeapSnapshot(int index);
|
||||
|
||||
/**
|
||||
* Returns SnapshotObjectId for a heap object referenced by |value| if
|
||||
* it has been seen by the heap profiler, kUnknownObjectId otherwise.
|
||||
*/
|
||||
SnapshotObjectId GetObjectId(Local<Value> value);
|
||||
|
||||
/**
|
||||
* Returns heap object with given SnapshotObjectId if the object is alive,
|
||||
* otherwise empty handle is returned.
|
||||
*/
|
||||
Local<Value> FindObjectById(SnapshotObjectId id);
|
||||
|
||||
/**
|
||||
* Clears internal map from SnapshotObjectId to heap object. The new objects
|
||||
* will not be added into it unless a heap snapshot is taken or heap object
|
||||
* tracking is kicked off.
|
||||
*/
|
||||
void ClearObjectIds();
|
||||
|
||||
/**
|
||||
* A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return
|
||||
* it in case heap profiler cannot find id for the object passed as
|
||||
* parameter. HeapSnapshot::GetNodeById will always return NULL for such id.
|
||||
*/
|
||||
static const SnapshotObjectId kUnknownObjectId = 0;
|
||||
|
||||
/**
|
||||
* Callback interface for retrieving user friendly names of global objects.
|
||||
*/
|
||||
class ObjectNameResolver {
|
||||
public:
|
||||
/**
|
||||
* Returns name to be used in the heap snapshot for given node. Returned
|
||||
* string must stay alive until snapshot collection is completed.
|
||||
*/
|
||||
virtual const char* GetName(Local<Object> object) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~ObjectNameResolver() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a heap snapshot and returns it.
|
||||
*/
|
||||
const HeapSnapshot* TakeHeapSnapshot(
|
||||
ActivityControl* control = NULL,
|
||||
ObjectNameResolver* global_object_name_resolver = NULL);
|
||||
|
||||
/**
|
||||
* Starts tracking of heap objects population statistics. After calling
|
||||
* this method, all heap objects relocations done by the garbage collector
|
||||
* are being registered.
|
||||
*
|
||||
* |track_allocations| parameter controls whether stack trace of each
|
||||
* allocation in the heap will be recorded and reported as part of
|
||||
* HeapSnapshot.
|
||||
*/
|
||||
void StartTrackingHeapObjects(bool track_allocations = false);
|
||||
|
||||
/**
|
||||
* Adds a new time interval entry to the aggregated statistics array. The
|
||||
* time interval entry contains information on the current heap objects
|
||||
* population size. The method also updates aggregated statistics and
|
||||
* reports updates for all previous time intervals via the OutputStream
|
||||
* object. Updates on each time interval are provided as a stream of the
|
||||
* HeapStatsUpdate structure instances.
|
||||
* If |timestamp_us| is supplied, timestamp of the new entry will be written
|
||||
* into it. The return value of the function is the last seen heap object Id.
|
||||
*
|
||||
* StartTrackingHeapObjects must be called before the first call to this
|
||||
* method.
|
||||
*/
|
||||
SnapshotObjectId GetHeapStats(OutputStream* stream,
|
||||
int64_t* timestamp_us = NULL);
|
||||
|
||||
/**
|
||||
* Stops tracking of heap objects population statistics, cleans up all
|
||||
* collected data. StartHeapObjectsTracking must be called again prior to
|
||||
* calling GetHeapStats next time.
|
||||
*/
|
||||
void StopTrackingHeapObjects();
|
||||
|
||||
/**
|
||||
* Starts gathering a sampling heap profile. A sampling heap profile is
|
||||
* similar to tcmalloc's heap profiler and Go's mprof. It samples object
|
||||
* allocations and builds an online 'sampling' heap profile. At any point in
|
||||
* time, this profile is expected to be a representative sample of objects
|
||||
* currently live in the system. Each sampled allocation includes the stack
|
||||
* trace at the time of allocation, which makes this really useful for memory
|
||||
* leak detection.
|
||||
*
|
||||
* This mechanism is intended to be cheap enough that it can be used in
|
||||
* production with minimal performance overhead.
|
||||
*
|
||||
* Allocations are sampled using a randomized Poisson process. On average, one
|
||||
* allocation will be sampled every |sample_interval| bytes allocated. The
|
||||
* |stack_depth| parameter controls the maximum number of stack frames to be
|
||||
* captured on each allocation.
|
||||
*
|
||||
* NOTE: This is a proof-of-concept at this point. Right now we only sample
|
||||
* newspace allocations. Support for paged space allocation (e.g. pre-tenured
|
||||
* objects, large objects, code objects, etc.) and native allocations
|
||||
* doesn't exist yet, but is anticipated in the future.
|
||||
*
|
||||
* Objects allocated before the sampling is started will not be included in
|
||||
* the profile.
|
||||
*
|
||||
* Returns false if a sampling heap profiler is already running.
|
||||
*/
|
||||
bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024,
|
||||
int stack_depth = 16,
|
||||
SamplingFlags flags = kSamplingNoFlags);
|
||||
|
||||
/**
|
||||
* Stops the sampling heap profile and discards the current profile.
|
||||
*/
|
||||
void StopSamplingHeapProfiler();
|
||||
|
||||
/**
|
||||
* Returns the sampled profile of allocations allocated (and still live) since
|
||||
* StartSamplingHeapProfiler was called. The ownership of the pointer is
|
||||
* transfered to the caller. Returns nullptr if sampling heap profiler is not
|
||||
* active.
|
||||
*/
|
||||
AllocationProfile* GetAllocationProfile();
|
||||
|
||||
/**
|
||||
* Deletes all snapshots taken. All previously returned pointers to
|
||||
* snapshots and their contents become invalid after this call.
|
||||
*/
|
||||
void DeleteAllHeapSnapshots();
|
||||
|
||||
/** Binds a callback to embedder's class ID. */
|
||||
void SetWrapperClassInfoProvider(
|
||||
uint16_t class_id,
|
||||
WrapperInfoCallback callback);
|
||||
|
||||
void SetGetRetainerInfosCallback(GetRetainerInfosCallback callback);
|
||||
|
||||
/**
|
||||
* Default value of persistent handle class ID. Must not be used to
|
||||
* define a class. Can be used to reset a class of a persistent
|
||||
* handle.
|
||||
*/
|
||||
static const uint16_t kPersistentHandleNoClassId = 0;
|
||||
|
||||
/** Returns memory used for profiler internal data and snapshots. */
|
||||
size_t GetProfilerMemorySize();
|
||||
|
||||
private:
|
||||
HeapProfiler();
|
||||
~HeapProfiler();
|
||||
HeapProfiler(const HeapProfiler&);
|
||||
HeapProfiler& operator=(const HeapProfiler&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for providing information about embedder's objects
|
||||
* held by global handles. This information is reported in two ways:
|
||||
*
|
||||
* 1. When calling AddObjectGroup, an embedder may pass
|
||||
* RetainedObjectInfo instance describing the group. To collect
|
||||
* this information while taking a heap snapshot, V8 calls GC
|
||||
* prologue and epilogue callbacks.
|
||||
*
|
||||
* 2. When a heap snapshot is collected, V8 additionally
|
||||
* requests RetainedObjectInfos for persistent handles that
|
||||
* were not previously reported via AddObjectGroup.
|
||||
*
|
||||
* Thus, if an embedder wants to provide information about native
|
||||
* objects for heap snapshots, it can do it in a GC prologue
|
||||
* handler, and / or by assigning wrapper class ids in the following way:
|
||||
*
|
||||
* 1. Bind a callback to class id by calling SetWrapperClassInfoProvider.
|
||||
* 2. Call SetWrapperClassId on certain persistent handles.
|
||||
*
|
||||
* V8 takes ownership of RetainedObjectInfo instances passed to it and
|
||||
* keeps them alive only during snapshot collection. Afterwards, they
|
||||
* are freed by calling the Dispose class function.
|
||||
*/
|
||||
class V8_EXPORT RetainedObjectInfo { // NOLINT
|
||||
public:
|
||||
/** Called by V8 when it no longer needs an instance. */
|
||||
virtual void Dispose() = 0;
|
||||
|
||||
/** Returns whether two instances are equivalent. */
|
||||
virtual bool IsEquivalent(RetainedObjectInfo* other) = 0;
|
||||
|
||||
/**
|
||||
* Returns hash value for the instance. Equivalent instances
|
||||
* must have the same hash value.
|
||||
*/
|
||||
virtual intptr_t GetHash() = 0;
|
||||
|
||||
/**
|
||||
* Returns human-readable label. It must be a null-terminated UTF-8
|
||||
* encoded string. V8 copies its contents during a call to GetLabel.
|
||||
*/
|
||||
virtual const char* GetLabel() = 0;
|
||||
|
||||
/**
|
||||
* Returns human-readable group label. It must be a null-terminated UTF-8
|
||||
* encoded string. V8 copies its contents during a call to GetGroupLabel.
|
||||
* Heap snapshot generator will collect all the group names, create
|
||||
* top level entries with these names and attach the objects to the
|
||||
* corresponding top level group objects. There is a default
|
||||
* implementation which is required because embedders don't have their
|
||||
* own implementation yet.
|
||||
*/
|
||||
virtual const char* GetGroupLabel() { return GetLabel(); }
|
||||
|
||||
/**
|
||||
* Returns element count in case if a global handle retains
|
||||
* a subgraph by holding one of its nodes.
|
||||
*/
|
||||
virtual intptr_t GetElementCount() { return -1; }
|
||||
|
||||
/** Returns embedder's object size in bytes. */
|
||||
virtual intptr_t GetSizeInBytes() { return -1; }
|
||||
|
||||
protected:
|
||||
RetainedObjectInfo() {}
|
||||
virtual ~RetainedObjectInfo() {}
|
||||
|
||||
private:
|
||||
RetainedObjectInfo(const RetainedObjectInfo&);
|
||||
RetainedObjectInfo& operator=(const RetainedObjectInfo&);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A struct for exporting HeapStats data from V8, using "push" model.
|
||||
* See HeapProfiler::GetHeapStats.
|
||||
*/
|
||||
struct HeapStatsUpdate {
|
||||
HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
|
||||
: index(index), count(count), size(size) { }
|
||||
uint32_t index; // Index of the time interval that was changed.
|
||||
uint32_t count; // New value of count field for the interval with this index.
|
||||
uint32_t size; // New value of size field for the interval with this index.
|
||||
};
|
||||
|
||||
|
||||
} // namespace v8
|
||||
|
||||
|
||||
#endif // V8_V8_PROFILER_H_
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_TEST_H_
|
||||
#define V8_V8_TEST_H_
|
||||
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
|
||||
/**
|
||||
* Testing support for the V8 JavaScript engine.
|
||||
*/
|
||||
namespace v8 {
|
||||
|
||||
class V8_EXPORT Testing {
|
||||
public:
|
||||
enum StressType {
|
||||
kStressTypeOpt,
|
||||
kStressTypeDeopt
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the type of stressing to do. The default if not set is kStressTypeOpt.
|
||||
*/
|
||||
static void SetStressRunType(StressType type);
|
||||
|
||||
/**
|
||||
* Get the number of runs of a given test that is required to get the full
|
||||
* stress coverage.
|
||||
*/
|
||||
static int GetStressRuns();
|
||||
|
||||
/**
|
||||
* Indicate the number of the run which is about to start. The value of run
|
||||
* should be between 0 and one less than the result from GetStressRuns()
|
||||
*/
|
||||
static void PrepareStressRun(int run);
|
||||
|
||||
/**
|
||||
* Force deoptimization of all functions.
|
||||
*/
|
||||
static void DeoptimizeAll(Isolate* isolate);
|
||||
};
|
||||
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_V8_TEST_H_
|
||||
|
|
@ -0,0 +1,655 @@
|
|||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_UTIL_H_
|
||||
#define V8_UTIL_H_
|
||||
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Support for Persistent containers.
|
||||
*
|
||||
* C++11 embedders can use STL containers with Global values,
|
||||
* but pre-C++11 does not support the required move semantic and hence
|
||||
* may want these container classes.
|
||||
*/
|
||||
namespace v8 {
|
||||
|
||||
typedef uintptr_t PersistentContainerValue;
|
||||
static const uintptr_t kPersistentContainerNotFound = 0;
|
||||
enum PersistentContainerCallbackType {
|
||||
kNotWeak,
|
||||
// These correspond to v8::WeakCallbackType
|
||||
kWeakWithParameter,
|
||||
kWeakWithInternalFields,
|
||||
kWeak = kWeakWithParameter // For backwards compatibility. Deprecate.
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A default trait implemenation for PersistentValueMap which uses std::map
|
||||
* as a backing map.
|
||||
*
|
||||
* Users will have to implement their own weak callbacks & dispose traits.
|
||||
*/
|
||||
template<typename K, typename V>
|
||||
class StdMapTraits {
|
||||
public:
|
||||
// STL map & related:
|
||||
typedef std::map<K, PersistentContainerValue> Impl;
|
||||
typedef typename Impl::iterator Iterator;
|
||||
|
||||
static bool Empty(Impl* impl) { return impl->empty(); }
|
||||
static size_t Size(Impl* impl) { return impl->size(); }
|
||||
static void Swap(Impl& a, Impl& b) { std::swap(a, b); } // NOLINT
|
||||
static Iterator Begin(Impl* impl) { return impl->begin(); }
|
||||
static Iterator End(Impl* impl) { return impl->end(); }
|
||||
static K Key(Iterator it) { return it->first; }
|
||||
static PersistentContainerValue Value(Iterator it) { return it->second; }
|
||||
static PersistentContainerValue Set(Impl* impl, K key,
|
||||
PersistentContainerValue value) {
|
||||
std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value));
|
||||
PersistentContainerValue old_value = kPersistentContainerNotFound;
|
||||
if (!res.second) {
|
||||
old_value = res.first->second;
|
||||
res.first->second = value;
|
||||
}
|
||||
return old_value;
|
||||
}
|
||||
static PersistentContainerValue Get(Impl* impl, K key) {
|
||||
Iterator it = impl->find(key);
|
||||
if (it == impl->end()) return kPersistentContainerNotFound;
|
||||
return it->second;
|
||||
}
|
||||
static PersistentContainerValue Remove(Impl* impl, K key) {
|
||||
Iterator it = impl->find(key);
|
||||
if (it == impl->end()) return kPersistentContainerNotFound;
|
||||
PersistentContainerValue value = it->second;
|
||||
impl->erase(it);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A default trait implementation for PersistentValueMap, which inherits
|
||||
* a std:map backing map from StdMapTraits and holds non-weak persistent
|
||||
* objects and has no special Dispose handling.
|
||||
*
|
||||
* You should not derive from this class, since MapType depends on the
|
||||
* surrounding class, and hence a subclass cannot simply inherit the methods.
|
||||
*/
|
||||
template<typename K, typename V>
|
||||
class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
|
||||
public:
|
||||
// Weak callback & friends:
|
||||
static const PersistentContainerCallbackType kCallbackType = kNotWeak;
|
||||
typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> >
|
||||
MapType;
|
||||
typedef void WeakCallbackDataType;
|
||||
|
||||
static WeakCallbackDataType* WeakCallbackParameter(
|
||||
MapType* map, const K& key, Local<V> value) {
|
||||
return NULL;
|
||||
}
|
||||
static MapType* MapFromWeakCallbackInfo(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {
|
||||
return NULL;
|
||||
}
|
||||
static K KeyFromWeakCallbackInfo(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {
|
||||
return K();
|
||||
}
|
||||
static void DisposeCallbackData(WeakCallbackDataType* data) { }
|
||||
static void Dispose(Isolate* isolate, Global<V> value, K key) {}
|
||||
};
|
||||
|
||||
|
||||
template <typename K, typename V>
|
||||
class DefaultGlobalMapTraits : public StdMapTraits<K, V> {
|
||||
private:
|
||||
template <typename T>
|
||||
struct RemovePointer;
|
||||
|
||||
public:
|
||||
// Weak callback & friends:
|
||||
static const PersistentContainerCallbackType kCallbackType = kNotWeak;
|
||||
typedef GlobalValueMap<K, V, DefaultGlobalMapTraits<K, V> > MapType;
|
||||
typedef void WeakCallbackDataType;
|
||||
|
||||
static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
|
||||
Local<V> value) {
|
||||
return nullptr;
|
||||
}
|
||||
static MapType* MapFromWeakCallbackInfo(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {
|
||||
return nullptr;
|
||||
}
|
||||
static K KeyFromWeakCallbackInfo(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {
|
||||
return K();
|
||||
}
|
||||
static void DisposeCallbackData(WeakCallbackDataType* data) {}
|
||||
static void OnWeakCallback(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {}
|
||||
static void Dispose(Isolate* isolate, Global<V> value, K key) {}
|
||||
// This is a second pass callback, so SetSecondPassCallback cannot be called.
|
||||
static void DisposeWeak(const WeakCallbackInfo<WeakCallbackDataType>& data) {}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
struct RemovePointer<T*> {
|
||||
typedef T Type;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A map wrapper that allows using Global as a mapped value.
|
||||
* C++11 embedders don't need this class, as they can use Global
|
||||
* directly in std containers.
|
||||
*
|
||||
* The map relies on a backing map, whose type and accessors are described
|
||||
* by the Traits class. The backing map will handle values of type
|
||||
* PersistentContainerValue, with all conversion into and out of V8
|
||||
* handles being transparently handled by this class.
|
||||
*/
|
||||
template <typename K, typename V, typename Traits>
|
||||
class PersistentValueMapBase {
|
||||
public:
|
||||
Isolate* GetIsolate() { return isolate_; }
|
||||
|
||||
/**
|
||||
* Return size of the map.
|
||||
*/
|
||||
size_t Size() { return Traits::Size(&impl_); }
|
||||
|
||||
/**
|
||||
* Return whether the map holds weak persistents.
|
||||
*/
|
||||
bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
|
||||
|
||||
/**
|
||||
* Get value stored in map.
|
||||
*/
|
||||
Local<V> Get(const K& key) {
|
||||
return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a value is contained in the map.
|
||||
*/
|
||||
bool Contains(const K& key) {
|
||||
return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value stored in map and set it in returnValue.
|
||||
* Return true if a value was found.
|
||||
*/
|
||||
bool SetReturnValue(const K& key,
|
||||
ReturnValue<Value> returnValue) {
|
||||
return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call Isolate::SetReference with the given parent and the map value.
|
||||
*/
|
||||
void SetReference(const K& key,
|
||||
const Persistent<Object>& parent) {
|
||||
GetIsolate()->SetReference(
|
||||
reinterpret_cast<internal::Object**>(parent.val_),
|
||||
reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call V8::RegisterExternallyReferencedObject with the map value for given
|
||||
* key.
|
||||
*/
|
||||
void RegisterExternallyReferencedObject(K& key) {
|
||||
assert(Contains(key));
|
||||
V8::RegisterExternallyReferencedObject(
|
||||
reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))),
|
||||
reinterpret_cast<internal::Isolate*>(GetIsolate()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value for key and remove it from the map.
|
||||
*/
|
||||
Global<V> Remove(const K& key) {
|
||||
return Release(Traits::Remove(&impl_, key)).Pass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the map repeatedly,
|
||||
* in case side effects of disposal cause insertions.
|
||||
**/
|
||||
void Clear() {
|
||||
typedef typename Traits::Iterator It;
|
||||
HandleScope handle_scope(isolate_);
|
||||
// TODO(dcarney): figure out if this swap and loop is necessary.
|
||||
while (!Traits::Empty(&impl_)) {
|
||||
typename Traits::Impl impl;
|
||||
Traits::Swap(impl_, impl);
|
||||
for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
|
||||
Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
|
||||
Traits::Key(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class for GetReference/SetWithReference. Do not use outside
|
||||
* that context.
|
||||
*/
|
||||
class PersistentValueReference {
|
||||
public:
|
||||
PersistentValueReference() : value_(kPersistentContainerNotFound) { }
|
||||
PersistentValueReference(const PersistentValueReference& other)
|
||||
: value_(other.value_) { }
|
||||
|
||||
Local<V> NewLocal(Isolate* isolate) const {
|
||||
return Local<V>::New(isolate, FromVal(value_));
|
||||
}
|
||||
bool IsEmpty() const {
|
||||
return value_ == kPersistentContainerNotFound;
|
||||
}
|
||||
template<typename T>
|
||||
bool SetReturnValue(ReturnValue<T> returnValue) {
|
||||
return SetReturnValueFromVal(&returnValue, value_);
|
||||
}
|
||||
void Reset() {
|
||||
value_ = kPersistentContainerNotFound;
|
||||
}
|
||||
void operator=(const PersistentValueReference& other) {
|
||||
value_ = other.value_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class PersistentValueMapBase;
|
||||
friend class PersistentValueMap<K, V, Traits>;
|
||||
friend class GlobalValueMap<K, V, Traits>;
|
||||
|
||||
explicit PersistentValueReference(PersistentContainerValue value)
|
||||
: value_(value) { }
|
||||
|
||||
void operator=(PersistentContainerValue value) {
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
PersistentContainerValue value_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a reference to a map value. This enables fast, repeated access
|
||||
* to a value stored in the map while the map remains unchanged.
|
||||
*
|
||||
* Careful: This is potentially unsafe, so please use with care.
|
||||
* The value will become invalid if the value for this key changes
|
||||
* in the underlying map, as a result of Set or Remove for the same
|
||||
* key; as a result of the weak callback for the same key; or as a
|
||||
* result of calling Clear() or destruction of the map.
|
||||
*/
|
||||
PersistentValueReference GetReference(const K& key) {
|
||||
return PersistentValueReference(Traits::Get(&impl_, key));
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {}
|
||||
|
||||
~PersistentValueMapBase() { Clear(); }
|
||||
|
||||
Isolate* isolate() { return isolate_; }
|
||||
typename Traits::Impl* impl() { return &impl_; }
|
||||
|
||||
static V* FromVal(PersistentContainerValue v) {
|
||||
return reinterpret_cast<V*>(v);
|
||||
}
|
||||
|
||||
static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
|
||||
V* v = persistent->val_;
|
||||
persistent->val_ = 0;
|
||||
return reinterpret_cast<PersistentContainerValue>(v);
|
||||
}
|
||||
|
||||
static PersistentContainerValue Leak(Global<V>* persistent) {
|
||||
return reinterpret_cast<PersistentContainerValue>(persistent->val_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a container value as Global and make sure the weak
|
||||
* callback is properly disposed of. All remove functionality should go
|
||||
* through this.
|
||||
*/
|
||||
static Global<V> Release(PersistentContainerValue v) {
|
||||
Global<V> p;
|
||||
p.val_ = FromVal(v);
|
||||
if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
|
||||
Traits::DisposeCallbackData(
|
||||
p.template ClearWeak<typename Traits::WeakCallbackDataType>());
|
||||
}
|
||||
return p.Pass();
|
||||
}
|
||||
|
||||
void RemoveWeak(const K& key) {
|
||||
Global<V> p;
|
||||
p.val_ = FromVal(Traits::Remove(&impl_, key));
|
||||
p.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
PersistentValueMapBase(PersistentValueMapBase&);
|
||||
void operator=(PersistentValueMapBase&);
|
||||
|
||||
static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
|
||||
PersistentContainerValue value) {
|
||||
bool hasValue = value != kPersistentContainerNotFound;
|
||||
if (hasValue) {
|
||||
returnValue->SetInternal(
|
||||
*reinterpret_cast<internal::Object**>(FromVal(value)));
|
||||
}
|
||||
return hasValue;
|
||||
}
|
||||
|
||||
Isolate* isolate_;
|
||||
typename Traits::Impl impl_;
|
||||
};
|
||||
|
||||
|
||||
template <typename K, typename V, typename Traits>
|
||||
class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
|
||||
public:
|
||||
explicit PersistentValueMap(Isolate* isolate)
|
||||
: PersistentValueMapBase<K, V, Traits>(isolate) {}
|
||||
|
||||
typedef
|
||||
typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
|
||||
PersistentValueReference;
|
||||
|
||||
/**
|
||||
* Put value into map. Depending on Traits::kIsWeak, the value will be held
|
||||
* by the map strongly or weakly.
|
||||
* Returns old value as Global.
|
||||
*/
|
||||
Global<V> Set(const K& key, Local<V> value) {
|
||||
Global<V> persistent(this->isolate(), value);
|
||||
return SetUnique(key, &persistent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put value into map, like Set(const K&, Local<V>).
|
||||
*/
|
||||
Global<V> Set(const K& key, Global<V> value) {
|
||||
return SetUnique(key, &value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the value into the map, and set the 'weak' callback when demanded
|
||||
* by the Traits class.
|
||||
*/
|
||||
Global<V> SetUnique(const K& key, Global<V>* persistent) {
|
||||
if (Traits::kCallbackType != kNotWeak) {
|
||||
Local<V> value(Local<V>::New(this->isolate(), *persistent));
|
||||
persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
|
||||
Traits::WeakCallbackParameter(this, key, value), WeakCallback);
|
||||
}
|
||||
PersistentContainerValue old_value =
|
||||
Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
|
||||
return this->Release(old_value).Pass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value into the map and update the reference.
|
||||
* Restrictions of GetReference apply here as well.
|
||||
*/
|
||||
Global<V> Set(const K& key, Global<V> value,
|
||||
PersistentValueReference* reference) {
|
||||
*reference = this->Leak(&value);
|
||||
return SetUnique(key, &value);
|
||||
}
|
||||
|
||||
private:
|
||||
static void WeakCallback(
|
||||
const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
|
||||
if (Traits::kCallbackType != kNotWeak) {
|
||||
PersistentValueMap<K, V, Traits>* persistentValueMap =
|
||||
Traits::MapFromWeakCallbackInfo(data);
|
||||
K key = Traits::KeyFromWeakCallbackInfo(data);
|
||||
Traits::Dispose(data.GetIsolate(),
|
||||
persistentValueMap->Remove(key).Pass(), key);
|
||||
Traits::DisposeCallbackData(data.GetParameter());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename K, typename V, typename Traits>
|
||||
class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
|
||||
public:
|
||||
explicit GlobalValueMap(Isolate* isolate)
|
||||
: PersistentValueMapBase<K, V, Traits>(isolate) {}
|
||||
|
||||
typedef
|
||||
typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
|
||||
PersistentValueReference;
|
||||
|
||||
/**
|
||||
* Put value into map. Depending on Traits::kIsWeak, the value will be held
|
||||
* by the map strongly or weakly.
|
||||
* Returns old value as Global.
|
||||
*/
|
||||
Global<V> Set(const K& key, Local<V> value) {
|
||||
Global<V> persistent(this->isolate(), value);
|
||||
return SetUnique(key, &persistent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put value into map, like Set(const K&, Local<V>).
|
||||
*/
|
||||
Global<V> Set(const K& key, Global<V> value) {
|
||||
return SetUnique(key, &value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the value into the map, and set the 'weak' callback when demanded
|
||||
* by the Traits class.
|
||||
*/
|
||||
Global<V> SetUnique(const K& key, Global<V>* persistent) {
|
||||
if (Traits::kCallbackType != kNotWeak) {
|
||||
WeakCallbackType callback_type =
|
||||
Traits::kCallbackType == kWeakWithInternalFields
|
||||
? WeakCallbackType::kInternalFields
|
||||
: WeakCallbackType::kParameter;
|
||||
Local<V> value(Local<V>::New(this->isolate(), *persistent));
|
||||
persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
|
||||
Traits::WeakCallbackParameter(this, key, value), OnWeakCallback,
|
||||
callback_type);
|
||||
}
|
||||
PersistentContainerValue old_value =
|
||||
Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
|
||||
return this->Release(old_value).Pass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value into the map and update the reference.
|
||||
* Restrictions of GetReference apply here as well.
|
||||
*/
|
||||
Global<V> Set(const K& key, Global<V> value,
|
||||
PersistentValueReference* reference) {
|
||||
*reference = this->Leak(&value);
|
||||
return SetUnique(key, &value);
|
||||
}
|
||||
|
||||
private:
|
||||
static void OnWeakCallback(
|
||||
const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
|
||||
if (Traits::kCallbackType != kNotWeak) {
|
||||
auto map = Traits::MapFromWeakCallbackInfo(data);
|
||||
K key = Traits::KeyFromWeakCallbackInfo(data);
|
||||
map->RemoveWeak(key);
|
||||
Traits::OnWeakCallback(data);
|
||||
data.SetSecondPassCallback(SecondWeakCallback);
|
||||
}
|
||||
}
|
||||
|
||||
static void SecondWeakCallback(
|
||||
const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
|
||||
Traits::DisposeWeak(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A map that uses Global as value and std::map as the backing
|
||||
* implementation. Persistents are held non-weak.
|
||||
*
|
||||
* C++11 embedders don't need this class, as they can use
|
||||
* Global directly in std containers.
|
||||
*/
|
||||
template<typename K, typename V,
|
||||
typename Traits = DefaultPersistentValueMapTraits<K, V> >
|
||||
class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
|
||||
public:
|
||||
explicit StdPersistentValueMap(Isolate* isolate)
|
||||
: PersistentValueMap<K, V, Traits>(isolate) {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A map that uses Global as value and std::map as the backing
|
||||
* implementation. Globals are held non-weak.
|
||||
*
|
||||
* C++11 embedders don't need this class, as they can use
|
||||
* Global directly in std containers.
|
||||
*/
|
||||
template <typename K, typename V,
|
||||
typename Traits = DefaultGlobalMapTraits<K, V> >
|
||||
class StdGlobalValueMap : public GlobalValueMap<K, V, Traits> {
|
||||
public:
|
||||
explicit StdGlobalValueMap(Isolate* isolate)
|
||||
: GlobalValueMap<K, V, Traits>(isolate) {}
|
||||
};
|
||||
|
||||
|
||||
class DefaultPersistentValueVectorTraits {
|
||||
public:
|
||||
typedef std::vector<PersistentContainerValue> Impl;
|
||||
|
||||
static void Append(Impl* impl, PersistentContainerValue value) {
|
||||
impl->push_back(value);
|
||||
}
|
||||
static bool IsEmpty(const Impl* impl) {
|
||||
return impl->empty();
|
||||
}
|
||||
static size_t Size(const Impl* impl) {
|
||||
return impl->size();
|
||||
}
|
||||
static PersistentContainerValue Get(const Impl* impl, size_t i) {
|
||||
return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
|
||||
}
|
||||
static void ReserveCapacity(Impl* impl, size_t capacity) {
|
||||
impl->reserve(capacity);
|
||||
}
|
||||
static void Clear(Impl* impl) {
|
||||
impl->clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A vector wrapper that safely stores Global values.
|
||||
* C++11 embedders don't need this class, as they can use Global
|
||||
* directly in std containers.
|
||||
*
|
||||
* This class relies on a backing vector implementation, whose type and methods
|
||||
* are described by the Traits class. The backing map will handle values of type
|
||||
* PersistentContainerValue, with all conversion into and out of V8
|
||||
* handles being transparently handled by this class.
|
||||
*/
|
||||
template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
|
||||
class PersistentValueVector {
|
||||
public:
|
||||
explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
|
||||
|
||||
~PersistentValueVector() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a value to the vector.
|
||||
*/
|
||||
void Append(Local<V> value) {
|
||||
Global<V> persistent(isolate_, value);
|
||||
Traits::Append(&impl_, ClearAndLeak(&persistent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a persistent's value to the vector.
|
||||
*/
|
||||
void Append(Global<V> persistent) {
|
||||
Traits::Append(&impl_, ClearAndLeak(&persistent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Are there any values in the vector?
|
||||
*/
|
||||
bool IsEmpty() const {
|
||||
return Traits::IsEmpty(&impl_);
|
||||
}
|
||||
|
||||
/**
|
||||
* How many elements are in the vector?
|
||||
*/
|
||||
size_t Size() const {
|
||||
return Traits::Size(&impl_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the i-th value in the vector.
|
||||
*/
|
||||
Local<V> Get(size_t index) const {
|
||||
return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements from the vector.
|
||||
*/
|
||||
void Clear() {
|
||||
size_t length = Traits::Size(&impl_);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
Global<V> p;
|
||||
p.val_ = FromVal(Traits::Get(&impl_, i));
|
||||
}
|
||||
Traits::Clear(&impl_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve capacity in the vector.
|
||||
* (Efficiency gains depend on the backing implementation.)
|
||||
*/
|
||||
void ReserveCapacity(size_t capacity) {
|
||||
Traits::ReserveCapacity(&impl_, capacity);
|
||||
}
|
||||
|
||||
private:
|
||||
static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
|
||||
V* v = persistent->val_;
|
||||
persistent->val_ = 0;
|
||||
return reinterpret_cast<PersistentContainerValue>(v);
|
||||
}
|
||||
|
||||
static V* FromVal(PersistentContainerValue v) {
|
||||
return reinterpret_cast<V*>(v);
|
||||
}
|
||||
|
||||
Isolate* isolate_;
|
||||
typename Traits::Impl impl_;
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_UTIL_H
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* Compile-time constants.
|
||||
*
|
||||
* This header provides access to information about the value serializer at
|
||||
* compile time, without declaring or defining any symbols that require linking
|
||||
* to V8.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_V8_VALUE_SERIALIZER_VERSION_H_
|
||||
#define INCLUDE_V8_VALUE_SERIALIZER_VERSION_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace v8 {
|
||||
|
||||
constexpr uint32_t CurrentValueSerializerFormatVersion() { return 13; }
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#endif // INCLUDE_V8_VALUE_SERIALIZER_VERSION_H_
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_VERSION_STRING_H_
|
||||
#define V8_VERSION_STRING_H_
|
||||
|
||||
#include "v8-version.h" // NOLINT(build/include)
|
||||
|
||||
// This is here rather than v8-version.h to keep that file simple and
|
||||
// machine-processable.
|
||||
|
||||
#if V8_IS_CANDIDATE_VERSION
|
||||
#define V8_CANDIDATE_STRING " (candidate)"
|
||||
#else
|
||||
#define V8_CANDIDATE_STRING ""
|
||||
#endif
|
||||
|
||||
#define V8_SX(x) #x
|
||||
#define V8_S(x) V8_SX(x)
|
||||
|
||||
#if V8_PATCH_LEVEL > 0
|
||||
#define V8_VERSION_STRING \
|
||||
V8_S(V8_MAJOR_VERSION) \
|
||||
"." V8_S(V8_MINOR_VERSION) "." V8_S(V8_BUILD_NUMBER) "." V8_S( \
|
||||
V8_PATCH_LEVEL) V8_CANDIDATE_STRING
|
||||
#else
|
||||
#define V8_VERSION_STRING \
|
||||
V8_S(V8_MAJOR_VERSION) \
|
||||
"." V8_S(V8_MINOR_VERSION) "." V8_S(V8_BUILD_NUMBER) V8_CANDIDATE_STRING
|
||||
#endif
|
||||
|
||||
#endif // V8_VERSION_STRING_H_
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_INCLUDE_VERSION_H_ // V8_VERSION_H_ conflicts with src/version.h
|
||||
#define V8_INCLUDE_VERSION_H_
|
||||
|
||||
// These macros define the version number for the current version.
|
||||
// NOTE these macros are used by some of the tool scripts and the build
|
||||
// system so their names cannot be changed without changing the scripts.
|
||||
#define V8_MAJOR_VERSION 6
|
||||
#define V8_MINOR_VERSION 0
|
||||
#define V8_BUILD_NUMBER 286
|
||||
#define V8_PATCH_LEVEL 52
|
||||
|
||||
// Use 1 for candidates and 0 otherwise.
|
||||
// (Boolean macro values are not supported by all preprocessors.)
|
||||
#define V8_IS_CANDIDATE_VERSION 0
|
||||
|
||||
#endif // V8_INCLUDE_VERSION_H_
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,428 @@
|
|||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8CONFIG_H_
|
||||
#define V8CONFIG_H_
|
||||
|
||||
// clang-format off
|
||||
|
||||
// Platform headers for feature detection below.
|
||||
#if defined(__ANDROID__)
|
||||
# include <sys/cdefs.h>
|
||||
#elif defined(__APPLE__)
|
||||
# include <TargetConditionals.h>
|
||||
#elif defined(__linux__)
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
|
||||
// This macro allows to test for the version of the GNU C library (or
|
||||
// a compatible C library that masquerades as glibc). It evaluates to
|
||||
// 0 if libc is not GNU libc or compatible.
|
||||
// Use like:
|
||||
// #if V8_GLIBC_PREREQ(2, 3)
|
||||
// ...
|
||||
// #endif
|
||||
#if defined(__GLIBC__) && defined(__GLIBC_MINOR__)
|
||||
# define V8_GLIBC_PREREQ(major, minor) \
|
||||
((__GLIBC__ * 100 + __GLIBC_MINOR__) >= ((major) * 100 + (minor)))
|
||||
#else
|
||||
# define V8_GLIBC_PREREQ(major, minor) 0
|
||||
#endif
|
||||
|
||||
|
||||
// This macro allows to test for the version of the GNU C++ compiler.
|
||||
// Note that this also applies to compilers that masquerade as GCC,
|
||||
// for example clang and the Intel C++ compiler for Linux.
|
||||
// Use like:
|
||||
// #if V8_GNUC_PREREQ(4, 3, 1)
|
||||
// ...
|
||||
// #endif
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
|
||||
# define V8_GNUC_PREREQ(major, minor, patchlevel) \
|
||||
((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= \
|
||||
((major) * 10000 + (minor) * 100 + (patchlevel)))
|
||||
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define V8_GNUC_PREREQ(major, minor, patchlevel) \
|
||||
((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= \
|
||||
((major) * 10000 + (minor) * 100 + (patchlevel)))
|
||||
#else
|
||||
# define V8_GNUC_PREREQ(major, minor, patchlevel) 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Operating system detection
|
||||
//
|
||||
// V8_OS_ANDROID - Android
|
||||
// V8_OS_BSD - BSDish (Mac OS X, Net/Free/Open/DragonFlyBSD)
|
||||
// V8_OS_CYGWIN - Cygwin
|
||||
// V8_OS_DRAGONFLYBSD - DragonFlyBSD
|
||||
// V8_OS_FREEBSD - FreeBSD
|
||||
// V8_OS_LINUX - Linux
|
||||
// V8_OS_MACOSX - Mac OS X
|
||||
// V8_OS_NETBSD - NetBSD
|
||||
// V8_OS_OPENBSD - OpenBSD
|
||||
// V8_OS_POSIX - POSIX compatible (mostly everything except Windows)
|
||||
// V8_OS_QNX - QNX Neutrino
|
||||
// V8_OS_SOLARIS - Sun Solaris and OpenSolaris
|
||||
// V8_OS_AIX - AIX
|
||||
// V8_OS_WIN - Microsoft Windows
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
# define V8_OS_ANDROID 1
|
||||
# define V8_OS_LINUX 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__APPLE__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_MACOSX 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__CYGWIN__)
|
||||
# define V8_OS_CYGWIN 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__linux__)
|
||||
# define V8_OS_LINUX 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__sun)
|
||||
# define V8_OS_POSIX 1
|
||||
# define V8_OS_SOLARIS 1
|
||||
#elif defined(_AIX)
|
||||
#define V8_OS_POSIX 1
|
||||
#define V8_OS_AIX 1
|
||||
#elif defined(__FreeBSD__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_FREEBSD 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__DragonFly__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_DRAGONFLYBSD 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__NetBSD__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_NETBSD 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__OpenBSD__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_OPENBSD 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__QNXNTO__)
|
||||
# define V8_OS_POSIX 1
|
||||
# define V8_OS_QNX 1
|
||||
#elif defined(_WIN32)
|
||||
# define V8_OS_WIN 1
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// C library detection
|
||||
//
|
||||
// V8_LIBC_MSVCRT - MSVC libc
|
||||
// V8_LIBC_BIONIC - Bionic libc
|
||||
// V8_LIBC_BSD - BSD libc derivate
|
||||
// V8_LIBC_GLIBC - GNU C library
|
||||
// V8_LIBC_UCLIBC - uClibc
|
||||
//
|
||||
// Note that testing for libc must be done using #if not #ifdef. For example,
|
||||
// to test for the GNU C library, use:
|
||||
// #if V8_LIBC_GLIBC
|
||||
// ...
|
||||
// #endif
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# define V8_LIBC_MSVCRT 1
|
||||
#elif defined(__BIONIC__)
|
||||
# define V8_LIBC_BIONIC 1
|
||||
# define V8_LIBC_BSD 1
|
||||
#elif defined(__UCLIBC__)
|
||||
// Must test for UCLIBC before GLIBC, as UCLIBC pretends to be GLIBC.
|
||||
# define V8_LIBC_UCLIBC 1
|
||||
#elif defined(__GLIBC__) || defined(__GNU_LIBRARY__)
|
||||
# define V8_LIBC_GLIBC 1
|
||||
#else
|
||||
# define V8_LIBC_BSD V8_OS_BSD
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Compiler detection
|
||||
//
|
||||
// V8_CC_GNU - GCC, or clang in gcc mode
|
||||
// V8_CC_INTEL - Intel C++
|
||||
// V8_CC_MINGW - Minimalist GNU for Windows
|
||||
// V8_CC_MINGW32 - Minimalist GNU for Windows (mingw32)
|
||||
// V8_CC_MINGW64 - Minimalist GNU for Windows (mingw-w64)
|
||||
// V8_CC_MSVC - Microsoft Visual C/C++, or clang in cl.exe mode
|
||||
//
|
||||
// C++11 feature detection
|
||||
//
|
||||
// V8_HAS_CXX11_ALIGNAS - alignas specifier supported
|
||||
// V8_HAS_CXX11_ALIGNOF - alignof(type) operator supported
|
||||
//
|
||||
// Compiler-specific feature detection
|
||||
//
|
||||
// V8_HAS___ALIGNOF - __alignof(type) operator supported
|
||||
// V8_HAS___ALIGNOF__ - __alignof__(type) operator supported
|
||||
// V8_HAS_ATTRIBUTE_ALIGNED - __attribute__((aligned(n))) supported
|
||||
// V8_HAS_ATTRIBUTE_ALWAYS_INLINE - __attribute__((always_inline))
|
||||
// supported
|
||||
// V8_HAS_ATTRIBUTE_DEPRECATED - __attribute__((deprecated)) supported
|
||||
// V8_HAS_ATTRIBUTE_NOINLINE - __attribute__((noinline)) supported
|
||||
// V8_HAS_ATTRIBUTE_NORETURN - __attribute__((noreturn)) supported
|
||||
// V8_HAS_ATTRIBUTE_UNUSED - __attribute__((unused)) supported
|
||||
// V8_HAS_ATTRIBUTE_VISIBILITY - __attribute__((visibility)) supported
|
||||
// V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT - __attribute__((warn_unused_result))
|
||||
// supported
|
||||
// V8_HAS_BUILTIN_CLZ - __builtin_clz() supported
|
||||
// V8_HAS_BUILTIN_CTZ - __builtin_ctz() supported
|
||||
// V8_HAS_BUILTIN_EXPECT - __builtin_expect() supported
|
||||
// V8_HAS_BUILTIN_FRAME_ADDRESS - __builtin_frame_address() supported
|
||||
// V8_HAS_BUILTIN_POPCOUNT - __builtin_popcount() supported
|
||||
// V8_HAS_BUILTIN_SADD_OVERFLOW - __builtin_sadd_overflow() supported
|
||||
// V8_HAS_BUILTIN_SSUB_OVERFLOW - __builtin_ssub_overflow() supported
|
||||
// V8_HAS_BUILTIN_UADD_OVERFLOW - __builtin_uadd_overflow() supported
|
||||
// V8_HAS_DECLSPEC_ALIGN - __declspec(align(n)) supported
|
||||
// V8_HAS_DECLSPEC_DEPRECATED - __declspec(deprecated) supported
|
||||
// V8_HAS_DECLSPEC_NOINLINE - __declspec(noinline) supported
|
||||
// V8_HAS_DECLSPEC_SELECTANY - __declspec(selectany) supported
|
||||
// V8_HAS_DECLSPEC_NORETURN - __declspec(noreturn) supported
|
||||
// V8_HAS___FORCEINLINE - __forceinline supported
|
||||
//
|
||||
// Note that testing for compilers and/or features must be done using #if
|
||||
// not #ifdef. For example, to test for Intel C++ Compiler, use:
|
||||
// #if V8_CC_INTEL
|
||||
// ...
|
||||
// #endif
|
||||
|
||||
#if defined(__clang__)
|
||||
|
||||
#if defined(__GNUC__) // Clang in gcc mode.
|
||||
# define V8_CC_GNU 1
|
||||
#endif
|
||||
|
||||
// Clang defines __alignof__ as alias for __alignof
|
||||
# define V8_HAS___ALIGNOF 1
|
||||
# define V8_HAS___ALIGNOF__ V8_HAS___ALIGNOF
|
||||
|
||||
# define V8_HAS_ATTRIBUTE_ALIGNED (__has_attribute(aligned))
|
||||
# define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline))
|
||||
# define V8_HAS_ATTRIBUTE_DEPRECATED (__has_attribute(deprecated))
|
||||
# define V8_HAS_ATTRIBUTE_NOINLINE (__has_attribute(noinline))
|
||||
# define V8_HAS_ATTRIBUTE_NORETURN (__has_attribute(noreturn))
|
||||
# define V8_HAS_ATTRIBUTE_UNUSED (__has_attribute(unused))
|
||||
# define V8_HAS_ATTRIBUTE_VISIBILITY (__has_attribute(visibility))
|
||||
# define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \
|
||||
(__has_attribute(warn_unused_result))
|
||||
|
||||
# define V8_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz))
|
||||
# define V8_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz))
|
||||
# define V8_HAS_BUILTIN_EXPECT (__has_builtin(__builtin_expect))
|
||||
# define V8_HAS_BUILTIN_FRAME_ADDRESS (__has_builtin(__builtin_frame_address))
|
||||
# define V8_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount))
|
||||
# define V8_HAS_BUILTIN_SADD_OVERFLOW (__has_builtin(__builtin_sadd_overflow))
|
||||
# define V8_HAS_BUILTIN_SSUB_OVERFLOW (__has_builtin(__builtin_ssub_overflow))
|
||||
# define V8_HAS_BUILTIN_UADD_OVERFLOW (__has_builtin(__builtin_uadd_overflow))
|
||||
|
||||
# define V8_HAS_CXX11_ALIGNAS (__has_feature(cxx_alignas))
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
# define V8_CC_GNU 1
|
||||
# if defined(__INTEL_COMPILER) // Intel C++ also masquerades as GCC 3.2.0
|
||||
# define V8_CC_INTEL 1
|
||||
# endif
|
||||
# if defined(__MINGW32__)
|
||||
# define V8_CC_MINGW32 1
|
||||
# endif
|
||||
# if defined(__MINGW64__)
|
||||
# define V8_CC_MINGW64 1
|
||||
# endif
|
||||
# define V8_CC_MINGW (V8_CC_MINGW32 || V8_CC_MINGW64)
|
||||
|
||||
# define V8_HAS___ALIGNOF__ (V8_GNUC_PREREQ(4, 3, 0))
|
||||
|
||||
# define V8_HAS_ATTRIBUTE_ALIGNED (V8_GNUC_PREREQ(2, 95, 0))
|
||||
// always_inline is available in gcc 4.0 but not very reliable until 4.4.
|
||||
// Works around "sorry, unimplemented: inlining failed" build errors with
|
||||
// older compilers.
|
||||
# define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (V8_GNUC_PREREQ(4, 4, 0))
|
||||
# define V8_HAS_ATTRIBUTE_DEPRECATED (V8_GNUC_PREREQ(3, 4, 0))
|
||||
# define V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE (V8_GNUC_PREREQ(4, 5, 0))
|
||||
# define V8_HAS_ATTRIBUTE_NOINLINE (V8_GNUC_PREREQ(3, 4, 0))
|
||||
# define V8_HAS_ATTRIBUTE_NORETURN (V8_GNUC_PREREQ(2, 5, 0))
|
||||
# define V8_HAS_ATTRIBUTE_UNUSED (V8_GNUC_PREREQ(2, 95, 0))
|
||||
# define V8_HAS_ATTRIBUTE_VISIBILITY (V8_GNUC_PREREQ(4, 3, 0))
|
||||
# define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \
|
||||
(!V8_CC_INTEL && V8_GNUC_PREREQ(4, 1, 0))
|
||||
|
||||
# define V8_HAS_BUILTIN_CLZ (V8_GNUC_PREREQ(3, 4, 0))
|
||||
# define V8_HAS_BUILTIN_CTZ (V8_GNUC_PREREQ(3, 4, 0))
|
||||
# define V8_HAS_BUILTIN_EXPECT (V8_GNUC_PREREQ(2, 96, 0))
|
||||
# define V8_HAS_BUILTIN_FRAME_ADDRESS (V8_GNUC_PREREQ(2, 96, 0))
|
||||
# define V8_HAS_BUILTIN_POPCOUNT (V8_GNUC_PREREQ(3, 4, 0))
|
||||
|
||||
# if __cplusplus >= 201103L
|
||||
# define V8_HAS_CXX11_ALIGNAS (V8_GNUC_PREREQ(4, 8, 0))
|
||||
# define V8_HAS_CXX11_ALIGNOF (V8_GNUC_PREREQ(4, 8, 0))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define V8_CC_MSVC 1
|
||||
# define V8_HAS___ALIGNOF 1
|
||||
|
||||
# define V8_HAS_DECLSPEC_ALIGN 1
|
||||
# define V8_HAS_DECLSPEC_DEPRECATED 1
|
||||
# define V8_HAS_DECLSPEC_NOINLINE 1
|
||||
# define V8_HAS_DECLSPEC_SELECTANY 1
|
||||
# define V8_HAS_DECLSPEC_NORETURN 1
|
||||
|
||||
# define V8_HAS___FORCEINLINE 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Helper macros
|
||||
|
||||
// A macro used to make better inlining. Don't bother for debug builds.
|
||||
// Use like:
|
||||
// V8_INLINE int GetZero() { return 0; }
|
||||
#if !defined(DEBUG) && V8_HAS_ATTRIBUTE_ALWAYS_INLINE
|
||||
# define V8_INLINE inline __attribute__((always_inline))
|
||||
#elif !defined(DEBUG) && V8_HAS___FORCEINLINE
|
||||
# define V8_INLINE __forceinline
|
||||
#else
|
||||
# define V8_INLINE inline
|
||||
#endif
|
||||
|
||||
|
||||
// A macro used to tell the compiler to never inline a particular function.
|
||||
// Don't bother for debug builds.
|
||||
// Use like:
|
||||
// V8_NOINLINE int GetMinusOne() { return -1; }
|
||||
#if !defined(DEBUG) && V8_HAS_ATTRIBUTE_NOINLINE
|
||||
# define V8_NOINLINE __attribute__((noinline))
|
||||
#elif !defined(DEBUG) && V8_HAS_DECLSPEC_NOINLINE
|
||||
# define V8_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
# define V8_NOINLINE /* NOT SUPPORTED */
|
||||
#endif
|
||||
|
||||
|
||||
// A macro used to tell the compiler that a particular function never returns.
|
||||
// Use like:
|
||||
// V8_NORETURN void MyAbort() { abort(); }
|
||||
#if V8_HAS_ATTRIBUTE_NORETURN
|
||||
# define V8_NORETURN __attribute__((noreturn))
|
||||
#elif V8_HAS_DECLSPEC_NORETURN
|
||||
# define V8_NORETURN __declspec(noreturn)
|
||||
#else
|
||||
# define V8_NORETURN /* NOT SUPPORTED */
|
||||
#endif
|
||||
|
||||
|
||||
// A macro (V8_DEPRECATED) to mark classes or functions as deprecated.
|
||||
#if defined(V8_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE
|
||||
#define V8_DEPRECATED(message, declarator) \
|
||||
declarator __attribute__((deprecated(message)))
|
||||
#elif defined(V8_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED
|
||||
#define V8_DEPRECATED(message, declarator) \
|
||||
declarator __attribute__((deprecated))
|
||||
#elif defined(V8_DEPRECATION_WARNINGS) && V8_HAS_DECLSPEC_DEPRECATED
|
||||
#define V8_DEPRECATED(message, declarator) __declspec(deprecated) declarator
|
||||
#else
|
||||
#define V8_DEPRECATED(message, declarator) declarator
|
||||
#endif
|
||||
|
||||
|
||||
// A macro (V8_DEPRECATE_SOON) to make it easier to see what will be deprecated.
|
||||
#if defined(V8_IMMINENT_DEPRECATION_WARNINGS) && \
|
||||
V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE
|
||||
#define V8_DEPRECATE_SOON(message, declarator) \
|
||||
declarator __attribute__((deprecated(message)))
|
||||
#elif defined(V8_IMMINENT_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED
|
||||
#define V8_DEPRECATE_SOON(message, declarator) \
|
||||
declarator __attribute__((deprecated))
|
||||
#elif defined(V8_IMMINENT_DEPRECATION_WARNINGS) && V8_HAS_DECLSPEC_DEPRECATED
|
||||
#define V8_DEPRECATE_SOON(message, declarator) __declspec(deprecated) declarator
|
||||
#else
|
||||
#define V8_DEPRECATE_SOON(message, declarator) declarator
|
||||
#endif
|
||||
|
||||
|
||||
// A macro to provide the compiler with branch prediction information.
|
||||
#if V8_HAS_BUILTIN_EXPECT
|
||||
# define V8_UNLIKELY(condition) (__builtin_expect(!!(condition), 0))
|
||||
# define V8_LIKELY(condition) (__builtin_expect(!!(condition), 1))
|
||||
#else
|
||||
# define V8_UNLIKELY(condition) (condition)
|
||||
# define V8_LIKELY(condition) (condition)
|
||||
#endif
|
||||
|
||||
|
||||
// This macro allows to specify memory alignment for structs, classes, etc.
|
||||
// Use like:
|
||||
// class V8_ALIGNED(16) MyClass { ... };
|
||||
// V8_ALIGNED(32) int array[42];
|
||||
#if V8_HAS_CXX11_ALIGNAS
|
||||
# define V8_ALIGNED(n) alignas(n)
|
||||
#elif V8_HAS_ATTRIBUTE_ALIGNED
|
||||
# define V8_ALIGNED(n) __attribute__((aligned(n)))
|
||||
#elif V8_HAS_DECLSPEC_ALIGN
|
||||
# define V8_ALIGNED(n) __declspec(align(n))
|
||||
#else
|
||||
# define V8_ALIGNED(n) /* NOT SUPPORTED */
|
||||
#endif
|
||||
|
||||
|
||||
// This macro is similar to V8_ALIGNED(), but takes a type instead of size
|
||||
// in bytes. If the compiler does not supports using the alignment of the
|
||||
// |type|, it will align according to the |alignment| instead. For example,
|
||||
// Visual Studio C++ cannot combine __declspec(align) and __alignof. The
|
||||
// |alignment| must be a literal that is used as a kind of worst-case fallback
|
||||
// alignment.
|
||||
// Use like:
|
||||
// struct V8_ALIGNAS(AnotherClass, 16) NewClass { ... };
|
||||
// V8_ALIGNAS(double, 8) int array[100];
|
||||
#if V8_HAS_CXX11_ALIGNAS
|
||||
# define V8_ALIGNAS(type, alignment) alignas(type)
|
||||
#elif V8_HAS___ALIGNOF__ && V8_HAS_ATTRIBUTE_ALIGNED
|
||||
# define V8_ALIGNAS(type, alignment) __attribute__((aligned(__alignof__(type))))
|
||||
#else
|
||||
# define V8_ALIGNAS(type, alignment) V8_ALIGNED(alignment)
|
||||
#endif
|
||||
|
||||
|
||||
// This macro returns alignment in bytes (an integer power of two) required for
|
||||
// any instance of the given type, which is either complete type, an array type,
|
||||
// or a reference type.
|
||||
// Use like:
|
||||
// size_t alignment = V8_ALIGNOF(double);
|
||||
#if V8_HAS_CXX11_ALIGNOF
|
||||
# define V8_ALIGNOF(type) alignof(type)
|
||||
#elif V8_HAS___ALIGNOF
|
||||
# define V8_ALIGNOF(type) __alignof(type)
|
||||
#elif V8_HAS___ALIGNOF__
|
||||
# define V8_ALIGNOF(type) __alignof__(type)
|
||||
#else
|
||||
// Note that alignment of a type within a struct can be less than the
|
||||
// alignment of the type stand-alone (because of ancient ABIs), so this
|
||||
// should only be used as a last resort.
|
||||
namespace v8 { template <typename T> class AlignOfHelper { char c; T t; }; }
|
||||
# define V8_ALIGNOF(type) (sizeof(::v8::AlignOfHelper<type>) - sizeof(type))
|
||||
#endif
|
||||
|
||||
// Annotate a function indicating the caller must examine the return value.
|
||||
// Use like:
|
||||
// int foo() WARN_UNUSED_RESULT;
|
||||
#if V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT
|
||||
#define V8_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define V8_WARN_UNUSED_RESULT /* NOT SUPPORTED */
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // V8CONFIG_H_
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue