diff --git a/android/arm64-v8a/include/v8/libplatform/libplatform-export.h b/android/arm64-v8a/include/v8/libplatform/libplatform-export.h new file mode 100644 index 00000000..15618434 --- /dev/null +++ b/android/arm64-v8a/include/v8/libplatform/libplatform-export.h @@ -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_ diff --git a/android/arm64-v8a/include/v8/libplatform/libplatform.h b/android/arm64-v8a/include/v8/libplatform/libplatform.h new file mode 100644 index 00000000..e9450456 --- /dev/null +++ b/android/arm64-v8a/include/v8/libplatform/libplatform.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_ diff --git a/android/arm64-v8a/include/v8/libplatform/v8-tracing.h b/android/arm64-v8a/include/v8/libplatform/v8-tracing.h new file mode 100644 index 00000000..902f8ea9 --- /dev/null +++ b/android/arm64-v8a/include/v8/libplatform/v8-tracing.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 +#include +#include +#include + +#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* 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* 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* 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 + 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 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* 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 trace_buffer_; + std::unique_ptr trace_config_; + std::unique_ptr mutex_; + std::unordered_set 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_ diff --git a/android/arm64-v8a/include/v8/v8-debug.h b/android/arm64-v8a/include/v8/v8-debug.h new file mode 100644 index 00000000..54c0f216 --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-debug.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 GetExecutionState() const = 0; + virtual Local GetEventData() const = 0; + + /** + * Get the debugger protocol JSON. + */ + virtual Local 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 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 GetExecutionState() const = 0; + virtual Local 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 GetEventContext() const = 0; + + /** + * Client data passed with the corresponding callback when it was + * registered. + */ + virtual Local 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 data = Local())); + + // 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 Call( + Local context, v8::Local fun, + Local data = Local())); + + // 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 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 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: [, ,...,, ]. Result array + * will be allocated in the current context. + */ + V8_DEPRECATED("No longer supported", + static MaybeLocal GetInternalProperties( + Isolate* isolate, Local 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_ diff --git a/android/arm64-v8a/include/v8/v8-inspector-protocol.h b/android/arm64-v8a/include/v8/v8-inspector-protocol.h new file mode 100644 index 00000000..612a2ebc --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-inspector-protocol.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_ diff --git a/android/arm64-v8a/include/v8/v8-inspector.h b/android/arm64-v8a/include/v8/v8-inspector.h new file mode 100644 index 00000000..43bf3b4f --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-inspector.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 +#include + +#include + +#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 create(const StringView&); +}; + +class V8_EXPORT V8ContextInfo { + public: + V8ContextInfo(v8::Local context, int contextGroupId, + const StringView& humanReadableName) + : context(context), + contextGroupId(contextGroupId), + humanReadableName(humanReadableName), + hasMemoryOnConsole(false) {} + + v8::Local 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 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 + buildInspectorObject() const = 0; + virtual std::unique_ptr toString() const = 0; + + // Safe to pass between threads, drops async chain. + virtual std::unique_ptr 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 get(v8::Local) = 0; + virtual ~Inspectable() {} + }; + virtual void addInspectedObject(std::unique_ptr) = 0; + + // Dispatching protocol messages. + static bool canDispatchMethod(const StringView& method); + virtual void dispatchProtocolMessage(const StringView& message) = 0; + virtual std::unique_ptr stateJSON() = 0; + virtual std::vector> + 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> + searchInTextByLines(const StringView& text, const StringView& query, + bool caseSensitive, bool isRegex) = 0; + + // Remote objects. + virtual std::unique_ptr wrapObject( + v8::Local, v8::Local, + const StringView& groupName) = 0; + virtual bool unwrapObject(std::unique_ptr* error, + const StringView& objectId, v8::Local*, + v8::Local*, + std::unique_ptr* 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 valueSubtype(v8::Local) { + return nullptr; + } + virtual bool formatAccessorsAsProperties(v8::Local) { + return false; + } + virtual bool isInspectableHeapObject(v8::Local) { return true; } + + virtual v8::Local ensureDefaultContextInGroup( + int contextGroupId) { + return v8::Local(); + } + virtual void beginEnsureAllContextsInGroup(int contextGroupId) {} + virtual void endEnsureAllContextsInGroup(int contextGroupId) {} + + virtual void installAdditionalCommandLineAPI(v8::Local, + v8::Local) {} + virtual void consoleAPIMessage(int contextGroupId, + v8::Isolate::MessageErrorLevel level, + const StringView& message, + const StringView& url, unsigned lineNumber, + unsigned columnNumber, V8StackTrace*) {} + virtual v8::MaybeLocal memoryInfo(v8::Isolate*, + v8::Local) { + return v8::MaybeLocal(); + } + + 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 create(v8::Isolate*, V8InspectorClient*); + virtual ~V8Inspector() {} + + // Contexts instrumentation. + virtual void contextCreated(const V8ContextInfo&) = 0; + virtual void contextDestroyed(v8::Local) = 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, const StringView& message, + v8::Local exception, const StringView& detailedMessage, + const StringView& url, unsigned lineNumber, unsigned columnNumber, + std::unique_ptr, int scriptId) = 0; + virtual void exceptionRevoked(v8::Local, unsigned exceptionId, + const StringView& message) = 0; + + // Connection. + class V8_EXPORT Channel { + public: + virtual ~Channel() {} + virtual void sendResponse(int callId, + std::unique_ptr message) = 0; + virtual void sendNotification(std::unique_ptr message) = 0; + virtual void flushProtocolNotifications() = 0; + }; + virtual std::unique_ptr connect( + int contextGroupId, Channel*, const StringView& state) = 0; + + // API methods. + virtual std::unique_ptr createStackTrace( + v8::Local) = 0; + virtual std::unique_ptr captureStackTrace(bool fullStack) = 0; +}; + +} // namespace v8_inspector + +#endif // V8_V8_INSPECTOR_H_ diff --git a/android/arm64-v8a/include/v8/v8-platform.h b/android/arm64-v8a/include/v8/v8-platform.h new file mode 100644 index 00000000..8f6d8042 --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-platform.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 +#include +#include +#include + +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* 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_ diff --git a/android/arm64-v8a/include/v8/v8-profiler.h b/android/arm64-v8a/include/v8/v8-profiler.h new file mode 100644 index 00000000..b60d137f --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-profiler.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 +#include +#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; +#endif + +namespace v8 { + +struct V8_EXPORT CpuProfileDeoptInfo { + /** A pointer to a static string owned by v8. */ + const char* deopt_reason; + std::vector stack; +}; + +} // namespace v8 + +#ifdef V8_OS_WIN +template class V8_EXPORT std::vector; +#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 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 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 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& 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 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 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 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 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 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 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 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 children; + + /** + * List of self allocations done by this node in the call-graph. + */ + std::vector 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*> + RetainerChildren; + typedef std::vector> + RetainerGroups; + typedef std::vector*, + const v8::PersistentBase*>> + 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 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); + + /** + * Returns heap object with given SnapshotObjectId if the object is alive, + * otherwise empty handle is returned. + */ + Local 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) = 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_ diff --git a/android/arm64-v8a/include/v8/v8-testing.h b/android/arm64-v8a/include/v8/v8-testing.h new file mode 100644 index 00000000..f67bf253 --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-testing.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_ diff --git a/android/arm64-v8a/include/v8/v8-util.h b/android/arm64-v8a/include/v8/v8-util.h new file mode 100644 index 00000000..a04a5e84 --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-util.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 +#include +#include + +/** + * 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 +class StdMapTraits { + public: + // STL map & related: + typedef std::map 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 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 +class DefaultPersistentValueMapTraits : public StdMapTraits { + public: + // Weak callback & friends: + static const PersistentContainerCallbackType kCallbackType = kNotWeak; + typedef PersistentValueMap > + MapType; + typedef void WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter( + MapType* map, const K& key, Local value) { + return NULL; + } + static MapType* MapFromWeakCallbackInfo( + const WeakCallbackInfo& data) { + return NULL; + } + static K KeyFromWeakCallbackInfo( + const WeakCallbackInfo& data) { + return K(); + } + static void DisposeCallbackData(WeakCallbackDataType* data) { } + static void Dispose(Isolate* isolate, Global value, K key) {} +}; + + +template +class DefaultGlobalMapTraits : public StdMapTraits { + private: + template + struct RemovePointer; + + public: + // Weak callback & friends: + static const PersistentContainerCallbackType kCallbackType = kNotWeak; + typedef GlobalValueMap > MapType; + typedef void WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key, + Local value) { + return nullptr; + } + static MapType* MapFromWeakCallbackInfo( + const WeakCallbackInfo& data) { + return nullptr; + } + static K KeyFromWeakCallbackInfo( + const WeakCallbackInfo& data) { + return K(); + } + static void DisposeCallbackData(WeakCallbackDataType* data) {} + static void OnWeakCallback( + const WeakCallbackInfo& data) {} + static void Dispose(Isolate* isolate, Global value, K key) {} + // This is a second pass callback, so SetSecondPassCallback cannot be called. + static void DisposeWeak(const WeakCallbackInfo& data) {} + + private: + template + struct RemovePointer { + 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 +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 Get(const K& key) { + return Local::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 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& parent) { + GetIsolate()->SetReference( + reinterpret_cast(parent.val_), + reinterpret_cast(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(FromVal(Traits::Get(&impl_, key))), + reinterpret_cast(GetIsolate())); + } + + /** + * Return value for key and remove it from the map. + */ + Global 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 NewLocal(Isolate* isolate) const { + return Local::New(isolate, FromVal(value_)); + } + bool IsEmpty() const { + return value_ == kPersistentContainerNotFound; + } + template + bool SetReturnValue(ReturnValue returnValue) { + return SetReturnValueFromVal(&returnValue, value_); + } + void Reset() { + value_ = kPersistentContainerNotFound; + } + void operator=(const PersistentValueReference& other) { + value_ = other.value_; + } + + private: + friend class PersistentValueMapBase; + friend class PersistentValueMap; + friend class GlobalValueMap; + + 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); + } + + static PersistentContainerValue ClearAndLeak(Global* persistent) { + V* v = persistent->val_; + persistent->val_ = 0; + return reinterpret_cast(v); + } + + static PersistentContainerValue Leak(Global* persistent) { + return reinterpret_cast(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 Release(PersistentContainerValue v) { + Global p; + p.val_ = FromVal(v); + if (Traits::kCallbackType != kNotWeak && p.IsWeak()) { + Traits::DisposeCallbackData( + p.template ClearWeak()); + } + return p.Pass(); + } + + void RemoveWeak(const K& key) { + Global p; + p.val_ = FromVal(Traits::Remove(&impl_, key)); + p.Reset(); + } + + private: + PersistentValueMapBase(PersistentValueMapBase&); + void operator=(PersistentValueMapBase&); + + static bool SetReturnValueFromVal(ReturnValue* returnValue, + PersistentContainerValue value) { + bool hasValue = value != kPersistentContainerNotFound; + if (hasValue) { + returnValue->SetInternal( + *reinterpret_cast(FromVal(value))); + } + return hasValue; + } + + Isolate* isolate_; + typename Traits::Impl impl_; +}; + + +template +class PersistentValueMap : public PersistentValueMapBase { + public: + explicit PersistentValueMap(Isolate* isolate) + : PersistentValueMapBase(isolate) {} + + typedef + typename PersistentValueMapBase::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 Set(const K& key, Local value) { + Global persistent(this->isolate(), value); + return SetUnique(key, &persistent); + } + + /** + * Put value into map, like Set(const K&, Local). + */ + Global Set(const K& key, Global value) { + return SetUnique(key, &value); + } + + /** + * Put the value into the map, and set the 'weak' callback when demanded + * by the Traits class. + */ + Global SetUnique(const K& key, Global* persistent) { + if (Traits::kCallbackType != kNotWeak) { + Local value(Local::New(this->isolate(), *persistent)); + persistent->template SetWeak( + 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 Set(const K& key, Global value, + PersistentValueReference* reference) { + *reference = this->Leak(&value); + return SetUnique(key, &value); + } + + private: + static void WeakCallback( + const WeakCallbackInfo& data) { + if (Traits::kCallbackType != kNotWeak) { + PersistentValueMap* persistentValueMap = + Traits::MapFromWeakCallbackInfo(data); + K key = Traits::KeyFromWeakCallbackInfo(data); + Traits::Dispose(data.GetIsolate(), + persistentValueMap->Remove(key).Pass(), key); + Traits::DisposeCallbackData(data.GetParameter()); + } + } +}; + + +template +class GlobalValueMap : public PersistentValueMapBase { + public: + explicit GlobalValueMap(Isolate* isolate) + : PersistentValueMapBase(isolate) {} + + typedef + typename PersistentValueMapBase::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 Set(const K& key, Local value) { + Global persistent(this->isolate(), value); + return SetUnique(key, &persistent); + } + + /** + * Put value into map, like Set(const K&, Local). + */ + Global Set(const K& key, Global value) { + return SetUnique(key, &value); + } + + /** + * Put the value into the map, and set the 'weak' callback when demanded + * by the Traits class. + */ + Global SetUnique(const K& key, Global* persistent) { + if (Traits::kCallbackType != kNotWeak) { + WeakCallbackType callback_type = + Traits::kCallbackType == kWeakWithInternalFields + ? WeakCallbackType::kInternalFields + : WeakCallbackType::kParameter; + Local value(Local::New(this->isolate(), *persistent)); + persistent->template SetWeak( + 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 Set(const K& key, Global value, + PersistentValueReference* reference) { + *reference = this->Leak(&value); + return SetUnique(key, &value); + } + + private: + static void OnWeakCallback( + const WeakCallbackInfo& 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& 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 > +class StdPersistentValueMap : public PersistentValueMap { + public: + explicit StdPersistentValueMap(Isolate* isolate) + : PersistentValueMap(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 > +class StdGlobalValueMap : public GlobalValueMap { + public: + explicit StdGlobalValueMap(Isolate* isolate) + : GlobalValueMap(isolate) {} +}; + + +class DefaultPersistentValueVectorTraits { + public: + typedef std::vector 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 +class PersistentValueVector { + public: + explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { } + + ~PersistentValueVector() { + Clear(); + } + + /** + * Append a value to the vector. + */ + void Append(Local value) { + Global persistent(isolate_, value); + Traits::Append(&impl_, ClearAndLeak(&persistent)); + } + + /** + * Append a persistent's value to the vector. + */ + void Append(Global 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 Get(size_t index) const { + return Local::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 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* persistent) { + V* v = persistent->val_; + persistent->val_ = 0; + return reinterpret_cast(v); + } + + static V* FromVal(PersistentContainerValue v) { + return reinterpret_cast(v); + } + + Isolate* isolate_; + typename Traits::Impl impl_; +}; + +} // namespace v8 + +#endif // V8_UTIL_H diff --git a/android/arm64-v8a/include/v8/v8-value-serializer-version.h b/android/arm64-v8a/include/v8/v8-value-serializer-version.h new file mode 100644 index 00000000..c72911c6 --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-value-serializer-version.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 + +namespace v8 { + +constexpr uint32_t CurrentValueSerializerFormatVersion() { return 13; } + +} // namespace v8 + +#endif // INCLUDE_V8_VALUE_SERIALIZER_VERSION_H_ diff --git a/android/arm64-v8a/include/v8/v8-version-string.h b/android/arm64-v8a/include/v8/v8-version-string.h new file mode 100644 index 00000000..075282de --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-version-string.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_ diff --git a/android/arm64-v8a/include/v8/v8-version.h b/android/arm64-v8a/include/v8/v8-version.h new file mode 100644 index 00000000..0889459c --- /dev/null +++ b/android/arm64-v8a/include/v8/v8-version.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_ diff --git a/android/arm64-v8a/include/v8/v8.h b/android/arm64-v8a/include/v8/v8.h new file mode 100644 index 00000000..da3cdfdc --- /dev/null +++ b/android/arm64-v8a/include/v8/v8.h @@ -0,0 +1,10155 @@ +// Copyright 2012 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. + +/** \mainpage V8 API Reference Guide + * + * V8 is Google's open source JavaScript engine. + * + * This set of documents provides reference material generated from the + * V8 header file, include/v8.h. + * + * For other documentation see http://code.google.com/apis/v8/ + */ + +#ifndef INCLUDE_V8_H_ +#define INCLUDE_V8_H_ + +#include +#include +#include +#include +#include +#include + +#include "v8-version.h" // NOLINT(build/include) +#include "v8config.h" // NOLINT(build/include) + +// We reserve the V8_* prefix for macros defined in V8 public API and +// assume there are no name conflicts with the embedder's code. + +#ifdef V8_OS_WIN + +// Setup for Windows DLL export/import. When building the V8 DLL the +// BUILDING_V8_SHARED needs to be defined. When building a program which uses +// the V8 DLL USING_V8_SHARED needs to be defined. When either building the V8 +// static library or building a program which uses the V8 static library neither +// BUILDING_V8_SHARED nor USING_V8_SHARED should be defined. +#ifdef BUILDING_V8_SHARED +# define V8_EXPORT __declspec(dllexport) +#elif USING_V8_SHARED +# define V8_EXPORT __declspec(dllimport) +#else +# define V8_EXPORT +#endif // BUILDING_V8_SHARED + +#else // V8_OS_WIN + +// Setup for Linux shared library export. +#if V8_HAS_ATTRIBUTE_VISIBILITY +# ifdef BUILDING_V8_SHARED +# define V8_EXPORT __attribute__ ((visibility("default"))) +# else +# define V8_EXPORT +# endif +#else +# define V8_EXPORT +#endif + +#endif // V8_OS_WIN + +/** + * The v8 JavaScript engine. + */ +namespace v8 { + +class AccessorSignature; +class Array; +class ArrayBuffer; +class Boolean; +class BooleanObject; +class Context; +class CpuProfiler; +class Data; +class Date; +class External; +class Function; +class FunctionTemplate; +class HeapProfiler; +class ImplementationUtilities; +class Int32; +class Integer; +class Isolate; +template +class Maybe; +class Name; +class Number; +class NumberObject; +class Object; +class ObjectOperationDescriptor; +class ObjectTemplate; +class Platform; +class Primitive; +class Promise; +class PropertyDescriptor; +class Proxy; +class RawOperationDescriptor; +class Script; +class SharedArrayBuffer; +class Signature; +class StartupData; +class StackFrame; +class StackTrace; +class String; +class StringObject; +class Symbol; +class SymbolObject; +class Private; +class Uint32; +class Utils; +class Value; +class WasmCompiledModule; +template class Local; +template +class MaybeLocal; +template class Eternal; +template class NonCopyablePersistentTraits; +template class PersistentBase; +template > +class Persistent; +template +class Global; +template class PersistentValueMap; +template +class PersistentValueMapBase; +template +class GlobalValueMap; +template class PersistentValueVector; +template class WeakCallbackObject; +class FunctionTemplate; +class ObjectTemplate; +template class FunctionCallbackInfo; +template class PropertyCallbackInfo; +class StackTrace; +class StackFrame; +class Isolate; +class CallHandlerHelper; +class EscapableHandleScope; +template class ReturnValue; + +namespace internal { +class Arguments; +class Heap; +class HeapObject; +class Isolate; +class Object; +struct StreamedSource; +template class CustomArguments; +class PropertyCallbackArguments; +class FunctionCallbackArguments; +class GlobalHandles; +} // namespace internal + +namespace debug { +class ConsoleCallArguments; +} // namespace debug + +// --- Handles --- + +#define TYPE_CHECK(T, S) \ + while (false) { \ + *(static_cast(0)) = static_cast(0); \ + } + +/** + * An object reference managed by the v8 garbage collector. + * + * All objects returned from v8 have to be tracked by the garbage + * collector so that it knows that the objects are still alive. Also, + * because the garbage collector may move objects, it is unsafe to + * point directly to an object. Instead, all objects are stored in + * handles which are known by the garbage collector and updated + * whenever an object moves. Handles should always be passed by value + * (except in cases like out-parameters) and they should never be + * allocated on the heap. + * + * There are two types of handles: local and persistent handles. + * + * Local handles are light-weight and transient and typically used in + * local operations. They are managed by HandleScopes. That means that a + * HandleScope must exist on the stack when they are created and that they are + * only valid inside of the HandleScope active during their creation. + * For passing a local handle to an outer HandleScope, an EscapableHandleScope + * and its Escape() method must be used. + * + * Persistent handles can be used when storing objects across several + * independent operations and have to be explicitly deallocated when they're no + * longer used. + * + * It is safe to extract the object stored in the handle by + * dereferencing the handle (for instance, to extract the Object* from + * a Local); the value will still be governed by a handle + * behind the scenes and the same rules apply to these values as to + * their handles. + */ +template +class Local { + public: + V8_INLINE Local() : val_(0) {} + template + V8_INLINE Local(Local that) + : val_(reinterpret_cast(*that)) { + /** + * This check fails when trying to convert between incompatible + * handles. For example, converting from a Local to a + * Local. + */ + TYPE_CHECK(T, S); + } + + /** + * Returns true if the handle is empty. + */ + V8_INLINE bool IsEmpty() const { return val_ == 0; } + + /** + * Sets the handle to be empty. IsEmpty() will then return true. + */ + V8_INLINE void Clear() { val_ = 0; } + + V8_INLINE T* operator->() const { return val_; } + + V8_INLINE T* operator*() const { return val_; } + + /** + * Checks whether two handles are the same. + * Returns true if both are empty, or if the objects + * to which they refer are identical. + * The handles' references are not checked. + */ + template + V8_INLINE bool operator==(const Local& that) const { + internal::Object** a = reinterpret_cast(this->val_); + internal::Object** b = reinterpret_cast(that.val_); + if (a == 0) return b == 0; + if (b == 0) return false; + return *a == *b; + } + + template V8_INLINE bool operator==( + const PersistentBase& that) const { + internal::Object** a = reinterpret_cast(this->val_); + internal::Object** b = reinterpret_cast(that.val_); + if (a == 0) return b == 0; + if (b == 0) return false; + return *a == *b; + } + + /** + * Checks whether two handles are different. + * Returns true if only one of the handles is empty, or if + * the objects to which they refer are different. + * The handles' references are not checked. + */ + template + V8_INLINE bool operator!=(const Local& that) const { + return !operator==(that); + } + + template V8_INLINE bool operator!=( + const Persistent& that) const { + return !operator==(that); + } + + /** + * Cast a handle to a subclass, e.g. Local to Local. + * This is only valid if the handle actually refers to a value of the + * target type. + */ + template V8_INLINE static Local Cast(Local that) { +#ifdef V8_ENABLE_CHECKS + // If we're going to perform the type check then we have to check + // that the handle isn't empty before doing the checked cast. + if (that.IsEmpty()) return Local(); +#endif + return Local(T::Cast(*that)); + } + + /** + * Calling this is equivalent to Local::Cast(). + * In particular, this is only valid if the handle actually refers to a value + * of the target type. + */ + template + V8_INLINE Local As() const { + return Local::Cast(*this); + } + + /** + * Create a local handle for the content of another handle. + * The referee is kept alive by the local handle even when + * the original handle is destroyed/disposed. + */ + V8_INLINE static Local New(Isolate* isolate, Local that); + V8_INLINE static Local New(Isolate* isolate, + const PersistentBase& that); + + private: + friend class Utils; + template friend class Eternal; + template friend class PersistentBase; + template friend class Persistent; + template friend class Local; + template + friend class MaybeLocal; + template friend class FunctionCallbackInfo; + template friend class PropertyCallbackInfo; + friend class String; + friend class Object; + friend class Context; + friend class Private; + template friend class internal::CustomArguments; + friend Local Undefined(Isolate* isolate); + friend Local Null(Isolate* isolate); + friend Local True(Isolate* isolate); + friend Local False(Isolate* isolate); + friend class HandleScope; + friend class EscapableHandleScope; + template + friend class PersistentValueMapBase; + template friend class PersistentValueVector; + template + friend class ReturnValue; + + explicit V8_INLINE Local(T* that) : val_(that) {} + V8_INLINE static Local New(Isolate* isolate, T* that); + T* val_; +}; + + +#if !defined(V8_IMMINENT_DEPRECATION_WARNINGS) +// Handle is an alias for Local for historical reasons. +template +using Handle = Local; +#endif + + +/** + * A MaybeLocal<> is a wrapper around Local<> that enforces a check whether + * the Local<> is empty before it can be used. + * + * If an API method returns a MaybeLocal<>, the API method can potentially fail + * either because an exception is thrown, or because an exception is pending, + * e.g. because a previous API call threw an exception that hasn't been caught + * yet, or because a TerminateExecution exception was thrown. In that case, an + * empty MaybeLocal is returned. + */ +template +class MaybeLocal { + public: + V8_INLINE MaybeLocal() : val_(nullptr) {} + template + V8_INLINE MaybeLocal(Local that) + : val_(reinterpret_cast(*that)) { + TYPE_CHECK(T, S); + } + + V8_INLINE bool IsEmpty() const { return val_ == nullptr; } + + /** + * Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty, + * |false| is returned and |out| is left untouched. + */ + template + V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local* out) const { + out->val_ = IsEmpty() ? nullptr : this->val_; + return !IsEmpty(); + } + + /** + * Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty, + * V8 will crash the process. + */ + V8_INLINE Local ToLocalChecked(); + + /** + * Converts this MaybeLocal<> to a Local<>, using a default value if this + * MaybeLocal<> is empty. + */ + template + V8_INLINE Local FromMaybe(Local default_value) const { + return IsEmpty() ? default_value : Local(val_); + } + + private: + T* val_; +}; + +/** + * Eternal handles are set-once handles that live for the lifetime of the + * isolate. + */ +template class Eternal { + public: + V8_INLINE Eternal() : val_(nullptr) {} + template + V8_INLINE Eternal(Isolate* isolate, Local handle) : val_(nullptr) { + Set(isolate, handle); + } + // Can only be safely called if already set. + V8_INLINE Local Get(Isolate* isolate) const; + V8_INLINE bool IsEmpty() const { return val_ == nullptr; } + template V8_INLINE void Set(Isolate* isolate, Local handle); + + private: + T* val_; +}; + + +static const int kInternalFieldsInWeakCallback = 2; +static const int kEmbedderFieldsInWeakCallback = 2; + +template +class WeakCallbackInfo { + public: + typedef void (*Callback)(const WeakCallbackInfo& data); + + WeakCallbackInfo(Isolate* isolate, T* parameter, + void* embedder_fields[kEmbedderFieldsInWeakCallback], + Callback* callback) + : isolate_(isolate), parameter_(parameter), callback_(callback) { + for (int i = 0; i < kEmbedderFieldsInWeakCallback; ++i) { + embedder_fields_[i] = embedder_fields[i]; + } + } + + V8_INLINE Isolate* GetIsolate() const { return isolate_; } + V8_INLINE T* GetParameter() const { return parameter_; } + V8_INLINE void* GetInternalField(int index) const; + + V8_INLINE V8_DEPRECATED("use indexed version", + void* GetInternalField1() const) { + return embedder_fields_[0]; + } + V8_INLINE V8_DEPRECATED("use indexed version", + void* GetInternalField2() const) { + return embedder_fields_[1]; + } + + V8_DEPRECATED("Not realiable once SetSecondPassCallback() was used.", + bool IsFirstPass() const) { + return callback_ != nullptr; + } + + // When first called, the embedder MUST Reset() the Global which triggered the + // callback. The Global itself is unusable for anything else. No v8 other api + // calls may be called in the first callback. Should additional work be + // required, the embedder must set a second pass callback, which will be + // called after all the initial callbacks are processed. + // Calling SetSecondPassCallback on the second pass will immediately crash. + void SetSecondPassCallback(Callback callback) const { *callback_ = callback; } + + private: + Isolate* isolate_; + T* parameter_; + Callback* callback_; + void* embedder_fields_[kEmbedderFieldsInWeakCallback]; +}; + + +// kParameter will pass a void* parameter back to the callback, kInternalFields +// will pass the first two internal fields back to the callback, kFinalizer +// will pass a void* parameter back, but is invoked before the object is +// actually collected, so it can be resurrected. In the last case, it is not +// possible to request a second pass callback. +enum class WeakCallbackType { kParameter, kInternalFields, kFinalizer }; + +/** + * An object reference that is independent of any handle scope. Where + * a Local handle only lives as long as the HandleScope in which it was + * allocated, a PersistentBase handle remains valid until it is explicitly + * disposed using Reset(). + * + * A persistent handle contains a reference to a storage cell within + * the V8 engine which holds an object value and which is updated by + * the garbage collector whenever the object is moved. A new storage + * cell can be created using the constructor or PersistentBase::Reset and + * existing handles can be disposed using PersistentBase::Reset. + * + */ +template class PersistentBase { + public: + /** + * If non-empty, destroy the underlying storage cell + * IsEmpty() will return true after this call. + */ + V8_INLINE void Reset(); + /** + * If non-empty, destroy the underlying storage cell + * and create a new one with the contents of other if other is non empty + */ + template + V8_INLINE void Reset(Isolate* isolate, const Local& other); + + /** + * If non-empty, destroy the underlying storage cell + * and create a new one with the contents of other if other is non empty + */ + template + V8_INLINE void Reset(Isolate* isolate, const PersistentBase& other); + + V8_INLINE bool IsEmpty() const { return val_ == NULL; } + V8_INLINE void Empty() { val_ = 0; } + + V8_INLINE Local Get(Isolate* isolate) const { + return Local::New(isolate, *this); + } + + template + V8_INLINE bool operator==(const PersistentBase& that) const { + internal::Object** a = reinterpret_cast(this->val_); + internal::Object** b = reinterpret_cast(that.val_); + if (a == NULL) return b == NULL; + if (b == NULL) return false; + return *a == *b; + } + + template + V8_INLINE bool operator==(const Local& that) const { + internal::Object** a = reinterpret_cast(this->val_); + internal::Object** b = reinterpret_cast(that.val_); + if (a == NULL) return b == NULL; + if (b == NULL) return false; + return *a == *b; + } + + template + V8_INLINE bool operator!=(const PersistentBase& that) const { + return !operator==(that); + } + + template + V8_INLINE bool operator!=(const Local& that) const { + return !operator==(that); + } + + /** + * Install a finalization callback on this object. + * NOTE: There is no guarantee as to *when* or even *if* the callback is + * invoked. The invocation is performed solely on a best effort basis. + * As always, GC-based finalization should *not* be relied upon for any + * critical form of resource management! + */ + template + V8_INLINE void SetWeak(P* parameter, + typename WeakCallbackInfo

