summaryrefslogtreecommitdiff
path: root/deps/v8/src/isolate.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/isolate.cc')
-rw-r--r--deps/v8/src/isolate.cc535
1 files changed, 385 insertions, 150 deletions
diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc
index eed52d9c19..94033f446b 100644
--- a/deps/v8/src/isolate.cc
+++ b/deps/v8/src/isolate.cc
@@ -15,6 +15,7 @@
#include "src/assembler-inl.h"
#include "src/ast/ast-value-factory.h"
#include "src/ast/context-slot-cache.h"
+#include "src/ast/scopes.h"
#include "src/base/adapters.h"
#include "src/base/hashmap.h"
#include "src/base/platform/platform.h"
@@ -28,6 +29,7 @@
#include "src/compilation-statistics.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h"
#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
+#include "src/debug/debug-frames.h"
#include "src/debug/debug.h"
#include "src/deoptimizer.h"
#include "src/elements.h"
@@ -42,8 +44,10 @@
#include "src/objects/frame-array-inl.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/js-array-inl.h"
+#include "src/objects/js-generator-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/promise-inl.h"
+#include "src/objects/stack-frame-info-inl.h"
#include "src/profiler/tracing-cpu-profiler.h"
#include "src/prototype.h"
#include "src/regexp/regexp-stack.h"
@@ -161,7 +165,6 @@ void ThreadLocalTop::Initialize(Isolate* isolate) {
}
void ThreadLocalTop::Free() {
- wasm_caught_exception_ = nullptr;
// Match unmatched PopPromise calls.
while (promise_on_stack_) isolate_->PopPromise();
}
@@ -252,7 +255,6 @@ void Isolate::IterateThread(ThreadVisitor* v, char* t) {
void Isolate::Iterate(RootVisitor* v, ThreadLocalTop* thread) {
// Visit the roots from the top for a given thread.
v->VisitRootPointer(Root::kTop, nullptr, &thread->pending_exception_);
- v->VisitRootPointer(Root::kTop, nullptr, &thread->wasm_caught_exception_);
v->VisitRootPointer(Root::kTop, nullptr, &thread->pending_message_obj_);
v->VisitRootPointer(Root::kTop, nullptr,
bit_cast<Object**>(&(thread->context_)));
@@ -409,82 +411,87 @@ class FrameArrayBuilder {
elements_ = isolate->factory()->NewFrameArray(Min(limit, 10));
}
- void AppendStandardFrame(StandardFrame* frame) {
- std::vector<FrameSummary> frames;
- frame->Summarize(&frames);
- // A standard frame may include many summarized frames (due to inlining).
- for (size_t i = frames.size(); i != 0 && !full(); i--) {
- const auto& summ = frames[i - 1];
- if (summ.IsJavaScript()) {
- //====================================================================
- // Handle a JavaScript frame.
- //====================================================================
- const auto& summary = summ.AsJavaScript();
-
- // Filter out internal frames that we do not want to show.
- if (!IsVisibleInStackTrace(summary.function())) continue;
-
- Handle<AbstractCode> abstract_code = summary.abstract_code();
- const int offset = summary.code_offset();
-
- bool is_constructor = summary.is_constructor();
- // Help CallSite::IsConstructor correctly detect hand-written
- // construct stubs.
- if (abstract_code->IsCode() &&
- Code::cast(*abstract_code)->is_construct_stub()) {
- is_constructor = true;
- }
+ void AppendAsyncFrame(Handle<JSGeneratorObject> generator_object) {
+ if (full()) return;
+ Handle<JSFunction> function(generator_object->function(), isolate_);
+ if (!IsVisibleInStackTrace(function)) return;
+ int flags = FrameArray::kIsAsync;
+ if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
- int flags = 0;
- Handle<JSFunction> function = summary.function();
- if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
- if (is_constructor) flags |= FrameArray::kIsConstructor;
-
- elements_ = FrameArray::AppendJSFrame(
- elements_, TheHoleToUndefined(isolate_, summary.receiver()),
- function, abstract_code, offset, flags);
- } else if (summ.IsWasmCompiled()) {
- //====================================================================
- // Handle a WASM compiled frame.
- //====================================================================
- const auto& summary = summ.AsWasmCompiled();
- if (summary.code()->kind() != wasm::WasmCode::kFunction) {
- continue;
- }
- Handle<WasmInstanceObject> instance = summary.wasm_instance();
- int flags = 0;
- if (instance->module_object()->is_asm_js()) {
- flags |= FrameArray::kIsAsmJsWasmFrame;
- if (WasmCompiledFrame::cast(frame)->at_to_number_conversion()) {
- flags |= FrameArray::kAsmJsAtNumberConversion;
- }
- } else {
- flags |= FrameArray::kIsWasmFrame;
- }
+ Handle<Object> receiver(generator_object->receiver(), isolate_);
+ Handle<AbstractCode> code(
+ AbstractCode::cast(function->shared()->GetBytecodeArray()), isolate_);
+ int offset = Smi::ToInt(generator_object->input_or_debug_pos());
+ // The stored bytecode offset is relative to a different base than what
+ // is used in the source position table, hence the subtraction.
+ offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
+ elements_ = FrameArray::AppendJSFrame(elements_, receiver, function, code,
+ offset, flags);
+ }
+
+ bool AppendJavaScriptFrame(
+ FrameSummary::JavaScriptFrameSummary const& summary) {
+ // Filter out internal frames that we do not want to show.
+ if (!IsVisibleInStackTrace(summary.function())) return false;
+
+ Handle<AbstractCode> abstract_code = summary.abstract_code();
+ const int offset = summary.code_offset();
+
+ bool is_constructor = summary.is_constructor();
+ // Help CallSite::IsConstructor correctly detect hand-written
+ // construct stubs.
+ if (abstract_code->IsCode() &&
+ Code::cast(*abstract_code)->is_construct_stub()) {
+ is_constructor = true;
+ }
- elements_ = FrameArray::AppendWasmFrame(
- elements_, instance, summary.function_index(), summary.code(),
- summary.code_offset(), flags);
- } else if (summ.IsWasmInterpreted()) {
- //====================================================================
- // Handle a WASM interpreted frame.
- //====================================================================
- const auto& summary = summ.AsWasmInterpreted();
- Handle<WasmInstanceObject> instance = summary.wasm_instance();
- int flags = FrameArray::kIsWasmInterpretedFrame;
- DCHECK(!instance->module_object()->is_asm_js());
- elements_ = FrameArray::AppendWasmFrame(elements_, instance,
- summary.function_index(), {},
- summary.byte_offset(), flags);
+ int flags = 0;
+ Handle<JSFunction> function = summary.function();
+ if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
+ if (is_constructor) flags |= FrameArray::kIsConstructor;
+
+ elements_ = FrameArray::AppendJSFrame(
+ elements_, TheHoleToUndefined(isolate_, summary.receiver()), function,
+ abstract_code, offset, flags);
+ return true;
+ }
+
+ bool AppendWasmCompiledFrame(
+ FrameSummary::WasmCompiledFrameSummary const& summary) {
+ if (summary.code()->kind() != wasm::WasmCode::kFunction) return false;
+ Handle<WasmInstanceObject> instance = summary.wasm_instance();
+ int flags = 0;
+ if (instance->module_object()->is_asm_js()) {
+ flags |= FrameArray::kIsAsmJsWasmFrame;
+ if (summary.at_to_number_conversion()) {
+ flags |= FrameArray::kAsmJsAtNumberConversion;
}
+ } else {
+ flags |= FrameArray::kIsWasmFrame;
}
+
+ elements_ = FrameArray::AppendWasmFrame(
+ elements_, instance, summary.function_index(), summary.code(),
+ summary.code_offset(), flags);
+ return true;
}
- void AppendBuiltinExitFrame(BuiltinExitFrame* exit_frame) {
+ bool AppendWasmInterpretedFrame(
+ FrameSummary::WasmInterpretedFrameSummary const& summary) {
+ Handle<WasmInstanceObject> instance = summary.wasm_instance();
+ int flags = FrameArray::kIsWasmInterpretedFrame;
+ DCHECK(!instance->module_object()->is_asm_js());
+ elements_ = FrameArray::AppendWasmFrame(elements_, instance,
+ summary.function_index(), {},
+ summary.byte_offset(), flags);
+ return true;
+ }
+
+ bool AppendBuiltinExitFrame(BuiltinExitFrame* exit_frame) {
Handle<JSFunction> function = handle(exit_frame->function(), isolate_);
// Filter out internal frames that we do not want to show.
- if (!IsVisibleInStackTrace(function)) return;
+ if (!IsVisibleInStackTrace(function)) return false;
Handle<Object> receiver(exit_frame->receiver(), isolate_);
Handle<Code> code(exit_frame->LookupCode(), isolate_);
@@ -498,6 +505,8 @@ class FrameArrayBuilder {
elements_ = FrameArray::AppendJSFrame(elements_, receiver, function,
Handle<AbstractCode>::cast(code),
offset, flags);
+
+ return true;
}
bool full() { return elements_->FrameCount() >= limit_; }
@@ -600,6 +609,89 @@ bool GetStackTraceLimit(Isolate* isolate, int* result) {
}
bool NoExtension(const v8::FunctionCallbackInfo<v8::Value>&) { return false; }
+
+bool IsBuiltinFunction(Isolate* isolate, HeapObject* object,
+ Builtins::Name builtin_index) {
+ if (!object->IsJSFunction()) return false;
+ JSFunction* const function = JSFunction::cast(object);
+ return function->code() == isolate->builtins()->builtin(builtin_index);
+}
+
+void CaptureAsyncStackTrace(Isolate* isolate, Handle<JSPromise> promise,
+ FrameArrayBuilder* builder) {
+ CHECK_EQ(Promise::kPending, promise->status());
+
+ while (!builder->full()) {
+ // Check that we have exactly one PromiseReaction on the {promise}.
+ if (!promise->reactions()->IsPromiseReaction()) return;
+ Handle<PromiseReaction> reaction(
+ PromiseReaction::cast(promise->reactions()), isolate);
+ if (!reaction->next()->IsSmi()) return;
+
+ // Check if the {reaction} has one of the known async function or
+ // async generator continuations as its fulfill handler.
+ if (IsBuiltinFunction(isolate, reaction->fulfill_handler(),
+ Builtins::kAsyncFunctionAwaitResolveClosure) ||
+ IsBuiltinFunction(isolate, reaction->fulfill_handler(),
+ Builtins::kAsyncGeneratorAwaitResolveClosure) ||
+ IsBuiltinFunction(isolate, reaction->fulfill_handler(),
+ Builtins::kAsyncGeneratorYieldResolveClosure)) {
+ // Now peak into the handlers' AwaitContext to get to
+ // the JSGeneratorObject for the async function.
+ Handle<Context> context(
+ JSFunction::cast(reaction->fulfill_handler())->context(), isolate);
+ Handle<JSGeneratorObject> generator_object(
+ JSGeneratorObject::cast(context->extension()), isolate);
+ CHECK(generator_object->is_suspended());
+
+ // Append async frame corresponding to the {generator_object}.
+ builder->AppendAsyncFrame(generator_object);
+
+ // Try to continue from here.
+ Handle<JSFunction> function(generator_object->function(), isolate);
+ Handle<SharedFunctionInfo> shared(function->shared(), isolate);
+ if (IsAsyncGeneratorFunction(shared->kind())) {
+ Handle<Object> dot_generator_object(
+ generator_object->parameters_and_registers()->get(
+ DeclarationScope::kGeneratorObjectVarIndex +
+ shared->scope_info()->ParameterCount()),
+ isolate);
+ if (!dot_generator_object->IsJSAsyncGeneratorObject()) return;
+ Handle<JSAsyncGeneratorObject> async_generator_object =
+ Handle<JSAsyncGeneratorObject>::cast(dot_generator_object);
+ Handle<AsyncGeneratorRequest> async_generator_request(
+ AsyncGeneratorRequest::cast(async_generator_object->queue()),
+ isolate);
+ promise = handle(JSPromise::cast(async_generator_request->promise()),
+ isolate);
+ } else {
+ CHECK(IsAsyncFunction(shared->kind()));
+ Handle<Object> dot_promise(
+ generator_object->parameters_and_registers()->get(
+ DeclarationScope::kPromiseVarIndex +
+ shared->scope_info()->ParameterCount()),
+ isolate);
+ if (!dot_promise->IsJSPromise()) return;
+ promise = Handle<JSPromise>::cast(dot_promise);
+ }
+ } else {
+ // We have some generic promise chain here, so try to
+ // continue with the chained promise on the reaction
+ // (only works for native promise chains).
+ Handle<HeapObject> promise_or_capability(
+ reaction->promise_or_capability(), isolate);
+ if (promise_or_capability->IsJSPromise()) {
+ promise = Handle<JSPromise>::cast(promise_or_capability);
+ } else {
+ Handle<PromiseCapability> capability =
+ Handle<PromiseCapability>::cast(promise_or_capability);
+ if (!capability->promise()->IsJSPromise()) return;
+ promise = handle(JSPromise::cast(capability->promise()), isolate);
+ }
+ }
+ }
+}
+
} // namespace
Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
@@ -612,28 +704,72 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
FrameArrayBuilder builder(this, mode, limit, caller);
- for (StackFrameIterator iter(this); !iter.done() && !builder.full();
- iter.Advance()) {
- StackFrame* frame = iter.frame();
-
+ // Build the regular stack trace, and remember the last relevant
+ // frame ID and inlined index (for the async stack trace handling
+ // below, which starts from this last frame).
+ int last_frame_index = 0;
+ StackFrame::Id last_frame_id = StackFrame::NO_ID;
+ for (StackFrameIterator it(this); !it.done() && !builder.full();
+ it.Advance()) {
+ StackFrame* const frame = it.frame();
switch (frame->type()) {
case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION:
case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH:
case StackFrame::OPTIMIZED:
case StackFrame::INTERPRETED:
case StackFrame::BUILTIN:
- builder.AppendStandardFrame(JavaScriptFrame::cast(frame));
+ case StackFrame::WASM_COMPILED:
+ case StackFrame::WASM_INTERPRETER_ENTRY: {
+ // A standard frame may include many summarized frames (due to
+ // inlining).
+ std::vector<FrameSummary> frames;
+ StandardFrame::cast(frame)->Summarize(&frames);
+ for (size_t i = frames.size(); i-- != 0 && !builder.full();) {
+ const auto& summary = frames[i];
+ if (summary.IsJavaScript()) {
+ //====================================================================
+ // Handle a JavaScript frame.
+ //====================================================================
+ auto const& java_script = summary.AsJavaScript();
+ if (builder.AppendJavaScriptFrame(java_script)) {
+ if (IsAsyncFunction(java_script.function()->shared()->kind())) {
+ last_frame_id = frame->id();
+ last_frame_index = static_cast<int>(i);
+ } else {
+ last_frame_id = StackFrame::NO_ID;
+ last_frame_index = 0;
+ }
+ }
+ } else if (summary.IsWasmCompiled()) {
+ //====================================================================
+ // Handle a WASM compiled frame.
+ //====================================================================
+ auto const& wasm_compiled = summary.AsWasmCompiled();
+ if (builder.AppendWasmCompiledFrame(wasm_compiled)) {
+ last_frame_id = StackFrame::NO_ID;
+ last_frame_index = 0;
+ }
+ } else if (summary.IsWasmInterpreted()) {
+ //====================================================================
+ // Handle a WASM interpreted frame.
+ //====================================================================
+ auto const& wasm_interpreted = summary.AsWasmInterpreted();
+ if (builder.AppendWasmInterpretedFrame(wasm_interpreted)) {
+ last_frame_id = StackFrame::NO_ID;
+ last_frame_index = 0;
+ }
+ }
+ }
break;
+ }
+
case StackFrame::BUILTIN_EXIT:
// BuiltinExitFrames are not standard frames, so they do not have
// Summarize(). However, they may have one JS frame worth showing.
- builder.AppendBuiltinExitFrame(BuiltinExitFrame::cast(frame));
- break;
- case StackFrame::WASM_COMPILED:
- builder.AppendStandardFrame(WasmCompiledFrame::cast(frame));
- break;
- case StackFrame::WASM_INTERPRETER_ENTRY:
- builder.AppendStandardFrame(WasmInterpreterEntryFrame::cast(frame));
+ if (builder.AppendBuiltinExitFrame(BuiltinExitFrame::cast(frame))) {
+ last_frame_id = StackFrame::NO_ID;
+ last_frame_index = 0;
+ }
break;
default:
@@ -641,6 +777,55 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
}
}
+ // If --async-stack-traces is enabled, and we ended on a regular JavaScript
+ // frame above, we can enrich the stack trace with async frames (if this
+ // last frame corresponds to an async function).
+ if (FLAG_async_stack_traces && last_frame_id != StackFrame::NO_ID) {
+ StackFrameIterator it(this);
+ while (it.frame()->id() != last_frame_id) it.Advance();
+ FrameInspector inspector(StandardFrame::cast(it.frame()), last_frame_index,
+ this);
+ FunctionKind const kind = inspector.GetFunction()->shared()->kind();
+ if (IsAsyncGeneratorFunction(kind)) {
+ Handle<Object> const dot_generator_object =
+ inspector.GetExpression(DeclarationScope::kGeneratorObjectVarIndex);
+ if (dot_generator_object->IsUndefined(this)) {
+ // The .generator_object was not yet initialized (i.e. we see a
+ // really early exception in the setup of the async generator).
+ } else {
+ // Check if there's a pending async request on the generator object.
+ Handle<JSAsyncGeneratorObject> async_generator_object =
+ Handle<JSAsyncGeneratorObject>::cast(dot_generator_object);
+ if (!async_generator_object->queue()->IsUndefined(this)) {
+ // Take the promise from the first async generatot request.
+ Handle<AsyncGeneratorRequest> request(
+ AsyncGeneratorRequest::cast(async_generator_object->queue()),
+ this);
+
+ // We can start collecting an async stack trace from the
+ // promise on the {request}.
+ Handle<JSPromise> promise(JSPromise::cast(request->promise()), this);
+ CaptureAsyncStackTrace(this, promise, &builder);
+ }
+ }
+ } else {
+ DCHECK(IsAsyncFunction(kind));
+ Handle<Object> const dot_promise =
+ inspector.GetExpression(DeclarationScope::kPromiseVarIndex);
+ if (dot_promise->IsJSPromise()) {
+ // We can start collecting an async stack trace from .promise here.
+ CaptureAsyncStackTrace(this, Handle<JSPromise>::cast(dot_promise),
+ &builder);
+ } else {
+ // If .promise was not yet initialized (i.e. we see a really
+ // early exception in the setup of the function), it holds
+ // the value undefined. Sanity check here to make sure that
+ // we're not peaking into the completely wrong stack slot.
+ CHECK(dot_promise->IsUndefined(this));
+ }
+ }
+ }
+
// TODO(yangguo): Queue this structured stack trace for preprocessing on GC.
return factory()->NewJSArrayWithElements(builder.GetElements());
}
@@ -1124,19 +1309,6 @@ void ReportBootstrappingException(Handle<Object> exception,
#endif
}
-bool Isolate::is_catchable_by_wasm(Object* exception) {
- // TODO(titzer): thread WASM features here, or just remove this check?
- if (!FLAG_experimental_wasm_eh) return false;
- if (!is_catchable_by_javascript(exception) || !exception->IsJSError())
- return false;
- HandleScope scope(this);
- Handle<Object> exception_handle(exception, this);
- return JSReceiver::HasProperty(Handle<JSReceiver>::cast(exception_handle),
- factory()->InternalizeUtf8String(
- wasm::WasmException::kRuntimeIdStr))
- .IsJust();
-}
-
Object* Isolate::Throw(Object* raw_exception, MessageLocation* location) {
DCHECK(!has_pending_exception());
@@ -1310,11 +1482,10 @@ Object* Isolate::UnwindAndFindHandler() {
trap_handler::ClearThreadInWasm();
}
- if (!is_catchable_by_wasm(exception)) {
- break;
- }
- int stack_slots = 0; // Will contain stack slot count of frame.
+ // For WebAssembly frames we perform a lookup in the handler table.
+ if (!catchable_by_js) break;
WasmCompiledFrame* wasm_frame = static_cast<WasmCompiledFrame*>(frame);
+ int stack_slots = 0; // Will contain stack slot count of frame.
int offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots);
if (offset < 0) break;
// Compute the stack pointer from the frame pointer. This ensures that
@@ -1324,10 +1495,10 @@ Object* Isolate::UnwindAndFindHandler() {
stack_slots * kPointerSize;
// This is going to be handled by Wasm, so we need to set the TLS flag
- // again.
+ // again. It was cleared above assuming the frame would be unwound.
trap_handler::SetThreadInWasm();
- set_wasm_caught_exception(exception);
+ // Gather information from the frame.
wasm::WasmCode* wasm_code =
wasm_engine()->code_manager()->LookupCode(frame->pc());
return FoundHandler(nullptr, wasm_code->instruction_start(), offset,
@@ -2229,9 +2400,16 @@ Handle<Context> Isolate::GetIncumbentContext() {
// 1st candidate: most-recently-entered author function's context
// if it's newer than the last Context::BackupIncumbentScope entry.
- if (!it.done() &&
- static_cast<const void*>(it.frame()) >
- static_cast<const void*>(top_backup_incumbent_scope())) {
+ //
+ // NOTE: This code assumes that the stack grows downward.
+ // This code doesn't work with ASAN because ASAN seems allocating stack
+ // separated for native C++ code and compiled JS code, and the following
+ // comparison doesn't make sense in ASAN.
+ // TODO(yukishiino): Make the implementation of BackupIncumbentScope more
+ // robust.
+ if (!it.done() && (!top_backup_incumbent_scope() ||
+ it.frame()->sp() < reinterpret_cast<Address>(
+ top_backup_incumbent_scope()))) {
Context* context = Context::cast(it.frame()->context());
return Handle<Context>(context->native_context(), this);
}
@@ -2274,10 +2452,6 @@ char* Isolate::RestoreThread(char* from) {
return from + sizeof(ThreadLocalTop);
}
-Isolate::ThreadDataTable::ThreadDataTable() : table_() {}
-
-Isolate::ThreadDataTable::~ThreadDataTable() {}
-
void Isolate::ReleaseSharedPtrs() {
while (managed_ptr_destructors_head_) {
ManagedPtrDestructor* l = managed_ptr_destructors_head_;
@@ -2313,6 +2487,14 @@ void Isolate::UnregisterManagedPtrDestructor(ManagedPtrDestructor* destructor) {
destructor->next_ = nullptr;
}
+void Isolate::SetWasmEngine(std::shared_ptr<wasm::WasmEngine> engine) {
+ DCHECK_NULL(wasm_engine_); // Only call once before {Init}.
+ wasm_engine_ = std::move(engine);
+ wasm_engine_->AddIsolate(this);
+ wasm::WasmCodeManager::InstallSamplingGCCallback(this);
+}
+
+// NOLINTNEXTLINE
Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
#if defined(USE_SIMULATOR)
delete simulator_;
@@ -2483,9 +2665,11 @@ Isolate::Isolate()
host_initialize_import_meta_object_callback_(nullptr),
load_start_time_ms_(0),
#ifdef V8_INTL_SUPPORT
+#if USE_CHROMIUM_ICU == 0 && U_ICU_VERSION_MAJOR_NUM < 63
language_singleton_regexp_matcher_(nullptr),
language_tag_regexp_matcher_(nullptr),
language_variant_regexp_matcher_(nullptr),
+#endif // USE_CHROMIUM_ICU == 0 && U_ICU_VERSION_MAJOR_NUM < 63
default_locale_(""),
#endif // V8_INTL_SUPPORT
serializer_enabled_(false),
@@ -2543,9 +2727,7 @@ Isolate::Isolate()
InitializeLoggingAndCounters();
debug_ = new Debug(this);
- tracing_cpu_profiler_.reset(new TracingCpuProfilerImpl(this));
-
- init_memcopy_functions(this);
+ init_memcopy_functions();
if (FLAG_embedded_builtins) {
#ifdef V8_MULTI_SNAPSHOTS
@@ -2602,20 +2784,27 @@ void Isolate::ClearSerializerData() {
external_reference_map_ = nullptr;
}
+bool Isolate::LogObjectRelocation() {
+ return FLAG_verify_predictable || logger()->is_logging() || is_profiling() ||
+ heap()->isolate()->logger()->is_listening_to_code_events() ||
+ (heap_profiler() != nullptr &&
+ heap_profiler()->is_tracking_object_moves()) ||
+ heap()->has_heap_object_allocation_tracker();
+}
void Isolate::Deinit() {
TRACE_ISOLATE(deinit);
debug()->Unload();
+ wasm_engine()->DeleteCompileJobsOnIsolate(this);
+
if (concurrent_recompilation_enabled()) {
optimizing_compile_dispatcher_->Stop();
delete optimizing_compile_dispatcher_;
optimizing_compile_dispatcher_ = nullptr;
}
- wasm_engine()->DeleteCompileJobsOnIsolate(this);
-
heap_.mark_compact_collector()->EnsureSweepingCompleted();
heap_.memory_allocator()->unmapper()->EnsureUnmappingCompleted();
@@ -2661,7 +2850,10 @@ void Isolate::Deinit() {
heap_.TearDown();
logger_->TearDown();
- wasm_engine_.reset();
+ if (wasm_engine_) {
+ wasm_engine_->RemoveIsolate(this);
+ wasm_engine_.reset();
+ }
if (FLAG_embedded_builtins) {
if (DefaultEmbeddedBlob() == nullptr && embedded_blob() != nullptr) {
@@ -2683,6 +2875,10 @@ void Isolate::Deinit() {
delete root_index_map_;
root_index_map_ = nullptr;
+ delete compiler_zone_;
+ compiler_zone_ = nullptr;
+ compiler_cache_ = nullptr;
+
ClearSerializerData();
}
@@ -2710,6 +2906,7 @@ Isolate::~Isolate() {
date_cache_ = nullptr;
#ifdef V8_INTL_SUPPORT
+#if USE_CHROMIUM_ICU == 0 && U_ICU_VERSION_MAJOR_NUM < 63
delete language_singleton_regexp_matcher_;
language_singleton_regexp_matcher_ = nullptr;
@@ -2718,6 +2915,7 @@ Isolate::~Isolate() {
delete language_variant_regexp_matcher_;
language_variant_regexp_matcher_ = nullptr;
+#endif // USE_CHROMIUM_ICU == 0 && U_ICU_VERSION_MAJOR_NUM < 63
#endif // V8_INTL_SUPPORT
delete regexp_stack_;
@@ -2958,6 +3156,7 @@ bool Isolate::Init(StartupDeserializer* des) {
date_cache_ = new DateCache();
heap_profiler_ = new HeapProfiler(heap());
interpreter_ = new interpreter::Interpreter(this);
+
compiler_dispatcher_ =
new CompilerDispatcher(this, V8::GetCurrentPlatform(), FLAG_stack_size);
@@ -2978,9 +3177,9 @@ bool Isolate::Init(StartupDeserializer* des) {
// Setup the wasm engine.
if (wasm_engine_ == nullptr) {
- wasm_engine_ = wasm::WasmEngine::GetWasmEngine();
- wasm::WasmCodeManager::InstallSamplingGCCallback(this);
+ SetWasmEngine(wasm::WasmEngine::GetWasmEngine());
}
+ DCHECK_NOT_NULL(wasm_engine_);
deoptimizer_data_ = new DeoptimizerData(heap());
@@ -3001,6 +3200,10 @@ bool Isolate::Init(StartupDeserializer* des) {
InitializeThreadLocal();
+ // Profiler has to be created after ThreadLocal is initialized
+ // because it makes use of interrupts.
+ tracing_cpu_profiler_.reset(new TracingCpuProfilerImpl(this));
+
bootstrapper_->Initialize(create_heap_objects);
if (FLAG_embedded_builtins) {
@@ -3042,8 +3245,7 @@ bool Isolate::Init(StartupDeserializer* des) {
if (!create_heap_objects) des->DeserializeInto(this);
load_stub_cache_->Initialize();
store_stub_cache_->Initialize();
- setup_delegate_->SetupInterpreter(interpreter_);
-
+ interpreter_->InitializeDispatchTable();
heap_.NotifyDeserializationComplete();
}
delete setup_delegate_;
@@ -3069,7 +3271,7 @@ bool Isolate::Init(StartupDeserializer* des) {
if (FLAG_trace_turbo) {
// Create an empty file.
- std::ofstream(GetTurboCfgFileName().c_str(), std::ios_base::trunc);
+ std::ofstream(GetTurboCfgFileName(this).c_str(), std::ios_base::trunc);
}
CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)),
@@ -3227,6 +3429,8 @@ void Isolate::DumpAndResetStats() {
}
if (V8_UNLIKELY(FLAG_runtime_stats ==
v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) {
+ counters()->worker_thread_runtime_call_stats()->AddToMainTable(
+ counters()->runtime_call_stats());
counters()->runtime_call_stats()->Print();
counters()->runtime_call_stats()->Reset();
}
@@ -3257,8 +3461,7 @@ bool Isolate::use_optimizer() {
}
bool Isolate::NeedsDetailedOptimizedCodeLineInfo() const {
- return NeedsSourcePositionsForProfiling() ||
- detailed_source_positions_for_profiling();
+ return NeedsSourcePositionsForProfiling() || FLAG_detailed_line_info;
}
bool Isolate::NeedsSourcePositionsForProfiling() const {
@@ -3552,6 +3755,15 @@ void Isolate::InvalidateArrayIteratorProtector() {
DCHECK(!IsArrayIteratorLookupChainIntact());
}
+void Isolate::InvalidateStringIteratorProtector() {
+ DCHECK(factory()->string_iterator_protector()->value()->IsSmi());
+ DCHECK(IsStringIteratorLookupChainIntact());
+ PropertyCell::SetValueWithInvalidation(
+ this, factory()->string_iterator_protector(),
+ handle(Smi::FromInt(kProtectorInvalid), this));
+ DCHECK(!IsStringIteratorLookupChainIntact());
+}
+
void Isolate::InvalidateArrayBufferNeuteringProtector() {
DCHECK(factory()->array_buffer_neutering_protector()->value()->IsSmi());
DCHECK(IsArrayBufferNeuteringIntact());
@@ -3643,7 +3855,7 @@ ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
#undef ISOLATE_FIELD_OFFSET
#endif
-Handle<Symbol> Isolate::SymbolFor(Heap::RootListIndex dictionary_index,
+Handle<Symbol> Isolate::SymbolFor(RootIndex dictionary_index,
Handle<String> name, bool private_symbol) {
Handle<String> key = factory()->InternalizeString(name);
Handle<NameDictionary> dictionary =
@@ -3657,14 +3869,14 @@ Handle<Symbol> Isolate::SymbolFor(Heap::RootListIndex dictionary_index,
dictionary = NameDictionary::Add(this, dictionary, key, symbol,
PropertyDetails::Empty(), &entry);
switch (dictionary_index) {
- case Heap::kPublicSymbolTableRootIndex:
+ case RootIndex::kPublicSymbolTable:
symbol->set_is_public(true);
heap()->set_public_symbol_table(*dictionary);
break;
- case Heap::kApiSymbolTableRootIndex:
+ case RootIndex::kApiSymbolTable:
heap()->set_api_symbol_table(*dictionary);
break;
- case Heap::kApiPrivateSymbolTableRootIndex:
+ case RootIndex::kApiPrivateSymbolTable:
heap()->set_api_private_symbol_table(*dictionary);
break;
default:
@@ -3725,7 +3937,7 @@ void Isolate::FireCallCompletedCallback() {
if (!handle_scope_implementer()->CallDepthIsZero()) return;
bool run_microtasks =
- pending_microtask_count() &&
+ heap()->default_microtask_queue()->pending_microtask_count() &&
!handle_scope_implementer()->HasMicrotasksSuppressions() &&
handle_scope_implementer()->microtasks_policy() ==
v8::MicrotasksPolicy::kAuto;
@@ -3829,6 +4041,29 @@ void Isolate::SetHostInitializeImportMetaObjectCallback(
host_initialize_import_meta_object_callback_ = callback;
}
+MaybeHandle<Object> Isolate::RunPrepareStackTraceCallback(
+ Handle<Context> context, Handle<JSObject> error) {
+ v8::Local<v8::Context> api_context = Utils::ToLocal(context);
+
+ v8::Local<StackTrace> trace =
+ Utils::StackTraceToLocal(GetDetailedStackTrace(error));
+
+ v8::Local<v8::Value> stack;
+ ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
+ this, stack,
+ prepare_stack_trace_callback_(api_context, Utils::ToLocal(error), trace),
+ MaybeHandle<Object>());
+ return Utils::OpenHandle(*stack);
+}
+
+void Isolate::SetPrepareStackTraceCallback(PrepareStackTraceCallback callback) {
+ prepare_stack_trace_callback_ = callback;
+}
+
+bool Isolate::HasPrepareStackTraceCallback() const {
+ return prepare_stack_trace_callback_ != nullptr;
+}
+
void Isolate::SetAtomicsWaitCallback(v8::Isolate::AtomicsWaitCallback callback,
void* data) {
atomics_wait_callback_ = callback;
@@ -3945,18 +4180,9 @@ void Isolate::ReportPromiseReject(Handle<JSPromise> promise,
}
void Isolate::EnqueueMicrotask(Handle<Microtask> microtask) {
- Handle<FixedArray> queue(heap()->microtask_queue(), this);
- int num_tasks = pending_microtask_count();
- DCHECK_LE(num_tasks, queue->length());
- if (num_tasks == queue->length()) {
- queue = factory()->CopyFixedArrayAndGrow(queue, std::max(num_tasks, 8));
- heap()->set_microtask_queue(*queue);
- }
- DCHECK_LE(8, queue->length());
- DCHECK_LT(num_tasks, queue->length());
- DCHECK(queue->get(num_tasks)->IsUndefined(this));
- queue->set(num_tasks, *microtask);
- set_pending_microtask_count(num_tasks + 1);
+ Handle<MicrotaskQueue> microtask_queue(heap()->default_microtask_queue(),
+ this);
+ MicrotaskQueue::EnqueueMicrotask(this, microtask_queue, microtask);
}
@@ -3964,25 +4190,27 @@ void Isolate::RunMicrotasks() {
// Increase call depth to prevent recursive callbacks.
v8::Isolate::SuppressMicrotaskExecutionScope suppress(
reinterpret_cast<v8::Isolate*>(this));
- if (pending_microtask_count()) {
+ HandleScope scope(this);
+ Handle<MicrotaskQueue> microtask_queue(heap()->default_microtask_queue(),
+ this);
+ if (microtask_queue->pending_microtask_count()) {
is_running_microtasks_ = true;
TRACE_EVENT0("v8.execute", "RunMicrotasks");
TRACE_EVENT_CALL_STATS_SCOPED(this, "v8", "V8.RunMicrotasks");
- HandleScope scope(this);
MaybeHandle<Object> maybe_exception;
MaybeHandle<Object> maybe_result = Execution::RunMicrotasks(
this, Execution::MessageHandling::kReport, &maybe_exception);
// If execution is terminating, bail out, clean up, and propagate to
// TryCatch scope.
if (maybe_result.is_null() && maybe_exception.is_null()) {
- heap()->set_microtask_queue(ReadOnlyRoots(heap()).empty_fixed_array());
- set_pending_microtask_count(0);
+ microtask_queue->set_queue(ReadOnlyRoots(heap()).empty_fixed_array());
+ microtask_queue->set_pending_microtask_count(0);
handle_scope_implementer()->LeaveMicrotaskContext();
SetTerminationOnExternalTryCatch();
}
- CHECK_EQ(0, pending_microtask_count());
- CHECK_EQ(0, heap()->microtask_queue()->length());
+ CHECK_EQ(0, microtask_queue->pending_microtask_count());
+ CHECK_EQ(0, microtask_queue->queue()->length());
is_running_microtasks_ = false;
}
FireMicrotasksCompletedCallback();
@@ -4007,10 +4235,17 @@ void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) {
}
}
-std::string Isolate::GetTurboCfgFileName() {
+// static
+std::string Isolate::GetTurboCfgFileName(Isolate* isolate) {
if (FLAG_trace_turbo_cfg_file == nullptr) {
std::ostringstream os;
- os << "turbo-" << base::OS::GetCurrentProcessId() << "-" << id() << ".cfg";
+ os << "turbo-" << base::OS::GetCurrentProcessId() << "-";
+ if (isolate != nullptr) {
+ os << isolate->id();
+ } else {
+ os << "any";
+ }
+ os << ".cfg";
return os.str();
} else {
return FLAG_trace_turbo_cfg_file;
@@ -4037,10 +4272,10 @@ void Isolate::CheckDetachedContextsAfterGC() {
if (length == 0) return;
int new_length = 0;
for (int i = 0; i < length; i += 2) {
- int mark_sweeps = Smi::ToInt(detached_contexts->Get(i)->ToSmi());
+ int mark_sweeps = Smi::ToInt(detached_contexts->Get(i)->cast<Smi>());
MaybeObject* context = detached_contexts->Get(i + 1);
- DCHECK(context->IsWeakHeapObject() || context->IsClearedWeakHeapObject());
- if (!context->IsClearedWeakHeapObject()) {
+ DCHECK(context->IsWeakOrCleared());
+ if (!context->IsCleared()) {
detached_contexts->Set(
new_length, MaybeObject::FromSmi(Smi::FromInt(mark_sweeps + 1)));
detached_contexts->Set(new_length + 1, context);
@@ -4057,9 +4292,9 @@ void Isolate::CheckDetachedContextsAfterGC() {
PrintF("%d detached contexts are collected out of %d\n",
length - new_length, length);
for (int i = 0; i < new_length; i += 2) {
- int mark_sweeps = Smi::ToInt(detached_contexts->Get(i)->ToSmi());
+ int mark_sweeps = Smi::ToInt(detached_contexts->Get(i)->cast<Smi>());
MaybeObject* context = detached_contexts->Get(i + 1);
- DCHECK(context->IsWeakHeapObject() || context->IsClearedWeakHeapObject());
+ DCHECK(context->IsWeakOrCleared());
if (mark_sweeps > 3) {
PrintF("detached context %p\n survived %d GCs (leak?)\n",
static_cast<void*>(context), mark_sweeps);