Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/isolate.h"
6 :
7 : #include <stdlib.h>
8 :
9 : #include <atomic>
10 : #include <fstream> // NOLINT(readability/streams)
11 : #include <memory>
12 : #include <sstream>
13 : #include <unordered_map>
14 :
15 : #include "src/api-inl.h"
16 : #include "src/assembler-inl.h"
17 : #include "src/ast/ast-value-factory.h"
18 : #include "src/ast/scopes.h"
19 : #include "src/base/adapters.h"
20 : #include "src/base/hashmap.h"
21 : #include "src/base/platform/platform.h"
22 : #include "src/base/sys-info.h"
23 : #include "src/base/utils/random-number-generator.h"
24 : #include "src/bootstrapper.h"
25 : #include "src/builtins/builtins-promise.h"
26 : #include "src/builtins/constants-table-builder.h"
27 : #include "src/cancelable-task.h"
28 : #include "src/compilation-cache.h"
29 : #include "src/compilation-statistics.h"
30 : #include "src/compiler-dispatcher/compiler-dispatcher.h"
31 : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
32 : #include "src/date.h"
33 : #include "src/debug/debug-frames.h"
34 : #include "src/debug/debug.h"
35 : #include "src/deoptimizer.h"
36 : #include "src/elements.h"
37 : #include "src/frames-inl.h"
38 : #include "src/hash-seed-inl.h"
39 : #include "src/heap/heap-inl.h"
40 : #include "src/heap/read-only-heap.h"
41 : #include "src/ic/stub-cache.h"
42 : #include "src/interpreter/interpreter.h"
43 : #include "src/isolate-inl.h"
44 : #include "src/libsampler/sampler.h"
45 : #include "src/log.h"
46 : #include "src/messages.h"
47 : #include "src/microtask-queue.h"
48 : #include "src/objects/frame-array-inl.h"
49 : #include "src/objects/hash-table-inl.h"
50 : #include "src/objects/js-array-inl.h"
51 : #include "src/objects/js-generator-inl.h"
52 : #include "src/objects/module-inl.h"
53 : #include "src/objects/promise-inl.h"
54 : #include "src/objects/slots.h"
55 : #include "src/objects/smi.h"
56 : #include "src/objects/stack-frame-info-inl.h"
57 : #include "src/ostreams.h"
58 : #include "src/profiler/heap-profiler.h"
59 : #include "src/profiler/tracing-cpu-profiler.h"
60 : #include "src/prototype.h"
61 : #include "src/ptr-compr.h"
62 : #include "src/regexp/regexp-stack.h"
63 : #include "src/runtime-profiler.h"
64 : #include "src/setup-isolate.h"
65 : #include "src/simulator.h"
66 : #include "src/snapshot/embedded-data.h"
67 : #include "src/snapshot/embedded-file-writer.h"
68 : #include "src/snapshot/read-only-deserializer.h"
69 : #include "src/snapshot/startup-deserializer.h"
70 : #include "src/string-builder-inl.h"
71 : #include "src/string-stream.h"
72 : #include "src/tracing/tracing-category-observer.h"
73 : #include "src/trap-handler/trap-handler.h"
74 : #include "src/unicode-cache.h"
75 : #include "src/v8.h"
76 : #include "src/v8threads.h"
77 : #include "src/version.h"
78 : #include "src/visitors.h"
79 : #include "src/vm-state-inl.h"
80 : #include "src/wasm/wasm-code-manager.h"
81 : #include "src/wasm/wasm-engine.h"
82 : #include "src/wasm/wasm-objects.h"
83 : #include "src/zone/accounting-allocator.h"
84 : #ifdef V8_INTL_SUPPORT
85 : #include "unicode/uobject.h"
86 : #endif // V8_INTL_SUPPORT
87 :
88 : #if defined(V8_OS_WIN_X64)
89 : #include "src/unwinding-info-win64.h"
90 : #endif
91 :
92 : extern "C" const uint8_t* v8_Default_embedded_blob_;
93 : extern "C" uint32_t v8_Default_embedded_blob_size_;
94 :
95 : namespace v8 {
96 : namespace internal {
97 :
98 : #ifdef DEBUG
99 : #define TRACE_ISOLATE(tag) \
100 : do { \
101 : if (FLAG_trace_isolates) { \
102 : PrintF("Isolate %p (id %d)" #tag "\n", reinterpret_cast<void*>(this), \
103 : id()); \
104 : } \
105 : } while (false)
106 : #else
107 : #define TRACE_ISOLATE(tag)
108 : #endif
109 :
110 62421 : const uint8_t* DefaultEmbeddedBlob() { return v8_Default_embedded_blob_; }
111 62421 : uint32_t DefaultEmbeddedBlobSize() { return v8_Default_embedded_blob_size_; }
112 :
113 : #ifdef V8_MULTI_SNAPSHOTS
114 : extern "C" const uint8_t* v8_Trusted_embedded_blob_;
115 : extern "C" uint32_t v8_Trusted_embedded_blob_size_;
116 :
117 : const uint8_t* TrustedEmbeddedBlob() { return v8_Trusted_embedded_blob_; }
118 : uint32_t TrustedEmbeddedBlobSize() { return v8_Trusted_embedded_blob_size_; }
119 : #endif
120 :
121 : namespace {
122 : // These variables provide access to the current embedded blob without requiring
123 : // an isolate instance. This is needed e.g. by Code::InstructionStart, which may
124 : // not have access to an isolate but still needs to access the embedded blob.
125 : // The variables are initialized by each isolate in Init(). Writes and reads are
126 : // relaxed since we can guarantee that the current thread has initialized these
127 : // variables before accessing them. Different threads may race, but this is fine
128 : // since they all attempt to set the same values of the blob pointer and size.
129 :
130 : std::atomic<const uint8_t*> current_embedded_blob_(nullptr);
131 : std::atomic<uint32_t> current_embedded_blob_size_(0);
132 :
133 : // The various workflows around embedded snapshots are fairly complex. We need
134 : // to support plain old snapshot builds, nosnap builds, and the requirements of
135 : // subtly different serialization tests. There's two related knobs to twiddle:
136 : //
137 : // - The default embedded blob may be overridden by setting the sticky embedded
138 : // blob. This is set automatically whenever we create a new embedded blob.
139 : //
140 : // - Lifecycle management can be either manual or set to refcounting.
141 : //
142 : // A few situations to demonstrate their use:
143 : //
144 : // - A plain old snapshot build neither overrides the default blob nor
145 : // refcounts.
146 : //
147 : // - mksnapshot sets the sticky blob and manually frees the embedded
148 : // blob once done.
149 : //
150 : // - Most serializer tests do the same.
151 : //
152 : // - Nosnapshot builds set the sticky blob and enable refcounting.
153 :
154 : // This mutex protects access to the following variables:
155 : // - sticky_embedded_blob_
156 : // - sticky_embedded_blob_size_
157 : // - enable_embedded_blob_refcounting_
158 : // - current_embedded_blob_refs_
159 : base::LazyMutex current_embedded_blob_refcount_mutex_ = LAZY_MUTEX_INITIALIZER;
160 :
161 : const uint8_t* sticky_embedded_blob_ = nullptr;
162 : uint32_t sticky_embedded_blob_size_ = 0;
163 :
164 : bool enable_embedded_blob_refcounting_ = true;
165 : int current_embedded_blob_refs_ = 0;
166 :
167 126350 : const uint8_t* StickyEmbeddedBlob() { return sticky_embedded_blob_; }
168 55 : uint32_t StickyEmbeddedBlobSize() { return sticky_embedded_blob_size_; }
169 :
170 : void SetStickyEmbeddedBlob(const uint8_t* blob, uint32_t blob_size) {
171 56 : sticky_embedded_blob_ = blob;
172 56 : sticky_embedded_blob_size_ = blob_size;
173 : }
174 :
175 : } // namespace
176 :
177 1360 : void DisableEmbeddedBlobRefcounting() {
178 : base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
179 1360 : enable_embedded_blob_refcounting_ = false;
180 1360 : }
181 :
182 1355 : void FreeCurrentEmbeddedBlob() {
183 1355 : CHECK(!enable_embedded_blob_refcounting_);
184 : base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
185 :
186 1355 : if (StickyEmbeddedBlob() == nullptr) return;
187 :
188 56 : CHECK_EQ(StickyEmbeddedBlob(), Isolate::CurrentEmbeddedBlob());
189 :
190 : InstructionStream::FreeOffHeapInstructionStream(
191 : const_cast<uint8_t*>(Isolate::CurrentEmbeddedBlob()),
192 56 : Isolate::CurrentEmbeddedBlobSize());
193 :
194 : current_embedded_blob_.store(nullptr, std::memory_order_relaxed);
195 : current_embedded_blob_size_.store(0, std::memory_order_relaxed);
196 56 : sticky_embedded_blob_ = nullptr;
197 56 : sticky_embedded_blob_size_ = 0;
198 : }
199 :
200 : // static
201 0 : bool Isolate::CurrentEmbeddedBlobIsBinaryEmbedded() {
202 : // In some situations, we must be able to rely on the embedded blob being
203 : // immortal immovable. This is the case if the blob is binary-embedded.
204 : // See blob lifecycle controls above for descriptions of when the current
205 : // embedded blob may change (e.g. in tests or mksnapshot). If the blob is
206 : // binary-embedded, it is immortal immovable.
207 : const uint8_t* blob =
208 : current_embedded_blob_.load(std::memory_order::memory_order_relaxed);
209 0 : if (blob == nullptr) return false;
210 : #ifdef V8_MULTI_SNAPSHOTS
211 : if (blob == TrustedEmbeddedBlob()) return true;
212 : #endif
213 0 : return blob == DefaultEmbeddedBlob();
214 : }
215 :
216 62474 : void Isolate::SetEmbeddedBlob(const uint8_t* blob, uint32_t blob_size) {
217 62474 : CHECK_NOT_NULL(blob);
218 :
219 62474 : embedded_blob_ = blob;
220 62474 : embedded_blob_size_ = blob_size;
221 : current_embedded_blob_.store(blob, std::memory_order_relaxed);
222 : current_embedded_blob_size_.store(blob_size, std::memory_order_relaxed);
223 :
224 : #ifdef DEBUG
225 : // Verify that the contents of the embedded blob are unchanged from
226 : // serialization-time, just to ensure the compiler isn't messing with us.
227 : EmbeddedData d = EmbeddedData::FromBlob();
228 : if (d.EmbeddedBlobHash() != d.CreateEmbeddedBlobHash()) {
229 : FATAL(
230 : "Embedded blob checksum verification failed. This indicates that the "
231 : "embedded blob has been modified since compilation time. A common "
232 : "cause is a debugging breakpoint set within builtin code.");
233 : }
234 : #endif // DEBUG
235 62474 : }
236 :
237 0 : void Isolate::ClearEmbeddedBlob() {
238 0 : CHECK(enable_embedded_blob_refcounting_);
239 0 : CHECK_EQ(embedded_blob_, CurrentEmbeddedBlob());
240 0 : CHECK_EQ(embedded_blob_, StickyEmbeddedBlob());
241 :
242 0 : embedded_blob_ = nullptr;
243 0 : embedded_blob_size_ = 0;
244 : current_embedded_blob_.store(nullptr, std::memory_order_relaxed);
245 : current_embedded_blob_size_.store(0, std::memory_order_relaxed);
246 0 : sticky_embedded_blob_ = nullptr;
247 0 : sticky_embedded_blob_size_ = 0;
248 0 : }
249 :
250 205201472 : const uint8_t* Isolate::embedded_blob() const { return embedded_blob_; }
251 97483392 : uint32_t Isolate::embedded_blob_size() const { return embedded_blob_size_; }
252 :
253 : // static
254 416206529 : const uint8_t* Isolate::CurrentEmbeddedBlob() {
255 416206529 : return current_embedded_blob_.load(std::memory_order::memory_order_relaxed);
256 : }
257 :
258 : // static
259 260415043 : uint32_t Isolate::CurrentEmbeddedBlobSize() {
260 : return current_embedded_blob_size_.load(
261 260415043 : std::memory_order::memory_order_relaxed);
262 : }
263 :
264 56 : size_t Isolate::HashIsolateForEmbeddedBlob() {
265 : DCHECK(builtins_.is_initialized());
266 : DCHECK(FLAG_embedded_builtins);
267 : DCHECK(Builtins::AllBuiltinsAreIsolateIndependent());
268 :
269 : DisallowHeapAllocation no_gc;
270 :
271 : static constexpr size_t kSeed = 0;
272 : size_t hash = kSeed;
273 :
274 : // Hash data sections of builtin code objects.
275 170408 : for (int i = 0; i < Builtins::builtin_count; i++) {
276 85176 : Code code = heap_.builtin(i);
277 :
278 : DCHECK(Internals::HasHeapObjectTag(code.ptr()));
279 : uint8_t* const code_ptr =
280 85176 : reinterpret_cast<uint8_t*>(code.ptr() - kHeapObjectTag);
281 :
282 : // These static asserts ensure we don't miss relevant fields. We don't hash
283 : // instruction size and flags since they change when creating the off-heap
284 : // trampolines. Other data fields must remain the same.
285 : STATIC_ASSERT(Code::kInstructionSizeOffset == Code::kDataStart);
286 : STATIC_ASSERT(Code::kFlagsOffset == Code::kInstructionSizeOffsetEnd + 1);
287 : STATIC_ASSERT(Code::kSafepointTableOffsetOffset ==
288 : Code::kFlagsOffsetEnd + 1);
289 : static constexpr int kStartOffset = Code::kSafepointTableOffsetOffset;
290 :
291 2810808 : for (int j = kStartOffset; j < Code::kUnalignedHeaderSize; j++) {
292 1362816 : hash = base::hash_combine(hash, size_t{code_ptr[j]});
293 : }
294 : }
295 :
296 : // The builtins constants table is also tightly tied to embedded builtins.
297 56 : hash = base::hash_combine(
298 112 : hash, static_cast<size_t>(heap_.builtins_constants_table()->length()));
299 :
300 56 : return hash;
301 : }
302 :
303 :
304 : base::Thread::LocalStorageKey Isolate::isolate_key_;
305 : base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
306 : #if DEBUG
307 : std::atomic<bool> Isolate::isolate_key_created_{false};
308 : #endif
309 :
310 : namespace {
311 : // A global counter for all generated Isolates, might overflow.
312 : std::atomic<int> isolate_counter{0};
313 : } // namespace
314 :
315 : Isolate::PerIsolateThreadData*
316 328326 : Isolate::FindOrAllocatePerThreadDataForThisThread() {
317 : ThreadId thread_id = ThreadId::Current();
318 : PerIsolateThreadData* per_thread = nullptr;
319 : {
320 328322 : base::MutexGuard lock_guard(&thread_data_table_mutex_);
321 : per_thread = thread_data_table_.Lookup(thread_id);
322 328340 : if (per_thread == nullptr) {
323 67957 : per_thread = new PerIsolateThreadData(this, thread_id);
324 67957 : thread_data_table_.Insert(per_thread);
325 : }
326 : DCHECK(thread_data_table_.Lookup(thread_id) == per_thread);
327 : }
328 328347 : return per_thread;
329 : }
330 :
331 :
332 1499 : void Isolate::DiscardPerThreadDataForThisThread() {
333 1499 : ThreadId thread_id = ThreadId::TryGetCurrent();
334 1499 : if (thread_id.IsValid()) {
335 : DCHECK_NE(thread_manager_->mutex_owner_.load(std::memory_order_relaxed),
336 : thread_id);
337 1000 : base::MutexGuard lock_guard(&thread_data_table_mutex_);
338 : PerIsolateThreadData* per_thread = thread_data_table_.Lookup(thread_id);
339 1000 : if (per_thread) {
340 : DCHECK(!per_thread->thread_state_);
341 : thread_data_table_.Remove(per_thread);
342 : }
343 : }
344 1499 : }
345 :
346 :
347 40303 : Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
348 40303 : ThreadId thread_id = ThreadId::Current();
349 40303 : return FindPerThreadDataForThread(thread_id);
350 : }
351 :
352 :
353 40303 : Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread(
354 : ThreadId thread_id) {
355 : PerIsolateThreadData* per_thread = nullptr;
356 : {
357 40303 : base::MutexGuard lock_guard(&thread_data_table_mutex_);
358 : per_thread = thread_data_table_.Lookup(thread_id);
359 : }
360 40303 : return per_thread;
361 : }
362 :
363 :
364 60988 : void Isolate::InitializeOncePerProcess() {
365 60988 : isolate_key_ = base::Thread::CreateThreadLocalKey();
366 : #if DEBUG
367 : bool expected = false;
368 : DCHECK_EQ(true, isolate_key_created_.compare_exchange_strong(
369 : expected, true, std::memory_order_relaxed));
370 : #endif
371 60988 : per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey();
372 60988 : }
373 :
374 801219 : Address Isolate::get_address_from_id(IsolateAddressId id) {
375 801219 : return isolate_addresses_[id];
376 : }
377 :
378 6283 : char* Isolate::Iterate(RootVisitor* v, char* thread_storage) {
379 : ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
380 6283 : Iterate(v, thread);
381 6283 : return thread_storage + sizeof(ThreadLocalTop);
382 : }
383 :
384 :
385 439 : void Isolate::IterateThread(ThreadVisitor* v, char* t) {
386 : ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
387 439 : v->VisitThread(this, thread);
388 439 : }
389 :
390 284198 : void Isolate::Iterate(RootVisitor* v, ThreadLocalTop* thread) {
391 : // Visit the roots from the top for a given thread.
392 284197 : v->VisitRootPointer(Root::kTop, nullptr,
393 568396 : FullObjectSlot(&thread->pending_exception_));
394 284198 : v->VisitRootPointer(Root::kTop, nullptr,
395 568394 : FullObjectSlot(&thread->pending_message_obj_));
396 568396 : v->VisitRootPointer(Root::kTop, nullptr, FullObjectSlot(&thread->context_));
397 284198 : v->VisitRootPointer(Root::kTop, nullptr,
398 568396 : FullObjectSlot(&thread->scheduled_exception_));
399 :
400 452468 : for (v8::TryCatch* block = thread->try_catch_handler_; block != nullptr;
401 : block = block->next_) {
402 : // TODO(3770): Make TryCatch::exception_ an Address (and message_obj_ too).
403 336540 : v->VisitRootPointer(
404 : Root::kTop, nullptr,
405 336540 : FullObjectSlot(reinterpret_cast<Address>(&(block->exception_))));
406 336540 : v->VisitRootPointer(
407 : Root::kTop, nullptr,
408 336540 : FullObjectSlot(reinterpret_cast<Address>(&(block->message_obj_))));
409 : }
410 :
411 : // Iterate over pointers on native execution stack.
412 568395 : wasm::WasmCodeRefScope wasm_code_ref_scope;
413 5043573 : for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
414 4759375 : it.frame()->Iterate(v);
415 : }
416 284198 : }
417 :
418 277915 : void Isolate::Iterate(RootVisitor* v) {
419 : ThreadLocalTop* current_t = thread_local_top();
420 277915 : Iterate(v, current_t);
421 277915 : }
422 :
423 277915 : void Isolate::IterateDeferredHandles(RootVisitor* visitor) {
424 281733 : for (DeferredHandles* deferred = deferred_handles_head_; deferred != nullptr;
425 : deferred = deferred->next_) {
426 3818 : deferred->Iterate(visitor);
427 : }
428 277915 : }
429 :
430 :
431 : #ifdef DEBUG
432 : bool Isolate::IsDeferredHandle(Address* handle) {
433 : // Comparing unrelated pointers (not from the same array) is undefined
434 : // behavior, so cast to Address before making arbitrary comparisons.
435 : Address handle_as_address = reinterpret_cast<Address>(handle);
436 : // Each DeferredHandles instance keeps the handles to one job in the
437 : // concurrent recompilation queue, containing a list of blocks. Each block
438 : // contains kHandleBlockSize handles except for the first block, which may
439 : // not be fully filled.
440 : // We iterate through all the blocks to see whether the argument handle
441 : // belongs to one of the blocks. If so, it is deferred.
442 : for (DeferredHandles* deferred = deferred_handles_head_; deferred != nullptr;
443 : deferred = deferred->next_) {
444 : std::vector<Address*>* blocks = &deferred->blocks_;
445 : for (size_t i = 0; i < blocks->size(); i++) {
446 : Address* block_limit = (i == 0) ? deferred->first_block_limit_
447 : : blocks->at(i) + kHandleBlockSize;
448 : if (reinterpret_cast<Address>(blocks->at(i)) <= handle_as_address &&
449 : handle_as_address < reinterpret_cast<Address>(block_limit)) {
450 : return true;
451 : }
452 : }
453 : }
454 : return false;
455 : }
456 : #endif // DEBUG
457 :
458 :
459 21000512 : void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
460 21000512 : thread_local_top()->try_catch_handler_ = that;
461 21000512 : }
462 :
463 :
464 21000520 : void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
465 : DCHECK(thread_local_top()->try_catch_handler_ == that);
466 21000520 : thread_local_top()->try_catch_handler_ = that->next_;
467 21000520 : }
468 :
469 :
470 0 : Handle<String> Isolate::StackTraceString() {
471 0 : if (stack_trace_nesting_level_ == 0) {
472 0 : stack_trace_nesting_level_++;
473 : HeapStringAllocator allocator;
474 0 : StringStream::ClearMentionedObjectCache(this);
475 : StringStream accumulator(&allocator);
476 0 : incomplete_message_ = &accumulator;
477 0 : PrintStack(&accumulator);
478 0 : Handle<String> stack_trace = accumulator.ToString(this);
479 0 : incomplete_message_ = nullptr;
480 0 : stack_trace_nesting_level_ = 0;
481 0 : return stack_trace;
482 0 : } else if (stack_trace_nesting_level_ == 1) {
483 0 : stack_trace_nesting_level_++;
484 : base::OS::PrintError(
485 0 : "\n\nAttempt to print stack while printing stack (double fault)\n");
486 : base::OS::PrintError(
487 0 : "If you are lucky you may find a partial stack dump on stdout.\n\n");
488 0 : incomplete_message_->OutputToStdOut();
489 : return factory()->empty_string();
490 : } else {
491 0 : base::OS::Abort();
492 : // Unreachable
493 : return factory()->empty_string();
494 : }
495 : }
496 :
497 0 : void Isolate::PushStackTraceAndDie(void* ptr1, void* ptr2, void* ptr3,
498 : void* ptr4) {
499 0 : StackTraceFailureMessage message(this, ptr1, ptr2, ptr3, ptr4);
500 0 : message.Print();
501 0 : base::OS::Abort();
502 : }
503 :
504 0 : void StackTraceFailureMessage::Print() volatile {
505 : // Print the details of this failure message object, including its own address
506 : // to force stack allocation.
507 0 : base::OS::PrintError(
508 : "Stacktrace:\n ptr1=%p\n ptr2=%p\n ptr3=%p\n ptr4=%p\n "
509 : "failure_message_object=%p\n%s",
510 0 : ptr1_, ptr2_, ptr3_, ptr4_, this, &js_stack_trace_[0]);
511 0 : }
512 :
513 0 : StackTraceFailureMessage::StackTraceFailureMessage(Isolate* isolate, void* ptr1,
514 : void* ptr2, void* ptr3,
515 0 : void* ptr4) {
516 0 : isolate_ = isolate;
517 0 : ptr1_ = ptr1;
518 0 : ptr2_ = ptr2;
519 0 : ptr3_ = ptr3;
520 0 : ptr4_ = ptr4;
521 : // Write a stracktrace into the {js_stack_trace_} buffer.
522 : const size_t buffer_length = arraysize(js_stack_trace_);
523 0 : memset(&js_stack_trace_, 0, buffer_length);
524 : FixedStringAllocator fixed(&js_stack_trace_[0], buffer_length - 1);
525 : StringStream accumulator(&fixed, StringStream::kPrintObjectConcise);
526 0 : isolate->PrintStack(&accumulator, Isolate::kPrintStackVerbose);
527 : // Keeping a reference to the last code objects to increase likelyhood that
528 : // they get included in the minidump.
529 : const size_t code_objects_length = arraysize(code_objects_);
530 : size_t i = 0;
531 0 : StackFrameIterator it(isolate);
532 0 : for (; !it.done() && i < code_objects_length; it.Advance()) {
533 0 : code_objects_[i++] =
534 0 : reinterpret_cast<void*>(it.frame()->unchecked_code().ptr());
535 : }
536 0 : }
537 :
538 : namespace {
539 :
540 : class StackFrameCacheHelper : public AllStatic {
541 : public:
542 61834 : static MaybeHandle<StackTraceFrame> LookupCachedFrame(
543 : Isolate* isolate, Handle<AbstractCode> code, int code_offset) {
544 61834 : if (FLAG_optimize_for_size) return MaybeHandle<StackTraceFrame>();
545 :
546 123668 : const auto maybe_cache = handle(code->stack_frame_cache(), isolate);
547 61834 : if (!maybe_cache->IsSimpleNumberDictionary())
548 8194 : return MaybeHandle<StackTraceFrame>();
549 :
550 : const auto cache = Handle<SimpleNumberDictionary>::cast(maybe_cache);
551 107280 : const int entry = cache->FindEntry(isolate, code_offset);
552 53640 : if (entry != NumberDictionary::kNotFound) {
553 51262 : return handle(StackTraceFrame::cast(cache->ValueAt(entry)), isolate);
554 : }
555 2378 : return MaybeHandle<StackTraceFrame>();
556 : }
557 :
558 10572 : static void CacheFrameAndUpdateCache(Isolate* isolate,
559 : Handle<AbstractCode> code,
560 : int code_offset,
561 : Handle<StackTraceFrame> frame) {
562 10572 : if (FLAG_optimize_for_size) return;
563 :
564 21144 : const auto maybe_cache = handle(code->stack_frame_cache(), isolate);
565 : const auto cache = maybe_cache->IsSimpleNumberDictionary()
566 : ? Handle<SimpleNumberDictionary>::cast(maybe_cache)
567 10572 : : SimpleNumberDictionary::New(isolate, 1);
568 : Handle<SimpleNumberDictionary> new_cache =
569 10572 : SimpleNumberDictionary::Set(isolate, cache, code_offset, frame);
570 20795 : if (*new_cache != *cache || !maybe_cache->IsSimpleNumberDictionary()) {
571 8543 : AbstractCode::SetStackFrameCache(code, new_cache);
572 : }
573 : }
574 : };
575 :
576 : } // anonymous namespace
577 :
578 : class FrameArrayBuilder {
579 : public:
580 : enum FrameFilterMode { ALL, CURRENT_SECURITY_CONTEXT };
581 :
582 1315632 : FrameArrayBuilder(Isolate* isolate, FrameSkipMode mode, int limit,
583 : Handle<Object> caller, FrameFilterMode filter_mode)
584 : : isolate_(isolate),
585 : mode_(mode),
586 : limit_(limit),
587 : caller_(caller),
588 1315632 : check_security_context_(filter_mode == CURRENT_SECURITY_CONTEXT) {
589 1315632 : switch (mode_) {
590 : case SKIP_FIRST:
591 : skip_next_frame_ = true;
592 : break;
593 : case SKIP_UNTIL_SEEN:
594 : DCHECK(caller_->IsJSFunction());
595 : skip_next_frame_ = true;
596 : break;
597 : case SKIP_NONE:
598 1292659 : skip_next_frame_ = false;
599 1292659 : break;
600 : }
601 :
602 1315632 : elements_ = isolate->factory()->NewFrameArray(Min(limit, 10));
603 1315632 : }
604 :
605 1355 : void AppendAsyncFrame(Handle<JSGeneratorObject> generator_object) {
606 1355 : if (full()) return;
607 1355 : Handle<JSFunction> function(generator_object->function(), isolate_);
608 1355 : if (!IsVisibleInStackTrace(function)) return;
609 : int flags = FrameArray::kIsAsync;
610 1355 : if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
611 :
612 1355 : Handle<Object> receiver(generator_object->receiver(), isolate_);
613 : Handle<AbstractCode> code(
614 4065 : AbstractCode::cast(function->shared()->GetBytecodeArray()), isolate_);
615 : int offset = Smi::ToInt(generator_object->input_or_debug_pos());
616 : // The stored bytecode offset is relative to a different base than what
617 : // is used in the source position table, hence the subtraction.
618 1355 : offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
619 :
620 1355 : Handle<FixedArray> parameters = isolate_->factory()->empty_fixed_array();
621 1355 : if (V8_UNLIKELY(FLAG_detailed_error_stack_trace)) {
622 0 : int param_count = function->shared()->internal_formal_parameter_count();
623 0 : parameters = isolate_->factory()->NewFixedArray(param_count);
624 0 : for (int i = 0; i < param_count; i++) {
625 0 : parameters->set(i,
626 0 : generator_object->parameters_and_registers()->get(i));
627 : }
628 : }
629 :
630 : elements_ = FrameArray::AppendJSFrame(elements_, receiver, function, code,
631 1355 : offset, flags, parameters);
632 : }
633 :
634 108 : void AppendPromiseAllFrame(Handle<Context> context, int offset) {
635 108 : if (full()) return;
636 : int flags = FrameArray::kIsAsync | FrameArray::kIsPromiseAll;
637 :
638 108 : Handle<Context> native_context(context->native_context(), isolate_);
639 324 : Handle<JSFunction> function(native_context->promise_all(), isolate_);
640 108 : if (!IsVisibleInStackTrace(function)) return;
641 :
642 324 : Handle<Object> receiver(native_context->promise_function(), isolate_);
643 108 : Handle<AbstractCode> code(AbstractCode::cast(function->code()), isolate_);
644 :
645 : // TODO(mmarchini) save Promises list from Promise.all()
646 216 : Handle<FixedArray> parameters = isolate_->factory()->empty_fixed_array();
647 :
648 : elements_ = FrameArray::AppendJSFrame(elements_, receiver, function, code,
649 108 : offset, flags, parameters);
650 : }
651 :
652 4984484 : void AppendJavaScriptFrame(
653 : FrameSummary::JavaScriptFrameSummary const& summary) {
654 : // Filter out internal frames that we do not want to show.
655 4992540 : if (!IsVisibleInStackTrace(summary.function())) return;
656 :
657 4976428 : Handle<AbstractCode> abstract_code = summary.abstract_code();
658 : const int offset = summary.code_offset();
659 :
660 : const bool is_constructor = summary.is_constructor();
661 :
662 : int flags = 0;
663 4976428 : Handle<JSFunction> function = summary.function();
664 4976428 : if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
665 4976428 : if (is_constructor) flags |= FrameArray::kIsConstructor;
666 :
667 9952856 : Handle<FixedArray> parameters = isolate_->factory()->empty_fixed_array();
668 4976428 : if (V8_UNLIKELY(FLAG_detailed_error_stack_trace))
669 45 : parameters = summary.parameters();
670 :
671 : elements_ = FrameArray::AppendJSFrame(
672 : elements_, TheHoleToUndefined(isolate_, summary.receiver()), function,
673 4976428 : abstract_code, offset, flags, parameters);
674 : }
675 :
676 154168 : void AppendWasmCompiledFrame(
677 : FrameSummary::WasmCompiledFrameSummary const& summary) {
678 154168 : if (summary.code()->kind() != wasm::WasmCode::kFunction) return;
679 : Handle<WasmInstanceObject> instance = summary.wasm_instance();
680 : int flags = 0;
681 308336 : if (instance->module_object()->is_asm_js()) {
682 : flags |= FrameArray::kIsAsmJsWasmFrame;
683 400 : if (summary.at_to_number_conversion()) {
684 : flags |= FrameArray::kAsmJsAtNumberConversion;
685 : }
686 : } else {
687 : flags |= FrameArray::kIsWasmFrame;
688 : }
689 :
690 : elements_ = FrameArray::AppendWasmFrame(
691 154168 : elements_, instance, summary.function_index(), summary.code(),
692 154168 : summary.code_offset(), flags);
693 : }
694 :
695 2464 : void AppendWasmInterpretedFrame(
696 : FrameSummary::WasmInterpretedFrameSummary const& summary) {
697 2464 : Handle<WasmInstanceObject> instance = summary.wasm_instance();
698 : int flags = FrameArray::kIsWasmInterpretedFrame;
699 : DCHECK(!instance->module_object()->is_asm_js());
700 : elements_ = FrameArray::AppendWasmFrame(elements_, instance,
701 : summary.function_index(), {},
702 2464 : summary.byte_offset(), flags);
703 2464 : }
704 :
705 61923 : void AppendBuiltinExitFrame(BuiltinExitFrame* exit_frame) {
706 123846 : Handle<JSFunction> function = handle(exit_frame->function(), isolate_);
707 :
708 : // Filter out internal frames that we do not want to show.
709 92299 : if (!IsVisibleInStackTrace(function)) return;
710 :
711 31547 : Handle<Object> receiver(exit_frame->receiver(), isolate_);
712 31547 : Handle<Code> code(exit_frame->LookupCode(), isolate_);
713 : const int offset =
714 94641 : static_cast<int>(exit_frame->pc() - code->InstructionStart());
715 :
716 : int flags = 0;
717 31547 : if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
718 31547 : if (exit_frame->IsConstructor()) flags |= FrameArray::kIsConstructor;
719 :
720 31547 : Handle<FixedArray> parameters = isolate_->factory()->empty_fixed_array();
721 31547 : if (V8_UNLIKELY(FLAG_detailed_error_stack_trace)) {
722 5 : int param_count = exit_frame->ComputeParametersCount();
723 5 : parameters = isolate_->factory()->NewFixedArray(param_count);
724 25 : for (int i = 0; i < param_count; i++) {
725 20 : parameters->set(i, exit_frame->GetParameter(i));
726 : }
727 : }
728 :
729 : elements_ = FrameArray::AppendJSFrame(elements_, receiver, function,
730 : Handle<AbstractCode>::cast(code),
731 31547 : offset, flags, parameters);
732 : }
733 :
734 14708713 : bool full() { return elements_->FrameCount() >= limit_; }
735 :
736 : Handle<FrameArray> GetElements() {
737 2501328 : elements_->ShrinkToFit(isolate_);
738 1250664 : return elements_;
739 : }
740 :
741 : // Creates a StackTraceFrame object for each frame in the FrameArray.
742 64968 : Handle<FixedArray> GetElementsAsStackTraceFrameArray() {
743 129936 : elements_->ShrinkToFit(isolate_);
744 : const int frame_count = elements_->FrameCount();
745 : Handle<FixedArray> stack_trace =
746 64968 : isolate_->factory()->NewFixedArray(frame_count);
747 :
748 189532 : for (int i = 0; i < frame_count; ++i) {
749 : // Caching stack frames only happens for non-Wasm frames.
750 62282 : if (!elements_->IsAnyWasmFrame(i)) {
751 : MaybeHandle<StackTraceFrame> maybe_frame =
752 : StackFrameCacheHelper::LookupCachedFrame(
753 : isolate_, handle(elements_->Code(i), isolate_),
754 123668 : Smi::ToInt(elements_->Offset(i)));
755 61834 : if (!maybe_frame.is_null()) {
756 : Handle<StackTraceFrame> frame = maybe_frame.ToHandleChecked();
757 102524 : stack_trace->set(i, *frame);
758 : continue;
759 : }
760 : }
761 :
762 : Handle<StackTraceFrame> frame =
763 11020 : isolate_->factory()->NewStackTraceFrame(elements_, i);
764 22040 : stack_trace->set(i, *frame);
765 :
766 11020 : if (!elements_->IsAnyWasmFrame(i)) {
767 21144 : StackFrameCacheHelper::CacheFrameAndUpdateCache(
768 : isolate_, handle(elements_->Code(i), isolate_),
769 10572 : Smi::ToInt(elements_->Offset(i)), frame);
770 : }
771 : }
772 64968 : return stack_trace;
773 : }
774 :
775 : private:
776 : // Poison stack frames below the first strict mode frame.
777 : // The stack trace API should not expose receivers and function
778 : // objects on frames deeper than the top-most one with a strict mode
779 : // function.
780 5009330 : bool IsStrictFrame(Handle<JSFunction> function) {
781 5009330 : if (!encountered_strict_function_) {
782 : encountered_strict_function_ =
783 3698910 : is_strict(function->shared()->language_mode());
784 : }
785 5009330 : return encountered_strict_function_;
786 : }
787 :
788 : // Determines whether the given stack frame should be displayed in a stack
789 : // trace.
790 5047870 : bool IsVisibleInStackTrace(Handle<JSFunction> function) {
791 10059684 : return ShouldIncludeFrame(function) && IsNotHidden(function) &&
792 5047870 : IsInSameSecurityContext(function);
793 : }
794 :
795 : // This mechanism excludes a number of uninteresting frames from the stack
796 : // trace. This can be be the first frame (which will be a builtin-exit frame
797 : // for the error constructor builtin) or every frame until encountering a
798 : // user-specified function.
799 5047870 : bool ShouldIncludeFrame(Handle<JSFunction> function) {
800 5047870 : switch (mode_) {
801 : case SKIP_NONE:
802 : return true;
803 : case SKIP_FIRST:
804 2714 : if (!skip_next_frame_) return true;
805 590 : skip_next_frame_ = false;
806 590 : return false;
807 : case SKIP_UNTIL_SEEN:
808 166838 : if (skip_next_frame_ && (*function == *caller_)) {
809 22122 : skip_next_frame_ = false;
810 22122 : return false;
811 : }
812 119111 : return !skip_next_frame_;
813 : }
814 0 : UNREACHABLE();
815 : }
816 :
817 5021675 : bool IsNotHidden(Handle<JSFunction> function) {
818 : // Functions defined not in user scripts are not visible unless directly
819 : // exposed, in which case the native flag is set.
820 : // The --builtins-in-stack-traces command line flag allows including
821 : // internal call sites in the stack trace for debugging purposes.
822 15064881 : if (!FLAG_builtins_in_stack_traces &&
823 10043206 : !function->shared()->IsUserJavaScript()) {
824 : return function->shared()->native();
825 : }
826 : return true;
827 : }
828 :
829 : bool IsInSameSecurityContext(Handle<JSFunction> function) {
830 5011814 : if (!check_security_context_) return true;
831 4950846 : return isolate_->context()->HasSameSecurityTokenAs(function->context());
832 : }
833 :
834 : // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the
835 : // receiver in RegExp constructor frames.
836 : Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) {
837 : return (in->IsTheHole(isolate))
838 : ? Handle<Object>::cast(isolate->factory()->undefined_value())
839 4976428 : : in;
840 : }
841 :
842 : Isolate* isolate_;
843 : const FrameSkipMode mode_;
844 : int limit_;
845 : const Handle<Object> caller_;
846 : bool skip_next_frame_ = true;
847 : bool encountered_strict_function_ = false;
848 : const bool check_security_context_;
849 : Handle<FrameArray> elements_;
850 : };
851 :
852 1258185 : bool GetStackTraceLimit(Isolate* isolate, int* result) {
853 1258185 : Handle<JSObject> error = isolate->error_function();
854 :
855 : Handle<String> key = isolate->factory()->stackTraceLimit_string();
856 1258185 : Handle<Object> stack_trace_limit = JSReceiver::GetDataProperty(error, key);
857 1258185 : if (!stack_trace_limit->IsNumber()) return false;
858 :
859 : // Ensure that limit is not negative.
860 1250664 : *result = Max(FastD2IChecked(stack_trace_limit->Number()), 0);
861 :
862 1250664 : if (*result != FLAG_stack_trace_limit) {
863 54 : isolate->CountUsage(v8::Isolate::kErrorStackTraceLimit);
864 : }
865 :
866 : return true;
867 : }
868 :
869 280415 : bool NoExtension(const v8::FunctionCallbackInfo<v8::Value>&) { return false; }
870 :
871 672961 : bool IsBuiltinFunction(Isolate* isolate, HeapObject object,
872 : Builtins::Name builtin_index) {
873 672961 : if (!object->IsJSFunction()) return false;
874 : JSFunction const function = JSFunction::cast(object);
875 901426 : return function->code() == isolate->builtins()->builtin(builtin_index);
876 : }
877 :
878 2938 : void CaptureAsyncStackTrace(Isolate* isolate, Handle<JSPromise> promise,
879 : FrameArrayBuilder* builder) {
880 170358 : while (!builder->full()) {
881 : // Check that the {promise} is not settled.
882 170349 : if (promise->status() != Promise::kPending) return;
883 :
884 : // Check that we have exactly one PromiseReaction on the {promise}.
885 170311 : if (!promise->reactions()->IsPromiseReaction()) return;
886 : Handle<PromiseReaction> reaction(
887 : PromiseReaction::cast(promise->reactions()), isolate);
888 167420 : if (!reaction->next()->IsSmi()) return;
889 :
890 : // Check if the {reaction} has one of the known async function or
891 : // async generator continuations as its fulfill handler.
892 334840 : if (IsBuiltinFunction(isolate, reaction->fulfill_handler(),
893 166137 : Builtins::kAsyncFunctionAwaitResolveClosure) ||
894 166137 : IsBuiltinFunction(isolate, reaction->fulfill_handler(),
895 333521 : Builtins::kAsyncGeneratorAwaitResolveClosure) ||
896 166101 : IsBuiltinFunction(isolate, reaction->fulfill_handler(),
897 : Builtins::kAsyncGeneratorYieldResolveClosure)) {
898 : // Now peak into the handlers' AwaitContext to get to
899 : // the JSGeneratorObject for the async function.
900 : Handle<Context> context(
901 : JSFunction::cast(reaction->fulfill_handler())->context(), isolate);
902 : Handle<JSGeneratorObject> generator_object(
903 2710 : JSGeneratorObject::cast(context->extension()), isolate);
904 1355 : CHECK(generator_object->is_suspended());
905 :
906 : // Append async frame corresponding to the {generator_object}.
907 1355 : builder->AppendAsyncFrame(generator_object);
908 :
909 : // Try to continue from here.
910 1355 : if (generator_object->IsJSAsyncFunctionObject()) {
911 : Handle<JSAsyncFunctionObject> async_function_object =
912 : Handle<JSAsyncFunctionObject>::cast(generator_object);
913 : promise = handle(async_function_object->promise(), isolate);
914 : } else {
915 : Handle<JSAsyncGeneratorObject> async_generator_object =
916 : Handle<JSAsyncGeneratorObject>::cast(generator_object);
917 72 : if (async_generator_object->queue()->IsUndefined(isolate)) return;
918 : Handle<AsyncGeneratorRequest> async_generator_request(
919 : AsyncGeneratorRequest::cast(async_generator_object->queue()),
920 : isolate);
921 : promise = handle(JSPromise::cast(async_generator_request->promise()),
922 : isolate);
923 : }
924 166065 : } else if (IsBuiltinFunction(isolate, reaction->fulfill_handler(),
925 : Builtins::kPromiseAllResolveElementClosure)) {
926 : Handle<JSFunction> function(JSFunction::cast(reaction->fulfill_handler()),
927 : isolate);
928 : Handle<Context> context(function->context(), isolate);
929 :
930 : // We store the offset of the promise into the {function}'s
931 : // hash field for promise resolve element callbacks.
932 216 : int const offset = Smi::ToInt(Smi::cast(function->GetIdentityHash())) - 1;
933 108 : builder->AppendPromiseAllFrame(context, offset);
934 :
935 : // Now peak into the Promise.all() resolve element context to
936 : // find the promise capability that's being resolved when all
937 : // the concurrent promises resolve.
938 : int const index =
939 : PromiseBuiltins::kPromiseAllResolveElementCapabilitySlot;
940 : Handle<PromiseCapability> capability(
941 : PromiseCapability::cast(context->get(index)), isolate);
942 108 : if (!capability->promise()->IsJSPromise()) return;
943 : promise = handle(JSPromise::cast(capability->promise()), isolate);
944 : } else {
945 : // We have some generic promise chain here, so try to
946 : // continue with the chained promise on the reaction
947 : // (only works for native promise chains).
948 : Handle<HeapObject> promise_or_capability(
949 : reaction->promise_or_capability(), isolate);
950 165957 : if (promise_or_capability->IsJSPromise()) {
951 : promise = Handle<JSPromise>::cast(promise_or_capability);
952 0 : } else if (promise_or_capability->IsPromiseCapability()) {
953 : Handle<PromiseCapability> capability =
954 : Handle<PromiseCapability>::cast(promise_or_capability);
955 0 : if (!capability->promise()->IsJSPromise()) return;
956 : promise = handle(JSPromise::cast(capability->promise()), isolate);
957 : } else {
958 : // Otherwise the {promise_or_capability} must be undefined here.
959 0 : CHECK(promise_or_capability->IsUndefined(isolate));
960 : return;
961 : }
962 : }
963 : }
964 : }
965 :
966 : namespace {
967 :
968 : struct CaptureStackTraceOptions {
969 : int limit;
970 : // 'filter_mode' and 'skip_mode' are somewhat orthogonal. 'filter_mode'
971 : // specifies whether to capture all frames, or just frames in the same
972 : // security context. While 'skip_mode' allows skipping the first frame.
973 : FrameSkipMode skip_mode;
974 : FrameArrayBuilder::FrameFilterMode filter_mode;
975 :
976 : bool capture_builtin_exit_frames;
977 : bool capture_only_frames_subject_to_debugging;
978 : bool async_stack_trace;
979 :
980 : enum CaptureResult { RAW_FRAME_ARRAY, STACK_TRACE_FRAME_ARRAY };
981 : CaptureResult capture_result;
982 : };
983 :
984 1315632 : Handle<Object> CaptureStackTrace(Isolate* isolate, Handle<Object> caller,
985 : CaptureStackTraceOptions options) {
986 2631264 : DisallowJavascriptExecution no_js(isolate);
987 :
988 2631264 : wasm::WasmCodeRefScope code_ref_scope;
989 : FrameArrayBuilder builder(isolate, options.skip_mode, options.limit, caller,
990 1315632 : options.filter_mode);
991 :
992 : // Build the regular stack trace, and remember the last relevant
993 : // frame ID and inlined index (for the async stack trace handling
994 : // below, which starts from this last frame).
995 10709099 : for (StackFrameIterator it(isolate); !it.done() && !builder.full();
996 9143641 : it.Advance()) {
997 : StackFrame* const frame = it.frame();
998 9143641 : switch (frame->type()) {
999 : case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION:
1000 : case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH:
1001 : case StackFrame::OPTIMIZED:
1002 : case StackFrame::INTERPRETED:
1003 : case StackFrame::BUILTIN:
1004 : case StackFrame::WASM_COMPILED:
1005 : case StackFrame::WASM_INTERPRETER_ENTRY: {
1006 : // A standard frame may include many summarized frames (due to
1007 : // inlining).
1008 4990033 : std::vector<FrameSummary> frames;
1009 4990033 : StandardFrame::cast(frame)->Summarize(&frames);
1010 15276749 : for (size_t i = frames.size(); i-- != 0 && !builder.full();) {
1011 : auto& summary = frames[i];
1012 5207748 : if (options.capture_only_frames_subject_to_debugging &&
1013 64457 : !summary.is_subject_to_debugging()) {
1014 : continue;
1015 : }
1016 :
1017 5141116 : if (summary.IsJavaScript()) {
1018 : //=========================================================
1019 : // Handle a JavaScript frame.
1020 : //=========================================================
1021 : auto const& java_script = summary.AsJavaScript();
1022 4984484 : builder.AppendJavaScriptFrame(java_script);
1023 156632 : } else if (summary.IsWasmCompiled()) {
1024 : //=========================================================
1025 : // Handle a WASM compiled frame.
1026 : //=========================================================
1027 : auto const& wasm_compiled = summary.AsWasmCompiled();
1028 154168 : builder.AppendWasmCompiledFrame(wasm_compiled);
1029 2464 : } else if (summary.IsWasmInterpreted()) {
1030 : //=========================================================
1031 : // Handle a WASM interpreted frame.
1032 : //=========================================================
1033 : auto const& wasm_interpreted = summary.AsWasmInterpreted();
1034 2464 : builder.AppendWasmInterpretedFrame(wasm_interpreted);
1035 : }
1036 : }
1037 : break;
1038 : }
1039 :
1040 : case StackFrame::BUILTIN_EXIT:
1041 69777 : if (!options.capture_builtin_exit_frames) continue;
1042 :
1043 : // BuiltinExitFrames are not standard frames, so they do not have
1044 : // Summarize(). However, they may have one JS frame worth showing.
1045 61923 : builder.AppendBuiltinExitFrame(BuiltinExitFrame::cast(frame));
1046 : break;
1047 :
1048 : default:
1049 : break;
1050 : }
1051 : }
1052 :
1053 : // If --async-stack-traces are enabled and the "current microtask" is a
1054 : // PromiseReactionJobTask, we try to enrich the stack trace with async
1055 : // frames.
1056 1315632 : if (options.async_stack_trace) {
1057 : Handle<Object> current_microtask = isolate->factory()->current_microtask();
1058 1250286 : if (current_microtask->IsPromiseReactionJobTask()) {
1059 : Handle<PromiseReactionJobTask> promise_reaction_job_task =
1060 : Handle<PromiseReactionJobTask>::cast(current_microtask);
1061 : // Check if the {reaction} has one of the known async function or
1062 : // async generator continuations as its fulfill handler.
1063 6130 : if (IsBuiltinFunction(isolate, promise_reaction_job_task->handler(),
1064 2154 : Builtins::kAsyncFunctionAwaitResolveClosure) ||
1065 2154 : IsBuiltinFunction(isolate, promise_reaction_job_task->handler(),
1066 5084 : Builtins::kAsyncGeneratorAwaitResolveClosure) ||
1067 2019 : IsBuiltinFunction(isolate, promise_reaction_job_task->handler(),
1068 : Builtins::kAsyncGeneratorYieldResolveClosure)) {
1069 : // Now peak into the handlers' AwaitContext to get to
1070 : // the JSGeneratorObject for the async function.
1071 : Handle<Context> context(
1072 : JSFunction::cast(promise_reaction_job_task->handler())->context(),
1073 : isolate);
1074 : Handle<JSGeneratorObject> generator_object(
1075 2092 : JSGeneratorObject::cast(context->extension()), isolate);
1076 1046 : if (generator_object->is_executing()) {
1077 1027 : if (generator_object->IsJSAsyncFunctionObject()) {
1078 : Handle<JSAsyncFunctionObject> async_function_object =
1079 : Handle<JSAsyncFunctionObject>::cast(generator_object);
1080 : Handle<JSPromise> promise(async_function_object->promise(),
1081 : isolate);
1082 892 : CaptureAsyncStackTrace(isolate, promise, &builder);
1083 : } else {
1084 : Handle<JSAsyncGeneratorObject> async_generator_object =
1085 : Handle<JSAsyncGeneratorObject>::cast(generator_object);
1086 : Handle<AsyncGeneratorRequest> async_generator_request(
1087 : AsyncGeneratorRequest::cast(async_generator_object->queue()),
1088 : isolate);
1089 : Handle<JSPromise> promise(
1090 : JSPromise::cast(async_generator_request->promise()), isolate);
1091 135 : CaptureAsyncStackTrace(isolate, promise, &builder);
1092 : }
1093 : }
1094 : } else {
1095 : // The {promise_reaction_job_task} doesn't belong to an await (or
1096 : // yield inside an async generator), but we might still be able to
1097 : // find an async frame if we follow along the chain of promises on
1098 : // the {promise_reaction_job_task}.
1099 : Handle<HeapObject> promise_or_capability(
1100 : promise_reaction_job_task->promise_or_capability(), isolate);
1101 2019 : if (promise_or_capability->IsJSPromise()) {
1102 : Handle<JSPromise> promise =
1103 1911 : Handle<JSPromise>::cast(promise_or_capability);
1104 1911 : CaptureAsyncStackTrace(isolate, promise, &builder);
1105 : }
1106 : }
1107 : }
1108 : }
1109 :
1110 : // TODO(yangguo): Queue this structured stack trace for preprocessing on GC.
1111 1315632 : if (options.capture_result == CaptureStackTraceOptions::RAW_FRAME_ARRAY) {
1112 1250664 : return builder.GetElements();
1113 : }
1114 64968 : return builder.GetElementsAsStackTraceFrameArray();
1115 : }
1116 :
1117 : } // namespace
1118 :
1119 1258185 : Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
1120 : FrameSkipMode mode,
1121 : Handle<Object> caller) {
1122 : int limit;
1123 1265706 : if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value();
1124 :
1125 : CaptureStackTraceOptions options;
1126 1250664 : options.limit = limit;
1127 : options.skip_mode = mode;
1128 : options.capture_builtin_exit_frames = true;
1129 1250664 : options.async_stack_trace = FLAG_async_stack_traces;
1130 : options.filter_mode = FrameArrayBuilder::CURRENT_SECURITY_CONTEXT;
1131 : options.capture_only_frames_subject_to_debugging = false;
1132 : options.capture_result = CaptureStackTraceOptions::RAW_FRAME_ARRAY;
1133 :
1134 1250664 : return CaptureStackTrace(this, caller, options);
1135 : }
1136 :
1137 1209858 : MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace(
1138 : Handle<JSReceiver> error_object) {
1139 1209858 : if (capture_stack_trace_for_uncaught_exceptions_) {
1140 : // Capture stack trace for a detailed exception message.
1141 : Handle<Name> key = factory()->detailed_stack_trace_symbol();
1142 : Handle<FixedArray> stack_trace = CaptureCurrentStackTrace(
1143 : stack_trace_for_uncaught_exceptions_frame_limit_,
1144 264 : stack_trace_for_uncaught_exceptions_options_);
1145 528 : RETURN_ON_EXCEPTION(
1146 : this,
1147 : Object::SetProperty(this, error_object, key, stack_trace,
1148 : StoreOrigin::kMaybeKeyed,
1149 : Just(ShouldThrow::kThrowOnError)),
1150 : JSReceiver);
1151 : }
1152 1209858 : return error_object;
1153 : }
1154 :
1155 1258185 : MaybeHandle<JSReceiver> Isolate::CaptureAndSetSimpleStackTrace(
1156 : Handle<JSReceiver> error_object, FrameSkipMode mode,
1157 : Handle<Object> caller) {
1158 : // Capture stack trace for simple stack trace string formatting.
1159 : Handle<Name> key = factory()->stack_trace_symbol();
1160 : Handle<Object> stack_trace =
1161 1258185 : CaptureSimpleStackTrace(error_object, mode, caller);
1162 2516370 : RETURN_ON_EXCEPTION(this,
1163 : Object::SetProperty(this, error_object, key, stack_trace,
1164 : StoreOrigin::kMaybeKeyed,
1165 : Just(ShouldThrow::kThrowOnError)),
1166 : JSReceiver);
1167 1258185 : return error_object;
1168 : }
1169 :
1170 363 : Handle<FixedArray> Isolate::GetDetailedStackTrace(
1171 : Handle<JSObject> error_object) {
1172 : Handle<Name> key_detailed = factory()->detailed_stack_trace_symbol();
1173 : Handle<Object> stack_trace =
1174 363 : JSReceiver::GetDataProperty(error_object, key_detailed);
1175 363 : if (stack_trace->IsFixedArray()) return Handle<FixedArray>::cast(stack_trace);
1176 16 : return Handle<FixedArray>();
1177 : }
1178 :
1179 4124 : Address Isolate::GetAbstractPC(int* line, int* column) {
1180 4124 : JavaScriptFrameIterator it(this);
1181 :
1182 4124 : if (it.done()) {
1183 0 : *line = -1;
1184 0 : *column = -1;
1185 0 : return kNullAddress;
1186 : }
1187 : JavaScriptFrame* frame = it.frame();
1188 : DCHECK(!frame->is_builtin());
1189 :
1190 8248 : Handle<SharedFunctionInfo> shared = handle(frame->function()->shared(), this);
1191 4124 : SharedFunctionInfo::EnsureSourcePositionsAvailable(this, shared);
1192 4124 : int position = frame->position();
1193 :
1194 8248 : Object maybe_script = frame->function()->shared()->script();
1195 4124 : if (maybe_script->IsScript()) {
1196 : Handle<Script> script(Script::cast(maybe_script), this);
1197 : Script::PositionInfo info;
1198 4124 : Script::GetPositionInfo(script, position, &info, Script::WITH_OFFSET);
1199 4124 : *line = info.line + 1;
1200 4124 : *column = info.column + 1;
1201 : } else {
1202 0 : *line = position;
1203 0 : *column = -1;
1204 : }
1205 :
1206 8248 : if (frame->is_interpreted()) {
1207 : InterpretedFrame* iframe = static_cast<InterpretedFrame*>(frame);
1208 : Address bytecode_start =
1209 6648 : iframe->GetBytecodeArray()->GetFirstBytecodeAddress();
1210 3324 : return bytecode_start + iframe->GetBytecodeOffset();
1211 : }
1212 :
1213 800 : return frame->pc();
1214 : }
1215 :
1216 64968 : Handle<FixedArray> Isolate::CaptureCurrentStackTrace(
1217 : int frame_limit, StackTrace::StackTraceOptions stack_trace_options) {
1218 : CaptureStackTraceOptions options;
1219 : options.limit = Max(frame_limit, 0); // Ensure no negative values.
1220 : options.skip_mode = SKIP_NONE;
1221 : options.capture_builtin_exit_frames = false;
1222 : options.async_stack_trace = false;
1223 : options.filter_mode =
1224 64968 : (stack_trace_options & StackTrace::kExposeFramesAcrossSecurityOrigins)
1225 : ? FrameArrayBuilder::ALL
1226 64968 : : FrameArrayBuilder::CURRENT_SECURITY_CONTEXT;
1227 : options.capture_only_frames_subject_to_debugging = true;
1228 : options.capture_result = CaptureStackTraceOptions::STACK_TRACE_FRAME_ARRAY;
1229 :
1230 : return Handle<FixedArray>::cast(
1231 64968 : CaptureStackTrace(this, factory()->undefined_value(), options));
1232 : }
1233 :
1234 17 : void Isolate::PrintStack(FILE* out, PrintStackMode mode) {
1235 17 : if (stack_trace_nesting_level_ == 0) {
1236 17 : stack_trace_nesting_level_++;
1237 17 : StringStream::ClearMentionedObjectCache(this);
1238 : HeapStringAllocator allocator;
1239 : StringStream accumulator(&allocator);
1240 17 : incomplete_message_ = &accumulator;
1241 17 : PrintStack(&accumulator, mode);
1242 17 : accumulator.OutputToFile(out);
1243 17 : InitializeLoggingAndCounters();
1244 17 : accumulator.Log(this);
1245 17 : incomplete_message_ = nullptr;
1246 17 : stack_trace_nesting_level_ = 0;
1247 0 : } else if (stack_trace_nesting_level_ == 1) {
1248 0 : stack_trace_nesting_level_++;
1249 : base::OS::PrintError(
1250 0 : "\n\nAttempt to print stack while printing stack (double fault)\n");
1251 : base::OS::PrintError(
1252 0 : "If you are lucky you may find a partial stack dump on stdout.\n\n");
1253 0 : incomplete_message_->OutputToFile(out);
1254 : }
1255 17 : }
1256 :
1257 :
1258 25 : static void PrintFrames(Isolate* isolate,
1259 : StringStream* accumulator,
1260 : StackFrame::PrintMode mode) {
1261 25 : StackFrameIterator it(isolate);
1262 477 : for (int i = 0; !it.done(); it.Advance()) {
1263 226 : it.frame()->Print(accumulator, mode, i++);
1264 : }
1265 25 : }
1266 :
1267 32 : void Isolate::PrintStack(StringStream* accumulator, PrintStackMode mode) {
1268 : HandleScope scope(this);
1269 49 : wasm::WasmCodeRefScope wasm_code_ref_scope;
1270 : DCHECK(accumulator->IsMentionedObjectCacheClear(this));
1271 :
1272 : // Avoid printing anything if there are no frames.
1273 47 : if (c_entry_fp(thread_local_top()) == 0) return;
1274 :
1275 : accumulator->Add(
1276 17 : "\n==== JS stack trace =========================================\n\n");
1277 17 : PrintFrames(this, accumulator, StackFrame::OVERVIEW);
1278 17 : if (mode == kPrintStackVerbose) {
1279 : accumulator->Add(
1280 8 : "\n==== Details ================================================\n\n");
1281 8 : PrintFrames(this, accumulator, StackFrame::DETAILS);
1282 8 : accumulator->PrintMentionedObjectCache(this);
1283 : }
1284 17 : accumulator->Add("=====================\n\n");
1285 : }
1286 :
1287 :
1288 26 : void Isolate::SetFailedAccessCheckCallback(
1289 : v8::FailedAccessCheckCallback callback) {
1290 26 : thread_local_top()->failed_access_check_callback_ = callback;
1291 26 : }
1292 :
1293 :
1294 1318 : void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver) {
1295 1318 : if (!thread_local_top()->failed_access_check_callback_) {
1296 3483 : return ScheduleThrow(*factory()->NewTypeError(MessageTemplate::kNoAccess));
1297 : }
1298 :
1299 : DCHECK(receiver->IsAccessCheckNeeded());
1300 : DCHECK(!context().is_null());
1301 :
1302 : // Get the data object from access check info.
1303 : HandleScope scope(this);
1304 : Handle<Object> data;
1305 : { DisallowHeapAllocation no_gc;
1306 157 : AccessCheckInfo access_check_info = AccessCheckInfo::Get(this, receiver);
1307 157 : if (access_check_info.is_null()) {
1308 : AllowHeapAllocation doesnt_matter_anymore;
1309 : return ScheduleThrow(
1310 0 : *factory()->NewTypeError(MessageTemplate::kNoAccess));
1311 : }
1312 : data = handle(access_check_info->data(), this);
1313 : }
1314 :
1315 : // Leaving JavaScript.
1316 314 : VMState<EXTERNAL> state(this);
1317 157 : thread_local_top()->failed_access_check_callback_(
1318 157 : v8::Utils::ToLocal(receiver), v8::ACCESS_HAS, v8::Utils::ToLocal(data));
1319 : }
1320 :
1321 :
1322 6040666 : bool Isolate::MayAccess(Handle<Context> accessing_context,
1323 : Handle<JSObject> receiver) {
1324 : DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
1325 :
1326 : // Check for compatibility between the security tokens in the
1327 : // current lexical context and the accessed object.
1328 :
1329 : // During bootstrapping, callback functions are not enabled yet.
1330 6040666 : if (bootstrapper()->IsActive()) return true;
1331 : {
1332 : DisallowHeapAllocation no_gc;
1333 :
1334 6040428 : if (receiver->IsJSGlobalProxy()) {
1335 : Object receiver_context =
1336 : JSGlobalProxy::cast(*receiver)->native_context();
1337 12075911 : if (!receiver_context->IsContext()) return false;
1338 :
1339 : // Get the native context of current top context.
1340 : // avoid using Isolate::native_context() because it uses Handle.
1341 : Context native_context =
1342 12076918 : accessing_context->global_object()->native_context();
1343 6038459 : if (receiver_context == native_context) return true;
1344 :
1345 3048 : if (Context::cast(receiver_context)->security_token() ==
1346 : native_context->security_token())
1347 : return true;
1348 : }
1349 : }
1350 :
1351 : HandleScope scope(this);
1352 : Handle<Object> data;
1353 : v8::AccessCheckCallback callback = nullptr;
1354 : { DisallowHeapAllocation no_gc;
1355 3097 : AccessCheckInfo access_check_info = AccessCheckInfo::Get(this, receiver);
1356 3097 : if (access_check_info.is_null()) return false;
1357 : Object fun_obj = access_check_info->callback();
1358 : callback = v8::ToCData<v8::AccessCheckCallback>(fun_obj);
1359 : data = handle(access_check_info->data(), this);
1360 : }
1361 :
1362 2400 : LOG(this, ApiSecurityCheck());
1363 :
1364 : {
1365 : // Leaving JavaScript.
1366 4800 : VMState<EXTERNAL> state(this);
1367 : return callback(v8::Utils::ToLocal(accessing_context),
1368 2400 : v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(data));
1369 : }
1370 : }
1371 :
1372 48327 : Object Isolate::StackOverflow() {
1373 48327 : if (FLAG_abort_on_stack_or_string_length_overflow) {
1374 0 : FATAL("Aborting on stack overflow");
1375 : }
1376 :
1377 96654 : DisallowJavascriptExecution no_js(this);
1378 : HandleScope scope(this);
1379 :
1380 48327 : Handle<JSFunction> fun = range_error_function();
1381 : Handle<Object> msg = factory()->NewStringFromAsciiChecked(
1382 48327 : MessageFormatter::TemplateString(MessageTemplate::kStackOverflow));
1383 : Handle<Object> no_caller;
1384 : Handle<Object> exception;
1385 96654 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1386 : this, exception,
1387 : ErrorUtils::Construct(this, fun, fun, msg, SKIP_NONE, no_caller, true));
1388 :
1389 48327 : Throw(*exception, nullptr);
1390 :
1391 : #ifdef VERIFY_HEAP
1392 : if (FLAG_verify_heap && FLAG_stress_compaction) {
1393 : heap()->CollectAllGarbage(Heap::kNoGCFlags,
1394 : GarbageCollectionReason::kTesting);
1395 : }
1396 : #endif // VERIFY_HEAP
1397 :
1398 48327 : return ReadOnlyRoots(heap()).exception();
1399 : }
1400 :
1401 4209 : Object Isolate::TerminateExecution() {
1402 4209 : return Throw(ReadOnlyRoots(this).termination_exception(), nullptr);
1403 : }
1404 :
1405 3016 : void Isolate::CancelTerminateExecution() {
1406 3016 : if (try_catch_handler()) {
1407 1235 : try_catch_handler()->has_terminated_ = false;
1408 : }
1409 5947 : if (has_pending_exception() &&
1410 : pending_exception() == ReadOnlyRoots(this).termination_exception()) {
1411 2931 : thread_local_top()->external_caught_exception_ = false;
1412 : clear_pending_exception();
1413 : }
1414 3081 : if (has_scheduled_exception() &&
1415 : scheduled_exception() == ReadOnlyRoots(this).termination_exception()) {
1416 65 : thread_local_top()->external_caught_exception_ = false;
1417 : clear_scheduled_exception();
1418 : }
1419 3016 : }
1420 :
1421 :
1422 60205 : void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
1423 : ExecutionAccess access(this);
1424 60205 : api_interrupts_queue_.push(InterruptEntry(callback, data));
1425 : stack_guard()->RequestApiInterrupt();
1426 60205 : }
1427 :
1428 :
1429 2166 : void Isolate::InvokeApiInterruptCallbacks() {
1430 : RuntimeCallTimerScope runtimeTimer(
1431 2166 : this, RuntimeCallCounterId::kInvokeApiInterruptCallbacks);
1432 : // Note: callback below should be called outside of execution access lock.
1433 : while (true) {
1434 : InterruptEntry entry;
1435 : {
1436 : ExecutionAccess access(this);
1437 64527 : if (api_interrupts_queue_.empty()) return;
1438 : entry = api_interrupts_queue_.front();
1439 : api_interrupts_queue_.pop();
1440 : }
1441 120390 : VMState<EXTERNAL> state(this);
1442 : HandleScope handle_scope(this);
1443 60195 : entry.first(reinterpret_cast<v8::Isolate*>(this), entry.second);
1444 : }
1445 : }
1446 :
1447 :
1448 30 : void ReportBootstrappingException(Handle<Object> exception,
1449 : MessageLocation* location) {
1450 30 : base::OS::PrintError("Exception thrown during bootstrapping\n");
1451 30 : if (location == nullptr || location->script().is_null()) return;
1452 : // We are bootstrapping and caught an error where the location is set
1453 : // and we have a script for the location.
1454 : // In this case we could have an extension (or an internal error
1455 : // somewhere) and we print out the line number at which the error occurred
1456 : // to the console for easier debugging.
1457 : int line_number =
1458 30 : location->script()->GetLineNumber(location->start_pos()) + 1;
1459 60 : if (exception->IsString() && location->script()->name()->IsString()) {
1460 : base::OS::PrintError(
1461 : "Extension or internal compilation error: %s in %s at line %d.\n",
1462 60 : String::cast(*exception)->ToCString().get(),
1463 60 : String::cast(location->script()->name())->ToCString().get(),
1464 30 : line_number);
1465 0 : } else if (location->script()->name()->IsString()) {
1466 : base::OS::PrintError(
1467 : "Extension or internal compilation error in %s at line %d.\n",
1468 0 : String::cast(location->script()->name())->ToCString().get(),
1469 0 : line_number);
1470 0 : } else if (exception->IsString()) {
1471 : base::OS::PrintError("Extension or internal compilation error: %s.\n",
1472 0 : String::cast(*exception)->ToCString().get());
1473 : } else {
1474 0 : base::OS::PrintError("Extension or internal compilation error.\n");
1475 : }
1476 : #ifdef OBJECT_PRINT
1477 : // Since comments and empty lines have been stripped from the source of
1478 : // builtins, print the actual source here so that line numbers match.
1479 : if (location->script()->source()->IsString()) {
1480 : Handle<String> src(String::cast(location->script()->source()),
1481 : location->script()->GetIsolate());
1482 : PrintF("Failing script:");
1483 : int len = src->length();
1484 : if (len == 0) {
1485 : PrintF(" <not available>\n");
1486 : } else {
1487 : PrintF("\n");
1488 : int line_number = 1;
1489 : PrintF("%5d: ", line_number);
1490 : for (int i = 0; i < len; i++) {
1491 : uint16_t character = src->Get(i);
1492 : PrintF("%c", character);
1493 : if (character == '\n' && i < len - 2) {
1494 : PrintF("%5d: ", ++line_number);
1495 : }
1496 : }
1497 : PrintF("\n");
1498 : }
1499 : }
1500 : #endif
1501 : }
1502 :
1503 1414098 : Object Isolate::Throw(Object raw_exception, MessageLocation* location) {
1504 : DCHECK(!has_pending_exception());
1505 :
1506 : HandleScope scope(this);
1507 : Handle<Object> exception(raw_exception, this);
1508 :
1509 1414098 : if (FLAG_print_all_exceptions) {
1510 : printf("=========================================================\n");
1511 : printf("Exception thrown:\n");
1512 0 : if (location) {
1513 : Handle<Script> script = location->script();
1514 0 : Handle<Object> name(script->GetNameOrSourceURL(), this);
1515 : printf("at ");
1516 0 : if (name->IsString() && String::cast(*name)->length() > 0)
1517 0 : String::cast(*name)->PrintOn(stdout);
1518 : else
1519 : printf("<anonymous>");
1520 : // Script::GetLineNumber and Script::GetColumnNumber can allocate on the heap to
1521 : // initialize the line_ends array, so be careful when calling them.
1522 : #ifdef DEBUG
1523 : if (AllowHeapAllocation::IsAllowed()) {
1524 : #else
1525 : if ((false)) {
1526 : #endif
1527 : printf(", %d:%d - %d:%d\n",
1528 : Script::GetLineNumber(script, location->start_pos()) + 1,
1529 : Script::GetColumnNumber(script, location->start_pos()),
1530 : Script::GetLineNumber(script, location->end_pos()) + 1,
1531 : Script::GetColumnNumber(script, location->end_pos()));
1532 : // Make sure to update the raw exception pointer in case it moved.
1533 : raw_exception = *exception;
1534 : } else {
1535 0 : printf(", line %d\n", script->GetLineNumber(location->start_pos()) + 1);
1536 : }
1537 : }
1538 : raw_exception->Print();
1539 : printf("Stack Trace:\n");
1540 0 : PrintStack(stdout);
1541 : printf("=========================================================\n");
1542 : }
1543 :
1544 : // Determine whether a message needs to be created for the given exception
1545 : // depending on the following criteria:
1546 : // 1) External v8::TryCatch missing: Always create a message because any
1547 : // JavaScript handler for a finally-block might re-throw to top-level.
1548 : // 2) External v8::TryCatch exists: Only create a message if the handler
1549 : // captures messages or is verbose (which reports despite the catch).
1550 : // 3) ReThrow from v8::TryCatch: The message from a previous throw still
1551 : // exists and we preserve it instead of creating a new message.
1552 1128616 : bool requires_message = try_catch_handler() == nullptr ||
1553 1472348 : try_catch_handler()->is_verbose_ ||
1554 58250 : try_catch_handler()->capture_message_;
1555 1414098 : bool rethrowing_message = thread_local_top()->rethrowing_message_;
1556 :
1557 1414098 : thread_local_top()->rethrowing_message_ = false;
1558 :
1559 : // Notify debugger of exception.
1560 1414098 : if (is_catchable_by_javascript(raw_exception)) {
1561 1409889 : debug()->OnThrow(exception);
1562 : }
1563 :
1564 : // Generate the message if required.
1565 1414098 : if (requires_message && !rethrowing_message) {
1566 1362654 : MessageLocation computed_location;
1567 : // If no location was specified we try to use a computed one instead.
1568 1362654 : if (location == nullptr && ComputeLocation(&computed_location)) {
1569 : location = &computed_location;
1570 : }
1571 :
1572 1362654 : if (bootstrapper()->IsActive()) {
1573 : // It's not safe to try to make message objects or collect stack traces
1574 : // while the bootstrapper is active since the infrastructure may not have
1575 : // been properly initialized.
1576 30 : ReportBootstrappingException(exception, location);
1577 : } else {
1578 1362624 : Handle<Object> message_obj = CreateMessage(exception, location);
1579 1362624 : thread_local_top()->pending_message_obj_ = *message_obj;
1580 :
1581 : // For any exception not caught by JavaScript, even when an external
1582 : // handler is present:
1583 : // If the abort-on-uncaught-exception flag is specified, and if the
1584 : // embedder didn't specify a custom uncaught exception callback,
1585 : // or if the custom callback determined that V8 should abort, then
1586 : // abort.
1587 1362624 : if (FLAG_abort_on_uncaught_exception) {
1588 5 : CatchType prediction = PredictExceptionCatcher();
1589 15 : if ((prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) &&
1590 10 : (!abort_on_uncaught_exception_callback_ ||
1591 5 : abort_on_uncaught_exception_callback_(
1592 : reinterpret_cast<v8::Isolate*>(this)))) {
1593 : // Prevent endless recursion.
1594 0 : FLAG_abort_on_uncaught_exception = false;
1595 : // This flag is intended for use by JavaScript developers, so
1596 : // print a user-friendly stack trace (not an internal one).
1597 : PrintF(stderr, "%s\n\nFROM\n",
1598 0 : MessageHandler::GetLocalizedMessage(this, message_obj).get());
1599 0 : PrintCurrentStackTrace(stderr);
1600 0 : base::OS::Abort();
1601 : }
1602 : }
1603 : }
1604 : }
1605 :
1606 : // Set the exception being thrown.
1607 : set_pending_exception(*exception);
1608 2828196 : return ReadOnlyRoots(heap()).exception();
1609 : }
1610 :
1611 83981 : Object Isolate::ReThrow(Object exception) {
1612 : DCHECK(!has_pending_exception());
1613 :
1614 : // Set the exception being re-thrown.
1615 : set_pending_exception(exception);
1616 83981 : return ReadOnlyRoots(heap()).exception();
1617 : }
1618 :
1619 1313932 : Object Isolate::UnwindAndFindHandler() {
1620 1313932 : Object exception = pending_exception();
1621 :
1622 : auto FoundHandler = [&](Context context, Address instruction_start,
1623 : intptr_t handler_offset,
1624 : Address constant_pool_address, Address handler_sp,
1625 : Address handler_fp) {
1626 : // Store information to be consumed by the CEntry.
1627 1313932 : thread_local_top()->pending_handler_context_ = context;
1628 : thread_local_top()->pending_handler_entrypoint_ =
1629 1313932 : instruction_start + handler_offset;
1630 1313932 : thread_local_top()->pending_handler_constant_pool_ = constant_pool_address;
1631 1313932 : thread_local_top()->pending_handler_fp_ = handler_fp;
1632 1313932 : thread_local_top()->pending_handler_sp_ = handler_sp;
1633 :
1634 : // Return and clear pending exception.
1635 : clear_pending_exception();
1636 1313932 : return exception;
1637 : };
1638 :
1639 : // Special handling of termination exceptions, uncatchable by JavaScript and
1640 : // Wasm code, we unwind the handlers until the top ENTRY handler is found.
1641 : bool catchable_by_js = is_catchable_by_javascript(exception);
1642 :
1643 : // Compute handler and stack unwinding information by performing a full walk
1644 : // over the stack and dispatching according to the frame type.
1645 22848872 : for (StackFrameIterator iter(this);; iter.Advance()) {
1646 : // Handler must exist.
1647 : DCHECK(!iter.done());
1648 :
1649 : StackFrame* frame = iter.frame();
1650 :
1651 22848872 : switch (frame->type()) {
1652 : case StackFrame::ENTRY:
1653 : case StackFrame::CONSTRUCT_ENTRY: {
1654 : // For JSEntry frames we always have a handler.
1655 : StackHandler* handler = frame->top_handler();
1656 :
1657 : // Restore the next handler.
1658 120271 : thread_local_top()->handler_ = handler->next_address();
1659 :
1660 : // Gather information from the handler.
1661 120271 : Code code = frame->LookupCode();
1662 120271 : HandlerTable table(code);
1663 : return FoundHandler(Context(), code->InstructionStart(),
1664 120271 : table.LookupReturn(0), code->constant_pool(),
1665 : handler->address() + StackHandlerConstants::kSize,
1666 120271 : 0);
1667 : }
1668 :
1669 : case StackFrame::WASM_COMPILED: {
1670 2615442 : if (trap_handler::IsThreadInWasm()) {
1671 : trap_handler::ClearThreadInWasm();
1672 : }
1673 :
1674 : // For WebAssembly frames we perform a lookup in the handler table.
1675 2615442 : if (!catchable_by_js) break;
1676 : // This code ref scope is here to avoid a check failure when looking up
1677 : // the code. It's not actually necessary to keep the code alive as it's
1678 : // currently being executed.
1679 2615434 : wasm::WasmCodeRefScope code_ref_scope;
1680 : WasmCompiledFrame* wasm_frame = static_cast<WasmCompiledFrame*>(frame);
1681 2615434 : int stack_slots = 0; // Will contain stack slot count of frame.
1682 2615434 : int offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots);
1683 2615434 : if (offset < 0) break;
1684 : // Compute the stack pointer from the frame pointer. This ensures that
1685 : // argument slots on the stack are dropped as returning would.
1686 : Address return_sp = frame->fp() +
1687 656 : StandardFrameConstants::kFixedFrameSizeAboveFp -
1688 1312 : stack_slots * kSystemPointerSize;
1689 :
1690 : // This is going to be handled by Wasm, so we need to set the TLS flag
1691 : // again. It was cleared above assuming the frame would be unwound.
1692 : trap_handler::SetThreadInWasm();
1693 :
1694 : // Gather information from the frame.
1695 : wasm::WasmCode* wasm_code =
1696 656 : wasm_engine()->code_manager()->LookupCode(frame->pc());
1697 : return FoundHandler(Context(), wasm_code->instruction_start(), offset,
1698 656 : wasm_code->constant_pool(), return_sp, frame->fp());
1699 : }
1700 :
1701 : case StackFrame::OPTIMIZED: {
1702 : // For optimized frames we perform a lookup in the handler table.
1703 3332948 : if (!catchable_by_js) break;
1704 : OptimizedFrame* js_frame = static_cast<OptimizedFrame*>(frame);
1705 3332585 : int stack_slots = 0; // Will contain stack slot count of frame.
1706 : int offset =
1707 3332585 : js_frame->LookupExceptionHandlerInTable(&stack_slots, nullptr);
1708 3332585 : if (offset < 0) break;
1709 : // Compute the stack pointer from the frame pointer. This ensures
1710 : // that argument slots on the stack are dropped as returning would.
1711 : Address return_sp = frame->fp() +
1712 331102 : StandardFrameConstants::kFixedFrameSizeAboveFp -
1713 662204 : stack_slots * kSystemPointerSize;
1714 :
1715 : // Gather information from the frame.
1716 331102 : Code code = frame->LookupCode();
1717 :
1718 : // TODO(bmeurer): Turbofanned BUILTIN frames appear as OPTIMIZED,
1719 : // but do not have a code kind of OPTIMIZED_FUNCTION.
1720 589707 : if (code->kind() == Code::OPTIMIZED_FUNCTION &&
1721 258605 : code->marked_for_deoptimization()) {
1722 : // If the target code is lazy deoptimized, we jump to the original
1723 : // return address, but we make a note that we are throwing, so
1724 : // that the deoptimizer can do the right thing.
1725 12218 : offset = static_cast<int>(frame->pc() - code->entry());
1726 : set_deoptimizer_lazy_throw(true);
1727 : }
1728 :
1729 : return FoundHandler(Context(), code->InstructionStart(), offset,
1730 331102 : code->constant_pool(), return_sp, frame->fp());
1731 : }
1732 :
1733 : case StackFrame::STUB: {
1734 : // Some stubs are able to handle exceptions.
1735 1053422 : if (!catchable_by_js) break;
1736 : StubFrame* stub_frame = static_cast<StubFrame*>(frame);
1737 1052073 : wasm::WasmCodeRefScope code_ref_scope;
1738 : wasm::WasmCode* wasm_code =
1739 1052073 : wasm_engine()->code_manager()->LookupCode(frame->pc());
1740 1052073 : if (wasm_code != nullptr) {
1741 : // It is safe to skip Wasm runtime stubs as none of them contain local
1742 : // exception handlers.
1743 0 : CHECK_EQ(wasm::WasmCode::kRuntimeStub, wasm_code->kind());
1744 0 : CHECK_EQ(0, wasm_code->handler_table_offset());
1745 1006469 : break;
1746 : }
1747 1052073 : Code code = stub_frame->LookupCode();
1748 2554534 : if (!code->IsCode() || code->kind() != Code::BUILTIN ||
1749 1548065 : !code->has_handler_table() || !code->is_turbofanned()) {
1750 : break;
1751 : }
1752 :
1753 45604 : int stack_slots = 0; // Will contain stack slot count of frame.
1754 45604 : int offset = stub_frame->LookupExceptionHandlerInTable(&stack_slots);
1755 45604 : if (offset < 0) break;
1756 :
1757 : // Compute the stack pointer from the frame pointer. This ensures
1758 : // that argument slots on the stack are dropped as returning would.
1759 : Address return_sp = frame->fp() +
1760 45604 : StandardFrameConstants::kFixedFrameSizeAboveFp -
1761 91208 : stack_slots * kSystemPointerSize;
1762 :
1763 : return FoundHandler(Context(), code->InstructionStart(), offset,
1764 45604 : code->constant_pool(), return_sp, frame->fp());
1765 : }
1766 :
1767 : case StackFrame::INTERPRETED: {
1768 : // For interpreted frame we perform a range lookup in the handler table.
1769 13291753 : if (!catchable_by_js) break;
1770 : InterpretedFrame* js_frame = static_cast<InterpretedFrame*>(frame);
1771 : int register_slots = InterpreterFrameConstants::RegisterStackSlotCount(
1772 26576504 : js_frame->GetBytecodeArray()->register_count());
1773 13288252 : int context_reg = 0; // Will contain register index holding context.
1774 : int offset =
1775 13288252 : js_frame->LookupExceptionHandlerInTable(&context_reg, nullptr);
1776 13288252 : if (offset < 0) break;
1777 : // Compute the stack pointer from the frame pointer. This ensures that
1778 : // argument slots on the stack are dropped as returning would.
1779 : // Note: This is only needed for interpreted frames that have been
1780 : // materialized by the deoptimizer. If there is a handler frame
1781 : // in between then {frame->sp()} would already be correct.
1782 : Address return_sp = frame->fp() -
1783 816291 : InterpreterFrameConstants::kFixedFrameSizeFromFp -
1784 1632582 : register_slots * kSystemPointerSize;
1785 :
1786 : // Patch the bytecode offset in the interpreted frame to reflect the
1787 : // position of the exception handler. The special builtin below will
1788 : // take care of continuing to dispatch at that position. Also restore
1789 : // the correct context for the handler from the interpreter register.
1790 : Context context =
1791 816291 : Context::cast(js_frame->ReadInterpreterRegister(context_reg));
1792 816291 : js_frame->PatchBytecodeOffset(static_cast<int>(offset));
1793 :
1794 : Code code =
1795 816291 : builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
1796 : return FoundHandler(context, code->InstructionStart(), 0,
1797 1632582 : code->constant_pool(), return_sp, frame->fp());
1798 : }
1799 :
1800 : case StackFrame::BUILTIN:
1801 : // For builtin frames we are guaranteed not to find a handler.
1802 0 : if (catchable_by_js) {
1803 0 : CHECK_EQ(-1,
1804 : JavaScriptFrame::cast(frame)->LookupExceptionHandlerInTable(
1805 : nullptr, nullptr));
1806 : }
1807 : break;
1808 :
1809 : case StackFrame::WASM_INTERPRETER_ENTRY: {
1810 3374 : if (trap_handler::IsThreadInWasm()) {
1811 : trap_handler::ClearThreadInWasm();
1812 : }
1813 : } break;
1814 :
1815 : case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH: {
1816 : // Builtin continuation frames with catch can handle exceptions.
1817 8 : if (!catchable_by_js) break;
1818 : JavaScriptBuiltinContinuationWithCatchFrame* js_frame =
1819 : JavaScriptBuiltinContinuationWithCatchFrame::cast(frame);
1820 8 : js_frame->SetException(exception);
1821 :
1822 : // Reconstruct the stack pointer from the frame pointer.
1823 8 : Address return_sp = js_frame->fp() - js_frame->GetSPToFPDelta();
1824 8 : Code code = js_frame->LookupCode();
1825 : return FoundHandler(Context(), code->InstructionStart(), 0,
1826 8 : code->constant_pool(), return_sp, frame->fp());
1827 : } break;
1828 :
1829 : default:
1830 : // All other types can not handle exception.
1831 : break;
1832 : }
1833 :
1834 21534940 : if (frame->is_optimized()) {
1835 : // Remove per-frame stored materialized objects.
1836 3001846 : bool removed = materialized_object_store_->Remove(frame->fp());
1837 : USE(removed);
1838 : // If there were any materialized objects, the code should be
1839 : // marked for deopt.
1840 : DCHECK_IMPLIES(removed, frame->LookupCode()->marked_for_deoptimization());
1841 : }
1842 : }
1843 :
1844 : UNREACHABLE();
1845 : }
1846 :
1847 : namespace {
1848 310340 : HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) {
1849 : HandlerTable::CatchPrediction prediction;
1850 620680 : if (frame->is_optimized()) {
1851 45542 : if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) {
1852 : // This optimized frame will catch. It's handler table does not include
1853 : // exception prediction, and we need to use the corresponding handler
1854 : // tables on the unoptimized code objects.
1855 101 : std::vector<FrameSummary> summaries;
1856 1366 : frame->Summarize(&summaries);
1857 1582 : for (size_t i = summaries.size(); i != 0; i--) {
1858 1373 : const FrameSummary& summary = summaries[i - 1];
1859 : Handle<AbstractCode> code = summary.AsJavaScript().abstract_code();
1860 1875 : if (code->IsCode() && code->kind() == AbstractCode::BUILTIN) {
1861 502 : prediction = code->GetCode()->GetBuiltinCatchPrediction();
1862 610 : if (prediction == HandlerTable::UNCAUGHT) continue;
1863 1265 : return prediction;
1864 : }
1865 :
1866 : // Must have been constructed from a bytecode array.
1867 871 : CHECK_EQ(AbstractCode::INTERPRETED_FUNCTION, code->kind());
1868 871 : int code_offset = summary.code_offset();
1869 871 : HandlerTable table(code->GetBytecodeArray());
1870 871 : int index = table.LookupRange(code_offset, nullptr, &prediction);
1871 871 : if (index <= 0) continue;
1872 864 : if (prediction == HandlerTable::UNCAUGHT) continue;
1873 : return prediction;
1874 : }
1875 : }
1876 264798 : } else if (frame->LookupExceptionHandlerInTable(nullptr, &prediction) > 0) {
1877 6149 : return prediction;
1878 : }
1879 : return HandlerTable::UNCAUGHT;
1880 : }
1881 :
1882 159666 : Isolate::CatchType ToCatchType(HandlerTable::CatchPrediction prediction) {
1883 159666 : switch (prediction) {
1884 : case HandlerTable::UNCAUGHT:
1885 : return Isolate::NOT_CAUGHT;
1886 : case HandlerTable::CAUGHT:
1887 2429 : return Isolate::CAUGHT_BY_JAVASCRIPT;
1888 : case HandlerTable::PROMISE:
1889 1261 : return Isolate::CAUGHT_BY_PROMISE;
1890 : case HandlerTable::DESUGARING:
1891 0 : return Isolate::CAUGHT_BY_DESUGARING;
1892 : case HandlerTable::ASYNC_AWAIT:
1893 2102 : return Isolate::CAUGHT_BY_ASYNC_AWAIT;
1894 : default:
1895 0 : UNREACHABLE();
1896 : }
1897 : }
1898 : } // anonymous namespace
1899 :
1900 6283 : Isolate::CatchType Isolate::PredictExceptionCatcher() {
1901 : Address external_handler = thread_local_top()->try_catch_handler_address();
1902 6283 : if (IsExternalHandlerOnTop(Object())) return CAUGHT_BY_EXTERNAL;
1903 :
1904 : // Search for an exception handler by performing a full walk over the stack.
1905 172786 : for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) {
1906 : StackFrame* frame = iter.frame();
1907 :
1908 172454 : switch (frame->type()) {
1909 : case StackFrame::ENTRY:
1910 : case StackFrame::CONSTRUCT_ENTRY: {
1911 : Address entry_handler = frame->top_handler()->next_address();
1912 : // The exception has been externally caught if and only if there is an
1913 : // external handler which is on top of the top-most JS_ENTRY handler.
1914 857 : if (external_handler != kNullAddress &&
1915 351 : !try_catch_handler()->is_verbose_) {
1916 256 : if (entry_handler == kNullAddress ||
1917 128 : entry_handler > external_handler) {
1918 : return CAUGHT_BY_EXTERNAL;
1919 : }
1920 : }
1921 : } break;
1922 :
1923 : // For JavaScript frames we perform a lookup in the handler table.
1924 : case StackFrame::OPTIMIZED:
1925 : case StackFrame::INTERPRETED:
1926 : case StackFrame::BUILTIN: {
1927 : JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
1928 158756 : Isolate::CatchType prediction = ToCatchType(PredictException(js_frame));
1929 158756 : if (prediction == NOT_CAUGHT) break;
1930 : return prediction;
1931 : } break;
1932 :
1933 : case StackFrame::STUB: {
1934 5296 : Handle<Code> code(frame->LookupCode(), this);
1935 11502 : if (!code->IsCode() || code->kind() != Code::BUILTIN ||
1936 7116 : !code->has_handler_table() || !code->is_turbofanned()) {
1937 : break;
1938 : }
1939 :
1940 910 : CatchType prediction = ToCatchType(code->GetBuiltinCatchPrediction());
1941 910 : if (prediction != NOT_CAUGHT) return prediction;
1942 : } break;
1943 :
1944 : case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH: {
1945 0 : Handle<Code> code(frame->LookupCode(), this);
1946 0 : CatchType prediction = ToCatchType(code->GetBuiltinCatchPrediction());
1947 0 : if (prediction != NOT_CAUGHT) return prediction;
1948 : } break;
1949 :
1950 : default:
1951 : // All other types can not handle exception.
1952 : break;
1953 : }
1954 : }
1955 :
1956 : // Handler not found.
1957 332 : return NOT_CAUGHT;
1958 : }
1959 :
1960 5 : Object Isolate::ThrowIllegalOperation() {
1961 5 : if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
1962 5 : return Throw(ReadOnlyRoots(heap()).illegal_access_string());
1963 : }
1964 :
1965 30127 : void Isolate::ScheduleThrow(Object exception) {
1966 : // When scheduling a throw we first throw the exception to get the
1967 : // error reporting if it is uncaught before rescheduling it.
1968 30127 : Throw(exception);
1969 30127 : PropagatePendingExceptionToExternalTryCatch();
1970 30127 : if (has_pending_exception()) {
1971 30127 : thread_local_top()->scheduled_exception_ = pending_exception();
1972 30127 : thread_local_top()->external_caught_exception_ = false;
1973 : clear_pending_exception();
1974 : }
1975 30127 : }
1976 :
1977 121 : void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) {
1978 : DCHECK(handler == try_catch_handler());
1979 : DCHECK(handler->HasCaught());
1980 : DCHECK(handler->rethrow_);
1981 : DCHECK(handler->capture_message_);
1982 121 : Object message(reinterpret_cast<Address>(handler->message_obj_));
1983 : DCHECK(message->IsJSMessageObject() || message->IsTheHole(this));
1984 121 : thread_local_top()->pending_message_obj_ = message;
1985 121 : }
1986 :
1987 :
1988 273 : void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) {
1989 : DCHECK(has_scheduled_exception());
1990 546 : if (reinterpret_cast<void*>(scheduled_exception().ptr()) ==
1991 273 : handler->exception_) {
1992 : DCHECK_NE(scheduled_exception(),
1993 : ReadOnlyRoots(heap()).termination_exception());
1994 : clear_scheduled_exception();
1995 : } else {
1996 : DCHECK_EQ(scheduled_exception(),
1997 : ReadOnlyRoots(heap()).termination_exception());
1998 : // Clear termination once we returned from all V8 frames.
1999 183 : if (handle_scope_implementer()->CallDepthIsZero()) {
2000 133 : thread_local_top()->external_caught_exception_ = false;
2001 : clear_scheduled_exception();
2002 : }
2003 : }
2004 546 : if (reinterpret_cast<void*>(thread_local_top()->pending_message_obj_.ptr()) ==
2005 273 : handler->message_obj_) {
2006 : clear_pending_message();
2007 : }
2008 273 : }
2009 :
2010 31273 : Object Isolate::PromoteScheduledException() {
2011 : Object thrown = scheduled_exception();
2012 : clear_scheduled_exception();
2013 : // Re-throw the exception to avoid getting repeated error reporting.
2014 31273 : return ReThrow(thrown);
2015 : }
2016 :
2017 0 : void Isolate::PrintCurrentStackTrace(FILE* out) {
2018 0 : IncrementalStringBuilder builder(this);
2019 0 : for (StackTraceFrameIterator it(this); !it.done(); it.Advance()) {
2020 0 : if (!it.is_javascript()) continue;
2021 :
2022 : HandleScope scope(this);
2023 : JavaScriptFrame* frame = it.javascript_frame();
2024 :
2025 0 : Handle<Object> receiver(frame->receiver(), this);
2026 0 : Handle<JSFunction> function(frame->function(), this);
2027 : Handle<AbstractCode> code;
2028 : int offset;
2029 0 : if (frame->is_interpreted()) {
2030 : InterpretedFrame* interpreted_frame = InterpretedFrame::cast(frame);
2031 0 : code = handle(AbstractCode::cast(interpreted_frame->GetBytecodeArray()),
2032 : this);
2033 0 : offset = interpreted_frame->GetBytecodeOffset();
2034 : } else {
2035 0 : code = handle(AbstractCode::cast(frame->LookupCode()), this);
2036 0 : offset = static_cast<int>(frame->pc() - code->InstructionStart());
2037 : }
2038 :
2039 : // To preserve backwards compatiblity, only append a newline when
2040 : // the current stringified frame actually has characters.
2041 0 : const int old_length = builder.Length();
2042 0 : JSStackFrame site(this, receiver, function, code, offset);
2043 0 : site.ToString(builder);
2044 0 : if (old_length != builder.Length()) builder.AppendCharacter('\n');
2045 : }
2046 :
2047 0 : Handle<String> stack_trace = builder.Finish().ToHandleChecked();
2048 0 : stack_trace->PrintOn(out);
2049 0 : }
2050 :
2051 979927 : bool Isolate::ComputeLocation(MessageLocation* target) {
2052 979927 : StackTraceFrameIterator it(this);
2053 979927 : if (it.done()) return false;
2054 : StandardFrame* frame = it.frame();
2055 : // Compute the location from the function and the relocation info of the
2056 : // baseline code. For optimized code this will use the deoptimization
2057 : // information to get canonical location information.
2058 972198 : std::vector<FrameSummary> frames;
2059 1944396 : wasm::WasmCodeRefScope code_ref_scope;
2060 972198 : frame->Summarize(&frames);
2061 : FrameSummary& summary = frames.back();
2062 972198 : summary.EnsureSourcePositionsAvailable();
2063 972198 : int pos = summary.SourcePosition();
2064 : Handle<SharedFunctionInfo> shared;
2065 972198 : Handle<Object> script = summary.script();
2066 1944008 : if (!script->IsScript() ||
2067 : (Script::cast(*script)->source()->IsUndefined(this))) {
2068 : return false;
2069 : }
2070 :
2071 971810 : if (summary.IsJavaScript()) {
2072 822349 : shared = handle(summary.AsJavaScript().function()->shared(), this);
2073 : }
2074 971810 : *target = MessageLocation(Handle<Script>::cast(script), pos, pos + 1, shared);
2075 971810 : return true;
2076 : }
2077 :
2078 4564 : bool Isolate::ComputeLocationFromException(MessageLocation* target,
2079 : Handle<Object> exception) {
2080 4564 : if (!exception->IsJSObject()) return false;
2081 :
2082 : Handle<Name> start_pos_symbol = factory()->error_start_pos_symbol();
2083 : Handle<Object> start_pos = JSReceiver::GetDataProperty(
2084 2666 : Handle<JSObject>::cast(exception), start_pos_symbol);
2085 2666 : if (!start_pos->IsSmi()) return false;
2086 : int start_pos_value = Handle<Smi>::cast(start_pos)->value();
2087 :
2088 : Handle<Name> end_pos_symbol = factory()->error_end_pos_symbol();
2089 : Handle<Object> end_pos = JSReceiver::GetDataProperty(
2090 15 : Handle<JSObject>::cast(exception), end_pos_symbol);
2091 15 : if (!end_pos->IsSmi()) return false;
2092 : int end_pos_value = Handle<Smi>::cast(end_pos)->value();
2093 :
2094 : Handle<Name> script_symbol = factory()->error_script_symbol();
2095 : Handle<Object> script = JSReceiver::GetDataProperty(
2096 15 : Handle<JSObject>::cast(exception), script_symbol);
2097 15 : if (!script->IsScript()) return false;
2098 :
2099 : Handle<Script> cast_script(Script::cast(*script), this);
2100 15 : *target = MessageLocation(cast_script, start_pos_value, end_pos_value);
2101 15 : return true;
2102 : }
2103 :
2104 :
2105 4585 : bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
2106 : Handle<Object> exception) {
2107 4585 : if (!exception->IsJSObject()) return false;
2108 : Handle<Name> key = factory()->stack_trace_symbol();
2109 : Handle<Object> property =
2110 2687 : JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key);
2111 2687 : if (!property->IsFixedArray()) return false;
2112 :
2113 : Handle<FrameArray> elements = Handle<FrameArray>::cast(property);
2114 :
2115 : const int frame_count = elements->FrameCount();
2116 3398 : for (int i = 0; i < frame_count; i++) {
2117 1824 : if (elements->IsWasmFrame(i) || elements->IsAsmJsWasmFrame(i)) {
2118 : Handle<WasmInstanceObject> instance(elements->WasmInstance(i), this);
2119 : uint32_t func_index =
2120 48 : static_cast<uint32_t>(elements->WasmFunctionIndex(i)->value());
2121 : int code_offset = elements->Offset(i)->value();
2122 : bool is_at_number_conversion =
2123 48 : elements->IsAsmJsWasmFrame(i) &&
2124 0 : elements->Flags(i)->value() & FrameArray::kAsmJsAtNumberConversion;
2125 : // WasmCode* held alive by the {GlobalWasmCodeRef}.
2126 : wasm::WasmCode* code =
2127 : Managed<wasm::GlobalWasmCodeRef>::cast(elements->WasmCodeObject(i))
2128 : ->get()
2129 : ->code();
2130 : int byte_offset =
2131 : FrameSummary::WasmCompiledFrameSummary::GetWasmSourcePosition(
2132 48 : code, code_offset);
2133 48 : int pos = WasmModuleObject::GetSourcePosition(
2134 : handle(instance->module_object(), this), func_index, byte_offset,
2135 48 : is_at_number_conversion);
2136 : Handle<Script> script(instance->module_object()->script(), this);
2137 :
2138 48 : *target = MessageLocation(script, pos, pos + 1);
2139 : return true;
2140 : }
2141 :
2142 : Handle<JSFunction> fun = handle(elements->Function(i), this);
2143 1276 : if (!fun->shared()->IsSubjectToDebugging()) continue;
2144 :
2145 500 : Object script = fun->shared()->script();
2146 1000 : if (script->IsScript() &&
2147 : !(Script::cast(script)->source()->IsUndefined(this))) {
2148 500 : Handle<SharedFunctionInfo> shared = handle(fun->shared(), this);
2149 500 : SharedFunctionInfo::EnsureSourcePositionsAvailable(this, shared);
2150 500 : AbstractCode abstract_code = elements->Code(i);
2151 : const int code_offset = elements->Offset(i)->value();
2152 500 : const int pos = abstract_code->SourcePosition(code_offset);
2153 :
2154 : Handle<Script> casted_script(Script::cast(script), this);
2155 500 : *target = MessageLocation(casted_script, pos, pos + 1);
2156 : return true;
2157 : }
2158 : }
2159 : return false;
2160 : }
2161 :
2162 :
2163 1362988 : Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception,
2164 : MessageLocation* location) {
2165 : Handle<FixedArray> stack_trace_object;
2166 1362988 : if (capture_stack_trace_for_uncaught_exceptions_) {
2167 452 : if (exception->IsJSError()) {
2168 : // We fetch the stack trace that corresponds to this error object.
2169 : // If the lookup fails, the exception is probably not a valid Error
2170 : // object. In that case, we fall through and capture the stack trace
2171 : // at this throw site.
2172 : stack_trace_object =
2173 271 : GetDetailedStackTrace(Handle<JSObject>::cast(exception));
2174 : }
2175 452 : if (stack_trace_object.is_null()) {
2176 : // Not an error object, we capture stack and location at throw site.
2177 : stack_trace_object = CaptureCurrentStackTrace(
2178 : stack_trace_for_uncaught_exceptions_frame_limit_,
2179 186 : stack_trace_for_uncaught_exceptions_options_);
2180 : }
2181 : }
2182 1362988 : MessageLocation computed_location;
2183 2730540 : if (location == nullptr &&
2184 9113 : (ComputeLocationFromException(&computed_location, exception) ||
2185 8586 : ComputeLocationFromStackTrace(&computed_location, exception) ||
2186 4037 : ComputeLocation(&computed_location))) {
2187 : location = &computed_location;
2188 : }
2189 :
2190 : return MessageHandler::MakeMessageObject(
2191 : this, MessageTemplate::kUncaughtException, location, exception,
2192 1362988 : stack_trace_object);
2193 : }
2194 :
2195 0 : bool Isolate::IsJavaScriptHandlerOnTop(Object exception) {
2196 : DCHECK_NE(ReadOnlyRoots(heap()).the_hole_value(), exception);
2197 :
2198 : // For uncatchable exceptions, the JavaScript handler cannot be on top.
2199 170847 : if (!is_catchable_by_javascript(exception)) return false;
2200 :
2201 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
2202 : Address entry_handler = Isolate::handler(thread_local_top());
2203 166613 : if (entry_handler == kNullAddress) return false;
2204 :
2205 : // Get the address of the external handler so we can compare the address to
2206 : // determine which one is closer to the top of the stack.
2207 : Address external_handler = thread_local_top()->try_catch_handler_address();
2208 148266 : if (external_handler == kNullAddress) return true;
2209 :
2210 : // The exception has been externally caught if and only if there is an
2211 : // external handler which is on top of the top-most JS_ENTRY handler.
2212 : //
2213 : // Note, that finally clauses would re-throw an exception unless it's aborted
2214 : // by jumps in control flow (like return, break, etc.) and we'll have another
2215 : // chance to set proper v8::TryCatch later.
2216 146898 : return (entry_handler < external_handler);
2217 : }
2218 :
2219 0 : bool Isolate::IsExternalHandlerOnTop(Object exception) {
2220 : DCHECK_NE(ReadOnlyRoots(heap()).the_hole_value(), exception);
2221 :
2222 : // Get the address of the external handler so we can compare the address to
2223 : // determine which one is closer to the top of the stack.
2224 : Address external_handler = thread_local_top()->try_catch_handler_address();
2225 53403 : if (external_handler == kNullAddress) return false;
2226 :
2227 : // For uncatchable exceptions, the external handler is always on top.
2228 46464 : if (!is_catchable_by_javascript(exception)) return true;
2229 :
2230 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
2231 : Address entry_handler = Isolate::handler(thread_local_top());
2232 43170 : if (entry_handler == kNullAddress) return true;
2233 :
2234 : // The exception has been externally caught if and only if there is an
2235 : // external handler which is on top of the top-most JS_ENTRY handler.
2236 : //
2237 : // Note, that finally clauses would re-throw an exception unless it's aborted
2238 : // by jumps in control flow (like return, break, etc.) and we'll have another
2239 : // chance to set proper v8::TryCatch later.
2240 20338 : return (entry_handler > external_handler);
2241 : }
2242 :
2243 15478 : void Isolate::ReportPendingMessagesImpl(bool report_externally) {
2244 : Object exception = pending_exception();
2245 :
2246 : // Clear the pending message object early to avoid endless recursion.
2247 15478 : Object message_obj = thread_local_top()->pending_message_obj_;
2248 : clear_pending_message();
2249 :
2250 : // For uncatchable exceptions we do nothing. If needed, the exception and the
2251 : // message have already been propagated to v8::TryCatch.
2252 15478 : if (!is_catchable_by_javascript(exception)) return;
2253 :
2254 : // Determine whether the message needs to be reported to all message handlers
2255 : // depending on whether and external v8::TryCatch or an internal JavaScript
2256 : // handler is on top.
2257 : bool should_report_exception;
2258 12768 : if (report_externally) {
2259 : // Only report the exception if the external handler is verbose.
2260 11809 : should_report_exception = try_catch_handler()->is_verbose_;
2261 : } else {
2262 : // Report the exception if it isn't caught by JavaScript code.
2263 959 : should_report_exception = !IsJavaScriptHandlerOnTop(exception);
2264 : }
2265 :
2266 : // Actually report the pending message to all message handlers.
2267 12768 : if (!message_obj->IsTheHole(this) && should_report_exception) {
2268 : HandleScope scope(this);
2269 : Handle<JSMessageObject> message(JSMessageObject::cast(message_obj), this);
2270 : Handle<Script> script(message->script(), this);
2271 : int start_pos = message->start_position();
2272 : int end_pos = message->end_position();
2273 8112 : MessageLocation location(script, start_pos, end_pos);
2274 8112 : MessageHandler::ReportMessage(this, &location, message);
2275 : }
2276 : }
2277 :
2278 122789 : void Isolate::ReportPendingMessages() {
2279 : DCHECK(AllowExceptions::IsAllowed(this));
2280 :
2281 : // The embedder might run script in response to an exception.
2282 : AllowJavascriptExecutionDebugOnly allow_script(this);
2283 :
2284 : Object exception = pending_exception();
2285 :
2286 : // Try to propagate the exception to an external v8::TryCatch handler. If
2287 : // propagation was unsuccessful, then we will get another chance at reporting
2288 : // the pending message if the exception is re-thrown.
2289 122789 : bool has_been_propagated = PropagatePendingExceptionToExternalTryCatch();
2290 122789 : if (!has_been_propagated) return;
2291 :
2292 15478 : ReportPendingMessagesImpl(IsExternalHandlerOnTop(exception));
2293 : }
2294 :
2295 33 : void Isolate::ReportPendingMessagesFromJavaScript() {
2296 : DCHECK(AllowExceptions::IsAllowed(this));
2297 :
2298 : auto IsHandledByJavaScript = [=]() {
2299 : // In this situation, the exception is always a non-terminating exception.
2300 :
2301 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
2302 33 : Address entry_handler = Isolate::handler(thread_local_top());
2303 : DCHECK_NE(entry_handler, kNullAddress);
2304 : entry_handler = StackHandler::FromAddress(entry_handler)->next_address();
2305 :
2306 : // Get the address of the external handler so we can compare the address to
2307 : // determine which one is closer to the top of the stack.
2308 : Address external_handler = thread_local_top()->try_catch_handler_address();
2309 33 : if (external_handler == kNullAddress) return true;
2310 :
2311 33 : return (entry_handler < external_handler);
2312 : };
2313 :
2314 : auto IsHandledExternally = [=]() {
2315 0 : Address external_handler = thread_local_top()->try_catch_handler_address();
2316 0 : if (external_handler == kNullAddress) return false;
2317 :
2318 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
2319 : Address entry_handler = Isolate::handler(thread_local_top());
2320 : DCHECK_NE(entry_handler, kNullAddress);
2321 : entry_handler = StackHandler::FromAddress(entry_handler)->next_address();
2322 0 : return (entry_handler > external_handler);
2323 : };
2324 :
2325 33 : auto PropagateToExternalHandler = [=]() {
2326 33 : if (IsHandledByJavaScript()) {
2327 33 : thread_local_top()->external_caught_exception_ = false;
2328 33 : return false;
2329 : }
2330 :
2331 0 : if (!IsHandledExternally()) {
2332 0 : thread_local_top()->external_caught_exception_ = false;
2333 0 : return true;
2334 : }
2335 :
2336 0 : thread_local_top()->external_caught_exception_ = true;
2337 : v8::TryCatch* handler = try_catch_handler();
2338 : DCHECK(thread_local_top()->pending_message_obj_->IsJSMessageObject() ||
2339 : thread_local_top()->pending_message_obj_->IsTheHole(this));
2340 0 : handler->can_continue_ = true;
2341 0 : handler->has_terminated_ = false;
2342 0 : handler->exception_ = reinterpret_cast<void*>(pending_exception().ptr());
2343 : // Propagate to the external try-catch only if we got an actual message.
2344 0 : if (thread_local_top()->pending_message_obj_->IsTheHole(this)) return true;
2345 :
2346 : handler->message_obj_ =
2347 0 : reinterpret_cast<void*>(thread_local_top()->pending_message_obj_.ptr());
2348 0 : return true;
2349 33 : };
2350 :
2351 : // Try to propagate to an external v8::TryCatch handler.
2352 66 : if (!PropagateToExternalHandler()) return;
2353 :
2354 0 : ReportPendingMessagesImpl(true);
2355 : }
2356 :
2357 16972 : bool Isolate::OptionalRescheduleException(bool clear_exception) {
2358 : DCHECK(has_pending_exception());
2359 16972 : PropagatePendingExceptionToExternalTryCatch();
2360 :
2361 : bool is_termination_exception =
2362 : pending_exception() == ReadOnlyRoots(this).termination_exception();
2363 :
2364 16972 : if (is_termination_exception) {
2365 1524 : if (clear_exception) {
2366 1080 : thread_local_top()->external_caught_exception_ = false;
2367 : clear_pending_exception();
2368 1080 : return false;
2369 : }
2370 15448 : } else if (thread_local_top()->external_caught_exception_) {
2371 : // If the exception is externally caught, clear it if there are no
2372 : // JavaScript frames on the way to the C++ frame that has the
2373 : // external handler.
2374 : DCHECK_NE(thread_local_top()->try_catch_handler_address(), kNullAddress);
2375 : Address external_handler_address =
2376 : thread_local_top()->try_catch_handler_address();
2377 13301 : JavaScriptFrameIterator it(this);
2378 13301 : if (it.done() || (it.frame()->sp() > external_handler_address)) {
2379 : clear_exception = true;
2380 : }
2381 : }
2382 :
2383 : // Clear the exception if needed.
2384 15892 : if (clear_exception) {
2385 14398 : thread_local_top()->external_caught_exception_ = false;
2386 : clear_pending_exception();
2387 14398 : return false;
2388 : }
2389 :
2390 : // Reschedule the exception.
2391 1494 : thread_local_top()->scheduled_exception_ = pending_exception();
2392 : clear_pending_exception();
2393 1494 : return true;
2394 : }
2395 :
2396 17420 : void Isolate::PushPromise(Handle<JSObject> promise) {
2397 : ThreadLocalTop* tltop = thread_local_top();
2398 17420 : PromiseOnStack* prev = tltop->promise_on_stack_;
2399 : Handle<JSObject> global_promise = global_handles()->Create(*promise);
2400 34840 : tltop->promise_on_stack_ = new PromiseOnStack(global_promise, prev);
2401 17420 : }
2402 :
2403 :
2404 17440 : void Isolate::PopPromise() {
2405 : ThreadLocalTop* tltop = thread_local_top();
2406 17440 : if (tltop->promise_on_stack_ == nullptr) return;
2407 : PromiseOnStack* prev = tltop->promise_on_stack_->prev();
2408 : Handle<Object> global_promise = tltop->promise_on_stack_->promise();
2409 17420 : delete tltop->promise_on_stack_;
2410 17420 : tltop->promise_on_stack_ = prev;
2411 17420 : global_handles()->Destroy(global_promise.location());
2412 : }
2413 :
2414 : namespace {
2415 : bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
2416 : Handle<JSPromise> promise);
2417 :
2418 985 : bool PromiseHandlerCheck(Isolate* isolate, Handle<JSReceiver> handler,
2419 : Handle<JSReceiver> deferred_promise) {
2420 : // Recurse to the forwarding Promise, if any. This may be due to
2421 : // - await reaction forwarding to the throwaway Promise, which has
2422 : // a dependency edge to the outer Promise.
2423 : // - PromiseIdResolveHandler forwarding to the output of .then
2424 : // - Promise.all/Promise.race forwarding to a throwaway Promise, which
2425 : // has a dependency edge to the generated outer Promise.
2426 : // Otherwise, this is a real reject handler for the Promise.
2427 : Handle<Symbol> key = isolate->factory()->promise_forwarding_handler_symbol();
2428 985 : Handle<Object> forwarding_handler = JSReceiver::GetDataProperty(handler, key);
2429 985 : if (forwarding_handler->IsUndefined(isolate)) {
2430 : return true;
2431 : }
2432 :
2433 365 : if (!deferred_promise->IsJSPromise()) {
2434 : return true;
2435 : }
2436 :
2437 : return InternalPromiseHasUserDefinedRejectHandler(
2438 365 : isolate, Handle<JSPromise>::cast(deferred_promise));
2439 : }
2440 :
2441 4876 : bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
2442 : Handle<JSPromise> promise) {
2443 : // If this promise was marked as being handled by a catch block
2444 : // in an async function, then it has a user-defined reject handler.
2445 4876 : if (promise->handled_hint()) return true;
2446 :
2447 : // If this Promise is subsumed by another Promise (a Promise resolved
2448 : // with another Promise, or an intermediate, hidden, throwaway Promise
2449 : // within async/await), then recurse on the outer Promise.
2450 : // In this case, the dependency is one possible way that the Promise
2451 : // could be resolved, so it does not subsume the other following cases.
2452 : Handle<Symbol> key = isolate->factory()->promise_handled_by_symbol();
2453 4330 : Handle<Object> outer_promise_obj = JSObject::GetDataProperty(promise, key);
2454 5333 : if (outer_promise_obj->IsJSPromise() &&
2455 1003 : InternalPromiseHasUserDefinedRejectHandler(
2456 : isolate, Handle<JSPromise>::cast(outer_promise_obj))) {
2457 : return true;
2458 : }
2459 :
2460 3608 : if (promise->status() == Promise::kPending) {
2461 3797 : for (Handle<Object> current(promise->reactions(), isolate);
2462 : !current->IsSmi();) {
2463 : Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(current);
2464 : Handle<HeapObject> promise_or_capability(
2465 : reaction->promise_or_capability(), isolate);
2466 1076 : if (!promise_or_capability->IsUndefined(isolate)) {
2467 : Handle<JSPromise> promise = Handle<JSPromise>::cast(
2468 : promise_or_capability->IsJSPromise()
2469 : ? promise_or_capability
2470 : : handle(Handle<PromiseCapability>::cast(promise_or_capability)
2471 : ->promise(),
2472 1076 : isolate));
2473 1076 : if (reaction->reject_handler()->IsUndefined(isolate)) {
2474 91 : if (InternalPromiseHasUserDefinedRejectHandler(isolate, promise)) {
2475 : return true;
2476 : }
2477 : } else {
2478 : Handle<JSReceiver> current_handler(
2479 : JSReceiver::cast(reaction->reject_handler()), isolate);
2480 985 : if (PromiseHandlerCheck(isolate, current_handler, promise)) {
2481 805 : return true;
2482 : }
2483 : }
2484 : }
2485 : current = handle(reaction->next(), isolate);
2486 : }
2487 : }
2488 :
2489 : return false;
2490 : }
2491 :
2492 : } // namespace
2493 :
2494 3417 : bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) {
2495 3417 : if (!promise->IsJSPromise()) return false;
2496 : return InternalPromiseHasUserDefinedRejectHandler(
2497 3417 : this, Handle<JSPromise>::cast(promise));
2498 : }
2499 :
2500 4206 : Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
2501 : Handle<Object> undefined = factory()->undefined_value();
2502 : ThreadLocalTop* tltop = thread_local_top();
2503 4206 : if (tltop->promise_on_stack_ == nullptr) return undefined;
2504 : // Find the top-most try-catch or try-finally handler.
2505 1593 : CatchType prediction = PredictExceptionCatcher();
2506 1593 : if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) {
2507 5 : return undefined;
2508 : }
2509 : Handle<Object> retval = undefined;
2510 1588 : PromiseOnStack* promise_on_stack = tltop->promise_on_stack_;
2511 156672 : for (StackFrameIterator it(this); !it.done(); it.Advance()) {
2512 : StackFrame* frame = it.frame();
2513 : HandlerTable::CatchPrediction catch_prediction;
2514 156262 : if (frame->is_java_script()) {
2515 151584 : catch_prediction = PredictException(JavaScriptFrame::cast(frame));
2516 4678 : } else if (frame->type() == StackFrame::STUB) {
2517 1621 : Code code = frame->LookupCode();
2518 3650 : if (!code->IsCode() || code->kind() != Code::BUILTIN ||
2519 2437 : !code->has_handler_table() || !code->is_turbofanned()) {
2520 1213 : continue;
2521 : }
2522 408 : catch_prediction = code->GetBuiltinCatchPrediction();
2523 : } else {
2524 : continue;
2525 : }
2526 :
2527 151992 : switch (catch_prediction) {
2528 : case HandlerTable::UNCAUGHT:
2529 : continue;
2530 : case HandlerTable::CAUGHT:
2531 : case HandlerTable::DESUGARING:
2532 462 : if (retval->IsJSPromise()) {
2533 : // Caught the result of an inner async/await invocation.
2534 : // Mark the inner promise as caught in the "synchronous case" so
2535 : // that Debug::OnException will see. In the synchronous case,
2536 : // namely in the code in an async function before the first
2537 : // await, the function which has this exception event has not yet
2538 : // returned, so the generated Promise has not yet been marked
2539 : // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol.
2540 325 : Handle<JSPromise>::cast(retval)->set_handled_hint(true);
2541 : }
2542 462 : return retval;
2543 : case HandlerTable::PROMISE:
2544 : return promise_on_stack
2545 : ? Handle<Object>::cast(promise_on_stack->promise())
2546 482 : : undefined;
2547 : case HandlerTable::ASYNC_AWAIT: {
2548 : // If in the initial portion of async/await, continue the loop to pop up
2549 : // successive async/await stack frames until an asynchronous one with
2550 : // dependents is found, or a non-async stack frame is encountered, in
2551 : // order to handle the synchronous async/await catch prediction case:
2552 : // assume that async function calls are awaited.
2553 1474 : if (!promise_on_stack) return retval;
2554 : retval = promise_on_stack->promise();
2555 1474 : if (PromiseHasUserDefinedRejectHandler(retval)) {
2556 234 : return retval;
2557 : }
2558 : promise_on_stack = promise_on_stack->prev();
2559 1240 : continue;
2560 : }
2561 : }
2562 : }
2563 410 : return retval;
2564 : }
2565 :
2566 :
2567 1371 : void Isolate::SetCaptureStackTraceForUncaughtExceptions(
2568 : bool capture,
2569 : int frame_limit,
2570 : StackTrace::StackTraceOptions options) {
2571 1371 : capture_stack_trace_for_uncaught_exceptions_ = capture;
2572 1371 : stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
2573 1371 : stack_trace_for_uncaught_exceptions_options_ = options;
2574 1371 : }
2575 :
2576 :
2577 5 : void Isolate::SetAbortOnUncaughtExceptionCallback(
2578 : v8::Isolate::AbortOnUncaughtExceptionCallback callback) {
2579 5 : abort_on_uncaught_exception_callback_ = callback;
2580 5 : }
2581 :
2582 1537237 : bool Isolate::AreWasmThreadsEnabled(Handle<Context> context) {
2583 1537237 : if (wasm_threads_enabled_callback()) {
2584 42 : v8::Local<v8::Context> api_context = v8::Utils::ToLocal(context);
2585 42 : return wasm_threads_enabled_callback()(api_context);
2586 : }
2587 1537195 : return FLAG_experimental_wasm_threads;
2588 : }
2589 :
2590 4 : Handle<Context> Isolate::GetIncumbentContext() {
2591 4 : JavaScriptFrameIterator it(this);
2592 :
2593 : // 1st candidate: most-recently-entered author function's context
2594 : // if it's newer than the last Context::BackupIncumbentScope entry.
2595 : //
2596 : // NOTE: This code assumes that the stack grows downward.
2597 : Address top_backup_incumbent =
2598 : top_backup_incumbent_scope()
2599 : ? top_backup_incumbent_scope()->JSStackComparableAddress()
2600 4 : : 0;
2601 8 : if (!it.done() &&
2602 2 : (!top_backup_incumbent || it.frame()->sp() < top_backup_incumbent)) {
2603 4 : Context context = Context::cast(it.frame()->context());
2604 4 : return Handle<Context>(context->native_context(), this);
2605 : }
2606 :
2607 : // 2nd candidate: the last Context::Scope's incumbent context if any.
2608 0 : if (top_backup_incumbent_scope()) {
2609 : return Utils::OpenHandle(
2610 : *top_backup_incumbent_scope()->backup_incumbent_context_);
2611 : }
2612 :
2613 : // Last candidate: the entered context or microtask context.
2614 : // Given that there is no other author function is running, there must be
2615 : // no cross-context function running, then the incumbent realm must match
2616 : // the entry realm.
2617 : v8::Local<v8::Context> entered_context =
2618 0 : reinterpret_cast<v8::Isolate*>(this)->GetEnteredOrMicrotaskContext();
2619 : return Utils::OpenHandle(*entered_context);
2620 : }
2621 :
2622 32463 : char* Isolate::ArchiveThread(char* to) {
2623 : MemCopy(to, reinterpret_cast<char*>(thread_local_top()),
2624 : sizeof(ThreadLocalTop));
2625 : InitializeThreadLocal();
2626 : clear_pending_exception();
2627 : clear_pending_message();
2628 : clear_scheduled_exception();
2629 32463 : return to + sizeof(ThreadLocalTop);
2630 : }
2631 :
2632 :
2633 32463 : char* Isolate::RestoreThread(char* from) {
2634 : MemCopy(reinterpret_cast<char*>(thread_local_top()), from,
2635 : sizeof(ThreadLocalTop));
2636 : // This might be just paranoia, but it seems to be needed in case a
2637 : // thread_local_top_ is restored on a separate OS thread.
2638 : #ifdef USE_SIMULATOR
2639 : thread_local_top()->simulator_ = Simulator::current(this);
2640 : #endif
2641 : DCHECK(context().is_null() || context()->IsContext());
2642 32463 : return from + sizeof(ThreadLocalTop);
2643 : }
2644 :
2645 62406 : void Isolate::ReleaseSharedPtrs() {
2646 62406 : base::MutexGuard lock(&managed_ptr_destructors_mutex_);
2647 74274 : while (managed_ptr_destructors_head_) {
2648 : ManagedPtrDestructor* l = managed_ptr_destructors_head_;
2649 : ManagedPtrDestructor* n = nullptr;
2650 11867 : managed_ptr_destructors_head_ = nullptr;
2651 851555 : for (; l != nullptr; l = n) {
2652 419844 : l->destructor_(l->shared_ptr_ptr_);
2653 419844 : n = l->next_;
2654 419844 : delete l;
2655 : }
2656 : }
2657 62407 : }
2658 :
2659 3118201 : void Isolate::RegisterManagedPtrDestructor(ManagedPtrDestructor* destructor) {
2660 3118201 : base::MutexGuard lock(&managed_ptr_destructors_mutex_);
2661 : DCHECK_NULL(destructor->prev_);
2662 : DCHECK_NULL(destructor->next_);
2663 3118202 : if (managed_ptr_destructors_head_) {
2664 3105130 : managed_ptr_destructors_head_->prev_ = destructor;
2665 : }
2666 3118202 : destructor->next_ = managed_ptr_destructors_head_;
2667 3118202 : managed_ptr_destructors_head_ = destructor;
2668 3118202 : }
2669 :
2670 2698358 : void Isolate::UnregisterManagedPtrDestructor(ManagedPtrDestructor* destructor) {
2671 2698358 : base::MutexGuard lock(&managed_ptr_destructors_mutex_);
2672 2698358 : if (destructor->prev_) {
2673 2689452 : destructor->prev_->next_ = destructor->next_;
2674 : } else {
2675 : DCHECK_EQ(destructor, managed_ptr_destructors_head_);
2676 8906 : managed_ptr_destructors_head_ = destructor->next_;
2677 : }
2678 2698358 : if (destructor->next_) destructor->next_->prev_ = destructor->prev_;
2679 2698358 : destructor->prev_ = nullptr;
2680 2698358 : destructor->next_ = nullptr;
2681 2698358 : }
2682 :
2683 62422 : void Isolate::SetWasmEngine(std::shared_ptr<wasm::WasmEngine> engine) {
2684 : DCHECK_NULL(wasm_engine_); // Only call once before {Init}.
2685 : wasm_engine_ = std::move(engine);
2686 62422 : wasm_engine_->AddIsolate(this);
2687 62422 : }
2688 :
2689 : // NOLINTNEXTLINE
2690 67942 : Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
2691 : #if defined(USE_SIMULATOR)
2692 : delete simulator_;
2693 : #endif
2694 0 : }
2695 :
2696 0 : Isolate::PerIsolateThreadData* Isolate::ThreadDataTable::Lookup(
2697 : ThreadId thread_id) {
2698 : auto t = table_.find(thread_id);
2699 369643 : if (t == table_.end()) return nullptr;
2700 295648 : return t->second;
2701 : }
2702 :
2703 :
2704 67956 : void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
2705 135911 : bool inserted = table_.insert(std::make_pair(data->thread_id_, data)).second;
2706 67955 : CHECK(inserted);
2707 67955 : }
2708 :
2709 :
2710 0 : void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
2711 500 : table_.erase(data->thread_id_);
2712 1000 : delete data;
2713 0 : }
2714 :
2715 62407 : void Isolate::ThreadDataTable::RemoveAllThreads() {
2716 129849 : for (auto& x : table_) {
2717 134884 : delete x.second;
2718 : }
2719 : table_.clear();
2720 62407 : }
2721 :
2722 0 : class VerboseAccountingAllocator : public AccountingAllocator {
2723 : public:
2724 : VerboseAccountingAllocator(Heap* heap, size_t allocation_sample_bytes)
2725 0 : : heap_(heap), allocation_sample_bytes_(allocation_sample_bytes) {}
2726 :
2727 0 : v8::internal::Segment* AllocateSegment(size_t size) override {
2728 0 : v8::internal::Segment* memory = AccountingAllocator::AllocateSegment(size);
2729 0 : if (!memory) return nullptr;
2730 : size_t malloced_current = GetCurrentMemoryUsage();
2731 :
2732 0 : if (last_memory_usage_ + allocation_sample_bytes_ < malloced_current) {
2733 0 : PrintMemoryJSON(malloced_current);
2734 : last_memory_usage_ = malloced_current;
2735 : }
2736 : return memory;
2737 : }
2738 :
2739 0 : void ReturnSegment(v8::internal::Segment* memory) override {
2740 0 : AccountingAllocator::ReturnSegment(memory);
2741 : size_t malloced_current = GetCurrentMemoryUsage();
2742 :
2743 0 : if (malloced_current + allocation_sample_bytes_ < last_memory_usage_) {
2744 0 : PrintMemoryJSON(malloced_current);
2745 : last_memory_usage_ = malloced_current;
2746 : }
2747 0 : }
2748 :
2749 0 : void ZoneCreation(const Zone* zone) override {
2750 0 : PrintZoneModificationSample(zone, "zonecreation");
2751 : nesting_deepth_++;
2752 0 : }
2753 :
2754 0 : void ZoneDestruction(const Zone* zone) override {
2755 : nesting_deepth_--;
2756 0 : PrintZoneModificationSample(zone, "zonedestruction");
2757 0 : }
2758 :
2759 : private:
2760 0 : void PrintZoneModificationSample(const Zone* zone, const char* type) {
2761 : PrintF(
2762 : "{"
2763 : "\"type\": \"%s\", "
2764 : "\"isolate\": \"%p\", "
2765 : "\"time\": %f, "
2766 : "\"ptr\": \"%p\", "
2767 : "\"name\": \"%s\", "
2768 : "\"size\": %" PRIuS
2769 : ","
2770 : "\"nesting\": %zu}\n",
2771 0 : type, reinterpret_cast<void*>(heap_->isolate()),
2772 0 : heap_->isolate()->time_millis_since_init(),
2773 : reinterpret_cast<const void*>(zone), zone->name(),
2774 0 : zone->allocation_size(), nesting_deepth_.load());
2775 0 : }
2776 :
2777 0 : void PrintMemoryJSON(size_t malloced) {
2778 : // Note: Neither isolate, nor heap is locked, so be careful with accesses
2779 : // as the allocator is potentially used on a concurrent thread.
2780 0 : double time = heap_->isolate()->time_millis_since_init();
2781 : PrintF(
2782 : "{"
2783 : "\"type\": \"zone\", "
2784 : "\"isolate\": \"%p\", "
2785 : "\"time\": %f, "
2786 : "\"allocated\": %" PRIuS "}\n",
2787 0 : reinterpret_cast<void*>(heap_->isolate()), time, malloced);
2788 0 : }
2789 :
2790 : Heap* heap_;
2791 : std::atomic<size_t> last_memory_usage_{0};
2792 : std::atomic<size_t> nesting_deepth_{0};
2793 : size_t allocation_sample_bytes_;
2794 : };
2795 :
2796 : #ifdef DEBUG
2797 : std::atomic<size_t> Isolate::non_disposed_isolates_;
2798 : #endif // DEBUG
2799 :
2800 : // static
2801 62414 : Isolate* Isolate::New(IsolateAllocationMode mode) {
2802 : // IsolateAllocator allocates the memory for the Isolate object according to
2803 : // the given allocation mode.
2804 : std::unique_ptr<IsolateAllocator> isolate_allocator =
2805 62420 : base::make_unique<IsolateAllocator>(mode);
2806 : // Construct Isolate object in the allocated memory.
2807 : void* isolate_ptr = isolate_allocator->isolate_memory();
2808 62418 : Isolate* isolate = new (isolate_ptr) Isolate(std::move(isolate_allocator));
2809 : #if V8_TARGET_ARCH_64_BIT
2810 : DCHECK_IMPLIES(
2811 : mode == IsolateAllocationMode::kInV8Heap,
2812 : IsAligned(isolate->isolate_root(), kPtrComprIsolateRootAlignment));
2813 : #endif
2814 :
2815 : #ifdef DEBUG
2816 : non_disposed_isolates_++;
2817 : #endif // DEBUG
2818 :
2819 62420 : return isolate;
2820 : }
2821 :
2822 : // static
2823 62406 : void Isolate::Delete(Isolate* isolate) {
2824 : DCHECK_NOT_NULL(isolate);
2825 : // Temporarily set this isolate as current so that various parts of
2826 : // the isolate can access it in their destructors without having a
2827 : // direct pointer. We don't use Enter/Exit here to avoid
2828 : // initializing the thread data.
2829 : PerIsolateThreadData* saved_data = isolate->CurrentPerIsolateThreadData();
2830 : DCHECK_EQ(true, isolate_key_created_.load(std::memory_order_relaxed));
2831 : Isolate* saved_isolate = reinterpret_cast<Isolate*>(
2832 62407 : base::Thread::GetThreadLocal(isolate->isolate_key_));
2833 62407 : SetIsolateThreadLocals(isolate, nullptr);
2834 :
2835 62407 : isolate->Deinit();
2836 :
2837 : #ifdef DEBUG
2838 : non_disposed_isolates_--;
2839 : #endif // DEBUG
2840 :
2841 : // Take ownership of the IsolateAllocator to ensure the Isolate memory will
2842 : // be available during Isolate descructor call.
2843 : std::unique_ptr<IsolateAllocator> isolate_allocator =
2844 62406 : std::move(isolate->isolate_allocator_);
2845 62407 : isolate->~Isolate();
2846 : // Now free the memory owned by the allocator.
2847 62407 : isolate_allocator.reset();
2848 :
2849 : // Restore the previous current isolate.
2850 62407 : SetIsolateThreadLocals(saved_isolate, saved_data);
2851 62405 : }
2852 :
2853 63437 : v8::PageAllocator* Isolate::page_allocator() {
2854 63437 : return isolate_allocator_->page_allocator();
2855 : }
2856 :
2857 62418 : Isolate::Isolate(std::unique_ptr<i::IsolateAllocator> isolate_allocator)
2858 : : isolate_allocator_(std::move(isolate_allocator)),
2859 : id_(isolate_counter.fetch_add(1, std::memory_order_relaxed)),
2860 : stack_guard_(this),
2861 : allocator_(FLAG_trace_zone_stats
2862 : ? new VerboseAccountingAllocator(&heap_, 256 * KB)
2863 : : new AccountingAllocator()),
2864 : builtins_(this),
2865 : rail_mode_(PERFORMANCE_ANIMATION),
2866 : code_event_dispatcher_(new CodeEventDispatcher()),
2867 1123570 : cancelable_task_manager_(new CancelableTaskManager()) {
2868 : TRACE_ISOLATE(constructor);
2869 : CheckIsolateLayout();
2870 :
2871 : // ThreadManager is initialized early to support locking an isolate
2872 : // before it is entered.
2873 62418 : thread_manager_ = new ThreadManager(this);
2874 :
2875 : handle_scope_data_.Initialize();
2876 :
2877 : #define ISOLATE_INIT_EXECUTE(type, name, initial_value) \
2878 : name##_ = (initial_value);
2879 62420 : ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
2880 : #undef ISOLATE_INIT_EXECUTE
2881 :
2882 : #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \
2883 : memset(name##_, 0, sizeof(type) * length);
2884 249680 : ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
2885 : #undef ISOLATE_INIT_ARRAY_EXECUTE
2886 :
2887 62420 : InitializeLoggingAndCounters();
2888 62422 : debug_ = new Debug(this);
2889 :
2890 62421 : InitializeDefaultEmbeddedBlob();
2891 :
2892 62418 : MicrotaskQueue::SetUpDefaultMicrotaskQueue(this);
2893 62421 : }
2894 :
2895 0 : void Isolate::CheckIsolateLayout() {
2896 : CHECK_EQ(OFFSET_OF(Isolate, isolate_data_), 0);
2897 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, isolate_data_.embedder_data_)),
2898 : Internals::kIsolateEmbedderDataOffset);
2899 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, isolate_data_.roots_)),
2900 : Internals::kIsolateRootsOffset);
2901 : CHECK_EQ(Internals::kExternalMemoryOffset % 8, 0);
2902 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, isolate_data_.external_memory_)),
2903 : Internals::kExternalMemoryOffset);
2904 : CHECK_EQ(Internals::kExternalMemoryLimitOffset % 8, 0);
2905 : CHECK_EQ(static_cast<int>(
2906 : OFFSET_OF(Isolate, isolate_data_.external_memory_limit_)),
2907 : Internals::kExternalMemoryLimitOffset);
2908 : CHECK_EQ(Internals::kExternalMemoryAtLastMarkCompactOffset % 8, 0);
2909 : CHECK_EQ(static_cast<int>(OFFSET_OF(
2910 : Isolate, isolate_data_.external_memory_at_last_mark_compact_)),
2911 : Internals::kExternalMemoryAtLastMarkCompactOffset);
2912 0 : }
2913 :
2914 63663 : void Isolate::ClearSerializerData() {
2915 64177 : delete external_reference_map_;
2916 63663 : external_reference_map_ = nullptr;
2917 63663 : }
2918 :
2919 85804 : bool Isolate::LogObjectRelocation() {
2920 170294 : return FLAG_verify_predictable || logger()->is_logging() || is_profiling() ||
2921 169020 : heap()->isolate()->logger()->is_listening_to_code_events() ||
2922 84505 : (heap_profiler() != nullptr &&
2923 170166 : heap_profiler()->is_tracking_object_moves()) ||
2924 85804 : heap()->has_heap_object_allocation_tracker();
2925 : }
2926 :
2927 62407 : void Isolate::Deinit() {
2928 : TRACE_ISOLATE(deinit);
2929 :
2930 : tracing_cpu_profiler_.reset();
2931 62407 : if (FLAG_stress_sampling_allocation_profiler > 0) {
2932 0 : heap_profiler()->StopSamplingHeapProfiler();
2933 : }
2934 :
2935 : #if defined(V8_OS_WIN_X64)
2936 : if (win64_unwindinfo::CanRegisterUnwindInfoForNonABICompliantCodeRange() &&
2937 : heap()->memory_allocator()) {
2938 : const base::AddressRegion& code_range =
2939 : heap()->memory_allocator()->code_range();
2940 : void* start = reinterpret_cast<void*>(code_range.begin());
2941 : win64_unwindinfo::UnregisterNonABICompliantCodeRange(start);
2942 : }
2943 : #endif
2944 :
2945 62407 : debug()->Unload();
2946 :
2947 62406 : wasm_engine()->DeleteCompileJobsOnIsolate(this);
2948 :
2949 62407 : if (concurrent_recompilation_enabled()) {
2950 62303 : optimizing_compile_dispatcher_->Stop();
2951 62302 : delete optimizing_compile_dispatcher_;
2952 62302 : optimizing_compile_dispatcher_ = nullptr;
2953 : }
2954 :
2955 62406 : wasm_engine()->memory_tracker()->DeleteSharedMemoryObjectsOnIsolate(this);
2956 :
2957 62407 : heap_.mark_compact_collector()->EnsureSweepingCompleted();
2958 62406 : heap_.memory_allocator()->unmapper()->EnsureUnmappingCompleted();
2959 :
2960 62406 : DumpAndResetStats();
2961 :
2962 62405 : if (FLAG_print_deopt_stress) {
2963 0 : PrintF(stdout, "=== Stress deopt counter: %u\n", stress_deopt_count_);
2964 : }
2965 :
2966 : // We must stop the logger before we tear down other components.
2967 62405 : sampler::Sampler* sampler = logger_->sampler();
2968 124751 : if (sampler && sampler->IsActive()) sampler->Stop();
2969 :
2970 : FreeThreadResources();
2971 62405 : logger_->StopProfilerThread();
2972 :
2973 : // We start with the heap tear down so that releasing managed objects does
2974 : // not cause a GC.
2975 62405 : heap_.StartTearDown();
2976 :
2977 62406 : ReleaseSharedPtrs();
2978 :
2979 62407 : delete deoptimizer_data_;
2980 62407 : deoptimizer_data_ = nullptr;
2981 62407 : builtins_.TearDown();
2982 62406 : bootstrapper_->TearDown();
2983 :
2984 62406 : if (runtime_profiler_ != nullptr) {
2985 62406 : delete runtime_profiler_;
2986 62406 : runtime_profiler_ = nullptr;
2987 : }
2988 :
2989 62406 : delete heap_profiler_;
2990 62405 : heap_profiler_ = nullptr;
2991 :
2992 62405 : compiler_dispatcher_->AbortAll();
2993 62406 : delete compiler_dispatcher_;
2994 62406 : compiler_dispatcher_ = nullptr;
2995 :
2996 : // This stops cancelable tasks (i.e. concurrent marking tasks)
2997 62406 : cancelable_task_manager()->CancelAndWait();
2998 :
2999 62406 : heap_.TearDown();
3000 62407 : logger_->TearDown();
3001 :
3002 62407 : if (wasm_engine_) {
3003 62407 : wasm_engine_->RemoveIsolate(this);
3004 : wasm_engine_.reset();
3005 : }
3006 :
3007 62407 : TearDownEmbeddedBlob();
3008 :
3009 62407 : delete interpreter_;
3010 62407 : interpreter_ = nullptr;
3011 :
3012 124814 : delete ast_string_constants_;
3013 62407 : ast_string_constants_ = nullptr;
3014 :
3015 : code_event_dispatcher_.reset();
3016 :
3017 79618 : delete root_index_map_;
3018 62407 : root_index_map_ = nullptr;
3019 :
3020 62407 : delete compiler_zone_;
3021 62407 : compiler_zone_ = nullptr;
3022 62407 : compiler_cache_ = nullptr;
3023 :
3024 62407 : ClearSerializerData();
3025 :
3026 : {
3027 62407 : base::MutexGuard lock_guard(&thread_data_table_mutex_);
3028 62407 : thread_data_table_.RemoveAllThreads();
3029 : }
3030 62407 : }
3031 :
3032 :
3033 552336 : void Isolate::SetIsolateThreadLocals(Isolate* isolate,
3034 : PerIsolateThreadData* data) {
3035 552336 : base::Thread::SetThreadLocal(isolate_key_, isolate);
3036 552296 : base::Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
3037 552282 : }
3038 :
3039 :
3040 374440 : Isolate::~Isolate() {
3041 : TRACE_ISOLATE(destructor);
3042 :
3043 : // The entry stack must be empty when we get here.
3044 : DCHECK(entry_stack_ == nullptr || entry_stack_->previous_item == nullptr);
3045 :
3046 62407 : delete entry_stack_;
3047 62407 : entry_stack_ = nullptr;
3048 :
3049 62407 : delete unicode_cache_;
3050 62407 : unicode_cache_ = nullptr;
3051 :
3052 62407 : delete date_cache_;
3053 62407 : date_cache_ = nullptr;
3054 :
3055 62407 : delete regexp_stack_;
3056 62407 : regexp_stack_ = nullptr;
3057 :
3058 62407 : delete descriptor_lookup_cache_;
3059 62407 : descriptor_lookup_cache_ = nullptr;
3060 :
3061 62407 : delete load_stub_cache_;
3062 62407 : load_stub_cache_ = nullptr;
3063 62407 : delete store_stub_cache_;
3064 62407 : store_stub_cache_ = nullptr;
3065 :
3066 124814 : delete materialized_object_store_;
3067 62407 : materialized_object_store_ = nullptr;
3068 :
3069 62407 : delete logger_;
3070 62407 : logger_ = nullptr;
3071 :
3072 62407 : delete handle_scope_implementer_;
3073 62407 : handle_scope_implementer_ = nullptr;
3074 :
3075 : delete code_tracer();
3076 : set_code_tracer(nullptr);
3077 :
3078 62407 : delete compilation_cache_;
3079 62407 : compilation_cache_ = nullptr;
3080 62407 : delete bootstrapper_;
3081 62407 : bootstrapper_ = nullptr;
3082 62407 : delete inner_pointer_to_code_cache_;
3083 62407 : inner_pointer_to_code_cache_ = nullptr;
3084 :
3085 62407 : delete thread_manager_;
3086 62407 : thread_manager_ = nullptr;
3087 :
3088 62407 : delete global_handles_;
3089 62407 : global_handles_ = nullptr;
3090 62407 : delete eternal_handles_;
3091 62407 : eternal_handles_ = nullptr;
3092 :
3093 62422 : delete string_stream_debug_object_cache_;
3094 62407 : string_stream_debug_object_cache_ = nullptr;
3095 :
3096 62407 : delete random_number_generator_;
3097 62407 : random_number_generator_ = nullptr;
3098 :
3099 62407 : delete fuzzer_rng_;
3100 62406 : fuzzer_rng_ = nullptr;
3101 :
3102 62406 : delete debug_;
3103 62406 : debug_ = nullptr;
3104 :
3105 62406 : delete cancelable_task_manager_;
3106 62406 : cancelable_task_manager_ = nullptr;
3107 :
3108 62406 : delete allocator_;
3109 62406 : allocator_ = nullptr;
3110 :
3111 : // Assert that |default_microtask_queue_| is the last MicrotaskQueue instance.
3112 : DCHECK_IMPLIES(default_microtask_queue_,
3113 : default_microtask_queue_ == default_microtask_queue_->next());
3114 62406 : delete default_microtask_queue_;
3115 62407 : default_microtask_queue_ = nullptr;
3116 62407 : }
3117 :
3118 94885 : void Isolate::InitializeThreadLocal() { thread_local_top()->Initialize(this); }
3119 :
3120 20 : void Isolate::SetTerminationOnExternalTryCatch() {
3121 1832 : if (try_catch_handler() == nullptr) return;
3122 1822 : try_catch_handler()->can_continue_ = false;
3123 1822 : try_catch_handler()->has_terminated_ = true;
3124 : try_catch_handler()->exception_ =
3125 1822 : reinterpret_cast<void*>(ReadOnlyRoots(heap()).null_value().ptr());
3126 : }
3127 :
3128 169888 : bool Isolate::PropagatePendingExceptionToExternalTryCatch() {
3129 : Object exception = pending_exception();
3130 :
3131 169888 : if (IsJavaScriptHandlerOnTop(exception)) {
3132 138246 : thread_local_top()->external_caught_exception_ = false;
3133 138246 : return false;
3134 : }
3135 :
3136 31642 : if (!IsExternalHandlerOnTop(exception)) {
3137 4492 : thread_local_top()->external_caught_exception_ = false;
3138 4492 : return true;
3139 : }
3140 :
3141 27150 : thread_local_top()->external_caught_exception_ = true;
3142 27150 : if (!is_catchable_by_javascript(exception)) {
3143 : SetTerminationOnExternalTryCatch();
3144 : } else {
3145 : v8::TryCatch* handler = try_catch_handler();
3146 : DCHECK(thread_local_top()->pending_message_obj_->IsJSMessageObject() ||
3147 : thread_local_top()->pending_message_obj_->IsTheHole(this));
3148 25338 : handler->can_continue_ = true;
3149 25338 : handler->has_terminated_ = false;
3150 25338 : handler->exception_ = reinterpret_cast<void*>(pending_exception().ptr());
3151 : // Propagate to the external try-catch only if we got an actual message.
3152 25338 : if (thread_local_top()->pending_message_obj_->IsTheHole(this)) return true;
3153 :
3154 : handler->message_obj_ =
3155 11218 : reinterpret_cast<void*>(thread_local_top()->pending_message_obj_.ptr());
3156 : }
3157 : return true;
3158 : }
3159 :
3160 62998 : bool Isolate::InitializeCounters() {
3161 62998 : if (async_counters_) return false;
3162 124841 : async_counters_ = std::make_shared<Counters>(this);
3163 62422 : return true;
3164 : }
3165 :
3166 63001 : void Isolate::InitializeLoggingAndCounters() {
3167 63001 : if (logger_ == nullptr) {
3168 62422 : logger_ = new Logger(this);
3169 : }
3170 62998 : InitializeCounters();
3171 63001 : }
3172 :
3173 : namespace {
3174 :
3175 56 : void CreateOffHeapTrampolines(Isolate* isolate) {
3176 : DCHECK_NOT_NULL(isolate->embedded_blob());
3177 : DCHECK_NE(0, isolate->embedded_blob_size());
3178 :
3179 : HandleScope scope(isolate);
3180 : Builtins* builtins = isolate->builtins();
3181 :
3182 56 : EmbeddedData d = EmbeddedData::FromBlob();
3183 :
3184 170408 : for (int i = 0; i < Builtins::builtin_count; i++) {
3185 : if (!Builtins::IsIsolateIndependent(i)) continue;
3186 :
3187 85176 : Address instruction_start = d.InstructionStartOfBuiltin(i);
3188 : Handle<Code> trampoline = isolate->factory()->NewOffHeapTrampolineFor(
3189 85176 : builtins->builtin_handle(i), instruction_start);
3190 :
3191 : // From this point onwards, the old builtin code object is unreachable and
3192 : // will be collected by the next GC.
3193 85176 : builtins->set_builtin(i, *trampoline);
3194 :
3195 85176 : if (isolate->logger()->is_listening_to_code_events() ||
3196 : isolate->is_profiling()) {
3197 0 : isolate->logger()->LogCodeObject(*trampoline);
3198 : }
3199 : }
3200 56 : }
3201 :
3202 : #ifdef DEBUG
3203 : bool IsolateIsCompatibleWithEmbeddedBlob(Isolate* isolate) {
3204 : if (!FLAG_embedded_builtins) return true;
3205 : EmbeddedData d = EmbeddedData::FromBlob(isolate);
3206 : return (d.IsolateHash() == isolate->HashIsolateForEmbeddedBlob());
3207 : }
3208 : #endif // DEBUG
3209 :
3210 : } // namespace
3211 :
3212 62421 : void Isolate::InitializeDefaultEmbeddedBlob() {
3213 : const uint8_t* blob = DefaultEmbeddedBlob();
3214 : uint32_t size = DefaultEmbeddedBlobSize();
3215 :
3216 : #ifdef V8_MULTI_SNAPSHOTS
3217 : if (!FLAG_untrusted_code_mitigations) {
3218 : blob = TrustedEmbeddedBlob();
3219 : size = TrustedEmbeddedBlobSize();
3220 : }
3221 : #endif
3222 :
3223 62421 : if (StickyEmbeddedBlob() != nullptr) {
3224 : base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
3225 : // Check again now that we hold the lock.
3226 55 : if (StickyEmbeddedBlob() != nullptr) {
3227 : blob = StickyEmbeddedBlob();
3228 : size = StickyEmbeddedBlobSize();
3229 55 : current_embedded_blob_refs_++;
3230 : }
3231 : }
3232 :
3233 62420 : if (blob == nullptr) {
3234 1 : CHECK_EQ(0, size);
3235 : } else {
3236 62419 : SetEmbeddedBlob(blob, size);
3237 : }
3238 62418 : }
3239 :
3240 56 : void Isolate::CreateAndSetEmbeddedBlob() {
3241 : base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
3242 :
3243 : PrepareBuiltinSourcePositionMap();
3244 :
3245 : // If a sticky blob has been set, we reuse it.
3246 56 : if (StickyEmbeddedBlob() != nullptr) {
3247 0 : CHECK_EQ(embedded_blob(), StickyEmbeddedBlob());
3248 0 : CHECK_EQ(CurrentEmbeddedBlob(), StickyEmbeddedBlob());
3249 : } else {
3250 : // Create and set a new embedded blob.
3251 : uint8_t* data;
3252 : uint32_t size;
3253 56 : InstructionStream::CreateOffHeapInstructionStream(this, &data, &size);
3254 :
3255 56 : CHECK_EQ(0, current_embedded_blob_refs_);
3256 56 : const uint8_t* const_data = const_cast<const uint8_t*>(data);
3257 56 : SetEmbeddedBlob(const_data, size);
3258 56 : current_embedded_blob_refs_++;
3259 :
3260 56 : SetStickyEmbeddedBlob(const_data, size);
3261 : }
3262 :
3263 56 : CreateOffHeapTrampolines(this);
3264 56 : }
3265 :
3266 62407 : void Isolate::TearDownEmbeddedBlob() {
3267 : // Nothing to do in case the blob is embedded into the binary or unset.
3268 62407 : if (StickyEmbeddedBlob() == nullptr) return;
3269 :
3270 111 : CHECK_EQ(embedded_blob(), StickyEmbeddedBlob());
3271 111 : CHECK_EQ(CurrentEmbeddedBlob(), StickyEmbeddedBlob());
3272 :
3273 : base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
3274 111 : current_embedded_blob_refs_--;
3275 111 : if (current_embedded_blob_refs_ == 0 && enable_embedded_blob_refcounting_) {
3276 : // We own the embedded blob and are the last holder. Free it.
3277 : InstructionStream::FreeOffHeapInstructionStream(
3278 0 : const_cast<uint8_t*>(embedded_blob()), embedded_blob_size());
3279 0 : ClearEmbeddedBlob();
3280 : }
3281 : }
3282 :
3283 1 : bool Isolate::InitWithoutSnapshot() { return Init(nullptr, nullptr); }
3284 :
3285 62309 : bool Isolate::InitWithSnapshot(ReadOnlyDeserializer* read_only_deserializer,
3286 : StartupDeserializer* startup_deserializer) {
3287 : DCHECK_NOT_NULL(read_only_deserializer);
3288 : DCHECK_NOT_NULL(startup_deserializer);
3289 62309 : return Init(read_only_deserializer, startup_deserializer);
3290 : }
3291 :
3292 62420 : bool Isolate::Init(ReadOnlyDeserializer* read_only_deserializer,
3293 : StartupDeserializer* startup_deserializer) {
3294 : TRACE_ISOLATE(init);
3295 62420 : const bool create_heap_objects = (read_only_deserializer == nullptr);
3296 : // We either have both or neither.
3297 : DCHECK_EQ(create_heap_objects, startup_deserializer == nullptr);
3298 :
3299 : base::ElapsedTimer timer;
3300 62420 : if (create_heap_objects && FLAG_profile_deserialization) timer.Start();
3301 :
3302 62420 : time_millis_at_init_ = heap_.MonotonicallyIncreasingTimeInMs();
3303 :
3304 62420 : stress_deopt_count_ = FLAG_deopt_every_n_times;
3305 62420 : force_slow_path_ = FLAG_force_slow_path;
3306 :
3307 62420 : has_fatal_error_ = false;
3308 :
3309 : // The initialization process does not handle memory exhaustion.
3310 : AlwaysAllocateScope always_allocate(this);
3311 :
3312 : // Safe after setting Heap::isolate_, and initializing StackGuard
3313 62420 : heap_.SetStackLimits();
3314 :
3315 : #define ASSIGN_ELEMENT(CamelName, hacker_name) \
3316 : isolate_addresses_[IsolateAddressId::k##CamelName##Address] = \
3317 : reinterpret_cast<Address>(hacker_name##_address());
3318 749028 : FOR_EACH_ISOLATE_ADDRESS_NAME(ASSIGN_ELEMENT)
3319 : #undef ASSIGN_ELEMENT
3320 :
3321 62419 : compilation_cache_ = new CompilationCache(this);
3322 124837 : descriptor_lookup_cache_ = new DescriptorLookupCache();
3323 124840 : unicode_cache_ = new UnicodeCache();
3324 62420 : inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this);
3325 62421 : global_handles_ = new GlobalHandles(this);
3326 124844 : eternal_handles_ = new EternalHandles();
3327 62422 : bootstrapper_ = new Bootstrapper(this);
3328 124843 : handle_scope_implementer_ = new HandleScopeImplementer(this);
3329 62421 : load_stub_cache_ = new StubCache(this);
3330 62421 : store_stub_cache_ = new StubCache(this);
3331 124844 : materialized_object_store_ = new MaterializedObjectStore(this);
3332 62422 : regexp_stack_ = new RegExpStack();
3333 62421 : regexp_stack_->isolate_ = this;
3334 62421 : date_cache_ = new DateCache();
3335 62422 : heap_profiler_ = new HeapProfiler(heap());
3336 62422 : interpreter_ = new interpreter::Interpreter(this);
3337 :
3338 : compiler_dispatcher_ =
3339 62421 : new CompilerDispatcher(this, V8::GetCurrentPlatform(), FLAG_stack_size);
3340 :
3341 : // Enable logging before setting up the heap
3342 62422 : logger_->SetUp(this);
3343 :
3344 : { // NOLINT
3345 : // Ensure that the thread has a valid stack guard. The v8::Locker object
3346 : // will ensure this too, but we don't have to use lockers if we are only
3347 : // using one thread.
3348 : ExecutionAccess lock(this);
3349 62422 : stack_guard_.InitThread(lock);
3350 : }
3351 :
3352 : // SetUp the object heap.
3353 : DCHECK(!heap_.HasBeenSetUp());
3354 62422 : heap_.SetUp();
3355 62422 : ReadOnlyHeap::SetUp(this, read_only_deserializer);
3356 62422 : heap_.SetUpSpaces();
3357 :
3358 62422 : isolate_data_.external_reference_table()->Init(this);
3359 :
3360 : // Setup the wasm engine.
3361 62422 : if (wasm_engine_ == nullptr) {
3362 124676 : SetWasmEngine(wasm::WasmEngine::GetWasmEngine());
3363 : }
3364 : DCHECK_NOT_NULL(wasm_engine_);
3365 :
3366 62422 : deoptimizer_data_ = new DeoptimizerData(heap());
3367 :
3368 62422 : if (setup_delegate_ == nullptr) {
3369 124314 : setup_delegate_ = new SetupIsolateDelegate(create_heap_objects);
3370 : }
3371 :
3372 62422 : if (!setup_delegate_->SetupHeap(&heap_)) {
3373 0 : V8::FatalProcessOutOfMemory(this, "heap object creation");
3374 : return false;
3375 : }
3376 :
3377 62422 : if (create_heap_objects) {
3378 : // Terminate the partial snapshot cache so we can iterate.
3379 112 : partial_snapshot_cache_.push_back(ReadOnlyRoots(this).undefined_value());
3380 : }
3381 :
3382 : InitializeThreadLocal();
3383 :
3384 : // Profiler has to be created after ThreadLocal is initialized
3385 : // because it makes use of interrupts.
3386 62422 : tracing_cpu_profiler_.reset(new TracingCpuProfilerImpl(this));
3387 :
3388 62422 : bootstrapper_->Initialize(create_heap_objects);
3389 :
3390 62422 : if (FLAG_embedded_builtins && create_heap_objects) {
3391 56 : builtins_constants_table_builder_ = new BuiltinsConstantsTableBuilder(this);
3392 : }
3393 62422 : setup_delegate_->SetupBuiltins(this);
3394 : #ifndef V8_TARGET_ARCH_ARM
3395 62422 : if (create_heap_objects) {
3396 : // Store the interpreter entry trampoline on the root list. It is used as a
3397 : // template for further copies that may later be created to help profile
3398 : // interpreted code.
3399 : // We currently cannot do this on arm due to RELATIVE_CODE_TARGETs
3400 : // assuming that all possible Code targets may be addressed with an int24
3401 : // offset, effectively limiting code space size to 32MB. We can guarantee
3402 : // this at mksnapshot-time, but not at runtime.
3403 : // See also: https://crbug.com/v8/8713.
3404 56 : heap_.SetInterpreterEntryTrampolineForProfiling(
3405 56 : heap_.builtin(Builtins::kInterpreterEntryTrampoline));
3406 : }
3407 : #endif
3408 62422 : if (FLAG_embedded_builtins && create_heap_objects) {
3409 56 : builtins_constants_table_builder_->Finalize();
3410 112 : delete builtins_constants_table_builder_;
3411 56 : builtins_constants_table_builder_ = nullptr;
3412 :
3413 56 : CreateAndSetEmbeddedBlob();
3414 : }
3415 :
3416 : // Initialize custom memcopy and memmove functions (must happen after
3417 : // embedded blob setup).
3418 62422 : init_memcopy_functions();
3419 :
3420 62422 : if (FLAG_log_internal_timer_events) {
3421 : set_event_logger(Logger::DefaultEventLoggerSentinel);
3422 : }
3423 :
3424 62422 : if (FLAG_trace_turbo || FLAG_trace_turbo_graph || FLAG_turbo_profiling) {
3425 5 : PrintF("Concurrent recompilation has been disabled for tracing.\n");
3426 62417 : } else if (OptimizingCompileDispatcher::Enabled()) {
3427 62318 : optimizing_compile_dispatcher_ = new OptimizingCompileDispatcher(this);
3428 : }
3429 :
3430 : // Initialize runtime profiler before deserialization, because collections may
3431 : // occur, clearing/updating ICs.
3432 62422 : runtime_profiler_ = new RuntimeProfiler(this);
3433 :
3434 : // If we are deserializing, read the state into the now-empty heap.
3435 : {
3436 : AlwaysAllocateScope always_allocate(this);
3437 124844 : CodeSpaceMemoryModificationScope modification_scope(&heap_);
3438 :
3439 62422 : if (!create_heap_objects) {
3440 62366 : startup_deserializer->DeserializeInto(this);
3441 : } else {
3442 56 : heap_.read_only_heap()->OnCreateHeapObjectsComplete();
3443 : }
3444 62421 : load_stub_cache_->Initialize();
3445 62422 : store_stub_cache_->Initialize();
3446 62422 : interpreter_->Initialize();
3447 62422 : heap_.NotifyDeserializationComplete();
3448 : }
3449 62422 : delete setup_delegate_;
3450 62422 : setup_delegate_ = nullptr;
3451 :
3452 : // Initialize the builtin entry table.
3453 62422 : Builtins::UpdateBuiltinEntryTable(this);
3454 :
3455 : #ifdef DEBUG
3456 : // Verify that the current heap state (usually deserialized from the snapshot)
3457 : // is compatible with the embedded blob. If this DCHECK fails, we've likely
3458 : // loaded a snapshot generated by a different V8 version or build-time
3459 : // configuration.
3460 : if (!IsolateIsCompatibleWithEmbeddedBlob(this)) {
3461 : FATAL(
3462 : "The Isolate is incompatible with the embedded blob. This is usually "
3463 : "caused by incorrect usage of mksnapshot. When generating custom "
3464 : "snapshots, embedders must ensure they pass the same flags as during "
3465 : "the V8 build process (e.g.: --turbo-instruction-scheduling).");
3466 : }
3467 : DCHECK_IMPLIES(FLAG_jitless, FLAG_embedded_builtins);
3468 : #endif // DEBUG
3469 :
3470 : #ifndef V8_TARGET_ARCH_ARM
3471 : // The IET for profiling should always be a full on-heap Code object.
3472 : DCHECK(!Code::cast(heap_.interpreter_entry_trampoline_for_profiling())
3473 : ->is_off_heap_trampoline());
3474 : #endif // V8_TARGET_ARCH_ARM
3475 :
3476 : if (FLAG_print_builtin_code) builtins()->PrintBuiltinCode();
3477 : if (FLAG_print_builtin_size) builtins()->PrintBuiltinSize();
3478 :
3479 : // Finish initialization of ThreadLocal after deserialization is done.
3480 : clear_pending_exception();
3481 : clear_pending_message();
3482 : clear_scheduled_exception();
3483 :
3484 : // Deserializing may put strange things in the root array's copy of the
3485 : // stack guard.
3486 62422 : heap_.SetStackLimits();
3487 :
3488 : // Quiet the heap NaN if needed on target platform.
3489 : if (!create_heap_objects)
3490 : Assembler::QuietNaN(ReadOnlyRoots(this).nan_value());
3491 :
3492 62422 : if (FLAG_trace_turbo) {
3493 : // Create an empty file.
3494 10 : std::ofstream(GetTurboCfgFileName(this).c_str(), std::ios_base::trunc);
3495 : }
3496 :
3497 : {
3498 : HandleScope scope(this);
3499 62422 : ast_string_constants_ = new AstStringConstants(this, HashSeed(this));
3500 : }
3501 :
3502 62422 : initialized_from_snapshot_ = !create_heap_objects;
3503 :
3504 62422 : if (!FLAG_inline_new) heap_.DisableInlineAllocation();
3505 :
3506 62422 : if (FLAG_stress_sampling_allocation_profiler > 0) {
3507 0 : uint64_t sample_interval = FLAG_stress_sampling_allocation_profiler;
3508 : int stack_depth = 128;
3509 : v8::HeapProfiler::SamplingFlags sampling_flags =
3510 : v8::HeapProfiler::SamplingFlags::kSamplingForceGC;
3511 : heap_profiler()->StartSamplingHeapProfiler(sample_interval, stack_depth,
3512 0 : sampling_flags);
3513 : }
3514 :
3515 : #if defined(V8_OS_WIN_X64)
3516 : if (win64_unwindinfo::CanRegisterUnwindInfoForNonABICompliantCodeRange()) {
3517 : const base::AddressRegion& code_range =
3518 : heap()->memory_allocator()->code_range();
3519 : void* start = reinterpret_cast<void*>(code_range.begin());
3520 : size_t size_in_bytes = code_range.size();
3521 : win64_unwindinfo::RegisterNonABICompliantCodeRange(start, size_in_bytes);
3522 : }
3523 : #endif
3524 :
3525 62422 : if (create_heap_objects && FLAG_profile_deserialization) {
3526 0 : double ms = timer.Elapsed().InMillisecondsF();
3527 0 : PrintF("[Initializing isolate from scratch took %0.3f ms]\n", ms);
3528 : }
3529 :
3530 : return true;
3531 : }
3532 :
3533 224022 : void Isolate::Enter() {
3534 : Isolate* current_isolate = nullptr;
3535 : PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
3536 224015 : if (current_data != nullptr) {
3537 11395 : current_isolate = current_data->isolate_;
3538 : DCHECK_NOT_NULL(current_isolate);
3539 11395 : if (current_isolate == this) {
3540 : DCHECK(Current() == this);
3541 : DCHECK_NOT_NULL(entry_stack_);
3542 : DCHECK(entry_stack_->previous_thread_data == nullptr ||
3543 : entry_stack_->previous_thread_data->thread_id() ==
3544 : ThreadId::Current());
3545 : // Same thread re-enters the isolate, no need to re-init anything.
3546 10241 : entry_stack_->entry_count++;
3547 10241 : return;
3548 : }
3549 : }
3550 :
3551 213774 : PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
3552 : DCHECK_NOT_NULL(data);
3553 : DCHECK(data->isolate_ == this);
3554 :
3555 : EntryStackItem* item = new EntryStackItem(current_data,
3556 : current_isolate,
3557 213786 : entry_stack_);
3558 213788 : entry_stack_ = item;
3559 :
3560 213788 : SetIsolateThreadLocals(this, data);
3561 :
3562 : // In case it's the first time some thread enters the isolate.
3563 : set_thread_id(data->thread_id());
3564 : }
3565 :
3566 :
3567 224016 : void Isolate::Exit() {
3568 : DCHECK_NOT_NULL(entry_stack_);
3569 : DCHECK(entry_stack_->previous_thread_data == nullptr ||
3570 : entry_stack_->previous_thread_data->thread_id() ==
3571 : ThreadId::Current());
3572 :
3573 224016 : if (--entry_stack_->entry_count > 0) return;
3574 :
3575 : DCHECK_NOT_NULL(CurrentPerIsolateThreadData());
3576 : DCHECK(CurrentPerIsolateThreadData()->isolate_ == this);
3577 :
3578 : // Pop the stack.
3579 213777 : EntryStackItem* item = entry_stack_;
3580 213777 : entry_stack_ = item->previous_item;
3581 :
3582 213777 : PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
3583 213777 : Isolate* previous_isolate = item->previous_isolate;
3584 :
3585 213777 : delete item;
3586 :
3587 : // Reinit the current thread for the isolate it was running before this one.
3588 213779 : SetIsolateThreadLocals(previous_isolate, previous_thread_data);
3589 : }
3590 :
3591 :
3592 6880 : void Isolate::LinkDeferredHandles(DeferredHandles* deferred) {
3593 6880 : deferred->next_ = deferred_handles_head_;
3594 6880 : if (deferred_handles_head_ != nullptr) {
3595 2076 : deferred_handles_head_->previous_ = deferred;
3596 : }
3597 6880 : deferred_handles_head_ = deferred;
3598 6880 : }
3599 :
3600 :
3601 6880 : void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) {
3602 : #ifdef DEBUG
3603 : // In debug mode assert that the linked list is well-formed.
3604 : DeferredHandles* deferred_iterator = deferred;
3605 : while (deferred_iterator->previous_ != nullptr) {
3606 : deferred_iterator = deferred_iterator->previous_;
3607 : }
3608 : DCHECK(deferred_handles_head_ == deferred_iterator);
3609 : #endif
3610 6880 : if (deferred_handles_head_ == deferred) {
3611 5128 : deferred_handles_head_ = deferred_handles_head_->next_;
3612 : }
3613 6880 : if (deferred->next_ != nullptr) {
3614 915 : deferred->next_->previous_ = deferred->previous_;
3615 : }
3616 6880 : if (deferred->previous_ != nullptr) {
3617 1752 : deferred->previous_->next_ = deferred->next_;
3618 : }
3619 6880 : }
3620 :
3621 62405 : void Isolate::DumpAndResetStats() {
3622 62405 : if (turbo_statistics() != nullptr) {
3623 : DCHECK(FLAG_turbo_stats || FLAG_turbo_stats_nvp);
3624 0 : StdoutStream os;
3625 0 : if (FLAG_turbo_stats) {
3626 0 : AsPrintableStatistics ps = {*turbo_statistics(), false};
3627 0 : os << ps << std::endl;
3628 : }
3629 0 : if (FLAG_turbo_stats_nvp) {
3630 0 : AsPrintableStatistics ps = {*turbo_statistics(), true};
3631 0 : os << ps << std::endl;
3632 : }
3633 0 : delete turbo_statistics_;
3634 0 : turbo_statistics_ = nullptr;
3635 : }
3636 : // TODO(7424): There is no public API for the {WasmEngine} yet. So for now we
3637 : // just dump and reset the engines statistics together with the Isolate.
3638 62405 : if (FLAG_turbo_stats_wasm) {
3639 0 : wasm_engine()->DumpAndResetTurboStatistics();
3640 : }
3641 62405 : if (V8_UNLIKELY(TracingFlags::runtime_stats.load(std::memory_order_relaxed) ==
3642 : v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) {
3643 : counters()->worker_thread_runtime_call_stats()->AddToMainTable(
3644 0 : counters()->runtime_call_stats());
3645 0 : counters()->runtime_call_stats()->Print();
3646 0 : counters()->runtime_call_stats()->Reset();
3647 : }
3648 62405 : }
3649 :
3650 23748 : void Isolate::AbortConcurrentOptimization(BlockingBehavior behavior) {
3651 23748 : if (concurrent_recompilation_enabled()) {
3652 : DisallowHeapAllocation no_recursive_gc;
3653 23692 : optimizing_compile_dispatcher()->Flush(behavior);
3654 : }
3655 23748 : }
3656 :
3657 0 : CompilationStatistics* Isolate::GetTurboStatistics() {
3658 0 : if (turbo_statistics() == nullptr)
3659 0 : set_turbo_statistics(new CompilationStatistics());
3660 0 : return turbo_statistics();
3661 : }
3662 :
3663 :
3664 285 : CodeTracer* Isolate::GetCodeTracer() {
3665 290 : if (code_tracer() == nullptr) set_code_tracer(new CodeTracer(id()));
3666 285 : return code_tracer();
3667 : }
3668 :
3669 1650364 : bool Isolate::use_optimizer() {
3670 180698 : return FLAG_opt && !serializer_enabled_ && CpuFeatures::SupportsOptimizer() &&
3671 1831030 : !is_precise_count_code_coverage() && !is_block_count_code_coverage();
3672 : }
3673 :
3674 483290 : bool Isolate::NeedsDetailedOptimizedCodeLineInfo() const {
3675 483290 : return NeedsSourcePositionsForProfiling() ||
3676 483293 : detailed_source_positions_for_profiling();
3677 : }
3678 :
3679 1603167 : bool Isolate::NeedsSourcePositionsForProfiling() const {
3680 1602035 : return FLAG_trace_deopt || FLAG_trace_turbo || FLAG_trace_turbo_graph ||
3681 3203559 : FLAG_turbo_profiling || FLAG_perf_prof || is_profiling() ||
3682 4769292 : debug_->is_active() || logger_->is_logging() || FLAG_trace_maps;
3683 : }
3684 :
3685 1498 : void Isolate::SetFeedbackVectorsForProfilingTools(Object value) {
3686 : DCHECK(value->IsUndefined(this) || value->IsArrayList());
3687 : heap()->set_feedback_vectors_for_profiling_tools(value);
3688 1498 : }
3689 :
3690 164 : void Isolate::MaybeInitializeVectorListFromHeap() {
3691 164 : if (!heap()->feedback_vectors_for_profiling_tools()->IsUndefined(this)) {
3692 : // Already initialized, return early.
3693 : DCHECK(heap()->feedback_vectors_for_profiling_tools()->IsArrayList());
3694 8 : return;
3695 : }
3696 :
3697 : // Collect existing feedback vectors.
3698 : std::vector<Handle<FeedbackVector>> vectors;
3699 :
3700 : {
3701 312 : HeapIterator heap_iterator(heap());
3702 1188354 : for (HeapObject current_obj = heap_iterator.next(); !current_obj.is_null();
3703 : current_obj = heap_iterator.next()) {
3704 2375963 : if (!current_obj->IsFeedbackVector()) continue;
3705 :
3706 433 : FeedbackVector vector = FeedbackVector::cast(current_obj);
3707 433 : SharedFunctionInfo shared = vector->shared_function_info();
3708 :
3709 : // No need to preserve the feedback vector for non-user-visible functions.
3710 433 : if (!shared->IsSubjectToDebugging()) continue;
3711 :
3712 433 : vectors.emplace_back(vector, this);
3713 : }
3714 : }
3715 :
3716 : // Add collected feedback vectors to the root list lest we lose them to GC.
3717 : Handle<ArrayList> list =
3718 156 : ArrayList::New(this, static_cast<int>(vectors.size()));
3719 1022 : for (const auto& vector : vectors) list = ArrayList::Add(this, list, vector);
3720 : SetFeedbackVectorsForProfilingTools(*list);
3721 : }
3722 :
3723 5 : void Isolate::set_date_cache(DateCache* date_cache) {
3724 5 : if (date_cache != date_cache_) {
3725 5 : delete date_cache_;
3726 : }
3727 5 : date_cache_ = date_cache;
3728 5 : }
3729 :
3730 15319 : bool Isolate::IsArrayOrObjectOrStringPrototype(Object object) {
3731 : Object context = heap()->native_contexts_list();
3732 60939 : while (!context->IsUndefined(this)) {
3733 23663 : Context current_context = Context::cast(context);
3734 70844 : if (current_context->initial_object_prototype() == object ||
3735 46531 : current_context->initial_array_prototype() == object ||
3736 22868 : current_context->initial_string_prototype() == object) {
3737 853 : return true;
3738 : }
3739 22810 : context = current_context->next_context_link();
3740 : }
3741 : return false;
3742 : }
3743 :
3744 6728621 : bool Isolate::IsInAnyContext(Object object, uint32_t index) {
3745 : DisallowHeapAllocation no_gc;
3746 : Object context = heap()->native_contexts_list();
3747 11605591 : while (!context->IsUndefined(this)) {
3748 8043290 : Context current_context = Context::cast(context);
3749 16086584 : if (current_context->get(index) == object) {
3750 5604809 : return true;
3751 : }
3752 2438485 : context = current_context->next_context_link();
3753 : }
3754 : return false;
3755 : }
3756 :
3757 100499 : bool Isolate::IsNoElementsProtectorIntact(Context context) {
3758 : PropertyCell no_elements_cell = heap()->no_elements_protector();
3759 : bool cell_reports_intact =
3760 11697494 : no_elements_cell->value()->IsSmi() &&
3761 : Smi::ToInt(no_elements_cell->value()) == kProtectorValid;
3762 :
3763 : #ifdef DEBUG
3764 : Context native_context = context->native_context();
3765 :
3766 : Map root_array_map =
3767 : native_context->GetInitialJSArrayMap(GetInitialFastElementsKind());
3768 : JSObject initial_array_proto = JSObject::cast(
3769 : native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
3770 : JSObject initial_object_proto = JSObject::cast(
3771 : native_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX));
3772 : JSObject initial_string_proto = JSObject::cast(
3773 : native_context->get(Context::INITIAL_STRING_PROTOTYPE_INDEX));
3774 :
3775 : if (root_array_map.is_null() || initial_array_proto == initial_object_proto) {
3776 : // We are in the bootstrapping process, and the entire check sequence
3777 : // shouldn't be performed.
3778 : return cell_reports_intact;
3779 : }
3780 :
3781 : // Check that the array prototype hasn't been altered WRT empty elements.
3782 : if (root_array_map->prototype() != initial_array_proto) {
3783 : DCHECK_EQ(false, cell_reports_intact);
3784 : return cell_reports_intact;
3785 : }
3786 :
3787 : FixedArrayBase elements = initial_array_proto->elements();
3788 : ReadOnlyRoots roots(heap());
3789 : if (elements != roots.empty_fixed_array() &&
3790 : elements != roots.empty_slow_element_dictionary()) {
3791 : DCHECK_EQ(false, cell_reports_intact);
3792 : return cell_reports_intact;
3793 : }
3794 :
3795 : // Check that the Object.prototype hasn't been altered WRT empty elements.
3796 : elements = initial_object_proto->elements();
3797 : if (elements != roots.empty_fixed_array() &&
3798 : elements != roots.empty_slow_element_dictionary()) {
3799 : DCHECK_EQ(false, cell_reports_intact);
3800 : return cell_reports_intact;
3801 : }
3802 :
3803 : // Check that the Array.prototype has the Object.prototype as its
3804 : // [[Prototype]] and that the Object.prototype has a null [[Prototype]].
3805 : PrototypeIterator iter(this, initial_array_proto);
3806 : if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) {
3807 : DCHECK_EQ(false, cell_reports_intact);
3808 : DCHECK(!has_pending_exception());
3809 : return cell_reports_intact;
3810 : }
3811 : iter.Advance();
3812 : if (!iter.IsAtEnd()) {
3813 : DCHECK_EQ(false, cell_reports_intact);
3814 : DCHECK(!has_pending_exception());
3815 : return cell_reports_intact;
3816 : }
3817 : DCHECK(!has_pending_exception());
3818 :
3819 : // Check that the String.prototype hasn't been altered WRT empty elements.
3820 : elements = initial_string_proto->elements();
3821 : if (elements != roots.empty_fixed_array() &&
3822 : elements != roots.empty_slow_element_dictionary()) {
3823 : DCHECK_EQ(false, cell_reports_intact);
3824 : return cell_reports_intact;
3825 : }
3826 :
3827 : // Check that the String.prototype has the Object.prototype
3828 : // as its [[Prototype]] still.
3829 : if (initial_string_proto->map()->prototype() != initial_object_proto) {
3830 : DCHECK_EQ(false, cell_reports_intact);
3831 : return cell_reports_intact;
3832 : }
3833 : #endif
3834 :
3835 100499 : return cell_reports_intact;
3836 : }
3837 :
3838 5731490 : bool Isolate::IsNoElementsProtectorIntact() {
3839 5731490 : return Isolate::IsNoElementsProtectorIntact(context());
3840 : }
3841 :
3842 301064 : bool Isolate::IsIsConcatSpreadableLookupChainIntact() {
3843 : Cell is_concat_spreadable_cell = heap()->is_concat_spreadable_protector();
3844 : bool is_is_concat_spreadable_set =
3845 : Smi::ToInt(is_concat_spreadable_cell->value()) == kProtectorInvalid;
3846 : #ifdef DEBUG
3847 : Map root_array_map =
3848 : raw_native_context()->GetInitialJSArrayMap(GetInitialFastElementsKind());
3849 : if (root_array_map.is_null()) {
3850 : // Ignore the value of is_concat_spreadable during bootstrap.
3851 : return !is_is_concat_spreadable_set;
3852 : }
3853 : Handle<Object> array_prototype(array_function()->prototype(), this);
3854 : Handle<Symbol> key = factory()->is_concat_spreadable_symbol();
3855 : Handle<Object> value;
3856 : LookupIterator it(this, array_prototype, key);
3857 : if (it.IsFound() && !JSReceiver::GetDataProperty(&it)->IsUndefined(this)) {
3858 : // TODO(cbruni): Currently we do not revert if we unset the
3859 : // @@isConcatSpreadable property on Array.prototype or Object.prototype
3860 : // hence the reverse implication doesn't hold.
3861 : DCHECK(is_is_concat_spreadable_set);
3862 : return false;
3863 : }
3864 : #endif // DEBUG
3865 :
3866 301064 : return !is_is_concat_spreadable_set;
3867 : }
3868 :
3869 10387 : bool Isolate::IsIsConcatSpreadableLookupChainIntact(JSReceiver receiver) {
3870 10387 : if (!IsIsConcatSpreadableLookupChainIntact()) return false;
3871 4282 : return !receiver->HasProxyInPrototype(this);
3872 : }
3873 :
3874 0 : bool Isolate::IsPromiseHookProtectorIntact() {
3875 : PropertyCell promise_hook_cell = heap()->promise_hook_protector();
3876 : bool is_promise_hook_protector_intact =
3877 0 : Smi::ToInt(promise_hook_cell->value()) == kProtectorValid;
3878 : DCHECK_IMPLIES(is_promise_hook_protector_intact,
3879 : !promise_hook_or_async_event_delegate_);
3880 : DCHECK_IMPLIES(is_promise_hook_protector_intact,
3881 : !promise_hook_or_debug_is_active_or_async_event_delegate_);
3882 0 : return is_promise_hook_protector_intact;
3883 : }
3884 :
3885 1728 : bool Isolate::IsPromiseResolveLookupChainIntact() {
3886 : Cell promise_resolve_cell = heap()->promise_resolve_protector();
3887 : bool is_promise_resolve_protector_intact =
3888 1728 : Smi::ToInt(promise_resolve_cell->value()) == kProtectorValid;
3889 1728 : return is_promise_resolve_protector_intact;
3890 : }
3891 :
3892 1686 : bool Isolate::IsPromiseThenLookupChainIntact() {
3893 : PropertyCell promise_then_cell = heap()->promise_then_protector();
3894 : bool is_promise_then_protector_intact =
3895 3288 : Smi::ToInt(promise_then_cell->value()) == kProtectorValid;
3896 1686 : return is_promise_then_protector_intact;
3897 : }
3898 :
3899 3728 : bool Isolate::IsPromiseThenLookupChainIntact(Handle<JSReceiver> receiver) {
3900 : DisallowHeapAllocation no_gc;
3901 3728 : if (!receiver->IsJSPromise()) return false;
3902 1602 : if (!IsInAnyContext(receiver->map()->prototype(),
3903 : Context::PROMISE_PROTOTYPE_INDEX)) {
3904 : return false;
3905 : }
3906 1602 : return IsPromiseThenLookupChainIntact();
3907 : }
3908 :
3909 1212839 : void Isolate::UpdateNoElementsProtectorOnSetElement(Handle<JSObject> object) {
3910 : DisallowHeapAllocation no_gc;
3911 1212839 : if (!object->map()->is_prototype_map()) return;
3912 16755 : if (!IsNoElementsProtectorIntact()) return;
3913 15319 : if (!IsArrayOrObjectOrStringPrototype(*object)) return;
3914 853 : PropertyCell::SetValueWithInvalidation(
3915 : this, factory()->no_elements_protector(),
3916 853 : handle(Smi::FromInt(kProtectorInvalid), this));
3917 : }
3918 :
3919 65 : void Isolate::InvalidateIsConcatSpreadableProtector() {
3920 : DCHECK(factory()->is_concat_spreadable_protector()->value()->IsSmi());
3921 : DCHECK(IsIsConcatSpreadableLookupChainIntact());
3922 130 : factory()->is_concat_spreadable_protector()->set_value(
3923 195 : Smi::FromInt(kProtectorInvalid));
3924 : DCHECK(!IsIsConcatSpreadableLookupChainIntact());
3925 65 : }
3926 :
3927 230 : void Isolate::InvalidateArrayConstructorProtector() {
3928 : DCHECK(factory()->array_constructor_protector()->value()->IsSmi());
3929 : DCHECK(IsArrayConstructorIntact());
3930 460 : factory()->array_constructor_protector()->set_value(
3931 690 : Smi::FromInt(kProtectorInvalid));
3932 : DCHECK(!IsArrayConstructorIntact());
3933 230 : }
3934 :
3935 123 : void Isolate::InvalidateArraySpeciesProtector() {
3936 : DCHECK(factory()->array_species_protector()->value()->IsSmi());
3937 : DCHECK(IsArraySpeciesLookupChainIntact());
3938 123 : PropertyCell::SetValueWithInvalidation(
3939 : this, factory()->array_species_protector(),
3940 123 : handle(Smi::FromInt(kProtectorInvalid), this));
3941 : DCHECK(!IsArraySpeciesLookupChainIntact());
3942 123 : }
3943 :
3944 245 : void Isolate::InvalidateTypedArraySpeciesProtector() {
3945 : DCHECK(factory()->typed_array_species_protector()->value()->IsSmi());
3946 : DCHECK(IsTypedArraySpeciesLookupChainIntact());
3947 245 : PropertyCell::SetValueWithInvalidation(
3948 : this, factory()->typed_array_species_protector(),
3949 245 : handle(Smi::FromInt(kProtectorInvalid), this));
3950 : DCHECK(!IsTypedArraySpeciesLookupChainIntact());
3951 245 : }
3952 :
3953 25 : void Isolate::InvalidateRegExpSpeciesProtector() {
3954 : DCHECK(factory()->regexp_species_protector()->value()->IsSmi());
3955 : DCHECK(IsRegExpSpeciesLookupChainIntact());
3956 25 : PropertyCell::SetValueWithInvalidation(
3957 : this, factory()->regexp_species_protector(),
3958 25 : handle(Smi::FromInt(kProtectorInvalid), this));
3959 : DCHECK(!IsRegExpSpeciesLookupChainIntact());
3960 25 : }
3961 :
3962 59 : void Isolate::InvalidatePromiseSpeciesProtector() {
3963 : DCHECK(factory()->promise_species_protector()->value()->IsSmi());
3964 : DCHECK(IsPromiseSpeciesLookupChainIntact());
3965 59 : PropertyCell::SetValueWithInvalidation(
3966 : this, factory()->promise_species_protector(),
3967 59 : handle(Smi::FromInt(kProtectorInvalid), this));
3968 : DCHECK(!IsPromiseSpeciesLookupChainIntact());
3969 59 : }
3970 :
3971 143 : void Isolate::InvalidateStringLengthOverflowProtector() {
3972 : DCHECK(factory()->string_length_protector()->value()->IsSmi());
3973 : DCHECK(IsStringLengthOverflowIntact());
3974 286 : factory()->string_length_protector()->set_value(
3975 429 : Smi::FromInt(kProtectorInvalid));
3976 : DCHECK(!IsStringLengthOverflowIntact());
3977 143 : }
3978 :
3979 107 : void Isolate::InvalidateArrayIteratorProtector() {
3980 : DCHECK(factory()->array_iterator_protector()->value()->IsSmi());
3981 : DCHECK(IsArrayIteratorLookupChainIntact());
3982 107 : PropertyCell::SetValueWithInvalidation(
3983 : this, factory()->array_iterator_protector(),
3984 107 : handle(Smi::FromInt(kProtectorInvalid), this));
3985 : DCHECK(!IsArrayIteratorLookupChainIntact());
3986 107 : }
3987 :
3988 55 : void Isolate::InvalidateMapIteratorProtector() {
3989 : DCHECK(factory()->map_iterator_protector()->value()->IsSmi());
3990 : DCHECK(IsMapIteratorLookupChainIntact());
3991 55 : PropertyCell::SetValueWithInvalidation(
3992 : this, factory()->map_iterator_protector(),
3993 55 : handle(Smi::FromInt(kProtectorInvalid), this));
3994 : DCHECK(!IsMapIteratorLookupChainIntact());
3995 55 : }
3996 :
3997 65 : void Isolate::InvalidateSetIteratorProtector() {
3998 : DCHECK(factory()->set_iterator_protector()->value()->IsSmi());
3999 : DCHECK(IsSetIteratorLookupChainIntact());
4000 65 : PropertyCell::SetValueWithInvalidation(
4001 : this, factory()->set_iterator_protector(),
4002 65 : handle(Smi::FromInt(kProtectorInvalid), this));
4003 : DCHECK(!IsSetIteratorLookupChainIntact());
4004 65 : }
4005 :
4006 25 : void Isolate::InvalidateStringIteratorProtector() {
4007 : DCHECK(factory()->string_iterator_protector()->value()->IsSmi());
4008 : DCHECK(IsStringIteratorLookupChainIntact());
4009 25 : PropertyCell::SetValueWithInvalidation(
4010 : this, factory()->string_iterator_protector(),
4011 25 : handle(Smi::FromInt(kProtectorInvalid), this));
4012 : DCHECK(!IsStringIteratorLookupChainIntact());
4013 25 : }
4014 :
4015 426 : void Isolate::InvalidateArrayBufferDetachingProtector() {
4016 : DCHECK(factory()->array_buffer_detaching_protector()->value()->IsSmi());
4017 : DCHECK(IsArrayBufferDetachingIntact());
4018 426 : PropertyCell::SetValueWithInvalidation(
4019 : this, factory()->array_buffer_detaching_protector(),
4020 426 : handle(Smi::FromInt(kProtectorInvalid), this));
4021 : DCHECK(!IsArrayBufferDetachingIntact());
4022 426 : }
4023 :
4024 2786 : void Isolate::InvalidatePromiseHookProtector() {
4025 : DCHECK(factory()->promise_hook_protector()->value()->IsSmi());
4026 : DCHECK(IsPromiseHookProtectorIntact());
4027 2786 : PropertyCell::SetValueWithInvalidation(
4028 : this, factory()->promise_hook_protector(),
4029 2786 : handle(Smi::FromInt(kProtectorInvalid), this));
4030 : DCHECK(!IsPromiseHookProtectorIntact());
4031 2786 : }
4032 :
4033 0 : void Isolate::InvalidatePromiseResolveProtector() {
4034 : DCHECK(factory()->promise_resolve_protector()->value()->IsSmi());
4035 : DCHECK(IsPromiseResolveLookupChainIntact());
4036 0 : factory()->promise_resolve_protector()->set_value(
4037 0 : Smi::FromInt(kProtectorInvalid));
4038 : DCHECK(!IsPromiseResolveLookupChainIntact());
4039 0 : }
4040 :
4041 103 : void Isolate::InvalidatePromiseThenProtector() {
4042 : DCHECK(factory()->promise_then_protector()->value()->IsSmi());
4043 : DCHECK(IsPromiseThenLookupChainIntact());
4044 103 : PropertyCell::SetValueWithInvalidation(
4045 : this, factory()->promise_then_protector(),
4046 103 : handle(Smi::FromInt(kProtectorInvalid), this));
4047 : DCHECK(!IsPromiseThenLookupChainIntact());
4048 103 : }
4049 :
4050 6493398 : bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) {
4051 : DisallowHeapAllocation no_gc;
4052 6493398 : return IsInAnyContext(*array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
4053 : }
4054 :
4055 128303 : static base::RandomNumberGenerator* ensure_rng_exists(
4056 : base::RandomNumberGenerator** rng, int seed) {
4057 128303 : if (*rng == nullptr) {
4058 62304 : if (seed != 0) {
4059 121648 : *rng = new base::RandomNumberGenerator(seed);
4060 : } else {
4061 1480 : *rng = new base::RandomNumberGenerator();
4062 : }
4063 : }
4064 128303 : return *rng;
4065 : }
4066 :
4067 74328 : base::RandomNumberGenerator* Isolate::random_number_generator() {
4068 : // TODO(bmeurer) Initialized lazily because it depends on flags; can
4069 : // be fixed once the default isolate cleanup is done.
4070 128303 : return ensure_rng_exists(&random_number_generator_, FLAG_random_seed);
4071 : }
4072 :
4073 0 : base::RandomNumberGenerator* Isolate::fuzzer_rng() {
4074 0 : if (fuzzer_rng_ == nullptr) {
4075 0 : int64_t seed = FLAG_fuzzer_random_seed;
4076 0 : if (seed == 0) {
4077 : seed = random_number_generator()->initial_seed();
4078 : }
4079 :
4080 0 : fuzzer_rng_ = new base::RandomNumberGenerator(seed);
4081 : }
4082 :
4083 0 : return fuzzer_rng_;
4084 : }
4085 :
4086 53975 : int Isolate::GenerateIdentityHash(uint32_t mask) {
4087 : int hash;
4088 : int attempts = 0;
4089 53975 : do {
4090 53975 : hash = random_number_generator()->NextInt() & mask;
4091 53975 : } while (hash == 0 && attempts++ < 30);
4092 53975 : return hash != 0 ? hash : 1;
4093 : }
4094 :
4095 20929 : Code Isolate::FindCodeObject(Address a) {
4096 20929 : return heap()->GcSafeFindCodeForInnerPointer(a);
4097 : }
4098 :
4099 :
4100 : #ifdef DEBUG
4101 : #define ISOLATE_FIELD_OFFSET(type, name, ignored) \
4102 : const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
4103 : ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
4104 : ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
4105 : #undef ISOLATE_FIELD_OFFSET
4106 : #endif
4107 :
4108 255007 : Handle<Symbol> Isolate::SymbolFor(RootIndex dictionary_index,
4109 : Handle<String> name, bool private_symbol) {
4110 255007 : Handle<String> key = factory()->InternalizeString(name);
4111 : Handle<NameDictionary> dictionary =
4112 : Handle<NameDictionary>::cast(root_handle(dictionary_index));
4113 255007 : int entry = dictionary->FindEntry(this, key);
4114 : Handle<Symbol> symbol;
4115 255007 : if (entry == NameDictionary::kNotFound) {
4116 : symbol =
4117 2723 : private_symbol ? factory()->NewPrivateSymbol() : factory()->NewSymbol();
4118 5446 : symbol->set_name(*key);
4119 : dictionary = NameDictionary::Add(this, dictionary, key, symbol,
4120 2723 : PropertyDetails::Empty(), &entry);
4121 2723 : switch (dictionary_index) {
4122 : case RootIndex::kPublicSymbolTable:
4123 : symbol->set_is_public(true);
4124 : heap()->set_public_symbol_table(*dictionary);
4125 : break;
4126 : case RootIndex::kApiSymbolTable:
4127 : heap()->set_api_symbol_table(*dictionary);
4128 : break;
4129 : case RootIndex::kApiPrivateSymbolTable:
4130 : heap()->set_api_private_symbol_table(*dictionary);
4131 : break;
4132 : default:
4133 0 : UNREACHABLE();
4134 : }
4135 : } else {
4136 : symbol = Handle<Symbol>(Symbol::cast(dictionary->ValueAt(entry)), this);
4137 : }
4138 255007 : return symbol;
4139 : }
4140 :
4141 15 : void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) {
4142 : auto pos = std::find(before_call_entered_callbacks_.begin(),
4143 15 : before_call_entered_callbacks_.end(), callback);
4144 20 : if (pos != before_call_entered_callbacks_.end()) return;
4145 10 : before_call_entered_callbacks_.push_back(callback);
4146 : }
4147 :
4148 5 : void Isolate::RemoveBeforeCallEnteredCallback(
4149 : BeforeCallEnteredCallback callback) {
4150 : auto pos = std::find(before_call_entered_callbacks_.begin(),
4151 5 : before_call_entered_callbacks_.end(), callback);
4152 5 : if (pos == before_call_entered_callbacks_.end()) return;
4153 5 : before_call_entered_callbacks_.erase(pos);
4154 : }
4155 :
4156 65 : void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
4157 : auto pos = std::find(call_completed_callbacks_.begin(),
4158 65 : call_completed_callbacks_.end(), callback);
4159 70 : if (pos != call_completed_callbacks_.end()) return;
4160 60 : call_completed_callbacks_.push_back(callback);
4161 : }
4162 :
4163 3730 : void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
4164 : auto pos = std::find(call_completed_callbacks_.begin(),
4165 3730 : call_completed_callbacks_.end(), callback);
4166 3730 : if (pos == call_completed_callbacks_.end()) return;
4167 45 : call_completed_callbacks_.erase(pos);
4168 : }
4169 :
4170 5428118 : void Isolate::FireCallCompletedCallback(MicrotaskQueue* microtask_queue) {
4171 10856206 : if (!handle_scope_implementer()->CallDepthIsZero()) return;
4172 :
4173 : bool run_microtasks =
4174 547747 : microtask_queue && microtask_queue->size() &&
4175 574855 : !microtask_queue->HasMicrotasksSuppressions() &&
4176 : microtask_queue->microtasks_policy() == v8::MicrotasksPolicy::kAuto;
4177 :
4178 547747 : if (run_microtasks) {
4179 1972 : microtask_queue->RunMicrotasks(this);
4180 : } else {
4181 : // TODO(marja): (spec) The discussion about when to clear the KeepDuringJob
4182 : // set is still open (whether to clear it after every microtask or once
4183 : // during a microtask checkpoint). See also
4184 : // https://github.com/tc39/proposal-weakrefs/issues/39 .
4185 545775 : heap()->ClearKeepDuringJobSet();
4186 : }
4187 :
4188 547747 : if (call_completed_callbacks_.empty()) return;
4189 : // Fire callbacks. Increase call depth to prevent recursive callbacks.
4190 : v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this);
4191 60 : v8::Isolate::SuppressMicrotaskExecutionScope suppress(isolate);
4192 30 : std::vector<CallCompletedCallback> callbacks(call_completed_callbacks_);
4193 65 : for (auto& callback : callbacks) {
4194 35 : callback(reinterpret_cast<v8::Isolate*>(this));
4195 : }
4196 : }
4197 :
4198 8483 : void Isolate::PromiseHookStateUpdated() {
4199 : bool promise_hook_or_async_event_delegate =
4200 8483 : promise_hook_ || async_event_delegate_;
4201 : bool promise_hook_or_debug_is_active_or_async_event_delegate =
4202 8483 : promise_hook_or_async_event_delegate || debug()->is_active();
4203 12975 : if (promise_hook_or_debug_is_active_or_async_event_delegate &&
4204 : IsPromiseHookProtectorIntact()) {
4205 : HandleScope scope(this);
4206 2785 : InvalidatePromiseHookProtector();
4207 : }
4208 8483 : promise_hook_or_async_event_delegate_ = promise_hook_or_async_event_delegate;
4209 : promise_hook_or_debug_is_active_or_async_event_delegate_ =
4210 8483 : promise_hook_or_debug_is_active_or_async_event_delegate;
4211 8483 : }
4212 :
4213 : namespace {
4214 :
4215 72 : MaybeHandle<JSPromise> NewRejectedPromise(Isolate* isolate,
4216 : v8::Local<v8::Context> api_context,
4217 : Handle<Object> exception) {
4218 : v8::Local<v8::Promise::Resolver> resolver;
4219 144 : ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
4220 : isolate, resolver, v8::Promise::Resolver::New(api_context),
4221 : MaybeHandle<JSPromise>());
4222 :
4223 144 : RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
4224 : isolate, resolver->Reject(api_context, v8::Utils::ToLocal(exception)),
4225 : MaybeHandle<JSPromise>());
4226 :
4227 72 : v8::Local<v8::Promise> promise = resolver->GetPromise();
4228 72 : return v8::Utils::OpenHandle(*promise);
4229 : }
4230 :
4231 : } // namespace
4232 :
4233 482 : MaybeHandle<JSPromise> Isolate::RunHostImportModuleDynamicallyCallback(
4234 : Handle<Script> referrer, Handle<Object> specifier) {
4235 : v8::Local<v8::Context> api_context =
4236 482 : v8::Utils::ToLocal(Handle<Context>(native_context()));
4237 :
4238 482 : if (host_import_module_dynamically_callback_ == nullptr) {
4239 : Handle<Object> exception =
4240 0 : factory()->NewError(error_function(), MessageTemplate::kUnsupported);
4241 0 : return NewRejectedPromise(this, api_context, exception);
4242 : }
4243 :
4244 : Handle<String> specifier_str;
4245 482 : MaybeHandle<String> maybe_specifier = Object::ToString(this, specifier);
4246 482 : if (!maybe_specifier.ToHandle(&specifier_str)) {
4247 : Handle<Object> exception(pending_exception(), this);
4248 : clear_pending_exception();
4249 :
4250 72 : return NewRejectedPromise(this, api_context, exception);
4251 : }
4252 : DCHECK(!has_pending_exception());
4253 :
4254 : v8::Local<v8::Promise> promise;
4255 820 : ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
4256 : this, promise,
4257 : host_import_module_dynamically_callback_(
4258 : api_context, v8::Utils::ScriptOrModuleToLocal(referrer),
4259 : v8::Utils::ToLocal(specifier_str)),
4260 : MaybeHandle<JSPromise>());
4261 410 : return v8::Utils::OpenHandle(*promise);
4262 : }
4263 :
4264 30789 : void Isolate::SetHostImportModuleDynamicallyCallback(
4265 : HostImportModuleDynamicallyCallback callback) {
4266 30789 : host_import_module_dynamically_callback_ = callback;
4267 30789 : }
4268 :
4269 39 : Handle<JSObject> Isolate::RunHostInitializeImportMetaObjectCallback(
4270 : Handle<Module> module) {
4271 : Handle<Object> host_meta(module->import_meta(), this);
4272 39 : if (host_meta->IsTheHole(this)) {
4273 23 : host_meta = factory()->NewJSObjectWithNullProto();
4274 23 : if (host_initialize_import_meta_object_callback_ != nullptr) {
4275 : v8::Local<v8::Context> api_context =
4276 23 : v8::Utils::ToLocal(Handle<Context>(native_context()));
4277 23 : host_initialize_import_meta_object_callback_(
4278 : api_context, Utils::ToLocal(module),
4279 23 : v8::Local<v8::Object>::Cast(v8::Utils::ToLocal(host_meta)));
4280 : }
4281 23 : module->set_import_meta(*host_meta);
4282 : }
4283 39 : return Handle<JSObject>::cast(host_meta);
4284 : }
4285 :
4286 30789 : void Isolate::SetHostInitializeImportMetaObjectCallback(
4287 : HostInitializeImportMetaObjectCallback callback) {
4288 30789 : host_initialize_import_meta_object_callback_ = callback;
4289 30789 : }
4290 :
4291 12 : MaybeHandle<Object> Isolate::RunPrepareStackTraceCallback(
4292 : Handle<Context> context, Handle<JSObject> error, Handle<JSArray> sites) {
4293 12 : v8::Local<v8::Context> api_context = Utils::ToLocal(context);
4294 :
4295 : v8::Local<v8::Value> stack;
4296 42 : ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
4297 : this, stack,
4298 : prepare_stack_trace_callback_(api_context, Utils::ToLocal(error),
4299 : Utils::ToLocal(sites)),
4300 : MaybeHandle<Object>());
4301 6 : return Utils::OpenHandle(*stack);
4302 : }
4303 :
4304 859504 : int Isolate::LookupOrAddExternallyCompiledFilename(const char* filename) {
4305 859504 : if (embedded_file_writer_ != nullptr) {
4306 : return embedded_file_writer_->LookupOrAddExternallyCompiledFilename(
4307 15214 : filename);
4308 : }
4309 : return 0;
4310 : }
4311 :
4312 0 : const char* Isolate::GetExternallyCompiledFilename(int index) const {
4313 0 : if (embedded_file_writer_ != nullptr) {
4314 0 : return embedded_file_writer_->GetExternallyCompiledFilename(index);
4315 : }
4316 : return "";
4317 : }
4318 :
4319 0 : int Isolate::GetExternallyCompiledFilenameCount() const {
4320 0 : if (embedded_file_writer_ != nullptr) {
4321 0 : return embedded_file_writer_->GetExternallyCompiledFilenameCount();
4322 : }
4323 : return 0;
4324 : }
4325 :
4326 0 : void Isolate::PrepareBuiltinSourcePositionMap() {
4327 56 : if (embedded_file_writer_ != nullptr) {
4328 : return embedded_file_writer_->PrepareBuiltinSourcePositionMap(
4329 2 : this->builtins());
4330 : }
4331 : }
4332 :
4333 : #if defined(V8_OS_WIN_X64)
4334 : void Isolate::SetBuiltinUnwindData(
4335 : int builtin_index,
4336 : const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) {
4337 : if (embedded_file_writer_ != nullptr) {
4338 : embedded_file_writer_->SetBuiltinUnwindData(builtin_index, unwinding_info);
4339 : }
4340 : }
4341 : #endif
4342 :
4343 12 : void Isolate::SetPrepareStackTraceCallback(PrepareStackTraceCallback callback) {
4344 12 : prepare_stack_trace_callback_ = callback;
4345 12 : }
4346 :
4347 15290 : bool Isolate::HasPrepareStackTraceCallback() const {
4348 15290 : return prepare_stack_trace_callback_ != nullptr;
4349 : }
4350 :
4351 13 : void Isolate::SetAtomicsWaitCallback(v8::Isolate::AtomicsWaitCallback callback,
4352 : void* data) {
4353 13 : atomics_wait_callback_ = callback;
4354 13 : atomics_wait_callback_data_ = data;
4355 13 : }
4356 :
4357 1833 : void Isolate::RunAtomicsWaitCallback(v8::Isolate::AtomicsWaitEvent event,
4358 : Handle<JSArrayBuffer> array_buffer,
4359 : size_t offset_in_bytes, int64_t value,
4360 : double timeout_in_ms,
4361 : AtomicsWaitWakeHandle* stop_handle) {
4362 : DCHECK(array_buffer->is_shared());
4363 1833 : if (atomics_wait_callback_ == nullptr) return;
4364 : HandleScope handle_scope(this);
4365 169 : atomics_wait_callback_(
4366 : event, v8::Utils::ToLocalShared(array_buffer), offset_in_bytes, value,
4367 : timeout_in_ms,
4368 : reinterpret_cast<v8::Isolate::AtomicsWaitWakeHandle*>(stop_handle),
4369 169 : atomics_wait_callback_data_);
4370 : }
4371 :
4372 119 : void Isolate::SetPromiseHook(PromiseHook hook) {
4373 119 : promise_hook_ = hook;
4374 119 : PromiseHookStateUpdated();
4375 119 : }
4376 :
4377 99499 : void Isolate::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
4378 : Handle<Object> parent) {
4379 99499 : RunPromiseHookForAsyncEventDelegate(type, promise);
4380 99499 : if (promise_hook_ == nullptr) return;
4381 : promise_hook_(type, v8::Utils::PromiseToLocal(promise),
4382 1145 : v8::Utils::ToLocal(parent));
4383 : }
4384 :
4385 99499 : void Isolate::RunPromiseHookForAsyncEventDelegate(PromiseHookType type,
4386 : Handle<JSPromise> promise) {
4387 99499 : if (!async_event_delegate_) return;
4388 37189 : if (type == PromiseHookType::kResolve) return;
4389 :
4390 21847 : if (type == PromiseHookType::kBefore) {
4391 3655 : if (!promise->async_task_id()) return;
4392 6345 : async_event_delegate_->AsyncEventOccurred(debug::kDebugWillHandle,
4393 4230 : promise->async_task_id(), false);
4394 18192 : } else if (type == PromiseHookType::kAfter) {
4395 3650 : if (!promise->async_task_id()) return;
4396 6300 : async_event_delegate_->AsyncEventOccurred(debug::kDebugDidHandle,
4397 4200 : promise->async_task_id(), false);
4398 : } else {
4399 : DCHECK(type == PromiseHookType::kInit);
4400 : debug::DebugAsyncActionType type = debug::kDebugPromiseThen;
4401 : bool last_frame_was_promise_builtin = false;
4402 14542 : JavaScriptFrameIterator it(this);
4403 28699 : while (!it.done()) {
4404 : std::vector<Handle<SharedFunctionInfo>> infos;
4405 26524 : it.frame()->GetFunctions(&infos);
4406 54838 : for (size_t i = 1; i <= infos.size(); ++i) {
4407 53048 : Handle<SharedFunctionInfo> info = infos[infos.size() - i];
4408 26524 : if (info->IsUserJavaScript()) {
4409 : // We should not report PromiseThen and PromiseCatch which is called
4410 : // indirectly, e.g. Promise.all calls Promise.then internally.
4411 12367 : if (last_frame_was_promise_builtin) {
4412 1855 : if (!promise->async_task_id()) {
4413 3710 : promise->set_async_task_id(++async_task_count_);
4414 : }
4415 7420 : async_event_delegate_->AsyncEventOccurred(
4416 3710 : type, promise->async_task_id(), debug()->IsBlackboxed(info));
4417 : }
4418 : return;
4419 : }
4420 : last_frame_was_promise_builtin = false;
4421 14157 : if (info->HasBuiltinId()) {
4422 14157 : if (info->builtin_id() == Builtins::kPromisePrototypeThen) {
4423 : type = debug::kDebugPromiseThen;
4424 : last_frame_was_promise_builtin = true;
4425 10807 : } else if (info->builtin_id() == Builtins::kPromisePrototypeCatch) {
4426 : type = debug::kDebugPromiseCatch;
4427 : last_frame_was_promise_builtin = true;
4428 10507 : } else if (info->builtin_id() == Builtins::kPromisePrototypeFinally) {
4429 : type = debug::kDebugPromiseFinally;
4430 : last_frame_was_promise_builtin = true;
4431 : }
4432 : }
4433 : }
4434 14157 : it.Advance();
4435 : }
4436 : }
4437 : }
4438 :
4439 3692 : void Isolate::OnAsyncFunctionStateChanged(Handle<JSPromise> promise,
4440 : debug::DebugAsyncActionType event) {
4441 3692 : if (!async_event_delegate_) return;
4442 440 : if (!promise->async_task_id()) {
4443 370 : promise->set_async_task_id(++async_task_count_);
4444 : }
4445 1320 : async_event_delegate_->AsyncEventOccurred(event, promise->async_task_id(),
4446 880 : false);
4447 : }
4448 :
4449 1154 : void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
4450 1154 : promise_reject_callback_ = callback;
4451 1154 : }
4452 :
4453 15707 : void Isolate::ReportPromiseReject(Handle<JSPromise> promise,
4454 : Handle<Object> value,
4455 : v8::PromiseRejectEvent event) {
4456 15707 : if (promise_reject_callback_ == nullptr) return;
4457 490 : promise_reject_callback_(v8::PromiseRejectMessage(
4458 490 : v8::Utils::PromiseToLocal(promise), event, v8::Utils::ToLocal(value)));
4459 : }
4460 :
4461 60 : void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) {
4462 : DCHECK(!use_counter_callback_);
4463 60 : use_counter_callback_ = callback;
4464 60 : }
4465 :
4466 :
4467 2341654 : void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) {
4468 : // The counter callback may cause the embedder to call into V8, which is not
4469 : // generally possible during GC.
4470 2341654 : if (heap_.gc_state() == Heap::NOT_IN_GC) {
4471 2341654 : if (use_counter_callback_) {
4472 : HandleScope handle_scope(this);
4473 199 : use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature);
4474 : }
4475 : } else {
4476 0 : heap_.IncrementDeferredCount(feature);
4477 : }
4478 2341654 : }
4479 :
4480 : // static
4481 55 : std::string Isolate::GetTurboCfgFileName(Isolate* isolate) {
4482 55 : if (FLAG_trace_turbo_cfg_file == nullptr) {
4483 0 : std::ostringstream os;
4484 0 : os << "turbo-" << base::OS::GetCurrentProcessId() << "-";
4485 0 : if (isolate != nullptr) {
4486 0 : os << isolate->id();
4487 : } else {
4488 0 : os << "any";
4489 : }
4490 0 : os << ".cfg";
4491 : return os.str();
4492 : } else {
4493 55 : return FLAG_trace_turbo_cfg_file;
4494 : }
4495 : }
4496 :
4497 : // Heap::detached_contexts tracks detached contexts as pairs
4498 : // (number of GC since the context was detached, the context).
4499 126 : void Isolate::AddDetachedContext(Handle<Context> context) {
4500 : HandleScope scope(this);
4501 : Handle<WeakArrayList> detached_contexts = factory()->detached_contexts();
4502 : detached_contexts = WeakArrayList::AddToEnd(
4503 126 : this, detached_contexts, MaybeObjectHandle(Smi::kZero, this));
4504 : detached_contexts = WeakArrayList::AddToEnd(this, detached_contexts,
4505 126 : MaybeObjectHandle::Weak(context));
4506 : heap()->set_detached_contexts(*detached_contexts);
4507 126 : }
4508 :
4509 :
4510 68864 : void Isolate::CheckDetachedContextsAfterGC() {
4511 : HandleScope scope(this);
4512 : Handle<WeakArrayList> detached_contexts = factory()->detached_contexts();
4513 : int length = detached_contexts->length();
4514 68864 : if (length == 0) return;
4515 : int new_length = 0;
4516 655 : for (int i = 0; i < length; i += 2) {
4517 : int mark_sweeps = detached_contexts->Get(i).ToSmi().value();
4518 : MaybeObject context = detached_contexts->Get(i + 1);
4519 : DCHECK(context->IsWeakOrCleared());
4520 297 : if (!context->IsCleared()) {
4521 729 : detached_contexts->Set(
4522 243 : new_length, MaybeObject::FromSmi(Smi::FromInt(mark_sweeps + 1)));
4523 486 : detached_contexts->Set(new_length + 1, context);
4524 243 : new_length += 2;
4525 : }
4526 : }
4527 : detached_contexts->set_length(new_length);
4528 277 : while (new_length < length) {
4529 108 : detached_contexts->Set(new_length, MaybeObject::FromSmi(Smi::zero()));
4530 108 : ++new_length;
4531 : }
4532 :
4533 61 : if (FLAG_trace_detached_contexts) {
4534 0 : PrintF("%d detached contexts are collected out of %d\n",
4535 0 : length - new_length, length);
4536 0 : for (int i = 0; i < new_length; i += 2) {
4537 : int mark_sweeps = detached_contexts->Get(i).ToSmi().value();
4538 : MaybeObject context = detached_contexts->Get(i + 1);
4539 : DCHECK(context->IsWeakOrCleared());
4540 0 : if (mark_sweeps > 3) {
4541 0 : PrintF("detached context %p\n survived %d GCs (leak?)\n",
4542 0 : reinterpret_cast<void*>(context.ptr()), mark_sweeps);
4543 : }
4544 : }
4545 : }
4546 : }
4547 :
4548 0 : double Isolate::LoadStartTimeMs() {
4549 0 : base::MutexGuard guard(&rail_mutex_);
4550 0 : return load_start_time_ms_;
4551 : }
4552 :
4553 0 : void Isolate::SetRAILMode(RAILMode rail_mode) {
4554 : RAILMode old_rail_mode = rail_mode_.load();
4555 0 : if (old_rail_mode != PERFORMANCE_LOAD && rail_mode == PERFORMANCE_LOAD) {
4556 0 : base::MutexGuard guard(&rail_mutex_);
4557 0 : load_start_time_ms_ = heap()->MonotonicallyIncreasingTimeInMs();
4558 : }
4559 : rail_mode_.store(rail_mode);
4560 0 : if (old_rail_mode == PERFORMANCE_LOAD && rail_mode != PERFORMANCE_LOAD) {
4561 : heap()->incremental_marking()->incremental_marking_job()->ScheduleTask(
4562 0 : heap());
4563 : }
4564 0 : if (FLAG_trace_rail) {
4565 0 : PrintIsolate(this, "RAIL mode: %s\n", RAILModeName(rail_mode));
4566 : }
4567 0 : }
4568 :
4569 0 : void Isolate::IsolateInBackgroundNotification() {
4570 0 : is_isolate_in_background_ = true;
4571 0 : heap()->ActivateMemoryReducerIfNeeded();
4572 0 : }
4573 :
4574 0 : void Isolate::IsolateInForegroundNotification() {
4575 0 : is_isolate_in_background_ = false;
4576 0 : }
4577 :
4578 114 : void Isolate::PrintWithTimestamp(const char* format, ...) {
4579 114 : base::OS::Print("[%d:%p] %8.0f ms: ", base::OS::GetCurrentProcessId(),
4580 114 : static_cast<void*>(this), time_millis_since_init());
4581 : va_list arguments;
4582 114 : va_start(arguments, format);
4583 114 : base::OS::VPrint(format, arguments);
4584 114 : va_end(arguments);
4585 114 : }
4586 :
4587 10 : void Isolate::SetIdle(bool is_idle) {
4588 10 : if (!is_profiling()) return;
4589 : StateTag state = current_vm_state();
4590 : DCHECK(state == EXTERNAL || state == IDLE);
4591 10 : if (js_entry_sp() != kNullAddress) return;
4592 10 : if (is_idle) {
4593 : set_current_vm_state(IDLE);
4594 5 : } else if (state == IDLE) {
4595 : set_current_vm_state(EXTERNAL);
4596 : }
4597 : }
4598 :
4599 : #ifdef V8_INTL_SUPPORT
4600 64958 : icu::UObject* Isolate::get_cached_icu_object(ICUObjectCacheType cache_type) {
4601 64958 : return icu_object_cache_[cache_type].get();
4602 : }
4603 :
4604 149 : void Isolate::set_icu_object_in_cache(ICUObjectCacheType cache_type,
4605 : std::shared_ptr<icu::UObject> obj) {
4606 : icu_object_cache_[cache_type] = obj;
4607 149 : }
4608 :
4609 0 : void Isolate::clear_cached_icu_object(ICUObjectCacheType cache_type) {
4610 : icu_object_cache_.erase(cache_type);
4611 0 : }
4612 : #endif // V8_INTL_SUPPORT
4613 :
4614 2595998 : bool StackLimitCheck::JsHasOverflowed(uintptr_t gap) const {
4615 2595998 : StackGuard* stack_guard = isolate_->stack_guard();
4616 : #ifdef USE_SIMULATOR
4617 : // The simulator uses a separate JS stack.
4618 : Address jssp_address = Simulator::current(isolate_)->get_sp();
4619 : uintptr_t jssp = static_cast<uintptr_t>(jssp_address);
4620 : if (jssp - gap < stack_guard->real_jslimit()) return true;
4621 : #endif // USE_SIMULATOR
4622 2595998 : return GetCurrentStackPosition() - gap < stack_guard->real_climit();
4623 : }
4624 :
4625 20594019 : SaveContext::SaveContext(Isolate* isolate) : isolate_(isolate) {
4626 20594019 : if (!isolate->context().is_null()) {
4627 20387000 : context_ = Handle<Context>(isolate->context(), isolate);
4628 : }
4629 :
4630 20594019 : c_entry_fp_ = isolate->c_entry_fp(isolate->thread_local_top());
4631 20594019 : }
4632 :
4633 41188090 : SaveContext::~SaveContext() {
4634 41188090 : isolate_->set_context(context_.is_null() ? Context() : *context_);
4635 20594045 : }
4636 :
4637 0 : bool SaveContext::IsBelowFrame(StandardFrame* frame) {
4638 0 : return (c_entry_fp_ == 0) || (c_entry_fp_ > frame->sp());
4639 : }
4640 :
4641 373511 : SaveAndSwitchContext::SaveAndSwitchContext(Isolate* isolate,
4642 : Context new_context)
4643 373511 : : SaveContext(isolate) {
4644 : isolate->set_context(new_context);
4645 373511 : }
4646 :
4647 : #ifdef DEBUG
4648 : AssertNoContextChange::AssertNoContextChange(Isolate* isolate)
4649 : : isolate_(isolate), context_(isolate->context(), isolate) {}
4650 : #endif // DEBUG
4651 :
4652 76547 : bool InterruptsScope::Intercept(StackGuard::InterruptFlag flag) {
4653 : InterruptsScope* last_postpone_scope = nullptr;
4654 229865 : for (InterruptsScope* current = this; current; current = current->prev_) {
4655 : // We only consider scopes related to passed flag.
4656 76852 : if (!(current->intercept_mask_ & flag)) continue;
4657 76184 : if (current->mode_ == kRunInterrupts) {
4658 : // If innermost scope is kRunInterrupts scope, prevent interrupt from
4659 : // being intercepted.
4660 : break;
4661 : } else {
4662 : DCHECK_EQ(current->mode_, kPostponeInterrupts);
4663 : last_postpone_scope = current;
4664 : }
4665 : }
4666 : // If there is no postpone scope for passed flag then we should not intercept.
4667 76547 : if (!last_postpone_scope) return false;
4668 75829 : last_postpone_scope->intercepted_flags_ |= flag;
4669 75829 : return true;
4670 : }
4671 :
4672 : #undef TRACE_ISOLATE
4673 :
4674 : } // namespace internal
4675 121996 : } // namespace v8
|