// 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. #ifdef V8_USE_ADDRESS_SANITIZER #include #endif // V8_USE_ADDRESS_SANITIZER #include // For isnan. #include "include/v8-debug.h" #include "include/v8-profiler.h" #include "include/v8-testing.h" #include "src/assert-scope.h" #include "src/background-parsing-task.h" #include "src/base/functional.h" #include "src/base/platform/platform.h" #include "src/base/platform/time.h" #include "src/base/utils/random-number-generator.h" #include "src/bootstrapper.h" #include "src/code-stubs.h" #include "src/compiler.h" #include "src/conversions-inl.h" #include "src/counters.h" #include "src/cpu-profiler.h" #include "src/debug.h" #include "src/deoptimizer.h" #include "src/execution.h" #include "src/full-codegen.h" #include "src/global-handles.h" #include "src/heap-profiler.h" #include "src/heap-snapshot-generator-inl.h" #include "src/icu_util.h" #include "src/json-parser.h" #include "src/messages.h" #include "src/natives.h" #include "src/parser.h" #include "src/profile-generator-inl.h" #include "src/property.h" #include "src/property-details.h" #include "src/prototype.h" #include "src/runtime/runtime.h" #include "src/runtime-profiler.h" #include "src/sampler.h" #include "src/scanner-character-streams.h" #include "src/simulator.h" #include "src/snapshot.h" #include "src/unicode-inl.h" #include "src/v8threads.h" #include "src/version.h" #include "src/vm-state-inl.h" #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr)) #define ENTER_V8(isolate) \ i::VMState __state__((isolate)) namespace v8 { #define ON_BAILOUT(isolate, location, code) \ if (IsExecutionTerminatingCheck(isolate)) { \ code; \ UNREACHABLE(); \ } #define EXCEPTION_PREAMBLE(isolate) \ (isolate)->handle_scope_implementer()->IncrementCallDepth(); \ DCHECK(!(isolate)->external_caught_exception()); \ bool has_pending_exception = false #define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback) \ do { \ i::HandleScopeImplementer* handle_scope_implementer = \ (isolate)->handle_scope_implementer(); \ handle_scope_implementer->DecrementCallDepth(); \ if (has_pending_exception) { \ bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); \ (isolate)->OptionalRescheduleException(call_depth_is_zero); \ do_callback \ return value; \ } \ do_callback \ } while (false) #define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value) \ EXCEPTION_BAILOUT_CHECK_GENERIC( \ isolate, value, isolate->FireCallCompletedCallback();) #define EXCEPTION_BAILOUT_CHECK(isolate, value) \ EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;) // --- E x c e p t i o n B e h a v i o r --- void i::FatalProcessOutOfMemory(const char* location) { i::V8::FatalProcessOutOfMemory(location, false); } // 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, bool take_snapshot) { i::HeapStats heap_stats; int start_marker; heap_stats.start_marker = &start_marker; int new_space_size; heap_stats.new_space_size = &new_space_size; int new_space_capacity; heap_stats.new_space_capacity = &new_space_capacity; intptr_t old_pointer_space_size; heap_stats.old_pointer_space_size = &old_pointer_space_size; intptr_t old_pointer_space_capacity; heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity; intptr_t old_data_space_size; heap_stats.old_data_space_size = &old_data_space_size; intptr_t old_data_space_capacity; heap_stats.old_data_space_capacity = &old_data_space_capacity; intptr_t code_space_size; heap_stats.code_space_size = &code_space_size; intptr_t code_space_capacity; heap_stats.code_space_capacity = &code_space_capacity; intptr_t map_space_size; heap_stats.map_space_size = &map_space_size; intptr_t map_space_capacity; heap_stats.map_space_capacity = &map_space_capacity; intptr_t cell_space_size; heap_stats.cell_space_size = &cell_space_size; intptr_t cell_space_capacity; heap_stats.cell_space_capacity = &cell_space_capacity; intptr_t property_cell_space_size; heap_stats.property_cell_space_size = &property_cell_space_size; intptr_t property_cell_space_capacity; heap_stats.property_cell_space_capacity = &property_cell_space_capacity; intptr_t lo_space_size; heap_stats.lo_space_size = &lo_space_size; int global_handle_count; heap_stats.global_handle_count = &global_handle_count; int weak_global_handle_count; heap_stats.weak_global_handle_count = &weak_global_handle_count; int pending_global_handle_count; heap_stats.pending_global_handle_count = &pending_global_handle_count; int near_death_global_handle_count; heap_stats.near_death_global_handle_count = &near_death_global_handle_count; int free_global_handle_count; heap_stats.free_global_handle_count = &free_global_handle_count; intptr_t memory_allocator_size; heap_stats.memory_allocator_size = &memory_allocator_size; intptr_t memory_allocator_capacity; heap_stats.memory_allocator_capacity = &memory_allocator_capacity; int objects_per_type[LAST_TYPE + 1] = {0}; heap_stats.objects_per_type = objects_per_type; int size_per_type[LAST_TYPE + 1] = {0}; heap_stats.size_per_type = size_per_type; int os_error; heap_stats.os_error = &os_error; int end_marker; heap_stats.end_marker = &end_marker; i::Isolate* isolate = i::Isolate::Current(); 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); } Utils::ApiCheck(false, location, "Allocation failed - process out of memory"); // 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 = isolate->exception_behavior(); if (callback == NULL) { 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(); } static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { if (isolate->has_scheduled_exception()) { return isolate->scheduled_exception() == isolate->heap()->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); } bool RunExtraCode(Isolate* isolate, char* utf8_source) { // Run custom script if provided. TryCatch try_catch; Local source_string = String::NewFromUtf8(isolate, utf8_source); if (try_catch.HasCaught()) return false; ScriptOrigin origin(String::NewFromUtf8(isolate, "")); ScriptCompiler::Source source(source_string, origin); Local