diff options
author | Ben Murdoch <benm@google.com> | 2014-11-26 15:28:44 +0000 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2014-12-04 14:47:29 +0000 |
commit | b8a8cc1952d61a2f3a2568848933943a543b5d3e (patch) | |
tree | 83e9846202f2a441db91efdd164d7d8478ba9897 /include | |
parent | b7a971bd8c35b5952b1f25fca56de6113506d3da (diff) | |
download | v8-b8a8cc1952d61a2f3a2568848933943a543b5d3e.tar.gz |
Upgrade to 3.29
Update V8 to 3.29.88.17 and update makefiles to support building on
all the relevant platforms.
Bug: 17370214
Change-Id: Ia3407c157fd8d72a93e23d8318ccaf6ecf77fa4e
Diffstat (limited to 'include')
-rw-r--r-- | include/libplatform/libplatform.h | 38 | ||||
-rw-r--r--[-rwxr-xr-x] | include/v8-debug.h | 206 | ||||
-rw-r--r-- | include/v8-platform.h | 62 | ||||
-rw-r--r-- | include/v8-preparser.h | 117 | ||||
-rw-r--r-- | include/v8-profiler.h | 464 | ||||
-rw-r--r-- | include/v8-testing.h | 62 | ||||
-rw-r--r-- | include/v8-util.h | 487 | ||||
-rw-r--r-- | include/v8.h | 5514 | ||||
-rw-r--r-- | include/v8config.h | 419 | ||||
-rw-r--r-- | include/v8stdint.h | 33 |
10 files changed, 5407 insertions, 1995 deletions
diff --git a/include/libplatform/libplatform.h b/include/libplatform/libplatform.h new file mode 100644 index 00000000..2125e974 --- /dev/null +++ b/include/libplatform/libplatform.h @@ -0,0 +1,38 @@ +// 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 "include/v8-platform.h" + +namespace v8 { +namespace platform { + +/** + * 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. + */ +v8::Platform* CreateDefaultPlatform(int thread_pool_size = 0); + + +/** + * 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. This call does + * not block if no task is pending. The |platform| has to be created using + * |CreateDefaultPlatform|. + */ +bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate); + + +} // namespace platform +} // namespace v8 + +#endif // V8_LIBPLATFORM_LIBPLATFORM_H_ diff --git a/include/v8-debug.h b/include/v8-debug.h index 9e85dc46..6abf4e09 100755..100644 --- a/include/v8-debug.h +++ b/include/v8-debug.h @@ -1,69 +1,12 @@ // Copyright 2008 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// 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" -#ifdef _WIN32 -typedef int int32_t; -typedef unsigned int uint32_t; -typedef unsigned short uint16_t; // NOLINT -typedef long long int64_t; // NOLINT - -// Setup for Windows DLL export/import. See v8.h in this directory for -// information on how to build/use V8 as a DLL. -#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED) -#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\ - build configuration to ensure that at most one of these is set -#endif - -#ifdef BUILDING_V8_SHARED -#define EXPORT __declspec(dllexport) -#elif USING_V8_SHARED -#define EXPORT __declspec(dllimport) -#else -#define EXPORT -#endif - -#else // _WIN32 - -// Setup for Linux shared library export. See v8.h in this directory for -// information on how to build/use V8 as shared library. -#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED) -#define EXPORT __attribute__ ((visibility("default"))) -#else // defined(__GNUC__) && (__GNUC__ >= 4) -#define EXPORT -#endif // defined(__GNUC__) && (__GNUC__ >= 4) - -#endif // _WIN32 - - /** * Debugger support for the V8 JavaScript engine. */ @@ -76,12 +19,14 @@ enum DebugEvent { NewFunction = 3, BeforeCompile = 4, AfterCompile = 5, - ScriptCollected = 6, - BreakForCommand = 7 + CompileError = 6, + PromiseEvent = 7, + AsyncTaskEvent = 8, + BreakForCommand = 9 }; -class EXPORT Debug { +class V8_EXPORT Debug { public: /** * A client object passed to the v8 debugger whose ownership will be taken by @@ -140,6 +85,8 @@ class EXPORT Debug { */ virtual ClientData* GetClientData() const = 0; + virtual Isolate* GetIsolate() const = 0; + virtual ~Message() {} }; @@ -184,21 +131,6 @@ class EXPORT Debug { virtual ~EventDetails() {} }; - - /** - * Debug event callback function. - * - * \param event the type of the debug event that triggered the callback - * (enum DebugEvent) - * \param exec_state execution state (JavaScript object) - * \param event_data event specific data (JavaScript object) - * \param data value passed by the user to SetDebugEventListener - */ - typedef void (*EventCallback)(DebugEvent event, - Handle<Object> exec_state, - Handle<Object> event_data, - Handle<Value> data); - /** * Debug event callback function. * @@ -207,100 +139,50 @@ class EXPORT Debug { * A EventCallback2 does not take possession of the event data, * and must not rely on the data persisting after the handler returns. */ - typedef void (*EventCallback2)(const EventDetails& event_details); - - /** - * Debug message callback function. - * - * \param message the debug message handler message object - * \param length length of the message - * \param client_data the data value passed when registering the message handler - - * A MessageHandler does not take possession of the message string, - * and must not rely on the data persisting after the handler returns. - * - * This message handler is deprecated. Use MessageHandler2 instead. - */ - typedef void (*MessageHandler)(const uint16_t* message, int length, - ClientData* client_data); + typedef void (*EventCallback)(const EventDetails& event_details); /** * Debug message callback function. * * \param message the debug message handler message object * - * A MessageHandler does not take possession of the message data, + * A MessageHandler2 does not take possession of the message data, * and must not rely on the data persisting after the handler returns. */ - typedef void (*MessageHandler2)(const Message& message); - - /** - * Debug host dispatch callback function. - */ - typedef void (*HostDispatchHandler)(); + typedef void (*MessageHandler)(const Message& message); /** * Callback function for the host to ensure debug messages are processed. */ typedef void (*DebugMessageDispatchHandler)(); - // Set a C debug event listener. static bool SetDebugEventListener(EventCallback that, Handle<Value> data = Handle<Value>()); - static bool SetDebugEventListener2(EventCallback2 that, - Handle<Value> data = Handle<Value>()); - - // Set a JavaScript debug event listener. - static bool SetDebugEventListener(v8::Handle<v8::Object> that, - Handle<Value> data = Handle<Value>()); // Schedule a debugger break to happen when JavaScript code is run - // in the given isolate. If no isolate is provided the default - // isolate is used. - static void DebugBreak(Isolate* isolate = NULL); + // in the given isolate. + static void DebugBreak(Isolate* isolate); // Remove scheduled debugger break in given isolate if it has not - // happened yet. If no isolate is provided the default isolate is - // used. - static void CancelDebugBreak(Isolate* isolate = NULL); + // happened yet. + static void CancelDebugBreak(Isolate* isolate); + + // Check if a debugger break is scheduled in the given isolate. + static bool CheckDebugBreak(Isolate* isolate); // Break execution of JavaScript in the given isolate (this method // can be invoked from a non-VM thread) for further client command // execution on a VM thread. Client data is then passed in - // EventDetails to EventCallback at the moment when the VM actually - // stops. If no isolate is provided the default isolate is used. - static void DebugBreakForCommand(ClientData* data = NULL, - Isolate* isolate = NULL); - - // Message based interface. The message protocol is JSON. NOTE the message - // handler thread is not supported any more parameter must be false. - static void SetMessageHandler(MessageHandler handler, - bool message_handler_thread = false); - static void SetMessageHandler2(MessageHandler2 handler); - - // If no isolate is provided the default isolate is - // used. - static void SendCommand(const uint16_t* command, int length, - ClientData* client_data = NULL, - Isolate* isolate = NULL); - - // Dispatch interface. - static void SetHostDispatchHandler(HostDispatchHandler handler, - int period = 100); + // EventDetails to EventCallback2 at the moment when the VM actually + // stops. + static void DebugBreakForCommand(Isolate* isolate, ClientData* data); - /** - * Register a callback function to be called when a debug message has been - * received and is ready to be processed. For the debug messages to be - * processed V8 needs to be entered, and in certain embedding scenarios this - * callback can be used to make sure V8 is entered for the debug message to - * be processed. Note that debug messages will only be processed if there is - * a V8 break. This can happen automatically by using the option - * --debugger-auto-break. - * \param provide_locker requires that V8 acquires v8::Locker for you before - * calling handler - */ - static void SetDebugMessageDispatchHandler( - DebugMessageDispatchHandler handler, bool provide_locker = false); + // Message based interface. The message protocol is JSON. + static void SetMessageHandler(MessageHandler handler); + + static void SendCommand(Isolate* isolate, + const uint16_t* command, int length, + ClientData* client_data = NULL); /** * Run a JavaScript function in the debugger. @@ -321,29 +203,13 @@ class EXPORT Debug { * \endcode */ static Local<Value> Call(v8::Handle<v8::Function> fun, - Handle<Value> data = Handle<Value>()); + Handle<Value> data = Handle<Value>()); /** * Returns a mirror object for the given object. */ static Local<Value> GetMirror(v8::Handle<v8::Value> obj); - /** - * Enable the V8 builtin debug agent. The debugger agent will listen on the - * supplied TCP/IP port for remote debugger connection. - * \param name the name of the embedding application - * \param port the TCP/IP port to listen on - * \param wait_for_connection whether V8 should pause on a first statement - * allowing remote debugger to connect before anything interesting happened - */ - static bool EnableAgent(const char* name, int port, - bool wait_for_connection = false); - - /** - * Disable the V8 builtin debug agent. The TCP/IP connection will be closed. - */ - static void DisableAgent(); - /** * Makes V8 process all pending debug messages. * @@ -354,7 +220,7 @@ class EXPORT Debug { * * Generally when message arrives V8 may be in one of 3 states: * 1. V8 is running script; V8 will automatically interrupt and process all - * pending messages (however auto_break flag should be enabled); + * pending messages; * 2. V8 is suspended on debug breakpoint; in this state V8 is dedicated * to reading and processing debug messages; * 3. V8 is not running at all or has called some long-working C++ function; @@ -362,10 +228,6 @@ class EXPORT Debug { * until V8 gets control again; however, embedding application may improve * this by manually calling this method. * - * It makes sense to call this method whenever a new debug message arrived and - * V8 is not already running. Method v8::Debug::SetDebugMessageDispatchHandler - * should help with the former condition. - * * Technically this method in many senses is equivalent to executing empty * script: * 1. It does nothing except for processing all pending debug messages. @@ -388,6 +250,14 @@ class EXPORT Debug { * to change. */ static Local<Context> GetDebugContext(); + + + /** + * 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. + */ + static void SetLiveEditEnabled(Isolate* isolate, bool enable); }; diff --git a/include/v8-platform.h b/include/v8-platform.h new file mode 100644 index 00000000..1f1679f0 --- /dev/null +++ b/include/v8-platform.h @@ -0,0 +1,62 @@ +// 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_ + +namespace v8 { + +class Isolate; + +/** + * A Task represents a unit of work. + */ +class Task { + public: + virtual ~Task() {} + + virtual void Run() = 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() {} + + /** + * 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; +}; + +} // namespace v8 + +#endif // V8_V8_PLATFORM_H_ diff --git a/include/v8-preparser.h b/include/v8-preparser.h deleted file mode 100644 index f11d05ef..00000000 --- a/include/v8-preparser.h +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2011 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef PREPARSER_H -#define PREPARSER_H - -#include "v8stdint.h" - -#ifdef _WIN32 - -// 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. -#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED) -#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\ - build configuration to ensure that at most one of these is set -#endif - -#ifdef BUILDING_V8_SHARED -#define V8EXPORT __declspec(dllexport) -#elif USING_V8_SHARED -#define V8EXPORT __declspec(dllimport) -#else -#define V8EXPORT -#endif // BUILDING_V8_SHARED - -#else // _WIN32 - -// Setup for Linux shared library export. There is no need to distinguish -// between building or using the V8 shared library, but we should not -// export symbols when we are building a static library. -#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED) -#define V8EXPORT __attribute__ ((visibility("default"))) -#else // defined(__GNUC__) && (__GNUC__ >= 4) -#define V8EXPORT -#endif // defined(__GNUC__) && (__GNUC__ >= 4) - -#endif // _WIN32 - - -namespace v8 { - -// The result of preparsing is either a stack overflow error, or an opaque -// blob of data that can be passed back into the parser. -class V8EXPORT PreParserData { - public: - PreParserData(size_t size, const uint8_t* data) - : data_(data), size_(size) { } - - // Create a PreParserData value where stack_overflow reports true. - static PreParserData StackOverflow() { return PreParserData(0, NULL); } - - // Whether the pre-parser stopped due to a stack overflow. - // If this is the case, size() and data() should not be used. - bool stack_overflow() { return size_ == 0u; } - - // The size of the data in bytes. - size_t size() const { return size_; } - - // Pointer to the data. - const uint8_t* data() const { return data_; } - - private: - const uint8_t* const data_; - const size_t size_; -}; - - -// Interface for a stream of Unicode characters. -class V8EXPORT UnicodeInputStream { // NOLINT - Thinks V8EXPORT is class name. - public: - virtual ~UnicodeInputStream(); - - // Returns the next Unicode code-point in the input, or a negative value when - // there is no more input in the stream. - virtual int32_t Next() = 0; -}; - - -// Preparse a JavaScript program. The source code is provided as a -// UnicodeInputStream. The max_stack_size limits the amount of stack -// space that the preparser is allowed to use. If the preparser uses -// more stack space than the limit provided, the result's stack_overflow() -// method will return true. Otherwise the result contains preparser -// data that can be used by the V8 parser to speed up parsing. -PreParserData V8EXPORT Preparse(UnicodeInputStream* input, - size_t max_stack_size); - -} // namespace v8. - -#endif // PREPARSER_H diff --git a/include/v8-profiler.h b/include/v8-profiler.h index 2499bbf0..7fc193db 100644 --- a/include/v8-profiler.h +++ b/include/v8-profiler.h @@ -1,78 +1,33 @@ // Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// 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 "v8.h" -#ifdef _WIN32 -// Setup for Windows DLL export/import. See v8.h in this directory for -// information on how to build/use V8 as a DLL. -#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED) -#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\ - build configuration to ensure that at most one of these is set -#endif - -#ifdef BUILDING_V8_SHARED -#define V8EXPORT __declspec(dllexport) -#elif USING_V8_SHARED -#define V8EXPORT __declspec(dllimport) -#else -#define V8EXPORT -#endif - -#else // _WIN32 - -// Setup for Linux shared library export. See v8.h in this directory for -// information on how to build/use V8 as shared library. -#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED) -#define V8EXPORT __attribute__ ((visibility("default"))) -#else // defined(__GNUC__) && (__GNUC__ >= 4) -#define V8EXPORT -#endif // defined(__GNUC__) && (__GNUC__ >= 4) - -#endif // _WIN32 - - /** * Profiler support for the V8 JavaScript engine. */ namespace v8 { +class HeapGraphNode; +struct HeapStatsUpdate; + +typedef uint32_t SnapshotObjectId; /** * CpuProfileNode represents a node in a call graph. */ -class V8EXPORT CpuProfileNode { +class V8_EXPORT CpuProfileNode { public: /** Returns function name (empty string for anonymous functions.) */ Handle<String> GetFunctionName() const; + /** Returns id of the script where function is located. */ + int GetScriptId() const; + /** Returns resource name for script from where the function originates. */ Handle<String> GetScriptResourceName() const; @@ -83,26 +38,27 @@ class V8EXPORT CpuProfileNode { int GetLineNumber() const; /** - * Returns total (self + children) execution time of the function, - * in milliseconds, estimated by samples count. + * Returns 1-based number of the column where the function originates. + * kNoColumnNumberInfo if no column number information is available. */ - double GetTotalTime() const; + int GetColumnNumber() const; - /** - * Returns self execution time of the function, in milliseconds, - * estimated by samples count. - */ - double GetSelfTime() const; + /** Returns bailout reason for the function + * if the optimization was disabled for it. + */ + const char* GetBailoutReason() const; - /** Returns the count of samples where function exists. */ - double GetTotalSamplesCount() const; - - /** Returns the count of samples where function was currently executing. */ - double GetSelfSamplesCount() const; + /** + * Returns the count of samples where the function was currently executing. + */ + unsigned GetHitCount() const; /** Returns function entry UID. */ 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; @@ -110,69 +66,74 @@ class V8EXPORT CpuProfileNode { const CpuProfileNode* GetChild(int index) const; static const int kNoLineNumberInfo = Message::kNoLineNumberInfo; + static const int kNoColumnNumberInfo = Message::kNoColumnInfo; }; /** - * CpuProfile contains a CPU profile in a form of two call trees: - * - top-down (from main() down to functions that do all the work); - * - bottom-up call graph (in backward direction). + * CpuProfile contains a CPU profile in a form of top-down call tree + * (from main() down to functions that do all the work). */ -class V8EXPORT CpuProfile { +class V8_EXPORT CpuProfile { public: - /** Returns CPU profile UID (assigned by the profiler.) */ - unsigned GetUid() const; - /** Returns CPU profile title. */ Handle<String> GetTitle() const; - /** Returns the root node of the bottom up call tree. */ - const CpuProfileNode* GetBottomUpRoot() 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. - * Profiles with the same uid but obtained using different - * security token are not deleted, but become inaccessible - * using FindProfile method. It is embedder's responsibility - * to call Delete on these profiles. */ void Delete(); }; /** - * Interface for controlling CPU profiling. + * Interface for controlling CPU profiling. Instance of the + * profiler can be retrieved using v8::Isolate::GetCpuProfiler. */ -class V8EXPORT CpuProfiler { +class V8_EXPORT CpuProfiler { public: /** - * A note on security tokens usage. As scripts from different - * origins can run inside a single V8 instance, it is possible to - * have functions from different security contexts intermixed in a - * single CPU profile. To avoid exposing function names belonging to - * other contexts, filtering by security token is performed while - * obtaining profiling results. + * 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. */ - - /** - * Returns the number of profiles collected (doesn't include - * profiles that are being collected at the moment of call.) - */ - static int GetProfilesCount(); - - /** Returns a profile by index. */ - static const CpuProfile* GetProfile( - int index, - Handle<Value> security_token = Handle<Value>()); - - /** Returns a profile by uid. */ - static const CpuProfile* FindProfile( - unsigned uid, - Handle<Value> security_token = Handle<Value>()); + void SetSamplingInterval(int us); /** * Starts collecting CPU profile. Title may be an empty string. It @@ -181,34 +142,45 @@ class V8EXPORT CpuProfiler { * 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. */ - static void StartProfiling(Handle<String> title); + void StartProfiling(Handle<String> title, bool record_samples = false); + + /** Deprecated. Use StartProfiling instead. */ + V8_DEPRECATED("Use StartProfiling", + void StartCpuProfiling(Handle<String> title, + bool record_samples = false)); /** * Stops collecting CPU profile with a given title and returns it. * If the title given is empty, finishes the last profile started. */ - static const CpuProfile* StopProfiling( - Handle<String> title, - Handle<Value> security_token = Handle<Value>()); + CpuProfile* StopProfiling(Handle<String> title); + + /** Deprecated. Use StopProfiling instead. */ + V8_DEPRECATED("Use StopProfiling", + const CpuProfile* StopCpuProfiling(Handle<String> title)); /** - * Deletes all existing profiles, also cancelling all profiling - * activity. All previously returned pointers to profiles and their - * contents become invalid after this call. + * Tells the profiler whether the embedder is idle. */ - static void DeleteAllProfiles(); -}; + void SetIdle(bool is_idle); - -class HeapGraphNode; + 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 V8EXPORT HeapGraphEdge { +class V8_EXPORT HeapGraphEdge { public: enum Type { kContextVariable = 0, // A variable from a function context. @@ -244,20 +216,23 @@ class V8EXPORT HeapGraphEdge { /** * HeapGraphNode represents a node in a heap graph. */ -class V8EXPORT HeapGraphNode { +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. + 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). */ @@ -274,60 +249,63 @@ class V8EXPORT HeapGraphNode { * Returns node id. For the same heap object, the id remains the same * across all snapshots. */ - uint64_t GetId() const; + SnapshotObjectId GetId() const; /** Returns node's own size, in bytes. */ - int GetSelfSize() const; + V8_DEPRECATED("Use GetShallowSize instead", + int GetSelfSize() const); - /** - * Returns node's retained size, in bytes. That is, self + sizes of - * the objects that are reachable only from this object. In other - * words, the size of memory that will be reclaimed having this node - * collected. - */ - int GetRetainedSize() 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; +}; - /** Returns retainer nodes count of the node. */ - int GetRetainersCount() const; - - /** Returns a retainer by index. */ - const HeapGraphEdge* GetRetainer(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; } /** - * Returns a dominator node. This is the node that participates in every - * path from the snapshot root to the current node. + * 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. */ - const HeapGraphNode* GetDominatorNode() const; - + virtual WriteResult WriteAsciiChunk(char* data, int size) = 0; /** - * Finds and returns a value from the heap corresponding to this node, - * if the value is still reachable. + * 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. */ - Handle<Value> GetHeapValue() const; + virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) { + return kAbort; + } }; /** * HeapSnapshots record the state of the JS heap at some moment. */ -class V8EXPORT HeapSnapshot { +class V8_EXPORT HeapSnapshot { public: - enum Type { - kFull = 0 // Heap snapshot with all instances and references. - }; enum SerializationFormat { kJSON = 0 // See format description near 'Serialize' method. }; - /** Returns heap snapshot type. */ - Type GetType() const; - /** Returns heap snapshot UID (assigned by the profiler.) */ unsigned GetUid() const; @@ -338,7 +316,7 @@ class V8EXPORT HeapSnapshot { const HeapGraphNode* GetRoot() const; /** Returns a node by its id. */ - const HeapGraphNode* GetNodeById(uint64_t id) const; + const HeapGraphNode* GetNodeById(SnapshotObjectId id) const; /** Returns total nodes count in the snapshot. */ int GetNodesCount() const; @@ -346,6 +324,9 @@ class V8EXPORT HeapSnapshot { /** 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 @@ -364,27 +345,49 @@ class V8EXPORT HeapSnapshot { * with the following structure: * * { - * snapshot: {title: "...", uid: nnn}, - * nodes: [ - * meta-info (JSON string), - * nodes themselves - * ], - * strings: [strings] + * snapshot: { + * title: "...", + * uid: nnn, + * meta: { meta-info }, + * node_count: nnn, + * edge_count: nnn + * }, + * nodes: [nodes array], + * edges: [edges array], + * strings: [strings array] * } * - * Outgoing node links are stored after each node. Nodes reference strings - * and other nodes by their indexes in corresponding arrays. + * Nodes reference strings, other nodes, and edges by their indexes + * in corresponding arrays. */ void Serialize(OutputStream* stream, SerializationFormat format) const; }; -class RetainedObjectInfo; +/** + * 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; +}; + /** - * Interface for controlling heap profiling. + * Interface for controlling heap profiling. Instance of the + * profiler can be retrieved using v8::Isolate::GetHeapProfiler. */ -class V8EXPORT HeapProfiler { +class V8_EXPORT HeapProfiler { public: /** * Callback function invoked for obtaining RetainedObjectInfo for @@ -396,31 +399,99 @@ class V8EXPORT HeapProfiler { (uint16_t class_id, Handle<Value> wrapper); /** Returns the number of snapshots taken. */ - static int GetSnapshotsCount(); + int GetSnapshotCount(); /** Returns a snapshot by index. */ - static const HeapSnapshot* GetSnapshot(int 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(Handle<Value> value); + + /** + * Returns heap object with given SnapshotObjectId if the object is alive, + * otherwise empty handle is returned. + */ + Handle<Value> FindObjectById(SnapshotObjectId id); + + /** + * Clears internal map from SnapshotObjectId to heap object. The new objects + * will not be added into it unless a heap snapshot is taken or heap object + * tracking is kicked off. + */ + void ClearObjectIds(); + + /** + * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return + * it in case heap profiler cannot find id for the object passed as + * parameter. HeapSnapshot::GetNodeById will always return NULL for such id. + */ + static const SnapshotObjectId kUnknownObjectId = 0; - /** Returns a profile by uid. */ - static const HeapSnapshot* FindSnapshot(unsigned uid); + /** + * 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(Handle<Object> object) = 0; + protected: + virtual ~ObjectNameResolver() {} + }; /** * Takes a heap snapshot and returns it. Title may be an empty string. - * See HeapSnapshot::Type for types description. */ - static const HeapSnapshot* TakeSnapshot( + const HeapSnapshot* TakeHeapSnapshot( Handle<String> title, - HeapSnapshot::Type type = HeapSnapshot::kFull, - ActivityControl* control = NULL); + 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. + * 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); + + /** + * Stops tracking of heap objects population statistics, cleans up all + * collected data. StartHeapObjectsTracking must be called again prior to + * calling PushHeapObjectsStats next time. + */ + void StopTrackingHeapObjects(); /** * Deletes all snapshots taken. All previously returned pointers to * snapshots and their contents become invalid after this call. */ - static void DeleteAllSnapshots(); + void DeleteAllHeapSnapshots(); /** Binds a callback to embedder's class ID. */ - static void DefineWrapperClass( + void SetWrapperClassInfoProvider( uint16_t class_id, WrapperInfoCallback callback); @@ -431,8 +502,19 @@ class V8EXPORT HeapProfiler { */ static const uint16_t kPersistentHandleNoClassId = 0; - /** Returns the number of currently existing persistent handles. */ - static int GetPersistentHandleCount(); + /** Returns memory used for profiler internal data and snapshots. */ + size_t GetProfilerMemorySize(); + + /** + * Sets a RetainedObjectInfo for an object group (see V8::SetObjectGroupId). + */ + void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info); + + private: + HeapProfiler(); + ~HeapProfiler(); + HeapProfiler(const HeapProfiler&); + HeapProfiler& operator=(const HeapProfiler&); }; @@ -453,14 +535,14 @@ class V8EXPORT HeapProfiler { * objects for heap snapshots, he 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 DefineWrapperClass. + * 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 V8EXPORT RetainedObjectInfo { // NOLINT +class V8_EXPORT RetainedObjectInfo { // NOLINT public: /** Called by V8 when it no longer needs an instance. */ virtual void Dispose() = 0; @@ -510,10 +592,20 @@ class V8EXPORT RetainedObjectInfo { // NOLINT }; -} // namespace v8 +/** + * 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. +}; -#undef V8EXPORT +} // namespace v8 #endif // V8_V8_PROFILER_H_ diff --git a/include/v8-testing.h b/include/v8-testing.h index 245f74d8..c827b694 100644 --- a/include/v8-testing.h +++ b/include/v8-testing.h @@ -1,70 +1,18 @@ // Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// 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" -#ifdef _WIN32 -// Setup for Windows DLL export/import. See v8.h in this directory for -// information on how to build/use V8 as a DLL. -#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED) -#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\ - build configuration to ensure that at most one of these is set -#endif - -#ifdef BUILDING_V8_SHARED -#define V8EXPORT __declspec(dllexport) -#elif USING_V8_SHARED -#define V8EXPORT __declspec(dllimport) -#else -#define V8EXPORT -#endif - -#else // _WIN32 - -// Setup for Linux shared library export. See v8.h in this directory for -// information on how to build/use V8 as shared library. -#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED) -#define V8EXPORT __attribute__ ((visibility("default"))) -#else // defined(__GNUC__) && (__GNUC__ >= 4) -#define V8EXPORT -#endif // defined(__GNUC__) && (__GNUC__ >= 4) - -#endif // _WIN32 - - /** * Testing support for the V8 JavaScript engine. */ namespace v8 { -class V8EXPORT Testing { +class V8_EXPORT Testing { public: enum StressType { kStressTypeOpt, @@ -97,8 +45,4 @@ class V8EXPORT Testing { } // namespace v8 - -#undef V8EXPORT - - #endif // V8_V8_TEST_H_ diff --git a/include/v8-util.h b/include/v8-util.h new file mode 100644 index 00000000..1eaf1ab6 --- /dev/null +++ b/include/v8-util.h @@ -0,0 +1,487 @@ +// 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" +#include <map> +#include <vector> + +/** + * Support for Persistent containers. + * + * C++11 embedders can use STL containers with UniquePersistent 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, + kWeak +}; + + +/** + * A default trait implemenation for PersistentValueMap which uses std::map + * as a backing map. + * + * Users will have to implement their own weak callbacks & dispose traits. + */ +template<typename K, typename V> +class StdMapTraits { + public: + // STL map & related: + typedef std::map<K, PersistentContainerValue> Impl; + typedef typename Impl::iterator Iterator; + + static bool Empty(Impl* impl) { return impl->empty(); } + static size_t Size(Impl* impl) { return impl->size(); } + static void Swap(Impl& a, Impl& b) { std::swap(a, b); } // NOLINT + static Iterator Begin(Impl* impl) { return impl->begin(); } + static Iterator End(Impl* impl) { return impl->end(); } + static K Key(Iterator it) { return it->first; } + static PersistentContainerValue Value(Iterator it) { return it->second; } + static PersistentContainerValue Set(Impl* impl, K key, + PersistentContainerValue value) { + std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value)); + PersistentContainerValue old_value = kPersistentContainerNotFound; + if (!res.second) { + old_value = res.first->second; + res.first->second = value; + } + return old_value; + } + static PersistentContainerValue Get(Impl* impl, K key) { + Iterator it = impl->find(key); + if (it == impl->end()) return kPersistentContainerNotFound; + return it->second; + } + static PersistentContainerValue Remove(Impl* impl, K key) { + Iterator it = impl->find(key); + if (it == impl->end()) return kPersistentContainerNotFound; + PersistentContainerValue value = it->second; + impl->erase(it); + return value; + } +}; + + +/** + * A default trait implementation for PersistentValueMap, which inherits + * a std:map backing map from StdMapTraits and holds non-weak persistent + * objects and has no special Dispose handling. + * + * You should not derive from this class, since MapType depends on the + * surrounding class, and hence a subclass cannot simply inherit the methods. + */ +template<typename K, typename V> +class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> { + public: + // Weak callback & friends: + static const PersistentContainerCallbackType kCallbackType = kNotWeak; + typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> > + MapType; + typedef void WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter( + MapType* map, const K& key, Local<V> value) { + return NULL; + } + static MapType* MapFromWeakCallbackData( + const WeakCallbackData<V, WeakCallbackDataType>& data) { + return NULL; + } + static K KeyFromWeakCallbackData( + const WeakCallbackData<V, WeakCallbackDataType>& data) { + return K(); + } + static void DisposeCallbackData(WeakCallbackDataType* data) { } + static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) { } +}; + + +/** + * A map wrapper that allows using UniquePersistent as a mapped value. + * C++11 embedders don't need this class, as they can use UniquePersistent + * directly in std containers. + * + * The map relies on a backing map, whose type and accessors are described + * by the Traits class. The backing map will handle values of type + * PersistentContainerValue, with all conversion into and out of V8 + * handles being transparently handled by this class. + */ +template<typename K, typename V, typename Traits> +class PersistentValueMap { + public: + explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {} + + ~PersistentValueMap() { Clear(); } + + Isolate* GetIsolate() { return isolate_; } + + /** + * Return size of the map. + */ + size_t Size() { return Traits::Size(&impl_); } + + /** + * Return whether the map holds weak persistents. + */ + bool IsWeak() { return Traits::kCallbackType != kNotWeak; } + + /** + * Get value stored in map. + */ + Local<V> Get(const K& key) { + return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key))); + } + + /** + * Check whether a value is contained in the map. + */ + bool Contains(const K& key) { + return Traits::Get(&impl_, key) != kPersistentContainerNotFound; + } + + /** + * Get value stored in map and set it in returnValue. + * Return true if a value was found. + */ + bool SetReturnValue(const K& key, + ReturnValue<Value> returnValue) { + return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key)); + } + + /** + * Call Isolate::SetReference with the given parent and the map value. + */ + void SetReference(const K& key, + const Persistent<Object>& parent) { + GetIsolate()->SetReference( + reinterpret_cast<internal::Object**>(parent.val_), + reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key)))); + } + + /** + * Put value into map. Depending on Traits::kIsWeak, the value will be held + * by the map strongly or weakly. + * Returns old value as UniquePersistent. + */ + UniquePersistent<V> Set(const K& key, Local<V> value) { + UniquePersistent<V> persistent(isolate_, value); + return SetUnique(key, &persistent); + } + + /** + * Put value into map, like Set(const K&, Local<V>). + */ + UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) { + return SetUnique(key, &value); + } + + /** + * Return value for key and remove it from the map. + */ + UniquePersistent<V> Remove(const K& key) { + return Release(Traits::Remove(&impl_, key)).Pass(); + } + + /** + * Traverses the map repeatedly, + * in case side effects of disposal cause insertions. + **/ + void Clear() { + typedef typename Traits::Iterator It; + HandleScope handle_scope(isolate_); + // TODO(dcarney): figure out if this swap and loop is necessary. + while (!Traits::Empty(&impl_)) { + typename Traits::Impl impl; + Traits::Swap(impl_, impl); + for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) { + Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(), + Traits::Key(i)); + } + } + } + + /** + * Helper class for GetReference/SetWithReference. Do not use outside + * that context. + */ + class PersistentValueReference { + public: + PersistentValueReference() : value_(kPersistentContainerNotFound) { } + PersistentValueReference(const PersistentValueReference& other) + : value_(other.value_) { } + + Local<V> NewLocal(Isolate* isolate) const { + return Local<V>::New(isolate, FromVal(value_)); + } + bool IsEmpty() const { + return value_ == kPersistentContainerNotFound; + } + template<typename T> + bool SetReturnValue(ReturnValue<T> returnValue) { + return SetReturnValueFromVal(&returnValue, value_); + } + void Reset() { + value_ = kPersistentContainerNotFound; + } + void operator=(const PersistentValueReference& other) { + value_ = other.value_; + } + + private: + friend class PersistentValueMap; + + 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)); + } + + /** + * Put a value into the map and update the reference. + * Restrictions of GetReference apply here as well. + */ + UniquePersistent<V> Set(const K& key, UniquePersistent<V> value, + PersistentValueReference* reference) { + *reference = Leak(&value); + return SetUnique(key, &value); + } + + private: + PersistentValueMap(PersistentValueMap&); + void operator=(PersistentValueMap&); + + /** + * Put the value into the map, and set the 'weak' callback when demanded + * by the Traits class. + */ + UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { + if (Traits::kCallbackType != kNotWeak) { + Local<V> value(Local<V>::New(isolate_, *persistent)); + persistent->template SetWeak<typename Traits::WeakCallbackDataType>( + Traits::WeakCallbackParameter(this, key, value), WeakCallback); + } + PersistentContainerValue old_value = + Traits::Set(&impl_, key, ClearAndLeak(persistent)); + return Release(old_value).Pass(); + } + + static void WeakCallback( + const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) { + if (Traits::kCallbackType != kNotWeak) { + PersistentValueMap<K, V, Traits>* persistentValueMap = + Traits::MapFromWeakCallbackData(data); + K key = Traits::KeyFromWeakCallbackData(data); + Traits::Dispose(data.GetIsolate(), + persistentValueMap->Remove(key).Pass(), key); + Traits::DisposeCallbackData(data.GetParameter()); + } + } + + static V* FromVal(PersistentContainerValue v) { + return reinterpret_cast<V*>(v); + } + + static bool SetReturnValueFromVal( + ReturnValue<Value>* returnValue, PersistentContainerValue value) { + bool hasValue = value != kPersistentContainerNotFound; + if (hasValue) { + returnValue->SetInternal( + *reinterpret_cast<internal::Object**>(FromVal(value))); + } + return hasValue; + } + + static PersistentContainerValue ClearAndLeak( + UniquePersistent<V>* persistent) { + V* v = persistent->val_; + persistent->val_ = 0; + return reinterpret_cast<PersistentContainerValue>(v); + } + + static PersistentContainerValue Leak( + UniquePersistent<V>* persistent) { + return reinterpret_cast<PersistentContainerValue>(persistent->val_); + } + + /** + * Return a container value as UniquePersistent and make sure the weak + * callback is properly disposed of. All remove functionality should go + * through this. + */ + static UniquePersistent<V> Release(PersistentContainerValue v) { + UniquePersistent<V> p; + p.val_ = FromVal(v); + if (Traits::kCallbackType != kNotWeak && p.IsWeak()) { + Traits::DisposeCallbackData( + p.template ClearWeak<typename Traits::WeakCallbackDataType>()); + } + return p.Pass(); + } + + Isolate* isolate_; + typename Traits::Impl impl_; +}; + + +/** + * A map that uses UniquePersistent 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 + * UniquePersistent directly in std containers. + */ +template<typename K, typename V, + typename Traits = DefaultPersistentValueMapTraits<K, V> > +class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> { + public: + explicit StdPersistentValueMap(Isolate* isolate) + : PersistentValueMap<K, V, Traits>(isolate) {} +}; + + +class DefaultPersistentValueVectorTraits { + public: + typedef std::vector<PersistentContainerValue> Impl; + + static void Append(Impl* impl, PersistentContainerValue value) { + impl->push_back(value); + } + static bool IsEmpty(const Impl* impl) { + return impl->empty(); + } + static size_t Size(const Impl* impl) { + return impl->size(); + } + static PersistentContainerValue Get(const Impl* impl, size_t i) { + return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound; + } + static void ReserveCapacity(Impl* impl, size_t capacity) { + impl->reserve(capacity); + } + static void Clear(Impl* impl) { + impl->clear(); + } +}; + + +/** + * A vector wrapper that safely stores UniquePersistent values. + * C++11 embedders don't need this class, as they can use UniquePersistent + * directly in std containers. + * + * This class relies on a backing vector implementation, whose type and methods + * are described by the Traits class. The backing map will handle values of type + * PersistentContainerValue, with all conversion into and out of V8 + * handles being transparently handled by this class. + */ +template<typename V, typename Traits = DefaultPersistentValueVectorTraits> +class PersistentValueVector { + public: + explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { } + + ~PersistentValueVector() { + Clear(); + } + + /** + * Append a value to the vector. + */ + void Append(Local<V> value) { + UniquePersistent<V> persistent(isolate_, value); + Traits::Append(&impl_, ClearAndLeak(&persistent)); + } + + /** + * Append a persistent's value to the vector. + */ + void Append(UniquePersistent<V> persistent) { + Traits::Append(&impl_, ClearAndLeak(&persistent)); + } + + /** + * Are there any values in the vector? + */ + bool IsEmpty() const { + return Traits::IsEmpty(&impl_); + } + + /** + * How many elements are in the vector? + */ + size_t Size() const { + return Traits::Size(&impl_); + } + + /** + * Retrieve the i-th value in the vector. + */ + Local<V> Get(size_t index) const { + return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index))); + } + + /** + * Remove all elements from the vector. + */ + void Clear() { + size_t length = Traits::Size(&impl_); + for (size_t i = 0; i < length; i++) { + UniquePersistent<V> p; + p.val_ = FromVal(Traits::Get(&impl_, i)); + } + Traits::Clear(&impl_); + } + + /** + * Reserve capacity in the vector. + * (Efficiency gains depend on the backing implementation.) + */ + void ReserveCapacity(size_t capacity) { + Traits::ReserveCapacity(&impl_, capacity); + } + + private: + static PersistentContainerValue ClearAndLeak( + UniquePersistent<V>* persistent) { + V* v = persistent->val_; + persistent->val_ = 0; + return reinterpret_cast<PersistentContainerValue>(v); + } + + static V* FromVal(PersistentContainerValue v) { + return reinterpret_cast<V*>(v); + } + + Isolate* isolate_; + typename Traits::Impl impl_; +}; + +} // namespace v8 + +#endif // V8_UTIL_H_ diff --git a/include/v8.h b/include/v8.h index 33179f5b..ec1941e6 100644 --- a/include/v8.h +++ b/include/v8.h @@ -1,29 +1,6 @@ -// Copyright 2011 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// 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 * @@ -40,7 +17,10 @@ #include "v8stdint.h" -#ifdef _WIN32 +// 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 @@ -53,86 +33,134 @@ #endif #ifdef BUILDING_V8_SHARED -#define V8EXPORT __declspec(dllexport) +# define V8_EXPORT __declspec(dllexport) #elif USING_V8_SHARED -#define V8EXPORT __declspec(dllimport) +# define V8_EXPORT __declspec(dllimport) #else -#define V8EXPORT +# define V8_EXPORT #endif // BUILDING_V8_SHARED -#else // _WIN32 +#else // V8_OS_WIN -// Setup for Linux shared library export. There is no need to distinguish -// between building or using the V8 shared library, but we should not -// export symbols when we are building a static library. -#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED) -#define V8EXPORT __attribute__ ((visibility("default"))) -#else // defined(__GNUC__) && (__GNUC__ >= 4) -#define V8EXPORT -#endif // defined(__GNUC__) && (__GNUC__ >= 4) +// Setup for Linux shared library export. +#if V8_HAS_ATTRIBUTE_VISIBILITY && defined(V8_SHARED) +# ifdef BUILDING_V8_SHARED +# define V8_EXPORT __attribute__ ((visibility("default"))) +# else +# define V8_EXPORT +# endif +#else +# define V8_EXPORT +#endif -#endif // _WIN32 +#endif // V8_OS_WIN /** * The v8 JavaScript engine. */ namespace v8 { -class Context; -class String; -class StringObject; -class Value; -class Utils; -class Number; -class NumberObject; -class Object; +class AccessorSignature; class Array; -class Int32; -class Uint32; -class External; -class Primitive; class Boolean; class BooleanObject; -class Integer; -class Function; +class Context; +class CpuProfiler; +class Data; class Date; +class DeclaredAccessorDescriptor; +class External; +class Function; +class FunctionTemplate; +class HeapProfiler; class ImplementationUtilities; +class Int32; +class Integer; +class Isolate; +class Name; +class Number; +class NumberObject; +class Object; +class ObjectOperationDescriptor; +class ObjectTemplate; +class Platform; +class Primitive; +class RawOperationDescriptor; +class Script; class Signature; +class StackFrame; +class StackTrace; +class String; +class StringObject; +class Symbol; +class SymbolObject; +class Private; +class Uint32; +class Utils; +class Value; template <class T> class Handle; template <class T> class Local; -template <class T> class Persistent; +template <class T> class Eternal; +template<class T> class NonCopyablePersistentTraits; +template<class T> class PersistentBase; +template<class T, + class M = NonCopyablePersistentTraits<T> > class Persistent; +template<class T> class UniquePersistent; +template<class K, class V, class T> class PersistentValueMap; +template<class V, class T> class PersistentValueVector; +template<class T, class P> class WeakCallbackObject; class FunctionTemplate; class ObjectTemplate; class Data; -class AccessorInfo; +template<typename T> class FunctionCallbackInfo; +template<typename T> class PropertyCallbackInfo; class StackTrace; class StackFrame; +class Isolate; +class DeclaredAccessorDescriptor; +class ObjectOperationDescriptor; +class RawOperationDescriptor; +class CallHandlerHelper; +class EscapableHandleScope; +template<typename T> class ReturnValue; namespace internal { - class Arguments; -class Object; class Heap; class HeapObject; class Isolate; +class Object; +struct StreamedSource; +template<typename T> class CustomArguments; +class PropertyCallbackArguments; +class FunctionCallbackArguments; +class GlobalHandles; } -// --- Weak Handles --- - - /** - * A weak reference callback function. - * - * This callback should either explicitly invoke Dispose on |object| if - * V8 wrapper is not needed anymore, or 'revive' it by invocation of MakeWeak. - * - * \param object the weak global object to be reclaimed by the garbage collector - * \param parameter the value passed in when making the weak global object + * General purpose unique identifier. */ -typedef void (*WeakReferenceCallback)(Persistent<Value> object, - void* parameter); +class UniqueId { + public: + explicit UniqueId(intptr_t data) + : data_(data) {} + + bool operator==(const UniqueId& other) const { + return data_ == other.data_; + } + + bool operator!=(const UniqueId& other) const { + return data_ != other.data_; + } + bool operator<(const UniqueId& other) const { + return data_ < other.data_; + } + + private: + intptr_t data_; +}; // --- Handles --- @@ -141,6 +169,7 @@ typedef void (*WeakReferenceCallback)(Persistent<Value> object, *(static_cast<T* volatile*>(0)) = static_cast<S*>(0); \ } + /** * An object reference managed by the v8 garbage collector. * @@ -171,12 +200,7 @@ template <class T> class Handle { /** * Creates an empty handle. */ - inline Handle() : val_(0) {} - - /** - * Creates a new handle for the specified value. - */ - inline explicit Handle(T* val) : val_(val) {} + V8_INLINE Handle() : val_(0) {} /** * Creates a handle for the contents of the specified handle. This @@ -188,7 +212,7 @@ template <class T> class Handle { * Handle<String> to a variable declared as Handle<Value>, is legal * because String is a subclass of Value. */ - template <class S> inline Handle(Handle<S> that) + template <class S> V8_INLINE Handle(Handle<S> that) : val_(reinterpret_cast<T*>(*that)) { /** * This check fails when trying to convert between incompatible @@ -201,16 +225,16 @@ template <class T> class Handle { /** * Returns true if the handle is empty. */ - inline bool IsEmpty() const { return val_ == 0; } + V8_INLINE bool IsEmpty() const { return val_ == 0; } /** * Sets the handle to be empty. IsEmpty() will then return true. */ - inline void Clear() { val_ = 0; } + V8_INLINE void Clear() { val_ = 0; } - inline T* operator->() const { return val_; } + V8_INLINE T* operator->() const { return val_; } - inline T* operator*() const { return val_; } + V8_INLINE T* operator*() const { return val_; } /** * Checks whether two handles are the same. @@ -218,9 +242,18 @@ template <class T> class Handle { * to which they refer are identical. * The handles' references are not checked. */ - template <class S> inline bool operator==(Handle<S> that) const { - internal::Object** a = reinterpret_cast<internal::Object**>(**this); - internal::Object** b = reinterpret_cast<internal::Object**>(*that); + template <class S> V8_INLINE bool operator==(const Handle<S>& that) const { + internal::Object** a = reinterpret_cast<internal::Object**>(this->val_); + internal::Object** b = reinterpret_cast<internal::Object**>(that.val_); + if (a == 0) return b == 0; + if (b == 0) return false; + return *a == *b; + } + + template <class S> V8_INLINE bool operator==( + const PersistentBase<S>& that) const { + internal::Object** a = reinterpret_cast<internal::Object**>(this->val_); + internal::Object** b = reinterpret_cast<internal::Object**>(that.val_); if (a == 0) return b == 0; if (b == 0) return false; return *a == *b; @@ -232,11 +265,16 @@ template <class T> class Handle { * the objects to which they refer are different. * The handles' references are not checked. */ - template <class S> inline bool operator!=(Handle<S> that) const { + template <class S> V8_INLINE bool operator!=(const Handle<S>& that) const { + return !operator==(that); + } + + template <class S> V8_INLINE bool operator!=( + const Persistent<S>& that) const { return !operator==(that); } - template <class S> static inline Handle<T> Cast(Handle<S> that) { + template <class S> V8_INLINE static Handle<T> Cast(Handle<S> 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. @@ -245,11 +283,43 @@ template <class T> class Handle { return Handle<T>(T::Cast(*that)); } - template <class S> inline Handle<S> As() { + template <class S> V8_INLINE Handle<S> As() { return Handle<S>::Cast(*this); } + V8_INLINE static Handle<T> New(Isolate* isolate, Handle<T> that) { + return New(isolate, that.val_); + } + V8_INLINE static Handle<T> New(Isolate* isolate, + const PersistentBase<T>& that) { + return New(isolate, that.val_); + } + private: + friend class Utils; + template<class F, class M> friend class Persistent; + template<class F> friend class PersistentBase; + template<class F> friend class Handle; + template<class F> friend class Local; + template<class F> friend class FunctionCallbackInfo; + template<class F> friend class PropertyCallbackInfo; + template<class F> friend class internal::CustomArguments; + friend Handle<Primitive> Undefined(Isolate* isolate); + friend Handle<Primitive> Null(Isolate* isolate); + friend Handle<Boolean> True(Isolate* isolate); + friend Handle<Boolean> False(Isolate* isolate); + friend class Context; + friend class HandleScope; + friend class Object; + friend class Private; + + /** + * Creates a new handle for the specified value. + */ + V8_INLINE explicit Handle(T* val) : val_(val) {} + + V8_INLINE static Handle<T> New(Isolate* isolate, T* that); + T* val_; }; @@ -263,8 +333,8 @@ template <class T> class Handle { */ template <class T> class Local : public Handle<T> { public: - inline Local(); - template <class S> inline Local(Local<S> that) + V8_INLINE Local(); + template <class S> V8_INLINE Local(Local<S> that) : Handle<T>(reinterpret_cast<T*>(*that)) { /** * This check fails when trying to convert between incompatible @@ -273,8 +343,9 @@ template <class T> class Local : public Handle<T> { */ TYPE_CHECK(T, S); } - template <class S> inline Local(S* that) : Handle<T>(that) { } - template <class S> static inline Local<T> Cast(Local<S> that) { + + + template <class S> V8_INLINE static Local<T> Cast(Local<S> 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. @@ -282,140 +353,435 @@ template <class T> class Local : public Handle<T> { #endif return Local<T>(T::Cast(*that)); } + template <class S> V8_INLINE Local(Handle<S> that) + : Handle<T>(reinterpret_cast<T*>(*that)) { + TYPE_CHECK(T, S); + } - template <class S> inline Local<S> As() { + template <class S> V8_INLINE Local<S> As() { return Local<S>::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. + /** + * 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. */ - inline static Local<T> New(Handle<T> that); + V8_INLINE static Local<T> New(Isolate* isolate, Handle<T> that); + V8_INLINE static Local<T> New(Isolate* isolate, + const PersistentBase<T>& that); + + private: + friend class Utils; + template<class F> friend class Eternal; + template<class F> friend class PersistentBase; + template<class F, class M> friend class Persistent; + template<class F> friend class Handle; + template<class F> friend class Local; + template<class F> friend class FunctionCallbackInfo; + template<class F> friend class PropertyCallbackInfo; + friend class String; + friend class Object; + friend class Context; + template<class F> friend class internal::CustomArguments; + friend class HandleScope; + friend class EscapableHandleScope; + template<class F1, class F2, class F3> friend class PersistentValueMap; + template<class F1, class F2> friend class PersistentValueVector; + + template <class S> V8_INLINE Local(S* that) : Handle<T>(that) { } + V8_INLINE static Local<T> New(Isolate* isolate, T* that); +}; + + +// Eternal handles are set-once handles that live for the life of the isolate. +template <class T> class Eternal { + public: + V8_INLINE Eternal() : index_(kInitialValue) { } + template<class S> + V8_INLINE Eternal(Isolate* isolate, Local<S> handle) : index_(kInitialValue) { + Set(isolate, handle); + } + // Can only be safely called if already set. + V8_INLINE Local<T> Get(Isolate* isolate); + V8_INLINE bool IsEmpty() { return index_ == kInitialValue; } + template<class S> V8_INLINE void Set(Isolate* isolate, Local<S> handle); + + private: + static const int kInitialValue = -1; + int index_; +}; + + +template<class T, class P> +class WeakCallbackData { + public: + typedef void (*Callback)(const WeakCallbackData<T, P>& data); + + V8_INLINE Isolate* GetIsolate() const { return isolate_; } + V8_INLINE Local<T> GetValue() const { return handle_; } + V8_INLINE P* GetParameter() const { return parameter_; } + + private: + friend class internal::GlobalHandles; + WeakCallbackData(Isolate* isolate, Local<T> handle, P* parameter) + : isolate_(isolate), handle_(handle), parameter_(parameter) { } + Isolate* isolate_; + Local<T> handle_; + P* parameter_; }; /** * 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 Persistent handle remains valid until it is explicitly + * allocated, a PersistentBase handle remains valid until it is explicitly * disposed. * * 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 Persistent::New and existing handles can - * be disposed using Persistent::Dispose. Since persistent handles - * are passed by value you may have many persistent handle objects - * that point to the same storage cell. For instance, if you pass a - * persistent handle as an argument to a function you will not get two - * different storage cells but rather two references to the same - * storage cell. + * cell can be created using the constructor or PersistentBase::Reset and + * existing handles can be disposed using PersistentBase::Reset. + * */ -template <class T> class Persistent : public Handle<T> { +template <class T> class PersistentBase { public: /** - * Creates an empty persistent handle that doesn't point to any - * storage cell. + * 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 */ - inline Persistent(); + template <class S> + V8_INLINE void Reset(Isolate* isolate, const Handle<S>& other); /** - * Creates a persistent handle for the same storage cell as the - * specified handle. This constructor allows you to pass persistent - * handles as arguments by value and to assign between persistent - * handles. However, attempting to assign between incompatible - * persistent handles, for instance from a Persistent<String> to a - * Persistent<Number> will cause a compile-time error. Assigning - * between compatible persistent handles, for instance assigning a - * Persistent<String> to a variable declared as Persistent<Value>, - * is allowed as String is a subclass of Value. + * If non-empty, destroy the underlying storage cell + * and create a new one with the contents of other if other is non empty */ - template <class S> inline Persistent(Persistent<S> that) - : Handle<T>(reinterpret_cast<T*>(*that)) { - /** - * This check fails when trying to convert between incompatible - * handles. For example, converting from a Handle<String> to a - * Handle<Number>. - */ - TYPE_CHECK(T, S); + template <class S> + V8_INLINE void Reset(Isolate* isolate, const PersistentBase<S>& other); + + V8_INLINE bool IsEmpty() const { return val_ == 0; } + + template <class S> + V8_INLINE bool operator==(const PersistentBase<S>& that) const { + internal::Object** a = reinterpret_cast<internal::Object**>(this->val_); + internal::Object** b = reinterpret_cast<internal::Object**>(that.val_); + if (a == 0) return b == 0; + if (b == 0) return false; + return *a == *b; + } + + template <class S> V8_INLINE bool operator==(const Handle<S>& that) const { + internal::Object** a = reinterpret_cast<internal::Object**>(this->val_); + internal::Object** b = reinterpret_cast<internal::Object**>(that.val_); + if (a == 0) return b == 0; + if (b == 0) return false; + return *a == *b; + } + + template <class S> + V8_INLINE bool operator!=(const PersistentBase<S>& that) const { + return !operator==(that); + } + + template <class S> V8_INLINE bool operator!=(const Handle<S>& 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<typename P> + V8_INLINE void SetWeak( + P* parameter, + typename WeakCallbackData<T, P>::Callback callback); + + template<typename S, typename P> + V8_INLINE void SetWeak( + P* parameter, + typename WeakCallbackData<S, P>::Callback callback); + + template<typename P> + V8_INLINE P* ClearWeak(); + + // TODO(dcarney): remove this. + V8_INLINE void ClearWeak() { ClearWeak<void>(); } + + /** + * 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 partially dependent. Partially dependent + * handles only depend on other partially dependent handles and these + * dependencies are provided through object groups. It provides a way to build + * smaller object groups for young objects that represent only a subset of all + * external dependencies. This mark is automatically cleared after each + * garbage collection. + */ + V8_INLINE void MarkPartiallyDependent(); + + 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; + + private: + friend class Isolate; + friend class Utils; + template<class F> friend class Handle; + template<class F> friend class Local; + template<class F1, class F2> friend class Persistent; + template<class F> friend class UniquePersistent; + template<class F> friend class PersistentBase; + template<class F> friend class ReturnValue; + template<class F1, class F2, class F3> friend class PersistentValueMap; + template<class F1, class F2> friend class PersistentValueVector; + friend class Object; + + explicit V8_INLINE PersistentBase(T* val) : val_(val) {} + PersistentBase(PersistentBase& other); // NOLINT + void operator=(PersistentBase&); + 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 T> +class NonCopyablePersistentTraits { + public: + typedef Persistent<T, NonCopyablePersistentTraits<T> > NonCopyablePersistent; + static const bool kResetInDestructor = false; + template<class S, class M> + V8_INLINE static void Copy(const Persistent<S, M>& source, + NonCopyablePersistent* dest) { + Uncompilable<Object>(); + } + // TODO(dcarney): come up with a good compile error here. + template<class O> 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<class T> +struct CopyablePersistentTraits { + typedef Persistent<T, CopyablePersistentTraits<T> > CopyablePersistent; + static const bool kResetInDestructor = true; + template<class S, class M> + static V8_INLINE void Copy(const Persistent<S, M>& source, + CopyablePersistent* dest) { + // do nothing, just allow copy } +}; - template <class S> inline Persistent(S* that) : Handle<T>(that) { } +/** + * A PersistentBase which allows copy and assignment. + * + * Copy, assignment and destructor bevavior is controlled by the traits + * class M. + * + * Note: Persistent class hierarchy is subject to future changes. + */ +template <class T, class M> class Persistent : public PersistentBase<T> { + public: + /** + * A Persistent with no storage cell. + */ + V8_INLINE Persistent() : PersistentBase<T>(0) { } + /** + * Construct a Persistent from a Handle. + * When the Handle is non-empty, a new storage cell is created + * pointing to the same object, and no flags are set. + */ + template <class S> V8_INLINE Persistent(Isolate* isolate, Handle<S> that) + : PersistentBase<T>(PersistentBase<T>::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 <class S, class M2> + V8_INLINE Persistent(Isolate* isolate, const Persistent<S, M2>& that) + : PersistentBase<T>(PersistentBase<T>::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<T>(0) { + Copy(that); + } + template <class S, class M2> + V8_INLINE Persistent(const Persistent<S, M2>& that) : PersistentBase<T>(0) { + Copy(that); + } + V8_INLINE Persistent& operator=(const Persistent& that) { // NOLINT + Copy(that); + return *this; + } + template <class S, class M2> + V8_INLINE Persistent& operator=(const Persistent<S, M2>& that) { // NOLINT + Copy(that); + return *this; + } /** - * "Casts" a plain handle which is known to be a persistent handle - * to a persistent handle. + * 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. */ - template <class S> explicit inline Persistent(Handle<S> that) - : Handle<T>(*that) { } + V8_INLINE ~Persistent() { + if (M::kResetInDestructor) this->Reset(); + } - template <class S> static inline Persistent<T> Cast(Persistent<S> that) { + // TODO(dcarney): this is pretty useless, fix or remove + template <class S> + V8_INLINE static Persistent<T>& Cast(Persistent<S>& 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()) return Persistent<T>(); + if (!that.IsEmpty()) T::Cast(*that); #endif - return Persistent<T>(T::Cast(*that)); + return reinterpret_cast<Persistent<T>&>(that); } - template <class S> inline Persistent<S> As() { + // TODO(dcarney): this is pretty useless, fix or remove + template <class S> V8_INLINE Persistent<S>& As() { // NOLINT return Persistent<S>::Cast(*this); } + // This will be removed. + V8_INLINE T* ClearAndLeak(); + + private: + friend class Isolate; + friend class Utils; + template<class F> friend class Handle; + template<class F> friend class Local; + template<class F1, class F2> friend class Persistent; + template<class F> friend class ReturnValue; + + template <class S> V8_INLINE Persistent(S* that) : PersistentBase<T>(that) { } + V8_INLINE T* operator*() const { return this->val_; } + template<class S, class M2> + V8_INLINE void Copy(const Persistent<S, M2>& that); +}; + + +/** + * A PersistentBase which has move semantics. + * + * Note: Persistent class hierarchy is subject to future changes. + */ +template<class T> +class UniquePersistent : public PersistentBase<T> { + struct RValue { + V8_INLINE explicit RValue(UniquePersistent* obj) : object(obj) {} + UniquePersistent* object; + }; + + public: /** - * Creates a new persistent handle for an existing local or - * persistent handle. + * A UniquePersistent with no storage cell. */ - inline static Persistent<T> New(Handle<T> that); - + V8_INLINE UniquePersistent() : PersistentBase<T>(0) { } /** - * Releases the storage cell referenced by this persistent handle. - * Does not remove the reference to the cell from any handles. - * This handle's reference, and any other references to the storage - * cell remain and IsEmpty will still return false. + * Construct a UniquePersistent from a Handle. + * When the Handle is non-empty, a new storage cell is created + * pointing to the same object, and no flags are set. */ - inline void Dispose(); - + template <class S> + V8_INLINE UniquePersistent(Isolate* isolate, Handle<S> that) + : PersistentBase<T>(PersistentBase<T>::New(isolate, *that)) { + TYPE_CHECK(T, S); + } /** - * Make the reference to this object weak. When only weak handles - * refer to the object, the garbage collector will perform a - * callback to the given V8::WeakReferenceCallback function, passing - * it the object reference and the given parameters. + * Construct a UniquePersistent 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. */ - inline void MakeWeak(void* parameters, WeakReferenceCallback callback); - - /** Clears the weak reference to this object.*/ - inline void ClearWeak(); - + template <class S> + V8_INLINE UniquePersistent(Isolate* isolate, const PersistentBase<S>& that) + : PersistentBase<T>(PersistentBase<T>::New(isolate, that.val_)) { + TYPE_CHECK(T, S); + } /** - * 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. + * Move constructor. */ - inline void MarkIndependent(); - + V8_INLINE UniquePersistent(RValue rvalue) + : PersistentBase<T>(rvalue.object->val_) { + rvalue.object->val_ = 0; + } + V8_INLINE ~UniquePersistent() { this->Reset(); } /** - *Checks if the handle holds the only reference to an object. + * Move via assignment. */ - inline bool IsNearDeath() const; - + template<class S> + V8_INLINE UniquePersistent& operator=(UniquePersistent<S> rhs) { + TYPE_CHECK(T, S); + this->Reset(); + this->val_ = rhs.val_; + rhs.val_ = 0; + return *this; + } /** - * Returns true if the handle's reference is weak. + * Cast operator for moves. */ - inline bool IsWeak() const; - + V8_INLINE operator RValue() { return RValue(this); } /** - * Assigns a wrapper class ID to the handle. See RetainedObjectInfo - * interface description in v8-profiler.h for details. + * Pass allows returning uniques from functions, etc. */ - inline void SetWrapperClassId(uint16_t class_id); + UniquePersistent Pass() { return UniquePersistent(RValue(this)); } private: - friend class ImplementationUtilities; - friend class ObjectTemplate; + UniquePersistent(UniquePersistent&); + void operator=(UniquePersistent&); }; @@ -433,273 +799,453 @@ template <class T> class Persistent : public Handle<T> { * handle and may deallocate it. The behavior of accessing a handle * for which the handle scope has been deleted is undefined. */ -class V8EXPORT HandleScope { +class V8_EXPORT HandleScope { public: - HandleScope(); + HandleScope(Isolate* isolate); ~HandleScope(); /** - * Closes the handle scope and returns the value as a handle in the - * previous scope, which is the new current scope after the call. - */ - template <class T> Local<T> Close(Handle<T> value); - - /** * Counts the number of allocated handles. */ - static int NumberOfHandles(); + static int NumberOfHandles(Isolate* isolate); - /** - * Creates a new handle with the given value. - */ - static internal::Object** CreateHandle(internal::Object* value); - // Faster version, uses HeapObject to obtain the current Isolate. - static internal::Object** CreateHandle(internal::HeapObject* value); + V8_INLINE Isolate* GetIsolate() const { + return reinterpret_cast<Isolate*>(isolate_); + } + + protected: + V8_INLINE HandleScope() {} + + void Initialize(Isolate* isolate); + + static internal::Object** CreateHandle(internal::Isolate* isolate, + internal::Object* value); private: - // Make it impossible to create heap-allocated or illegal handle - // scopes by disallowing certain operations. + // Uses heap_object to obtain the current Isolate. + static internal::Object** CreateHandle(internal::HeapObject* heap_object, + internal::Object* value); + + // Make it hard to create heap-allocated or illegal handle scopes by + // disallowing certain operations. HandleScope(const HandleScope&); void operator=(const HandleScope&); void* operator new(size_t size); void operator delete(void*, size_t); - // This Data class is accessible internally as HandleScopeData through a - // typedef in the ImplementationUtilities class. - class V8EXPORT Data { - public: - internal::Object** next; - internal::Object** limit; - int level; - inline void Initialize() { - next = limit = NULL; - level = 0; - } - }; - - void Leave(); - internal::Isolate* isolate_; internal::Object** prev_next_; internal::Object** prev_limit_; - // Allow for the active closing of HandleScopes which allows to pass a handle - // from the HandleScope being closed to the next top most HandleScope. - bool is_closed_; - internal::Object** RawClose(internal::Object** value); + // Local::New uses CreateHandle with an Isolate* parameter. + template<class F> 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: + EscapableHandleScope(Isolate* isolate); + V8_INLINE ~EscapableHandleScope() {} + + /** + * Pushes the value into the previous scope and returns a handle to it. + * Cannot be called twice. + */ + template <class T> + V8_INLINE Local<T> Escape(Local<T> value) { + internal::Object** slot = + Escape(reinterpret_cast<internal::Object**>(*value)); + return Local<T>(reinterpret_cast<T*>(slot)); + } + + private: + internal::Object** Escape(internal::Object** escape_value); + + // Make it hard to create heap-allocated or illegal handle scopes by + // disallowing certain operations. + EscapableHandleScope(const EscapableHandleScope&); + void operator=(const EscapableHandleScope&); + void* operator new(size_t size); + void operator delete(void*, size_t); - friend class ImplementationUtilities; + internal::Object** escape_slot_; +}; + + +/** + * A simple Maybe type, representing an object which may or may not have a + * value. + */ +template<class T> +struct Maybe { + Maybe() : has_value(false) {} + explicit Maybe(T t) : has_value(true), value(t) {} + Maybe(bool has, T t) : has_value(has), value(t) {} + + bool has_value; + T value; }; +// Convenience wrapper. +template <class T> +inline Maybe<T> maybe(T t) { + return Maybe<T>(t); +} + + // --- Special objects --- /** * The superclass of values and API object templates. */ -class V8EXPORT Data { +class V8_EXPORT Data { private: Data(); }; /** - * Pre-compilation data that can be associated with a script. This - * data can be calculated for a script in advance of actually - * compiling it, and can be stored between compilations. When script - * data is given to the compile method compilation will be faster. + * The origin, within a file, of a script. */ -class V8EXPORT ScriptData { // NOLINT +class ScriptOrigin { public: - virtual ~ScriptData() { } + V8_INLINE ScriptOrigin( + Handle<Value> resource_name, + Handle<Integer> resource_line_offset = Handle<Integer>(), + Handle<Integer> resource_column_offset = Handle<Integer>(), + Handle<Boolean> resource_is_shared_cross_origin = Handle<Boolean>(), + Handle<Integer> script_id = Handle<Integer>()) + : resource_name_(resource_name), + resource_line_offset_(resource_line_offset), + resource_column_offset_(resource_column_offset), + resource_is_shared_cross_origin_(resource_is_shared_cross_origin), + script_id_(script_id) { } + V8_INLINE Handle<Value> ResourceName() const; + V8_INLINE Handle<Integer> ResourceLineOffset() const; + V8_INLINE Handle<Integer> ResourceColumnOffset() const; + V8_INLINE Handle<Boolean> ResourceIsSharedCrossOrigin() const; + V8_INLINE Handle<Integer> ScriptID() const; + private: + Handle<Value> resource_name_; + Handle<Integer> resource_line_offset_; + Handle<Integer> resource_column_offset_; + Handle<Boolean> resource_is_shared_cross_origin_; + Handle<Integer> script_id_; +}; + +/** + * A compiled JavaScript script, not yet tied to a Context. + */ +class V8_EXPORT UnboundScript { + public: /** - * Pre-compiles the specified script (context-independent). - * - * \param input Pointer to UTF-8 script source code. - * \param length Length of UTF-8 script source code. + * Binds the script to the currently entered context. */ - static ScriptData* PreCompile(const char* input, int length); + Local<Script> BindToCurrentContext(); + + int GetId(); + Handle<Value> GetScriptName(); /** - * Pre-compiles the specified script (context-independent). - * - * NOTE: Pre-compilation using this method cannot happen on another thread - * without using Lockers. - * - * \param source Script source code. + * Data read from magic sourceURL comments. */ - static ScriptData* PreCompile(Handle<String> source); + Handle<Value> GetSourceURL(); + /** + * Data read from magic sourceMappingURL comments. + */ + Handle<Value> GetSourceMappingURL(); /** - * Load previous pre-compilation data. - * - * \param data Pointer to data returned by a call to Data() of a previous - * ScriptData. Ownership is not transferred. - * \param length Length of data. + * Returns zero based line number of the code_pos location in the script. + * -1 will be returned if no information available. */ - static ScriptData* New(const char* data, int length); + int GetLineNumber(int code_pos); + static const int kNoScriptId = 0; +}; + + +/** + * A compiled JavaScript script, tied to a Context which was active when the + * script was compiled. + */ +class V8_EXPORT Script { + public: /** - * Returns the length of Data(). + * A shorthand for ScriptCompiler::Compile(). */ - virtual int Length() = 0; + static Local<Script> Compile(Handle<String> source, + ScriptOrigin* origin = NULL); + + // To be decprecated, use the Compile above. + static Local<Script> Compile(Handle<String> source, + Handle<String> file_name); /** - * Returns a serialized representation of this ScriptData that can later be - * passed to New(). NOTE: Serialized data is platform-dependent. + * Runs the script returning the resulting value. It will be run in the + * context in which it was created (ScriptCompiler::CompileBound or + * UnboundScript::BindToGlobalContext()). */ - virtual const char* Data() = 0; + Local<Value> Run(); /** - * Returns true if the source code could not be parsed. + * Returns the corresponding context-unbound script. */ - virtual bool HasError() = 0; + Local<UnboundScript> GetUnboundScript(); + + V8_DEPRECATED("Use GetUnboundScript()->GetId()", + int GetId()) { + return GetUnboundScript()->GetId(); + } }; /** - * The origin, within a file, of a script. + * For compiling scripts. */ -class ScriptOrigin { +class V8_EXPORT ScriptCompiler { public: - inline ScriptOrigin( - Handle<Value> resource_name, - Handle<Integer> resource_line_offset = Handle<Integer>(), - Handle<Integer> resource_column_offset = Handle<Integer>()) - : resource_name_(resource_name), - resource_line_offset_(resource_line_offset), - resource_column_offset_(resource_column_offset) { } - inline Handle<Value> ResourceName() const; - inline Handle<Integer> ResourceLineOffset() const; - inline Handle<Integer> ResourceColumnOffset() const; - private: - Handle<Value> resource_name_; - Handle<Integer> resource_line_offset_; - Handle<Integer> resource_column_offset_; -}; + /** + * Compilation data that the embedder can cache and pass back to speed up + * future compilations. The data is produced if the CompilerOptions passed to + * the compilation functions in ScriptCompiler contains produce_data_to_cache + * = true. The data to cache can then can be retrieved from + * UnboundScript. + */ + struct V8_EXPORT CachedData { + enum BufferPolicy { + BufferNotOwned, + BufferOwned + }; + + CachedData() : data(NULL), length(0), buffer_policy(BufferNotOwned) {} + + // If buffer_policy is BufferNotOwned, the caller keeps the ownership of + // data and guarantees that it stays alive until the CachedData object is + // destroyed. If the policy is BufferOwned, the given data will be deleted + // (with delete[]) when the CachedData object is destroyed. + CachedData(const uint8_t* data, int length, + BufferPolicy buffer_policy = BufferNotOwned); + ~CachedData(); + // TODO(marja): Async compilation; add constructors which take a callback + // which will be called when V8 no longer needs the data. + const uint8_t* data; + int length; + BufferPolicy buffer_policy; + private: + // Prevent copying. Not implemented. + CachedData(const CachedData&); + CachedData& operator=(const CachedData&); + }; -/** - * A compiled JavaScript script. - */ -class V8EXPORT Script { - public: /** - * Compiles the specified script (context-independent). - * - * \param source Script source code. - * \param origin Script origin, owned by caller, no references are kept - * when New() returns - * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile() - * using pre_data speeds compilation if it's done multiple times. - * Owned by caller, no references are kept when New() returns. - * \param script_data Arbitrary data associated with script. Using - * this has same effect as calling SetData(), but allows data to be - * available to compile event handlers. - * \return Compiled script object (context independent; when run it - * will use the currently entered context). + * Source code which can be then compiled to a UnboundScript or Script. */ - static Local<Script> New(Handle<String> source, - ScriptOrigin* origin = NULL, - ScriptData* pre_data = NULL, - Handle<String> script_data = Handle<String>()); + class Source { + public: + // Source takes ownership of CachedData. + V8_INLINE Source(Local<String> source_string, const ScriptOrigin& origin, + CachedData* cached_data = NULL); + V8_INLINE Source(Local<String> source_string, + CachedData* cached_data = NULL); + V8_INLINE ~Source(); + + // Ownership of the CachedData or its buffers is *not* transferred to the + // caller. The CachedData object is alive as long as the Source object is + // alive. + V8_INLINE const CachedData* GetCachedData() const; + + private: + friend class ScriptCompiler; + // Prevent copying. Not implemented. + Source(const Source&); + Source& operator=(const Source&); + + Local<String> source_string; + + // Origin information + Handle<Value> resource_name; + Handle<Integer> resource_line_offset; + Handle<Integer> resource_column_offset; + Handle<Boolean> resource_is_shared_cross_origin; + + // Cached data from previous compilation (if a kConsume*Cache flag is + // set), or hold newly generated cache data (kProduce*Cache flags) are + // set when calling a compile method. + CachedData* cached_data; + }; /** - * Compiles the specified script using the specified file name - * object (typically a string) as the script's origin. + * For streaming incomplete script data to V8. The embedder should implement a + * subclass of this class. + */ + class ExternalSourceStream { + public: + virtual ~ExternalSourceStream() {} + + /** + * V8 calls this to request the next chunk of data from the embedder. This + * function will be called on a background thread, so it's OK to block and + * wait for the data, if the embedder doesn't have data yet. Returns the + * length of the data returned. When the data ends, GetMoreData should + * return 0. Caller takes ownership of the data. + * + * When streaming UTF-8 data, V8 handles multi-byte characters split between + * two data chunks, but doesn't handle multi-byte characters split between + * more than two data chunks. The embedder can avoid this problem by always + * returning at least 2 bytes of data. + * + * If the embedder wants to cancel the streaming, they should make the next + * GetMoreData call return 0. V8 will interpret it as end of data (and most + * probably, parsing will fail). The streaming task will return as soon as + * V8 has parsed the data it received so far. + */ + virtual size_t GetMoreData(const uint8_t** src) = 0; + }; + + + /** + * Source code which can be streamed into V8 in pieces. It will be parsed + * while streaming. It can be compiled after the streaming is complete. + * StreamedSource must be kept alive while the streaming task is ran (see + * ScriptStreamingTask below). + */ + class V8_EXPORT StreamedSource { + public: + enum Encoding { ONE_BYTE, TWO_BYTE, UTF8 }; + + StreamedSource(ExternalSourceStream* source_stream, Encoding encoding); + ~StreamedSource(); + + // Ownership of the CachedData or its buffers is *not* transferred to the + // caller. The CachedData object is alive as long as the StreamedSource + // object is alive. + const CachedData* GetCachedData() const; + + internal::StreamedSource* impl() const { return impl_; } + + private: + // Prevent copying. Not implemented. + StreamedSource(const StreamedSource&); + StreamedSource& operator=(const StreamedSource&); + + internal::StreamedSource* impl_; + }; + + /** + * A streaming task which the embedder must run on a background thread to + * stream scripts into V8. Returned by ScriptCompiler::StartStreamingScript. + */ + class ScriptStreamingTask { + public: + virtual ~ScriptStreamingTask() {} + virtual void Run() = 0; + }; + + enum CompileOptions { + kNoCompileOptions = 0, + kProduceParserCache, + kConsumeParserCache, + kProduceCodeCache, + kConsumeCodeCache, + + // Support the previous API for a transition period. + kProduceDataToCache + }; + + /** + * Compiles the specified script (context-independent). + * Cached data as part of the source object can be optionally produced to be + * consumed later to speed up compilation of identical source scripts. + * + * Note that when producing cached data, the source must point to NULL for + * cached data. When consuming cached data, the cached data must have been + * produced by the same version of V8. * * \param source Script source code. - * \param file_name file name object (typically a string) to be used - * as the script's origin. - * \return Compiled script object (context independent; when run it - * will use the currently entered context). + * \return Compiled script object (context independent; for running it must be + * bound to a context). */ - static Local<Script> New(Handle<String> source, - Handle<Value> file_name); + static Local<UnboundScript> CompileUnbound( + Isolate* isolate, Source* source, + CompileOptions options = kNoCompileOptions); /** * Compiles the specified script (bound to current context). * * \param source Script source code. - * \param origin Script origin, owned by caller, no references are kept - * when Compile() returns * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile() * using pre_data speeds compilation if it's done multiple times. - * Owned by caller, no references are kept when Compile() returns. - * \param script_data Arbitrary data associated with script. Using - * this has same effect as calling SetData(), but makes data available - * earlier (i.e. to compile event handlers). + * Owned by caller, no references are kept when this function returns. * \return Compiled script object, bound to the context that was active - * when this function was called. When run it will always use this + * when this function was called. When run it will always use this * context. */ - static Local<Script> Compile(Handle<String> source, - ScriptOrigin* origin = NULL, - ScriptData* pre_data = NULL, - Handle<String> script_data = Handle<String>()); + static Local<Script> Compile( + Isolate* isolate, Source* source, + CompileOptions options = kNoCompileOptions); /** - * Compiles the specified script using the specified file name - * object (typically a string) as the script's origin. + * Returns a task which streams script data into V8, or NULL if the script + * cannot be streamed. The user is responsible for running the task on a + * background thread and deleting it. When ran, the task starts parsing the + * script, and it will request data from the StreamedSource as needed. When + * ScriptStreamingTask::Run exits, all data has been streamed and the script + * can be compiled (see Compile below). * - * \param source Script source code. - * \param file_name File name to use as script's origin - * \param script_data Arbitrary data associated with script. Using - * this has same effect as calling SetData(), but makes data available - * earlier (i.e. to compile event handlers). - * \return Compiled script object, bound to the context that was active - * when this function was called. When run it will always use this - * context. + * This API allows to start the streaming with as little data as possible, and + * the remaining data (for example, the ScriptOrigin) is passed to Compile. */ - static Local<Script> Compile(Handle<String> source, - Handle<Value> file_name, - Handle<String> script_data = Handle<String>()); + static ScriptStreamingTask* StartStreamingScript( + Isolate* isolate, StreamedSource* source, + CompileOptions options = kNoCompileOptions); /** - * Runs the script returning the resulting value. If the script is - * context independent (created using ::New) it will be run in the - * currently entered context. If it is context specific (created - * using ::Compile) it will be run in the context in which it was - * compiled. - */ - Local<Value> Run(); - - /** - * Returns the script id value. - */ - Local<Value> Id(); - - /** - * Associate an additional data object with the script. This is mainly used - * with the debugger as this data object is only available through the - * debugger API. + * Compiles a streamed script (bound to current context). + * + * This can only be called after the streaming has finished + * (ScriptStreamingTask has been run). V8 doesn't construct the source string + * during streaming, so the embedder needs to pass the full source here. */ - void SetData(Handle<String> data); + static Local<Script> Compile(Isolate* isolate, StreamedSource* source, + Handle<String> full_source_string, + const ScriptOrigin& origin); }; /** * An error message. */ -class V8EXPORT Message { +class V8_EXPORT Message { public: Local<String> Get() const; Local<String> GetSourceLine() const; /** - * Returns the resource name for the script from where the function causing - * the error originates. + * Returns the origin for the script from where the function causing the + * error originates. */ - Handle<Value> GetScriptResourceName() const; + ScriptOrigin GetScriptOrigin() const; /** - * Returns the resource data for the script from where the function causing + * Returns the resource name for the script from where the function causing * the error originates. */ - Handle<Value> GetScriptData() const; + Handle<Value> GetScriptResourceName() const; /** * Exception stack trace. By default stack traces are not captured for @@ -737,11 +1283,18 @@ class V8EXPORT Message { */ int GetEndColumn() const; + /** + * Passes on the value set by the embedder when it fed the script from which + * this Message was generated to V8. + */ + bool IsSharedCrossOrigin() const; + // TODO(1245381): Print to a string instead of on a FILE. - static void PrintCurrentStackTrace(FILE* out); + static void PrintCurrentStackTrace(Isolate* isolate, FILE* out); static const int kNoLineNumberInfo = 0; static const int kNoColumnInfo = 0; + static const int kNoScriptIdInfo = 0; }; @@ -750,7 +1303,7 @@ class V8EXPORT Message { * snapshot of the execution stack and the information remains valid after * execution continues. */ -class V8EXPORT StackTrace { +class V8_EXPORT StackTrace { public: /** * Flags that determine what information is placed captured for each @@ -764,6 +1317,8 @@ class V8EXPORT StackTrace { kIsEval = 1 << 4, kIsConstructor = 1 << 5, kScriptNameOrSourceURL = 1 << 6, + kScriptId = 1 << 7, + kExposeFramesAcrossSecurityOrigins = 1 << 8, kOverview = kLineNumber | kColumnOffset | kScriptName | kFunctionName, kDetailed = kOverview | kIsEval | kIsConstructor | kScriptNameOrSourceURL }; @@ -791,6 +1346,7 @@ class V8EXPORT StackTrace { * StackFrame. */ static Local<StackTrace> CurrentStackTrace( + Isolate* isolate, int frame_limit, StackTraceOptions options = kOverview); }; @@ -799,7 +1355,7 @@ class V8EXPORT StackTrace { /** * A single JavaScript stack frame. */ -class V8EXPORT StackFrame { +class V8_EXPORT StackFrame { public: /** * Returns the number, 1-based, of the line for the associate function call. @@ -819,6 +1375,14 @@ class V8EXPORT StackFrame { int GetColumn() const; /** + * Returns the id of the script for the function for this StackFrame. + * This method will return Message::kNoScriptIdInfo if it is unable to + * retrieve the script id, or if kScriptId was not passed as an option when + * capturing the StackTrace. + */ + int GetScriptId() const; + + /** * Returns the name of the resource that contains the script for the * function for this StackFrame. */ @@ -827,7 +1391,8 @@ class V8EXPORT StackFrame { /** * Returns the name of the resource that contains the script for the * function for this StackFrame or sourceURL value if the script name - * is undefined and its source ends with //@ sourceURL=... string. + * is undefined and its source ends with //# sourceURL=... string or + * deprecated //@ sourceURL=... string. */ Local<String> GetScriptNameOrSourceURL() const; @@ -850,183 +1415,359 @@ class V8EXPORT StackFrame { }; +/** + * A JSON Parser. + */ +class V8_EXPORT JSON { + public: + /** + * Tries to parse the string |json_string| and returns it as value if + * successful. + * + * \param json_string The string to parse. + * \return The corresponding value if successfully parsed. + */ + static Local<Value> Parse(Local<String> json_string); +}; + + // --- Value --- /** * The superclass of all JavaScript values and objects. */ -class Value : public Data { +class V8_EXPORT Value : public Data { public: /** * Returns true if this value is the undefined value. See ECMA-262 * 4.3.10. */ - V8EXPORT bool IsUndefined() const; + V8_INLINE bool IsUndefined() const; /** * Returns true if this value is the null value. See ECMA-262 * 4.3.11. */ - V8EXPORT bool IsNull() const; + V8_INLINE bool IsNull() const; /** * Returns true if this value is true. */ - V8EXPORT bool IsTrue() const; + bool IsTrue() const; /** * Returns true if this value is false. */ - V8EXPORT bool IsFalse() const; + bool IsFalse() const; + + /** + * Returns true if this value is a symbol or a string. + * This is an experimental feature. + */ + bool IsName() const; /** * Returns true if this value is an instance of the String type. * See ECMA-262 8.4. */ - inline bool IsString() const; + V8_INLINE bool IsString() const; + + /** + * Returns true if this value is a symbol. + * This is an experimental feature. + */ + bool IsSymbol() const; /** * Returns true if this value is a function. */ - V8EXPORT bool IsFunction() const; + bool IsFunction() const; /** * Returns true if this value is an array. */ - V8EXPORT bool IsArray() const; + bool IsArray() const; /** * Returns true if this value is an object. */ - V8EXPORT bool IsObject() const; + bool IsObject() const; /** * Returns true if this value is boolean. */ - V8EXPORT bool IsBoolean() const; + bool IsBoolean() const; /** * Returns true if this value is a number. */ - V8EXPORT bool IsNumber() const; + bool IsNumber() const; /** * Returns true if this value is external. */ - V8EXPORT bool IsExternal() const; + bool IsExternal() const; /** * Returns true if this value is a 32-bit signed integer. */ - V8EXPORT bool IsInt32() const; + bool IsInt32() const; /** * Returns true if this value is a 32-bit unsigned integer. */ - V8EXPORT bool IsUint32() const; + bool IsUint32() const; /** * Returns true if this value is a Date. */ - V8EXPORT bool IsDate() const; + bool IsDate() const; + + /** + * Returns true if this value is an Arguments object. + */ + bool IsArgumentsObject() const; /** * Returns true if this value is a Boolean object. */ - V8EXPORT bool IsBooleanObject() const; + bool IsBooleanObject() const; /** * Returns true if this value is a Number object. */ - V8EXPORT bool IsNumberObject() const; + bool IsNumberObject() const; /** * Returns true if this value is a String object. */ - V8EXPORT bool IsStringObject() const; + bool IsStringObject() const; + + /** + * Returns true if this value is a Symbol object. + * This is an experimental feature. + */ + bool IsSymbolObject() const; /** * Returns true if this value is a NativeError. */ - V8EXPORT bool IsNativeError() const; + bool IsNativeError() const; /** * Returns true if this value is a RegExp. */ - V8EXPORT bool IsRegExp() const; + bool IsRegExp() const; + + /** + * Returns true if this value is a Promise. + * This is an experimental feature. + */ + bool IsPromise() const; - V8EXPORT Local<Boolean> ToBoolean() const; - V8EXPORT Local<Number> ToNumber() const; - V8EXPORT Local<String> ToString() const; - V8EXPORT Local<String> ToDetailString() const; - V8EXPORT Local<Object> ToObject() const; - V8EXPORT Local<Integer> ToInteger() const; - V8EXPORT Local<Uint32> ToUint32() const; - V8EXPORT Local<Int32> ToInt32() const; + /** + * Returns true if this value is a Map. + * This is an experimental feature. + */ + bool IsMap() const; + + /** + * Returns true if this value is a Set. + * This is an experimental feature. + */ + bool IsSet() const; + + /** + * Returns true if this value is a WeakMap. + * This is an experimental feature. + */ + bool IsWeakMap() const; + + /** + * Returns true if this value is a WeakSet. + * This is an experimental feature. + */ + bool IsWeakSet() const; + + /** + * Returns true if this value is an ArrayBuffer. + * This is an experimental feature. + */ + bool IsArrayBuffer() const; + + /** + * Returns true if this value is an ArrayBufferView. + * This is an experimental feature. + */ + bool IsArrayBufferView() const; + + /** + * Returns true if this value is one of TypedArrays. + * This is an experimental feature. + */ + bool IsTypedArray() const; + + /** + * Returns true if this value is an Uint8Array. + * This is an experimental feature. + */ + bool IsUint8Array() const; + + /** + * Returns true if this value is an Uint8ClampedArray. + * This is an experimental feature. + */ + bool IsUint8ClampedArray() const; + + /** + * Returns true if this value is an Int8Array. + * This is an experimental feature. + */ + bool IsInt8Array() const; + + /** + * Returns true if this value is an Uint16Array. + * This is an experimental feature. + */ + bool IsUint16Array() const; + + /** + * Returns true if this value is an Int16Array. + * This is an experimental feature. + */ + bool IsInt16Array() const; + + /** + * Returns true if this value is an Uint32Array. + * This is an experimental feature. + */ + bool IsUint32Array() const; + + /** + * Returns true if this value is an Int32Array. + * This is an experimental feature. + */ + bool IsInt32Array() const; + + /** + * Returns true if this value is a Float32Array. + * This is an experimental feature. + */ + bool IsFloat32Array() const; + + /** + * Returns true if this value is a Float64Array. + * This is an experimental feature. + */ + bool IsFloat64Array() const; + + /** + * Returns true if this value is a DataView. + * This is an experimental feature. + */ + bool IsDataView() const; + + Local<Boolean> ToBoolean() const; + Local<Number> ToNumber() const; + Local<String> ToString() const; + Local<String> ToDetailString() const; + Local<Object> ToObject() const; + Local<Integer> ToInteger() const; + Local<Uint32> ToUint32() const; + Local<Int32> ToInt32() const; /** * Attempts to convert a string to an array index. * Returns an empty handle if the conversion fails. */ - V8EXPORT Local<Uint32> ToArrayIndex() const; + Local<Uint32> ToArrayIndex() const; - V8EXPORT bool BooleanValue() const; - V8EXPORT double NumberValue() const; - V8EXPORT int64_t IntegerValue() const; - V8EXPORT uint32_t Uint32Value() const; - V8EXPORT int32_t Int32Value() const; + bool BooleanValue() const; + double NumberValue() const; + int64_t IntegerValue() const; + uint32_t Uint32Value() const; + int32_t Int32Value() const; /** JS == */ - V8EXPORT bool Equals(Handle<Value> that) const; - V8EXPORT bool StrictEquals(Handle<Value> that) const; + bool Equals(Handle<Value> that) const; + bool StrictEquals(Handle<Value> that) const; + bool SameValue(Handle<Value> that) const; + + template <class T> V8_INLINE static Value* Cast(T* value); private: - inline bool QuickIsString() const; - V8EXPORT bool FullIsString() const; + V8_INLINE bool QuickIsUndefined() const; + V8_INLINE bool QuickIsNull() const; + V8_INLINE bool QuickIsString() const; + bool FullIsUndefined() const; + bool FullIsNull() const; + bool FullIsString() const; }; /** * The superclass of primitive values. See ECMA-262 4.3.2. */ -class Primitive : public Value { }; +class V8_EXPORT Primitive : public Value { }; /** * A primitive boolean value (ECMA-262, 4.3.14). Either the true * or false value. */ -class Boolean : public Primitive { +class V8_EXPORT Boolean : public Primitive { + public: + bool Value() const; + V8_INLINE static Handle<Boolean> New(Isolate* isolate, bool value); +}; + + +/** + * A superclass for symbols and strings. + */ +class V8_EXPORT Name : public Primitive { public: - V8EXPORT bool Value() const; - static inline Handle<Boolean> New(bool value); + V8_INLINE static Name* Cast(v8::Value* obj); + private: + static void CheckCast(v8::Value* obj); }; /** * A JavaScript string value (ECMA-262, 4.3.17). */ -class String : public Primitive { +class V8_EXPORT String : public Name { public: + enum Encoding { + UNKNOWN_ENCODING = 0x1, + TWO_BYTE_ENCODING = 0x0, + ASCII_ENCODING = 0x4, // TODO(yangguo): deprecate this. + ONE_BYTE_ENCODING = 0x4 + }; /** * Returns the number of characters in this string. */ - V8EXPORT int Length() const; + int Length() const; /** * Returns the number of bytes in the UTF-8 encoded * representation of this string. */ - V8EXPORT int Utf8Length() const; + int Utf8Length() const; + + /** + * Returns whether this string is known to contain only one byte data. + * Does not read the string. + * False negatives are possible. + */ + bool IsOneByte() const; /** - * A fast conservative check for non-ASCII characters. May - * return true even for ASCII strings, but if it returns - * false you can be sure that all characters are in the range - * 0-127. + * Returns whether this string contain only one byte data. + * Will read the entire string in some cases. */ - V8EXPORT bool MayContainNonAscii() const; + bool ContainsOnlyOneByte() const; /** * Write the contents of the string to an external buffer. @@ -1056,41 +1797,50 @@ class String : public Primitive { enum WriteOptions { NO_OPTIONS = 0, HINT_MANY_WRITES_EXPECTED = 1, - NO_NULL_TERMINATION = 2 + NO_NULL_TERMINATION = 2, + PRESERVE_ASCII_NULL = 4, // TODO(yangguo): deprecate this. + PRESERVE_ONE_BYTE_NULL = 4, + // Used by WriteUtf8 to replace orphan surrogate code units with the + // unicode replacement character. Needs to be set to guarantee valid UTF-8 + // output. + REPLACE_INVALID_UTF8 = 8 }; // 16-bit character codes. - V8EXPORT int Write(uint16_t* buffer, - int start = 0, - int length = -1, - int options = NO_OPTIONS) const; - // ASCII characters. - V8EXPORT int WriteAscii(char* buffer, - int start = 0, - int length = -1, - int options = NO_OPTIONS) const; + int Write(uint16_t* buffer, + int start = 0, + int length = -1, + int options = NO_OPTIONS) const; + // One byte characters. + int WriteOneByte(uint8_t* buffer, + int start = 0, + int length = -1, + int options = NO_OPTIONS) const; // UTF-8 encoded characters. - V8EXPORT int WriteUtf8(char* buffer, - int length = -1, - int* nchars_ref = NULL, - int options = NO_OPTIONS) const; + int WriteUtf8(char* buffer, + int length = -1, + int* nchars_ref = NULL, + int options = NO_OPTIONS) const; /** * A zero length string. */ - V8EXPORT static v8::Local<v8::String> Empty(); + V8_INLINE static v8::Local<v8::String> Empty(Isolate* isolate); /** * Returns true if the string is external */ - V8EXPORT bool IsExternal() const; + bool IsExternal() const; /** - * Returns true if the string is both external and ASCII + * Returns true if the string is both external and one-byte. */ - V8EXPORT bool IsExternalAscii() const; + bool IsExternalOneByte() const; + + // TODO(yangguo): deprecate this. + bool IsExternalAscii() const { return IsExternalOneByte(); } - class V8EXPORT ExternalStringResourceBase { // NOLINT + class V8_EXPORT ExternalStringResourceBase { // NOLINT public: virtual ~ExternalStringResourceBase() {} @@ -1119,7 +1869,7 @@ class String : public Primitive { * ExternalStringResource to manage the life cycle of the underlying * buffer. Note that the string data must be immutable. */ - class V8EXPORT ExternalStringResource + class V8_EXPORT ExternalStringResource : public ExternalStringResourceBase { public: /** @@ -1143,70 +1893,89 @@ class String : public Primitive { }; /** - * An ExternalAsciiStringResource is a wrapper around an ASCII + * An ExternalOneByteStringResource is a wrapper around an one-byte * string buffer that resides outside V8's heap. Implement an - * ExternalAsciiStringResource to manage the life cycle of the + * ExternalOneByteStringResource to manage the life cycle of the * underlying buffer. Note that the string data must be immutable - * and that the data must be strict (7-bit) ASCII, not Latin-1 or - * UTF-8, which would require special treatment internally in the - * engine and, in the case of UTF-8, do not allow efficient indexing. - * Use String::New or convert to 16 bit data for non-ASCII. + * and that the data must be Latin-1 and not UTF-8, which would require + * special treatment internally in the engine and do not allow efficient + * indexing. Use String::New or convert to 16 bit data for non-Latin1. */ - class V8EXPORT ExternalAsciiStringResource + class V8_EXPORT ExternalOneByteStringResource : public ExternalStringResourceBase { public: /** * Override the destructor to manage the life cycle of the underlying * buffer. */ - virtual ~ExternalAsciiStringResource() {} + virtual ~ExternalOneByteStringResource() {} /** The string data from the underlying buffer.*/ virtual const char* data() const = 0; - /** The number of ASCII characters in the string.*/ + /** The number of Latin-1 characters in the string.*/ virtual size_t length() const = 0; protected: - ExternalAsciiStringResource() {} + ExternalOneByteStringResource() {} }; + typedef ExternalOneByteStringResource ExternalAsciiStringResource; + + /** + * If the string is an external string, return the ExternalStringResourceBase + * regardless of the encoding, otherwise return NULL. The encoding of the + * string is returned in encoding_out. + */ + V8_INLINE ExternalStringResourceBase* GetExternalStringResourceBase( + Encoding* encoding_out) const; + /** * Get the ExternalStringResource for an external string. Returns * NULL if IsExternal() doesn't return true. */ - inline ExternalStringResource* GetExternalStringResource() const; + V8_INLINE ExternalStringResource* GetExternalStringResource() const; /** - * Get the ExternalAsciiStringResource for an external ASCII string. - * Returns NULL if IsExternalAscii() doesn't return true. + * Get the ExternalOneByteStringResource for an external one-byte string. + * Returns NULL if IsExternalOneByte() doesn't return true. */ - V8EXPORT const ExternalAsciiStringResource* GetExternalAsciiStringResource() - const; + const ExternalOneByteStringResource* GetExternalOneByteStringResource() const; + + // TODO(yangguo): deprecate this. + const ExternalAsciiStringResource* GetExternalAsciiStringResource() const { + return GetExternalOneByteStringResource(); + } - static inline String* Cast(v8::Value* obj); + V8_INLINE static String* Cast(v8::Value* obj); - /** - * Allocates a new string from either UTF-8 encoded or ASCII data. - * The second parameter 'length' gives the buffer length. - * If the data is UTF-8 encoded, the caller must - * be careful to supply the length parameter. - * If it is not given, the function calls - * 'strlen' to determine the buffer length, it might be - * wrong if 'data' contains a null character. - */ - V8EXPORT static Local<String> New(const char* data, int length = -1); + enum NewStringType { + kNormalString, kInternalizedString, kUndetectableString + }; - /** Allocates a new string from 16-bit character codes.*/ - V8EXPORT static Local<String> New(const uint16_t* data, int length = -1); + /** Allocates a new string from UTF-8 data.*/ + static Local<String> NewFromUtf8(Isolate* isolate, + const char* data, + NewStringType type = kNormalString, + int length = -1); - /** Creates a symbol. Returns one if it exists already.*/ - V8EXPORT static Local<String> NewSymbol(const char* data, int length = -1); + /** Allocates a new string from Latin-1 data.*/ + static Local<String> NewFromOneByte( + Isolate* isolate, + const uint8_t* data, + NewStringType type = kNormalString, + int length = -1); + + /** Allocates a new string from UTF-16 data.*/ + static Local<String> NewFromTwoByte( + Isolate* isolate, + const uint16_t* data, + NewStringType type = kNormalString, + int length = -1); /** * Creates a new string by concatenating the left and the right strings * passed in as parameters. */ - V8EXPORT static Local<String> Concat(Handle<String> left, - Handle<String> right); + static Local<String> Concat(Handle<String> left, Handle<String> right); /** * Creates a new external string using the data defined in the given @@ -1216,7 +1985,8 @@ class String : public Primitive { * should the underlying buffer be deallocated or modified except through the * destructor of the external string resource. */ - V8EXPORT static Local<String> NewExternal(ExternalStringResource* resource); + static Local<String> NewExternal(Isolate* isolate, + ExternalStringResource* resource); /** * Associate an external string resource with this string by transforming it @@ -1227,18 +1997,18 @@ class String : public Primitive { * The string is not modified if the operation fails. See NewExternal for * information on the lifetime of the resource. */ - V8EXPORT bool MakeExternal(ExternalStringResource* resource); + bool MakeExternal(ExternalStringResource* resource); /** - * Creates a new external string using the ASCII data defined in the given + * Creates a new external string using the one-byte data defined in the given * resource. When the external string is no longer live on V8's heap the * resource will be disposed by calling its Dispose method. The caller of * this function should not otherwise delete or modify the resource. Neither * should the underlying buffer be deallocated or modified except through the * destructor of the external string resource. */ - V8EXPORT static Local<String> NewExternal( - ExternalAsciiStringResource* resource); + static Local<String> NewExternal(Isolate* isolate, + ExternalOneByteStringResource* resource); /** * Associate an external string resource with this string by transforming it @@ -1249,20 +2019,12 @@ class String : public Primitive { * The string is not modified if the operation fails. See NewExternal for * information on the lifetime of the resource. */ - V8EXPORT bool MakeExternal(ExternalAsciiStringResource* resource); + bool MakeExternal(ExternalOneByteStringResource* resource); /** * Returns true if this string can be made external. */ - V8EXPORT bool CanMakeExternal(); - - /** Creates an undetectable string from the supplied ASCII or UTF-8 data.*/ - V8EXPORT static Local<String> NewUndetectable(const char* data, - int length = -1); - - /** Creates an undetectable string from the supplied 16-bit character codes.*/ - V8EXPORT static Local<String> NewUndetectable(const uint16_t* data, - int length = -1); + bool CanMakeExternal(); /** * Converts an object to a UTF-8-encoded character array. Useful if @@ -1271,7 +2033,7 @@ class String : public Primitive { * then the length() method returns 0 and the * operator returns * NULL. */ - class V8EXPORT Utf8Value { + class V8_EXPORT Utf8Value { public: explicit Utf8Value(Handle<v8::Value> obj); ~Utf8Value(); @@ -1288,35 +2050,12 @@ class String : public Primitive { }; /** - * Converts an object to an ASCII string. - * Useful if you want to print the object. - * If conversion to a string fails (eg. due to an exception in the toString() - * method of the object) then the length() method returns 0 and the * operator - * returns NULL. - */ - class V8EXPORT AsciiValue { - public: - explicit AsciiValue(Handle<v8::Value> obj); - ~AsciiValue(); - char* operator*() { return str_; } - const char* operator*() const { return str_; } - int length() const { return length_; } - private: - char* str_; - int length_; - - // Disallow copying and assigning. - AsciiValue(const AsciiValue&); - void operator=(const AsciiValue&); - }; - - /** * Converts an object to a two-byte string. * If conversion to a string fails (eg. due to an exception in the toString() * method of the object) then the length() method returns 0 and the * operator * returns NULL. */ - class V8EXPORT Value { + class V8_EXPORT Value { public: explicit Value(Handle<v8::Value> obj); ~Value(); @@ -1333,59 +2072,126 @@ class String : public Primitive { }; private: - V8EXPORT void VerifyExternalStringResource(ExternalStringResource* val) const; - V8EXPORT static void CheckCast(v8::Value* obj); + void VerifyExternalStringResourceBase(ExternalStringResourceBase* v, + Encoding encoding) const; + void VerifyExternalStringResource(ExternalStringResource* val) const; + static void CheckCast(v8::Value* obj); +}; + + +/** + * A JavaScript symbol (ECMA-262 edition 6) + * + * This is an experimental feature. Use at your own risk. + */ +class V8_EXPORT Symbol : public Name { + public: + // Returns the print name string of the symbol, or undefined if none. + Local<Value> Name() const; + + // Create a symbol. If name is not empty, it will be used as the description. + static Local<Symbol> New( + Isolate *isolate, Local<String> name = Local<String>()); + + // Access global symbol registry. + // Note that symbols created this way are never collected, so + // they should only be used for statically fixed properties. + // Also, there is only one global name space for the names used as keys. + // To minimize the potential for clashes, use qualified names as keys. + static Local<Symbol> For(Isolate *isolate, Local<String> name); + + // Retrieve a global symbol. Similar to |For|, but using a separate + // registry that is not accessible by (and cannot clash with) JavaScript code. + static Local<Symbol> ForApi(Isolate *isolate, Local<String> name); + + // Well-known symbols + static Local<Symbol> GetIterator(Isolate* isolate); + static Local<Symbol> GetUnscopables(Isolate* isolate); + + V8_INLINE static Symbol* Cast(v8::Value* obj); + + private: + Symbol(); + static void CheckCast(v8::Value* obj); +}; + + +/** + * A private symbol + * + * This is an experimental feature. Use at your own risk. + */ +class V8_EXPORT Private : public Data { + public: + // Returns the print name string of the private symbol, or undefined if none. + Local<Value> Name() const; + + // Create a private symbol. If name is not empty, it will be the description. + static Local<Private> New( + Isolate *isolate, Local<String> name = Local<String>()); + + // Retrieve a global private symbol. If a symbol with this name has not + // been retrieved in the same isolate before, it is created. + // Note that private symbols created this way are never collected, so + // they should only be used for statically fixed properties. + // Also, there is only one global name space for the names used as keys. + // To minimize the potential for clashes, use qualified names as keys, + // e.g., "Class#property". + static Local<Private> ForApi(Isolate *isolate, Local<String> name); + + private: + Private(); }; /** * A JavaScript number value (ECMA-262, 4.3.20) */ -class Number : public Primitive { +class V8_EXPORT Number : public Primitive { public: - V8EXPORT double Value() const; - V8EXPORT static Local<Number> New(double value); - static inline Number* Cast(v8::Value* obj); + double Value() const; + static Local<Number> New(Isolate* isolate, double value); + V8_INLINE static Number* Cast(v8::Value* obj); private: - V8EXPORT Number(); - V8EXPORT static void CheckCast(v8::Value* obj); + Number(); + static void CheckCast(v8::Value* obj); }; /** * A JavaScript value representing a signed integer. */ -class Integer : public Number { +class V8_EXPORT Integer : public Number { public: - V8EXPORT static Local<Integer> New(int32_t value); - V8EXPORT static Local<Integer> NewFromUnsigned(uint32_t value); - V8EXPORT int64_t Value() const; - static inline Integer* Cast(v8::Value* obj); + static Local<Integer> New(Isolate* isolate, int32_t value); + static Local<Integer> NewFromUnsigned(Isolate* isolate, uint32_t value); + int64_t Value() const; + V8_INLINE static Integer* Cast(v8::Value* obj); private: - V8EXPORT Integer(); - V8EXPORT static void CheckCast(v8::Value* obj); + Integer(); + static void CheckCast(v8::Value* obj); }; /** * A JavaScript value representing a 32-bit signed integer. */ -class Int32 : public Integer { +class V8_EXPORT Int32 : public Integer { public: - V8EXPORT int32_t Value() const; + int32_t Value() const; private: - V8EXPORT Int32(); + Int32(); }; /** * A JavaScript value representing a 32-bit unsigned integer. */ -class Uint32 : public Integer { +class V8_EXPORT Uint32 : public Integer { public: - V8EXPORT uint32_t Value() const; + uint32_t Value() const; private: - V8EXPORT Uint32(); + Uint32(); }; @@ -1397,15 +2203,26 @@ enum PropertyAttribute { }; enum ExternalArrayType { - kExternalByteArray = 1, - kExternalUnsignedByteArray, - kExternalShortArray, - kExternalUnsignedShortArray, - kExternalIntArray, - kExternalUnsignedIntArray, - kExternalFloatArray, - kExternalDoubleArray, - kExternalPixelArray + kExternalInt8Array = 1, + kExternalUint8Array, + kExternalInt16Array, + kExternalUint16Array, + kExternalInt32Array, + kExternalUint32Array, + kExternalFloat32Array, + kExternalFloat64Array, + kExternalUint8ClampedArray, + + // Legacy constant names + kExternalByteArray = kExternalInt8Array, + kExternalUnsignedByteArray = kExternalUint8Array, + kExternalShortArray = kExternalInt16Array, + kExternalUnsignedShortArray = kExternalUint16Array, + kExternalIntArray = kExternalInt32Array, + kExternalUnsignedIntArray = kExternalUint32Array, + kExternalFloatArray = kExternalFloat32Array, + kExternalDoubleArray = kExternalFloat64Array, + kExternalPixelArray = kExternalUint8ClampedArray }; /** @@ -1413,13 +2230,22 @@ enum ExternalArrayType { * setting|getting a particular property. See Object and ObjectTemplate's * method SetAccessor. */ -typedef Handle<Value> (*AccessorGetter)(Local<String> property, - const AccessorInfo& info); +typedef void (*AccessorGetterCallback)( + Local<String> property, + const PropertyCallbackInfo<Value>& info); +typedef void (*AccessorNameGetterCallback)( + Local<Name> property, + const PropertyCallbackInfo<Value>& info); -typedef void (*AccessorSetter)(Local<String> property, - Local<Value> value, - const AccessorInfo& info); +typedef void (*AccessorSetterCallback)( + Local<String> property, + Local<Value> value, + const PropertyCallbackInfo<void>& info); +typedef void (*AccessorNameSetterCallback)( + Local<Name> property, + Local<Value> value, + const PropertyCallbackInfo<void>& info); /** @@ -1429,11 +2255,7 @@ typedef void (*AccessorSetter)(Local<String> property, * accessors have an explicit access control parameter which specifies * the kind of cross-context access that should be allowed. * - * Additionally, for security, accessors can prohibit overwriting by - * accessors defined in JavaScript. For objects that have such - * accessors either locally or in their prototype chain it is not - * possible to overwrite the accessor by using __defineGetter__ or - * __defineSetter__ from JavaScript code. + * TODO(dcarney): Remove PROHIBITS_OVERWRITING as it is now unused. */ enum AccessControl { DEFAULT = 0, @@ -1446,16 +2268,13 @@ enum AccessControl { /** * A JavaScript object (ECMA-262, 4.3.3) */ -class Object : public Value { +class V8_EXPORT Object : public Value { public: - V8EXPORT bool Set(Handle<Value> key, - Handle<Value> value, - PropertyAttribute attribs = None); + bool Set(Handle<Value> key, Handle<Value> value); - V8EXPORT bool Set(uint32_t index, - Handle<Value> value); + bool Set(uint32_t index, Handle<Value> value); - // Sets a local property on this object bypassing interceptors and + // Sets an own property on this object bypassing interceptors and // overriding accessors or read-only properties. // // Note that if the object has an interceptor the property will be set @@ -1463,41 +2282,73 @@ class Object : public Value { // will only be returned if the interceptor doesn't return a value. // // Note also that this only works for named properties. - V8EXPORT bool ForceSet(Handle<Value> key, - Handle<Value> value, - PropertyAttribute attribs = None); + bool ForceSet(Handle<Value> key, + Handle<Value> value, + PropertyAttribute attribs = None); - V8EXPORT Local<Value> Get(Handle<Value> key); + Local<Value> Get(Handle<Value> key); - V8EXPORT Local<Value> Get(uint32_t index); + Local<Value> Get(uint32_t index); /** * Gets the property attributes of a property which can be None or * any combination of ReadOnly, DontEnum and DontDelete. Returns * None when the property doesn't exist. */ - V8EXPORT PropertyAttribute GetPropertyAttributes(Handle<Value> key); + PropertyAttribute GetPropertyAttributes(Handle<Value> key); + + /** + * Returns Object.getOwnPropertyDescriptor as per ES5 section 15.2.3.3. + */ + Local<Value> GetOwnPropertyDescriptor(Local<String> key); - // TODO(1245389): Replace the type-specific versions of these - // functions with generic ones that accept a Handle<Value> key. - V8EXPORT bool Has(Handle<String> key); + bool Has(Handle<Value> key); - V8EXPORT bool Delete(Handle<String> key); + bool Delete(Handle<Value> key); // Delete a property on this object bypassing interceptors and // ignoring dont-delete attributes. - V8EXPORT bool ForceDelete(Handle<Value> key); + bool ForceDelete(Handle<Value> key); - V8EXPORT bool Has(uint32_t index); + bool Has(uint32_t index); - V8EXPORT bool Delete(uint32_t index); + bool Delete(uint32_t index); + + bool SetAccessor(Handle<String> name, + AccessorGetterCallback getter, + AccessorSetterCallback setter = 0, + Handle<Value> data = Handle<Value>(), + AccessControl settings = DEFAULT, + PropertyAttribute attribute = None); + bool SetAccessor(Handle<Name> name, + AccessorNameGetterCallback getter, + AccessorNameSetterCallback setter = 0, + Handle<Value> data = Handle<Value>(), + AccessControl settings = DEFAULT, + PropertyAttribute attribute = None); - V8EXPORT bool SetAccessor(Handle<String> name, - AccessorGetter getter, - AccessorSetter setter = 0, - Handle<Value> data = Handle<Value>(), - AccessControl settings = DEFAULT, - PropertyAttribute attribute = None); + // This function is not yet stable and should not be used at this time. + bool SetDeclaredAccessor(Local<Name> name, + Local<DeclaredAccessorDescriptor> descriptor, + PropertyAttribute attribute = None, + AccessControl settings = DEFAULT); + + void SetAccessorProperty(Local<Name> name, + Local<Function> getter, + Handle<Function> setter = Handle<Function>(), + PropertyAttribute attribute = None, + AccessControl settings = DEFAULT); + + /** + * Functionality for private properties. + * This is an experimental feature, use at your own risk. + * Note: Private properties are inherited. Do not rely on this, since it may + * change. + */ + bool HasPrivate(Handle<Private> key); + bool SetPrivate(Handle<Private> key, Handle<Value> value); + bool DeletePrivate(Handle<Private> key); + Local<Value> GetPrivate(Handle<Private> key); /** * Returns an array containing the names of the enumerable properties @@ -1505,93 +2356,113 @@ class Object : public Value { * array returned by this method contains the same values as would * be enumerated by a for-in statement over this object. */ - V8EXPORT Local<Array> GetPropertyNames(); + Local<Array> GetPropertyNames(); /** * This function has the same functionality as GetPropertyNames but * the returned array doesn't contain the names of properties from * prototype objects. */ - V8EXPORT Local<Array> GetOwnPropertyNames(); + Local<Array> GetOwnPropertyNames(); /** * Get the prototype object. This does not skip objects marked to * be skipped by __proto__ and it does not consult the security * handler. */ - V8EXPORT Local<Value> GetPrototype(); + Local<Value> GetPrototype(); /** * Set the prototype object. This does not skip objects marked to * be skipped by __proto__ and it does not consult the security * handler. */ - V8EXPORT bool SetPrototype(Handle<Value> prototype); + bool SetPrototype(Handle<Value> prototype); /** * Finds an instance of the given function template in the prototype * chain. */ - V8EXPORT Local<Object> FindInstanceInPrototypeChain( - Handle<FunctionTemplate> tmpl); + Local<Object> FindInstanceInPrototypeChain(Handle<FunctionTemplate> tmpl); /** * Call builtin Object.prototype.toString on this object. * This is different from Value::ToString() that may call * user-defined toString function. This one does not. */ - V8EXPORT Local<String> ObjectProtoToString(); + Local<String> ObjectProtoToString(); /** * Returns the name of the function invoked as a constructor for this object. */ - V8EXPORT Local<String> GetConstructorName(); + Local<String> GetConstructorName(); /** Gets the number of internal fields for this Object. */ - V8EXPORT int InternalFieldCount(); - /** Gets the value in an internal field. */ - inline Local<Value> GetInternalField(int index); + int InternalFieldCount(); + + /** Same as above, but works for Persistents */ + V8_INLINE static int InternalFieldCount( + const PersistentBase<Object>& object) { + return object.val_->InternalFieldCount(); + } + + /** Gets the value from an internal field. */ + V8_INLINE Local<Value> GetInternalField(int index); + /** Sets the value in an internal field. */ - V8EXPORT void SetInternalField(int index, Handle<Value> value); + void SetInternalField(int index, Handle<Value> value); - /** Gets a native pointer from an internal field. */ - inline void* GetPointerFromInternalField(int index); + /** + * Gets a 2-byte-aligned native pointer from an internal field. This field + * must have been set by SetAlignedPointerInInternalField, everything else + * leads to undefined behavior. + */ + V8_INLINE void* GetAlignedPointerFromInternalField(int index); - /** Sets a native pointer in an internal field. */ - V8EXPORT void SetPointerInInternalField(int index, void* value); + /** Same as above, but works for Persistents */ + V8_INLINE static void* GetAlignedPointerFromInternalField( + const PersistentBase<Object>& object, int index) { + return object.val_->GetAlignedPointerFromInternalField(index); + } + + /** + * Sets a 2-byte-aligned native pointer in an internal field. To retrieve such + * a field, GetAlignedPointerFromInternalField must be used, everything else + * leads to undefined behavior. + */ + void SetAlignedPointerInInternalField(int index, void* value); // Testers for local properties. - V8EXPORT bool HasOwnProperty(Handle<String> key); - V8EXPORT bool HasRealNamedProperty(Handle<String> key); - V8EXPORT bool HasRealIndexedProperty(uint32_t index); - V8EXPORT bool HasRealNamedCallbackProperty(Handle<String> key); + bool HasOwnProperty(Handle<String> key); + bool HasRealNamedProperty(Handle<String> key); + bool HasRealIndexedProperty(uint32_t index); + bool HasRealNamedCallbackProperty(Handle<String> key); /** * If result.IsEmpty() no real property was located in the prototype chain. * This means interceptors in the prototype chain are not called. */ - V8EXPORT Local<Value> GetRealNamedPropertyInPrototypeChain( - Handle<String> key); + Local<Value> GetRealNamedPropertyInPrototypeChain(Handle<String> key); /** * If result.IsEmpty() no real property was located on the object or * in the prototype chain. * This means interceptors in the prototype chain are not called. */ - V8EXPORT Local<Value> GetRealNamedProperty(Handle<String> key); + Local<Value> GetRealNamedProperty(Handle<String> key); /** Tests for a named lookup interceptor.*/ - V8EXPORT bool HasNamedLookupInterceptor(); + bool HasNamedLookupInterceptor(); /** Tests for an index lookup interceptor.*/ - V8EXPORT bool HasIndexedLookupInterceptor(); + bool HasIndexedLookupInterceptor(); /** * Turns on access check on the object if the object is an instance of * a template that has access check callbacks. If an object has no * access check info, the object cannot be accessed by anyone. */ - V8EXPORT void TurnOnAccessCheck(); + void TurnOnAccessCheck(); /** * Returns the identity hash for this object. The current implementation @@ -1600,7 +2471,7 @@ class Object : public Value { * The return value will never be 0. Also, it is not guaranteed to be * unique. */ - V8EXPORT int GetIdentityHash(); + int GetIdentityHash(); /** * Access hidden properties on JavaScript objects. These properties are @@ -1608,9 +2479,9 @@ class Object : public Value { * C++ API. Hidden properties introduced by V8 internally (for example the * identity hash) are prefixed with "v8::". */ - V8EXPORT bool SetHiddenValue(Handle<String> key, Handle<Value> value); - V8EXPORT Local<Value> GetHiddenValue(Handle<String> key); - V8EXPORT bool DeleteHiddenValue(Handle<String> key); + bool SetHiddenValue(Handle<String> key, Handle<Value> value); + Local<Value> GetHiddenValue(Handle<String> key); + bool DeleteHiddenValue(Handle<String> key); /** * Returns true if this is an instance of an api function (one @@ -1619,18 +2490,18 @@ class Object : public Value { * conservative and may return true for objects that haven't actually * been modified. */ - V8EXPORT bool IsDirty(); + bool IsDirty(); /** * Clone this object with a fast but shallow copy. Values will point * to the same values as the original object. */ - V8EXPORT Local<Object> Clone(); + Local<Object> Clone(); /** * Returns the context in which the object was created. */ - V8EXPORT Local<Context> CreationContext(); + Local<Context> CreationContext(); /** * Set the backing store of the indexed properties to be managed by the @@ -1639,10 +2510,10 @@ class Object : public Value { * Note: The embedding program still owns the data and needs to ensure that * the backing store is preserved while V8 has a reference. */ - V8EXPORT void SetIndexedPropertiesToPixelData(uint8_t* data, int length); - V8EXPORT bool HasIndexedPropertiesInPixelData(); - V8EXPORT uint8_t* GetIndexedPropertiesPixelData(); - V8EXPORT int GetIndexedPropertiesPixelDataLength(); + void SetIndexedPropertiesToPixelData(uint8_t* data, int length); + bool HasIndexedPropertiesInPixelData(); + uint8_t* GetIndexedPropertiesPixelData(); + int GetIndexedPropertiesPixelDataLength(); /** * Set the backing store of the indexed properties to be managed by the @@ -1651,93 +2522,208 @@ class Object : public Value { * Note: The embedding program still owns the data and needs to ensure that * the backing store is preserved while V8 has a reference. */ - V8EXPORT void SetIndexedPropertiesToExternalArrayData( - void* data, - ExternalArrayType array_type, - int number_of_elements); - V8EXPORT bool HasIndexedPropertiesInExternalArrayData(); - V8EXPORT void* GetIndexedPropertiesExternalArrayData(); - V8EXPORT ExternalArrayType GetIndexedPropertiesExternalArrayDataType(); - V8EXPORT int GetIndexedPropertiesExternalArrayDataLength(); + void SetIndexedPropertiesToExternalArrayData(void* data, + ExternalArrayType array_type, + int number_of_elements); + bool HasIndexedPropertiesInExternalArrayData(); + void* GetIndexedPropertiesExternalArrayData(); + ExternalArrayType GetIndexedPropertiesExternalArrayDataType(); + int GetIndexedPropertiesExternalArrayDataLength(); /** * Checks whether a callback is set by the * ObjectTemplate::SetCallAsFunctionHandler method. * When an Object is callable this method returns true. */ - V8EXPORT bool IsCallable(); + bool IsCallable(); /** * Call an Object as a function if a callback is set by the * ObjectTemplate::SetCallAsFunctionHandler method. */ - V8EXPORT Local<Value> CallAsFunction(Handle<Object> recv, - int argc, - Handle<Value> argv[]); + Local<Value> CallAsFunction(Handle<Value> recv, + int argc, + Handle<Value> argv[]); /** * Call an Object as a constructor if a callback is set by the * ObjectTemplate::SetCallAsFunctionHandler method. * Note: This method behaves like the Function::NewInstance method. */ - V8EXPORT Local<Value> CallAsConstructor(int argc, - Handle<Value> argv[]); + Local<Value> CallAsConstructor(int argc, Handle<Value> argv[]); - V8EXPORT static Local<Object> New(); - static inline Object* Cast(Value* obj); + static Local<Object> New(Isolate* isolate); - private: - V8EXPORT Object(); - V8EXPORT static void CheckCast(Value* obj); - V8EXPORT Local<Value> CheckedGetInternalField(int index); - V8EXPORT void* SlowGetPointerFromInternalField(int index); + V8_INLINE static Object* Cast(Value* obj); - /** - * If quick access to the internal field is possible this method - * returns the value. Otherwise an empty handle is returned. - */ - inline Local<Value> UncheckedGetInternalField(int index); + private: + Object(); + static void CheckCast(Value* obj); + Local<Value> SlowGetInternalField(int index); + void* SlowGetAlignedPointerFromInternalField(int index); }; /** * An instance of the built-in array constructor (ECMA-262, 15.4.2). */ -class Array : public Object { +class V8_EXPORT Array : public Object { public: - V8EXPORT uint32_t Length() const; + uint32_t Length() const; /** * Clones an element at index |index|. Returns an empty * handle if cloning fails (for any reason). */ - V8EXPORT Local<Object> CloneElementAt(uint32_t index); + Local<Object> CloneElementAt(uint32_t index); /** * Creates a JavaScript array with the given length. If the length * is negative the returned array will have length 0. */ - V8EXPORT static Local<Array> New(int length = 0); + static Local<Array> New(Isolate* isolate, int length = 0); + + V8_INLINE static Array* Cast(Value* obj); + private: + Array(); + static void CheckCast(Value* obj); +}; + + +template<typename T> +class ReturnValue { + public: + template <class S> V8_INLINE ReturnValue(const ReturnValue<S>& that) + : value_(that.value_) { + TYPE_CHECK(T, S); + } + // Handle setters + template <typename S> V8_INLINE void Set(const Persistent<S>& handle); + template <typename S> V8_INLINE void Set(const Handle<S> handle); + // Fast primitive setters + V8_INLINE void Set(bool value); + V8_INLINE void Set(double i); + V8_INLINE void Set(int32_t i); + V8_INLINE void Set(uint32_t i); + // Fast JS primitive setters + V8_INLINE void SetNull(); + V8_INLINE void SetUndefined(); + V8_INLINE void SetEmptyString(); + // Convenience getter for Isolate + V8_INLINE Isolate* GetIsolate(); + + // Pointer setter: Uncompilable to prevent inadvertent misuse. + template <typename S> + V8_INLINE void Set(S* whatever); - static inline Array* Cast(Value* obj); private: - V8EXPORT Array(); - V8EXPORT static void CheckCast(Value* obj); + template<class F> friend class ReturnValue; + template<class F> friend class FunctionCallbackInfo; + template<class F> friend class PropertyCallbackInfo; + template<class F, class G, class H> friend class PersistentValueMap; + V8_INLINE void SetInternal(internal::Object* value) { *value_ = value; } + V8_INLINE internal::Object* GetDefaultValue(); + V8_INLINE explicit ReturnValue(internal::Object** slot); + internal::Object** value_; }; /** + * The argument information given to function call callbacks. This + * class provides access to information about the context of the call, + * including the receiver, the number and values of arguments, and + * the holder of the function. + */ +template<typename T> +class FunctionCallbackInfo { + public: + V8_INLINE int Length() const; + V8_INLINE Local<Value> operator[](int i) const; + V8_INLINE Local<Function> Callee() const; + V8_INLINE Local<Object> This() const; + V8_INLINE Local<Object> Holder() const; + V8_INLINE bool IsConstructCall() const; + V8_INLINE Local<Value> Data() const; + V8_INLINE Isolate* GetIsolate() const; + V8_INLINE ReturnValue<T> GetReturnValue() const; + // This shouldn't be public, but the arm compiler needs it. + static const int kArgsLength = 7; + + protected: + friend class internal::FunctionCallbackArguments; + friend class internal::CustomArguments<FunctionCallbackInfo>; + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kCalleeIndex = 5; + static const int kContextSaveIndex = 6; + + V8_INLINE FunctionCallbackInfo(internal::Object** implicit_args, + internal::Object** values, + int length, + bool is_construct_call); + internal::Object** implicit_args_; + internal::Object** values_; + int length_; + bool is_construct_call_; +}; + + +/** + * The information passed to a property callback about the context + * of the property access. + */ +template<typename T> +class PropertyCallbackInfo { + public: + V8_INLINE Isolate* GetIsolate() const; + V8_INLINE Local<Value> Data() const; + V8_INLINE Local<Object> This() const; + V8_INLINE Local<Object> Holder() const; + V8_INLINE ReturnValue<T> GetReturnValue() const; + // This shouldn't be public, but the arm compiler needs it. + static const int kArgsLength = 6; + + protected: + friend class MacroAssembler; + friend class internal::PropertyCallbackArguments; + friend class internal::CustomArguments<PropertyCallbackInfo>; + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kThisIndex = 5; + + V8_INLINE PropertyCallbackInfo(internal::Object** args) : args_(args) {} + internal::Object** args_; +}; + + +typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info); + + +/** * A JavaScript function object (ECMA-262, 15.3). */ -class Function : public Object { +class V8_EXPORT Function : public Object { public: - V8EXPORT Local<Object> NewInstance() const; - V8EXPORT Local<Object> NewInstance(int argc, Handle<Value> argv[]) const; - V8EXPORT Local<Value> Call(Handle<Object> recv, - int argc, - Handle<Value> argv[]); - V8EXPORT void SetName(Handle<String> name); - V8EXPORT Handle<Value> GetName() const; + /** + * Create a function in the current execution context + * for a given FunctionCallback. + */ + static Local<Function> New(Isolate* isolate, + FunctionCallback callback, + Local<Value> data = Local<Value>(), + int length = 0); + + Local<Object> NewInstance() const; + Local<Object> NewInstance(int argc, Handle<Value> argv[]) const; + Local<Value> Call(Handle<Value> recv, int argc, Handle<Value> argv[]); + void SetName(Handle<String> name); + Handle<Value> GetName() const; /** * Name inferred from variable or property assignment of this function. @@ -1745,43 +2731,455 @@ class Function : public Object { * in an OO style, where many functions are anonymous but are assigned * to object properties. */ - V8EXPORT Handle<Value> GetInferredName() const; + Handle<Value> GetInferredName() const; + + /** + * User-defined name assigned to the "displayName" property of this function. + * Used to facilitate debugging and profiling of JavaScript code. + */ + Handle<Value> GetDisplayName() const; /** * Returns zero based line number of function body and * kLineOffsetNotFound if no information available. */ - V8EXPORT int GetScriptLineNumber() const; + int GetScriptLineNumber() const; /** * Returns zero based column number of function body and * kLineOffsetNotFound if no information available. */ - V8EXPORT int GetScriptColumnNumber() const; - V8EXPORT Handle<Value> GetScriptId() const; - V8EXPORT ScriptOrigin GetScriptOrigin() const; - static inline Function* Cast(Value* obj); - V8EXPORT static const int kLineOffsetNotFound; + int GetScriptColumnNumber() const; + + /** + * Tells whether this function is builtin. + */ + bool IsBuiltin() const; + + /** + * Returns scriptId. + */ + int ScriptId() const; + + /** + * Returns the original function if this function is bound, else returns + * v8::Undefined. + */ + Local<Value> GetBoundFunction() const; + + ScriptOrigin GetScriptOrigin() const; + V8_INLINE static Function* Cast(Value* obj); + static const int kLineOffsetNotFound; + + private: + Function(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of the built-in Promise constructor (ES6 draft). + * This API is experimental. Only works with --harmony flag. + */ +class V8_EXPORT Promise : public Object { + public: + class V8_EXPORT Resolver : public Object { + public: + /** + * Create a new resolver, along with an associated promise in pending state. + */ + static Local<Resolver> New(Isolate* isolate); + + /** + * Extract the associated promise. + */ + Local<Promise> GetPromise(); + + /** + * Resolve/reject the associated promise with a given value. + * Ignored if the promise is no longer pending. + */ + void Resolve(Handle<Value> value); + void Reject(Handle<Value> value); + + V8_INLINE static Resolver* Cast(Value* obj); + + private: + Resolver(); + static void CheckCast(Value* obj); + }; + + /** + * Register a resolution/rejection handler with a promise. + * The handler is given the respective resolution/rejection value as + * an argument. If the promise is already resolved/rejected, the handler is + * invoked at the end of turn. + */ + Local<Promise> Chain(Handle<Function> handler); + Local<Promise> Catch(Handle<Function> handler); + Local<Promise> Then(Handle<Function> handler); + + V8_INLINE static Promise* Cast(Value* obj); private: - V8EXPORT Function(); - V8EXPORT static void CheckCast(Value* obj); + Promise(); + static void CheckCast(Value* obj); +}; + + +#ifndef V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT +// The number of required internal fields can be defined by embedder. +#define V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT 2 +#endif + +/** + * An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5). + * This API is experimental and may change significantly. + */ +class V8_EXPORT ArrayBuffer : public Object { + public: + /** + * Allocator that V8 uses to allocate |ArrayBuffer|'s memory. + * The allocator is a global V8 setting. It should be set with + * V8::SetArrayBufferAllocator prior to creation of a first ArrayBuffer. + * + * This API is experimental and may change significantly. + */ + class V8_EXPORT Allocator { // NOLINT + public: + virtual ~Allocator() {} + + /** + * Allocate |length| bytes. Return NULL if allocation is not successful. + * Memory should be initialized to zeroes. + */ + virtual void* Allocate(size_t length) = 0; + + /** + * Allocate |length| bytes. Return NULL if allocation is not successful. + * Memory does not have to be initialized. + */ + virtual void* AllocateUninitialized(size_t length) = 0; + /** + * Free the memory block of size |length|, pointed to by |data|. + * That memory is guaranteed to be previously allocated by |Allocate|. + */ + virtual void Free(void* data, size_t length) = 0; + }; + + /** + * The contents of an |ArrayBuffer|. Externalization of |ArrayBuffer| + * returns an instance of this class, populated, with a pointer to data + * and byte length. + * + * The Data pointer of ArrayBuffer::Contents is always allocated with + * Allocator::Allocate that is set with V8::SetArrayBufferAllocator. + * + * This API is experimental and may change significantly. + */ + class V8_EXPORT Contents { // NOLINT + public: + Contents() : data_(NULL), byte_length_(0) {} + + void* Data() const { return data_; } + size_t ByteLength() const { return byte_length_; } + + private: + void* data_; + size_t byte_length_; + + friend class ArrayBuffer; + }; + + + /** + * Data length in bytes. + */ + size_t ByteLength() const; + + /** + * Create a new ArrayBuffer. Allocate |byte_length| bytes. + * Allocated memory will be owned by a created ArrayBuffer and + * will be deallocated when it is garbage-collected, + * unless the object is externalized. + */ + static Local<ArrayBuffer> New(Isolate* isolate, size_t byte_length); + + /** + * Create a new ArrayBuffer over an existing memory block. + * The created array buffer is immediately in externalized state. + * The memory block will not be reclaimed when a created ArrayBuffer + * is garbage-collected. + */ + static Local<ArrayBuffer> New(Isolate* isolate, void* data, + size_t byte_length); + + /** + * Returns true if ArrayBuffer is extrenalized, that is, does not + * own its memory block. + */ + bool IsExternal() const; + + /** + * Neuters this ArrayBuffer and all its views (typed arrays). + * Neutering sets the byte length of the buffer and all typed arrays to zero, + * preventing JavaScript from ever accessing underlying backing store. + * ArrayBuffer should have been externalized. + */ + void Neuter(); + + /** + * Make this ArrayBuffer external. The pointer to underlying memory block + * and byte length are returned as |Contents| structure. After ArrayBuffer + * had been etxrenalized, it does no longer owns the memory block. The caller + * should take steps to free memory when it is no longer needed. + * + * The memory block is guaranteed to be allocated with |Allocator::Allocate| + * that has been set with V8::SetArrayBufferAllocator. + */ + Contents Externalize(); + + V8_INLINE static ArrayBuffer* Cast(Value* obj); + + static const int kInternalFieldCount = V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT; + + private: + ArrayBuffer(); + static void CheckCast(Value* obj); +}; + + +#ifndef V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT +// The number of required internal fields can be defined by embedder. +#define V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT 2 +#endif + + +/** + * A base class for an instance of one of "views" over ArrayBuffer, + * including TypedArrays and DataView (ES6 draft 15.13). + * + * This API is experimental and may change significantly. + */ +class V8_EXPORT ArrayBufferView : public Object { + public: + /** + * Returns underlying ArrayBuffer. + */ + Local<ArrayBuffer> Buffer(); + /** + * Byte offset in |Buffer|. + */ + size_t ByteOffset(); + /** + * Size of a view in bytes. + */ + size_t ByteLength(); + + V8_INLINE static ArrayBufferView* Cast(Value* obj); + + static const int kInternalFieldCount = + V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT; + + private: + ArrayBufferView(); + static void CheckCast(Value* obj); +}; + + +/** + * A base class for an instance of TypedArray series of constructors + * (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT TypedArray : public ArrayBufferView { + public: + /** + * Number of elements in this typed array + * (e.g. for Int16Array, |ByteLength|/2). + */ + size_t Length(); + + V8_INLINE static TypedArray* Cast(Value* obj); + + private: + TypedArray(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Uint8Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT Uint8Array : public TypedArray { + public: + static Local<Uint8Array> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static Uint8Array* Cast(Value* obj); + + private: + Uint8Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Uint8ClampedArray constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT Uint8ClampedArray : public TypedArray { + public: + static Local<Uint8ClampedArray> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static Uint8ClampedArray* Cast(Value* obj); + + private: + Uint8ClampedArray(); + static void CheckCast(Value* obj); +}; + +/** + * An instance of Int8Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT Int8Array : public TypedArray { + public: + static Local<Int8Array> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static Int8Array* Cast(Value* obj); + + private: + Int8Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Uint16Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT Uint16Array : public TypedArray { + public: + static Local<Uint16Array> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static Uint16Array* Cast(Value* obj); + + private: + Uint16Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Int16Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT Int16Array : public TypedArray { + public: + static Local<Int16Array> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static Int16Array* Cast(Value* obj); + + private: + Int16Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Uint32Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT Uint32Array : public TypedArray { + public: + static Local<Uint32Array> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static Uint32Array* Cast(Value* obj); + + private: + Uint32Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Int32Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT Int32Array : public TypedArray { + public: + static Local<Int32Array> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static Int32Array* Cast(Value* obj); + + private: + Int32Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Float32Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT Float32Array : public TypedArray { + public: + static Local<Float32Array> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static Float32Array* Cast(Value* obj); + + private: + Float32Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of Float64Array constructor (ES6 draft 15.13.6). + * This API is experimental and may change significantly. + */ +class V8_EXPORT Float64Array : public TypedArray { + public: + static Local<Float64Array> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static Float64Array* Cast(Value* obj); + + private: + Float64Array(); + static void CheckCast(Value* obj); +}; + + +/** + * An instance of DataView constructor (ES6 draft 15.13.7). + * This API is experimental and may change significantly. + */ +class V8_EXPORT DataView : public ArrayBufferView { + public: + static Local<DataView> New(Handle<ArrayBuffer> array_buffer, + size_t byte_offset, size_t length); + V8_INLINE static DataView* Cast(Value* obj); + + private: + DataView(); + static void CheckCast(Value* obj); }; /** * An instance of the built-in Date constructor (ECMA-262, 15.9). */ -class Date : public Object { +class V8_EXPORT Date : public Object { public: - V8EXPORT static Local<Value> New(double time); + static Local<Value> New(Isolate* isolate, double time); /** * A specialization of Value::NumberValue that is more efficient * because we know the structure of this object. */ - V8EXPORT double NumberValue() const; + double ValueOf() const; - static inline Date* Cast(v8::Value* obj); + V8_INLINE static Date* Cast(v8::Value* obj); /** * Notification that the embedder has changed the time zone, @@ -1795,74 +3193,83 @@ class Date : public Object { * This API should not be called more than needed as it will * negatively impact the performance of date operations. */ - V8EXPORT static void DateTimeConfigurationChangeNotification(); + static void DateTimeConfigurationChangeNotification(Isolate* isolate); private: - V8EXPORT static void CheckCast(v8::Value* obj); + static void CheckCast(v8::Value* obj); }; /** * A Number object (ECMA-262, 4.3.21). */ -class NumberObject : public Object { +class V8_EXPORT NumberObject : public Object { public: - V8EXPORT static Local<Value> New(double value); + static Local<Value> New(Isolate* isolate, double value); - /** - * Returns the Number held by the object. - */ - V8EXPORT double NumberValue() const; + double ValueOf() const; - static inline NumberObject* Cast(v8::Value* obj); + V8_INLINE static NumberObject* Cast(v8::Value* obj); private: - V8EXPORT static void CheckCast(v8::Value* obj); + static void CheckCast(v8::Value* obj); }; /** * A Boolean object (ECMA-262, 4.3.15). */ -class BooleanObject : public Object { +class V8_EXPORT BooleanObject : public Object { public: - V8EXPORT static Local<Value> New(bool value); + static Local<Value> New(bool value); - /** - * Returns the Boolean held by the object. - */ - V8EXPORT bool BooleanValue() const; + bool ValueOf() const; - static inline BooleanObject* Cast(v8::Value* obj); + V8_INLINE static BooleanObject* Cast(v8::Value* obj); private: - V8EXPORT static void CheckCast(v8::Value* obj); + static void CheckCast(v8::Value* obj); }; /** * A String object (ECMA-262, 4.3.18). */ -class StringObject : public Object { +class V8_EXPORT StringObject : public Object { public: - V8EXPORT static Local<Value> New(Handle<String> value); + static Local<Value> New(Handle<String> value); - /** - * Returns the String held by the object. - */ - V8EXPORT Local<String> StringValue() const; + Local<String> ValueOf() const; - static inline StringObject* Cast(v8::Value* obj); + V8_INLINE static StringObject* Cast(v8::Value* obj); private: - V8EXPORT static void CheckCast(v8::Value* obj); + static void CheckCast(v8::Value* obj); +}; + + +/** + * A Symbol object (ECMA-262 edition 6). + * + * This is an experimental feature. Use at your own risk. + */ +class V8_EXPORT SymbolObject : public Object { + public: + static Local<Value> New(Isolate* isolate, Handle<Symbol> value); + + Local<Symbol> ValueOf() const; + + V8_INLINE static SymbolObject* Cast(v8::Value* obj); + + private: + static void CheckCast(v8::Value* obj); }; /** * An instance of the built-in RegExp constructor (ECMA-262, 15.10). */ -class RegExp : public Object { +class V8_EXPORT RegExp : public Object { public: /** * Regular expression flag bits. They can be or'ed to enable a set @@ -1885,51 +3292,37 @@ class RegExp : public Object { * static_cast<RegExp::Flags>(kGlobal | kMultiline)) * is equivalent to evaluating "/foo/gm". */ - V8EXPORT static Local<RegExp> New(Handle<String> pattern, - Flags flags); + static Local<RegExp> New(Handle<String> pattern, Flags flags); /** * Returns the value of the source property: a string representing * the regular expression. */ - V8EXPORT Local<String> GetSource() const; + Local<String> GetSource() const; /** * Returns the flags bit field. */ - V8EXPORT Flags GetFlags() const; + Flags GetFlags() const; - static inline RegExp* Cast(v8::Value* obj); + V8_INLINE static RegExp* Cast(v8::Value* obj); private: - V8EXPORT static void CheckCast(v8::Value* obj); + static void CheckCast(v8::Value* obj); }; /** - * A JavaScript value that wraps a C++ void*. This type of value is - * mainly used to associate C++ data structures with JavaScript - * objects. - * - * The Wrap function V8 will return the most optimal Value object wrapping the - * C++ void*. The type of the value is not guaranteed to be an External object - * and no assumptions about its type should be made. To access the wrapped - * value Unwrap should be used, all other operations on that object will lead - * to unpredictable results. + * A JavaScript value that wraps a C++ void*. This type of value is mainly used + * to associate C++ data structures with JavaScript objects. */ -class External : public Value { +class V8_EXPORT External : public Value { public: - V8EXPORT static Local<Value> Wrap(void* data); - static inline void* Unwrap(Handle<Value> obj); - - V8EXPORT static Local<External> New(void* value); - static inline External* Cast(Value* obj); - V8EXPORT void* Value() const; + static Local<External> New(Isolate* isolate, void* value); + V8_INLINE static External* Cast(Value* obj); + void* Value() const; private: - V8EXPORT External(); - V8EXPORT static void CheckCast(v8::Value* obj); - static inline void* QuickUnwrap(Handle<v8::Value> obj); - V8EXPORT static void* FullUnwrap(Handle<v8::Value> obj); + static void CheckCast(v8::Value* obj); }; @@ -1939,93 +3332,109 @@ class External : public Value { /** * The superclass of object and function templates. */ -class V8EXPORT Template : public Data { +class V8_EXPORT Template : public Data { public: /** Adds a property to each instance created by this template.*/ - void Set(Handle<String> name, Handle<Data> value, + void Set(Handle<Name> name, Handle<Data> value, PropertyAttribute attributes = None); - inline void Set(const char* name, Handle<Data> value); - private: - Template(); + V8_INLINE void Set(Isolate* isolate, const char* name, Handle<Data> value); - friend class ObjectTemplate; - friend class FunctionTemplate; -}; + void SetAccessorProperty( + Local<Name> name, + Local<FunctionTemplate> getter = Local<FunctionTemplate>(), + Local<FunctionTemplate> setter = Local<FunctionTemplate>(), + PropertyAttribute attribute = None, + AccessControl settings = DEFAULT); + /** + * Whenever the property with the given name is accessed on objects + * created from this Template the getter and setter callbacks + * are called instead of getting and setting the property directly + * on the JavaScript object. + * + * \param name The name of the property for which an accessor is added. + * \param getter The callback to invoke when getting the property. + * \param setter The callback to invoke when setting the property. + * \param data A piece of data that will be passed to the getter and setter + * callbacks whenever they are invoked. + * \param settings Access control settings for the accessor. This is a bit + * field consisting of one of more of + * DEFAULT = 0, ALL_CAN_READ = 1, or ALL_CAN_WRITE = 2. + * The default is to not allow cross-context access. + * ALL_CAN_READ means that all cross-context reads are allowed. + * ALL_CAN_WRITE means that all cross-context writes are allowed. + * The combination ALL_CAN_READ | ALL_CAN_WRITE can be used to allow all + * cross-context access. + * \param attribute The attributes of the property for which an accessor + * is added. + * \param signature The signature describes valid receivers for the accessor + * and is used to perform implicit instance checks against them. If the + * receiver is incompatible (i.e. is not an instance of the constructor as + * defined by FunctionTemplate::HasInstance()), an implicit TypeError is + * thrown and no callback is invoked. + */ + void SetNativeDataProperty(Local<String> name, + AccessorGetterCallback getter, + AccessorSetterCallback setter = 0, + // TODO(dcarney): gcc can't handle Local below + Handle<Value> data = Handle<Value>(), + PropertyAttribute attribute = None, + Local<AccessorSignature> signature = + Local<AccessorSignature>(), + AccessControl settings = DEFAULT); + void SetNativeDataProperty(Local<Name> name, + AccessorNameGetterCallback getter, + AccessorNameSetterCallback setter = 0, + // TODO(dcarney): gcc can't handle Local below + Handle<Value> data = Handle<Value>(), + PropertyAttribute attribute = None, + Local<AccessorSignature> signature = + Local<AccessorSignature>(), + AccessControl settings = DEFAULT); + + // This function is not yet stable and should not be used at this time. + bool SetDeclaredAccessor(Local<Name> name, + Local<DeclaredAccessorDescriptor> descriptor, + PropertyAttribute attribute = None, + Local<AccessorSignature> signature = + Local<AccessorSignature>(), + AccessControl settings = DEFAULT); -/** - * The argument information given to function call callbacks. This - * class provides access to information about the context of the call, - * including the receiver, the number and values of arguments, and - * the holder of the function. - */ -class Arguments { - public: - inline int Length() const; - inline Local<Value> operator[](int i) const; - inline Local<Function> Callee() const; - inline Local<Object> This() const; - inline Local<Object> Holder() const; - inline bool IsConstructCall() const; - inline Local<Value> Data() const; private: - static const int kDataIndex = 0; - static const int kCalleeIndex = -1; - static const int kHolderIndex = -2; - - friend class ImplementationUtilities; - inline Arguments(internal::Object** implicit_args, - internal::Object** values, - int length, - bool is_construct_call); - internal::Object** implicit_args_; - internal::Object** values_; - int length_; - bool is_construct_call_; -}; - + Template(); -/** - * The information passed to an accessor callback about the context - * of the property access. - */ -class V8EXPORT AccessorInfo { - public: - inline AccessorInfo(internal::Object** args) - : args_(args) { } - inline Local<Value> Data() const; - inline Local<Object> This() const; - inline Local<Object> Holder() const; - private: - internal::Object** args_; + friend class ObjectTemplate; + friend class FunctionTemplate; }; -typedef Handle<Value> (*InvocationCallback)(const Arguments& args); - /** * NamedProperty[Getter|Setter] are used as interceptors on object. * See ObjectTemplate::SetNamedPropertyHandler. */ -typedef Handle<Value> (*NamedPropertyGetter)(Local<String> property, - const AccessorInfo& info); +typedef void (*NamedPropertyGetterCallback)( + Local<String> property, + const PropertyCallbackInfo<Value>& info); /** * Returns the value if the setter intercepts the request. * Otherwise, returns an empty handle. */ -typedef Handle<Value> (*NamedPropertySetter)(Local<String> property, - Local<Value> value, - const AccessorInfo& info); +typedef void (*NamedPropertySetterCallback)( + Local<String> property, + Local<Value> value, + const PropertyCallbackInfo<Value>& info); + /** * Returns a non-empty handle if the interceptor intercepts the request. * The result is an integer encoding property attributes (like v8::None, * v8::DontEnum, etc.) */ -typedef Handle<Integer> (*NamedPropertyQuery)(Local<String> property, - const AccessorInfo& info); +typedef void (*NamedPropertyQueryCallback)( + Local<String> property, + const PropertyCallbackInfo<Integer>& info); /** @@ -2033,53 +3442,63 @@ typedef Handle<Integer> (*NamedPropertyQuery)(Local<String> property, * The return value is true if the property could be deleted and false * otherwise. */ -typedef Handle<Boolean> (*NamedPropertyDeleter)(Local<String> property, - const AccessorInfo& info); +typedef void (*NamedPropertyDeleterCallback)( + Local<String> property, + const PropertyCallbackInfo<Boolean>& info); + /** * Returns an array containing the names of the properties the named * property getter intercepts. */ -typedef Handle<Array> (*NamedPropertyEnumerator)(const AccessorInfo& info); +typedef void (*NamedPropertyEnumeratorCallback)( + const PropertyCallbackInfo<Array>& info); /** * Returns the value of the property if the getter intercepts the * request. Otherwise, returns an empty handle. */ -typedef Handle<Value> (*IndexedPropertyGetter)(uint32_t index, - const AccessorInfo& info); +typedef void (*IndexedPropertyGetterCallback)( + uint32_t index, + const PropertyCallbackInfo<Value>& info); /** * Returns the value if the setter intercepts the request. * Otherwise, returns an empty handle. */ -typedef Handle<Value> (*IndexedPropertySetter)(uint32_t index, - Local<Value> value, - const AccessorInfo& info); +typedef void (*IndexedPropertySetterCallback)( + uint32_t index, + Local<Value> value, + const PropertyCallbackInfo<Value>& info); /** * Returns a non-empty handle if the interceptor intercepts the request. * The result is an integer encoding property attributes. */ -typedef Handle<Integer> (*IndexedPropertyQuery)(uint32_t index, - const AccessorInfo& info); +typedef void (*IndexedPropertyQueryCallback)( + uint32_t index, + const PropertyCallbackInfo<Integer>& info); + /** * Returns a non-empty handle if the deleter intercepts the request. * The return value is true if the property could be deleted and false * otherwise. */ -typedef Handle<Boolean> (*IndexedPropertyDeleter)(uint32_t index, - const AccessorInfo& info); +typedef void (*IndexedPropertyDeleterCallback)( + uint32_t index, + const PropertyCallbackInfo<Boolean>& info); + /** * Returns an array containing the indices of the properties the * indexed property getter intercepts. */ -typedef Handle<Array> (*IndexedPropertyEnumerator)(const AccessorInfo& info); +typedef void (*IndexedPropertyEnumeratorCallback)( + const PropertyCallbackInfo<Array>& info); /** @@ -2206,13 +3625,16 @@ typedef bool (*IndexedSecurityCallback)(Local<Object> host, * child_instance.instance_property == 3; * \endcode */ -class V8EXPORT FunctionTemplate : public Template { +class V8_EXPORT FunctionTemplate : public Template { public: /** Creates a function template.*/ static Local<FunctionTemplate> New( - InvocationCallback callback = 0, + Isolate* isolate, + FunctionCallback callback = 0, Handle<Value> data = Handle<Value>(), - Handle<Signature> signature = Handle<Signature>()); + Handle<Signature> signature = Handle<Signature>(), + int length = 0); + /** Returns the unique function instance in the current execution context.*/ Local<Function> GetFunction(); @@ -2221,9 +3643,12 @@ class V8EXPORT FunctionTemplate : public Template { * callback is called whenever the function created from this * FunctionTemplate is called. */ - void SetCallHandler(InvocationCallback callback, + void SetCallHandler(FunctionCallback callback, Handle<Value> data = Handle<Value>()); + /** Set the predefined length property for the FunctionTemplate. */ + void SetLength(int length); + /** Get the InstanceTemplate. */ Local<ObjectTemplate> InstanceTemplate(); @@ -2236,7 +3661,6 @@ class V8EXPORT FunctionTemplate : public Template { */ Local<ObjectTemplate> PrototypeTemplate(); - /** * Set the class name of the FunctionTemplate. This is used for * printing objects created with the function created from the @@ -2265,6 +3689,12 @@ class V8EXPORT FunctionTemplate : public Template { void ReadOnlyPrototype(); /** + * Removes the prototype property from functions created from this + * FunctionTemplate. + */ + void RemovePrototype(); + + /** * Returns true if the given object is an instance of this function * template. */ @@ -2272,27 +3702,6 @@ class V8EXPORT FunctionTemplate : public Template { private: FunctionTemplate(); - void AddInstancePropertyAccessor(Handle<String> name, - AccessorGetter getter, - AccessorSetter setter, - Handle<Value> data, - AccessControl settings, - PropertyAttribute attributes); - void SetNamedInstancePropertyHandler(NamedPropertyGetter getter, - NamedPropertySetter setter, - NamedPropertyQuery query, - NamedPropertyDeleter remover, - NamedPropertyEnumerator enumerator, - Handle<Value> data); - void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter, - IndexedPropertySetter setter, - IndexedPropertyQuery query, - IndexedPropertyDeleter remover, - IndexedPropertyEnumerator enumerator, - Handle<Value> data); - void SetInstanceCallAsFunctionHandler(InvocationCallback callback, - Handle<Value> data); - friend class Context; friend class ObjectTemplate; }; @@ -2304,9 +3713,11 @@ class V8EXPORT FunctionTemplate : public Template { * Properties added to an ObjectTemplate are added to each object * created from the ObjectTemplate. */ -class V8EXPORT ObjectTemplate : public Template { +class V8_EXPORT ObjectTemplate : public Template { public: /** Creates an ObjectTemplate. */ + static Local<ObjectTemplate> New(Isolate* isolate); + // Will be deprecated soon. static Local<ObjectTemplate> New(); /** Creates a new instance of this template.*/ @@ -2335,19 +3746,34 @@ class V8EXPORT ObjectTemplate : public Template { * cross-context access. * \param attribute The attributes of the property for which an accessor * is added. + * \param signature The signature describes valid receivers for the accessor + * and is used to perform implicit instance checks against them. If the + * receiver is incompatible (i.e. is not an instance of the constructor as + * defined by FunctionTemplate::HasInstance()), an implicit TypeError is + * thrown and no callback is invoked. */ void SetAccessor(Handle<String> name, - AccessorGetter getter, - AccessorSetter setter = 0, + AccessorGetterCallback getter, + AccessorSetterCallback setter = 0, Handle<Value> data = Handle<Value>(), AccessControl settings = DEFAULT, - PropertyAttribute attribute = None); + PropertyAttribute attribute = None, + Handle<AccessorSignature> signature = + Handle<AccessorSignature>()); + void SetAccessor(Handle<Name> name, + AccessorNameGetterCallback getter, + AccessorNameSetterCallback setter = 0, + Handle<Value> data = Handle<Value>(), + AccessControl settings = DEFAULT, + PropertyAttribute attribute = None, + Handle<AccessorSignature> signature = + Handle<AccessorSignature>()); /** * Sets a named property handler on the object template. * - * Whenever a named property is accessed on objects created from - * this object template, the provided callback is invoked instead of + * Whenever a property whose name is a string is accessed on objects created + * from this object template, the provided callback is invoked instead of * accessing the property directly on the JavaScript object. * * \param getter The callback to invoke when getting a property. @@ -2360,12 +3786,13 @@ class V8EXPORT ObjectTemplate : public Template { * \param data A piece of data that will be passed to the callbacks * whenever they are invoked. */ - void SetNamedPropertyHandler(NamedPropertyGetter getter, - NamedPropertySetter setter = 0, - NamedPropertyQuery query = 0, - NamedPropertyDeleter deleter = 0, - NamedPropertyEnumerator enumerator = 0, - Handle<Value> data = Handle<Value>()); + void SetNamedPropertyHandler( + NamedPropertyGetterCallback getter, + NamedPropertySetterCallback setter = 0, + NamedPropertyQueryCallback query = 0, + NamedPropertyDeleterCallback deleter = 0, + NamedPropertyEnumeratorCallback enumerator = 0, + Handle<Value> data = Handle<Value>()); /** * Sets an indexed property handler on the object template. @@ -2383,12 +3810,13 @@ class V8EXPORT ObjectTemplate : public Template { * \param data A piece of data that will be passed to the callbacks * whenever they are invoked. */ - void SetIndexedPropertyHandler(IndexedPropertyGetter getter, - IndexedPropertySetter setter = 0, - IndexedPropertyQuery query = 0, - IndexedPropertyDeleter deleter = 0, - IndexedPropertyEnumerator enumerator = 0, - Handle<Value> data = Handle<Value>()); + void SetIndexedPropertyHandler( + IndexedPropertyGetterCallback getter, + IndexedPropertySetterCallback setter = 0, + IndexedPropertyQueryCallback query = 0, + IndexedPropertyDeleterCallback deleter = 0, + IndexedPropertyEnumeratorCallback enumerator = 0, + Handle<Value> data = Handle<Value>()); /** * Sets the callback to be used when calling instances created from @@ -2396,7 +3824,7 @@ class V8EXPORT ObjectTemplate : public Template { * behave like normal JavaScript objects that cannot be called as a * function. */ - void SetCallAsFunctionHandler(InvocationCallback callback, + void SetCallAsFunctionHandler(FunctionCallback callback, Handle<Value> data = Handle<Value>()); /** @@ -2439,31 +3867,104 @@ class V8EXPORT ObjectTemplate : public Template { private: ObjectTemplate(); - static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor); + static Local<ObjectTemplate> New(internal::Isolate* isolate, + Handle<FunctionTemplate> constructor); friend class FunctionTemplate; }; /** - * A Signature specifies which receivers and arguments a function can - * legally be called with. + * A Signature specifies which receivers and arguments are valid + * parameters to a function. */ -class V8EXPORT Signature : public Data { +class V8_EXPORT Signature : public Data { public: - static Local<Signature> New(Handle<FunctionTemplate> receiver = + static Local<Signature> New(Isolate* isolate, + Handle<FunctionTemplate> receiver = Handle<FunctionTemplate>(), int argc = 0, Handle<FunctionTemplate> argv[] = 0); + private: Signature(); }; /** + * An AccessorSignature specifies which receivers are valid parameters + * to an accessor callback. + */ +class V8_EXPORT AccessorSignature : public Data { + public: + static Local<AccessorSignature> New(Isolate* isolate, + Handle<FunctionTemplate> receiver = + Handle<FunctionTemplate>()); + + private: + AccessorSignature(); +}; + + +class V8_EXPORT DeclaredAccessorDescriptor : public Data { + private: + DeclaredAccessorDescriptor(); +}; + + +class V8_EXPORT ObjectOperationDescriptor : public Data { + public: + // This function is not yet stable and should not be used at this time. + static Local<RawOperationDescriptor> NewInternalFieldDereference( + Isolate* isolate, + int internal_field); + private: + ObjectOperationDescriptor(); +}; + + +enum DeclaredAccessorDescriptorDataType { + kDescriptorBoolType, + kDescriptorInt8Type, kDescriptorUint8Type, + kDescriptorInt16Type, kDescriptorUint16Type, + kDescriptorInt32Type, kDescriptorUint32Type, + kDescriptorFloatType, kDescriptorDoubleType +}; + + +class V8_EXPORT RawOperationDescriptor : public Data { + public: + Local<DeclaredAccessorDescriptor> NewHandleDereference(Isolate* isolate); + Local<RawOperationDescriptor> NewRawDereference(Isolate* isolate); + Local<RawOperationDescriptor> NewRawShift(Isolate* isolate, + int16_t byte_offset); + Local<DeclaredAccessorDescriptor> NewPointerCompare(Isolate* isolate, + void* compare_value); + Local<DeclaredAccessorDescriptor> NewPrimitiveValue( + Isolate* isolate, + DeclaredAccessorDescriptorDataType data_type, + uint8_t bool_offset = 0); + Local<DeclaredAccessorDescriptor> NewBitmaskCompare8(Isolate* isolate, + uint8_t bitmask, + uint8_t compare_value); + Local<DeclaredAccessorDescriptor> NewBitmaskCompare16( + Isolate* isolate, + uint16_t bitmask, + uint16_t compare_value); + Local<DeclaredAccessorDescriptor> NewBitmaskCompare32( + Isolate* isolate, + uint32_t bitmask, + uint32_t compare_value); + + private: + RawOperationDescriptor(); +}; + + +/** * A utility for determining the type of objects based on the template * they were constructed from. */ -class V8EXPORT TypeSwitch : public Data { +class V8_EXPORT TypeSwitch : public Data { public: static Local<TypeSwitch> New(Handle<FunctionTemplate> type); static Local<TypeSwitch> New(int argc, Handle<FunctionTemplate> types[]); @@ -2475,11 +3976,11 @@ class V8EXPORT TypeSwitch : public Data { // --- Extensions --- -class V8EXPORT ExternalAsciiStringResourceImpl - : public String::ExternalAsciiStringResource { +class V8_EXPORT ExternalOneByteStringResourceImpl + : public String::ExternalOneByteStringResource { public: - ExternalAsciiStringResourceImpl() : data_(0), length_(0) {} - ExternalAsciiStringResourceImpl(const char* data, size_t length) + ExternalOneByteStringResourceImpl() : data_(0), length_(0) {} + ExternalOneByteStringResourceImpl(const char* data, size_t length) : data_(data), length_(length) {} const char* data() const { return data_; } size_t length() const { return length_; } @@ -2492,7 +3993,7 @@ class V8EXPORT ExternalAsciiStringResourceImpl /** * Ignore */ -class V8EXPORT Extension { // NOLINT +class V8_EXPORT Extension { // NOLINT public: // Note that the strings passed into this constructor must live as long // as the Extension itself. @@ -2502,14 +4003,14 @@ class V8EXPORT Extension { // NOLINT const char** deps = 0, int source_length = -1); virtual ~Extension() { } - virtual v8::Handle<v8::FunctionTemplate> - GetNativeFunction(v8::Handle<v8::String> name) { + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate( + v8::Isolate* isolate, v8::Handle<v8::String> name) { return v8::Handle<v8::FunctionTemplate>(); } const char* name() const { return name_; } size_t source_length() const { return source_length_; } - const String::ExternalAsciiStringResource* source() const { + const String::ExternalOneByteStringResource* source() const { return &source_; } int dependency_count() { return dep_count_; } const char** dependencies() { return deps_; } @@ -2519,7 +4020,7 @@ class V8EXPORT Extension { // NOLINT private: const char* name_; size_t source_length_; // expected to initialize before source_ - ExternalAsciiStringResourceImpl source_; + ExternalOneByteStringResourceImpl source_; int dep_count_; const char** deps_; bool auto_enable_; @@ -2530,27 +4031,15 @@ class V8EXPORT Extension { // NOLINT }; -void V8EXPORT RegisterExtension(Extension* extension); - - -/** - * Ignore - */ -class V8EXPORT DeclareExtension { - public: - inline DeclareExtension(Extension* extension) { - RegisterExtension(extension); - } -}; +void V8_EXPORT RegisterExtension(Extension* extension); // --- Statics --- - -Handle<Primitive> V8EXPORT Undefined(); -Handle<Primitive> V8EXPORT Null(); -Handle<Boolean> V8EXPORT True(); -Handle<Boolean> V8EXPORT False(); +V8_INLINE Handle<Primitive> Undefined(Isolate* isolate); +V8_INLINE Handle<Primitive> Null(Isolate* isolate); +V8_INLINE Handle<Boolean> True(Isolate* isolate); +V8_INLINE Handle<Boolean> False(Isolate* isolate); /** @@ -2562,51 +4051,71 @@ Handle<Boolean> V8EXPORT False(); * setting the stack limit and you must set a non-default stack limit separately * for each thread. */ -class V8EXPORT ResourceConstraints { +class V8_EXPORT ResourceConstraints { public: ResourceConstraints(); - int max_young_space_size() const { return max_young_space_size_; } - void set_max_young_space_size(int value) { max_young_space_size_ = value; } + + /** + * Configures the constraints with reasonable default values based on the + * capabilities of the current device the VM is running on. + * + * \param physical_memory The total amount of physical memory on the current + * device, in bytes. + * \param virtual_memory_limit The amount of virtual memory on the current + * device, in bytes, or zero, if there is no limit. + * \param number_of_processors The number of CPUs available on the current + * device. + */ + void ConfigureDefaults(uint64_t physical_memory, + uint64_t virtual_memory_limit, + uint32_t number_of_processors); + + int max_semi_space_size() const { return max_semi_space_size_; } + void set_max_semi_space_size(int value) { max_semi_space_size_ = value; } int max_old_space_size() const { return max_old_space_size_; } void set_max_old_space_size(int value) { max_old_space_size_ = value; } - int max_executable_size() { return max_executable_size_; } + int max_executable_size() const { return max_executable_size_; } void set_max_executable_size(int value) { max_executable_size_ = value; } uint32_t* stack_limit() const { return stack_limit_; } // Sets an address beyond which the VM's stack may not grow. void set_stack_limit(uint32_t* value) { stack_limit_ = value; } + int max_available_threads() const { return max_available_threads_; } + // Set the number of threads available to V8, assuming at least 1. + void set_max_available_threads(int value) { + max_available_threads_ = value; + } + size_t code_range_size() const { return code_range_size_; } + void set_code_range_size(size_t value) { + code_range_size_ = value; + } + private: - int max_young_space_size_; + int max_semi_space_size_; int max_old_space_size_; int max_executable_size_; uint32_t* stack_limit_; + int max_available_threads_; + size_t code_range_size_; }; -bool V8EXPORT SetResourceConstraints(ResourceConstraints* constraints); - - // --- Exceptions --- typedef void (*FatalErrorCallback)(const char* location, const char* message); -typedef void (*MessageCallback)(Handle<Message> message, Handle<Value> data); +typedef void (*MessageCallback)(Handle<Message> message, Handle<Value> error); +// --- Tracing --- -/** - * Schedules an exception to be thrown when returning to JavaScript. When an - * exception has been scheduled it is illegal to invoke any JavaScript - * operation; the caller must return immediately and only after the exception - * has been handled does it become legal to invoke JavaScript operations. - */ -Handle<Value> V8EXPORT ThrowException(Handle<Value> exception); +typedef void (*LogEventCallback)(const char* name, int event); /** * Create new error objects by calling the corresponding error object * constructor with the message. */ -class V8EXPORT Exception { +class V8_EXPORT Exception { public: static Local<Value> RangeError(Handle<String> message); static Local<Value> ReferenceError(Handle<String> message); @@ -2654,6 +4163,9 @@ typedef void (*MemoryAllocationCallback)(ObjectSpace space, // --- Leave Script Callback --- typedef void (*CallCompletedCallback)(); +// --- Microtask Callback --- +typedef void (*MicrotaskCallback)(void* data); + // --- Failed Access Check Callback --- typedef void (*FailedAccessCheckCallback)(Local<Object> target, AccessType type, @@ -2684,13 +4196,15 @@ enum GCType { enum GCCallbackFlags { kNoGCCallbackFlags = 0, - kGCCallbackFlagCompacted = 1 << 0 + kGCCallbackFlagCompacted = 1 << 0, + kGCCallbackFlagConstructRetainedObjectInfos = 1 << 1, + kGCCallbackFlagForced = 1 << 2 }; typedef void (*GCPrologueCallback)(GCType type, GCCallbackFlags flags); typedef void (*GCEpilogueCallback)(GCType type, GCCallbackFlags flags); -typedef void (*GCCallback)(); +typedef void (*InterruptCallback)(Isolate* isolate, void* data); /** @@ -2699,49 +4213,177 @@ typedef void (*GCCallback)(); * Instances of this class can be passed to v8::V8::HeapStatistics to * get heap statistics from V8. */ -class V8EXPORT HeapStatistics { +class V8_EXPORT HeapStatistics { public: HeapStatistics(); size_t total_heap_size() { return total_heap_size_; } size_t total_heap_size_executable() { return total_heap_size_executable_; } + size_t total_physical_size() { return total_physical_size_; } size_t used_heap_size() { return used_heap_size_; } size_t heap_size_limit() { return heap_size_limit_; } private: - void set_total_heap_size(size_t size) { total_heap_size_ = size; } - void set_total_heap_size_executable(size_t size) { - total_heap_size_executable_ = size; - } - void set_used_heap_size(size_t size) { used_heap_size_ = size; } - void set_heap_size_limit(size_t size) { heap_size_limit_ = size; } - size_t total_heap_size_; size_t total_heap_size_executable_; + size_t total_physical_size_; size_t used_heap_size_; size_t heap_size_limit_; friend class V8; + friend class Isolate; }; class RetainedObjectInfo; + +/** + * FunctionEntryHook is the type of the profile entry hook called at entry to + * any generated function when function-level profiling is enabled. + * + * \param function the address of the function that's being entered. + * \param return_addr_location points to a location on stack where the machine + * return address resides. This can be used to identify the caller of + * \p function, and/or modified to divert execution when \p function exits. + * + * \note the entry hook must not cause garbage collection. + */ +typedef void (*FunctionEntryHook)(uintptr_t function, + uintptr_t return_addr_location); + /** - * Isolate represents an isolated instance of the V8 engine. V8 - * isolates have completely separate states. Objects from one isolate - * must not be used in other isolates. When V8 is initialized a - * default isolate is implicitly created and entered. The embedder - * can create additional isolates and use them in parallel in multiple - * threads. An isolate can be entered by at most one thread at any - * given time. The Locker/Unlocker API must be used to synchronize. + * A JIT code event is issued each time code is added, moved or removed. + * + * \note removal events are not currently issued. */ -class V8EXPORT Isolate { +struct JitCodeEvent { + enum EventType { + CODE_ADDED, + CODE_MOVED, + CODE_REMOVED, + CODE_ADD_LINE_POS_INFO, + CODE_START_LINE_INFO_RECORDING, + CODE_END_LINE_INFO_RECORDING + }; + // Definition of the code position type. The "POSITION" type means the place + // in the source code which are of interest when making stack traces to + // pin-point the source location of a stack frame as close as possible. + // The "STATEMENT_POSITION" means the place at the beginning of each + // statement, and is used to indicate possible break locations. + enum PositionType { POSITION, STATEMENT_POSITION }; + + // Type of event. + EventType type; + // Start of the instructions. + void* code_start; + // Size of the instructions. + size_t code_len; + // Script info for CODE_ADDED event. + Handle<UnboundScript> script; + // User-defined data for *_LINE_INFO_* event. It's used to hold the source + // code line information which is returned from the + // CODE_START_LINE_INFO_RECORDING event. And it's passed to subsequent + // CODE_ADD_LINE_POS_INFO and CODE_END_LINE_INFO_RECORDING events. + void* user_data; + + struct name_t { + // Name of the object associated with the code, note that the string is not + // zero-terminated. + const char* str; + // Number of chars in str. + size_t len; + }; + + struct line_info_t { + // PC offset + size_t offset; + // Code postion + size_t pos; + // The position type. + PositionType position_type; + }; + + union { + // Only valid for CODE_ADDED. + struct name_t name; + + // Only valid for CODE_ADD_LINE_POS_INFO + struct line_info_t line_info; + + // New location of instructions. Only valid for CODE_MOVED. + void* new_code_start; + }; +}; + +/** + * Option flags passed to the SetJitCodeEventHandler function. + */ +enum JitCodeEventOptions { + kJitCodeEventDefault = 0, + // Generate callbacks for already existent code. + kJitCodeEventEnumExisting = 1 +}; + + +/** + * Callback function passed to SetJitCodeEventHandler. + * + * \param event code add, move or removal event. + */ +typedef void (*JitCodeEventHandler)(const JitCodeEvent* event); + + +/** + * Isolate represents an isolated instance of the V8 engine. V8 isolates have + * completely separate states. Objects from one isolate must not be used in + * other isolates. The embedder can create multiple isolates and use them in + * parallel in multiple threads. An isolate can be entered by at most one + * thread at any given time. The Locker/Unlocker API must be used to + * synchronize. + */ +class V8_EXPORT Isolate { public: /** + * Initial configuration parameters for a new Isolate. + */ + struct CreateParams { + CreateParams() + : entry_hook(NULL), + code_event_handler(NULL), + enable_serializer(false) {} + + /** + * The optional entry_hook allows the host application to provide the + * address of a function that's invoked on entry to every V8-generated + * function. Note that entry_hook is invoked at the very start of each + * generated function. Furthermore, if an entry_hook is given, V8 will + * always run without a context snapshot. + */ + FunctionEntryHook entry_hook; + + /** + * Allows the host application to provide the address of a function that is + * notified each time code is added, moved or removed. + */ + JitCodeEventHandler code_event_handler; + + /** + * ResourceConstraints to use for the new Isolate. + */ + ResourceConstraints constraints; + + /** + * This flag currently renders the Isolate unusable. + */ + bool enable_serializer; + }; + + + /** * Stack-allocated class which sets the isolate for all operations * executed within a local scope. */ - class V8EXPORT Scope { + class V8_EXPORT Scope { public: explicit Scope(Isolate* isolate) : isolate_(isolate) { isolate->Enter(); @@ -2757,14 +4399,97 @@ class V8EXPORT Isolate { Scope& operator=(const Scope&); }; + + /** + * Assert that no Javascript code is invoked. + */ + class V8_EXPORT DisallowJavascriptExecutionScope { + public: + enum OnFailure { CRASH_ON_FAILURE, THROW_ON_FAILURE }; + + DisallowJavascriptExecutionScope(Isolate* isolate, OnFailure on_failure); + ~DisallowJavascriptExecutionScope(); + + private: + bool on_failure_; + void* internal_; + + // Prevent copying of Scope objects. + DisallowJavascriptExecutionScope(const DisallowJavascriptExecutionScope&); + DisallowJavascriptExecutionScope& operator=( + const DisallowJavascriptExecutionScope&); + }; + + + /** + * Introduce exception to DisallowJavascriptExecutionScope. + */ + class V8_EXPORT AllowJavascriptExecutionScope { + public: + explicit AllowJavascriptExecutionScope(Isolate* isolate); + ~AllowJavascriptExecutionScope(); + + private: + void* internal_throws_; + void* internal_assert_; + + // Prevent copying of Scope objects. + AllowJavascriptExecutionScope(const AllowJavascriptExecutionScope&); + AllowJavascriptExecutionScope& operator=( + const AllowJavascriptExecutionScope&); + }; + + /** + * Do not run microtasks while this scope is active, even if microtasks are + * automatically executed otherwise. + */ + class V8_EXPORT SuppressMicrotaskExecutionScope { + public: + explicit SuppressMicrotaskExecutionScope(Isolate* isolate); + ~SuppressMicrotaskExecutionScope(); + + private: + internal::Isolate* isolate_; + + // Prevent copying of Scope objects. + SuppressMicrotaskExecutionScope(const SuppressMicrotaskExecutionScope&); + SuppressMicrotaskExecutionScope& operator=( + const SuppressMicrotaskExecutionScope&); + }; + + /** + * Types of garbage collections that can be requested via + * RequestGarbageCollectionForTesting. + */ + enum GarbageCollectionType { + kFullGarbageCollection, + kMinorGarbageCollection + }; + + /** + * Features reported via the SetUseCounterCallback callback. Do not chang + * assigned numbers of existing items; add new features to the end of this + * list. + */ + enum UseCounterFeature { + kUseAsm = 0, + kUseCounterFeatureCount // This enum value must be last. + }; + + typedef void (*UseCounterCallback)(Isolate* isolate, + UseCounterFeature feature); + + /** * Creates a new isolate. Does not change the currently entered * isolate. * * When an isolate is no longer used its resources should be freed * by calling Dispose(). Using the delete operator is not allowed. + * + * V8::Initialize() must have run prior to this. */ - static Isolate* New(); + static Isolate* New(const CreateParams& params = CreateParams()); /** * Returns the entered isolate for the current thread or NULL in @@ -2800,27 +4525,333 @@ class V8EXPORT Isolate { void Dispose(); /** - * Associate embedder-specific data with the isolate + * Associate embedder-specific data with the isolate. |slot| has to be + * between 0 and GetNumberOfDataSlots() - 1. + */ + V8_INLINE void SetData(uint32_t slot, void* data); + + /** + * Retrieve embedder-specific data from the isolate. + * Returns NULL if SetData has never been called for the given |slot|. + */ + V8_INLINE void* GetData(uint32_t slot); + + /** + * Returns the maximum number of available embedder data slots. Valid slots + * are in the range of 0 - GetNumberOfDataSlots() - 1. + */ + V8_INLINE static uint32_t GetNumberOfDataSlots(); + + /** + * Get statistics about the heap memory usage. + */ + void GetHeapStatistics(HeapStatistics* heap_statistics); + + /** + * Adjusts the amount of registered external memory. Used to give V8 an + * indication of the amount of externally allocated memory that is kept alive + * by JavaScript objects. V8 uses this to decide when to perform global + * garbage collections. Registering externally allocated memory will trigger + * global garbage collections more often than it would otherwise in an attempt + * to garbage collect the JavaScript objects that keep the externally + * allocated memory alive. + * + * \param change_in_bytes the change in externally allocated memory that is + * kept alive by JavaScript objects. + * \returns the adjusted value. + */ + V8_INLINE int64_t + AdjustAmountOfExternalAllocatedMemory(int64_t change_in_bytes); + + /** + * Returns heap profiler for this isolate. Will return NULL until the isolate + * is initialized. + */ + HeapProfiler* GetHeapProfiler(); + + /** + * Returns CPU profiler for this isolate. Will return NULL unless the isolate + * is initialized. It is the embedder's responsibility to stop all CPU + * profiling activities if it has started any. + */ + CpuProfiler* GetCpuProfiler(); + + /** Returns true if this isolate has a current context. */ + bool InContext(); + + /** Returns the context that is on the top of the stack. */ + Local<Context> GetCurrentContext(); + + /** + * Returns the context of the calling JavaScript code. That is the + * context of the top-most JavaScript frame. If there are no + * JavaScript frames an empty handle is returned. + */ + Local<Context> GetCallingContext(); + + /** Returns the last entered context. */ + Local<Context> GetEnteredContext(); + + /** + * Schedules an exception to be thrown when returning to JavaScript. When an + * exception has been scheduled it is illegal to invoke any JavaScript + * operation; the caller must return immediately and only after the exception + * has been handled does it become legal to invoke JavaScript operations. */ - void SetData(void* data); + Local<Value> ThrowException(Local<Value> exception); /** - * Retrive embedder-specific data from the isolate. - * Returns NULL if SetData has never been called. + * Allows the host application to group objects together. If one + * object in the group is alive, all objects in the group are alive. + * After each garbage collection, object groups are removed. It is + * intended to be used in the before-garbage-collection callback + * function, for instance to simulate DOM tree connections among JS + * wrapper objects. Object groups for all dependent handles need to + * be provided for kGCTypeMarkSweepCompact collections, for all other + * garbage collection types it is sufficient to provide object groups + * for partially dependent handles only. + */ + template<typename T> void SetObjectGroupId(const Persistent<T>& object, + UniqueId id); + + /** + * Allows the host application to declare implicit references from an object + * group to an object. If the objects of the object group are alive, the child + * object is alive too. After each garbage collection, all implicit references + * are removed. It is intended to be used in the before-garbage-collection + * callback function. + */ + template<typename T> void SetReferenceFromGroup(UniqueId id, + const Persistent<T>& child); + + /** + * Allows the host application to declare implicit references from an object + * to another object. If the parent object is alive, the child object is alive + * too. After each garbage collection, all implicit references are removed. It + * is intended to be used in the before-garbage-collection callback function. + */ + template<typename T, typename S> + void SetReference(const Persistent<T>& parent, const Persistent<S>& child); + + typedef void (*GCPrologueCallback)(Isolate* isolate, + GCType type, + GCCallbackFlags flags); + typedef void (*GCEpilogueCallback)(Isolate* isolate, + GCType type, + GCCallbackFlags flags); + + /** + * Enables the host application to receive a notification before a + * garbage collection. Allocations are allowed in the callback function, + * but the callback is not re-entrant: if the allocation inside it will + * trigger the garbage collection, the callback won't be called again. + * It is possible to specify the GCType filter for your callback. But it is + * not possible to register the same callback function two times with + * different GCType filters. + */ + void AddGCPrologueCallback( + GCPrologueCallback callback, GCType gc_type_filter = kGCTypeAll); + + /** + * This function removes callback which was installed by + * AddGCPrologueCallback function. */ - void* GetData(); + void RemoveGCPrologueCallback(GCPrologueCallback callback); + + /** + * Enables the host application to receive a notification after a + * garbage collection. Allocations are allowed in the callback function, + * but the callback is not re-entrant: if the allocation inside it will + * trigger the garbage collection, the callback won't be called again. + * It is possible to specify the GCType filter for your callback. But it is + * not possible to register the same callback function two times with + * different GCType filters. + */ + void AddGCEpilogueCallback( + GCEpilogueCallback callback, GCType gc_type_filter = kGCTypeAll); + + /** + * This function removes callback which was installed by + * AddGCEpilogueCallback function. + */ + void RemoveGCEpilogueCallback(GCEpilogueCallback callback); + + /** + * Request V8 to interrupt long running JavaScript code and invoke + * the given |callback| passing the given |data| to it. After |callback| + * returns control will be returned to the JavaScript code. + * At any given moment V8 can remember only a single callback for the very + * last interrupt request. + * Can be called from another thread without acquiring a |Locker|. + * Registered |callback| must not reenter interrupted Isolate. + */ + void RequestInterrupt(InterruptCallback callback, void* data); + + /** + * Clear interrupt request created by |RequestInterrupt|. + * Can be called from another thread without acquiring a |Locker|. + */ + void ClearInterrupt(); + + /** + * Request garbage collection in this Isolate. It is only valid to call this + * function if --expose_gc was specified. + * + * This should only be used for testing purposes and not to enforce a garbage + * collection schedule. It has strong negative impact on the garbage + * collection performance. Use IdleNotification() or LowMemoryNotification() + * instead to influence the garbage collection schedule. + */ + void RequestGarbageCollectionForTesting(GarbageCollectionType type); + + /** + * Set the callback to invoke for logging event. + */ + void SetEventLogger(LogEventCallback that); + + /** + * Adds a callback to notify the host application when a script finished + * running. If a script re-enters the runtime during executing, the + * CallCompletedCallback is only invoked when the outer-most script + * execution ends. Executing scripts inside the callback do not trigger + * further callbacks. + */ + void AddCallCompletedCallback(CallCompletedCallback callback); + + /** + * Removes callback that was installed by AddCallCompletedCallback. + */ + void RemoveCallCompletedCallback(CallCompletedCallback callback); + + /** + * Experimental: Runs the Microtask Work Queue until empty + * Any exceptions thrown by microtask callbacks are swallowed. + */ + void RunMicrotasks(); + + /** + * Experimental: Enqueues the callback to the Microtask Work Queue + */ + void EnqueueMicrotask(Handle<Function> microtask); + + /** + * Experimental: Enqueues the callback to the Microtask Work Queue + */ + void EnqueueMicrotask(MicrotaskCallback microtask, void* data = NULL); + + /** + * Experimental: Controls whether the Microtask Work Queue is automatically + * run when the script call depth decrements to zero. + */ + void SetAutorunMicrotasks(bool autorun); + + /** + * Experimental: Returns whether the Microtask Work Queue is automatically + * run when the script call depth decrements to zero. + */ + bool WillAutorunMicrotasks() const; + + /** + * Sets a callback for counting the number of times a feature of V8 is used. + */ + void SetUseCounterCallback(UseCounterCallback callback); + + /** + * Enables the host application to provide a mechanism for recording + * statistics counters. + */ + void SetCounterFunction(CounterLookupCallback); + + /** + * Enables the host application to provide a mechanism for recording + * histograms. The CreateHistogram function returns a + * histogram which will later be passed to the AddHistogramSample + * function. + */ + void SetCreateHistogramFunction(CreateHistogramCallback); + void SetAddHistogramSampleFunction(AddHistogramSampleCallback); + + /** + * Optional notification that the embedder is idle. + * V8 uses the notification to reduce memory footprint. + * This call can be used repeatedly if the embedder remains idle. + * Returns true if the embedder should stop calling IdleNotification + * until real work has been done. This indicates that V8 has done + * as much cleanup as it will be able to do. + * + * The idle_time_in_ms argument specifies the time V8 has to do reduce + * the memory footprint. There is no guarantee that the actual work will be + * done within the time limit. + */ + bool IdleNotification(int idle_time_in_ms); + + /** + * Optional notification that the system is running low on memory. + * V8 uses these notifications to attempt to free memory. + */ + void LowMemoryNotification(); + + /** + * Optional notification that a context has been disposed. V8 uses + * these notifications to guide the GC heuristic. Returns the number + * of context disposals - including this one - since the last time + * V8 had a chance to clean up. + */ + int ContextDisposedNotification(); + + /** + * Allows the host application to provide the address of a function that is + * notified each time code is added, moved or removed. + * + * \param options options for the JIT code event handler. + * \param event_handler the JIT code event handler, which will be invoked + * each time code is added, moved or removed. + * \note \p event_handler won't get notified of existent code. + * \note since code removal notifications are not currently issued, the + * \p event_handler may get notifications of code that overlaps earlier + * code notifications. This happens when code areas are reused, and the + * earlier overlapping code areas should therefore be discarded. + * \note the events passed to \p event_handler and the strings they point to + * are not guaranteed to live past each call. The \p event_handler must + * copy strings and other parameters it needs to keep around. + * \note the set of events declared in JitCodeEvent::EventType is expected to + * grow over time, and the JitCodeEvent structure is expected to accrue + * new members. The \p event_handler function must ignore event codes + * it does not recognize to maintain future compatibility. + * \note Use Isolate::CreateParams to get events for code executed during + * Isolate setup. + */ + void SetJitCodeEventHandler(JitCodeEventOptions options, + JitCodeEventHandler event_handler); + + /** + * Modifies the stack limit for this Isolate. + * + * \param stack_limit An address beyond which the Vm's stack may not grow. + * + * \note If you are using threads then you should hold the V8::Locker lock + * while setting the stack limit and you must set a non-default stack + * limit separately for each thread. + */ + void SetStackLimit(uintptr_t stack_limit); private: + template<class K, class V, class Traits> friend class PersistentValueMap; + Isolate(); Isolate(const Isolate&); ~Isolate(); Isolate& operator=(const Isolate&); void* operator new(size_t size); void operator delete(void*, size_t); -}; + void SetObjectGroupId(internal::Object** object, UniqueId id); + void SetReferenceFromGroup(UniqueId id, internal::Object** object); + void SetReference(internal::Object** parent, internal::Object** child); + void CollectAllGarbage(const char* gc_reason); +}; -class StartupData { +class V8_EXPORT StartupData { public: enum CompressionAlgorithm { kUncompressed, @@ -2841,7 +4872,7 @@ class StartupData { * * For an example of the class usage, see the "shell.cc" sample application. */ -class V8EXPORT StartupDataDecompressor { // NOLINT +class V8_EXPORT StartupDataDecompressor { // NOLINT public: StartupDataDecompressor(); virtual ~StartupDataDecompressor(); @@ -2870,19 +4901,22 @@ typedef bool (*EntropySource)(unsigned char* buffer, size_t length); * resolving the location of a return address on the stack. Profilers that * change the return address on the stack can use this to resolve the stack * location to whereever the profiler stashed the original return address. - * When invoked, return_addr_location will point to a location on stack where - * a machine return address resides, this function should return either the - * same pointer, or a pointer to the profiler's copy of the original return - * address. + * + * \param return_addr_location points to a location on stack where a machine + * return address resides. + * \returns either return_addr_location, or else a pointer to the profiler's + * copy of the original return address. + * + * \note the resolver function must not cause garbage collection. */ typedef uintptr_t (*ReturnAddressLocationResolver)( uintptr_t return_addr_location); /** - * Interface for iterating though all external resources in the heap. + * Interface for iterating through all external resources in the heap. */ -class V8EXPORT ExternalResourceVisitor { // NOLINT +class V8_EXPORT ExternalResourceVisitor { // NOLINT public: virtual ~ExternalResourceVisitor() {} virtual void VisitExternalString(Handle<String> string) {} @@ -2890,9 +4924,20 @@ class V8EXPORT ExternalResourceVisitor { // NOLINT /** + * Interface for iterating through all the persistent handles in the heap. + */ +class V8_EXPORT PersistentHandleVisitor { // NOLINT + public: + virtual ~PersistentHandleVisitor() {} + virtual void VisitPersistentHandle(Persistent<Value>* value, + uint16_t class_id) {} +}; + + +/** * Container class for static utility functions. */ -class V8EXPORT V8 { +class V8_EXPORT V8 { public: /** Set the callback to invoke in case of fatal errors. */ static void SetFatalErrorHandler(FatalErrorCallback that); @@ -2905,18 +4950,12 @@ class V8EXPORT V8 { AllowCodeGenerationFromStringsCallback that); /** - * Ignore out-of-memory exceptions. - * - * V8 running out of memory is treated as a fatal error by default. - * This means that the fatal error handler is called and that V8 is - * terminated. - * - * IgnoreOutOfMemoryException can be used to not treat an - * out-of-memory situation as a fatal error. This way, the contexts - * that did not cause the out of memory problem might be able to - * continue execution. + * Set allocator to use for ArrayBuffer memory. + * The allocator should be set only once. The allocator should be set + * before any code tha uses ArrayBuffers is executed. + * This allocator is used in all isolates. */ - static void IgnoreOutOfMemoryException(); + static void SetArrayBufferAllocator(ArrayBuffer::Allocator* allocator); /** * Check if V8 is dead and therefore unusable. This is the case after @@ -2949,10 +4988,31 @@ class V8EXPORT V8 { static void SetDecompressedStartupData(StartupData* decompressed_data); /** + * Hand startup data to V8, in case the embedder has chosen to build + * V8 with external startup data. + * + * Note: + * - By default the startup data is linked into the V8 library, in which + * case this function is not meaningful. + * - If this needs to be called, it needs to be called before V8 + * tries to make use of its built-ins. + * - To avoid unnecessary copies of data, V8 will point directly into the + * given data blob, so pretty please keep it around until V8 exit. + * - Compression of the startup blob might be useful, but needs to + * handled entirely on the embedders' side. + * - The call will abort if the data is invalid. + */ + static void SetNativesDataBlob(StartupData* startup_blob); + static void SetSnapshotDataBlob(StartupData* startup_blob); + + /** * Adds a message listener. * * The same message listener can be added more than once and in that * case it will be called more than once for each message. + * + * If data is specified, it will be passed to the callback when it is called. + * Otherwise, the exception object will be passed to the callback instead. */ static bool AddMessageListener(MessageCallback that, Handle<Value> data = Handle<Value>()); @@ -2986,27 +5046,6 @@ class V8EXPORT V8 { /** Get the version string. */ static const char* GetVersion(); - /** - * Enables the host application to provide a mechanism for recording - * statistics counters. - */ - static void SetCounterFunction(CounterLookupCallback); - - /** - * Enables the host application to provide a mechanism for recording - * histograms. The CreateHistogram function returns a - * histogram which will later be passed to the AddHistogramSample - * function. - */ - static void SetCreateHistogramFunction(CreateHistogramCallback); - static void SetAddHistogramSampleFunction(AddHistogramSampleCallback); - - /** - * Enables the computation of a sliding window of states. The sliding - * window information is recorded in statistics counters. - */ - static void EnableSlidingStateWindow(); - /** Callback function for reporting failed access checks.*/ static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback); @@ -3030,16 +5069,6 @@ class V8EXPORT V8 { static void RemoveGCPrologueCallback(GCPrologueCallback callback); /** - * The function is deprecated. Please use AddGCPrologueCallback instead. - * Enables the host application to receive a notification before a - * garbage collection. Allocations are not allowed in the - * callback function, you therefore cannot manipulate objects (set - * or delete properties for example) since it is possible such - * operations will result in the allocation of objects. - */ - static void SetGlobalGCPrologueCallback(GCCallback); - - /** * Enables the host application to receive a notification after a * garbage collection. Allocations are not allowed in the * callback function, you therefore cannot manipulate objects (set @@ -3059,16 +5088,6 @@ class V8EXPORT V8 { static void RemoveGCEpilogueCallback(GCEpilogueCallback callback); /** - * The function is deprecated. Please use AddGCEpilogueCallback instead. - * Enables the host application to receive a notification after a - * major garbage collection. Allocations are not allowed in the - * callback function, you therefore cannot manipulate objects (set - * or delete properties for example) since it is possible such - * operations will result in the allocation of objects. - */ - static void SetGlobalGCEpilogueCallback(GCCallback); - - /** * Enables the host application to provide a mechanism to be notified * and perform custom logging when V8 Allocates Executable Memory. */ @@ -3082,47 +5101,8 @@ class V8EXPORT V8 { static void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback); /** - * Adds a callback to notify the host application when a script finished - * running. If a script re-enters the runtime during executing, the - * CallCompletedCallback is only invoked when the outer-most script - * execution ends. Executing scripts inside the callback do not trigger - * further callbacks. - */ - static void AddCallCompletedCallback(CallCompletedCallback callback); - - /** - * Removes callback that was installed by AddCallCompletedCallback. - */ - static void RemoveCallCompletedCallback(CallCompletedCallback callback); - - /** - * Allows the host application to group objects together. If one - * object in the group is alive, all objects in the group are alive. - * After each garbage collection, object groups are removed. It is - * intended to be used in the before-garbage-collection callback - * function, for instance to simulate DOM tree connections among JS - * wrapper objects. - * See v8-profiler.h for RetainedObjectInfo interface description. - */ - static void AddObjectGroup(Persistent<Value>* objects, - size_t length, - RetainedObjectInfo* info = NULL); - - /** - * Allows the host application to declare implicit references between - * the objects: if |parent| is alive, all |children| are alive too. - * After each garbage collection, all implicit references - * are removed. It is intended to be used in the before-garbage-collection - * callback function. - */ - static void AddImplicitReferences(Persistent<Object> parent, - Persistent<Value>* children, - size_t length); - - /** - * Initializes from snapshot if possible. Otherwise, attempts to - * initialize from scratch. This function is called implicitly if - * you use the API without calling it first. + * Initializes V8. This function needs to be called before the first Isolate + * is created. It always returns true. */ static bool Initialize(); @@ -3140,88 +5120,15 @@ class V8EXPORT V8 { ReturnAddressLocationResolver return_address_resolver); /** - * Adjusts the amount of registered external memory. Used to give - * V8 an indication of the amount of externally allocated memory - * that is kept alive by JavaScript objects. V8 uses this to decide - * when to perform global garbage collections. Registering - * externally allocated memory will trigger global garbage - * collections more often than otherwise in an attempt to garbage - * collect the JavaScript objects keeping the externally allocated - * memory alive. - * - * \param change_in_bytes the change in externally allocated memory - * that is kept alive by JavaScript objects. - * \returns the adjusted value. - */ - static int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes); - - /** - * Suspends recording of tick samples in the profiler. - * When the V8 profiling mode is enabled (usually via command line - * switches) this function suspends recording of tick samples. - * Profiling ticks are discarded until ResumeProfiler() is called. - * - * See also the --prof and --prof_auto command line switches to - * enable V8 profiling. - */ - static void PauseProfiler(); - - /** - * Resumes recording of tick samples in the profiler. - * See also PauseProfiler(). - */ - static void ResumeProfiler(); - - /** - * Return whether profiler is currently paused. - */ - static bool IsProfilerPaused(); - - /** - * Retrieve the V8 thread id of the calling thread. - * - * The thread id for a thread should only be retrieved after the V8 - * lock has been acquired with a Locker object with that thread. - */ - static int GetCurrentThreadId(); - - /** - * Forcefully terminate execution of a JavaScript thread. This can - * be used to terminate long-running scripts. - * - * TerminateExecution should only be called when then V8 lock has - * been acquired with a Locker object. Therefore, in order to be - * able to terminate long-running threads, preemption must be - * enabled to allow the user of TerminateExecution to acquire the - * lock. - * - * The termination is achieved by throwing an exception that is - * uncatchable by JavaScript exception handlers. Termination - * exceptions act as if they were caught by a C++ TryCatch exception - * handler. If forceful termination is used, any C++ TryCatch - * exception handler that catches an exception should check if that - * exception is a termination exception and immediately return if - * that is the case. Returning immediately in that case will - * continue the propagation of the termination exception if needed. - * - * The thread id passed to TerminateExecution must have been - * obtained by calling GetCurrentThreadId on the thread in question. - * - * \param thread_id The thread id of the thread to terminate. - */ - static void TerminateExecution(int thread_id); - - /** * Forcefully terminate the current thread of JavaScript execution - * in the given isolate. If no isolate is provided, the default - * isolate is used. + * in the given isolate. * * This method can be used by any thread even if that thread has not * acquired the V8 lock with a Locker object. * * \param isolate The isolate in which to terminate the current JS execution. */ - static void TerminateExecution(Isolate* isolate = NULL); + static void TerminateExecution(Isolate* isolate); /** * Is V8 terminating JavaScript execution. @@ -3236,6 +5143,24 @@ class V8EXPORT V8 { static bool IsExecutionTerminating(Isolate* isolate = NULL); /** + * Resume execution capability in the given isolate, whose execution + * was previously forcefully terminated using TerminateExecution(). + * + * When execution is forcefully terminated using TerminateExecution(), + * the isolate can not resume execution until all JavaScript frames + * have propagated the uncatchable exception which is generated. This + * method allows the program embedding the engine to handle the + * termination event and resume execution capability, even if + * JavaScript frames remain on the stack. + * + * This method can be used by any thread even if that thread has not + * acquired the V8 lock with a Locker object. + * + * \param isolate The isolate in which to resume execution capability. + */ + static void CancelTerminateExecution(Isolate* isolate); + + /** * Releases any resources used by v8 and stops any utility threads * that may be running. Note that disposing v8 is permanent, it * cannot be reinitialized. @@ -3247,63 +5172,71 @@ class V8EXPORT V8 { static bool Dispose(); /** - * Get statistics about the heap memory usage. + * Iterates through all external resources referenced from current isolate + * heap. GC is not invoked prior to iterating, therefore there is no + * guarantee that visited objects are still alive. */ - static void GetHeapStatistics(HeapStatistics* heap_statistics); + static void VisitExternalResources(ExternalResourceVisitor* visitor); /** - * Iterates through all external resources referenced from current isolate - * heap. This method is not expected to be used except for debugging purposes - * and may be quite slow. + * Iterates through all the persistent handles in the current isolate's heap + * that have class_ids. */ - static void VisitExternalResources(ExternalResourceVisitor* visitor); + static void VisitHandlesWithClassIds(PersistentHandleVisitor* visitor); /** - * Optional notification that the embedder is idle. - * V8 uses the notification to reduce memory footprint. - * This call can be used repeatedly if the embedder remains idle. - * Returns true if the embedder should stop calling IdleNotification - * until real work has been done. This indicates that V8 has done - * as much cleanup as it will be able to do. + * Iterates through all the persistent handles in the current isolate's heap + * that have class_ids and are candidates to be marked as partially dependent + * handles. This will visit handles to young objects created since the last + * garbage collection but is free to visit an arbitrary superset of these + * objects. + */ + static void VisitHandlesForPartialDependence( + Isolate* isolate, PersistentHandleVisitor* visitor); + + /** + * Initialize the ICU library bundled with V8. The embedder should only + * invoke this method when using the bundled ICU. Returns true on success. * - * The hint argument specifies the amount of work to be done in the function - * on scale from 1 to 1000. There is no guarantee that the actual work will - * match the hint. + * If V8 was compiled with the ICU data in an external file, the location + * of the data file has to be provided. */ - static bool IdleNotification(int hint = 1000); + static bool InitializeICU(const char* icu_data_file = NULL); /** - * Optional notification that the system is running low on memory. - * V8 uses these notifications to attempt to free memory. + * Sets the v8::Platform to use. This should be invoked before V8 is + * initialized. */ - static void LowMemoryNotification(); + static void InitializePlatform(Platform* platform); /** - * Optional notification that a context has been disposed. V8 uses - * these notifications to guide the GC heuristic. Returns the number - * of context disposals - including this one - since the last time - * V8 had a chance to clean up. + * Clears all references to the v8::Platform. This should be invoked after + * V8 was disposed. */ - static int ContextDisposedNotification(); + static void ShutdownPlatform(); private: V8(); - static internal::Object** GlobalizeReference(internal::Object** handle); + static internal::Object** GlobalizeReference(internal::Isolate* isolate, + internal::Object** handle); + static internal::Object** CopyPersistent(internal::Object** handle); static void DisposeGlobal(internal::Object** global_handle); + typedef WeakCallbackData<Value, void>::Callback WeakCallback; static void MakeWeak(internal::Object** global_handle, void* data, - WeakReferenceCallback); - static void ClearWeak(internal::Object** global_handle); - static void MarkIndependent(internal::Object** global_handle); - static bool IsGlobalNearDeath(internal::Object** global_handle); - static bool IsGlobalWeak(internal::Object** global_handle); - static void SetWrapperClassId(internal::Object** global_handle, - uint16_t class_id); + WeakCallback weak_callback); + static void* ClearWeak(internal::Object** global_handle); + static void Eternalize(Isolate* isolate, + Value* handle, + int* index); + static Local<Value> GetEternal(Isolate* isolate, int index); template <class T> friend class Handle; template <class T> friend class Local; - template <class T> friend class Persistent; + template <class T> friend class Eternal; + template <class T> friend class PersistentBase; + template <class T, class M> friend class Persistent; friend class Context; }; @@ -3311,10 +5244,12 @@ class V8EXPORT V8 { /** * An external exception handler. */ -class V8EXPORT TryCatch { +class V8_EXPORT TryCatch { public: /** - * Creates a new try/catch block and registers it with v8. + * Creates a new try/catch block and registers it with v8. Note that + * all TryCatch blocks should be stack allocated because the memory + * location itself is compared against JavaScript try/catch blocks. */ TryCatch(); @@ -3329,21 +5264,30 @@ class V8EXPORT TryCatch { bool HasCaught() const; /** - * For certain types of exceptions, it makes no sense to continue - * execution. + * For certain types of exceptions, it makes no sense to continue execution. * - * Currently, the only type of exception that can be caught by a - * TryCatch handler and for which it does not make sense to continue - * is termination exception. Such exceptions are thrown when the - * TerminateExecution methods are called to terminate a long-running - * script. - * - * If CanContinue returns false, the correct action is to perform - * any C++ cleanup needed and then return. + * If CanContinue returns false, the correct action is to perform any C++ + * cleanup needed and then return. If CanContinue returns false and + * HasTerminated returns true, it is possible to call + * CancelTerminateExecution in order to continue calling into the engine. */ bool CanContinue() const; /** + * Returns true if an exception has been caught due to script execution + * being terminated. + * + * There is no JavaScript representation of an execution termination + * exception. Such exceptions are thrown when the TerminateExecution + * methods are called to terminate a long-running script. + * + * If such an exception has been thrown, HasTerminated will return true, + * indicating that it is possible to call CancelTerminateExecution in order + * to continue calling into the engine. + */ + bool HasTerminated() const; + + /** * Throws the exception caught by this TryCatch in a way that avoids * it being caught again by this same TryCatch. As with ThrowException * it is illegal to execute any JavaScript operations after calling @@ -3377,7 +5321,8 @@ class V8EXPORT TryCatch { /** * Clears any exceptions that may have been caught by this try/catch block. - * After this method has been called, HasCaught() will return false. + * After this method has been called, HasCaught() will return false. Cancels + * the scheduled exception if it is caught and ReThrow() is not called before. * * It is not necessary to clear a try/catch block before using it again; if * another exception is thrown the previously caught exception will just be @@ -3403,15 +5348,44 @@ class V8EXPORT TryCatch { */ void SetCaptureMessage(bool value); + /** + * There are cases when the raw address of C++ TryCatch object cannot be + * used for comparisons with addresses into the JS stack. The cases are: + * 1) ARM, ARM64 and MIPS simulators which have separate JS stack. + * 2) Address sanitizer allocates local C++ object in the heap when + * UseAfterReturn mode is enabled. + * This method returns address that can be used for comparisons with + * addresses into the JS stack. When neither simulator nor ASAN's + * UseAfterReturn is enabled, then the address returned will be the address + * of the C++ try catch handler itself. + */ + static void* JSStackComparableAddress(v8::TryCatch* handler) { + if (handler == NULL) return NULL; + return handler->js_stack_comparable_address_; + } + private: + void ResetInternal(); + + // Make it hard to create heap-allocated TryCatch blocks. + TryCatch(const TryCatch&); + void operator=(const TryCatch&); + void* operator new(size_t size); + void operator delete(void*, size_t); + v8::internal::Isolate* isolate_; - void* next_; + v8::TryCatch* next_; void* exception_; - void* message_; + void* message_obj_; + void* message_script_; + void* js_stack_comparable_address_; + int message_start_pos_; + int message_end_pos_; bool is_verbose_ : 1; bool can_continue_ : 1; bool capture_message_ : 1; bool rethrow_ : 1; + bool has_terminated_ : 1; friend class v8::internal::Isolate; }; @@ -3421,15 +5395,19 @@ class V8EXPORT TryCatch { /** - * Ignore + * A container for extension names. */ -class V8EXPORT ExtensionConfiguration { +class V8_EXPORT ExtensionConfiguration { public: + ExtensionConfiguration() : name_count_(0), names_(NULL) { } ExtensionConfiguration(int name_count, const char* names[]) : name_count_(name_count), names_(names) { } + + const char** begin() const { return &names_[0]; } + const char** end() const { return &names_[name_count_]; } + private: - friend class ImplementationUtilities; - int name_count_; + const int name_count_; const char** names_; }; @@ -3438,23 +5416,19 @@ class V8EXPORT ExtensionConfiguration { * A sandboxed execution context with its own set of built-in objects * and functions. */ -class V8EXPORT Context { +class V8_EXPORT Context { public: /** - * Returns the global proxy object or global object itself for - * detached contexts. + * Returns the global proxy object. * - * Global proxy object is a thin wrapper whose prototype points to - * actual context's global object with the properties like Object, etc. - * This is done that way for security reasons (for more details see + * Global proxy object is a thin wrapper whose prototype points to actual + * context's global object with the properties like Object, etc. This is done + * that way for security reasons (for more details see * https://wiki.mozilla.org/Gecko:SplitWindow). * * Please note that changes to global proxy object prototype most probably - * would break VM---v8 expects only global object as a prototype of - * global proxy object. - * - * If DetachGlobal() has been invoked, Global() would return actual global - * object until global is reattached with ReattachGlobal(). + * would break VM---v8 expects only global object as a prototype of global + * proxy object. */ Local<Object> Global(); @@ -3465,22 +5439,10 @@ class V8EXPORT Context { void DetachGlobal(); /** - * Reattaches a global object to a context. This can be used to - * restore the connection between a global object and a context - * after DetachGlobal has been called. - * - * \param global_object The global object to reattach to the - * context. For this to work, the global object must be the global - * object that was associated with this context before a call to - * DetachGlobal. - */ - void ReattachGlobal(Handle<Object> global_object); - - /** Creates a new context. + * Creates a new context and returns a handle to the newly allocated + * context. * - * Returns a persistent handle to the newly allocated context. This - * persistent handle has to be disposed when the context is no - * longer used so the context can be garbage collected. + * \param isolate The isolate in which to create the context. * * \param extensions An optional extension configuration containing * the extensions to be installed in the newly created context. @@ -3494,24 +5456,12 @@ class V8EXPORT Context { * template. The state of the global object will be completely reset * and only object identify will remain. */ - static Persistent<Context> New( + static Local<Context> New( + Isolate* isolate, ExtensionConfiguration* extensions = NULL, Handle<ObjectTemplate> global_template = Handle<ObjectTemplate>(), Handle<Value> global_object = Handle<Value>()); - /** Returns the last entered context. */ - static Local<Context> GetEntered(); - - /** Returns the context that is on the top of the stack. */ - static Local<Context> GetCurrent(); - - /** - * Returns the context of the calling JavaScript code. That is the - * context of the top-most JavaScript frame. If there are no - * JavaScript frames an empty handle is returned. - */ - static Local<Context> GetCalling(); - /** * Sets the security token for the context. To access an object in * another context, the security tokens must match. @@ -3538,19 +5488,37 @@ class V8EXPORT Context { */ void Exit(); - /** Returns true if the context has experienced an out of memory situation. */ - bool HasOutOfMemoryException(); + /** Returns an isolate associated with a current context. */ + v8::Isolate* GetIsolate(); + + /** + * Gets the embedder data with the given index, which must have been set by a + * previous call to SetEmbedderData with the same index. Note that index 0 + * currently has a special meaning for Chrome's debugger. + */ + V8_INLINE Local<Value> GetEmbedderData(int index); + + /** + * Sets the embedder data with the given index, growing the data as + * needed. Note that index 0 currently has a special meaning for Chrome's + * debugger. + */ + void SetEmbedderData(int index, Handle<Value> value); - /** Returns true if V8 has a current context. */ - static bool InContext(); + /** + * Gets a 2-byte-aligned native pointer from the embedder data with the given + * index, which must have bees set by a previous call to + * SetAlignedPointerInEmbedderData with the same index. Note that index 0 + * currently has a special meaning for Chrome's debugger. + */ + V8_INLINE void* GetAlignedPointerFromEmbedderData(int index); /** - * Associate an additional data object with the context. This is mainly used - * with the debugger to provide additional information on the context through - * the debugger API. + * Sets a 2-byte-aligned native pointer in the embedder data with the given + * index, growing the data as needed. Note that index 0 currently has a + * special meaning for Chrome's debugger. */ - void SetData(Handle<String> data); - Local<Value> GetData(); + void SetAlignedPointerInEmbedderData(int index, void* value); /** * Control whether code generation from strings is allowed. Calling @@ -3574,15 +5542,23 @@ class V8EXPORT Context { bool IsCodeGenerationFromStringsAllowed(); /** + * Sets the error description for the exception that is thrown when + * code generation from strings is not allowed and 'eval' or the 'Function' + * constructor are called. + */ + void SetErrorMessageForCodeGenerationFromStrings(Handle<String> message); + + /** * Stack-allocated class which sets the execution context for all * operations executed within a local scope. */ class Scope { public: - explicit inline Scope(Handle<Context> context) : context_(context) { + explicit V8_INLINE Scope(Handle<Context> context) : context_(context) { context_->Enter(); } - inline ~Scope() { context_->Exit(); } + V8_INLINE ~Scope() { context_->Exit(); } + private: Handle<Context> context_; }; @@ -3592,25 +5568,26 @@ class V8EXPORT Context { friend class Script; friend class Object; friend class Function; + + Local<Value> SlowGetEmbedderData(int index); + void* SlowGetAlignedPointerFromEmbedderData(int index); }; /** - * Multiple threads in V8 are allowed, but only one thread at a time - * is allowed to use any given V8 isolate. See Isolate class - * comments. The definition of 'using V8 isolate' includes - * accessing handles or holding onto object pointers obtained - * from V8 handles while in the particular V8 isolate. It is up - * to the user of V8 to ensure (perhaps with locking) that this - * constraint is not violated. In addition to any other synchronization - * mechanism that may be used, the v8::Locker and v8::Unlocker classes - * must be used to signal thead switches to V8. + * Multiple threads in V8 are allowed, but only one thread at a time is allowed + * to use any given V8 isolate, see the comments in the Isolate class. The + * definition of 'using a V8 isolate' includes accessing handles or holding onto + * object pointers obtained from V8 handles while in the particular V8 isolate. + * It is up to the user of V8 to ensure, perhaps with locking, that this + * constraint is not violated. In addition to any other synchronization + * mechanism that may be used, the v8::Locker and v8::Unlocker classes must be + * used to signal thead switches to V8. * - * v8::Locker is a scoped lock object. While it's - * active (i.e. between its construction and destruction) the current thread is - * allowed to use the locked isolate. V8 guarantees that an isolate can be - * locked by at most one thread at any time. In other words, the scope of a - * v8::Locker is a critical section. + * v8::Locker is a scoped lock object. While it's active, i.e. between its + * construction and destruction, the current thread is allowed to use the locked + * isolate. V8 guarantees that an isolate can be locked by at most one thread at + * any time. In other words, the scope of a v8::Locker is a critical section. * * Sample usage: * \code @@ -3624,9 +5601,9 @@ class V8EXPORT Context { * } // Destructor called here * \endcode * - * If you wish to stop using V8 in a thread A you can do this either - * by destroying the v8::Locker object as above or by constructing a - * v8::Unlocker object: + * If you wish to stop using V8 in a thread A you can do this either by + * destroying the v8::Locker object as above or by constructing a v8::Unlocker + * object: * * \code * { @@ -3639,19 +5616,17 @@ class V8EXPORT Context { * isolate->Enter(); * \endcode * - * The Unlocker object is intended for use in a long-running callback - * from V8, where you want to release the V8 lock for other threads to - * use. + * The Unlocker object is intended for use in a long-running callback from V8, + * where you want to release the V8 lock for other threads to use. * - * The v8::Locker is a recursive lock. That is, you can lock more than - * once in a given thread. This can be useful if you have code that can - * be called either from code that holds the lock or from code that does - * not. The Unlocker is not recursive so you can not have several - * Unlockers on the stack at once, and you can not use an Unlocker in a - * thread that is not inside a Locker's scope. + * The v8::Locker is a recursive lock, i.e. you can lock more than once in a + * given thread. This can be useful if you have code that can be called either + * from code that holds the lock or from code that does not. The Unlocker is + * not recursive so you can not have several Unlockers on the stack at once, and + * you can not use an Unlocker in a thread that is not inside a Locker's scope. * - * An unlocker will unlock several lockers if it has to and reinstate - * the correct depth of locking on its destruction. eg.: + * An unlocker will unlock several lockers if it has to and reinstate the + * correct depth of locking on its destruction, e.g.: * * \code * // V8 not locked. @@ -3674,48 +5649,36 @@ class V8EXPORT Context { * } * // V8 Now no longer locked. * \endcode - * - * */ -class V8EXPORT Unlocker { +class V8_EXPORT Unlocker { public: /** - * Initialize Unlocker for a given Isolate. NULL means default isolate. + * Initialize Unlocker for a given Isolate. */ - explicit Unlocker(Isolate* isolate = NULL); + V8_INLINE explicit Unlocker(Isolate* isolate) { Initialize(isolate); } + ~Unlocker(); private: + void Initialize(Isolate* isolate); + internal::Isolate* isolate_; }; -class V8EXPORT Locker { +class V8_EXPORT Locker { public: /** - * Initialize Locker for a given Isolate. NULL means default isolate. - */ - explicit Locker(Isolate* isolate = NULL); - ~Locker(); - - /** - * Start preemption. - * - * When preemption is started, a timer is fired every n milliseconds - * that will switch between multiple threads that are in contention - * for the V8 lock. + * Initialize Locker for a given Isolate. */ - static void StartPreemption(int every_n_ms); + V8_INLINE explicit Locker(Isolate* isolate) { Initialize(isolate); } - /** - * Stop preemption. - */ - static void StopPreemption(); + ~Locker(); /** - * Returns whether or not the locker for a given isolate, or default isolate - * if NULL is given, is locked by the current thread. + * Returns whether or not the locker for a given isolate, is locked by the + * current thread. */ - static bool IsLocked(Isolate* isolate = NULL); + static bool IsLocked(Isolate* isolate); /** * Returns whether v8::Locker is being used by this V8 instance. @@ -3723,6 +5686,8 @@ class V8EXPORT Locker { static bool IsActive(); private: + void Initialize(Isolate* isolate); + bool has_lock_; bool top_level_; internal::Isolate* isolate_; @@ -3735,53 +5700,6 @@ class V8EXPORT Locker { }; -/** - * An interface for exporting data from V8, using "push" model. - */ -class V8EXPORT OutputStream { // NOLINT - public: - enum OutputEncoding { - kAscii = 0 // 7-bit ASCII. - }; - 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; } - /** Get preferred output encoding. Called only once. */ - virtual OutputEncoding GetOutputEncoding() { return kAscii; } - /** - * 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; -}; - - -/** - * An interface for reporting progress and controlling long-running - * activities. - */ -class V8EXPORT 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; -}; - - // --- Implementation --- @@ -3789,6 +5707,7 @@ namespace internal { const int kApiPointerSize = sizeof(void*); // NOLINT const int kApiIntSize = sizeof(int); // NOLINT +const int kApiInt64Size = sizeof(int64_t); // NOLINT // Tag information for HeapObject. const int kHeapObjectTag = 1; @@ -3802,63 +5721,67 @@ const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1; template <size_t ptr_size> struct SmiTagging; +template<int kSmiShiftSize> +V8_INLINE internal::Object* IntToSmi(int value) { + int smi_shift_bits = kSmiTagSize + kSmiShiftSize; + uintptr_t tagged_value = + (static_cast<uintptr_t>(value) << smi_shift_bits) | kSmiTag; + return reinterpret_cast<internal::Object*>(tagged_value); +} + // Smi constants for 32-bit systems. template <> struct SmiTagging<4> { - static const int kSmiShiftSize = 0; - static const int kSmiValueSize = 31; - static inline int SmiToInt(internal::Object* value) { + enum { kSmiShiftSize = 0, kSmiValueSize = 31 }; + static int SmiShiftSize() { return kSmiShiftSize; } + static int SmiValueSize() { return kSmiValueSize; } + V8_INLINE static int SmiToInt(const internal::Object* value) { int shift_bits = kSmiTagSize + kSmiShiftSize; // Throw away top 32 bits and shift down (requires >> to be sign extending). return static_cast<int>(reinterpret_cast<intptr_t>(value)) >> shift_bits; } - - // For 32-bit systems any 2 bytes aligned pointer can be encoded as smi - // with a plain reinterpret_cast. - static const uintptr_t kEncodablePointerMask = 0x1; - static const int kPointerToSmiShift = 0; + V8_INLINE static internal::Object* IntToSmi(int value) { + return internal::IntToSmi<kSmiShiftSize>(value); + } + V8_INLINE static bool IsValidSmi(intptr_t value) { + // To be representable as an tagged small integer, the two + // most-significant bits of 'value' must be either 00 or 11 due to + // sign-extension. To check this we add 01 to the two + // most-significant bits, and check if the most-significant bit is 0 + // + // CAUTION: The original code below: + // bool result = ((value + 0x40000000) & 0x80000000) == 0; + // may lead to incorrect results according to the C language spec, and + // in fact doesn't work correctly with gcc4.1.1 in some cases: The + // compiler may produce undefined results in case of signed integer + // overflow. The computation must be done w/ unsigned ints. + return static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U; + } }; // Smi constants for 64-bit systems. template <> struct SmiTagging<8> { - static const int kSmiShiftSize = 31; - static const int kSmiValueSize = 32; - static inline int SmiToInt(internal::Object* value) { + enum { kSmiShiftSize = 31, kSmiValueSize = 32 }; + static int SmiShiftSize() { return kSmiShiftSize; } + static int SmiValueSize() { return kSmiValueSize; } + V8_INLINE static int SmiToInt(const internal::Object* value) { int shift_bits = kSmiTagSize + kSmiShiftSize; // Shift down and throw away top 32 bits. return static_cast<int>(reinterpret_cast<intptr_t>(value) >> shift_bits); } - - // To maximize the range of pointers that can be encoded - // in the available 32 bits, we require them to be 8 bytes aligned. - // This gives 2 ^ (32 + 3) = 32G address space covered. - // It might be not enough to cover stack allocated objects on some platforms. - static const int kPointerAlignment = 3; - - static const uintptr_t kEncodablePointerMask = - ~(uintptr_t(0xffffffff) << kPointerAlignment); - - static const int kPointerToSmiShift = - kSmiTagSize + kSmiShiftSize - kPointerAlignment; + V8_INLINE static internal::Object* IntToSmi(int value) { + return internal::IntToSmi<kSmiShiftSize>(value); + } + V8_INLINE static bool IsValidSmi(intptr_t value) { + // To be representable as a long smi, the value must be a 32-bit integer. + return (value == static_cast<int32_t>(value)); + } }; typedef SmiTagging<kApiPointerSize> PlatformSmiTagging; const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize; const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize; -const uintptr_t kEncodablePointerMask = - PlatformSmiTagging::kEncodablePointerMask; -const int kPointerToSmiShift = PlatformSmiTagging::kPointerToSmiShift; - -template <size_t ptr_size> struct InternalConstants; - -// Internal constants for 32-bit systems. -template <> struct InternalConstants<4> { - static const int kStringResourceOffset = 3 * kApiPointerSize; -}; - -// Internal constants for 64-bit systems. -template <> struct InternalConstants<8> { - static const int kStringResourceOffset = 3 * kApiPointerSize; -}; +V8_INLINE static bool SmiValuesAre31Bits() { return kSmiValueSize == 31; } +V8_INLINE static bool SmiValuesAre32Bits() { return kSmiValueSize == 32; } /** * This class exports constants and functionality from within v8 that @@ -3870,71 +5793,163 @@ class Internals { // These values match non-compiler-dependent values defined within // the implementation of v8. static const int kHeapObjectMapOffset = 0; - static const int kMapInstanceTypeOffset = 1 * kApiPointerSize + kApiIntSize; - static const int kStringResourceOffset = - InternalConstants<kApiPointerSize>::kStringResourceOffset; + static const int kMapInstanceTypeAndBitFieldOffset = + 1 * kApiPointerSize + kApiIntSize; + static const int kStringResourceOffset = 3 * kApiPointerSize; + static const int kOddballKindOffset = 3 * kApiPointerSize; static const int kForeignAddressOffset = kApiPointerSize; static const int kJSObjectHeaderSize = 3 * kApiPointerSize; + static const int kFixedArrayHeaderSize = 2 * kApiPointerSize; + static const int kContextHeaderSize = 2 * kApiPointerSize; + static const int kContextEmbedderDataIndex = 95; static const int kFullStringRepresentationMask = 0x07; + static const int kStringEncodingMask = 0x4; static const int kExternalTwoByteRepresentationTag = 0x02; - - static const int kJSObjectType = 0xaa; + static const int kExternalOneByteRepresentationTag = 0x06; + + static const int kIsolateEmbedderDataOffset = 0 * kApiPointerSize; + static const int kAmountOfExternalAllocatedMemoryOffset = + 4 * kApiPointerSize; + static const int kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset = + kAmountOfExternalAllocatedMemoryOffset + kApiInt64Size; + static const int kIsolateRootsOffset = + kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset + kApiInt64Size + + kApiPointerSize; + static const int kUndefinedValueRootIndex = 5; + static const int kNullValueRootIndex = 7; + static const int kTrueValueRootIndex = 8; + static const int kFalseValueRootIndex = 9; + static const int kEmptyStringRootIndex = 164; + + // The external allocation limit should be below 256 MB on all architectures + // to avoid that resource-constrained embedders run low on memory. + static const int kExternalAllocationLimit = 192 * 1024 * 1024; + + static const int kNodeClassIdOffset = 1 * kApiPointerSize; + static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3; + static const int kNodeStateMask = 0xf; + static const int kNodeStateIsWeakValue = 2; + static const int kNodeStateIsPendingValue = 3; + static const int kNodeStateIsNearDeathValue = 4; + static const int kNodeIsIndependentShift = 4; + static const int kNodeIsPartiallyDependentShift = 5; + + static const int kJSObjectType = 0xbc; static const int kFirstNonstringType = 0x80; - static const int kForeignType = 0x85; + static const int kOddballType = 0x83; + static const int kForeignType = 0x88; - static inline bool HasHeapObjectTag(internal::Object* value) { + static const int kUndefinedOddballKind = 5; + static const int kNullOddballKind = 3; + + static const uint32_t kNumIsolateDataSlots = 4; + + V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate); + V8_INLINE static void CheckInitialized(v8::Isolate* isolate) { +#ifdef V8_ENABLE_CHECKS + CheckInitializedImpl(isolate); +#endif + } + + V8_INLINE static bool HasHeapObjectTag(const internal::Object* value) { return ((reinterpret_cast<intptr_t>(value) & kHeapObjectTagMask) == kHeapObjectTag); } - static inline bool HasSmiTag(internal::Object* value) { - return ((reinterpret_cast<intptr_t>(value) & kSmiTagMask) == kSmiTag); + V8_INLINE static int SmiValue(const internal::Object* value) { + return PlatformSmiTagging::SmiToInt(value); + } + + V8_INLINE static internal::Object* IntToSmi(int value) { + return PlatformSmiTagging::IntToSmi(value); } - static inline int SmiValue(internal::Object* value) { - return PlatformSmiTagging::SmiToInt(value); + V8_INLINE static bool IsValidSmi(intptr_t value) { + return PlatformSmiTagging::IsValidSmi(value); } - static inline int GetInstanceType(internal::Object* obj) { + V8_INLINE static int GetInstanceType(const internal::Object* obj) { typedef internal::Object O; O* map = ReadField<O*>(obj, kHeapObjectMapOffset); - return ReadField<uint8_t>(map, kMapInstanceTypeOffset); + // Map::InstanceType is defined so that it will always be loaded into + // the LS 8 bits of one 16-bit word, regardless of endianess. + return ReadField<uint16_t>(map, kMapInstanceTypeAndBitFieldOffset) & 0xff; } - static inline void* GetExternalPointerFromSmi(internal::Object* value) { - const uintptr_t address = reinterpret_cast<uintptr_t>(value); - return reinterpret_cast<void*>(address >> kPointerToSmiShift); - } - - static inline void* GetExternalPointer(internal::Object* obj) { - if (HasSmiTag(obj)) { - return GetExternalPointerFromSmi(obj); - } else if (GetInstanceType(obj) == kForeignType) { - return ReadField<void*>(obj, kForeignAddressOffset); - } else { - return NULL; - } + V8_INLINE static int GetOddballKind(const internal::Object* obj) { + typedef internal::Object O; + return SmiValue(ReadField<O*>(obj, kOddballKindOffset)); } - static inline bool IsExternalTwoByteString(int instance_type) { + V8_INLINE static bool IsExternalTwoByteString(int instance_type) { int representation = (instance_type & kFullStringRepresentationMask); return representation == kExternalTwoByteRepresentationTag; } + V8_INLINE static uint8_t GetNodeFlag(internal::Object** obj, int shift) { + uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; + return *addr & static_cast<uint8_t>(1U << shift); + } + + V8_INLINE static void UpdateNodeFlag(internal::Object** obj, + bool value, int shift) { + uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; + uint8_t mask = static_cast<uint8_t>(1U << shift); + *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift)); + } + + V8_INLINE static uint8_t GetNodeState(internal::Object** obj) { + uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; + return *addr & kNodeStateMask; + } + + V8_INLINE static void UpdateNodeState(internal::Object** obj, + uint8_t value) { + uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; + *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value); + } + + V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, + uint32_t slot, + void* data) { + uint8_t *addr = reinterpret_cast<uint8_t *>(isolate) + + kIsolateEmbedderDataOffset + slot * kApiPointerSize; + *reinterpret_cast<void**>(addr) = data; + } + + V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate, + uint32_t slot) { + const uint8_t* addr = reinterpret_cast<const uint8_t*>(isolate) + + kIsolateEmbedderDataOffset + slot * kApiPointerSize; + return *reinterpret_cast<void* const*>(addr); + } + + V8_INLINE static internal::Object** GetRoot(v8::Isolate* isolate, + int index) { + uint8_t* addr = reinterpret_cast<uint8_t*>(isolate) + kIsolateRootsOffset; + return reinterpret_cast<internal::Object**>(addr + index * kApiPointerSize); + } + template <typename T> - static inline T ReadField(Object* ptr, int offset) { - uint8_t* addr = reinterpret_cast<uint8_t*>(ptr) + offset - kHeapObjectTag; - return *reinterpret_cast<T*>(addr); + V8_INLINE static T ReadField(const internal::Object* ptr, int offset) { + const uint8_t* addr = + reinterpret_cast<const uint8_t*>(ptr) + offset - kHeapObjectTag; + return *reinterpret_cast<const T*>(addr); } - static inline bool CanCastToHeapObject(void* o) { return false; } - static inline bool CanCastToHeapObject(Context* o) { return true; } - static inline bool CanCastToHeapObject(String* o) { return true; } - static inline bool CanCastToHeapObject(Object* o) { return true; } - static inline bool CanCastToHeapObject(Message* o) { return true; } - static inline bool CanCastToHeapObject(StackTrace* o) { return true; } - static inline bool CanCastToHeapObject(StackFrame* o) { return true; } + template <typename T> + V8_INLINE static T ReadEmbedderData(const v8::Context* context, int index) { + typedef internal::Object O; + typedef internal::Internals I; + O* ctx = *reinterpret_cast<O* const*>(context); + int embedder_data_offset = I::kContextHeaderSize + + (internal::kApiPointerSize * I::kContextEmbedderDataIndex); + O* embedder_data = I::ReadField<O*>(ctx, embedder_data_offset); + int value_offset = + I::kFixedArrayHeaderSize + (internal::kApiPointerSize * index); + return I::ReadField<T>(embedder_data, value_offset); + } }; } // namespace internal @@ -3945,126 +5960,384 @@ Local<T>::Local() : Handle<T>() { } template <class T> -Local<T> Local<T>::New(Handle<T> that) { - if (that.IsEmpty()) return Local<T>(); - T* that_ptr = *that; +Local<T> Local<T>::New(Isolate* isolate, Handle<T> that) { + return New(isolate, that.val_); +} + +template <class T> +Local<T> Local<T>::New(Isolate* isolate, const PersistentBase<T>& that) { + return New(isolate, that.val_); +} + +template <class T> +Handle<T> Handle<T>::New(Isolate* isolate, T* that) { + if (that == NULL) return Handle<T>(); + T* that_ptr = that; internal::Object** p = reinterpret_cast<internal::Object**>(that_ptr); - if (internal::Internals::CanCastToHeapObject(that_ptr)) { - return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle( - reinterpret_cast<internal::HeapObject*>(*p)))); - } - return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle(*p))); + return Handle<T>(reinterpret_cast<T*>(HandleScope::CreateHandle( + reinterpret_cast<internal::Isolate*>(isolate), *p))); } template <class T> -Persistent<T> Persistent<T>::New(Handle<T> that) { - if (that.IsEmpty()) return Persistent<T>(); - internal::Object** p = reinterpret_cast<internal::Object**>(*that); - return Persistent<T>(reinterpret_cast<T*>(V8::GlobalizeReference(p))); +Local<T> Local<T>::New(Isolate* isolate, T* that) { + if (that == NULL) return Local<T>(); + T* that_ptr = that; + internal::Object** p = reinterpret_cast<internal::Object**>(that_ptr); + return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle( + reinterpret_cast<internal::Isolate*>(isolate), *p))); +} + + +template<class T> +template<class S> +void Eternal<T>::Set(Isolate* isolate, Local<S> handle) { + TYPE_CHECK(T, S); + V8::Eternalize(isolate, reinterpret_cast<Value*>(*handle), &this->index_); +} + + +template<class T> +Local<T> Eternal<T>::Get(Isolate* isolate) { + return Local<T>(reinterpret_cast<T*>(*V8::GetEternal(isolate, index_))); } template <class T> -bool Persistent<T>::IsNearDeath() const { +T* PersistentBase<T>::New(Isolate* isolate, T* that) { + if (that == NULL) return NULL; + internal::Object** p = reinterpret_cast<internal::Object**>(that); + return reinterpret_cast<T*>( + V8::GlobalizeReference(reinterpret_cast<internal::Isolate*>(isolate), + p)); +} + + +template <class T, class M> +template <class S, class M2> +void Persistent<T, M>::Copy(const Persistent<S, M2>& that) { + TYPE_CHECK(T, S); + this->Reset(); + if (that.IsEmpty()) return; + internal::Object** p = reinterpret_cast<internal::Object**>(that.val_); + this->val_ = reinterpret_cast<T*>(V8::CopyPersistent(p)); + M::Copy(that, this); +} + + +template <class T> +bool PersistentBase<T>::IsIndependent() const { + typedef internal::Internals I; if (this->IsEmpty()) return false; - return V8::IsGlobalNearDeath(reinterpret_cast<internal::Object**>(**this)); + return I::GetNodeFlag(reinterpret_cast<internal::Object**>(this->val_), + I::kNodeIsIndependentShift); } template <class T> -bool Persistent<T>::IsWeak() const { +bool PersistentBase<T>::IsNearDeath() const { + typedef internal::Internals I; if (this->IsEmpty()) return false; - return V8::IsGlobalWeak(reinterpret_cast<internal::Object**>(**this)); + uint8_t node_state = + I::GetNodeState(reinterpret_cast<internal::Object**>(this->val_)); + return node_state == I::kNodeStateIsNearDeathValue || + node_state == I::kNodeStateIsPendingValue; } template <class T> -void Persistent<T>::Dispose() { +bool PersistentBase<T>::IsWeak() const { + typedef internal::Internals I; + if (this->IsEmpty()) return false; + return I::GetNodeState(reinterpret_cast<internal::Object**>(this->val_)) == + I::kNodeStateIsWeakValue; +} + + +template <class T> +void PersistentBase<T>::Reset() { if (this->IsEmpty()) return; - V8::DisposeGlobal(reinterpret_cast<internal::Object**>(**this)); + V8::DisposeGlobal(reinterpret_cast<internal::Object**>(this->val_)); + val_ = 0; +} + + +template <class T> +template <class S> +void PersistentBase<T>::Reset(Isolate* isolate, const Handle<S>& other) { + TYPE_CHECK(T, S); + Reset(); + if (other.IsEmpty()) return; + this->val_ = New(isolate, other.val_); } template <class T> -Persistent<T>::Persistent() : Handle<T>() { } +template <class S> +void PersistentBase<T>::Reset(Isolate* isolate, + const PersistentBase<S>& other) { + TYPE_CHECK(T, S); + Reset(); + if (other.IsEmpty()) return; + this->val_ = New(isolate, other.val_); +} + + +template <class T> +template <typename S, typename P> +void PersistentBase<T>::SetWeak( + P* parameter, + typename WeakCallbackData<S, P>::Callback callback) { + TYPE_CHECK(S, T); + typedef typename WeakCallbackData<Value, void>::Callback Callback; + V8::MakeWeak(reinterpret_cast<internal::Object**>(this->val_), + parameter, + reinterpret_cast<Callback>(callback)); +} + template <class T> -void Persistent<T>::MakeWeak(void* parameters, WeakReferenceCallback callback) { - V8::MakeWeak(reinterpret_cast<internal::Object**>(**this), - parameters, - callback); +template <typename P> +void PersistentBase<T>::SetWeak( + P* parameter, + typename WeakCallbackData<T, P>::Callback callback) { + SetWeak<T, P>(parameter, callback); } + template <class T> -void Persistent<T>::ClearWeak() { - V8::ClearWeak(reinterpret_cast<internal::Object**>(**this)); +template<typename P> +P* PersistentBase<T>::ClearWeak() { + return reinterpret_cast<P*>( + V8::ClearWeak(reinterpret_cast<internal::Object**>(this->val_))); } + template <class T> -void Persistent<T>::MarkIndependent() { - V8::MarkIndependent(reinterpret_cast<internal::Object**>(**this)); +void PersistentBase<T>::MarkIndependent() { + typedef internal::Internals I; + if (this->IsEmpty()) return; + I::UpdateNodeFlag(reinterpret_cast<internal::Object**>(this->val_), + true, + I::kNodeIsIndependentShift); } + template <class T> -void Persistent<T>::SetWrapperClassId(uint16_t class_id) { - V8::SetWrapperClassId(reinterpret_cast<internal::Object**>(**this), class_id); +void PersistentBase<T>::MarkPartiallyDependent() { + typedef internal::Internals I; + if (this->IsEmpty()) return; + I::UpdateNodeFlag(reinterpret_cast<internal::Object**>(this->val_), + true, + I::kNodeIsPartiallyDependentShift); +} + + +template <class T, class M> +T* Persistent<T, M>::ClearAndLeak() { + T* old; + old = this->val_; + this->val_ = NULL; + return old; +} + + +template <class T> +void PersistentBase<T>::SetWrapperClassId(uint16_t class_id) { + typedef internal::Internals I; + if (this->IsEmpty()) return; + internal::Object** obj = reinterpret_cast<internal::Object**>(this->val_); + uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + I::kNodeClassIdOffset; + *reinterpret_cast<uint16_t*>(addr) = class_id; +} + + +template <class T> +uint16_t PersistentBase<T>::WrapperClassId() const { + typedef internal::Internals I; + if (this->IsEmpty()) return 0; + internal::Object** obj = reinterpret_cast<internal::Object**>(this->val_); + uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + I::kNodeClassIdOffset; + return *reinterpret_cast<uint16_t*>(addr); +} + + +template<typename T> +ReturnValue<T>::ReturnValue(internal::Object** slot) : value_(slot) {} + +template<typename T> +template<typename S> +void ReturnValue<T>::Set(const Persistent<S>& handle) { + TYPE_CHECK(T, S); + if (V8_UNLIKELY(handle.IsEmpty())) { + *value_ = GetDefaultValue(); + } else { + *value_ = *reinterpret_cast<internal::Object**>(*handle); + } +} + +template<typename T> +template<typename S> +void ReturnValue<T>::Set(const Handle<S> handle) { + TYPE_CHECK(T, S); + if (V8_UNLIKELY(handle.IsEmpty())) { + *value_ = GetDefaultValue(); + } else { + *value_ = *reinterpret_cast<internal::Object**>(*handle); + } +} + +template<typename T> +void ReturnValue<T>::Set(double i) { + TYPE_CHECK(T, Number); + Set(Number::New(GetIsolate(), i)); +} + +template<typename T> +void ReturnValue<T>::Set(int32_t i) { + TYPE_CHECK(T, Integer); + typedef internal::Internals I; + if (V8_LIKELY(I::IsValidSmi(i))) { + *value_ = I::IntToSmi(i); + return; + } + Set(Integer::New(GetIsolate(), i)); +} + +template<typename T> +void ReturnValue<T>::Set(uint32_t i) { + TYPE_CHECK(T, Integer); + // Can't simply use INT32_MAX here for whatever reason. + bool fits_into_int32_t = (i & (1U << 31)) == 0; + if (V8_LIKELY(fits_into_int32_t)) { + Set(static_cast<int32_t>(i)); + return; + } + Set(Integer::NewFromUnsigned(GetIsolate(), i)); } -Arguments::Arguments(internal::Object** implicit_args, - internal::Object** values, int length, - bool is_construct_call) +template<typename T> +void ReturnValue<T>::Set(bool value) { + TYPE_CHECK(T, Boolean); + typedef internal::Internals I; + int root_index; + if (value) { + root_index = I::kTrueValueRootIndex; + } else { + root_index = I::kFalseValueRootIndex; + } + *value_ = *I::GetRoot(GetIsolate(), root_index); +} + +template<typename T> +void ReturnValue<T>::SetNull() { + TYPE_CHECK(T, Primitive); + typedef internal::Internals I; + *value_ = *I::GetRoot(GetIsolate(), I::kNullValueRootIndex); +} + +template<typename T> +void ReturnValue<T>::SetUndefined() { + TYPE_CHECK(T, Primitive); + typedef internal::Internals I; + *value_ = *I::GetRoot(GetIsolate(), I::kUndefinedValueRootIndex); +} + +template<typename T> +void ReturnValue<T>::SetEmptyString() { + TYPE_CHECK(T, String); + typedef internal::Internals I; + *value_ = *I::GetRoot(GetIsolate(), I::kEmptyStringRootIndex); +} + +template<typename T> +Isolate* ReturnValue<T>::GetIsolate() { + // Isolate is always the pointer below the default value on the stack. + return *reinterpret_cast<Isolate**>(&value_[-2]); +} + +template<typename T> +template<typename S> +void ReturnValue<T>::Set(S* whatever) { + // Uncompilable to prevent inadvertent misuse. + TYPE_CHECK(S*, Primitive); +} + +template<typename T> +internal::Object* ReturnValue<T>::GetDefaultValue() { + // Default value is always the pointer below value_ on the stack. + return value_[-1]; +} + + +template<typename T> +FunctionCallbackInfo<T>::FunctionCallbackInfo(internal::Object** implicit_args, + internal::Object** values, + int length, + bool is_construct_call) : implicit_args_(implicit_args), values_(values), length_(length), is_construct_call_(is_construct_call) { } -Local<Value> Arguments::operator[](int i) const { - if (i < 0 || length_ <= i) return Local<Value>(*Undefined()); +template<typename T> +Local<Value> FunctionCallbackInfo<T>::operator[](int i) const { + if (i < 0 || length_ <= i) return Local<Value>(*Undefined(GetIsolate())); return Local<Value>(reinterpret_cast<Value*>(values_ - i)); } -Local<Function> Arguments::Callee() const { +template<typename T> +Local<Function> FunctionCallbackInfo<T>::Callee() const { return Local<Function>(reinterpret_cast<Function*>( &implicit_args_[kCalleeIndex])); } -Local<Object> Arguments::This() const { +template<typename T> +Local<Object> FunctionCallbackInfo<T>::This() const { return Local<Object>(reinterpret_cast<Object*>(values_ + 1)); } -Local<Object> Arguments::Holder() const { +template<typename T> +Local<Object> FunctionCallbackInfo<T>::Holder() const { return Local<Object>(reinterpret_cast<Object*>( &implicit_args_[kHolderIndex])); } -Local<Value> Arguments::Data() const { +template<typename T> +Local<Value> FunctionCallbackInfo<T>::Data() const { return Local<Value>(reinterpret_cast<Value*>(&implicit_args_[kDataIndex])); } -bool Arguments::IsConstructCall() const { - return is_construct_call_; +template<typename T> +Isolate* FunctionCallbackInfo<T>::GetIsolate() const { + return *reinterpret_cast<Isolate**>(&implicit_args_[kIsolateIndex]); } -int Arguments::Length() const { - return length_; +template<typename T> +ReturnValue<T> FunctionCallbackInfo<T>::GetReturnValue() const { + return ReturnValue<T>(&implicit_args_[kReturnValueIndex]); } -template <class T> -Local<T> HandleScope::Close(Handle<T> value) { - internal::Object** before = reinterpret_cast<internal::Object**>(*value); - internal::Object** after = RawClose(before); - return Local<T>(reinterpret_cast<T*>(after)); +template<typename T> +bool FunctionCallbackInfo<T>::IsConstructCall() const { + return is_construct_call_; } + +template<typename T> +int FunctionCallbackInfo<T>::Length() const { + return length_; +} + + Handle<Value> ScriptOrigin::ResourceName() const { return resource_name_; } @@ -4080,75 +6353,84 @@ Handle<Integer> ScriptOrigin::ResourceColumnOffset() const { } -Handle<Boolean> Boolean::New(bool value) { - return value ? True() : False(); +Handle<Boolean> ScriptOrigin::ResourceIsSharedCrossOrigin() const { + return resource_is_shared_cross_origin_; } -void Template::Set(const char* name, v8::Handle<Data> value) { - Set(v8::String::New(name), value); +Handle<Integer> ScriptOrigin::ScriptID() const { + return script_id_; } -Local<Value> Object::GetInternalField(int index) { -#ifndef V8_ENABLE_CHECKS - Local<Value> quick_result = UncheckedGetInternalField(index); - if (!quick_result.IsEmpty()) return quick_result; -#endif - return CheckedGetInternalField(index); +ScriptCompiler::Source::Source(Local<String> string, const ScriptOrigin& origin, + CachedData* data) + : source_string(string), + resource_name(origin.ResourceName()), + resource_line_offset(origin.ResourceLineOffset()), + resource_column_offset(origin.ResourceColumnOffset()), + resource_is_shared_cross_origin(origin.ResourceIsSharedCrossOrigin()), + cached_data(data) {} + + +ScriptCompiler::Source::Source(Local<String> string, + CachedData* data) + : source_string(string), cached_data(data) {} + + +ScriptCompiler::Source::~Source() { + delete cached_data; } -Local<Value> Object::UncheckedGetInternalField(int index) { - typedef internal::Object O; - typedef internal::Internals I; - O* obj = *reinterpret_cast<O**>(this); - if (I::GetInstanceType(obj) == I::kJSObjectType) { - // If the object is a plain JSObject, which is the common case, - // we know where to find the internal fields and can return the - // value directly. - int offset = I::kJSObjectHeaderSize + (internal::kApiPointerSize * index); - O* value = I::ReadField<O*>(obj, offset); - O** result = HandleScope::CreateHandle(value); - return Local<Value>(reinterpret_cast<Value*>(result)); - } else { - return Local<Value>(); - } +const ScriptCompiler::CachedData* ScriptCompiler::Source::GetCachedData() + const { + return cached_data; } -void* External::Unwrap(Handle<v8::Value> obj) { -#ifdef V8_ENABLE_CHECKS - return FullUnwrap(obj); -#else - return QuickUnwrap(obj); -#endif +Handle<Boolean> Boolean::New(Isolate* isolate, bool value) { + return value ? True(isolate) : False(isolate); } -void* External::QuickUnwrap(Handle<v8::Value> wrapper) { - typedef internal::Object O; - O* obj = *reinterpret_cast<O**>(const_cast<v8::Value*>(*wrapper)); - return internal::Internals::GetExternalPointer(obj); +void Template::Set(Isolate* isolate, const char* name, v8::Handle<Data> value) { + Set(v8::String::NewFromUtf8(isolate, name), value); } -void* Object::GetPointerFromInternalField(int index) { +Local<Value> Object::GetInternalField(int index) { +#ifndef V8_ENABLE_CHECKS typedef internal::Object O; + typedef internal::HeapObject HO; typedef internal::Internals I; - O* obj = *reinterpret_cast<O**>(this); - + // Fast path: If the object is a plain JSObject, which is the common case, we + // know where to find the internal fields and can return the value directly. if (I::GetInstanceType(obj) == I::kJSObjectType) { - // If the object is a plain JSObject, which is the common case, - // we know where to find the internal fields and can return the - // value directly. int offset = I::kJSObjectHeaderSize + (internal::kApiPointerSize * index); O* value = I::ReadField<O*>(obj, offset); - return I::GetExternalPointer(value); + O** result = HandleScope::CreateHandle(reinterpret_cast<HO*>(obj), value); + return Local<Value>(reinterpret_cast<Value*>(result)); } +#endif + return SlowGetInternalField(index); +} - return SlowGetPointerFromInternalField(index); + +void* Object::GetAlignedPointerFromInternalField(int index) { +#ifndef V8_ENABLE_CHECKS + typedef internal::Object O; + typedef internal::Internals I; + O* obj = *reinterpret_cast<O**>(this); + // Fast path: If the object is a plain JSObject, which is the common case, we + // know where to find the internal fields and can return the value directly. + if (V8_LIKELY(I::GetInstanceType(obj) == I::kJSObjectType)) { + int offset = I::kJSObjectHeaderSize + (internal::kApiPointerSize * index); + return I::ReadField<void*>(obj, offset); + } +#endif + return SlowGetAlignedPointerFromInternalField(index); } @@ -4160,10 +6442,19 @@ String* String::Cast(v8::Value* value) { } +Local<String> String::Empty(Isolate* isolate) { + typedef internal::Object* S; + typedef internal::Internals I; + I::CheckInitialized(isolate); + S* slot = I::GetRoot(isolate, I::kEmptyStringRootIndex); + return Local<String>(reinterpret_cast<String*>(slot)); +} + + String::ExternalStringResource* String::GetExternalStringResource() const { typedef internal::Object O; typedef internal::Internals I; - O* obj = *reinterpret_cast<O**>(const_cast<String*>(this)); + O* obj = *reinterpret_cast<O* const*>(this); String::ExternalStringResource* result; if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) { void* value = I::ReadField<void*>(obj, I::kStringResourceOffset); @@ -4178,6 +6469,62 @@ String::ExternalStringResource* String::GetExternalStringResource() const { } +String::ExternalStringResourceBase* String::GetExternalStringResourceBase( + String::Encoding* encoding_out) const { + typedef internal::Object O; + typedef internal::Internals I; + O* obj = *reinterpret_cast<O* const*>(this); + int type = I::GetInstanceType(obj) & I::kFullStringRepresentationMask; + *encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask); + ExternalStringResourceBase* resource = NULL; + if (type == I::kExternalOneByteRepresentationTag || + type == I::kExternalTwoByteRepresentationTag) { + void* value = I::ReadField<void*>(obj, I::kStringResourceOffset); + resource = static_cast<ExternalStringResourceBase*>(value); + } +#ifdef V8_ENABLE_CHECKS + VerifyExternalStringResourceBase(resource, *encoding_out); +#endif + return resource; +} + + +bool Value::IsUndefined() const { +#ifdef V8_ENABLE_CHECKS + return FullIsUndefined(); +#else + return QuickIsUndefined(); +#endif +} + +bool Value::QuickIsUndefined() const { + typedef internal::Object O; + typedef internal::Internals I; + O* obj = *reinterpret_cast<O* const*>(this); + if (!I::HasHeapObjectTag(obj)) return false; + if (I::GetInstanceType(obj) != I::kOddballType) return false; + return (I::GetOddballKind(obj) == I::kUndefinedOddballKind); +} + + +bool Value::IsNull() const { +#ifdef V8_ENABLE_CHECKS + return FullIsNull(); +#else + return QuickIsNull(); +#endif +} + +bool Value::QuickIsNull() const { + typedef internal::Object O; + typedef internal::Internals I; + O* obj = *reinterpret_cast<O* const*>(this); + if (!I::HasHeapObjectTag(obj)) return false; + if (I::GetInstanceType(obj) != I::kOddballType) return false; + return (I::GetOddballKind(obj) == I::kNullOddballKind); +} + + bool Value::IsString() const { #ifdef V8_ENABLE_CHECKS return FullIsString(); @@ -4189,12 +6536,33 @@ bool Value::IsString() const { bool Value::QuickIsString() const { typedef internal::Object O; typedef internal::Internals I; - O* obj = *reinterpret_cast<O**>(const_cast<Value*>(this)); + O* obj = *reinterpret_cast<O* const*>(this); if (!I::HasHeapObjectTag(obj)) return false; return (I::GetInstanceType(obj) < I::kFirstNonstringType); } +template <class T> Value* Value::Cast(T* value) { + return static_cast<Value*>(value); +} + + +Name* Name::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Name*>(value); +} + + +Symbol* Symbol::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Symbol*>(value); +} + + Number* Number::Cast(v8::Value* value) { #ifdef V8_ENABLE_CHECKS CheckCast(value); @@ -4227,6 +6595,14 @@ StringObject* StringObject::Cast(v8::Value* value) { } +SymbolObject* SymbolObject::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<SymbolObject*>(value); +} + + NumberObject* NumberObject::Cast(v8::Value* value) { #ifdef V8_ENABLE_CHECKS CheckCast(value); @@ -4267,6 +6643,126 @@ Array* Array::Cast(v8::Value* value) { } +Promise* Promise::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Promise*>(value); +} + + +Promise::Resolver* Promise::Resolver::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Promise::Resolver*>(value); +} + + +ArrayBuffer* ArrayBuffer::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<ArrayBuffer*>(value); +} + + +ArrayBufferView* ArrayBufferView::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<ArrayBufferView*>(value); +} + + +TypedArray* TypedArray::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<TypedArray*>(value); +} + + +Uint8Array* Uint8Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Uint8Array*>(value); +} + + +Int8Array* Int8Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Int8Array*>(value); +} + + +Uint16Array* Uint16Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Uint16Array*>(value); +} + + +Int16Array* Int16Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Int16Array*>(value); +} + + +Uint32Array* Uint32Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Uint32Array*>(value); +} + + +Int32Array* Int32Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Int32Array*>(value); +} + + +Float32Array* Float32Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Float32Array*>(value); +} + + +Float64Array* Float64Array::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Float64Array*>(value); +} + + +Uint8ClampedArray* Uint8ClampedArray::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<Uint8ClampedArray*>(value); +} + + +DataView* DataView::Cast(v8::Value* value) { +#ifdef V8_ENABLE_CHECKS + CheckCast(value); +#endif + return static_cast<DataView*>(value); +} + + Function* Function::Cast(v8::Value* value) { #ifdef V8_ENABLE_CHECKS CheckCast(value); @@ -4283,18 +6779,161 @@ External* External::Cast(v8::Value* value) { } -Local<Value> AccessorInfo::Data() const { - return Local<Value>(reinterpret_cast<Value*>(&args_[-2])); +template<typename T> +Isolate* PropertyCallbackInfo<T>::GetIsolate() const { + return *reinterpret_cast<Isolate**>(&args_[kIsolateIndex]); +} + + +template<typename T> +Local<Value> PropertyCallbackInfo<T>::Data() const { + return Local<Value>(reinterpret_cast<Value*>(&args_[kDataIndex])); +} + + +template<typename T> +Local<Object> PropertyCallbackInfo<T>::This() const { + return Local<Object>(reinterpret_cast<Object*>(&args_[kThisIndex])); +} + + +template<typename T> +Local<Object> PropertyCallbackInfo<T>::Holder() const { + return Local<Object>(reinterpret_cast<Object*>(&args_[kHolderIndex])); } -Local<Object> AccessorInfo::This() const { - return Local<Object>(reinterpret_cast<Object*>(&args_[0])); +template<typename T> +ReturnValue<T> PropertyCallbackInfo<T>::GetReturnValue() const { + return ReturnValue<T>(&args_[kReturnValueIndex]); } -Local<Object> AccessorInfo::Holder() const { - return Local<Object>(reinterpret_cast<Object*>(&args_[-1])); +Handle<Primitive> Undefined(Isolate* isolate) { + typedef internal::Object* S; + typedef internal::Internals I; + I::CheckInitialized(isolate); + S* slot = I::GetRoot(isolate, I::kUndefinedValueRootIndex); + return Handle<Primitive>(reinterpret_cast<Primitive*>(slot)); +} + + +Handle<Primitive> Null(Isolate* isolate) { + typedef internal::Object* S; + typedef internal::Internals I; + I::CheckInitialized(isolate); + S* slot = I::GetRoot(isolate, I::kNullValueRootIndex); + return Handle<Primitive>(reinterpret_cast<Primitive*>(slot)); +} + + +Handle<Boolean> True(Isolate* isolate) { + typedef internal::Object* S; + typedef internal::Internals I; + I::CheckInitialized(isolate); + S* slot = I::GetRoot(isolate, I::kTrueValueRootIndex); + return Handle<Boolean>(reinterpret_cast<Boolean*>(slot)); +} + + +Handle<Boolean> False(Isolate* isolate) { + typedef internal::Object* S; + typedef internal::Internals I; + I::CheckInitialized(isolate); + S* slot = I::GetRoot(isolate, I::kFalseValueRootIndex); + return Handle<Boolean>(reinterpret_cast<Boolean*>(slot)); +} + + +void Isolate::SetData(uint32_t slot, void* data) { + typedef internal::Internals I; + I::SetEmbedderData(this, slot, data); +} + + +void* Isolate::GetData(uint32_t slot) { + typedef internal::Internals I; + return I::GetEmbedderData(this, slot); +} + + +uint32_t Isolate::GetNumberOfDataSlots() { + typedef internal::Internals I; + return I::kNumIsolateDataSlots; +} + + +int64_t Isolate::AdjustAmountOfExternalAllocatedMemory( + int64_t change_in_bytes) { + typedef internal::Internals I; + int64_t* amount_of_external_allocated_memory = + reinterpret_cast<int64_t*>(reinterpret_cast<uint8_t*>(this) + + I::kAmountOfExternalAllocatedMemoryOffset); + int64_t* amount_of_external_allocated_memory_at_last_global_gc = + reinterpret_cast<int64_t*>( + reinterpret_cast<uint8_t*>(this) + + I::kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset); + int64_t amount = *amount_of_external_allocated_memory + change_in_bytes; + if (change_in_bytes > 0 && + amount - *amount_of_external_allocated_memory_at_last_global_gc > + I::kExternalAllocationLimit) { + CollectAllGarbage("external memory allocation limit reached."); + } else { + *amount_of_external_allocated_memory = amount; + } + return *amount_of_external_allocated_memory; +} + + +template<typename T> +void Isolate::SetObjectGroupId(const Persistent<T>& object, + UniqueId id) { + TYPE_CHECK(Value, T); + SetObjectGroupId(reinterpret_cast<v8::internal::Object**>(object.val_), id); +} + + +template<typename T> +void Isolate::SetReferenceFromGroup(UniqueId id, + const Persistent<T>& object) { + TYPE_CHECK(Value, T); + SetReferenceFromGroup(id, + reinterpret_cast<v8::internal::Object**>(object.val_)); +} + + +template<typename T, typename S> +void Isolate::SetReference(const Persistent<T>& parent, + const Persistent<S>& child) { + TYPE_CHECK(Object, T); + TYPE_CHECK(Value, S); + SetReference(reinterpret_cast<v8::internal::Object**>(parent.val_), + reinterpret_cast<v8::internal::Object**>(child.val_)); +} + + +Local<Value> Context::GetEmbedderData(int index) { +#ifndef V8_ENABLE_CHECKS + typedef internal::Object O; + typedef internal::HeapObject HO; + typedef internal::Internals I; + HO* context = *reinterpret_cast<HO**>(this); + O** result = + HandleScope::CreateHandle(context, I::ReadEmbedderData<O*>(this, index)); + return Local<Value>(reinterpret_cast<Value*>(result)); +#else + return SlowGetEmbedderData(index); +#endif +} + + +void* Context::GetAlignedPointerFromEmbedderData(int index) { +#ifndef V8_ENABLE_CHECKS + typedef internal::Internals I; + return I::ReadEmbedderData<void*>(this, index); +#else + return SlowGetAlignedPointerFromEmbedderData(index); +#endif } @@ -4313,7 +6952,6 @@ Local<Object> AccessorInfo::Holder() const { } // namespace v8 -#undef V8EXPORT #undef TYPE_CHECK diff --git a/include/v8config.h b/include/v8config.h new file mode 100644 index 00000000..87de9941 --- /dev/null +++ b/include/v8config.h @@ -0,0 +1,419 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8CONFIG_H_ +#define V8CONFIG_H_ + +// Platform headers for feature detection below. +#if defined(__ANDROID__) +# include <sys/cdefs.h> +#elif defined(__APPLE__) +# include <TargetConditionals.h> +#elif defined(__linux__) +# include <features.h> +#endif + + +// This macro allows to test for the version of the GNU C library (or +// a compatible C library that masquerades as glibc). It evaluates to +// 0 if libc is not GNU libc or compatible. +// Use like: +// #if V8_GLIBC_PREREQ(2, 3) +// ... +// #endif +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define V8_GLIBC_PREREQ(major, minor) \ + ((__GLIBC__ * 100 + __GLIBC_MINOR__) >= ((major) * 100 + (minor))) +#else +# define V8_GLIBC_PREREQ(major, minor) 0 +#endif + + +// This macro allows to test for the version of the GNU C++ compiler. +// Note that this also applies to compilers that masquerade as GCC, +// for example clang and the Intel C++ compiler for Linux. +// Use like: +// #if V8_GNUC_PREREQ(4, 3, 1) +// ... +// #endif +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define V8_GNUC_PREREQ(major, minor, patchlevel) \ + ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= \ + ((major) * 10000 + (minor) * 100 + (patchlevel))) +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) +# define V8_GNUC_PREREQ(major, minor, patchlevel) \ + ((__GNUC__ * 10000 + __GNUC_MINOR__) >= \ + ((major) * 10000 + (minor) * 100 + (patchlevel))) +#else +# define V8_GNUC_PREREQ(major, minor, patchlevel) 0 +#endif + + + +// ----------------------------------------------------------------------------- +// Operating system detection +// +// V8_OS_ANDROID - Android +// V8_OS_BSD - BSDish (Mac OS X, Net/Free/Open/DragonFlyBSD) +// V8_OS_CYGWIN - Cygwin +// V8_OS_DRAGONFLYBSD - DragonFlyBSD +// V8_OS_FREEBSD - FreeBSD +// V8_OS_LINUX - Linux +// V8_OS_MACOSX - Mac OS X +// V8_OS_NACL - Native Client +// V8_OS_NETBSD - NetBSD +// V8_OS_OPENBSD - OpenBSD +// V8_OS_POSIX - POSIX compatible (mostly everything except Windows) +// V8_OS_QNX - QNX Neutrino +// V8_OS_SOLARIS - Sun Solaris and OpenSolaris +// V8_OS_WIN - Microsoft Windows + +#if defined(__ANDROID__) +# define V8_OS_ANDROID 1 +# define V8_OS_LINUX 1 +# define V8_OS_POSIX 1 +#elif defined(__APPLE__) +# define V8_OS_BSD 1 +# define V8_OS_MACOSX 1 +# define V8_OS_POSIX 1 +#elif defined(__native_client__) +# define V8_OS_NACL 1 +# define V8_OS_POSIX 1 +#elif defined(__CYGWIN__) +# define V8_OS_CYGWIN 1 +# define V8_OS_POSIX 1 +#elif defined(__linux__) +# define V8_OS_LINUX 1 +# define V8_OS_POSIX 1 +#elif defined(__sun) +# define V8_OS_POSIX 1 +# define V8_OS_SOLARIS 1 +#elif defined(__FreeBSD__) +# define V8_OS_BSD 1 +# define V8_OS_FREEBSD 1 +# define V8_OS_POSIX 1 +#elif defined(__DragonFly__) +# define V8_OS_BSD 1 +# define V8_OS_DRAGONFLYBSD 1 +# define V8_OS_POSIX 1 +#elif defined(__NetBSD__) +# define V8_OS_BSD 1 +# define V8_OS_NETBSD 1 +# define V8_OS_POSIX 1 +#elif defined(__OpenBSD__) +# define V8_OS_BSD 1 +# define V8_OS_OPENBSD 1 +# define V8_OS_POSIX 1 +#elif defined(__QNXNTO__) +# define V8_OS_POSIX 1 +# define V8_OS_QNX 1 +#elif defined(_WIN32) +# define V8_OS_WIN 1 +#endif + + +// ----------------------------------------------------------------------------- +// C library detection +// +// V8_LIBC_MSVCRT - MSVC libc +// V8_LIBC_BIONIC - Bionic libc +// V8_LIBC_BSD - BSD libc derivate +// V8_LIBC_GLIBC - GNU C library +// V8_LIBC_UCLIBC - uClibc +// +// Note that testing for libc must be done using #if not #ifdef. For example, +// to test for the GNU C library, use: +// #if V8_LIBC_GLIBC +// ... +// #endif + +#if defined (_MSC_VER) +# define V8_LIBC_MSVCRT 1 +#elif defined(__BIONIC__) +# define V8_LIBC_BIONIC 1 +# define V8_LIBC_BSD 1 +#elif defined(__UCLIBC__) +# define V8_LIBC_UCLIBC 1 +#elif defined(__GLIBC__) || defined(__GNU_LIBRARY__) +# define V8_LIBC_GLIBC 1 +#else +# define V8_LIBC_BSD V8_OS_BSD +#endif + + +// ----------------------------------------------------------------------------- +// Compiler detection +// +// V8_CC_CLANG - Clang +// V8_CC_GNU - GNU C++ +// V8_CC_INTEL - Intel C++ +// V8_CC_MINGW - Minimalist GNU for Windows +// V8_CC_MINGW32 - Minimalist GNU for Windows (mingw32) +// V8_CC_MINGW64 - Minimalist GNU for Windows (mingw-w64) +// V8_CC_MSVC - Microsoft Visual C/C++ +// +// C++11 feature detection +// +// V8_HAS_CXX11_ALIGNAS - alignas specifier supported +// V8_HAS_CXX11_ALIGNOF - alignof(type) operator supported +// V8_HAS_CXX11_STATIC_ASSERT - static_assert() supported +// V8_HAS_CXX11_DELETE - deleted functions supported +// V8_HAS_CXX11_FINAL - final marker supported +// V8_HAS_CXX11_OVERRIDE - override marker supported +// +// Compiler-specific feature detection +// +// V8_HAS___ALIGNOF - __alignof(type) operator supported +// V8_HAS___ALIGNOF__ - __alignof__(type) operator supported +// V8_HAS_ATTRIBUTE_ALIGNED - __attribute__((aligned(n))) supported +// V8_HAS_ATTRIBUTE_ALWAYS_INLINE - __attribute__((always_inline)) +// supported +// V8_HAS_ATTRIBUTE_DEPRECATED - __attribute__((deprecated)) supported +// V8_HAS_ATTRIBUTE_NOINLINE - __attribute__((noinline)) supported +// V8_HAS_ATTRIBUTE_UNUSED - __attribute__((unused)) supported +// V8_HAS_ATTRIBUTE_VISIBILITY - __attribute__((visibility)) supported +// V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT - __attribute__((warn_unused_result)) +// supported +// V8_HAS_BUILTIN_CLZ - __builtin_clz() supported +// V8_HAS_BUILTIN_CTZ - __builtin_ctz() supported +// V8_HAS_BUILTIN_EXPECT - __builtin_expect() supported +// V8_HAS_BUILTIN_POPCOUNT - __builtin_popcount() supported +// V8_HAS_BUILTIN_SADD_OVERFLOW - __builtin_sadd_overflow() supported +// V8_HAS_BUILTIN_SSUB_OVERFLOW - __builtin_ssub_overflow() supported +// V8_HAS_DECLSPEC_ALIGN - __declspec(align(n)) supported +// V8_HAS_DECLSPEC_DEPRECATED - __declspec(deprecated) supported +// V8_HAS_DECLSPEC_NOINLINE - __declspec(noinline) supported +// V8_HAS___FINAL - __final supported in non-C++11 mode +// V8_HAS___FORCEINLINE - __forceinline supported +// V8_HAS_SEALED - MSVC style sealed marker supported +// +// Note that testing for compilers and/or features must be done using #if +// not #ifdef. For example, to test for Intel C++ Compiler, use: +// #if V8_CC_INTEL +// ... +// #endif + +#if defined(__clang__) + +# define V8_CC_CLANG 1 + +// Clang defines __alignof__ as alias for __alignof +# define V8_HAS___ALIGNOF 1 +# define V8_HAS___ALIGNOF__ V8_HAS___ALIGNOF + +# define V8_HAS_ATTRIBUTE_ALIGNED (__has_attribute(aligned)) +# define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline)) +# define V8_HAS_ATTRIBUTE_DEPRECATED (__has_attribute(deprecated)) +# define V8_HAS_ATTRIBUTE_NOINLINE (__has_attribute(noinline)) +# define V8_HAS_ATTRIBUTE_UNUSED (__has_attribute(unused)) +# define V8_HAS_ATTRIBUTE_VISIBILITY (__has_attribute(visibility)) +# define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \ + (__has_attribute(warn_unused_result)) + +# define V8_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz)) +# define V8_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz)) +# define V8_HAS_BUILTIN_EXPECT (__has_builtin(__builtin_expect)) +# define V8_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount)) +# define V8_HAS_BUILTIN_SADD_OVERFLOW (__has_builtin(__builtin_sadd_overflow)) +# define V8_HAS_BUILTIN_SSUB_OVERFLOW (__has_builtin(__builtin_ssub_overflow)) + +# define V8_HAS_CXX11_ALIGNAS (__has_feature(cxx_alignas)) +# define V8_HAS_CXX11_STATIC_ASSERT (__has_feature(cxx_static_assert)) +# define V8_HAS_CXX11_DELETE (__has_feature(cxx_deleted_functions)) +# define V8_HAS_CXX11_FINAL (__has_feature(cxx_override_control)) +# define V8_HAS_CXX11_OVERRIDE (__has_feature(cxx_override_control)) + +#elif defined(__GNUC__) + +# define V8_CC_GNU 1 +// Intel C++ also masquerades as GCC 3.2.0 +# define V8_CC_INTEL (defined(__INTEL_COMPILER)) +# define V8_CC_MINGW32 (defined(__MINGW32__)) +# define V8_CC_MINGW64 (defined(__MINGW64__)) +# define V8_CC_MINGW (V8_CC_MINGW32 || V8_CC_MINGW64) + +# define V8_HAS___ALIGNOF__ (V8_GNUC_PREREQ(4, 3, 0)) + +# define V8_HAS_ATTRIBUTE_ALIGNED (V8_GNUC_PREREQ(2, 95, 0)) +// always_inline is available in gcc 4.0 but not very reliable until 4.4. +// Works around "sorry, unimplemented: inlining failed" build errors with +// older compilers. +# define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (V8_GNUC_PREREQ(4, 4, 0)) +# define V8_HAS_ATTRIBUTE_DEPRECATED (V8_GNUC_PREREQ(3, 4, 0)) +# define V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE (V8_GNUC_PREREQ(4, 5, 0)) +# define V8_HAS_ATTRIBUTE_NOINLINE (V8_GNUC_PREREQ(3, 4, 0)) +# define V8_HAS_ATTRIBUTE_UNUSED (V8_GNUC_PREREQ(2, 95, 0)) +# define V8_HAS_ATTRIBUTE_VISIBILITY (V8_GNUC_PREREQ(4, 3, 0)) +# define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \ + (!V8_CC_INTEL && V8_GNUC_PREREQ(4, 1, 0)) + +# define V8_HAS_BUILTIN_CLZ (V8_GNUC_PREREQ(3, 4, 0)) +# define V8_HAS_BUILTIN_CTZ (V8_GNUC_PREREQ(3, 4, 0)) +# define V8_HAS_BUILTIN_EXPECT (V8_GNUC_PREREQ(2, 96, 0)) +# define V8_HAS_BUILTIN_POPCOUNT (V8_GNUC_PREREQ(3, 4, 0)) + +// g++ requires -std=c++0x or -std=gnu++0x to support C++11 functionality +// without warnings (functionality used by the macros below). These modes +// are detectable by checking whether __GXX_EXPERIMENTAL_CXX0X__ is defined or, +// more standardly, by checking whether __cplusplus has a C++11 or greater +// value. Current versions of g++ do not correctly set __cplusplus, so we check +// both for forward compatibility. +# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L +# define V8_HAS_CXX11_ALIGNAS (V8_GNUC_PREREQ(4, 8, 0)) +# define V8_HAS_CXX11_ALIGNOF (V8_GNUC_PREREQ(4, 8, 0)) +# define V8_HAS_CXX11_STATIC_ASSERT (V8_GNUC_PREREQ(4, 3, 0)) +# define V8_HAS_CXX11_DELETE (V8_GNUC_PREREQ(4, 4, 0)) +# define V8_HAS_CXX11_OVERRIDE (V8_GNUC_PREREQ(4, 7, 0)) +# define V8_HAS_CXX11_FINAL (V8_GNUC_PREREQ(4, 7, 0)) +# else +// '__final' is a non-C++11 GCC synonym for 'final', per GCC r176655. +# define V8_HAS___FINAL (V8_GNUC_PREREQ(4, 7, 0)) +# endif + +#elif defined(_MSC_VER) + +# define V8_CC_MSVC 1 + +# define V8_HAS___ALIGNOF 1 + +// Override control was added with Visual Studio 2005, but +// Visual Studio 2010 and earlier spell "final" as "sealed". +# define V8_HAS_CXX11_FINAL (_MSC_VER >= 1700) +# define V8_HAS_CXX11_OVERRIDE (_MSC_VER >= 1400) +# define V8_HAS_SEALED (_MSC_VER >= 1400) + +# define V8_HAS_DECLSPEC_ALIGN 1 +# define V8_HAS_DECLSPEC_DEPRECATED (_MSC_VER >= 1300) +# define V8_HAS_DECLSPEC_NOINLINE 1 + +# define V8_HAS___FORCEINLINE 1 + +#endif + + +// ----------------------------------------------------------------------------- +// Helper macros + +// A macro used to make better inlining. Don't bother for debug builds. +// Use like: +// V8_INLINE int GetZero() { return 0; } +#if !defined(DEBUG) && V8_HAS_ATTRIBUTE_ALWAYS_INLINE +# define V8_INLINE inline __attribute__((always_inline)) +#elif !defined(DEBUG) && V8_HAS___FORCEINLINE +# define V8_INLINE __forceinline +#else +# define V8_INLINE inline +#endif + + +// A macro used to tell the compiler to never inline a particular function. +// Don't bother for debug builds. +// Use like: +// V8_NOINLINE int GetMinusOne() { return -1; } +#if !defined(DEBUG) && V8_HAS_ATTRIBUTE_NOINLINE +# define V8_NOINLINE __attribute__((noinline)) +#elif !defined(DEBUG) && V8_HAS_DECLSPEC_NOINLINE +# define V8_NOINLINE __declspec(noinline) +#else +# define V8_NOINLINE /* NOT SUPPORTED */ +#endif + + +// A macro to mark classes or functions as deprecated. +#if defined(V8_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE +# define V8_DEPRECATED(message, declarator) \ +declarator __attribute__((deprecated(message))) +#elif defined(V8_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED +# define V8_DEPRECATED(message, declarator) \ +declarator __attribute__((deprecated)) +#elif defined(V8_DEPRECATION_WARNINGS) && V8_HAS_DECLSPEC_DEPRECATED +# define V8_DEPRECATED(message, declarator) __declspec(deprecated) declarator +#else +# define V8_DEPRECATED(message, declarator) declarator +#endif + + +// A macro to provide the compiler with branch prediction information. +#if V8_HAS_BUILTIN_EXPECT +# define V8_UNLIKELY(condition) (__builtin_expect(!!(condition), 0)) +# define V8_LIKELY(condition) (__builtin_expect(!!(condition), 1)) +#else +# define V8_UNLIKELY(condition) (condition) +# define V8_LIKELY(condition) (condition) +#endif + + +// A macro to specify that a method is deleted from the corresponding class. +// Any attempt to use the method will always produce an error at compile time +// when this macro can be implemented (i.e. if the compiler supports C++11). +// If the current compiler does not support C++11, use of the annotated method +// will still cause an error, but the error will most likely occur at link time +// rather than at compile time. As a backstop, method declarations using this +// macro should be private. +// Use like: +// class A { +// private: +// A(const A& other) V8_DELETE; +// A& operator=(const A& other) V8_DELETE; +// }; +#if V8_HAS_CXX11_DELETE +# define V8_DELETE = delete +#else +# define V8_DELETE /* NOT SUPPORTED */ +#endif + + +// This macro allows to specify memory alignment for structs, classes, etc. +// Use like: +// class V8_ALIGNED(16) MyClass { ... }; +// V8_ALIGNED(32) int array[42]; +#if V8_HAS_CXX11_ALIGNAS +# define V8_ALIGNED(n) alignas(n) +#elif V8_HAS_ATTRIBUTE_ALIGNED +# define V8_ALIGNED(n) __attribute__((aligned(n))) +#elif V8_HAS_DECLSPEC_ALIGN +# define V8_ALIGNED(n) __declspec(align(n)) +#else +# define V8_ALIGNED(n) /* NOT SUPPORTED */ +#endif + + +// This macro is similar to V8_ALIGNED(), but takes a type instead of size +// in bytes. If the compiler does not supports using the alignment of the +// |type|, it will align according to the |alignment| instead. For example, +// Visual Studio C++ cannot combine __declspec(align) and __alignof. The +// |alignment| must be a literal that is used as a kind of worst-case fallback +// alignment. +// Use like: +// struct V8_ALIGNAS(AnotherClass, 16) NewClass { ... }; +// V8_ALIGNAS(double, 8) int array[100]; +#if V8_HAS_CXX11_ALIGNAS +# define V8_ALIGNAS(type, alignment) alignas(type) +#elif V8_HAS___ALIGNOF__ && V8_HAS_ATTRIBUTE_ALIGNED +# define V8_ALIGNAS(type, alignment) __attribute__((aligned(__alignof__(type)))) +#else +# define V8_ALIGNAS(type, alignment) V8_ALIGNED(alignment) +#endif + + +// This macro returns alignment in bytes (an integer power of two) required for +// any instance of the given type, which is either complete type, an array type, +// or a reference type. +// Use like: +// size_t alignment = V8_ALIGNOF(double); +#if V8_HAS_CXX11_ALIGNOF +# define V8_ALIGNOF(type) alignof(type) +#elif V8_HAS___ALIGNOF +# define V8_ALIGNOF(type) __alignof(type) +#elif V8_HAS___ALIGNOF__ +# define V8_ALIGNOF(type) __alignof__(type) +#else +// Note that alignment of a type within a struct can be less than the +// alignment of the type stand-alone (because of ancient ABIs), so this +// should only be used as a last resort. +namespace v8 { template <typename T> class AlignOfHelper { char c; T t; }; } +# define V8_ALIGNOF(type) (sizeof(::v8::AlignOfHelper<type>) - sizeof(type)) +#endif + +#endif // V8CONFIG_H_ diff --git a/include/v8stdint.h b/include/v8stdint.h index 7c12e1f4..9a935ddd 100644 --- a/include/v8stdint.h +++ b/include/v8stdint.h @@ -1,29 +1,6 @@ // Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. // Load definitions of standard types. @@ -33,7 +10,9 @@ #include <stddef.h> #include <stdio.h> -#if defined(_WIN32) && !defined(__MINGW32__) +#include "v8config.h" + +#if V8_OS_WIN && !V8_CC_MINGW typedef signed char int8_t; typedef unsigned char uint8_t; @@ -47,7 +26,7 @@ typedef unsigned __int64 uint64_t; #else -#include <stdint.h> +#include <stdint.h> // NOLINT #endif |