::Callback callback, + WeakCallbackType type); + + /** + * Turns this handle into a weak phantom handle without finalization callback. + * The handle will be reset automatically when the garbage collector detects + * that the object is no longer reachable. + * A related function Isolate::NumberOfPhantomHandleResetsSinceLastCall + * returns how many phantom handles were reset by the garbage collector. + */ + V8_INLINE void SetWeak(); + + template + V8_INLINE P* ClearWeak(); + + // TODO(dcarney): remove this. + V8_INLINE void ClearWeak() { ClearWeak(); } + + /** + * Allows the embedder to tell the v8 garbage collector that a certain object + * is alive. Only allowed when the embedder is asked to trace its heap by + * EmbedderHeapTracer. + */ + V8_INLINE void RegisterExternalReference(Isolate* isolate) const; + + /** + * Marks the reference to this object independent. Garbage collector is free + * to ignore any object groups containing this object. Weak callback for an + * independent handle should not assume that it will be preceded by a global + * GC prologue callback or followed by a global GC epilogue callback. + */ + V8_INLINE void MarkIndependent(); + + /** + * Marks the reference to this object as active. The scavenge garbage + * collection should not reclaim the objects marked as active. + * This bit is cleared after the each garbage collection pass. + */ + V8_INLINE void MarkActive(); + + V8_INLINE bool IsIndependent() const; + + /** Checks if the handle holds the only reference to an object. */ + V8_INLINE bool IsNearDeath() const; + + /** Returns true if the handle's reference is weak. */ + V8_INLINE bool IsWeak() const; + + /** + * Assigns a wrapper class ID to the handle. See RetainedObjectInfo interface + * description in v8-profiler.h for details. + */ + V8_INLINE void SetWrapperClassId(uint16_t class_id); + + /** + * Returns the class ID previously assigned to this handle or 0 if no class ID + * was previously assigned. + */ + V8_INLINE uint16_t WrapperClassId() const; + + PersistentBase(const PersistentBase& other) = delete; // NOLINT + void operator=(const PersistentBase&) = delete; + + private: + friend class Isolate; + friend class Utils; + template friend class Local; + template friend class Persistent; + template + friend class Global; + template friend class PersistentBase; + template friend class ReturnValue; + template + friend class PersistentValueMapBase; + template friend class PersistentValueVector; + friend class Object; + + explicit V8_INLINE PersistentBase(T* val) : val_(val) {} + V8_INLINE static T* New(Isolate* isolate, T* that); + + T* val_; +}; + + +/** + * Default traits for Persistent. This class does not allow + * use of the copy constructor or assignment operator. + * At present kResetInDestructor is not set, but that will change in a future + * version. + */ +template +class NonCopyablePersistentTraits { + public: + typedef Persistent > NonCopyablePersistent; + static const bool kResetInDestructor = false; + template + V8_INLINE static void Copy(const Persistent& source, + NonCopyablePersistent* dest) { + Uncompilable(); + } + // TODO(dcarney): come up with a good compile error here. + template V8_INLINE static void Uncompilable() { + TYPE_CHECK(O, Primitive); + } +}; + + +/** + * Helper class traits to allow copying and assignment of Persistent. + * This will clone the contents of storage cell, but not any of the flags, etc. + */ +template +struct CopyablePersistentTraits { + typedef Persistent > CopyablePersistent; + static const bool kResetInDestructor = true; + template + static V8_INLINE void Copy(const Persistent& source, + CopyablePersistent* dest) { + // do nothing, just allow copy + } +}; + + +/** + * A PersistentBase which allows copy and assignment. + * + * Copy, assignment and destructor behavior is controlled by the traits + * class M. + * + * Note: Persistent class hierarchy is subject to future changes. + */ +template class Persistent : public PersistentBase { + public: + /** + * A Persistent with no storage cell. + */ + V8_INLINE Persistent() : PersistentBase(0) { } + /** + * Construct a Persistent from a Local. + * When the Local is non-empty, a new storage cell is created + * pointing to the same object, and no flags are set. + */ + template + V8_INLINE Persistent(Isolate* isolate, Local that) + : PersistentBase(PersistentBase::New(isolate, *that)) { + TYPE_CHECK(T, S); + } + /** + * Construct a Persistent from a Persistent. + * When the Persistent is non-empty, a new storage cell is created + * pointing to the same object, and no flags are set. + */ + template + V8_INLINE Persistent(Isolate* isolate, const Persistent& that) + : PersistentBase(PersistentBase::New(isolate, *that)) { + TYPE_CHECK(T, S); + } + /** + * The copy constructors and assignment operator create a Persistent + * exactly as the Persistent constructor, but the Copy function from the + * traits class is called, allowing the setting of flags based on the + * copied Persistent. + */ + V8_INLINE Persistent(const Persistent& that) : PersistentBase(0) { + Copy(that); + } + template + V8_INLINE Persistent(const Persistent& that) : PersistentBase(0) { + Copy(that); + } + V8_INLINE Persistent& operator=(const Persistent& that) { // NOLINT + Copy(that); + return *this; + } + template + V8_INLINE Persistent& operator=(const Persistent& that) { // NOLINT + Copy(that); + return *this; + } + /** + * The destructor will dispose the Persistent based on the + * kResetInDestructor flags in the traits class. Since not calling dispose + * can result in a memory leak, it is recommended to always set this flag. + */ + V8_INLINE ~Persistent() { + if (M::kResetInDestructor) this->Reset(); + } + + // TODO(dcarney): this is pretty useless, fix or remove + template + V8_INLINE static Persistent& Cast(const Persistent& that) { // NOLINT +#ifdef V8_ENABLE_CHECKS + // If we're going to perform the type check then we have to check + // that the handle isn't empty before doing the checked cast. + if (!that.IsEmpty()) T::Cast(*that); +#endif + return reinterpret_cast&>(const_cast&>(that)); + } + + // TODO(dcarney): this is pretty useless, fix or remove + template + V8_INLINE Persistent& As() const { // NOLINT + return Persistent::Cast(*this); + } + + private: + friend class Isolate; + friend class Utils; + template friend class Local; + template friend class Persistent; + template friend class ReturnValue; + + explicit V8_INLINE Persistent(T* that) : PersistentBase(that) {} + V8_INLINE T* operator*() const { return this->val_; } + template + V8_INLINE void Copy(const Persistent& that); +}; + + +/** + * A PersistentBase which has move semantics. + * + * Note: Persistent class hierarchy is subject to future changes. + */ +template +class Global : public PersistentBase { + public: + /** + * A Global with no storage cell. + */ + V8_INLINE Global() : PersistentBase(nullptr) {} + /** + * Construct a Global from a Local. + * When the Local is non-empty, a new storage cell is created + * pointing to the same object, and no flags are set. + */ + template + V8_INLINE Global(Isolate* isolate, Local that) + : PersistentBase(PersistentBase::New(isolate, *that)) { + TYPE_CHECK(T, S); + } + /** + * Construct a Global from a PersistentBase. + * When the Persistent is non-empty, a new storage cell is created + * pointing to the same object, and no flags are set. + */ + template + V8_INLINE Global(Isolate* isolate, const PersistentBase& that) + : PersistentBase(PersistentBase::New(isolate, that.val_)) { + TYPE_CHECK(T, S); + } + /** + * Move constructor. + */ + V8_INLINE Global(Global&& other) : PersistentBase(other.val_) { // NOLINT + other.val_ = nullptr; + } + V8_INLINE ~Global() { this->Reset(); } + /** + * Move via assignment. + */ + template + V8_INLINE Global& operator=(Global&& rhs) { // NOLINT + TYPE_CHECK(T, S); + if (this != &rhs) { + this->Reset(); + this->val_ = rhs.val_; + rhs.val_ = nullptr; + } + return *this; + } + /** + * Pass allows returning uniques from functions, etc. + */ + Global Pass() { return static_cast(*this); } // NOLINT + + /* + * For compatibility with Chromium's base::Bind (base::Passed). + */ + typedef void MoveOnlyTypeForCPP03; + + Global(const Global&) = delete; + void operator=(const Global&) = delete; + + private: + template + friend class ReturnValue; + V8_INLINE T* operator*() const { return this->val_; } +}; + + +// UniquePersistent is an alias for Global for historical reason. +template +using UniquePersistent = Global; + + + /** + * A stack-allocated class that governs a number of local handles. + * After a handle scope has been created, all local handles will be + * allocated within that handle scope until either the handle scope is + * deleted or another handle scope is created. If there is already a + * handle scope and a new one is created, all allocations will take + * place in the new handle scope until it is deleted. After that, + * new handles will again be allocated in the original handle scope. + * + * After the handle scope of a local handle has been deleted the + * garbage collector will no longer track the object stored in the + * handle and may deallocate it. The behavior of accessing a handle + * for which the handle scope has been deleted is undefined. + */ +class V8_EXPORT HandleScope { + public: + explicit HandleScope(Isolate* isolate); + + ~HandleScope(); + + /** + * Counts the number of allocated handles. + */ + static int NumberOfHandles(Isolate* isolate); + + V8_INLINE Isolate* GetIsolate() const { + return reinterpret_cast(isolate_); + } + + HandleScope(const HandleScope&) = delete; + void operator=(const HandleScope&) = delete; + void* operator new(size_t size); + void operator delete(void*, size_t); + + protected: + V8_INLINE HandleScope() {} + + void Initialize(Isolate* isolate); + + static internal::Object** CreateHandle(internal::Isolate* isolate, + internal::Object* value); + + private: + // Uses heap_object to obtain the current Isolate. + static internal::Object** CreateHandle(internal::HeapObject* heap_object, + internal::Object* value); + + internal::Isolate* isolate_; + internal::Object** prev_next_; + internal::Object** prev_limit_; + + // Local::New uses CreateHandle with an Isolate* parameter. + template friend class Local; + + // Object::GetInternalField and Context::GetEmbedderData use CreateHandle with + // a HeapObject* in their shortcuts. + friend class Object; + friend class Context; +}; + + +/** + * A HandleScope which first allocates a handle in the current scope + * which will be later filled with the escape value. + */ +class V8_EXPORT EscapableHandleScope : public HandleScope { + public: + explicit EscapableHandleScope(Isolate* isolate); + V8_INLINE ~EscapableHandleScope() {} + + /** + * Pushes the value into the previous scope and returns a handle to it. + * Cannot be called twice. + */ + template + V8_INLINE Local Escape(Local value) { + internal::Object** slot = + Escape(reinterpret_cast(*value)); + return Local(reinterpret_cast(slot)); + } + + EscapableHandleScope(const EscapableHandleScope&) = delete; + void operator=(const EscapableHandleScope&) = delete; + void* operator new(size_t size); + void operator delete(void*, size_t); + + private: + internal::Object** Escape(internal::Object** escape_value); + internal::Object** escape_slot_; +}; + +/** + * A SealHandleScope acts like a handle scope in which no handle allocations + * are allowed. It can be useful for debugging handle leaks. + * Handles can be allocated within inner normal HandleScopes. + */ +class V8_EXPORT SealHandleScope { + public: + SealHandleScope(Isolate* isolate); + ~SealHandleScope(); + + SealHandleScope(const SealHandleScope&) = delete; + void operator=(const SealHandleScope&) = delete; + void* operator new(size_t size); + void operator delete(void*, size_t); + + private: + internal::Isolate* const isolate_; + internal::Object** prev_limit_; + int prev_sealed_level_; +}; + + +// --- Special objects --- + + +/** + * The superclass of values and API object templates. + */ +class V8_EXPORT Data { + private: + Data(); +}; + + +/** + * The optional attributes of ScriptOrigin. + */ +class ScriptOriginOptions { + public: + V8_INLINE ScriptOriginOptions(bool is_shared_cross_origin = false, + bool is_opaque = false, bool is_wasm = false, + bool is_module = false) + : flags_((is_shared_cross_origin ? kIsSharedCrossOrigin : 0) | + (is_wasm ? kIsWasm : 0) | (is_opaque ? kIsOpaque : 0) | + (is_module ? kIsModule : 0)) {} + V8_INLINE ScriptOriginOptions(int flags) + : flags_(flags & + (kIsSharedCrossOrigin | kIsOpaque | kIsWasm | kIsModule)) {} + + bool IsSharedCrossOrigin() const { + return (flags_ & kIsSharedCrossOrigin) != 0; + } + bool IsOpaque() const { return (flags_ & kIsOpaque) != 0; } + bool IsWasm() const { return (flags_ & kIsWasm) != 0; } + bool IsModule() const { return (flags_ & kIsModule) != 0; } + + int Flags() const { return flags_; } + + private: + enum { + kIsSharedCrossOrigin = 1, + kIsOpaque = 1 << 1, + kIsWasm = 1 << 2, + kIsModule = 1 << 3 + }; + const int flags_; +}; + +/** + * The origin, within a file, of a script. + */ +class ScriptOrigin { + public: + V8_INLINE ScriptOrigin( + Local resource_name, + Local resource_line_offset = Local(), + Local resource_column_offset = Local(), + Local resource_is_shared_cross_origin = Local(), + Local script_id = Local(), + Local source_map_url = Local(), + Local resource_is_opaque = Local(), + Local is_wasm = Local(), + Local is_module = Local()); + + V8_INLINE Local ResourceName() const; + V8_INLINE Local ResourceLineOffset() const; + V8_INLINE Local ResourceColumnOffset() const; + /** + * Returns true for embedder's debugger scripts + */ + V8_INLINE Local ScriptID() const; + V8_INLINE Local SourceMapUrl() const; + V8_INLINE ScriptOriginOptions Options() const { return options_; } + + private: + Local resource_name_; + Local resource_line_offset_; + Local resource_column_offset_; + ScriptOriginOptions options_; + Local script_id_; + Local source_map_url_; +}; + + +/** + * A compiled JavaScript script, not yet tied to a Context. + */ +class V8_EXPORT UnboundScript { + public: + /** + * Binds the script to the currently entered context. + */ + Local