HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Android 10
|
10.0.0_r6
下载
查看原文件
收藏
根目录
external
v8
src
api.cc
// 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. #include "src/api.h" #include
// For memcpy, strlen. #include
// For isnan. #include
#include
#include "src/api-inl.h" #include "include/v8-profiler.h" #include "include/v8-testing.h" #include "include/v8-util.h" #include "src/accessors.h" #include "src/api-natives.h" #include "src/assert-scope.h" #include "src/base/functional.h" #include "src/base/logging.h" #include "src/base/platform/platform.h" #include "src/base/platform/time.h" #include "src/base/safe_conversions.h" #include "src/base/utils/random-number-generator.h" #include "src/bootstrapper.h" #include "src/builtins/builtins-utils.h" #include "src/char-predicates-inl.h" #include "src/code-stubs.h" #include "src/compiler-dispatcher/compiler-dispatcher.h" #include "src/compiler.h" #include "src/contexts.h" #include "src/conversions-inl.h" #include "src/counters.h" #include "src/debug/debug-coverage.h" #include "src/debug/debug-evaluate.h" #include "src/debug/debug-type-profile.h" #include "src/debug/debug.h" #include "src/debug/liveedit.h" #include "src/deoptimizer.h" #include "src/detachable-vector.h" #include "src/execution.h" #include "src/frames-inl.h" #include "src/gdb-jit.h" #include "src/global-handles.h" #include "src/globals.h" #include "src/icu_util.h" #include "src/isolate-inl.h" #include "src/json-parser.h" #include "src/json-stringifier.h" #include "src/messages.h" #include "src/objects-inl.h" #include "src/objects/api-callbacks.h" #include "src/objects/js-array-inl.h" #include "src/objects/js-collection-inl.h" #include "src/objects/js-generator-inl.h" #include "src/objects/js-promise-inl.h" #include "src/objects/js-regexp-inl.h" #include "src/objects/module-inl.h" #include "src/objects/ordered-hash-table-inl.h" #include "src/objects/templates.h" #include "src/parsing/parser.h" #include "src/parsing/scanner-character-streams.h" #include "src/pending-compilation-error-handler.h" #include "src/profiler/cpu-profiler.h" #include "src/profiler/heap-profiler.h" #include "src/profiler/heap-snapshot-generator-inl.h" #include "src/profiler/profile-generator-inl.h" #include "src/profiler/tick-sample.h" #include "src/property-descriptor.h" #include "src/property-details.h" #include "src/property.h" #include "src/prototype.h" #include "src/runtime-profiler.h" #include "src/runtime/runtime.h" #include "src/simulator.h" #include "src/snapshot/builtin-serializer.h" #include "src/snapshot/code-serializer.h" #include "src/snapshot/natives.h" #include "src/snapshot/snapshot.h" #include "src/startup-data-util.h" #include "src/string-hasher.h" #include "src/tracing/trace-event.h" #include "src/trap-handler/trap-handler.h" #include "src/unicode-cache-inl.h" #include "src/unicode-inl.h" #include "src/v8.h" #include "src/v8threads.h" #include "src/value-serializer.h" #include "src/version.h" #include "src/vm-state-inl.h" #include "src/wasm/streaming-decoder.h" #include "src/wasm/wasm-engine.h" #include "src/wasm/wasm-objects-inl.h" #include "src/wasm/wasm-result.h" #include "src/wasm/wasm-serialization.h" namespace v8 { /* * Most API methods should use one of the three macros: * * ENTER_V8, ENTER_V8_NO_SCRIPT, ENTER_V8_NO_SCRIPT_NO_EXCEPTION. * * The latter two assume that no script is executed, and no exceptions are * scheduled in addition (respectively). Creating a pending exception and * removing it before returning is ok. * * Exceptions should be handled either by invoking one of the * RETURN_ON_FAILED_EXECUTION* macros. * * Don't use macros with DO_NOT_USE in their name. * * TODO(jochen): Document debugger specific macros. * TODO(jochen): Document LOG_API and other RuntimeCallStats macros. * TODO(jochen): All API methods should invoke one of the ENTER_V8* macros. * TODO(jochen): Remove calls form API methods to DO_NOT_USE macros. */ #define LOG_API(isolate, class_name, function_name) \ i::RuntimeCallTimerScope _runtime_timer( \ isolate, i::RuntimeCallCounterId::kAPI_##class_name##_##function_name); \ LOG(isolate, ApiEntryCall("v8::" #class_name "::" #function_name)) #define ENTER_V8_DO_NOT_USE(isolate) i::VMState
__state__((isolate)) #define ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, \ function_name, bailout_value, \ HandleScopeClass, do_callback) \ if (IsExecutionTerminatingCheck(isolate)) { \ return bailout_value; \ } \ HandleScopeClass handle_scope(isolate); \ CallDepthScope
call_depth_scope(isolate, context); \ LOG_API(isolate, class_name, function_name); \ i::VMState
__state__((isolate)); \ bool has_pending_exception = false #define PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, T) \ if (IsExecutionTerminatingCheck(isolate)) { \ return MaybeLocal
(); \ } \ InternalEscapableScope handle_scope(isolate); \ CallDepthScope
call_depth_scope(isolate, v8::Local
()); \ i::VMState
__state__((isolate)); \ bool has_pending_exception = false #define PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ bailout_value, HandleScopeClass, \ do_callback) \ auto isolate = context.IsEmpty() \ ? i::Isolate::Current() \ : reinterpret_cast
(context->GetIsolate()); \ ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \ bailout_value, HandleScopeClass, do_callback); #define PREPARE_FOR_EXECUTION(context, class_name, function_name, T) \ PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ MaybeLocal
(), InternalEscapableScope, \ false) #define ENTER_V8(isolate, context, class_name, function_name, bailout_value, \ HandleScopeClass) \ ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \ bailout_value, HandleScopeClass, true) #ifdef DEBUG #define ENTER_V8_NO_SCRIPT(isolate, context, class_name, function_name, \ bailout_value, HandleScopeClass) \ ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \ bailout_value, HandleScopeClass, false); \ i::DisallowJavascriptExecutionDebugOnly __no_script__((isolate)) #define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \ i::VMState
__state__((isolate)); \ i::DisallowJavascriptExecutionDebugOnly __no_script__((isolate)); \ i::DisallowExceptions __no_exceptions__((isolate)) #define ENTER_V8_FOR_NEW_CONTEXT(isolate) \ i::VMState
__state__((isolate)); \ i::DisallowExceptions __no_exceptions__((isolate)) #else #define ENTER_V8_NO_SCRIPT(isolate, context, class_name, function_name, \ bailout_value, HandleScopeClass) \ ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \ bailout_value, HandleScopeClass, false) #define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \ i::VMState
__state__((isolate)); #define ENTER_V8_FOR_NEW_CONTEXT(isolate) \ i::VMState
__state__((isolate)); #endif // DEBUG #define EXCEPTION_BAILOUT_CHECK_SCOPED_DO_NOT_USE(isolate, value) \ do { \ if (has_pending_exception) { \ call_depth_scope.Escape(); \ return value; \ } \ } while (false) #define RETURN_ON_FAILED_EXECUTION(T) \ EXCEPTION_BAILOUT_CHECK_SCOPED_DO_NOT_USE(isolate, MaybeLocal
()) #define RETURN_ON_FAILED_EXECUTION_PRIMITIVE(T) \ EXCEPTION_BAILOUT_CHECK_SCOPED_DO_NOT_USE(isolate, Nothing
()) #define RETURN_TO_LOCAL_UNCHECKED(maybe_local, T) \ return maybe_local.FromMaybe(Local
()); #define RETURN_ESCAPED(value) return handle_scope.Escape(value); namespace { Local
ContextFromNeverReadOnlySpaceObject( i::Handle
obj) { return reinterpret_cast
(obj->GetIsolate())->GetCurrentContext(); } // TODO(delphick): Remove this completely when the deprecated functions that use // it are removed. // DO NOT USE THIS IN NEW CODE! i::Isolate* UnsafeIsolateFromHeapObject(i::Handle
obj) { // Use MemoryChunk directly instead of Isolate::FromWritableHeapObject to // temporarily allow isolate access from read-only space objects. i::MemoryChunk* chunk = i::MemoryChunk::FromHeapObject(*obj); return chunk->heap()->isolate(); } // TODO(delphick): Remove this completely when the deprecated functions that use // it are removed. // DO NOT USE THIS IN NEW CODE! Local
UnsafeContextFromHeapObject(i::Handle
obj) { // Use MemoryChunk directly instead of Isolate::FromWritableHeapObject to // temporarily allow isolate access from read-only space objects. i::MemoryChunk* chunk = i::MemoryChunk::FromHeapObject(i::HeapObject::cast(*obj)); return reinterpret_cast
(chunk->heap()->isolate()) ->GetCurrentContext(); } class InternalEscapableScope : public v8::EscapableHandleScope { public: explicit inline InternalEscapableScope(i::Isolate* isolate) : v8::EscapableHandleScope(reinterpret_cast
(isolate)) {} }; // TODO(jochen): This should be #ifdef DEBUG #ifdef V8_CHECK_MICROTASKS_SCOPES_CONSISTENCY void CheckMicrotasksScopesConsistency(i::Isolate* isolate) { auto handle_scope_implementer = isolate->handle_scope_implementer(); if (handle_scope_implementer->microtasks_policy() == v8::MicrotasksPolicy::kScoped) { DCHECK(handle_scope_implementer->GetMicrotasksScopeDepth() || !handle_scope_implementer->DebugMicrotasksScopeDepthIsZero()); } } #endif template
class CallDepthScope { public: explicit CallDepthScope(i::Isolate* isolate, Local
context) : isolate_(isolate), context_(context), escaped_(false), safe_for_termination_(isolate->next_v8_call_is_safe_for_termination()), interrupts_scope_(isolate_, i::StackGuard::TERMINATE_EXECUTION, isolate_->only_terminate_in_safe_scope() ? (safe_for_termination_ ? i::InterruptsScope::kRunInterrupts : i::InterruptsScope::kPostponeInterrupts) : i::InterruptsScope::kNoop) { // TODO(dcarney): remove this when blink stops crashing. DCHECK(!isolate_->external_caught_exception()); isolate_->handle_scope_implementer()->IncrementCallDepth(); isolate_->set_next_v8_call_is_safe_for_termination(false); if (!context.IsEmpty()) { i::Handle
env = Utils::OpenHandle(*context); i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); if (isolate->context() != nullptr && isolate->context()->native_context() == env->native_context()) { context_ = Local
(); } else { impl->SaveContext(isolate->context()); isolate->set_context(*env); } } if (do_callback) isolate_->FireBeforeCallEnteredCallback(); } ~CallDepthScope() { if (!context_.IsEmpty()) { i::HandleScopeImplementer* impl = isolate_->handle_scope_implementer(); isolate_->set_context(impl->RestoreContext()); } if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth(); if (do_callback) isolate_->FireCallCompletedCallback(); // TODO(jochen): This should be #ifdef DEBUG #ifdef V8_CHECK_MICROTASKS_SCOPES_CONSISTENCY if (do_callback) CheckMicrotasksScopesConsistency(isolate_); #endif isolate_->set_next_v8_call_is_safe_for_termination(safe_for_termination_); } void Escape() { DCHECK(!escaped_); escaped_ = true; auto handle_scope_implementer = isolate_->handle_scope_implementer(); handle_scope_implementer->DecrementCallDepth(); bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); isolate_->OptionalRescheduleException(call_depth_is_zero); } private: i::Isolate* const isolate_; Local
context_; bool escaped_; bool do_callback_; bool safe_for_termination_; i::InterruptsScope interrupts_scope_; }; } // namespace static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, i::Handle
script) { i::Handle
scriptName(script->GetNameOrSourceURL(), isolate); i::Handle
source_map_url(script->source_mapping_url(), isolate); i::Handle
host_defined_options(script->host_defined_options(), isolate); v8::Isolate* v8_isolate = reinterpret_cast
(isolate); ScriptOriginOptions options(script->origin_options()); v8::ScriptOrigin origin( Utils::ToLocal(scriptName), v8::Integer::New(v8_isolate, script->line_offset()), v8::Integer::New(v8_isolate, script->column_offset()), v8::Boolean::New(v8_isolate, options.IsSharedCrossOrigin()), v8::Integer::New(v8_isolate, script->id()), Utils::ToLocal(source_map_url), v8::Boolean::New(v8_isolate, options.IsOpaque()), v8::Boolean::New(v8_isolate, script->type() == i::Script::TYPE_WASM), v8::Boolean::New(v8_isolate, options.IsModule()), Utils::ToLocal(host_defined_options)); return origin; } // --- E x c e p t i o n B e h a v i o r --- void i::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location) { i::V8::FatalProcessOutOfMemory(isolate, location, false); } // When V8 cannot allocate memory FatalProcessOutOfMemory is called. The default // OOM error handler is called and execution is stopped. void i::V8::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location, bool is_heap_oom) { char last_few_messages[Heap::kTraceRingBufferSize + 1]; char js_stacktrace[Heap::kStacktraceBufferSize + 1]; i::HeapStats heap_stats; if (isolate == nullptr) { isolate = Isolate::Current(); } if (isolate == nullptr) { // On a background thread -> we cannot retrieve memory information from the // Isolate. Write easy-to-recognize values on the stack. memset(last_few_messages, 0x0BADC0DE, Heap::kTraceRingBufferSize + 1); memset(js_stacktrace, 0x0BADC0DE, Heap::kStacktraceBufferSize + 1); memset(&heap_stats, 0xBADC0DE, sizeof(heap_stats)); // Note that the embedder's oom handler won't be called in this case. We // just crash. FATAL( "API fatal error handler returned after process out of memory on the " "background thread"); UNREACHABLE(); } memset(last_few_messages, 0, Heap::kTraceRingBufferSize + 1); memset(js_stacktrace, 0, Heap::kStacktraceBufferSize + 1); intptr_t start_marker; heap_stats.start_marker = &start_marker; size_t ro_space_size; heap_stats.ro_space_size = &ro_space_size; size_t ro_space_capacity; heap_stats.ro_space_capacity = &ro_space_capacity; size_t new_space_size; heap_stats.new_space_size = &new_space_size; size_t new_space_capacity; heap_stats.new_space_capacity = &new_space_capacity; size_t old_space_size; heap_stats.old_space_size = &old_space_size; size_t old_space_capacity; heap_stats.old_space_capacity = &old_space_capacity; size_t code_space_size; heap_stats.code_space_size = &code_space_size; size_t code_space_capacity; heap_stats.code_space_capacity = &code_space_capacity; size_t map_space_size; heap_stats.map_space_size = &map_space_size; size_t map_space_capacity; heap_stats.map_space_capacity = &map_space_capacity; size_t lo_space_size; heap_stats.lo_space_size = &lo_space_size; size_t global_handle_count; heap_stats.global_handle_count = &global_handle_count; size_t weak_global_handle_count; heap_stats.weak_global_handle_count = &weak_global_handle_count; size_t pending_global_handle_count; heap_stats.pending_global_handle_count = &pending_global_handle_count; size_t near_death_global_handle_count; heap_stats.near_death_global_handle_count = &near_death_global_handle_count; size_t free_global_handle_count; heap_stats.free_global_handle_count = &free_global_handle_count; size_t memory_allocator_size; heap_stats.memory_allocator_size = &memory_allocator_size; size_t memory_allocator_capacity; heap_stats.memory_allocator_capacity = &memory_allocator_capacity; size_t malloced_memory; heap_stats.malloced_memory = &malloced_memory; size_t malloced_peak_memory; heap_stats.malloced_peak_memory = &malloced_peak_memory; size_t objects_per_type[LAST_TYPE + 1] = {0}; heap_stats.objects_per_type = objects_per_type; size_t size_per_type[LAST_TYPE + 1] = {0}; heap_stats.size_per_type = size_per_type; int os_error; heap_stats.os_error = &os_error; heap_stats.last_few_messages = last_few_messages; heap_stats.js_stacktrace = js_stacktrace; intptr_t end_marker; heap_stats.end_marker = &end_marker; if (isolate->heap()->HasBeenSetUp()) { // BUG(1718): Don't use the take_snapshot since we don't support // HeapIterator here without doing a special GC. isolate->heap()->RecordStats(&heap_stats, false); char* first_newline = strchr(last_few_messages, '\n'); if (first_newline == nullptr || first_newline[1] == '\0') first_newline = last_few_messages; PrintF("\n<--- Last few GCs --->\n%s\n", first_newline); PrintF("\n<--- JS stacktrace --->\n%s\n", js_stacktrace); } Utils::ReportOOMFailure(isolate, location, is_heap_oom); // If the fatal error handler returns, we stop execution. FATAL("API fatal error handler returned after process out of memory"); } void Utils::ReportApiFailure(const char* location, const char* message) { i::Isolate* isolate = i::Isolate::Current(); FatalErrorCallback callback = nullptr; if (isolate != nullptr) { callback = isolate->exception_behavior(); } if (callback == nullptr) { base::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", location, message); base::OS::Abort(); } else { callback(location, message); } isolate->SignalFatalError(); } void Utils::ReportOOMFailure(i::Isolate* isolate, const char* location, bool is_heap_oom) { OOMErrorCallback oom_callback = isolate->oom_behavior(); if (oom_callback == nullptr) { // TODO(wfh): Remove this fallback once Blink is setting OOM handler. See // crbug.com/614440. FatalErrorCallback fatal_callback = isolate->exception_behavior(); if (fatal_callback == nullptr) { base::OS::PrintError("\n#\n# Fatal %s OOM in %s\n#\n\n", is_heap_oom ? "javascript" : "process", location); base::OS::Abort(); } else { fatal_callback(location, is_heap_oom ? "Allocation failed - JavaScript heap out of memory" : "Allocation failed - process out of memory"); } } else { oom_callback(location, is_heap_oom); } isolate->SignalFatalError(); } static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { if (isolate->has_scheduled_exception()) { return isolate->scheduled_exception() == i::ReadOnlyRoots(isolate).termination_exception(); } return false; } void V8::SetNativesDataBlob(StartupData* natives_blob) { i::V8::SetNativesBlob(natives_blob); } void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) { i::V8::SetSnapshotBlob(snapshot_blob); } namespace { class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { public: void* Allocate(size_t length) override { #if V8_OS_AIX && _LINUX_SOURCE_COMPAT // Work around for GCC bug on AIX // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839 void* data = __linux_calloc(length, 1); #else void* data = calloc(length, 1); #endif return data; } void* AllocateUninitialized(size_t length) override { #if V8_OS_AIX && _LINUX_SOURCE_COMPAT // Work around for GCC bug on AIX // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839 void* data = __linux_malloc(length); #else void* data = malloc(length); #endif return data; } void Free(void* data, size_t) override { free(data); } }; struct SnapshotCreatorData { explicit SnapshotCreatorData(Isolate* isolate) : isolate_(isolate), default_context_(), contexts_(isolate), created_(false) {} static SnapshotCreatorData* cast(void* data) { return reinterpret_cast
(data); } ArrayBufferAllocator allocator_; Isolate* isolate_; Persistent
default_context_; SerializeInternalFieldsCallback default_embedder_fields_serializer_; PersistentValueVector
contexts_; std::vector
embedder_fields_serializers_; bool created_; }; } // namespace SnapshotCreator::SnapshotCreator(Isolate* isolate, const intptr_t* external_references, StartupData* existing_snapshot) { SnapshotCreatorData* data = new SnapshotCreatorData(isolate); data->isolate_ = isolate; i::Isolate* internal_isolate = reinterpret_cast
(isolate); internal_isolate->set_array_buffer_allocator(&data->allocator_); internal_isolate->set_api_external_references(external_references); internal_isolate->enable_serializer(); isolate->Enter(); const StartupData* blob = existing_snapshot ? existing_snapshot : i::Snapshot::DefaultSnapshotBlob(); if (blob && blob->raw_size > 0) { internal_isolate->set_snapshot_blob(blob); i::Snapshot::Initialize(internal_isolate); } else { internal_isolate->Init(nullptr); } data_ = data; } SnapshotCreator::SnapshotCreator(const intptr_t* external_references, StartupData* existing_snapshot) : SnapshotCreator(reinterpret_cast
(new i::Isolate()), external_references, existing_snapshot) {} SnapshotCreator::~SnapshotCreator() { SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); DCHECK(data->created_); Isolate* isolate = data->isolate_; isolate->Exit(); isolate->Dispose(); delete data; } Isolate* SnapshotCreator::GetIsolate() { return SnapshotCreatorData::cast(data_)->isolate_; } void SnapshotCreator::SetDefaultContext( Local
context, SerializeInternalFieldsCallback callback) { DCHECK(!context.IsEmpty()); SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); DCHECK(!data->created_); DCHECK(data->default_context_.IsEmpty()); Isolate* isolate = data->isolate_; CHECK_EQ(isolate, context->GetIsolate()); data->default_context_.Reset(isolate, context); data->default_embedder_fields_serializer_ = callback; } size_t SnapshotCreator::AddContext(Local
context, SerializeInternalFieldsCallback callback) { DCHECK(!context.IsEmpty()); SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); DCHECK(!data->created_); Isolate* isolate = data->isolate_; CHECK_EQ(isolate, context->GetIsolate()); size_t index = data->contexts_.Size(); data->contexts_.Append(context); data->embedder_fields_serializers_.push_back(callback); return index; } size_t SnapshotCreator::AddTemplate(Local
template_obj) { return AddData(template_obj); } size_t SnapshotCreator::AddData(i::Object* object) { DCHECK_NOT_NULL(object); SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); DCHECK(!data->created_); i::Isolate* isolate = reinterpret_cast
(data->isolate_); i::HandleScope scope(isolate); i::Handle
obj(object, isolate); i::Handle
list; if (!isolate->heap()->serialized_objects()->IsArrayList()) { list = i::ArrayList::New(isolate, 1); } else { list = i::Handle
( i::ArrayList::cast(isolate->heap()->serialized_objects()), isolate); } size_t index = static_cast
(list->Length()); list = i::ArrayList::Add(isolate, list, obj); isolate->heap()->SetSerializedObjects(*list); return index; } size_t SnapshotCreator::AddData(Local
context, i::Object* object) { DCHECK_NOT_NULL(object); DCHECK(!SnapshotCreatorData::cast(data_)->created_); i::Handle
ctx = Utils::OpenHandle(*context); i::Isolate* isolate = ctx->GetIsolate(); i::HandleScope scope(isolate); i::Handle
obj(object, isolate); i::Handle
list; if (!ctx->serialized_objects()->IsArrayList()) { list = i::ArrayList::New(isolate, 1); } else { list = i::Handle
( i::ArrayList::cast(ctx->serialized_objects()), isolate); } size_t index = static_cast
(list->Length()); list = i::ArrayList::Add(isolate, list, obj); ctx->set_serialized_objects(*list); return index; } namespace { void ConvertSerializedObjectsToFixedArray(Local
context) { i::Handle
ctx = Utils::OpenHandle(*context); i::Isolate* isolate = ctx->GetIsolate(); if (!ctx->serialized_objects()->IsArrayList()) { ctx->set_serialized_objects(i::ReadOnlyRoots(isolate).empty_fixed_array()); } else { i::Handle
list(i::ArrayList::cast(ctx->serialized_objects()), isolate); i::Handle
elements = i::ArrayList::Elements(isolate, list); ctx->set_serialized_objects(*elements); } } void ConvertSerializedObjectsToFixedArray(i::Isolate* isolate) { if (!isolate->heap()->serialized_objects()->IsArrayList()) { isolate->heap()->SetSerializedObjects( i::ReadOnlyRoots(isolate).empty_fixed_array()); } else { i::Handle
list( i::ArrayList::cast(isolate->heap()->serialized_objects()), isolate); i::Handle
elements = i::ArrayList::Elements(isolate, list); isolate->heap()->SetSerializedObjects(*elements); } } } // anonymous namespace StartupData SnapshotCreator::CreateBlob( SnapshotCreator::FunctionCodeHandling function_code_handling) { SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); i::Isolate* isolate = reinterpret_cast
(data->isolate_); DCHECK(!data->created_); DCHECK(!data->default_context_.IsEmpty()); int num_additional_contexts = static_cast
(data->contexts_.Size()); { i::HandleScope scope(isolate); // Convert list of context-independent data to FixedArray. ConvertSerializedObjectsToFixedArray(isolate); // Convert lists of context-dependent data to FixedArray. ConvertSerializedObjectsToFixedArray( data->default_context_.Get(data->isolate_)); for (int i = 0; i < num_additional_contexts; i++) { ConvertSerializedObjectsToFixedArray(data->contexts_.Get(i)); } // We need to store the global proxy size upfront in case we need the // bootstrapper to create a global proxy before we deserialize the context. i::Handle
global_proxy_sizes = isolate->factory()->NewFixedArray(num_additional_contexts, i::TENURED); for (int i = 0; i < num_additional_contexts; i++) { i::Handle
context = v8::Utils::OpenHandle(*data->contexts_.Get(i)); global_proxy_sizes->set(i, i::Smi::FromInt(context->global_proxy()->Size())); } isolate->heap()->SetSerializedGlobalProxySizes(*global_proxy_sizes); } // We might rehash strings and re-sort descriptors. Clear the lookup cache. isolate->descriptor_lookup_cache()->Clear(); // If we don't do this then we end up with a stray root pointing at the // context even after we have disposed of the context. isolate->heap()->CollectAllAvailableGarbage( i::GarbageCollectionReason::kSnapshotCreator); { i::HandleScope scope(isolate); isolate->heap()->CompactWeakArrayLists(internal::TENURED); } isolate->heap()->read_only_space()->ClearStringPaddingIfNeeded(); if (function_code_handling == FunctionCodeHandling::kClear) { // Clear out re-compilable data from all shared function infos. Any // JSFunctions using these SFIs will have their code pointers reset by the // partial serializer. // // We have to iterate the heap and collect handles to each clearable SFI, // before we disable allocation, since we have to allocate UncompiledDatas // to be able to recompile them. i::HandleScope scope(isolate); std::vector
> sfis_to_clear; i::HeapIterator heap_iterator(isolate->heap()); while (i::HeapObject* current_obj = heap_iterator.next()) { if (current_obj->IsSharedFunctionInfo()) { i::SharedFunctionInfo* shared = i::SharedFunctionInfo::cast(current_obj); if (shared->CanDiscardCompiled()) { sfis_to_clear.emplace_back(shared, isolate); } } } i::AllowHeapAllocation allocate_for_discard; for (i::Handle
shared : sfis_to_clear) { i::SharedFunctionInfo::DiscardCompiled(isolate, shared); } } i::DisallowHeapAllocation no_gc_from_here_on; int num_contexts = num_additional_contexts + 1; std::vector
contexts; contexts.reserve(num_contexts); { i::HandleScope scope(isolate); contexts.push_back( *v8::Utils::OpenHandle(*data->default_context_.Get(data->isolate_))); data->default_context_.Reset(); for (int i = 0; i < num_additional_contexts; i++) { i::Handle
context = v8::Utils::OpenHandle(*data->contexts_.Get(i)); contexts.push_back(*context); } data->contexts_.Clear(); } // Check that values referenced by global/eternal handles are accounted for. i::SerializedHandleChecker handle_checker(isolate, &contexts); CHECK(handle_checker.CheckGlobalAndEternalHandles()); i::HeapIterator heap_iterator(isolate->heap()); while (i::HeapObject* current_obj = heap_iterator.next()) { if (current_obj->IsJSFunction()) { i::JSFunction* fun = i::JSFunction::cast(current_obj); // Complete in-object slack tracking for all functions. fun->CompleteInobjectSlackTrackingIfActive(); // Also, clear out feedback vectors, or any optimized code. if (fun->has_feedback_vector()) { fun->feedback_cell()->set_value( i::ReadOnlyRoots(isolate).undefined_value()); fun->set_code(isolate->builtins()->builtin(i::Builtins::kCompileLazy)); } if (function_code_handling == FunctionCodeHandling::kClear) { DCHECK(fun->shared()->HasWasmExportedFunctionData() || fun->shared()->HasBuiltinId() || fun->shared()->IsApiFunction() || fun->shared()->HasUncompiledDataWithoutPreParsedScope()); } } } i::StartupSerializer startup_serializer(isolate); startup_serializer.SerializeStrongReferences(); // Serialize each context with a new partial serializer. std::vector
context_snapshots; context_snapshots.reserve(num_contexts); // TODO(6593): generalize rehashing, and remove this flag. bool can_be_rehashed = true; for (int i = 0; i < num_contexts; i++) { bool is_default_context = i == 0; i::PartialSerializer partial_serializer( isolate, &startup_serializer, is_default_context ? data->default_embedder_fields_serializer_ : data->embedder_fields_serializers_[i - 1]); partial_serializer.Serialize(&contexts[i], !is_default_context); can_be_rehashed = can_be_rehashed && partial_serializer.can_be_rehashed(); context_snapshots.push_back(new i::SnapshotData(&partial_serializer)); } // Builtin serialization places additional objects into the partial snapshot // cache and thus needs to happen before SerializeWeakReferencesAndDeferred // is called below. i::BuiltinSerializer builtin_serializer(isolate, &startup_serializer); builtin_serializer.SerializeBuiltinsAndHandlers(); startup_serializer.SerializeWeakReferencesAndDeferred(); can_be_rehashed = can_be_rehashed && startup_serializer.can_be_rehashed(); i::SnapshotData startup_snapshot(&startup_serializer); i::BuiltinSnapshotData builtin_snapshot(&builtin_serializer); StartupData result = i::Snapshot::CreateSnapshotBlob( &startup_snapshot, &builtin_snapshot, context_snapshots, can_be_rehashed); // Delete heap-allocated context snapshot instances. for (const auto context_snapshot : context_snapshots) { delete context_snapshot; } data->created_ = true; return result; } void V8::SetDcheckErrorHandler(DcheckErrorCallback that) { v8::base::SetDcheckFunction(that); } void V8::SetFlagsFromString(const char* str, int length) { i::FlagList::SetFlagsFromString(str, length); i::FlagList::EnforceFlagImplications(); } void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); } RegisteredExtension* RegisteredExtension::first_extension_ = nullptr; RegisteredExtension::RegisteredExtension(Extension* extension) : extension_(extension) { } void RegisteredExtension::Register(RegisteredExtension* that) { that->next_ = first_extension_; first_extension_ = that; } void RegisteredExtension::UnregisterAll() { RegisteredExtension* re = first_extension_; while (re != nullptr) { RegisteredExtension* next = re->next(); delete re; re = next; } first_extension_ = nullptr; } namespace { class ExtensionResource : public String::ExternalOneByteStringResource { public: ExtensionResource() : data_(0), length_(0) {} ExtensionResource(const char* data, size_t length) : data_(data), length_(length) {} const char* data() const { return data_; } size_t length() const { return length_; } virtual void Dispose() {} private: const char* data_; size_t length_; }; } // anonymous namespace 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, int source_length) : name_(name), source_length_(source_length >= 0 ? source_length : (source ? static_cast
(strlen(source)) : 0)), dep_count_(dep_count), deps_(deps), auto_enable_(false) { source_ = new ExtensionResource(source, source_length_); CHECK(source != nullptr || source_length_ == 0); } ResourceConstraints::ResourceConstraints() : max_semi_space_size_in_kb_(0), max_old_space_size_(0), stack_limit_(nullptr), code_range_size_(0), max_zone_pool_size_(0) {} void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory, uint64_t virtual_memory_limit) { set_max_semi_space_size_in_kb( i::Heap::ComputeMaxSemiSpaceSize(physical_memory)); set_max_old_space_size(i::Heap::ComputeMaxOldGenerationSize(physical_memory)); set_max_zone_pool_size(i::AccountingAllocator::kMaxPoolSize); if (virtual_memory_limit > 0 && i::kRequiresCodeRange) { // Reserve no more than 1/8 of the memory for the code range, but at most // kMaximalCodeRangeSize. set_code_range_size( i::Min(i::kMaximalCodeRangeSize / i::MB, static_cast
((virtual_memory_limit >> 3) / i::MB))); } } void SetResourceConstraints(i::Isolate* isolate, const ResourceConstraints& constraints) { size_t semi_space_size = constraints.max_semi_space_size_in_kb(); size_t old_space_size = constraints.max_old_space_size(); size_t code_range_size = constraints.code_range_size(); size_t max_pool_size = constraints.max_zone_pool_size(); if (semi_space_size != 0 || old_space_size != 0 || code_range_size != 0) { isolate->heap()->ConfigureHeap(semi_space_size, old_space_size, code_range_size); } isolate->allocator()->ConfigureSegmentPool(max_pool_size); if (constraints.stack_limit() != nullptr) { uintptr_t limit = reinterpret_cast
(constraints.stack_limit()); isolate->stack_guard()->SetStackLimit(limit); } } i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) { LOG_API(isolate, Persistent, New); i::Handle
result = isolate->global_handles()->Create(*obj); #ifdef VERIFY_HEAP if (i::FLAG_verify_heap) { (*obj)->ObjectVerify(isolate); } #endif // VERIFY_HEAP return result.location(); } i::Object** V8::CopyPersistent(i::Object** obj) { i::Handle
result = i::GlobalHandles::CopyGlobal(obj); return result.location(); } void V8::RegisterExternallyReferencedObject(i::Object** object, i::Isolate* isolate) { isolate->heap()->RegisterExternallyReferencedObject(object); } void V8::MakeWeak(i::Object** location, void* parameter, int embedder_field_index1, int embedder_field_index2, WeakCallbackInfo
::Callback weak_callback) { WeakCallbackType type = WeakCallbackType::kParameter; if (embedder_field_index1 == 0) { if (embedder_field_index2 == 1) { type = WeakCallbackType::kInternalFields; } else { DCHECK_EQ(embedder_field_index2, -1); type = WeakCallbackType::kInternalFields; } } else { DCHECK_EQ(embedder_field_index1, -1); DCHECK_EQ(embedder_field_index2, -1); } i::GlobalHandles::MakeWeak(location, parameter, weak_callback, type); } void V8::MakeWeak(i::Object** location, void* parameter, WeakCallbackInfo
::Callback weak_callback, WeakCallbackType type) { i::GlobalHandles::MakeWeak(location, parameter, weak_callback, type); } void V8::MakeWeak(i::Object*** location_addr) { i::GlobalHandles::MakeWeak(location_addr); } void* V8::ClearWeak(i::Object** location) { return i::GlobalHandles::ClearWeakness(location); } void V8::AnnotateStrongRetainer(i::Object** location, const char* label) { i::GlobalHandles::AnnotateStrongRetainer(location, label); } void V8::DisposeGlobal(i::Object** location) { i::GlobalHandles::Destroy(location); } Value* V8::Eternalize(Isolate* v8_isolate, Value* value) { i::Isolate* isolate = reinterpret_cast
(v8_isolate); i::Object* object = *Utils::OpenHandle(value); int index = -1; isolate->eternal_handles()->Create(isolate, object, &index); return reinterpret_cast
( isolate->eternal_handles()->Get(index).location()); } void V8::FromJustIsNothing() { Utils::ApiCheck(false, "v8::FromJust", "Maybe value is Nothing."); } void V8::ToLocalEmpty() { Utils::ApiCheck(false, "v8::ToLocalChecked", "Empty MaybeLocal."); } void V8::InternalFieldOutOfBounds(int index) { Utils::ApiCheck(0 <= index && index < kInternalFieldsInWeakCallback, "WeakCallbackInfo::GetInternalField", "Internal field out of bounds."); } // --- H a n d l e s --- HandleScope::HandleScope(Isolate* isolate) { Initialize(isolate); } void HandleScope::Initialize(Isolate* isolate) { i::Isolate* internal_isolate = reinterpret_cast
(isolate); // We do not want to check the correct usage of the Locker class all over the // place, so we do it only here: Without a HandleScope, an embedder can do // almost nothing, so it is enough to check in this central place. // We make an exception if the serializer is enabled, which means that the // Isolate is exclusively used to create a snapshot. Utils::ApiCheck( !v8::Locker::IsActive() || internal_isolate->thread_manager()->IsLockedByCurrentThread() || internal_isolate->serializer_enabled(), "HandleScope::HandleScope", "Entering the V8 API without proper locking in place"); i::HandleScopeData* current = internal_isolate->handle_scope_data(); isolate_ = internal_isolate; prev_next_ = current->next; prev_limit_ = current->limit; current->level++; } HandleScope::~HandleScope() { i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_); } void* HandleScope::operator new(size_t) { base::OS::Abort(); } void* HandleScope::operator new[](size_t) { base::OS::Abort(); } void HandleScope::operator delete(void*, size_t) { base::OS::Abort(); } void HandleScope::operator delete[](void*, size_t) { base::OS::Abort(); } int HandleScope::NumberOfHandles(Isolate* isolate) { return i::HandleScope::NumberOfHandles( reinterpret_cast
(isolate)); } i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) { return i::HandleScope::CreateHandle(isolate, value); } i::Object** HandleScope::CreateHandle( i::NeverReadOnlySpaceObject* writable_object, i::Object* value) { DCHECK(reinterpret_cast
(writable_object)->IsHeapObject()); return i::HandleScope::CreateHandle(writable_object->GetIsolate(), value); } EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast
(v8_isolate); escape_slot_ = CreateHandle(isolate, i::ReadOnlyRoots(isolate).the_hole_value()); Initialize(v8_isolate); } i::Object** EscapableHandleScope::Escape(i::Object** escape_value) { i::Heap* heap = reinterpret_cast
(GetIsolate())->heap(); Utils::ApiCheck((*escape_slot_)->IsTheHole(heap->isolate()), "EscapableHandleScope::Escape", "Escape value set twice"); if (escape_value == nullptr) { *escape_slot_ = i::ReadOnlyRoots(heap).undefined_value(); return nullptr; } *escape_slot_ = *escape_value; return escape_slot_; } void* EscapableHandleScope::operator new(size_t) { base::OS::Abort(); } void* EscapableHandleScope::operator new[](size_t) { base::OS::Abort(); } void EscapableHandleScope::operator delete(void*, size_t) { base::OS::Abort(); } void EscapableHandleScope::operator delete[](void*, size_t) { base::OS::Abort(); } SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(reinterpret_cast
(isolate)) { i::HandleScopeData* current = isolate_->handle_scope_data(); prev_limit_ = current->limit; current->limit = current->next; prev_sealed_level_ = current->sealed_level; current->sealed_level = current->level; } SealHandleScope::~SealHandleScope() { i::HandleScopeData* current = isolate_->handle_scope_data(); DCHECK_EQ(current->next, current->limit); current->limit = prev_limit_; DCHECK_EQ(current->level, current->sealed_level); current->sealed_level = prev_sealed_level_; } void* SealHandleScope::operator new(size_t) { base::OS::Abort(); } void* SealHandleScope::operator new[](size_t) { base::OS::Abort(); } void SealHandleScope::operator delete(void*, size_t) { base::OS::Abort(); } void SealHandleScope::operator delete[](void*, size_t) { base::OS::Abort(); } void Context::Enter() { i::Handle
env = Utils::OpenHandle(this); i::Isolate* isolate = env->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); impl->EnterContext(env); impl->SaveContext(isolate->context()); isolate->set_context(*env); } void Context::Exit() { i::Handle
env = Utils::OpenHandle(this); i::Isolate* isolate = env->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); if (!Utils::ApiCheck(impl->LastEnteredContextWas(env), "v8::Context::Exit()", "Cannot exit non-entered context")) { return; } impl->LeaveContext(); isolate->set_context(impl->RestoreContext()); } Context::BackupIncumbentScope::BackupIncumbentScope( Local
backup_incumbent_context) : backup_incumbent_context_(backup_incumbent_context) { DCHECK(!backup_incumbent_context_.IsEmpty()); i::Handle
env = Utils::OpenHandle(*backup_incumbent_context_); i::Isolate* isolate = env->GetIsolate(); prev_ = isolate->top_backup_incumbent_scope(); isolate->set_top_backup_incumbent_scope(this); } Context::BackupIncumbentScope::~BackupIncumbentScope() { i::Handle
env = Utils::OpenHandle(*backup_incumbent_context_); i::Isolate* isolate = env->GetIsolate(); isolate->set_top_backup_incumbent_scope(prev_); } static void* DecodeSmiToAligned(i::Object* value, const char* location) { Utils::ApiCheck(value->IsSmi(), location, "Not a Smi"); return reinterpret_cast
(value); } static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) { i::Smi* smi = reinterpret_cast
(value); Utils::ApiCheck(smi->IsSmi(), location, "Pointer is not aligned"); return smi; } static i::Handle
EmbedderDataFor(Context* context, int index, bool can_grow, const char* location) { i::Handle
env = Utils::OpenHandle(context); i::Isolate* isolate = env->GetIsolate(); bool ok = Utils::ApiCheck(env->IsNativeContext(), location, "Not a native context") && Utils::ApiCheck(index >= 0, location, "Negative index"); if (!ok) return i::Handle
(); i::Handle
data(env->embedder_data(), isolate); if (index < data->length()) return data; if (!Utils::ApiCheck(can_grow, location, "Index too large")) { return i::Handle
(); } int new_size = index + 1; int grow_by = new_size - data->length(); data = isolate->factory()->CopyFixedArrayAndGrow(data, grow_by); env->set_embedder_data(*data); return data; } uint32_t Context::GetNumberOfEmbedderDataFields() { i::Handle
context = Utils::OpenHandle(this); CHECK(context->IsNativeContext()); return static_cast
(context->embedder_data()->length()); } v8::Local
Context::SlowGetEmbedderData(int index) { const char* location = "v8::Context::GetEmbedderData()"; i::Handle
data = EmbedderDataFor(this, index, false, location); if (data.is_null()) return Local
(); i::Handle
result( data->get(index), reinterpret_cast
(Utils::OpenHandle(this)->GetIsolate())); return Utils::ToLocal(result); } void Context::SetEmbedderData(int index, v8::Local
value) { const char* location = "v8::Context::SetEmbedderData()"; i::Handle
data = EmbedderDataFor(this, index, true, location); if (data.is_null()) return; i::Handle
val = Utils::OpenHandle(*value); data->set(index, *val); DCHECK_EQ(*Utils::OpenHandle(*value), *Utils::OpenHandle(*GetEmbedderData(index))); } void* Context::SlowGetAlignedPointerFromEmbedderData(int index) { const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()"; i::Handle
data = EmbedderDataFor(this, index, false, location); if (data.is_null()) return nullptr; return DecodeSmiToAligned(data->get(index), location); } void Context::SetAlignedPointerInEmbedderData(int index, void* value) { const char* location = "v8::Context::SetAlignedPointerInEmbedderData()"; i::Handle
data = EmbedderDataFor(this, index, true, location); data->set(index, EncodeAlignedAsSmi(value, location)); DCHECK_EQ(value, GetAlignedPointerFromEmbedderData(index)); } // --- T e m p l a t e --- static void InitializeTemplate(i::Handle
that, int type) { that->set_number_of_properties(0); that->set_tag(i::Smi::FromInt(type)); } void Template::Set(v8::Local
name, v8::Local
value, v8::PropertyAttribute attribute) { auto templ = Utils::OpenHandle(this); i::Isolate* isolate = templ->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto value_obj = Utils::OpenHandle(*value); CHECK(!value_obj->IsJSReceiver() || value_obj->IsTemplateInfo()); if (value_obj->IsObjectTemplateInfo()) { templ->set_serial_number(i::Smi::kZero); if (templ->IsFunctionTemplateInfo()) { i::Handle
::cast(templ)->set_do_not_cache(true); } } i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name), value_obj, static_cast
(attribute)); } void Template::SetPrivate(v8::Local
name, v8::Local
value, v8::PropertyAttribute attribute) { Set(Utils::ToLocal(Utils::OpenHandle(reinterpret_cast
(*name))), value, attribute); } void Template::SetAccessorProperty( v8::Local
name, v8::Local
getter, v8::Local
setter, v8::PropertyAttribute attribute, v8::AccessControl access_control) { // TODO(verwaest): Remove |access_control|. DCHECK_EQ(v8::DEFAULT, access_control); auto templ = Utils::OpenHandle(this); auto isolate = templ->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); DCHECK(!name.IsEmpty()); DCHECK(!getter.IsEmpty() || !setter.IsEmpty()); i::HandleScope scope(isolate); i::ApiNatives::AddAccessorProperty( isolate, templ, Utils::OpenHandle(*name), Utils::OpenHandle(*getter, true), Utils::OpenHandle(*setter, true), static_cast
(attribute)); } // --- F u n c t i o n T e m p l a t e --- static void InitializeFunctionTemplate( i::Handle
info) { InitializeTemplate(info, Consts::FUNCTION_TEMPLATE); info->set_flag(0); } static Local
ObjectTemplateNew( i::Isolate* isolate, v8::Local
constructor, bool do_not_cache); Local
FunctionTemplate::PrototypeTemplate() { i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle
result(Utils::OpenHandle(this)->prototype_template(), i_isolate); if (result->IsUndefined(i_isolate)) { // Do not cache prototype objects. result = Utils::OpenHandle( *ObjectTemplateNew(i_isolate, Local
(), true)); Utils::OpenHandle(this)->set_prototype_template(*result); } return ToApiHandle
(result); } void FunctionTemplate::SetPrototypeProviderTemplate( Local
prototype_provider) { i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle
result = Utils::OpenHandle(*prototype_provider); auto info = Utils::OpenHandle(this); CHECK(info->prototype_template()->IsUndefined(i_isolate)); CHECK(info->parent_template()->IsUndefined(i_isolate)); info->set_prototype_provider_template(*result); } static void EnsureNotInstantiated(i::Handle
info, const char* func) { Utils::ApiCheck(!info->instantiated(), func, "FunctionTemplate already instantiated"); } void FunctionTemplate::Inherit(v8::Local
value) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::Inherit"); i::Isolate* i_isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); CHECK(info->prototype_provider_template()->IsUndefined(i_isolate)); info->set_parent_template(*Utils::OpenHandle(*value)); } static Local
FunctionTemplateNew( i::Isolate* isolate, FunctionCallback callback, v8::Local
data, v8::Local
signature, int length, bool do_not_cache, v8::Local
cached_property_name = v8::Local
(), SideEffectType side_effect_type = SideEffectType::kHasSideEffect) { i::Handle
struct_obj = isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE, i::TENURED); i::Handle
obj = i::Handle
::cast(struct_obj); InitializeFunctionTemplate(obj); obj->set_do_not_cache(do_not_cache); int next_serial_number = i::FunctionTemplateInfo::kInvalidSerialNumber; if (!do_not_cache) { next_serial_number = isolate->heap()->GetNextTemplateSerialNumber(); } obj->set_serial_number(i::Smi::FromInt(next_serial_number)); if (callback != 0) { Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type); } obj->set_length(length); obj->set_undetectable(false); obj->set_needs_access_check(false); obj->set_accept_any_receiver(true); if (!signature.IsEmpty()) { obj->set_signature(*Utils::OpenHandle(*signature)); } obj->set_cached_property_name( cached_property_name.IsEmpty() ? i::ReadOnlyRoots(isolate).the_hole_value() : *Utils::OpenHandle(*cached_property_name)); return Utils::ToLocal(obj); } Local
FunctionTemplate::New( Isolate* isolate, FunctionCallback callback, v8::Local
data, v8::Local
signature, int length, ConstructorBehavior behavior, SideEffectType side_effect_type) { i::Isolate* i_isolate = reinterpret_cast
(isolate); // Changes to the environment cannot be captured in the snapshot. Expect no // function templates when the isolate is created for serialization. LOG_API(i_isolate, FunctionTemplate, New); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); auto templ = FunctionTemplateNew(i_isolate, callback, data, signature, length, false, Local
(), side_effect_type); if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype(); return templ; } MaybeLocal
FunctionTemplate::FromSnapshot(Isolate* isolate, size_t index) { i::Isolate* i_isolate = reinterpret_cast
(isolate); i::FixedArray* serialized_objects = i_isolate->heap()->serialized_objects(); int int_index = static_cast
(index); if (int_index < serialized_objects->length()) { i::Object* info = serialized_objects->get(int_index); if (info->IsFunctionTemplateInfo()) { return Utils::ToLocal(i::Handle
( i::FunctionTemplateInfo::cast(info), i_isolate)); } } return Local
(); } Local
FunctionTemplate::NewWithCache( Isolate* isolate, FunctionCallback callback, Local
cache_property, Local
data, Local
signature, int length, SideEffectType side_effect_type) { i::Isolate* i_isolate = reinterpret_cast
(isolate); LOG_API(i_isolate, FunctionTemplate, NewWithCache); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); return FunctionTemplateNew(i_isolate, callback, data, signature, length, false, cache_property, side_effect_type); } Local
Signature::New(Isolate* isolate, Local
receiver) { return Utils::SignatureToLocal(Utils::OpenHandle(*receiver)); } Local
AccessorSignature::New( Isolate* isolate, Local
receiver) { return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver)); } #define SET_FIELD_WRAPPED(isolate, obj, setter, cdata) \ do { \ i::Handle
foreign = FromCData(isolate, cdata); \ (obj)->setter(*foreign); \ } while (false) void FunctionTemplate::SetCallHandler(FunctionCallback callback, v8::Local
data, SideEffectType side_effect_type) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetCallHandler"); i::Isolate* isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); i::Handle
obj = isolate->factory()->NewCallHandlerInfo( side_effect_type == SideEffectType::kHasNoSideEffect); SET_FIELD_WRAPPED(isolate, obj, set_callback, callback); SET_FIELD_WRAPPED(isolate, obj, set_js_callback, obj->redirected_callback()); if (data.IsEmpty()) { data = v8::Undefined(reinterpret_cast
(isolate)); } obj->set_data(*Utils::OpenHandle(*data)); info->set_call_code(*obj); } namespace { template
i::Handle
MakeAccessorInfo( i::Isolate* isolate, v8::Local
name, Getter getter, Setter setter, v8::Local
data, v8::AccessControl settings, v8::Local
signature, bool is_special_data_property, bool replace_on_access) { i::Handle
obj = isolate->factory()->NewAccessorInfo(); SET_FIELD_WRAPPED(isolate, obj, set_getter, getter); DCHECK_IMPLIES(replace_on_access, is_special_data_property && setter == nullptr); if (is_special_data_property && setter == nullptr) { setter = reinterpret_cast
(&i::Accessors::ReconfigureToDataProperty); } SET_FIELD_WRAPPED(isolate, obj, set_setter, setter); i::Address redirected = obj->redirected_getter(); if (redirected != i::kNullAddress) { SET_FIELD_WRAPPED(isolate, obj, set_js_getter, redirected); } if (data.IsEmpty()) { data = v8::Undefined(reinterpret_cast
(isolate)); } obj->set_data(*Utils::OpenHandle(*data)); obj->set_is_special_data_property(is_special_data_property); obj->set_replace_on_access(replace_on_access); i::Handle
accessor_name = Utils::OpenHandle(*name); if (!accessor_name->IsUniqueName()) { accessor_name = isolate->factory()->InternalizeString( i::Handle
::cast(accessor_name)); } obj->set_name(*accessor_name); if (settings & ALL_CAN_READ) obj->set_all_can_read(true); if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true); obj->set_initial_property_attributes(i::NONE); if (!signature.IsEmpty()) { obj->set_expected_receiver_type(*Utils::OpenHandle(*signature)); } return obj; } } // namespace Local
FunctionTemplate::InstanceTemplate() { i::Handle
handle = Utils::OpenHandle(this, true); if (!Utils::ApiCheck(!handle.is_null(), "v8::FunctionTemplate::InstanceTemplate()", "Reading from empty handle")) { return Local
(); } i::Isolate* isolate = handle->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); if (handle->instance_template()->IsUndefined(isolate)) { Local
templ = ObjectTemplate::New(isolate, ToApiHandle
(handle)); handle->set_instance_template(*Utils::OpenHandle(*templ)); } i::Handle
result( i::ObjectTemplateInfo::cast(handle->instance_template()), isolate); return Utils::ToLocal(result); } void FunctionTemplate::SetLength(int length) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetLength"); auto isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_length(length); } void FunctionTemplate::SetClassName(Local
name) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetClassName"); auto isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_class_name(*Utils::OpenHandle(*name)); } void FunctionTemplate::SetAcceptAnyReceiver(bool value) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetAcceptAnyReceiver"); auto isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_accept_any_receiver(value); } void FunctionTemplate::SetHiddenPrototype(bool value) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetHiddenPrototype"); auto isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_hidden_prototype(value); } void FunctionTemplate::ReadOnlyPrototype() { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::ReadOnlyPrototype"); auto isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_read_only_prototype(true); } void FunctionTemplate::RemovePrototype() { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::RemovePrototype"); auto isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_remove_prototype(true); } // --- O b j e c t T e m p l a t e --- Local
ObjectTemplate::New( Isolate* isolate, v8::Local
constructor) { return New(reinterpret_cast
(isolate), constructor); } static Local
ObjectTemplateNew( i::Isolate* isolate, v8::Local
constructor, bool do_not_cache) { LOG_API(isolate, ObjectTemplate, New); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::Handle
struct_obj = isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE, i::TENURED); i::Handle
obj = i::Handle
::cast(struct_obj); InitializeTemplate(obj, Consts::OBJECT_TEMPLATE); int next_serial_number = 0; if (!do_not_cache) { next_serial_number = isolate->heap()->GetNextTemplateSerialNumber(); } obj->set_serial_number(i::Smi::FromInt(next_serial_number)); if (!constructor.IsEmpty()) obj->set_constructor(*Utils::OpenHandle(*constructor)); obj->set_data(i::Smi::kZero); return Utils::ToLocal(obj); } Local
ObjectTemplate::New( i::Isolate* isolate, v8::Local
constructor) { return ObjectTemplateNew(isolate, constructor, false); } MaybeLocal
ObjectTemplate::FromSnapshot(Isolate* isolate, size_t index) { i::Isolate* i_isolate = reinterpret_cast
(isolate); i::FixedArray* serialized_objects = i_isolate->heap()->serialized_objects(); int int_index = static_cast
(index); if (int_index < serialized_objects->length()) { i::Object* info = serialized_objects->get(int_index); if (info->IsObjectTemplateInfo()) { return Utils::ToLocal(i::Handle
( i::ObjectTemplateInfo::cast(info), i_isolate)); } } return Local
(); } // Ensure that the object template has a constructor. If no // constructor is available we create one. static i::Handle
EnsureConstructor( i::Isolate* isolate, ObjectTemplate* object_template) { i::Object* obj = Utils::OpenHandle(object_template)->constructor(); if (!obj->IsUndefined(isolate)) { i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj); return i::Handle
(info, isolate); } Local
templ = FunctionTemplate::New(reinterpret_cast
(isolate)); i::Handle
constructor = Utils::OpenHandle(*templ); constructor->set_instance_template(*Utils::OpenHandle(object_template)); Utils::OpenHandle(object_template)->set_constructor(*constructor); return constructor; } template
static void TemplateSetAccessor( Template* template_obj, v8::Local
name, Getter getter, Setter setter, Data data, AccessControl settings, PropertyAttribute attribute, v8::Local
signature, bool is_special_data_property, bool replace_on_access, SideEffectType getter_side_effect_type) { auto info = Utils::OpenHandle(template_obj); auto isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); i::Handle
accessor_info = MakeAccessorInfo(isolate, name, getter, setter, data, settings, signature, is_special_data_property, replace_on_access); accessor_info->set_initial_property_attributes( static_cast
(attribute)); accessor_info->set_has_no_side_effect(getter_side_effect_type == SideEffectType::kHasNoSideEffect); i::ApiNatives::AddNativeDataProperty(isolate, info, accessor_info); } void Template::SetNativeDataProperty( v8::Local
name, AccessorGetterCallback getter, AccessorSetterCallback setter, v8::Local
data, PropertyAttribute attribute, v8::Local
signature, AccessControl settings, SideEffectType getter_side_effect_type) { TemplateSetAccessor(this, name, getter, setter, data, settings, attribute, signature, true, false, getter_side_effect_type); } void Template::SetNativeDataProperty( v8::Local
name, AccessorNameGetterCallback getter, AccessorNameSetterCallback setter, v8::Local
data, PropertyAttribute attribute, v8::Local
signature, AccessControl settings, SideEffectType getter_side_effect_type) { TemplateSetAccessor(this, name, getter, setter, data, settings, attribute, signature, true, false, getter_side_effect_type); } void Template::SetLazyDataProperty(v8::Local
name, AccessorNameGetterCallback getter, v8::Local
data, PropertyAttribute attribute, SideEffectType getter_side_effect_type) { TemplateSetAccessor(this, name, getter, static_cast
(nullptr), data, DEFAULT, attribute, Local
(), true, true, getter_side_effect_type); } void Template::SetIntrinsicDataProperty(Local
name, Intrinsic intrinsic, PropertyAttribute attribute) { auto templ = Utils::OpenHandle(this); i::Isolate* isolate = templ->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name), intrinsic, static_cast
(attribute)); } void ObjectTemplate::SetAccessor(v8::Local
name, AccessorGetterCallback getter, AccessorSetterCallback setter, v8::Local
data, AccessControl settings, PropertyAttribute attribute, v8::Local
signature, SideEffectType getter_side_effect_type) { TemplateSetAccessor(this, name, getter, setter, data, settings, attribute, signature, i::FLAG_disable_old_api_accessors, false, getter_side_effect_type); } void ObjectTemplate::SetAccessor(v8::Local
name, AccessorNameGetterCallback getter, AccessorNameSetterCallback setter, v8::Local
data, AccessControl settings, PropertyAttribute attribute, v8::Local
signature, SideEffectType getter_side_effect_type) { TemplateSetAccessor(this, name, getter, setter, data, settings, attribute, signature, i::FLAG_disable_old_api_accessors, false, getter_side_effect_type); } template
static i::Handle
CreateInterceptorInfo( i::Isolate* isolate, Getter getter, Setter setter, Query query, Descriptor descriptor, Deleter remover, Enumerator enumerator, Definer definer, Local
data, PropertyHandlerFlags flags) { auto obj = i::Handle
::cast( isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE, i::TENURED)); obj->set_flags(0); if (getter != 0) SET_FIELD_WRAPPED(isolate, obj, set_getter, getter); if (setter != 0) SET_FIELD_WRAPPED(isolate, obj, set_setter, setter); if (query != 0) SET_FIELD_WRAPPED(isolate, obj, set_query, query); if (descriptor != 0) SET_FIELD_WRAPPED(isolate, obj, set_descriptor, descriptor); if (remover != 0) SET_FIELD_WRAPPED(isolate, obj, set_deleter, remover); if (enumerator != 0) SET_FIELD_WRAPPED(isolate, obj, set_enumerator, enumerator); if (definer != 0) SET_FIELD_WRAPPED(isolate, obj, set_definer, definer); obj->set_can_intercept_symbols( !(static_cast
(flags) & static_cast
(PropertyHandlerFlags::kOnlyInterceptStrings))); obj->set_all_can_read(static_cast
(flags) & static_cast
(PropertyHandlerFlags::kAllCanRead)); obj->set_non_masking(static_cast
(flags) & static_cast
(PropertyHandlerFlags::kNonMasking)); obj->set_has_no_side_effect( static_cast
(flags) & static_cast
(PropertyHandlerFlags::kHasNoSideEffect)); if (data.IsEmpty()) { data = v8::Undefined(reinterpret_cast
(isolate)); } obj->set_data(*Utils::OpenHandle(*data)); return obj; } template
static i::Handle
CreateNamedInterceptorInfo( i::Isolate* isolate, Getter getter, Setter setter, Query query, Descriptor descriptor, Deleter remover, Enumerator enumerator, Definer definer, Local
data, PropertyHandlerFlags flags) { auto interceptor = CreateInterceptorInfo(isolate, getter, setter, query, descriptor, remover, enumerator, definer, data, flags); interceptor->set_is_named(true); return interceptor; } template
static i::Handle
CreateIndexedInterceptorInfo( i::Isolate* isolate, Getter getter, Setter setter, Query query, Descriptor descriptor, Deleter remover, Enumerator enumerator, Definer definer, Local
data, PropertyHandlerFlags flags) { auto interceptor = CreateInterceptorInfo(isolate, getter, setter, query, descriptor, remover, enumerator, definer, data, flags); interceptor->set_is_named(false); return interceptor; } template
static void ObjectTemplateSetNamedPropertyHandler( ObjectTemplate* templ, Getter getter, Setter setter, Query query, Descriptor descriptor, Deleter remover, Enumerator enumerator, Definer definer, Local
data, PropertyHandlerFlags flags) { i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, templ); EnsureNotInstantiated(cons, "ObjectTemplateSetNamedPropertyHandler"); auto obj = CreateNamedInterceptorInfo(isolate, getter, setter, query, descriptor, remover, enumerator, definer, data, flags); cons->set_named_property_handler(*obj); } void ObjectTemplate::SetHandler( const NamedPropertyHandlerConfiguration& config) { ObjectTemplateSetNamedPropertyHandler( this, config.getter, config.setter, config.query, config.descriptor, config.deleter, config.enumerator, config.definer, config.data, config.flags); } void ObjectTemplate::MarkAsUndetectable() { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, this); EnsureNotInstantiated(cons, "v8::ObjectTemplate::MarkAsUndetectable"); cons->set_undetectable(true); } void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback, Local
data) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, this); EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetAccessCheckCallback"); i::Handle
struct_info = isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE, i::TENURED); i::Handle
info = i::Handle
::cast(struct_info); SET_FIELD_WRAPPED(isolate, info, set_callback, callback); info->set_named_interceptor(nullptr); info->set_indexed_interceptor(nullptr); if (data.IsEmpty()) { data = v8::Undefined(reinterpret_cast
(isolate)); } info->set_data(*Utils::OpenHandle(*data)); cons->set_access_check_info(*info); cons->set_needs_access_check(true); } void ObjectTemplate::SetAccessCheckCallbackAndHandler( AccessCheckCallback callback, const NamedPropertyHandlerConfiguration& named_handler, const IndexedPropertyHandlerConfiguration& indexed_handler, Local
data) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, this); EnsureNotInstantiated( cons, "v8::ObjectTemplate::SetAccessCheckCallbackWithHandler"); i::Handle