📄 api.cc.svn-base
字号:
// Copyright 2007-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.#include "v8.h"#include "api.h"#include "bootstrapper.h"#include "compiler.h"#include "debug.h"#include "execution.h"#include "global-handles.h"#include "platform.h"#include "serialize.h"#include "snapshot.h"namespace i = v8::internal;#define LOG_API(expr) LOG(ApiEntryCall(expr))namespace v8 {#define ON_BAILOUT(location, code) \ if (IsDeadCheck(location)) { \ code; \ UNREACHABLE(); \ }#define EXCEPTION_PREAMBLE() \ thread_local.IncrementCallDepth(); \ ASSERT(!i::Top::external_caught_exception()); \ bool has_pending_exception = false#define EXCEPTION_BAILOUT_CHECK(value) \ do { \ thread_local.DecrementCallDepth(); \ if (has_pending_exception) { \ if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) { \ if (!thread_local.IgnoreOutOfMemory()) \ i::V8::FatalProcessOutOfMemory(NULL); \ } \ bool call_depth_is_zero = thread_local.CallDepthIsZero(); \ i::Top::optional_reschedule_exception(call_depth_is_zero); \ return value; \ } \ } while (false)// --- D a t a t h a t i s s p e c i f i c t o a t h r e a d ---static i::HandleScopeImplementer thread_local;// --- E x c e p t i o n B e h a v i o r ---static bool has_shut_down = false;static FatalErrorCallback exception_behavior = NULL;static void DefaultFatalErrorHandler(const char* location, const char* message) { API_Fatal(location, message);}static FatalErrorCallback& GetFatalErrorHandler() { if (exception_behavior == NULL) { exception_behavior = DefaultFatalErrorHandler; } return exception_behavior;}// When V8 cannot allocated memory FatalProcessOutOfMemory is called.// The default fatal error handler is called and execution is stopped.void i::V8::FatalProcessOutOfMemory(const char* location) { has_shut_down = true; FatalErrorCallback callback = GetFatalErrorHandler(); callback(location, "Allocation failed - process out of memory"); // If the callback returns, we stop execution. UNREACHABLE();}void V8::SetFatalErrorHandler(FatalErrorCallback that) { exception_behavior = that;}bool Utils::ReportApiFailure(const char* location, const char* message) { FatalErrorCallback callback = GetFatalErrorHandler(); callback(location, message); has_shut_down = true; return false;}bool V8::IsDead() { return has_shut_down;}static inline bool ApiCheck(bool condition, const char* location, const char* message) { return condition ? true : Utils::ReportApiFailure(location, message);}static bool ReportV8Dead(const char* location) { FatalErrorCallback callback = GetFatalErrorHandler(); callback(location, "V8 is no longer useable"); return true;}static bool ReportEmptyHandle(const char* location) { FatalErrorCallback callback = GetFatalErrorHandler(); callback(location, "Reading from empty handle"); return true;}/** * IsDeadCheck checks that the vm is useable. If, for instance, the vm has been * out of memory at some point this check will fail. It should be called on * entry to all methods that touch anything in the heap, except destructors * which you sometimes can't avoid calling after the vm has crashed. Functions * that call EnsureInitialized or ON_BAILOUT don't have to also call * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you * can arrange to return if the VM is dead. This is needed to ensure that no VM * heap allocations are attempted on a dead VM. EnsureInitialized has the * advantage over ON_BAILOUT that it actually initializes the VM if this has not * yet been done. */static inline bool IsDeadCheck(const char* location) { return has_shut_down ? ReportV8Dead(location) : false;}static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) { return obj.IsEmpty() ? ReportEmptyHandle(location) : false;}static inline bool EmptyCheck(const char* location, v8::Data* obj) { return (obj == 0) ? ReportEmptyHandle(location) : false;}// --- S t a t i c s ---static i::StringInputBuffer write_input_buffer;static void EnsureInitialized(const char* location) { if (IsDeadCheck(location)) return; ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");}v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() { if (IsDeadCheck("v8::Undefined()")) return v8::Handle<v8::Primitive>(); EnsureInitialized("v8::Undefined()"); return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));}v8::Handle<v8::Primitive> ImplementationUtilities::Null() { if (IsDeadCheck("v8::Null()")) return v8::Handle<v8::Primitive>(); EnsureInitialized("v8::Null()"); return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));}v8::Handle<v8::Boolean> ImplementationUtilities::True() { if (IsDeadCheck("v8::True()")) return v8::Handle<v8::Boolean>(); EnsureInitialized("v8::True()"); return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));}v8::Handle<v8::Boolean> ImplementationUtilities::False() { if (IsDeadCheck("v8::False()")) return v8::Handle<v8::Boolean>(); EnsureInitialized("v8::False()"); return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));}void V8::SetFlagsFromString(const char* str, int length) { i::FlagList::SetFlagsFromString(str, length);}void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);}v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) { if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>(); i::Top::ScheduleThrow(*Utils::OpenHandle(*value)); return v8::Undefined();}RegisteredExtension* RegisteredExtension::first_extension_ = NULL;RegisteredExtension::RegisteredExtension(Extension* extension) : extension_(extension), state_(UNVISITED) { }void RegisteredExtension::Register(RegisteredExtension* that) { that->next_ = RegisteredExtension::first_extension_; RegisteredExtension::first_extension_ = that;}void RegisterExtension(Extension* that) { RegisteredExtension* extension = new RegisteredExtension(that); RegisteredExtension::Register(extension);}Extension::Extension(const char* name, const char* source, int dep_count, const char** deps) : name_(name), source_(source), dep_count_(dep_count), deps_(deps), auto_enable_(false) { }v8::Handle<Primitive> Undefined() { LOG_API("Undefined"); return ImplementationUtilities::Undefined();}v8::Handle<Primitive> Null() { LOG_API("Null"); return ImplementationUtilities::Null();}v8::Handle<Boolean> True() { LOG_API("True"); return ImplementationUtilities::True();}v8::Handle<Boolean> False() { LOG_API("False"); return ImplementationUtilities::False();}ResourceConstraints::ResourceConstraints() : max_young_space_size_(0), max_old_space_size_(0), stack_limit_(NULL) { }bool SetResourceConstraints(ResourceConstraints* constraints) { bool result = i::Heap::ConfigureHeap(constraints->max_young_space_size(), constraints->max_old_space_size()); if (!result) return false; if (constraints->stack_limit() != NULL) { uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit()); i::StackGuard::SetStackLimit(limit); } return true;}void** V8::GlobalizeReference(void** obj) { LOG_API("Persistent::New"); if (IsDeadCheck("V8::Persistent::New")) return NULL; i::Handle<i::Object> result = i::GlobalHandles::Create(*reinterpret_cast<i::Object**>(obj)); return reinterpret_cast<void**>(result.location());}void V8::MakeWeak(void** object, void* parameters, WeakReferenceCallback callback) { LOG_API("MakeWeak"); i::GlobalHandles::MakeWeak(reinterpret_cast<i::Object**>(object), parameters, callback);}void V8::ClearWeak(void** obj) { LOG_API("ClearWeak"); i::GlobalHandles::ClearWeakness(reinterpret_cast<i::Object**>(obj));}bool V8::IsGlobalNearDeath(void** obj) { LOG_API("IsGlobalNearDeath"); if (has_shut_down) return false; return i::GlobalHandles::IsNearDeath(reinterpret_cast<i::Object**>(obj));}bool V8::IsGlobalWeak(void** obj) { LOG_API("IsGlobalWeak"); if (has_shut_down) return false; return i::GlobalHandles::IsWeak(reinterpret_cast<i::Object**>(obj));}void V8::DisposeGlobal(void** obj) { LOG_API("DisposeGlobal"); if (has_shut_down) return; i::GlobalHandles::Destroy(reinterpret_cast<i::Object**>(obj));}// --- H a n d l e s ---HandleScope::Data HandleScope::current_ = { -1, NULL, NULL };int HandleScope::NumberOfHandles() { int n = thread_local.Blocks()->length(); if (n == 0) return 0; return ((n - 1) * i::kHandleBlockSize) + (current_.next - thread_local.Blocks()->last());}void** v8::HandleScope::CreateHandle(void* value) { void** result = current_.next; if (result == current_.limit) { // Make sure there's at least one scope on the stack and that the // top of the scope stack isn't a barrier. if (!ApiCheck(current_.extensions >= 0, "v8::HandleScope::CreateHandle()", "Cannot create a handle without a HandleScope")) { return NULL; } // If there's more room in the last block, we use that. This is used // for fast creation of scopes after scope barriers. if (!thread_local.Blocks()->is_empty()) { void** limit = &thread_local.Blocks()->last()[i::kHandleBlockSize]; if (current_.limit != limit) { current_.limit = limit; } } // If we still haven't found a slot for the handle, we extend the // current handle scope by allocating a new handle block. if (result == current_.limit) { // If there's a spare block, use it for growing the current scope. result = thread_local.GetSpareOrNewBlock(); // Add the extension to the global list of blocks, but count the // extension as part of the current scope. thread_local.Blocks()->Add(result); current_.extensions++; current_.limit = &result[i::kHandleBlockSize]; } } // Update the current next field, set the value in the created // handle, and return the result. ASSERT(result < current_.limit); current_.next = result + 1; *result = value; return result;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -