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 62441 : const uint8_t* DefaultEmbeddedBlob() { return v8_Default_embedded_blob_; }
111 62441 : 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 126390 : 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 62496 : void Isolate::SetEmbeddedBlob(const uint8_t* blob, uint32_t blob_size) {
217 62496 : CHECK_NOT_NULL(blob);
218 :
219 62496 : embedded_blob_ = blob;
220 62496 : 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 62496 : }
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 205004877 : const uint8_t* Isolate::embedded_blob() const { return embedded_blob_; }
251 97165341 : uint32_t Isolate::embedded_blob_size() const { return embedded_blob_size_; }
252 :
253 : // static
254 416162865 : const uint8_t* Isolate::CurrentEmbeddedBlob() {
255 416162865 : return current_embedded_blob_.load(std::memory_order::memory_order_relaxed);
256 : }
257 :
258 : // static
259 260438283 : uint32_t Isolate::CurrentEmbeddedBlobSize() {
260 : return current_embedded_blob_size_.load(
261 260438283 : 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 170520 : for (int i = 0; i < Builtins::builtin_count; i++) {
276 85232 : Code code = heap_.builtin(i);
277 :
278 : DCHECK(Internals::HasHeapObjectTag(code.ptr()));
279 : uint8_t* const code_ptr =
280 85232 : 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 2812656 : for (int j = kStartOffset; j < Code::kUnalignedHeaderSize; j++) {
292 1363712 : 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 328485 : Isolate::FindOrAllocatePerThreadDataForThisThread() {
317 : ThreadId thread_id = ThreadId::Current();
318 : PerIsolateThreadData* per_thread = nullptr;
319 : {
320 328478 : base::MutexGuard lock_guard(&thread_data_table_mutex_);
321 : per_thread = thread_data_table_.Lookup(thread_id);
322 328489 : if (per_thread == nullptr) {
323 67977 : per_thread = new PerIsolateThreadData(this, thread_id);
324 67977 : thread_data_table_.Insert(per_thread);
325 : }
326 : DCHECK(thread_data_table_.Lookup(thread_id) == per_thread);
327 : }
328 328498 : return per_thread;
329 : }
330 :
331 :
332 1498 : void Isolate::DiscardPerThreadDataForThisThread() {
333 1498 : 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 61008 : void Isolate::InitializeOncePerProcess() {
365 61008 : 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 61008 : per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey();
372 61008 : }
373 :
374 801480 : Address Isolate::get_address_from_id(IsolateAddressId id) {
375 801480 : return isolate_addresses_[id];
376 : }
377 :
378 6336 : char* Isolate::Iterate(RootVisitor* v, char* thread_storage) {
379 : ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
380 6336 : Iterate(v, thread);
381 6336 : return thread_storage + sizeof(ThreadLocalTop);
382 : }
383 :
384 :
385 215 : void Isolate::IterateThread(ThreadVisitor* v, char* t) {
386 : ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
387 215 : v->VisitThread(this, thread);
388 215 : }
389 :
390 281875 : void Isolate::Iterate(RootVisitor* v, ThreadLocalTop* thread) {
391 : // Visit the roots from the top for a given thread.
392 281875 : v->VisitRootPointer(Root::kTop, nullptr,
393 563750 : FullObjectSlot(&thread->pending_exception_));
394 281875 : v->VisitRootPointer(Root::kTop, nullptr,
395 563750 : FullObjectSlot(&thread->pending_message_obj_));
396 563750 : v->VisitRootPointer(Root::kTop, nullptr, FullObjectSlot(&thread->context_));
397 281875 : v->VisitRootPointer(Root::kTop, nullptr,
398 563750 : FullObjectSlot(&thread->scheduled_exception_));
399 :
400 448466 : 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 333182 : v->VisitRootPointer(
404 : Root::kTop, nullptr,
405 333182 : FullObjectSlot(reinterpret_cast<Address>(&(block->exception_))));
406 333182 : v->VisitRootPointer(
407 : Root::kTop, nullptr,
408 333182 : FullObjectSlot(reinterpret_cast<Address>(&(block->message_obj_))));
409 : }
410 :
411 : // Iterate over pointers on native execution stack.
412 563750 : wasm::WasmCodeRefScope wasm_code_ref_scope;
413 4984898 : for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
414 4703023 : it.frame()->Iterate(v);
415 : }
416 281875 : }
417 :
418 275539 : void Isolate::Iterate(RootVisitor* v) {
419 : ThreadLocalTop* current_t = thread_local_top();
420 275539 : Iterate(v, current_t);
421 275539 : }
422 :
423 275539 : void Isolate::IterateDeferredHandles(RootVisitor* visitor) {
424 279289 : for (DeferredHandles* deferred = deferred_handles_head_; deferred != nullptr;
425 : deferred = deferred->next_) {
426 3750 : deferred->Iterate(visitor);
427 : }
428 275539 : }
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 20997455 : void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
460 20997455 : thread_local_top()->try_catch_handler_ = that;
461 20997455 : }
462 :
463 :
464 20997466 : void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
465 : DCHECK(thread_local_top()->try_catch_handler_ == that);
466 20997466 : thread_local_top()->try_catch_handler_ = that->next_;
467 20997466 : }
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 61856 : static MaybeHandle<StackTraceFrame> LookupCachedFrame(
543 : Isolate* isolate, Handle<AbstractCode> code, int code_offset) {
544 61856 : if (FLAG_optimize_for_size) return MaybeHandle<StackTraceFrame>();
545 :
546 123712 : const auto maybe_cache = handle(code->stack_frame_cache(), isolate);
547 61856 : if (!maybe_cache->IsSimpleNumberDictionary())
548 8194 : return MaybeHandle<StackTraceFrame>();
549 :
550 : const auto cache = Handle<SimpleNumberDictionary>::cast(maybe_cache);
551 107324 : const int entry = cache->FindEntry(isolate, code_offset);
552 53662 : if (entry != NumberDictionary::kNotFound) {
553 51284 : 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 1315670 : 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 1315670 : check_security_context_(filter_mode == CURRENT_SECURITY_CONTEXT) {
589 1315670 : 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 1292676 : skip_next_frame_ = false;
599 1292676 : break;
600 : }
601 :
602 1315670 : elements_ = isolate->factory()->NewFrameArray(Min(limit, 10));
603 1315670 : }
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 4984423 : void AppendJavaScriptFrame(
653 : FrameSummary::JavaScriptFrameSummary const& summary) {
654 : // Filter out internal frames that we do not want to show.
655 4992479 : if (!IsVisibleInStackTrace(summary.function())) return;
656 :
657 4976367 : 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 4976367 : Handle<JSFunction> function = summary.function();
664 4976367 : if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
665 4976367 : if (is_constructor) flags |= FrameArray::kIsConstructor;
666 :
667 9952734 : Handle<FixedArray> parameters = isolate_->factory()->empty_fixed_array();
668 4976367 : 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 4976367 : 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 61925 : void AppendBuiltinExitFrame(BuiltinExitFrame* exit_frame) {
706 123850 : Handle<JSFunction> function = handle(exit_frame->function(), isolate_);
707 :
708 : // Filter out internal frames that we do not want to show.
709 92322 : if (!IsVisibleInStackTrace(function)) return;
710 :
711 31528 : Handle<Object> receiver(exit_frame->receiver(), isolate_);
712 31528 : Handle<Code> code(exit_frame->LookupCode(), isolate_);
713 : const int offset =
714 94584 : static_cast<int>(exit_frame->pc() - code->InstructionStart());
715 :
716 : int flags = 0;
717 31528 : if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
718 31528 : if (exit_frame->IsConstructor()) flags |= FrameArray::kIsConstructor;
719 :
720 31528 : Handle<FixedArray> parameters = isolate_->factory()->empty_fixed_array();
721 31528 : 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 31528 : offset, flags, parameters);
732 : }
733 :
734 14707043 : bool full() { return elements_->FrameCount() >= limit_; }
735 :
736 : Handle<FrameArray> GetElements() {
737 2501360 : elements_->ShrinkToFit(isolate_);
738 1250680 : return elements_;
739 : }
740 :
741 : // Creates a StackTraceFrame object for each frame in the FrameArray.
742 64990 : Handle<FixedArray> GetElementsAsStackTraceFrameArray() {
743 129980 : elements_->ShrinkToFit(isolate_);
744 : const int frame_count = elements_->FrameCount();
745 : Handle<FixedArray> stack_trace =
746 64990 : isolate_->factory()->NewFixedArray(frame_count);
747 :
748 189598 : for (int i = 0; i < frame_count; ++i) {
749 : // Caching stack frames only happens for non-Wasm frames.
750 62304 : if (!elements_->IsAnyWasmFrame(i)) {
751 : MaybeHandle<StackTraceFrame> maybe_frame =
752 : StackFrameCacheHelper::LookupCachedFrame(
753 : isolate_, handle(elements_->Code(i), isolate_),
754 123712 : Smi::ToInt(elements_->Offset(i)));
755 61856 : if (!maybe_frame.is_null()) {
756 : Handle<StackTraceFrame> frame = maybe_frame.ToHandleChecked();
757 102568 : 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 64990 : 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 5009250 : bool IsStrictFrame(Handle<JSFunction> function) {
781 5009250 : if (!encountered_strict_function_) {
782 : encountered_strict_function_ =
783 3698738 : is_strict(function->shared()->language_mode());
784 : }
785 5009250 : return encountered_strict_function_;
786 : }
787 :
788 : // Determines whether the given stack frame should be displayed in a stack
789 : // trace.
790 5047811 : bool IsVisibleInStackTrace(Handle<JSFunction> function) {
791 10059545 : return ShouldIncludeFrame(function) && IsNotHidden(function) &&
792 5047811 : 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 5047811 : bool ShouldIncludeFrame(Handle<JSFunction> function) {
800 5047811 : 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 166949 : if (skip_next_frame_ && (*function == *caller_)) {
809 22143 : skip_next_frame_ = false;
810 22143 : return false;
811 : }
812 119180 : return !skip_next_frame_;
813 : }
814 0 : UNREACHABLE();
815 : }
816 :
817 5021595 : 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 15064641 : if (!FLAG_builtins_in_stack_traces &&
823 10043046 : !function->shared()->IsUserJavaScript()) {
824 : return function->shared()->native();
825 : }
826 : return true;
827 : }
828 :
829 : bool IsInSameSecurityContext(Handle<JSFunction> function) {
830 5011734 : if (!check_security_context_) return true;
831 4950744 : 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 4976367 : : 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 1258201 : bool GetStackTraceLimit(Isolate* isolate, int* result) {
853 1258201 : Handle<JSObject> error = isolate->error_function();
854 :
855 : Handle<String> key = isolate->factory()->stackTraceLimit_string();
856 1258201 : Handle<Object> stack_trace_limit = JSReceiver::GetDataProperty(error, key);
857 1258201 : if (!stack_trace_limit->IsNumber()) return false;
858 :
859 : // Ensure that limit is not negative.
860 1250680 : *result = Max(FastD2IChecked(stack_trace_limit->Number()), 0);
861 :
862 1250680 : if (*result != FLAG_stack_trace_limit) {
863 54 : isolate->CountUsage(v8::Isolate::kErrorStackTraceLimit);
864 : }
865 :
866 : return true;
867 : }
868 :
869 280426 : bool NoExtension(const v8::FunctionCallbackInfo<v8::Value>&) { return false; }
870 :
871 673065 : bool IsBuiltinFunction(Isolate* isolate, HeapObject object,
872 : Builtins::Name builtin_index) {
873 673065 : if (!object->IsJSFunction()) return false;
874 : JSFunction const function = JSFunction::cast(object);
875 901634 : return function->code() == isolate->builtins()->builtin(builtin_index);
876 : }
877 :
878 2954 : void CaptureAsyncStackTrace(Isolate* isolate, Handle<JSPromise> promise,
879 : FrameArrayBuilder* builder) {
880 170388 : while (!builder->full()) {
881 : // Check that the {promise} is not settled.
882 170379 : if (promise->status() != Promise::kPending) return;
883 :
884 : // Check that we have exactly one PromiseReaction on the {promise}.
885 170341 : if (!promise->reactions()->IsPromiseReaction()) return;
886 : Handle<PromiseReaction> reaction(
887 : PromiseReaction::cast(promise->reactions()), isolate);
888 167434 : 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 334868 : if (IsBuiltinFunction(isolate, reaction->fulfill_handler(),
893 166151 : Builtins::kAsyncFunctionAwaitResolveClosure) ||
894 166151 : IsBuiltinFunction(isolate, reaction->fulfill_handler(),
895 333549 : Builtins::kAsyncGeneratorAwaitResolveClosure) ||
896 166115 : 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 166079 : } 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 165971 : 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 1315670 : Handle<Object> CaptureStackTrace(Isolate* isolate, Handle<Object> caller,
985 : CaptureStackTraceOptions options) {
986 2631340 : DisallowJavascriptExecution no_js(isolate);
987 :
988 2631340 : wasm::WasmCodeRefScope code_ref_scope;
989 : FrameArrayBuilder builder(isolate, options.skip_mode, options.limit, caller,
990 1315670 : 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 10707498 : for (StackFrameIterator it(isolate); !it.done() && !builder.full();
996 9142026 : it.Advance()) {
997 : StackFrame* const frame = it.frame();
998 9142026 : 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 4988822 : std::vector<FrameSummary> frames;
1009 4988822 : StandardFrame::cast(frame)->Summarize(&frames);
1010 15275416 : for (size_t i = frames.size(); i-- != 0 && !builder.full();) {
1011 : auto& summary = frames[i];
1012 5207709 : if (options.capture_only_frames_subject_to_debugging &&
1013 64479 : !summary.is_subject_to_debugging()) {
1014 : continue;
1015 : }
1016 :
1017 5141055 : if (summary.IsJavaScript()) {
1018 : //=========================================================
1019 : // Handle a JavaScript frame.
1020 : //=========================================================
1021 : auto const& java_script = summary.AsJavaScript();
1022 4984423 : 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 69801 : 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 61925 : 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 1315670 : if (options.async_stack_trace) {
1057 : Handle<Object> current_microtask = isolate->factory()->current_microtask();
1058 1250302 : 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 6162 : if (IsBuiltinFunction(isolate, promise_reaction_job_task->handler(),
1064 2170 : Builtins::kAsyncFunctionAwaitResolveClosure) ||
1065 2170 : IsBuiltinFunction(isolate, promise_reaction_job_task->handler(),
1066 5116 : Builtins::kAsyncGeneratorAwaitResolveClosure) ||
1067 2035 : 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 2035 : if (promise_or_capability->IsJSPromise()) {
1102 : Handle<JSPromise> promise =
1103 1927 : Handle<JSPromise>::cast(promise_or_capability);
1104 1927 : CaptureAsyncStackTrace(isolate, promise, &builder);
1105 : }
1106 : }
1107 : }
1108 : }
1109 :
1110 : // TODO(yangguo): Queue this structured stack trace for preprocessing on GC.
1111 1315670 : if (options.capture_result == CaptureStackTraceOptions::RAW_FRAME_ARRAY) {
1112 1250680 : return builder.GetElements();
1113 : }
1114 64990 : return builder.GetElementsAsStackTraceFrameArray();
1115 : }
1116 :
1117 : } // namespace
1118 :
1119 1258201 : Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
1120 : FrameSkipMode mode,
1121 : Handle<Object> caller) {
1122 : int limit;
1123 1265722 : if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value();
1124 :
1125 : CaptureStackTraceOptions options;
1126 1250680 : options.limit = limit;
1127 : options.skip_mode = mode;
1128 : options.capture_builtin_exit_frames = true;
1129 1250680 : 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 1250680 : return CaptureStackTrace(this, caller, options);
1135 : }
1136 :
1137 1209921 : MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace(
1138 : Handle<JSReceiver> error_object) {
1139 1209921 : 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 1209921 : return error_object;
1153 : }
1154 :
1155 1258201 : 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 1258201 : CaptureSimpleStackTrace(error_object, mode, caller);
1162 2516402 : RETURN_ON_EXCEPTION(this,
1163 : Object::SetProperty(this, error_object, key, stack_trace,
1164 : StoreOrigin::kMaybeKeyed,
1165 : Just(ShouldThrow::kThrowOnError)),
1166 : JSReceiver);
1167 1258201 : 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 64990 : 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 64990 : (stack_trace_options & StackTrace::kExposeFramesAcrossSecurityOrigins)
1225 : ? FrameArrayBuilder::ALL
1226 64990 : : 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 64990 : 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 6040679 : 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 6040679 : if (bootstrapper()->IsActive()) return true;
1331 : {
1332 : DisallowHeapAllocation no_gc;
1333 :
1334 6040441 : if (receiver->IsJSGlobalProxy()) {
1335 : Object receiver_context =
1336 : JSGlobalProxy::cast(*receiver)->native_context();
1337 12075937 : 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 12076944 : accessing_context->global_object()->native_context();
1343 6038472 : 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 48280 : Object Isolate::StackOverflow() {
1373 48280 : if (FLAG_abort_on_stack_or_string_length_overflow) {
1374 0 : FATAL("Aborting on stack overflow");
1375 : }
1376 :
1377 96560 : DisallowJavascriptExecution no_js(this);
1378 : HandleScope scope(this);
1379 :
1380 48280 : Handle<JSFunction> fun = range_error_function();
1381 : Handle<Object> msg = factory()->NewStringFromAsciiChecked(
1382 48280 : MessageFormatter::TemplateString(MessageTemplate::kStackOverflow));
1383 : Handle<Object> no_caller;
1384 : Handle<Object> exception;
1385 96560 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1386 : this, exception,
1387 : ErrorUtils::Construct(this, fun, fun, msg, SKIP_NONE, no_caller, true));
1388 :
1389 48280 : 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 48280 : return ReadOnlyRoots(heap()).exception();
1399 : }
1400 :
1401 4206 : Object Isolate::TerminateExecution() {
1402 4206 : 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 3078 : if (has_scheduled_exception() &&
1415 : scheduled_exception() == ReadOnlyRoots(this).termination_exception()) {
1416 62 : 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 2165 : void Isolate::InvokeApiInterruptCallbacks() {
1430 : RuntimeCallTimerScope runtimeTimer(
1431 2165 : 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 64525 : 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 1414095 : 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 1414095 : 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 1128613 : bool requires_message = try_catch_handler() == nullptr ||
1553 1472359 : try_catch_handler()->is_verbose_ ||
1554 58264 : try_catch_handler()->capture_message_;
1555 1414095 : bool rethrowing_message = thread_local_top()->rethrowing_message_;
1556 :
1557 1414095 : thread_local_top()->rethrowing_message_ = false;
1558 :
1559 : // Notify debugger of exception.
1560 1414095 : if (is_catchable_by_javascript(raw_exception)) {
1561 1409889 : debug()->OnThrow(exception);
1562 : }
1563 :
1564 : // Generate the message if required.
1565 1414095 : if (requires_message && !rethrowing_message) {
1566 1362635 : MessageLocation computed_location;
1567 : // If no location was specified we try to use a computed one instead.
1568 1362635 : if (location == nullptr && ComputeLocation(&computed_location)) {
1569 : location = &computed_location;
1570 : }
1571 :
1572 1362635 : 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 1362605 : Handle<Object> message_obj = CreateMessage(exception, location);
1579 1362605 : 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 1362605 : 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 2828190 : 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 1314162 : Object Isolate::UnwindAndFindHandler() {
1620 1314162 : 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 1314162 : thread_local_top()->pending_handler_context_ = context;
1628 : thread_local_top()->pending_handler_entrypoint_ =
1629 1314162 : instruction_start + handler_offset;
1630 1314162 : thread_local_top()->pending_handler_constant_pool_ = constant_pool_address;
1631 1314162 : thread_local_top()->pending_handler_fp_ = handler_fp;
1632 1314162 : thread_local_top()->pending_handler_sp_ = handler_sp;
1633 :
1634 : // Return and clear pending exception.
1635 : clear_pending_exception();
1636 1314162 : 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 22846803 : for (StackFrameIterator iter(this);; iter.Advance()) {
1646 : // Handler must exist.
1647 : DCHECK(!iter.done());
1648 :
1649 : StackFrame* frame = iter.frame();
1650 :
1651 22846803 : 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 120477 : thread_local_top()->handler_ = handler->next_address();
1659 :
1660 : // Gather information from the handler.
1661 120477 : Code code = frame->LookupCode();
1662 120477 : HandlerTable table(code);
1663 : return FoundHandler(Context(), code->InstructionStart(),
1664 120477 : table.LookupReturn(0), code->constant_pool(),
1665 : handler->address() + StackHandlerConstants::kSize,
1666 120477 : 0);
1667 : }
1668 :
1669 : case StackFrame::WASM_COMPILED: {
1670 2616503 : if (trap_handler::IsThreadInWasm()) {
1671 : trap_handler::ClearThreadInWasm();
1672 : }
1673 :
1674 : // For WebAssembly frames we perform a lookup in the handler table.
1675 2616503 : 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 2616495 : wasm::WasmCodeRefScope code_ref_scope;
1680 : WasmCompiledFrame* wasm_frame = static_cast<WasmCompiledFrame*>(frame);
1681 2616495 : int stack_slots = 0; // Will contain stack slot count of frame.
1682 2616495 : int offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots);
1683 2616495 : 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::WASM_COMPILE_LAZY: {
1702 : // Can only fail directly on invocation. This happens if an invalid
1703 : // function was validated lazily.
1704 : DCHECK_IMPLIES(trap_handler::IsTrapHandlerEnabled(),
1705 : trap_handler::IsThreadInWasm());
1706 : DCHECK(FLAG_wasm_lazy_validation);
1707 : trap_handler::ClearThreadInWasm();
1708 : break;
1709 : }
1710 :
1711 : case StackFrame::OPTIMIZED: {
1712 : // For optimized frames we perform a lookup in the handler table.
1713 3322413 : if (!catchable_by_js) break;
1714 : OptimizedFrame* js_frame = static_cast<OptimizedFrame*>(frame);
1715 3322050 : int stack_slots = 0; // Will contain stack slot count of frame.
1716 : int offset =
1717 3322050 : js_frame->LookupExceptionHandlerInTable(&stack_slots, nullptr);
1718 3322050 : if (offset < 0) break;
1719 : // Compute the stack pointer from the frame pointer. This ensures
1720 : // that argument slots on the stack are dropped as returning would.
1721 : Address return_sp = frame->fp() +
1722 330372 : StandardFrameConstants::kFixedFrameSizeAboveFp -
1723 660744 : stack_slots * kSystemPointerSize;
1724 :
1725 : // Gather information from the frame.
1726 330372 : Code code = frame->LookupCode();
1727 :
1728 : // TODO(bmeurer): Turbofanned BUILTIN frames appear as OPTIMIZED,
1729 : // but do not have a code kind of OPTIMIZED_FUNCTION.
1730 588247 : if (code->kind() == Code::OPTIMIZED_FUNCTION &&
1731 257875 : code->marked_for_deoptimization()) {
1732 : // If the target code is lazy deoptimized, we jump to the original
1733 : // return address, but we make a note that we are throwing, so
1734 : // that the deoptimizer can do the right thing.
1735 12218 : offset = static_cast<int>(frame->pc() - code->entry());
1736 : set_deoptimizer_lazy_throw(true);
1737 : }
1738 :
1739 : return FoundHandler(Context(), code->InstructionStart(), offset,
1740 330372 : code->constant_pool(), return_sp, frame->fp());
1741 : }
1742 :
1743 : case StackFrame::STUB: {
1744 : // Some stubs are able to handle exceptions.
1745 1055145 : if (!catchable_by_js) break;
1746 : StubFrame* stub_frame = static_cast<StubFrame*>(frame);
1747 1053799 : wasm::WasmCodeRefScope code_ref_scope;
1748 : wasm::WasmCode* wasm_code =
1749 1053799 : wasm_engine()->code_manager()->LookupCode(frame->pc());
1750 1053799 : if (wasm_code != nullptr) {
1751 : // It is safe to skip Wasm runtime stubs as none of them contain local
1752 : // exception handlers.
1753 0 : CHECK_EQ(wasm::WasmCode::kRuntimeStub, wasm_code->kind());
1754 0 : CHECK_EQ(0, wasm_code->handler_table_size());
1755 1008195 : break;
1756 : }
1757 1053799 : Code code = stub_frame->LookupCode();
1758 2558654 : if (!code->IsCode() || code->kind() != Code::BUILTIN ||
1759 1550459 : !code->has_handler_table() || !code->is_turbofanned()) {
1760 : break;
1761 : }
1762 :
1763 45604 : int stack_slots = 0; // Will contain stack slot count of frame.
1764 45604 : int offset = stub_frame->LookupExceptionHandlerInTable(&stack_slots);
1765 45604 : if (offset < 0) break;
1766 :
1767 : // Compute the stack pointer from the frame pointer. This ensures
1768 : // that argument slots on the stack are dropped as returning would.
1769 : Address return_sp = frame->fp() +
1770 45604 : StandardFrameConstants::kFixedFrameSizeAboveFp -
1771 91208 : stack_slots * kSystemPointerSize;
1772 :
1773 : return FoundHandler(Context(), code->InstructionStart(), offset,
1774 45604 : code->constant_pool(), return_sp, frame->fp());
1775 : }
1776 :
1777 : case StackFrame::INTERPRETED: {
1778 : // For interpreted frame we perform a range lookup in the handler table.
1779 13294351 : if (!catchable_by_js) break;
1780 : InterpretedFrame* js_frame = static_cast<InterpretedFrame*>(frame);
1781 : int register_slots = InterpreterFrameConstants::RegisterStackSlotCount(
1782 26581706 : js_frame->GetBytecodeArray()->register_count());
1783 13290853 : int context_reg = 0; // Will contain register index holding context.
1784 : int offset =
1785 13290853 : js_frame->LookupExceptionHandlerInTable(&context_reg, nullptr);
1786 13290853 : if (offset < 0) break;
1787 : // Compute the stack pointer from the frame pointer. This ensures that
1788 : // argument slots on the stack are dropped as returning would.
1789 : // Note: This is only needed for interpreted frames that have been
1790 : // materialized by the deoptimizer. If there is a handler frame
1791 : // in between then {frame->sp()} would already be correct.
1792 : Address return_sp = frame->fp() -
1793 817045 : InterpreterFrameConstants::kFixedFrameSizeFromFp -
1794 1634090 : register_slots * kSystemPointerSize;
1795 :
1796 : // Patch the bytecode offset in the interpreted frame to reflect the
1797 : // position of the exception handler. The special builtin below will
1798 : // take care of continuing to dispatch at that position. Also restore
1799 : // the correct context for the handler from the interpreter register.
1800 : Context context =
1801 817045 : Context::cast(js_frame->ReadInterpreterRegister(context_reg));
1802 817045 : js_frame->PatchBytecodeOffset(static_cast<int>(offset));
1803 :
1804 : Code code =
1805 817045 : builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
1806 : return FoundHandler(context, code->InstructionStart(), 0,
1807 1634090 : code->constant_pool(), return_sp, frame->fp());
1808 : }
1809 :
1810 : case StackFrame::BUILTIN:
1811 : // For builtin frames we are guaranteed not to find a handler.
1812 0 : if (catchable_by_js) {
1813 0 : CHECK_EQ(-1,
1814 : JavaScriptFrame::cast(frame)->LookupExceptionHandlerInTable(
1815 : nullptr, nullptr));
1816 : }
1817 : break;
1818 :
1819 : case StackFrame::WASM_INTERPRETER_ENTRY: {
1820 3374 : if (trap_handler::IsThreadInWasm()) {
1821 : trap_handler::ClearThreadInWasm();
1822 : }
1823 : } break;
1824 :
1825 : case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH: {
1826 : // Builtin continuation frames with catch can handle exceptions.
1827 8 : if (!catchable_by_js) break;
1828 : JavaScriptBuiltinContinuationWithCatchFrame* js_frame =
1829 : JavaScriptBuiltinContinuationWithCatchFrame::cast(frame);
1830 8 : js_frame->SetException(exception);
1831 :
1832 : // Reconstruct the stack pointer from the frame pointer.
1833 8 : Address return_sp = js_frame->fp() - js_frame->GetSPToFPDelta();
1834 8 : Code code = js_frame->LookupCode();
1835 : return FoundHandler(Context(), code->InstructionStart(), 0,
1836 8 : code->constant_pool(), return_sp, frame->fp());
1837 : } break;
1838 :
1839 : default:
1840 : // All other types can not handle exception.
1841 : break;
1842 : }
1843 :
1844 21532641 : if (frame->is_optimized()) {
1845 : // Remove per-frame stored materialized objects.
1846 2992041 : bool removed = materialized_object_store_->Remove(frame->fp());
1847 : USE(removed);
1848 : // If there were any materialized objects, the code should be
1849 : // marked for deopt.
1850 : DCHECK_IMPLIES(removed, frame->LookupCode()->marked_for_deoptimization());
1851 : }
1852 : }
1853 :
1854 : UNREACHABLE();
1855 : }
1856 :
1857 : namespace {
1858 310340 : HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) {
1859 : HandlerTable::CatchPrediction prediction;
1860 620680 : if (frame->is_optimized()) {
1861 45551 : if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) {
1862 : // This optimized frame will catch. It's handler table does not include
1863 : // exception prediction, and we need to use the corresponding handler
1864 : // tables on the unoptimized code objects.
1865 101 : std::vector<FrameSummary> summaries;
1866 1375 : frame->Summarize(&summaries);
1867 1591 : for (size_t i = summaries.size(); i != 0; i--) {
1868 1382 : const FrameSummary& summary = summaries[i - 1];
1869 : Handle<AbstractCode> code = summary.AsJavaScript().abstract_code();
1870 1884 : if (code->IsCode() && code->kind() == AbstractCode::BUILTIN) {
1871 502 : prediction = code->GetCode()->GetBuiltinCatchPrediction();
1872 610 : if (prediction == HandlerTable::UNCAUGHT) continue;
1873 1274 : return prediction;
1874 : }
1875 :
1876 : // Must have been constructed from a bytecode array.
1877 880 : CHECK_EQ(AbstractCode::INTERPRETED_FUNCTION, code->kind());
1878 880 : int code_offset = summary.code_offset();
1879 880 : HandlerTable table(code->GetBytecodeArray());
1880 880 : int index = table.LookupRange(code_offset, nullptr, &prediction);
1881 880 : if (index <= 0) continue;
1882 873 : if (prediction == HandlerTable::UNCAUGHT) continue;
1883 : return prediction;
1884 : }
1885 : }
1886 264789 : } else if (frame->LookupExceptionHandlerInTable(nullptr, &prediction) > 0) {
1887 6140 : return prediction;
1888 : }
1889 : return HandlerTable::UNCAUGHT;
1890 : }
1891 :
1892 159666 : Isolate::CatchType ToCatchType(HandlerTable::CatchPrediction prediction) {
1893 159666 : switch (prediction) {
1894 : case HandlerTable::UNCAUGHT:
1895 : return Isolate::NOT_CAUGHT;
1896 : case HandlerTable::CAUGHT:
1897 2429 : return Isolate::CAUGHT_BY_JAVASCRIPT;
1898 : case HandlerTable::PROMISE:
1899 1261 : return Isolate::CAUGHT_BY_PROMISE;
1900 : case HandlerTable::DESUGARING:
1901 0 : return Isolate::CAUGHT_BY_DESUGARING;
1902 : case HandlerTable::ASYNC_AWAIT:
1903 2102 : return Isolate::CAUGHT_BY_ASYNC_AWAIT;
1904 : default:
1905 0 : UNREACHABLE();
1906 : }
1907 : }
1908 : } // anonymous namespace
1909 :
1910 6283 : Isolate::CatchType Isolate::PredictExceptionCatcher() {
1911 : Address external_handler = thread_local_top()->try_catch_handler_address();
1912 6283 : if (IsExternalHandlerOnTop(Object())) return CAUGHT_BY_EXTERNAL;
1913 :
1914 : // Search for an exception handler by performing a full walk over the stack.
1915 172780 : for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) {
1916 : StackFrame* frame = iter.frame();
1917 :
1918 172448 : switch (frame->type()) {
1919 : case StackFrame::ENTRY:
1920 : case StackFrame::CONSTRUCT_ENTRY: {
1921 : Address entry_handler = frame->top_handler()->next_address();
1922 : // The exception has been externally caught if and only if there is an
1923 : // external handler which is on top of the top-most JS_ENTRY handler.
1924 857 : if (external_handler != kNullAddress &&
1925 351 : !try_catch_handler()->is_verbose_) {
1926 256 : if (entry_handler == kNullAddress ||
1927 128 : entry_handler > external_handler) {
1928 : return CAUGHT_BY_EXTERNAL;
1929 : }
1930 : }
1931 : } break;
1932 :
1933 : // For JavaScript frames we perform a lookup in the handler table.
1934 : case StackFrame::OPTIMIZED:
1935 : case StackFrame::INTERPRETED:
1936 : case StackFrame::BUILTIN: {
1937 : JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
1938 158756 : Isolate::CatchType prediction = ToCatchType(PredictException(js_frame));
1939 158756 : if (prediction == NOT_CAUGHT) break;
1940 : return prediction;
1941 : } break;
1942 :
1943 : case StackFrame::STUB: {
1944 5290 : Handle<Code> code(frame->LookupCode(), this);
1945 11490 : if (!code->IsCode() || code->kind() != Code::BUILTIN ||
1946 7110 : !code->has_handler_table() || !code->is_turbofanned()) {
1947 : break;
1948 : }
1949 :
1950 910 : CatchType prediction = ToCatchType(code->GetBuiltinCatchPrediction());
1951 910 : if (prediction != NOT_CAUGHT) return prediction;
1952 : } break;
1953 :
1954 : case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH: {
1955 0 : Handle<Code> code(frame->LookupCode(), this);
1956 0 : CatchType prediction = ToCatchType(code->GetBuiltinCatchPrediction());
1957 0 : if (prediction != NOT_CAUGHT) return prediction;
1958 : } break;
1959 :
1960 : default:
1961 : // All other types can not handle exception.
1962 : break;
1963 : }
1964 : }
1965 :
1966 : // Handler not found.
1967 332 : return NOT_CAUGHT;
1968 : }
1969 :
1970 5 : Object Isolate::ThrowIllegalOperation() {
1971 5 : if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
1972 5 : return Throw(ReadOnlyRoots(heap()).illegal_access_string());
1973 : }
1974 :
1975 30127 : void Isolate::ScheduleThrow(Object exception) {
1976 : // When scheduling a throw we first throw the exception to get the
1977 : // error reporting if it is uncaught before rescheduling it.
1978 30127 : Throw(exception);
1979 30127 : PropagatePendingExceptionToExternalTryCatch();
1980 30127 : if (has_pending_exception()) {
1981 30127 : thread_local_top()->scheduled_exception_ = pending_exception();
1982 30127 : thread_local_top()->external_caught_exception_ = false;
1983 : clear_pending_exception();
1984 : }
1985 30127 : }
1986 :
1987 121 : void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) {
1988 : DCHECK(handler == try_catch_handler());
1989 : DCHECK(handler->HasCaught());
1990 : DCHECK(handler->rethrow_);
1991 : DCHECK(handler->capture_message_);
1992 121 : Object message(reinterpret_cast<Address>(handler->message_obj_));
1993 : DCHECK(message->IsJSMessageObject() || message->IsTheHole(this));
1994 121 : thread_local_top()->pending_message_obj_ = message;
1995 121 : }
1996 :
1997 :
1998 273 : void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) {
1999 : DCHECK(has_scheduled_exception());
2000 546 : if (reinterpret_cast<void*>(scheduled_exception().ptr()) ==
2001 273 : handler->exception_) {
2002 : DCHECK_NE(scheduled_exception(),
2003 : ReadOnlyRoots(heap()).termination_exception());
2004 : clear_scheduled_exception();
2005 : } else {
2006 : DCHECK_EQ(scheduled_exception(),
2007 : ReadOnlyRoots(heap()).termination_exception());
2008 : // Clear termination once we returned from all V8 frames.
2009 183 : if (handle_scope_implementer()->CallDepthIsZero()) {
2010 133 : thread_local_top()->external_caught_exception_ = false;
2011 : clear_scheduled_exception();
2012 : }
2013 : }
2014 546 : if (reinterpret_cast<void*>(thread_local_top()->pending_message_obj_.ptr()) ==
2015 273 : handler->message_obj_) {
2016 : clear_pending_message();
2017 : }
2018 273 : }
2019 :
2020 31273 : Object Isolate::PromoteScheduledException() {
2021 : Object thrown = scheduled_exception();
2022 : clear_scheduled_exception();
2023 : // Re-throw the exception to avoid getting repeated error reporting.
2024 31273 : return ReThrow(thrown);
2025 : }
2026 :
2027 0 : void Isolate::PrintCurrentStackTrace(FILE* out) {
2028 0 : IncrementalStringBuilder builder(this);
2029 0 : for (StackTraceFrameIterator it(this); !it.done(); it.Advance()) {
2030 0 : if (!it.is_javascript()) continue;
2031 :
2032 : HandleScope scope(this);
2033 : JavaScriptFrame* frame = it.javascript_frame();
2034 :
2035 0 : Handle<Object> receiver(frame->receiver(), this);
2036 0 : Handle<JSFunction> function(frame->function(), this);
2037 : Handle<AbstractCode> code;
2038 : int offset;
2039 0 : if (frame->is_interpreted()) {
2040 : InterpretedFrame* interpreted_frame = InterpretedFrame::cast(frame);
2041 0 : code = handle(AbstractCode::cast(interpreted_frame->GetBytecodeArray()),
2042 : this);
2043 0 : offset = interpreted_frame->GetBytecodeOffset();
2044 : } else {
2045 0 : code = handle(AbstractCode::cast(frame->LookupCode()), this);
2046 0 : offset = static_cast<int>(frame->pc() - code->InstructionStart());
2047 : }
2048 :
2049 : // To preserve backwards compatiblity, only append a newline when
2050 : // the current stringified frame actually has characters.
2051 0 : const int old_length = builder.Length();
2052 0 : JSStackFrame site(this, receiver, function, code, offset);
2053 0 : site.ToString(builder);
2054 0 : if (old_length != builder.Length()) builder.AppendCharacter('\n');
2055 : }
2056 :
2057 0 : Handle<String> stack_trace = builder.Finish().ToHandleChecked();
2058 0 : stack_trace->PrintOn(out);
2059 0 : }
2060 :
2061 979908 : bool Isolate::ComputeLocation(MessageLocation* target) {
2062 979908 : StackTraceFrameIterator it(this);
2063 979908 : if (it.done()) return false;
2064 : StandardFrame* frame = it.frame();
2065 : // Compute the location from the function and the relocation info of the
2066 : // baseline code. For optimized code this will use the deoptimization
2067 : // information to get canonical location information.
2068 972179 : std::vector<FrameSummary> frames;
2069 1944358 : wasm::WasmCodeRefScope code_ref_scope;
2070 972179 : frame->Summarize(&frames);
2071 : FrameSummary& summary = frames.back();
2072 972179 : summary.EnsureSourcePositionsAvailable();
2073 972179 : int pos = summary.SourcePosition();
2074 : Handle<SharedFunctionInfo> shared;
2075 972179 : Handle<Object> script = summary.script();
2076 1943970 : if (!script->IsScript() ||
2077 : (Script::cast(*script)->source()->IsUndefined(this))) {
2078 : return false;
2079 : }
2080 :
2081 971791 : if (summary.IsJavaScript()) {
2082 822330 : shared = handle(summary.AsJavaScript().function()->shared(), this);
2083 : }
2084 971791 : *target = MessageLocation(Handle<Script>::cast(script), pos, pos + 1, shared);
2085 971791 : return true;
2086 : }
2087 :
2088 4564 : bool Isolate::ComputeLocationFromException(MessageLocation* target,
2089 : Handle<Object> exception) {
2090 4564 : if (!exception->IsJSObject()) return false;
2091 :
2092 : Handle<Name> start_pos_symbol = factory()->error_start_pos_symbol();
2093 : Handle<Object> start_pos = JSReceiver::GetDataProperty(
2094 2666 : Handle<JSObject>::cast(exception), start_pos_symbol);
2095 2666 : if (!start_pos->IsSmi()) return false;
2096 : int start_pos_value = Handle<Smi>::cast(start_pos)->value();
2097 :
2098 : Handle<Name> end_pos_symbol = factory()->error_end_pos_symbol();
2099 : Handle<Object> end_pos = JSReceiver::GetDataProperty(
2100 15 : Handle<JSObject>::cast(exception), end_pos_symbol);
2101 15 : if (!end_pos->IsSmi()) return false;
2102 : int end_pos_value = Handle<Smi>::cast(end_pos)->value();
2103 :
2104 : Handle<Name> script_symbol = factory()->error_script_symbol();
2105 : Handle<Object> script = JSReceiver::GetDataProperty(
2106 15 : Handle<JSObject>::cast(exception), script_symbol);
2107 15 : if (!script->IsScript()) return false;
2108 :
2109 : Handle<Script> cast_script(Script::cast(*script), this);
2110 15 : *target = MessageLocation(cast_script, start_pos_value, end_pos_value);
2111 15 : return true;
2112 : }
2113 :
2114 :
2115 4585 : bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
2116 : Handle<Object> exception) {
2117 4585 : if (!exception->IsJSObject()) return false;
2118 : Handle<Name> key = factory()->stack_trace_symbol();
2119 : Handle<Object> property =
2120 2687 : JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key);
2121 2687 : if (!property->IsFixedArray()) return false;
2122 :
2123 : Handle<FrameArray> elements = Handle<FrameArray>::cast(property);
2124 :
2125 : const int frame_count = elements->FrameCount();
2126 3398 : for (int i = 0; i < frame_count; i++) {
2127 1824 : if (elements->IsWasmFrame(i) || elements->IsAsmJsWasmFrame(i)) {
2128 : Handle<WasmInstanceObject> instance(elements->WasmInstance(i), this);
2129 : uint32_t func_index =
2130 48 : static_cast<uint32_t>(elements->WasmFunctionIndex(i)->value());
2131 : int code_offset = elements->Offset(i)->value();
2132 : bool is_at_number_conversion =
2133 48 : elements->IsAsmJsWasmFrame(i) &&
2134 0 : elements->Flags(i)->value() & FrameArray::kAsmJsAtNumberConversion;
2135 : // WasmCode* held alive by the {GlobalWasmCodeRef}.
2136 : wasm::WasmCode* code =
2137 : Managed<wasm::GlobalWasmCodeRef>::cast(elements->WasmCodeObject(i))
2138 : ->get()
2139 : ->code();
2140 : int byte_offset =
2141 : FrameSummary::WasmCompiledFrameSummary::GetWasmSourcePosition(
2142 48 : code, code_offset);
2143 48 : int pos = WasmModuleObject::GetSourcePosition(
2144 : handle(instance->module_object(), this), func_index, byte_offset,
2145 48 : is_at_number_conversion);
2146 : Handle<Script> script(instance->module_object()->script(), this);
2147 :
2148 48 : *target = MessageLocation(script, pos, pos + 1);
2149 : return true;
2150 : }
2151 :
2152 : Handle<JSFunction> fun = handle(elements->Function(i), this);
2153 1276 : if (!fun->shared()->IsSubjectToDebugging()) continue;
2154 :
2155 500 : Object script = fun->shared()->script();
2156 1000 : if (script->IsScript() &&
2157 : !(Script::cast(script)->source()->IsUndefined(this))) {
2158 500 : Handle<SharedFunctionInfo> shared = handle(fun->shared(), this);
2159 500 : SharedFunctionInfo::EnsureSourcePositionsAvailable(this, shared);
2160 500 : AbstractCode abstract_code = elements->Code(i);
2161 : const int code_offset = elements->Offset(i)->value();
2162 500 : const int pos = abstract_code->SourcePosition(code_offset);
2163 :
2164 : Handle<Script> casted_script(Script::cast(script), this);
2165 500 : *target = MessageLocation(casted_script, pos, pos + 1);
2166 : return true;
2167 : }
2168 : }
2169 : return false;
2170 : }
2171 :
2172 :
2173 1362969 : Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception,
2174 : MessageLocation* location) {
2175 : Handle<FixedArray> stack_trace_object;
2176 1362969 : if (capture_stack_trace_for_uncaught_exceptions_) {
2177 452 : if (exception->IsJSError()) {
2178 : // We fetch the stack trace that corresponds to this error object.
2179 : // If the lookup fails, the exception is probably not a valid Error
2180 : // object. In that case, we fall through and capture the stack trace
2181 : // at this throw site.
2182 : stack_trace_object =
2183 271 : GetDetailedStackTrace(Handle<JSObject>::cast(exception));
2184 : }
2185 452 : if (stack_trace_object.is_null()) {
2186 : // Not an error object, we capture stack and location at throw site.
2187 : stack_trace_object = CaptureCurrentStackTrace(
2188 : stack_trace_for_uncaught_exceptions_frame_limit_,
2189 186 : stack_trace_for_uncaught_exceptions_options_);
2190 : }
2191 : }
2192 1362969 : MessageLocation computed_location;
2193 2730502 : if (location == nullptr &&
2194 9113 : (ComputeLocationFromException(&computed_location, exception) ||
2195 8586 : ComputeLocationFromStackTrace(&computed_location, exception) ||
2196 4037 : ComputeLocation(&computed_location))) {
2197 : location = &computed_location;
2198 : }
2199 :
2200 : return MessageHandler::MakeMessageObject(
2201 : this, MessageTemplate::kUncaughtException, location, exception,
2202 1362969 : stack_trace_object);
2203 : }
2204 :
2205 0 : bool Isolate::IsJavaScriptHandlerOnTop(Object exception) {
2206 : DCHECK_NE(ReadOnlyRoots(heap()).the_hole_value(), exception);
2207 :
2208 : // For uncatchable exceptions, the JavaScript handler cannot be on top.
2209 171053 : if (!is_catchable_by_javascript(exception)) return false;
2210 :
2211 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
2212 : Address entry_handler = Isolate::handler(thread_local_top());
2213 166825 : if (entry_handler == kNullAddress) return false;
2214 :
2215 : // Get the address of the external handler so we can compare the address to
2216 : // determine which one is closer to the top of the stack.
2217 : Address external_handler = thread_local_top()->try_catch_handler_address();
2218 148470 : if (external_handler == kNullAddress) return true;
2219 :
2220 : // The exception has been externally caught if and only if there is an
2221 : // external handler which is on top of the top-most JS_ENTRY handler.
2222 : //
2223 : // Note, that finally clauses would re-throw an exception unless it's aborted
2224 : // by jumps in control flow (like return, break, etc.) and we'll have another
2225 : // chance to set proper v8::TryCatch later.
2226 147102 : return (entry_handler < external_handler);
2227 : }
2228 :
2229 0 : bool Isolate::IsExternalHandlerOnTop(Object exception) {
2230 : DCHECK_NE(ReadOnlyRoots(heap()).the_hole_value(), exception);
2231 :
2232 : // Get the address of the external handler so we can compare the address to
2233 : // determine which one is closer to the top of the stack.
2234 : Address external_handler = thread_local_top()->try_catch_handler_address();
2235 53401 : if (external_handler == kNullAddress) return false;
2236 :
2237 : // For uncatchable exceptions, the external handler is always on top.
2238 46462 : if (!is_catchable_by_javascript(exception)) return true;
2239 :
2240 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
2241 : Address entry_handler = Isolate::handler(thread_local_top());
2242 43177 : if (entry_handler == kNullAddress) return true;
2243 :
2244 : // The exception has been externally caught if and only if there is an
2245 : // external handler which is on top of the top-most JS_ENTRY handler.
2246 : //
2247 : // Note, that finally clauses would re-throw an exception unless it's aborted
2248 : // by jumps in control flow (like return, break, etc.) and we'll have another
2249 : // chance to set proper v8::TryCatch later.
2250 20333 : return (entry_handler > external_handler);
2251 : }
2252 :
2253 15477 : void Isolate::ReportPendingMessagesImpl(bool report_externally) {
2254 : Object exception = pending_exception();
2255 :
2256 : // Clear the pending message object early to avoid endless recursion.
2257 15477 : Object message_obj = thread_local_top()->pending_message_obj_;
2258 : clear_pending_message();
2259 :
2260 : // For uncatchable exceptions we do nothing. If needed, the exception and the
2261 : // message have already been propagated to v8::TryCatch.
2262 15477 : if (!is_catchable_by_javascript(exception)) return;
2263 :
2264 : // Determine whether the message needs to be reported to all message handlers
2265 : // depending on whether and external v8::TryCatch or an internal JavaScript
2266 : // handler is on top.
2267 : bool should_report_exception;
2268 12770 : if (report_externally) {
2269 : // Only report the exception if the external handler is verbose.
2270 11811 : should_report_exception = try_catch_handler()->is_verbose_;
2271 : } else {
2272 : // Report the exception if it isn't caught by JavaScript code.
2273 959 : should_report_exception = !IsJavaScriptHandlerOnTop(exception);
2274 : }
2275 :
2276 : // Actually report the pending message to all message handlers.
2277 12770 : if (!message_obj->IsTheHole(this) && should_report_exception) {
2278 : HandleScope scope(this);
2279 : Handle<JSMessageObject> message(JSMessageObject::cast(message_obj), this);
2280 : Handle<Script> script(message->script(), this);
2281 : int start_pos = message->start_position();
2282 : int end_pos = message->end_position();
2283 8116 : MessageLocation location(script, start_pos, end_pos);
2284 8116 : MessageHandler::ReportMessage(this, &location, message);
2285 : }
2286 : }
2287 :
2288 122995 : void Isolate::ReportPendingMessages() {
2289 : DCHECK(AllowExceptions::IsAllowed(this));
2290 :
2291 : // The embedder might run script in response to an exception.
2292 : AllowJavascriptExecutionDebugOnly allow_script(this);
2293 :
2294 : Object exception = pending_exception();
2295 :
2296 : // Try to propagate the exception to an external v8::TryCatch handler. If
2297 : // propagation was unsuccessful, then we will get another chance at reporting
2298 : // the pending message if the exception is re-thrown.
2299 122995 : bool has_been_propagated = PropagatePendingExceptionToExternalTryCatch();
2300 122995 : if (!has_been_propagated) return;
2301 :
2302 15477 : ReportPendingMessagesImpl(IsExternalHandlerOnTop(exception));
2303 : }
2304 :
2305 33 : void Isolate::ReportPendingMessagesFromJavaScript() {
2306 : DCHECK(AllowExceptions::IsAllowed(this));
2307 :
2308 : auto IsHandledByJavaScript = [=]() {
2309 : // In this situation, the exception is always a non-terminating exception.
2310 :
2311 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
2312 33 : Address entry_handler = Isolate::handler(thread_local_top());
2313 : DCHECK_NE(entry_handler, kNullAddress);
2314 : entry_handler = StackHandler::FromAddress(entry_handler)->next_address();
2315 :
2316 : // Get the address of the external handler so we can compare the address to
2317 : // determine which one is closer to the top of the stack.
2318 : Address external_handler = thread_local_top()->try_catch_handler_address();
2319 33 : if (external_handler == kNullAddress) return true;
2320 :
2321 33 : return (entry_handler < external_handler);
2322 : };
2323 :
2324 : auto IsHandledExternally = [=]() {
2325 0 : Address external_handler = thread_local_top()->try_catch_handler_address();
2326 0 : if (external_handler == kNullAddress) return false;
2327 :
2328 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
2329 : Address entry_handler = Isolate::handler(thread_local_top());
2330 : DCHECK_NE(entry_handler, kNullAddress);
2331 : entry_handler = StackHandler::FromAddress(entry_handler)->next_address();
2332 0 : return (entry_handler > external_handler);
2333 : };
2334 :
2335 33 : auto PropagateToExternalHandler = [=]() {
2336 33 : if (IsHandledByJavaScript()) {
2337 33 : thread_local_top()->external_caught_exception_ = false;
2338 33 : return false;
2339 : }
2340 :
2341 0 : if (!IsHandledExternally()) {
2342 0 : thread_local_top()->external_caught_exception_ = false;
2343 0 : return true;
2344 : }
2345 :
2346 0 : thread_local_top()->external_caught_exception_ = true;
2347 : v8::TryCatch* handler = try_catch_handler();
2348 : DCHECK(thread_local_top()->pending_message_obj_->IsJSMessageObject() ||
2349 : thread_local_top()->pending_message_obj_->IsTheHole(this));
2350 0 : handler->can_continue_ = true;
2351 0 : handler->has_terminated_ = false;
2352 0 : handler->exception_ = reinterpret_cast<void*>(pending_exception().ptr());
2353 : // Propagate to the external try-catch only if we got an actual message.
2354 0 : if (thread_local_top()->pending_message_obj_->IsTheHole(this)) return true;
2355 :
2356 : handler->message_obj_ =
2357 0 : reinterpret_cast<void*>(thread_local_top()->pending_message_obj_.ptr());
2358 0 : return true;
2359 33 : };
2360 :
2361 : // Try to propagate to an external v8::TryCatch handler.
2362 66 : if (!PropagateToExternalHandler()) return;
2363 :
2364 0 : ReportPendingMessagesImpl(true);
2365 : }
2366 :
2367 16972 : bool Isolate::OptionalRescheduleException(bool clear_exception) {
2368 : DCHECK(has_pending_exception());
2369 16972 : PropagatePendingExceptionToExternalTryCatch();
2370 :
2371 : bool is_termination_exception =
2372 : pending_exception() == ReadOnlyRoots(this).termination_exception();
2373 :
2374 16972 : if (is_termination_exception) {
2375 1521 : if (clear_exception) {
2376 1080 : thread_local_top()->external_caught_exception_ = false;
2377 : clear_pending_exception();
2378 1080 : return false;
2379 : }
2380 15451 : } else if (thread_local_top()->external_caught_exception_) {
2381 : // If the exception is externally caught, clear it if there are no
2382 : // JavaScript frames on the way to the C++ frame that has the
2383 : // external handler.
2384 : DCHECK_NE(thread_local_top()->try_catch_handler_address(), kNullAddress);
2385 : Address external_handler_address =
2386 : thread_local_top()->try_catch_handler_address();
2387 13304 : JavaScriptFrameIterator it(this);
2388 13304 : if (it.done() || (it.frame()->sp() > external_handler_address)) {
2389 : clear_exception = true;
2390 : }
2391 : }
2392 :
2393 : // Clear the exception if needed.
2394 15892 : if (clear_exception) {
2395 14401 : thread_local_top()->external_caught_exception_ = false;
2396 : clear_pending_exception();
2397 14401 : return false;
2398 : }
2399 :
2400 : // Reschedule the exception.
2401 1491 : thread_local_top()->scheduled_exception_ = pending_exception();
2402 : clear_pending_exception();
2403 1491 : return true;
2404 : }
2405 :
2406 17420 : void Isolate::PushPromise(Handle<JSObject> promise) {
2407 : ThreadLocalTop* tltop = thread_local_top();
2408 17420 : PromiseOnStack* prev = tltop->promise_on_stack_;
2409 : Handle<JSObject> global_promise = global_handles()->Create(*promise);
2410 34840 : tltop->promise_on_stack_ = new PromiseOnStack(global_promise, prev);
2411 17420 : }
2412 :
2413 :
2414 17440 : void Isolate::PopPromise() {
2415 : ThreadLocalTop* tltop = thread_local_top();
2416 17440 : if (tltop->promise_on_stack_ == nullptr) return;
2417 : PromiseOnStack* prev = tltop->promise_on_stack_->prev();
2418 : Handle<Object> global_promise = tltop->promise_on_stack_->promise();
2419 17420 : delete tltop->promise_on_stack_;
2420 17420 : tltop->promise_on_stack_ = prev;
2421 17420 : global_handles()->Destroy(global_promise.location());
2422 : }
2423 :
2424 : namespace {
2425 : bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
2426 : Handle<JSPromise> promise);
2427 :
2428 985 : bool PromiseHandlerCheck(Isolate* isolate, Handle<JSReceiver> handler,
2429 : Handle<JSReceiver> deferred_promise) {
2430 : // Recurse to the forwarding Promise, if any. This may be due to
2431 : // - await reaction forwarding to the throwaway Promise, which has
2432 : // a dependency edge to the outer Promise.
2433 : // - PromiseIdResolveHandler forwarding to the output of .then
2434 : // - Promise.all/Promise.race forwarding to a throwaway Promise, which
2435 : // has a dependency edge to the generated outer Promise.
2436 : // Otherwise, this is a real reject handler for the Promise.
2437 : Handle<Symbol> key = isolate->factory()->promise_forwarding_handler_symbol();
2438 985 : Handle<Object> forwarding_handler = JSReceiver::GetDataProperty(handler, key);
2439 985 : if (forwarding_handler->IsUndefined(isolate)) {
2440 : return true;
2441 : }
2442 :
2443 365 : if (!deferred_promise->IsJSPromise()) {
2444 : return true;
2445 : }
2446 :
2447 : return InternalPromiseHasUserDefinedRejectHandler(
2448 365 : isolate, Handle<JSPromise>::cast(deferred_promise));
2449 : }
2450 :
2451 4876 : bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
2452 : Handle<JSPromise> promise) {
2453 : // If this promise was marked as being handled by a catch block
2454 : // in an async function, then it has a user-defined reject handler.
2455 4876 : if (promise->handled_hint()) return true;
2456 :
2457 : // If this Promise is subsumed by another Promise (a Promise resolved
2458 : // with another Promise, or an intermediate, hidden, throwaway Promise
2459 : // within async/await), then recurse on the outer Promise.
2460 : // In this case, the dependency is one possible way that the Promise
2461 : // could be resolved, so it does not subsume the other following cases.
2462 : Handle<Symbol> key = isolate->factory()->promise_handled_by_symbol();
2463 4330 : Handle<Object> outer_promise_obj = JSObject::GetDataProperty(promise, key);
2464 5333 : if (outer_promise_obj->IsJSPromise() &&
2465 1003 : InternalPromiseHasUserDefinedRejectHandler(
2466 : isolate, Handle<JSPromise>::cast(outer_promise_obj))) {
2467 : return true;
2468 : }
2469 :
2470 3608 : if (promise->status() == Promise::kPending) {
2471 3797 : for (Handle<Object> current(promise->reactions(), isolate);
2472 : !current->IsSmi();) {
2473 : Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(current);
2474 : Handle<HeapObject> promise_or_capability(
2475 : reaction->promise_or_capability(), isolate);
2476 1076 : if (!promise_or_capability->IsUndefined(isolate)) {
2477 : Handle<JSPromise> promise = Handle<JSPromise>::cast(
2478 : promise_or_capability->IsJSPromise()
2479 : ? promise_or_capability
2480 : : handle(Handle<PromiseCapability>::cast(promise_or_capability)
2481 : ->promise(),
2482 1076 : isolate));
2483 1076 : if (reaction->reject_handler()->IsUndefined(isolate)) {
2484 91 : if (InternalPromiseHasUserDefinedRejectHandler(isolate, promise)) {
2485 : return true;
2486 : }
2487 : } else {
2488 : Handle<JSReceiver> current_handler(
2489 : JSReceiver::cast(reaction->reject_handler()), isolate);
2490 985 : if (PromiseHandlerCheck(isolate, current_handler, promise)) {
2491 805 : return true;
2492 : }
2493 : }
2494 : }
2495 : current = handle(reaction->next(), isolate);
2496 : }
2497 : }
2498 :
2499 : return false;
2500 : }
2501 :
2502 : } // namespace
2503 :
2504 3417 : bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) {
2505 3417 : if (!promise->IsJSPromise()) return false;
2506 : return InternalPromiseHasUserDefinedRejectHandler(
2507 3417 : this, Handle<JSPromise>::cast(promise));
2508 : }
2509 :
2510 4206 : Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
2511 : Handle<Object> undefined = factory()->undefined_value();
2512 : ThreadLocalTop* tltop = thread_local_top();
2513 4206 : if (tltop->promise_on_stack_ == nullptr) return undefined;
2514 : // Find the top-most try-catch or try-finally handler.
2515 1593 : CatchType prediction = PredictExceptionCatcher();
2516 1593 : if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) {
2517 5 : return undefined;
2518 : }
2519 : Handle<Object> retval = undefined;
2520 1588 : PromiseOnStack* promise_on_stack = tltop->promise_on_stack_;
2521 156669 : for (StackFrameIterator it(this); !it.done(); it.Advance()) {
2522 : StackFrame* frame = it.frame();
2523 : HandlerTable::CatchPrediction catch_prediction;
2524 156259 : if (frame->is_java_script()) {
2525 151584 : catch_prediction = PredictException(JavaScriptFrame::cast(frame));
2526 4675 : } else if (frame->type() == StackFrame::STUB) {
2527 1618 : Code code = frame->LookupCode();
2528 3644 : if (!code->IsCode() || code->kind() != Code::BUILTIN ||
2529 2434 : !code->has_handler_table() || !code->is_turbofanned()) {
2530 1210 : continue;
2531 : }
2532 408 : catch_prediction = code->GetBuiltinCatchPrediction();
2533 : } else {
2534 : continue;
2535 : }
2536 :
2537 151992 : switch (catch_prediction) {
2538 : case HandlerTable::UNCAUGHT:
2539 : continue;
2540 : case HandlerTable::CAUGHT:
2541 : case HandlerTable::DESUGARING:
2542 462 : if (retval->IsJSPromise()) {
2543 : // Caught the result of an inner async/await invocation.
2544 : // Mark the inner promise as caught in the "synchronous case" so
2545 : // that Debug::OnException will see. In the synchronous case,
2546 : // namely in the code in an async function before the first
2547 : // await, the function which has this exception event has not yet
2548 : // returned, so the generated Promise has not yet been marked
2549 : // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol.
2550 325 : Handle<JSPromise>::cast(retval)->set_handled_hint(true);
2551 : }
2552 462 : return retval;
2553 : case HandlerTable::PROMISE:
2554 : return promise_on_stack
2555 : ? Handle<Object>::cast(promise_on_stack->promise())
2556 482 : : undefined;
2557 : case HandlerTable::ASYNC_AWAIT: {
2558 : // If in the initial portion of async/await, continue the loop to pop up
2559 : // successive async/await stack frames until an asynchronous one with
2560 : // dependents is found, or a non-async stack frame is encountered, in
2561 : // order to handle the synchronous async/await catch prediction case:
2562 : // assume that async function calls are awaited.
2563 1474 : if (!promise_on_stack) return retval;
2564 : retval = promise_on_stack->promise();
2565 1474 : if (PromiseHasUserDefinedRejectHandler(retval)) {
2566 234 : return retval;
2567 : }
2568 : promise_on_stack = promise_on_stack->prev();
2569 1240 : continue;
2570 : }
2571 : }
2572 : }
2573 410 : return retval;
2574 : }
2575 :
2576 :
2577 1371 : void Isolate::SetCaptureStackTraceForUncaughtExceptions(
2578 : bool capture,
2579 : int frame_limit,
2580 : StackTrace::StackTraceOptions options) {
2581 1371 : capture_stack_trace_for_uncaught_exceptions_ = capture;
2582 1371 : stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
2583 1371 : stack_trace_for_uncaught_exceptions_options_ = options;
2584 1371 : }
2585 :
2586 :
2587 5 : void Isolate::SetAbortOnUncaughtExceptionCallback(
2588 : v8::Isolate::AbortOnUncaughtExceptionCallback callback) {
2589 5 : abort_on_uncaught_exception_callback_ = callback;
2590 5 : }
2591 :
2592 1537297 : bool Isolate::AreWasmThreadsEnabled(Handle<Context> context) {
2593 1537297 : if (wasm_threads_enabled_callback()) {
2594 42 : v8::Local<v8::Context> api_context = v8::Utils::ToLocal(context);
2595 42 : return wasm_threads_enabled_callback()(api_context);
2596 : }
2597 1537255 : return FLAG_experimental_wasm_threads;
2598 : }
2599 :
2600 4 : Handle<Context> Isolate::GetIncumbentContext() {
2601 4 : JavaScriptFrameIterator it(this);
2602 :
2603 : // 1st candidate: most-recently-entered author function's context
2604 : // if it's newer than the last Context::BackupIncumbentScope entry.
2605 : //
2606 : // NOTE: This code assumes that the stack grows downward.
2607 : Address top_backup_incumbent =
2608 : top_backup_incumbent_scope()
2609 : ? top_backup_incumbent_scope()->JSStackComparableAddress()
2610 4 : : 0;
2611 8 : if (!it.done() &&
2612 2 : (!top_backup_incumbent || it.frame()->sp() < top_backup_incumbent)) {
2613 4 : Context context = Context::cast(it.frame()->context());
2614 4 : return Handle<Context>(context->native_context(), this);
2615 : }
2616 :
2617 : // 2nd candidate: the last Context::Scope's incumbent context if any.
2618 0 : if (top_backup_incumbent_scope()) {
2619 : return Utils::OpenHandle(
2620 : *top_backup_incumbent_scope()->backup_incumbent_context_);
2621 : }
2622 :
2623 : // Last candidate: the entered context or microtask context.
2624 : // Given that there is no other author function is running, there must be
2625 : // no cross-context function running, then the incumbent realm must match
2626 : // the entry realm.
2627 : v8::Local<v8::Context> entered_context =
2628 0 : reinterpret_cast<v8::Isolate*>(this)->GetEnteredOrMicrotaskContext();
2629 : return Utils::OpenHandle(*entered_context);
2630 : }
2631 :
2632 32424 : char* Isolate::ArchiveThread(char* to) {
2633 : MemCopy(to, reinterpret_cast<char*>(thread_local_top()),
2634 : sizeof(ThreadLocalTop));
2635 : InitializeThreadLocal();
2636 : clear_pending_exception();
2637 : clear_pending_message();
2638 : clear_scheduled_exception();
2639 32424 : return to + sizeof(ThreadLocalTop);
2640 : }
2641 :
2642 :
2643 32424 : char* Isolate::RestoreThread(char* from) {
2644 : MemCopy(reinterpret_cast<char*>(thread_local_top()), from,
2645 : sizeof(ThreadLocalTop));
2646 : // This might be just paranoia, but it seems to be needed in case a
2647 : // thread_local_top_ is restored on a separate OS thread.
2648 : #ifdef USE_SIMULATOR
2649 : thread_local_top()->simulator_ = Simulator::current(this);
2650 : #endif
2651 : DCHECK(context().is_null() || context()->IsContext());
2652 32424 : return from + sizeof(ThreadLocalTop);
2653 : }
2654 :
2655 62427 : void Isolate::ReleaseSharedPtrs() {
2656 62427 : base::MutexGuard lock(&managed_ptr_destructors_mutex_);
2657 74295 : while (managed_ptr_destructors_head_) {
2658 : ManagedPtrDestructor* l = managed_ptr_destructors_head_;
2659 : ManagedPtrDestructor* n = nullptr;
2660 11868 : managed_ptr_destructors_head_ = nullptr;
2661 843454 : for (; l != nullptr; l = n) {
2662 415793 : l->destructor_(l->shared_ptr_ptr_);
2663 415793 : n = l->next_;
2664 415793 : delete l;
2665 : }
2666 : }
2667 62427 : }
2668 :
2669 3118267 : void Isolate::RegisterManagedPtrDestructor(ManagedPtrDestructor* destructor) {
2670 3118267 : base::MutexGuard lock(&managed_ptr_destructors_mutex_);
2671 : DCHECK_NULL(destructor->prev_);
2672 : DCHECK_NULL(destructor->next_);
2673 3118266 : if (managed_ptr_destructors_head_) {
2674 3105166 : managed_ptr_destructors_head_->prev_ = destructor;
2675 : }
2676 3118266 : destructor->next_ = managed_ptr_destructors_head_;
2677 3118266 : managed_ptr_destructors_head_ = destructor;
2678 3118266 : }
2679 :
2680 2702474 : void Isolate::UnregisterManagedPtrDestructor(ManagedPtrDestructor* destructor) {
2681 2702474 : base::MutexGuard lock(&managed_ptr_destructors_mutex_);
2682 2702474 : if (destructor->prev_) {
2683 2693036 : destructor->prev_->next_ = destructor->next_;
2684 : } else {
2685 : DCHECK_EQ(destructor, managed_ptr_destructors_head_);
2686 9438 : managed_ptr_destructors_head_ = destructor->next_;
2687 : }
2688 2702474 : if (destructor->next_) destructor->next_->prev_ = destructor->prev_;
2689 2702474 : destructor->prev_ = nullptr;
2690 2702474 : destructor->next_ = nullptr;
2691 2702474 : }
2692 :
2693 62442 : void Isolate::SetWasmEngine(std::shared_ptr<wasm::WasmEngine> engine) {
2694 : DCHECK_NULL(wasm_engine_); // Only call once before {Init}.
2695 : wasm_engine_ = std::move(engine);
2696 62442 : wasm_engine_->AddIsolate(this);
2697 62442 : }
2698 :
2699 : // NOLINTNEXTLINE
2700 67962 : Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
2701 : #if defined(USE_SIMULATOR)
2702 : delete simulator_;
2703 : #endif
2704 0 : }
2705 :
2706 0 : Isolate::PerIsolateThreadData* Isolate::ThreadDataTable::Lookup(
2707 : ThreadId thread_id) {
2708 : auto t = table_.find(thread_id);
2709 369792 : if (t == table_.end()) return nullptr;
2710 295780 : return t->second;
2711 : }
2712 :
2713 :
2714 67977 : void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
2715 135952 : bool inserted = table_.insert(std::make_pair(data->thread_id_, data)).second;
2716 67975 : CHECK(inserted);
2717 67975 : }
2718 :
2719 :
2720 0 : void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
2721 500 : table_.erase(data->thread_id_);
2722 1000 : delete data;
2723 0 : }
2724 :
2725 62427 : void Isolate::ThreadDataTable::RemoveAllThreads() {
2726 129889 : for (auto& x : table_) {
2727 134924 : delete x.second;
2728 : }
2729 : table_.clear();
2730 62427 : }
2731 :
2732 0 : class VerboseAccountingAllocator : public AccountingAllocator {
2733 : public:
2734 : VerboseAccountingAllocator(Heap* heap, size_t allocation_sample_bytes)
2735 0 : : heap_(heap), allocation_sample_bytes_(allocation_sample_bytes) {}
2736 :
2737 0 : v8::internal::Segment* AllocateSegment(size_t size) override {
2738 0 : v8::internal::Segment* memory = AccountingAllocator::AllocateSegment(size);
2739 0 : if (!memory) return nullptr;
2740 : size_t malloced_current = GetCurrentMemoryUsage();
2741 :
2742 0 : if (last_memory_usage_ + allocation_sample_bytes_ < malloced_current) {
2743 0 : PrintMemoryJSON(malloced_current);
2744 : last_memory_usage_ = malloced_current;
2745 : }
2746 : return memory;
2747 : }
2748 :
2749 0 : void ReturnSegment(v8::internal::Segment* memory) override {
2750 0 : AccountingAllocator::ReturnSegment(memory);
2751 : size_t malloced_current = GetCurrentMemoryUsage();
2752 :
2753 0 : if (malloced_current + allocation_sample_bytes_ < last_memory_usage_) {
2754 0 : PrintMemoryJSON(malloced_current);
2755 : last_memory_usage_ = malloced_current;
2756 : }
2757 0 : }
2758 :
2759 0 : void ZoneCreation(const Zone* zone) override {
2760 0 : PrintZoneModificationSample(zone, "zonecreation");
2761 : nesting_deepth_++;
2762 0 : }
2763 :
2764 0 : void ZoneDestruction(const Zone* zone) override {
2765 : nesting_deepth_--;
2766 0 : PrintZoneModificationSample(zone, "zonedestruction");
2767 0 : }
2768 :
2769 : private:
2770 0 : void PrintZoneModificationSample(const Zone* zone, const char* type) {
2771 : PrintF(
2772 : "{"
2773 : "\"type\": \"%s\", "
2774 : "\"isolate\": \"%p\", "
2775 : "\"time\": %f, "
2776 : "\"ptr\": \"%p\", "
2777 : "\"name\": \"%s\", "
2778 : "\"size\": %" PRIuS
2779 : ","
2780 : "\"nesting\": %zu}\n",
2781 0 : type, reinterpret_cast<void*>(heap_->isolate()),
2782 0 : heap_->isolate()->time_millis_since_init(),
2783 : reinterpret_cast<const void*>(zone), zone->name(),
2784 0 : zone->allocation_size(), nesting_deepth_.load());
2785 0 : }
2786 :
2787 0 : void PrintMemoryJSON(size_t malloced) {
2788 : // Note: Neither isolate, nor heap is locked, so be careful with accesses
2789 : // as the allocator is potentially used on a concurrent thread.
2790 0 : double time = heap_->isolate()->time_millis_since_init();
2791 : PrintF(
2792 : "{"
2793 : "\"type\": \"zone\", "
2794 : "\"isolate\": \"%p\", "
2795 : "\"time\": %f, "
2796 : "\"allocated\": %" PRIuS "}\n",
2797 0 : reinterpret_cast<void*>(heap_->isolate()), time, malloced);
2798 0 : }
2799 :
2800 : Heap* heap_;
2801 : std::atomic<size_t> last_memory_usage_{0};
2802 : std::atomic<size_t> nesting_deepth_{0};
2803 : size_t allocation_sample_bytes_;
2804 : };
2805 :
2806 : #ifdef DEBUG
2807 : std::atomic<size_t> Isolate::non_disposed_isolates_;
2808 : #endif // DEBUG
2809 :
2810 : // static
2811 62439 : Isolate* Isolate::New(IsolateAllocationMode mode) {
2812 : // IsolateAllocator allocates the memory for the Isolate object according to
2813 : // the given allocation mode.
2814 : std::unique_ptr<IsolateAllocator> isolate_allocator =
2815 62441 : base::make_unique<IsolateAllocator>(mode);
2816 : // Construct Isolate object in the allocated memory.
2817 : void* isolate_ptr = isolate_allocator->isolate_memory();
2818 62441 : Isolate* isolate = new (isolate_ptr) Isolate(std::move(isolate_allocator));
2819 : #if V8_TARGET_ARCH_64_BIT
2820 : DCHECK_IMPLIES(
2821 : mode == IsolateAllocationMode::kInV8Heap,
2822 : IsAligned(isolate->isolate_root(), kPtrComprIsolateRootAlignment));
2823 : #endif
2824 :
2825 : #ifdef DEBUG
2826 : non_disposed_isolates_++;
2827 : #endif // DEBUG
2828 :
2829 62441 : return isolate;
2830 : }
2831 :
2832 : // static
2833 62426 : void Isolate::Delete(Isolate* isolate) {
2834 : DCHECK_NOT_NULL(isolate);
2835 : // Temporarily set this isolate as current so that various parts of
2836 : // the isolate can access it in their destructors without having a
2837 : // direct pointer. We don't use Enter/Exit here to avoid
2838 : // initializing the thread data.
2839 : PerIsolateThreadData* saved_data = isolate->CurrentPerIsolateThreadData();
2840 : DCHECK_EQ(true, isolate_key_created_.load(std::memory_order_relaxed));
2841 : Isolate* saved_isolate = reinterpret_cast<Isolate*>(
2842 62426 : base::Thread::GetThreadLocal(isolate->isolate_key_));
2843 62426 : SetIsolateThreadLocals(isolate, nullptr);
2844 :
2845 62426 : isolate->Deinit();
2846 :
2847 : #ifdef DEBUG
2848 : non_disposed_isolates_--;
2849 : #endif // DEBUG
2850 :
2851 : // Take ownership of the IsolateAllocator to ensure the Isolate memory will
2852 : // be available during Isolate descructor call.
2853 : std::unique_ptr<IsolateAllocator> isolate_allocator =
2854 62427 : std::move(isolate->isolate_allocator_);
2855 62427 : isolate->~Isolate();
2856 : // Now free the memory owned by the allocator.
2857 62427 : isolate_allocator.reset();
2858 :
2859 : // Restore the previous current isolate.
2860 62427 : SetIsolateThreadLocals(saved_isolate, saved_data);
2861 62427 : }
2862 :
2863 63457 : v8::PageAllocator* Isolate::page_allocator() {
2864 63457 : return isolate_allocator_->page_allocator();
2865 : }
2866 :
2867 62441 : Isolate::Isolate(std::unique_ptr<i::IsolateAllocator> isolate_allocator)
2868 : : isolate_allocator_(std::move(isolate_allocator)),
2869 : id_(isolate_counter.fetch_add(1, std::memory_order_relaxed)),
2870 : stack_guard_(this),
2871 : allocator_(FLAG_trace_zone_stats
2872 : ? new VerboseAccountingAllocator(&heap_, 256 * KB)
2873 : : new AccountingAllocator()),
2874 : builtins_(this),
2875 : rail_mode_(PERFORMANCE_ANIMATION),
2876 : code_event_dispatcher_(new CodeEventDispatcher()),
2877 1123944 : cancelable_task_manager_(new CancelableTaskManager()) {
2878 : TRACE_ISOLATE(constructor);
2879 : CheckIsolateLayout();
2880 :
2881 : // ThreadManager is initialized early to support locking an isolate
2882 : // before it is entered.
2883 62440 : thread_manager_ = new ThreadManager(this);
2884 :
2885 : handle_scope_data_.Initialize();
2886 :
2887 : #define ISOLATE_INIT_EXECUTE(type, name, initial_value) \
2888 : name##_ = (initial_value);
2889 62440 : ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
2890 : #undef ISOLATE_INIT_EXECUTE
2891 :
2892 : #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \
2893 : memset(name##_, 0, sizeof(type) * length);
2894 249760 : ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
2895 : #undef ISOLATE_INIT_ARRAY_EXECUTE
2896 :
2897 62440 : InitializeLoggingAndCounters();
2898 62442 : debug_ = new Debug(this);
2899 :
2900 62441 : InitializeDefaultEmbeddedBlob();
2901 :
2902 62441 : MicrotaskQueue::SetUpDefaultMicrotaskQueue(this);
2903 62442 : }
2904 :
2905 0 : void Isolate::CheckIsolateLayout() {
2906 : CHECK_EQ(OFFSET_OF(Isolate, isolate_data_), 0);
2907 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, isolate_data_.embedder_data_)),
2908 : Internals::kIsolateEmbedderDataOffset);
2909 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, isolate_data_.roots_)),
2910 : Internals::kIsolateRootsOffset);
2911 : CHECK_EQ(Internals::kExternalMemoryOffset % 8, 0);
2912 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, isolate_data_.external_memory_)),
2913 : Internals::kExternalMemoryOffset);
2914 : CHECK_EQ(Internals::kExternalMemoryLimitOffset % 8, 0);
2915 : CHECK_EQ(static_cast<int>(
2916 : OFFSET_OF(Isolate, isolate_data_.external_memory_limit_)),
2917 : Internals::kExternalMemoryLimitOffset);
2918 : CHECK_EQ(Internals::kExternalMemoryAtLastMarkCompactOffset % 8, 0);
2919 : CHECK_EQ(static_cast<int>(OFFSET_OF(
2920 : Isolate, isolate_data_.external_memory_at_last_mark_compact_)),
2921 : Internals::kExternalMemoryAtLastMarkCompactOffset);
2922 0 : }
2923 :
2924 63692 : void Isolate::ClearSerializerData() {
2925 64206 : delete external_reference_map_;
2926 63692 : external_reference_map_ = nullptr;
2927 63692 : }
2928 :
2929 83993 : bool Isolate::LogObjectRelocation() {
2930 166825 : return FLAG_verify_predictable || logger()->is_logging() || is_profiling() ||
2931 165702 : heap()->isolate()->logger()->is_listening_to_code_events() ||
2932 82846 : (heap_profiler() != nullptr &&
2933 166699 : heap_profiler()->is_tracking_object_moves()) ||
2934 83993 : heap()->has_heap_object_allocation_tracker();
2935 : }
2936 :
2937 62427 : void Isolate::Deinit() {
2938 : TRACE_ISOLATE(deinit);
2939 :
2940 : tracing_cpu_profiler_.reset();
2941 62426 : if (FLAG_stress_sampling_allocation_profiler > 0) {
2942 0 : heap_profiler()->StopSamplingHeapProfiler();
2943 : }
2944 :
2945 : #if defined(V8_OS_WIN_X64)
2946 : if (win64_unwindinfo::CanRegisterUnwindInfoForNonABICompliantCodeRange() &&
2947 : heap()->memory_allocator()) {
2948 : const base::AddressRegion& code_range =
2949 : heap()->memory_allocator()->code_range();
2950 : void* start = reinterpret_cast<void*>(code_range.begin());
2951 : win64_unwindinfo::UnregisterNonABICompliantCodeRange(start);
2952 : }
2953 : #endif
2954 :
2955 62426 : debug()->Unload();
2956 :
2957 62426 : wasm_engine()->DeleteCompileJobsOnIsolate(this);
2958 :
2959 62427 : if (concurrent_recompilation_enabled()) {
2960 62323 : optimizing_compile_dispatcher_->Stop();
2961 62323 : delete optimizing_compile_dispatcher_;
2962 62323 : optimizing_compile_dispatcher_ = nullptr;
2963 : }
2964 :
2965 62427 : wasm_engine()->memory_tracker()->DeleteSharedMemoryObjectsOnIsolate(this);
2966 :
2967 62427 : heap_.mark_compact_collector()->EnsureSweepingCompleted();
2968 62427 : heap_.memory_allocator()->unmapper()->EnsureUnmappingCompleted();
2969 :
2970 62427 : DumpAndResetStats();
2971 :
2972 62427 : if (FLAG_print_deopt_stress) {
2973 0 : PrintF(stdout, "=== Stress deopt counter: %u\n", stress_deopt_count_);
2974 : }
2975 :
2976 : // We must stop the logger before we tear down other components.
2977 62427 : sampler::Sampler* sampler = logger_->sampler();
2978 124795 : if (sampler && sampler->IsActive()) sampler->Stop();
2979 :
2980 : FreeThreadResources();
2981 62427 : logger_->StopProfilerThread();
2982 :
2983 : // We start with the heap tear down so that releasing managed objects does
2984 : // not cause a GC.
2985 62427 : heap_.StartTearDown();
2986 :
2987 62427 : ReleaseSharedPtrs();
2988 :
2989 62427 : delete deoptimizer_data_;
2990 62427 : deoptimizer_data_ = nullptr;
2991 62427 : builtins_.TearDown();
2992 62427 : bootstrapper_->TearDown();
2993 :
2994 62427 : if (runtime_profiler_ != nullptr) {
2995 62427 : delete runtime_profiler_;
2996 62427 : runtime_profiler_ = nullptr;
2997 : }
2998 :
2999 62427 : delete heap_profiler_;
3000 62426 : heap_profiler_ = nullptr;
3001 :
3002 62426 : compiler_dispatcher_->AbortAll();
3003 62427 : delete compiler_dispatcher_;
3004 62427 : compiler_dispatcher_ = nullptr;
3005 :
3006 : // This stops cancelable tasks (i.e. concurrent marking tasks)
3007 62427 : cancelable_task_manager()->CancelAndWait();
3008 :
3009 62427 : heap_.TearDown();
3010 62427 : logger_->TearDown();
3011 :
3012 62427 : if (wasm_engine_) {
3013 62427 : wasm_engine_->RemoveIsolate(this);
3014 : wasm_engine_.reset();
3015 : }
3016 :
3017 62427 : TearDownEmbeddedBlob();
3018 :
3019 62427 : delete interpreter_;
3020 62427 : interpreter_ = nullptr;
3021 :
3022 124854 : delete ast_string_constants_;
3023 62427 : ast_string_constants_ = nullptr;
3024 :
3025 : code_event_dispatcher_.reset();
3026 :
3027 79651 : delete root_index_map_;
3028 62427 : root_index_map_ = nullptr;
3029 :
3030 62427 : delete compiler_zone_;
3031 62427 : compiler_zone_ = nullptr;
3032 62427 : compiler_cache_ = nullptr;
3033 :
3034 62427 : ClearSerializerData();
3035 :
3036 : {
3037 62427 : base::MutexGuard lock_guard(&thread_data_table_mutex_);
3038 62427 : thread_data_table_.RemoveAllThreads();
3039 : }
3040 62427 : }
3041 :
3042 :
3043 552634 : void Isolate::SetIsolateThreadLocals(Isolate* isolate,
3044 : PerIsolateThreadData* data) {
3045 552634 : base::Thread::SetThreadLocal(isolate_key_, isolate);
3046 552578 : base::Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
3047 552553 : }
3048 :
3049 :
3050 374562 : Isolate::~Isolate() {
3051 : TRACE_ISOLATE(destructor);
3052 :
3053 : // The entry stack must be empty when we get here.
3054 : DCHECK(entry_stack_ == nullptr || entry_stack_->previous_item == nullptr);
3055 :
3056 62427 : delete entry_stack_;
3057 62427 : entry_stack_ = nullptr;
3058 :
3059 62427 : delete unicode_cache_;
3060 62427 : unicode_cache_ = nullptr;
3061 :
3062 62427 : delete date_cache_;
3063 62427 : date_cache_ = nullptr;
3064 :
3065 62427 : delete regexp_stack_;
3066 62427 : regexp_stack_ = nullptr;
3067 :
3068 62427 : delete descriptor_lookup_cache_;
3069 62427 : descriptor_lookup_cache_ = nullptr;
3070 :
3071 62427 : delete load_stub_cache_;
3072 62427 : load_stub_cache_ = nullptr;
3073 62427 : delete store_stub_cache_;
3074 62427 : store_stub_cache_ = nullptr;
3075 :
3076 124854 : delete materialized_object_store_;
3077 62427 : materialized_object_store_ = nullptr;
3078 :
3079 62427 : delete logger_;
3080 62427 : logger_ = nullptr;
3081 :
3082 62427 : delete handle_scope_implementer_;
3083 62427 : handle_scope_implementer_ = nullptr;
3084 :
3085 : delete code_tracer();
3086 : set_code_tracer(nullptr);
3087 :
3088 62427 : delete compilation_cache_;
3089 62427 : compilation_cache_ = nullptr;
3090 62427 : delete bootstrapper_;
3091 62427 : bootstrapper_ = nullptr;
3092 62427 : delete inner_pointer_to_code_cache_;
3093 62427 : inner_pointer_to_code_cache_ = nullptr;
3094 :
3095 62427 : delete thread_manager_;
3096 62427 : thread_manager_ = nullptr;
3097 :
3098 62427 : delete global_handles_;
3099 62427 : global_handles_ = nullptr;
3100 62427 : delete eternal_handles_;
3101 62427 : eternal_handles_ = nullptr;
3102 :
3103 62442 : delete string_stream_debug_object_cache_;
3104 62427 : string_stream_debug_object_cache_ = nullptr;
3105 :
3106 62427 : delete random_number_generator_;
3107 62427 : random_number_generator_ = nullptr;
3108 :
3109 62427 : delete fuzzer_rng_;
3110 62427 : fuzzer_rng_ = nullptr;
3111 :
3112 62427 : delete debug_;
3113 62427 : debug_ = nullptr;
3114 :
3115 62427 : delete cancelable_task_manager_;
3116 62427 : cancelable_task_manager_ = nullptr;
3117 :
3118 62427 : delete allocator_;
3119 62427 : allocator_ = nullptr;
3120 :
3121 : // Assert that |default_microtask_queue_| is the last MicrotaskQueue instance.
3122 : DCHECK_IMPLIES(default_microtask_queue_,
3123 : default_microtask_queue_ == default_microtask_queue_->next());
3124 62427 : delete default_microtask_queue_;
3125 62427 : default_microtask_queue_ = nullptr;
3126 62427 : }
3127 :
3128 94866 : void Isolate::InitializeThreadLocal() { thread_local_top()->Initialize(this); }
3129 :
3130 20 : void Isolate::SetTerminationOnExternalTryCatch() {
3131 1826 : if (try_catch_handler() == nullptr) return;
3132 1816 : try_catch_handler()->can_continue_ = false;
3133 1816 : try_catch_handler()->has_terminated_ = true;
3134 : try_catch_handler()->exception_ =
3135 1816 : reinterpret_cast<void*>(ReadOnlyRoots(heap()).null_value().ptr());
3136 : }
3137 :
3138 170094 : bool Isolate::PropagatePendingExceptionToExternalTryCatch() {
3139 : Object exception = pending_exception();
3140 :
3141 170094 : if (IsJavaScriptHandlerOnTop(exception)) {
3142 138453 : thread_local_top()->external_caught_exception_ = false;
3143 138453 : return false;
3144 : }
3145 :
3146 31641 : if (!IsExternalHandlerOnTop(exception)) {
3147 4492 : thread_local_top()->external_caught_exception_ = false;
3148 4492 : return true;
3149 : }
3150 :
3151 27149 : thread_local_top()->external_caught_exception_ = true;
3152 27149 : if (!is_catchable_by_javascript(exception)) {
3153 : SetTerminationOnExternalTryCatch();
3154 : } else {
3155 : v8::TryCatch* handler = try_catch_handler();
3156 : DCHECK(thread_local_top()->pending_message_obj_->IsJSMessageObject() ||
3157 : thread_local_top()->pending_message_obj_->IsTheHole(this));
3158 25343 : handler->can_continue_ = true;
3159 25343 : handler->has_terminated_ = false;
3160 25343 : handler->exception_ = reinterpret_cast<void*>(pending_exception().ptr());
3161 : // Propagate to the external try-catch only if we got an actual message.
3162 25343 : if (thread_local_top()->pending_message_obj_->IsTheHole(this)) return true;
3163 :
3164 : handler->message_obj_ =
3165 11221 : reinterpret_cast<void*>(thread_local_top()->pending_message_obj_.ptr());
3166 : }
3167 : return true;
3168 : }
3169 :
3170 63018 : bool Isolate::InitializeCounters() {
3171 63018 : if (async_counters_) return false;
3172 124883 : async_counters_ = std::make_shared<Counters>(this);
3173 62442 : return true;
3174 : }
3175 :
3176 63019 : void Isolate::InitializeLoggingAndCounters() {
3177 63019 : if (logger_ == nullptr) {
3178 62440 : logger_ = new Logger(this);
3179 : }
3180 63017 : InitializeCounters();
3181 63021 : }
3182 :
3183 : namespace {
3184 :
3185 56 : void CreateOffHeapTrampolines(Isolate* isolate) {
3186 : DCHECK_NOT_NULL(isolate->embedded_blob());
3187 : DCHECK_NE(0, isolate->embedded_blob_size());
3188 :
3189 : HandleScope scope(isolate);
3190 : Builtins* builtins = isolate->builtins();
3191 :
3192 56 : EmbeddedData d = EmbeddedData::FromBlob();
3193 :
3194 170520 : for (int i = 0; i < Builtins::builtin_count; i++) {
3195 : if (!Builtins::IsIsolateIndependent(i)) continue;
3196 :
3197 85232 : Address instruction_start = d.InstructionStartOfBuiltin(i);
3198 : Handle<Code> trampoline = isolate->factory()->NewOffHeapTrampolineFor(
3199 85232 : builtins->builtin_handle(i), instruction_start);
3200 :
3201 : // From this point onwards, the old builtin code object is unreachable and
3202 : // will be collected by the next GC.
3203 85232 : builtins->set_builtin(i, *trampoline);
3204 :
3205 85232 : if (isolate->logger()->is_listening_to_code_events() ||
3206 : isolate->is_profiling()) {
3207 0 : isolate->logger()->LogCodeObject(*trampoline);
3208 : }
3209 : }
3210 56 : }
3211 :
3212 : #ifdef DEBUG
3213 : bool IsolateIsCompatibleWithEmbeddedBlob(Isolate* isolate) {
3214 : if (!FLAG_embedded_builtins) return true;
3215 : EmbeddedData d = EmbeddedData::FromBlob(isolate);
3216 : return (d.IsolateHash() == isolate->HashIsolateForEmbeddedBlob());
3217 : }
3218 : #endif // DEBUG
3219 :
3220 : } // namespace
3221 :
3222 62441 : void Isolate::InitializeDefaultEmbeddedBlob() {
3223 : const uint8_t* blob = DefaultEmbeddedBlob();
3224 : uint32_t size = DefaultEmbeddedBlobSize();
3225 :
3226 : #ifdef V8_MULTI_SNAPSHOTS
3227 : if (!FLAG_untrusted_code_mitigations) {
3228 : blob = TrustedEmbeddedBlob();
3229 : size = TrustedEmbeddedBlobSize();
3230 : }
3231 : #endif
3232 :
3233 62441 : if (StickyEmbeddedBlob() != nullptr) {
3234 : base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
3235 : // Check again now that we hold the lock.
3236 55 : if (StickyEmbeddedBlob() != nullptr) {
3237 : blob = StickyEmbeddedBlob();
3238 : size = StickyEmbeddedBlobSize();
3239 55 : current_embedded_blob_refs_++;
3240 : }
3241 : }
3242 :
3243 62441 : if (blob == nullptr) {
3244 1 : CHECK_EQ(0, size);
3245 : } else {
3246 62440 : SetEmbeddedBlob(blob, size);
3247 : }
3248 62441 : }
3249 :
3250 56 : void Isolate::CreateAndSetEmbeddedBlob() {
3251 : base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
3252 :
3253 : PrepareBuiltinSourcePositionMap();
3254 :
3255 : // If a sticky blob has been set, we reuse it.
3256 56 : if (StickyEmbeddedBlob() != nullptr) {
3257 0 : CHECK_EQ(embedded_blob(), StickyEmbeddedBlob());
3258 0 : CHECK_EQ(CurrentEmbeddedBlob(), StickyEmbeddedBlob());
3259 : } else {
3260 : // Create and set a new embedded blob.
3261 : uint8_t* data;
3262 : uint32_t size;
3263 56 : InstructionStream::CreateOffHeapInstructionStream(this, &data, &size);
3264 :
3265 56 : CHECK_EQ(0, current_embedded_blob_refs_);
3266 56 : const uint8_t* const_data = const_cast<const uint8_t*>(data);
3267 56 : SetEmbeddedBlob(const_data, size);
3268 56 : current_embedded_blob_refs_++;
3269 :
3270 56 : SetStickyEmbeddedBlob(const_data, size);
3271 : }
3272 :
3273 56 : CreateOffHeapTrampolines(this);
3274 56 : }
3275 :
3276 62427 : void Isolate::TearDownEmbeddedBlob() {
3277 : // Nothing to do in case the blob is embedded into the binary or unset.
3278 62427 : if (StickyEmbeddedBlob() == nullptr) return;
3279 :
3280 111 : CHECK_EQ(embedded_blob(), StickyEmbeddedBlob());
3281 111 : CHECK_EQ(CurrentEmbeddedBlob(), StickyEmbeddedBlob());
3282 :
3283 : base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
3284 111 : current_embedded_blob_refs_--;
3285 111 : if (current_embedded_blob_refs_ == 0 && enable_embedded_blob_refcounting_) {
3286 : // We own the embedded blob and are the last holder. Free it.
3287 : InstructionStream::FreeOffHeapInstructionStream(
3288 0 : const_cast<uint8_t*>(embedded_blob()), embedded_blob_size());
3289 0 : ClearEmbeddedBlob();
3290 : }
3291 : }
3292 :
3293 1 : bool Isolate::InitWithoutSnapshot() { return Init(nullptr, nullptr); }
3294 :
3295 62329 : bool Isolate::InitWithSnapshot(ReadOnlyDeserializer* read_only_deserializer,
3296 : StartupDeserializer* startup_deserializer) {
3297 : DCHECK_NOT_NULL(read_only_deserializer);
3298 : DCHECK_NOT_NULL(startup_deserializer);
3299 62329 : return Init(read_only_deserializer, startup_deserializer);
3300 : }
3301 :
3302 62440 : bool Isolate::Init(ReadOnlyDeserializer* read_only_deserializer,
3303 : StartupDeserializer* startup_deserializer) {
3304 : TRACE_ISOLATE(init);
3305 62440 : const bool create_heap_objects = (read_only_deserializer == nullptr);
3306 : // We either have both or neither.
3307 : DCHECK_EQ(create_heap_objects, startup_deserializer == nullptr);
3308 :
3309 : base::ElapsedTimer timer;
3310 62440 : if (create_heap_objects && FLAG_profile_deserialization) timer.Start();
3311 :
3312 62440 : time_millis_at_init_ = heap_.MonotonicallyIncreasingTimeInMs();
3313 :
3314 62439 : stress_deopt_count_ = FLAG_deopt_every_n_times;
3315 62439 : force_slow_path_ = FLAG_force_slow_path;
3316 :
3317 62439 : has_fatal_error_ = false;
3318 :
3319 : // The initialization process does not handle memory exhaustion.
3320 : AlwaysAllocateScope always_allocate(this);
3321 :
3322 : // Safe after setting Heap::isolate_, and initializing StackGuard
3323 62439 : heap_.SetStackLimits();
3324 :
3325 : #define ASSIGN_ELEMENT(CamelName, hacker_name) \
3326 : isolate_addresses_[IsolateAddressId::k##CamelName##Address] = \
3327 : reinterpret_cast<Address>(hacker_name##_address());
3328 749292 : FOR_EACH_ISOLATE_ADDRESS_NAME(ASSIGN_ELEMENT)
3329 : #undef ASSIGN_ELEMENT
3330 :
3331 62441 : compilation_cache_ = new CompilationCache(this);
3332 124884 : descriptor_lookup_cache_ = new DescriptorLookupCache();
3333 124884 : unicode_cache_ = new UnicodeCache();
3334 62442 : inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this);
3335 62442 : global_handles_ = new GlobalHandles(this);
3336 124884 : eternal_handles_ = new EternalHandles();
3337 62442 : bootstrapper_ = new Bootstrapper(this);
3338 124884 : handle_scope_implementer_ = new HandleScopeImplementer(this);
3339 62442 : load_stub_cache_ = new StubCache(this);
3340 62441 : store_stub_cache_ = new StubCache(this);
3341 124884 : materialized_object_store_ = new MaterializedObjectStore(this);
3342 62442 : regexp_stack_ = new RegExpStack();
3343 62441 : regexp_stack_->isolate_ = this;
3344 62441 : date_cache_ = new DateCache();
3345 62442 : heap_profiler_ = new HeapProfiler(heap());
3346 62442 : interpreter_ = new interpreter::Interpreter(this);
3347 :
3348 : compiler_dispatcher_ =
3349 62442 : new CompilerDispatcher(this, V8::GetCurrentPlatform(), FLAG_stack_size);
3350 :
3351 : // Enable logging before setting up the heap
3352 62442 : logger_->SetUp(this);
3353 :
3354 : { // NOLINT
3355 : // Ensure that the thread has a valid stack guard. The v8::Locker object
3356 : // will ensure this too, but we don't have to use lockers if we are only
3357 : // using one thread.
3358 : ExecutionAccess lock(this);
3359 62442 : stack_guard_.InitThread(lock);
3360 : }
3361 :
3362 : // SetUp the object heap.
3363 : DCHECK(!heap_.HasBeenSetUp());
3364 62442 : heap_.SetUp();
3365 62442 : ReadOnlyHeap::SetUp(this, read_only_deserializer);
3366 62442 : heap_.SetUpSpaces();
3367 :
3368 62442 : isolate_data_.external_reference_table()->Init(this);
3369 :
3370 : // Setup the wasm engine.
3371 62442 : if (wasm_engine_ == nullptr) {
3372 124716 : SetWasmEngine(wasm::WasmEngine::GetWasmEngine());
3373 : }
3374 : DCHECK_NOT_NULL(wasm_engine_);
3375 :
3376 62442 : deoptimizer_data_ = new DeoptimizerData(heap());
3377 :
3378 62442 : if (setup_delegate_ == nullptr) {
3379 124354 : setup_delegate_ = new SetupIsolateDelegate(create_heap_objects);
3380 : }
3381 :
3382 62442 : if (!setup_delegate_->SetupHeap(&heap_)) {
3383 0 : V8::FatalProcessOutOfMemory(this, "heap object creation");
3384 : return false;
3385 : }
3386 :
3387 62442 : if (create_heap_objects) {
3388 : // Terminate the partial snapshot cache so we can iterate.
3389 112 : partial_snapshot_cache_.push_back(ReadOnlyRoots(this).undefined_value());
3390 : }
3391 :
3392 : InitializeThreadLocal();
3393 :
3394 : // Profiler has to be created after ThreadLocal is initialized
3395 : // because it makes use of interrupts.
3396 62442 : tracing_cpu_profiler_.reset(new TracingCpuProfilerImpl(this));
3397 :
3398 62442 : bootstrapper_->Initialize(create_heap_objects);
3399 :
3400 62442 : if (FLAG_embedded_builtins && create_heap_objects) {
3401 56 : builtins_constants_table_builder_ = new BuiltinsConstantsTableBuilder(this);
3402 : }
3403 62442 : setup_delegate_->SetupBuiltins(this);
3404 : #ifndef V8_TARGET_ARCH_ARM
3405 62442 : if (create_heap_objects) {
3406 : // Store the interpreter entry trampoline on the root list. It is used as a
3407 : // template for further copies that may later be created to help profile
3408 : // interpreted code.
3409 : // We currently cannot do this on arm due to RELATIVE_CODE_TARGETs
3410 : // assuming that all possible Code targets may be addressed with an int24
3411 : // offset, effectively limiting code space size to 32MB. We can guarantee
3412 : // this at mksnapshot-time, but not at runtime.
3413 : // See also: https://crbug.com/v8/8713.
3414 56 : heap_.SetInterpreterEntryTrampolineForProfiling(
3415 56 : heap_.builtin(Builtins::kInterpreterEntryTrampoline));
3416 : }
3417 : #endif
3418 62442 : if (FLAG_embedded_builtins && create_heap_objects) {
3419 56 : builtins_constants_table_builder_->Finalize();
3420 112 : delete builtins_constants_table_builder_;
3421 56 : builtins_constants_table_builder_ = nullptr;
3422 :
3423 56 : CreateAndSetEmbeddedBlob();
3424 : }
3425 :
3426 : // Initialize custom memcopy and memmove functions (must happen after
3427 : // embedded blob setup).
3428 62442 : init_memcopy_functions();
3429 :
3430 62442 : if (FLAG_log_internal_timer_events) {
3431 : set_event_logger(Logger::DefaultEventLoggerSentinel);
3432 : }
3433 :
3434 62442 : if (FLAG_trace_turbo || FLAG_trace_turbo_graph || FLAG_turbo_profiling) {
3435 5 : PrintF("Concurrent recompilation has been disabled for tracing.\n");
3436 62437 : } else if (OptimizingCompileDispatcher::Enabled()) {
3437 62338 : optimizing_compile_dispatcher_ = new OptimizingCompileDispatcher(this);
3438 : }
3439 :
3440 : // Initialize runtime profiler before deserialization, because collections may
3441 : // occur, clearing/updating ICs.
3442 62442 : runtime_profiler_ = new RuntimeProfiler(this);
3443 :
3444 : // If we are deserializing, read the state into the now-empty heap.
3445 : {
3446 : AlwaysAllocateScope always_allocate(this);
3447 124884 : CodeSpaceMemoryModificationScope modification_scope(&heap_);
3448 :
3449 62442 : if (!create_heap_objects) {
3450 62386 : startup_deserializer->DeserializeInto(this);
3451 : } else {
3452 56 : heap_.read_only_heap()->OnCreateHeapObjectsComplete();
3453 : }
3454 62441 : load_stub_cache_->Initialize();
3455 62441 : store_stub_cache_->Initialize();
3456 62442 : interpreter_->Initialize();
3457 62442 : heap_.NotifyDeserializationComplete();
3458 : }
3459 62442 : delete setup_delegate_;
3460 62442 : setup_delegate_ = nullptr;
3461 :
3462 : // Initialize the builtin entry table.
3463 62442 : Builtins::UpdateBuiltinEntryTable(this);
3464 :
3465 : #ifdef DEBUG
3466 : // Verify that the current heap state (usually deserialized from the snapshot)
3467 : // is compatible with the embedded blob. If this DCHECK fails, we've likely
3468 : // loaded a snapshot generated by a different V8 version or build-time
3469 : // configuration.
3470 : if (!IsolateIsCompatibleWithEmbeddedBlob(this)) {
3471 : FATAL(
3472 : "The Isolate is incompatible with the embedded blob. This is usually "
3473 : "caused by incorrect usage of mksnapshot. When generating custom "
3474 : "snapshots, embedders must ensure they pass the same flags as during "
3475 : "the V8 build process (e.g.: --turbo-instruction-scheduling).");
3476 : }
3477 : DCHECK_IMPLIES(FLAG_jitless, FLAG_embedded_builtins);
3478 : #endif // DEBUG
3479 :
3480 : #ifndef V8_TARGET_ARCH_ARM
3481 : // The IET for profiling should always be a full on-heap Code object.
3482 : DCHECK(!Code::cast(heap_.interpreter_entry_trampoline_for_profiling())
3483 : ->is_off_heap_trampoline());
3484 : #endif // V8_TARGET_ARCH_ARM
3485 :
3486 : if (FLAG_print_builtin_code) builtins()->PrintBuiltinCode();
3487 : if (FLAG_print_builtin_size) builtins()->PrintBuiltinSize();
3488 :
3489 : // Finish initialization of ThreadLocal after deserialization is done.
3490 : clear_pending_exception();
3491 : clear_pending_message();
3492 : clear_scheduled_exception();
3493 :
3494 : // Deserializing may put strange things in the root array's copy of the
3495 : // stack guard.
3496 62442 : heap_.SetStackLimits();
3497 :
3498 : // Quiet the heap NaN if needed on target platform.
3499 : if (!create_heap_objects)
3500 : Assembler::QuietNaN(ReadOnlyRoots(this).nan_value());
3501 :
3502 62442 : if (FLAG_trace_turbo) {
3503 : // Create an empty file.
3504 10 : std::ofstream(GetTurboCfgFileName(this).c_str(), std::ios_base::trunc);
3505 : }
3506 :
3507 : {
3508 : HandleScope scope(this);
3509 62442 : ast_string_constants_ = new AstStringConstants(this, HashSeed(this));
3510 : }
3511 :
3512 62442 : initialized_from_snapshot_ = !create_heap_objects;
3513 :
3514 62442 : if (!FLAG_inline_new) heap_.DisableInlineAllocation();
3515 :
3516 62442 : if (FLAG_stress_sampling_allocation_profiler > 0) {
3517 0 : uint64_t sample_interval = FLAG_stress_sampling_allocation_profiler;
3518 : int stack_depth = 128;
3519 : v8::HeapProfiler::SamplingFlags sampling_flags =
3520 : v8::HeapProfiler::SamplingFlags::kSamplingForceGC;
3521 : heap_profiler()->StartSamplingHeapProfiler(sample_interval, stack_depth,
3522 0 : sampling_flags);
3523 : }
3524 :
3525 : #if defined(V8_OS_WIN_X64)
3526 : if (win64_unwindinfo::CanRegisterUnwindInfoForNonABICompliantCodeRange()) {
3527 : const base::AddressRegion& code_range =
3528 : heap()->memory_allocator()->code_range();
3529 : void* start = reinterpret_cast<void*>(code_range.begin());
3530 : size_t size_in_bytes = code_range.size();
3531 : win64_unwindinfo::RegisterNonABICompliantCodeRange(start, size_in_bytes);
3532 : }
3533 : #endif
3534 :
3535 62442 : if (create_heap_objects && FLAG_profile_deserialization) {
3536 0 : double ms = timer.Elapsed().InMillisecondsF();
3537 0 : PrintF("[Initializing isolate from scratch took %0.3f ms]\n", ms);
3538 : }
3539 :
3540 : return true;
3541 : }
3542 :
3543 224153 : void Isolate::Enter() {
3544 : Isolate* current_isolate = nullptr;
3545 : PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
3546 224149 : if (current_data != nullptr) {
3547 11395 : current_isolate = current_data->isolate_;
3548 : DCHECK_NOT_NULL(current_isolate);
3549 11395 : if (current_isolate == this) {
3550 : DCHECK(Current() == this);
3551 : DCHECK_NOT_NULL(entry_stack_);
3552 : DCHECK(entry_stack_->previous_thread_data == nullptr ||
3553 : entry_stack_->previous_thread_data->thread_id() ==
3554 : ThreadId::Current());
3555 : // Same thread re-enters the isolate, no need to re-init anything.
3556 10241 : entry_stack_->entry_count++;
3557 10241 : return;
3558 : }
3559 : }
3560 :
3561 213908 : PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
3562 : DCHECK_NOT_NULL(data);
3563 : DCHECK(data->isolate_ == this);
3564 :
3565 : EntryStackItem* item = new EntryStackItem(current_data,
3566 : current_isolate,
3567 213915 : entry_stack_);
3568 213917 : entry_stack_ = item;
3569 :
3570 213917 : SetIsolateThreadLocals(this, data);
3571 :
3572 : // In case it's the first time some thread enters the isolate.
3573 : set_thread_id(data->thread_id());
3574 : }
3575 :
3576 :
3577 224149 : void Isolate::Exit() {
3578 : DCHECK_NOT_NULL(entry_stack_);
3579 : DCHECK(entry_stack_->previous_thread_data == nullptr ||
3580 : entry_stack_->previous_thread_data->thread_id() ==
3581 : ThreadId::Current());
3582 :
3583 224149 : if (--entry_stack_->entry_count > 0) return;
3584 :
3585 : DCHECK_NOT_NULL(CurrentPerIsolateThreadData());
3586 : DCHECK(CurrentPerIsolateThreadData()->isolate_ == this);
3587 :
3588 : // Pop the stack.
3589 213909 : EntryStackItem* item = entry_stack_;
3590 213909 : entry_stack_ = item->previous_item;
3591 :
3592 213909 : PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
3593 213909 : Isolate* previous_isolate = item->previous_isolate;
3594 :
3595 213909 : delete item;
3596 :
3597 : // Reinit the current thread for the isolate it was running before this one.
3598 213912 : SetIsolateThreadLocals(previous_isolate, previous_thread_data);
3599 : }
3600 :
3601 :
3602 6884 : void Isolate::LinkDeferredHandles(DeferredHandles* deferred) {
3603 6884 : deferred->next_ = deferred_handles_head_;
3604 6884 : if (deferred_handles_head_ != nullptr) {
3605 2039 : deferred_handles_head_->previous_ = deferred;
3606 : }
3607 6884 : deferred_handles_head_ = deferred;
3608 6884 : }
3609 :
3610 :
3611 6884 : void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) {
3612 : #ifdef DEBUG
3613 : // In debug mode assert that the linked list is well-formed.
3614 : DeferredHandles* deferred_iterator = deferred;
3615 : while (deferred_iterator->previous_ != nullptr) {
3616 : deferred_iterator = deferred_iterator->previous_;
3617 : }
3618 : DCHECK(deferred_handles_head_ == deferred_iterator);
3619 : #endif
3620 6884 : if (deferred_handles_head_ == deferred) {
3621 5153 : deferred_handles_head_ = deferred_handles_head_->next_;
3622 : }
3623 6884 : if (deferred->next_ != nullptr) {
3624 817 : deferred->next_->previous_ = deferred->previous_;
3625 : }
3626 6884 : if (deferred->previous_ != nullptr) {
3627 1731 : deferred->previous_->next_ = deferred->next_;
3628 : }
3629 6884 : }
3630 :
3631 62427 : void Isolate::DumpAndResetStats() {
3632 62427 : if (turbo_statistics() != nullptr) {
3633 : DCHECK(FLAG_turbo_stats || FLAG_turbo_stats_nvp);
3634 0 : StdoutStream os;
3635 0 : if (FLAG_turbo_stats) {
3636 0 : AsPrintableStatistics ps = {*turbo_statistics(), false};
3637 0 : os << ps << std::endl;
3638 : }
3639 0 : if (FLAG_turbo_stats_nvp) {
3640 0 : AsPrintableStatistics ps = {*turbo_statistics(), true};
3641 0 : os << ps << std::endl;
3642 : }
3643 0 : delete turbo_statistics_;
3644 0 : turbo_statistics_ = nullptr;
3645 : }
3646 : // TODO(7424): There is no public API for the {WasmEngine} yet. So for now we
3647 : // just dump and reset the engines statistics together with the Isolate.
3648 62427 : if (FLAG_turbo_stats_wasm) {
3649 0 : wasm_engine()->DumpAndResetTurboStatistics();
3650 : }
3651 62427 : if (V8_UNLIKELY(TracingFlags::runtime_stats.load(std::memory_order_relaxed) ==
3652 : v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) {
3653 : counters()->worker_thread_runtime_call_stats()->AddToMainTable(
3654 0 : counters()->runtime_call_stats());
3655 0 : counters()->runtime_call_stats()->Print();
3656 0 : counters()->runtime_call_stats()->Reset();
3657 : }
3658 62427 : }
3659 :
3660 23758 : void Isolate::AbortConcurrentOptimization(BlockingBehavior behavior) {
3661 23758 : if (concurrent_recompilation_enabled()) {
3662 : DisallowHeapAllocation no_recursive_gc;
3663 23702 : optimizing_compile_dispatcher()->Flush(behavior);
3664 : }
3665 23758 : }
3666 :
3667 0 : CompilationStatistics* Isolate::GetTurboStatistics() {
3668 0 : if (turbo_statistics() == nullptr)
3669 0 : set_turbo_statistics(new CompilationStatistics());
3670 0 : return turbo_statistics();
3671 : }
3672 :
3673 :
3674 264 : CodeTracer* Isolate::GetCodeTracer() {
3675 269 : if (code_tracer() == nullptr) set_code_tracer(new CodeTracer(id()));
3676 264 : return code_tracer();
3677 : }
3678 :
3679 1630650 : bool Isolate::use_optimizer() {
3680 1809016 : return FLAG_opt && !serializer_enabled_ && CpuFeatures::SupportsOptimizer() &&
3681 1630650 : !is_count_code_coverage();
3682 : }
3683 :
3684 483599 : bool Isolate::NeedsDetailedOptimizedCodeLineInfo() const {
3685 483599 : return NeedsSourcePositionsForProfiling() ||
3686 483601 : detailed_source_positions_for_profiling();
3687 : }
3688 :
3689 1604795 : bool Isolate::NeedsSourcePositionsForProfiling() const {
3690 1603662 : return FLAG_trace_deopt || FLAG_trace_turbo || FLAG_trace_turbo_graph ||
3691 3206796 : FLAG_turbo_profiling || FLAG_perf_prof || is_profiling() ||
3692 4774143 : debug_->is_active() || logger_->is_logging() || FLAG_trace_maps;
3693 : }
3694 :
3695 1498 : void Isolate::SetFeedbackVectorsForProfilingTools(Object value) {
3696 : DCHECK(value->IsUndefined(this) || value->IsArrayList());
3697 : heap()->set_feedback_vectors_for_profiling_tools(value);
3698 1498 : }
3699 :
3700 164 : void Isolate::MaybeInitializeVectorListFromHeap() {
3701 164 : if (!heap()->feedback_vectors_for_profiling_tools()->IsUndefined(this)) {
3702 : // Already initialized, return early.
3703 : DCHECK(heap()->feedback_vectors_for_profiling_tools()->IsArrayList());
3704 8 : return;
3705 : }
3706 :
3707 : // Collect existing feedback vectors.
3708 : std::vector<Handle<FeedbackVector>> vectors;
3709 :
3710 : {
3711 312 : HeapIterator heap_iterator(heap());
3712 1187999 : for (HeapObject current_obj = heap_iterator.next(); !current_obj.is_null();
3713 : current_obj = heap_iterator.next()) {
3714 2375254 : if (!current_obj->IsFeedbackVector()) continue;
3715 :
3716 432 : FeedbackVector vector = FeedbackVector::cast(current_obj);
3717 432 : SharedFunctionInfo shared = vector->shared_function_info();
3718 :
3719 : // No need to preserve the feedback vector for non-user-visible functions.
3720 432 : if (!shared->IsSubjectToDebugging()) continue;
3721 :
3722 432 : vectors.emplace_back(vector, this);
3723 : }
3724 : }
3725 :
3726 : // Add collected feedback vectors to the root list lest we lose them to GC.
3727 : Handle<ArrayList> list =
3728 156 : ArrayList::New(this, static_cast<int>(vectors.size()));
3729 1020 : for (const auto& vector : vectors) list = ArrayList::Add(this, list, vector);
3730 : SetFeedbackVectorsForProfilingTools(*list);
3731 : }
3732 :
3733 5 : void Isolate::set_date_cache(DateCache* date_cache) {
3734 5 : if (date_cache != date_cache_) {
3735 5 : delete date_cache_;
3736 : }
3737 5 : date_cache_ = date_cache;
3738 5 : }
3739 :
3740 15319 : bool Isolate::IsArrayOrObjectOrStringPrototype(Object object) {
3741 : Object context = heap()->native_contexts_list();
3742 59927 : while (!context->IsUndefined(this)) {
3743 23157 : Context current_context = Context::cast(context);
3744 69326 : if (current_context->initial_object_prototype() == object ||
3745 45519 : current_context->initial_array_prototype() == object ||
3746 22362 : current_context->initial_string_prototype() == object) {
3747 853 : return true;
3748 : }
3749 22304 : context = current_context->next_context_link();
3750 : }
3751 : return false;
3752 : }
3753 :
3754 6732286 : bool Isolate::IsInAnyContext(Object object, uint32_t index) {
3755 : DisallowHeapAllocation no_gc;
3756 : Object context = heap()->native_contexts_list();
3757 11608514 : while (!context->IsUndefined(this)) {
3758 8046849 : Context current_context = Context::cast(context);
3759 16093699 : if (current_context->get(index) == object) {
3760 5608736 : return true;
3761 : }
3762 2438114 : context = current_context->next_context_link();
3763 : }
3764 : return false;
3765 : }
3766 :
3767 100545 : bool Isolate::IsNoElementsProtectorIntact(Context context) {
3768 : PropertyCell no_elements_cell = heap()->no_elements_protector();
3769 : bool cell_reports_intact =
3770 11705530 : no_elements_cell->value()->IsSmi() &&
3771 : Smi::ToInt(no_elements_cell->value()) == kProtectorValid;
3772 :
3773 : #ifdef DEBUG
3774 : Context native_context = context->native_context();
3775 :
3776 : Map root_array_map =
3777 : native_context->GetInitialJSArrayMap(GetInitialFastElementsKind());
3778 : JSObject initial_array_proto = JSObject::cast(
3779 : native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
3780 : JSObject initial_object_proto = JSObject::cast(
3781 : native_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX));
3782 : JSObject initial_string_proto = JSObject::cast(
3783 : native_context->get(Context::INITIAL_STRING_PROTOTYPE_INDEX));
3784 :
3785 : if (root_array_map.is_null() || initial_array_proto == initial_object_proto) {
3786 : // We are in the bootstrapping process, and the entire check sequence
3787 : // shouldn't be performed.
3788 : return cell_reports_intact;
3789 : }
3790 :
3791 : // Check that the array prototype hasn't been altered WRT empty elements.
3792 : if (root_array_map->prototype() != initial_array_proto) {
3793 : DCHECK_EQ(false, cell_reports_intact);
3794 : return cell_reports_intact;
3795 : }
3796 :
3797 : FixedArrayBase elements = initial_array_proto->elements();
3798 : ReadOnlyRoots roots(heap());
3799 : if (elements != roots.empty_fixed_array() &&
3800 : elements != roots.empty_slow_element_dictionary()) {
3801 : DCHECK_EQ(false, cell_reports_intact);
3802 : return cell_reports_intact;
3803 : }
3804 :
3805 : // Check that the Object.prototype hasn't been altered WRT empty elements.
3806 : elements = initial_object_proto->elements();
3807 : if (elements != roots.empty_fixed_array() &&
3808 : elements != roots.empty_slow_element_dictionary()) {
3809 : DCHECK_EQ(false, cell_reports_intact);
3810 : return cell_reports_intact;
3811 : }
3812 :
3813 : // Check that the Array.prototype has the Object.prototype as its
3814 : // [[Prototype]] and that the Object.prototype has a null [[Prototype]].
3815 : PrototypeIterator iter(this, initial_array_proto);
3816 : if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) {
3817 : DCHECK_EQ(false, cell_reports_intact);
3818 : DCHECK(!has_pending_exception());
3819 : return cell_reports_intact;
3820 : }
3821 : iter.Advance();
3822 : if (!iter.IsAtEnd()) {
3823 : DCHECK_EQ(false, cell_reports_intact);
3824 : DCHECK(!has_pending_exception());
3825 : return cell_reports_intact;
3826 : }
3827 : DCHECK(!has_pending_exception());
3828 :
3829 : // Check that the String.prototype hasn't been altered WRT empty elements.
3830 : elements = initial_string_proto->elements();
3831 : if (elements != roots.empty_fixed_array() &&
3832 : elements != roots.empty_slow_element_dictionary()) {
3833 : DCHECK_EQ(false, cell_reports_intact);
3834 : return cell_reports_intact;
3835 : }
3836 :
3837 : // Check that the String.prototype has the Object.prototype
3838 : // as its [[Prototype]] still.
3839 : if (initial_string_proto->map()->prototype() != initial_object_proto) {
3840 : DCHECK_EQ(false, cell_reports_intact);
3841 : return cell_reports_intact;
3842 : }
3843 : #endif
3844 :
3845 100545 : return cell_reports_intact;
3846 : }
3847 :
3848 5735464 : bool Isolate::IsNoElementsProtectorIntact() {
3849 5735464 : return Isolate::IsNoElementsProtectorIntact(context());
3850 : }
3851 :
3852 301064 : bool Isolate::IsIsConcatSpreadableLookupChainIntact() {
3853 : Cell is_concat_spreadable_cell = heap()->is_concat_spreadable_protector();
3854 : bool is_is_concat_spreadable_set =
3855 : Smi::ToInt(is_concat_spreadable_cell->value()) == kProtectorInvalid;
3856 : #ifdef DEBUG
3857 : Map root_array_map =
3858 : raw_native_context()->GetInitialJSArrayMap(GetInitialFastElementsKind());
3859 : if (root_array_map.is_null()) {
3860 : // Ignore the value of is_concat_spreadable during bootstrap.
3861 : return !is_is_concat_spreadable_set;
3862 : }
3863 : Handle<Object> array_prototype(array_function()->prototype(), this);
3864 : Handle<Symbol> key = factory()->is_concat_spreadable_symbol();
3865 : Handle<Object> value;
3866 : LookupIterator it(this, array_prototype, key);
3867 : if (it.IsFound() && !JSReceiver::GetDataProperty(&it)->IsUndefined(this)) {
3868 : // TODO(cbruni): Currently we do not revert if we unset the
3869 : // @@isConcatSpreadable property on Array.prototype or Object.prototype
3870 : // hence the reverse implication doesn't hold.
3871 : DCHECK(is_is_concat_spreadable_set);
3872 : return false;
3873 : }
3874 : #endif // DEBUG
3875 :
3876 301064 : return !is_is_concat_spreadable_set;
3877 : }
3878 :
3879 10387 : bool Isolate::IsIsConcatSpreadableLookupChainIntact(JSReceiver receiver) {
3880 10387 : if (!IsIsConcatSpreadableLookupChainIntact()) return false;
3881 4282 : return !receiver->HasProxyInPrototype(this);
3882 : }
3883 :
3884 0 : bool Isolate::IsPromiseHookProtectorIntact() {
3885 : PropertyCell promise_hook_cell = heap()->promise_hook_protector();
3886 : bool is_promise_hook_protector_intact =
3887 0 : Smi::ToInt(promise_hook_cell->value()) == kProtectorValid;
3888 : DCHECK_IMPLIES(is_promise_hook_protector_intact,
3889 : !promise_hook_or_async_event_delegate_);
3890 : DCHECK_IMPLIES(is_promise_hook_protector_intact,
3891 : !promise_hook_or_debug_is_active_or_async_event_delegate_);
3892 0 : return is_promise_hook_protector_intact;
3893 : }
3894 :
3895 1728 : bool Isolate::IsPromiseResolveLookupChainIntact() {
3896 : Cell promise_resolve_cell = heap()->promise_resolve_protector();
3897 : bool is_promise_resolve_protector_intact =
3898 1728 : Smi::ToInt(promise_resolve_cell->value()) == kProtectorValid;
3899 1728 : return is_promise_resolve_protector_intact;
3900 : }
3901 :
3902 1686 : bool Isolate::IsPromiseThenLookupChainIntact() {
3903 : PropertyCell promise_then_cell = heap()->promise_then_protector();
3904 : bool is_promise_then_protector_intact =
3905 3296 : Smi::ToInt(promise_then_cell->value()) == kProtectorValid;
3906 1686 : return is_promise_then_protector_intact;
3907 : }
3908 :
3909 3750 : bool Isolate::IsPromiseThenLookupChainIntact(Handle<JSReceiver> receiver) {
3910 : DisallowHeapAllocation no_gc;
3911 3750 : if (!receiver->IsJSPromise()) return false;
3912 1610 : if (!IsInAnyContext(receiver->map()->prototype(),
3913 : Context::PROMISE_PROTOTYPE_INDEX)) {
3914 : return false;
3915 : }
3916 1610 : return IsPromiseThenLookupChainIntact();
3917 : }
3918 :
3919 1205980 : void Isolate::UpdateNoElementsProtectorOnSetElement(Handle<JSObject> object) {
3920 : DisallowHeapAllocation no_gc;
3921 1205980 : if (!object->map()->is_prototype_map()) return;
3922 16755 : if (!IsNoElementsProtectorIntact()) return;
3923 15319 : if (!IsArrayOrObjectOrStringPrototype(*object)) return;
3924 853 : PropertyCell::SetValueWithInvalidation(
3925 : this, factory()->no_elements_protector(),
3926 853 : handle(Smi::FromInt(kProtectorInvalid), this));
3927 : }
3928 :
3929 65 : void Isolate::InvalidateIsConcatSpreadableProtector() {
3930 : DCHECK(factory()->is_concat_spreadable_protector()->value()->IsSmi());
3931 : DCHECK(IsIsConcatSpreadableLookupChainIntact());
3932 130 : factory()->is_concat_spreadable_protector()->set_value(
3933 195 : Smi::FromInt(kProtectorInvalid));
3934 : DCHECK(!IsIsConcatSpreadableLookupChainIntact());
3935 65 : }
3936 :
3937 230 : void Isolate::InvalidateArrayConstructorProtector() {
3938 : DCHECK(factory()->array_constructor_protector()->value()->IsSmi());
3939 : DCHECK(IsArrayConstructorIntact());
3940 460 : factory()->array_constructor_protector()->set_value(
3941 690 : Smi::FromInt(kProtectorInvalid));
3942 : DCHECK(!IsArrayConstructorIntact());
3943 230 : }
3944 :
3945 123 : void Isolate::InvalidateArraySpeciesProtector() {
3946 : DCHECK(factory()->array_species_protector()->value()->IsSmi());
3947 : DCHECK(IsArraySpeciesLookupChainIntact());
3948 123 : PropertyCell::SetValueWithInvalidation(
3949 : this, factory()->array_species_protector(),
3950 123 : handle(Smi::FromInt(kProtectorInvalid), this));
3951 : DCHECK(!IsArraySpeciesLookupChainIntact());
3952 123 : }
3953 :
3954 245 : void Isolate::InvalidateTypedArraySpeciesProtector() {
3955 : DCHECK(factory()->typed_array_species_protector()->value()->IsSmi());
3956 : DCHECK(IsTypedArraySpeciesLookupChainIntact());
3957 245 : PropertyCell::SetValueWithInvalidation(
3958 : this, factory()->typed_array_species_protector(),
3959 245 : handle(Smi::FromInt(kProtectorInvalid), this));
3960 : DCHECK(!IsTypedArraySpeciesLookupChainIntact());
3961 245 : }
3962 :
3963 25 : void Isolate::InvalidateRegExpSpeciesProtector() {
3964 : DCHECK(factory()->regexp_species_protector()->value()->IsSmi());
3965 : DCHECK(IsRegExpSpeciesLookupChainIntact());
3966 25 : PropertyCell::SetValueWithInvalidation(
3967 : this, factory()->regexp_species_protector(),
3968 25 : handle(Smi::FromInt(kProtectorInvalid), this));
3969 : DCHECK(!IsRegExpSpeciesLookupChainIntact());
3970 25 : }
3971 :
3972 59 : void Isolate::InvalidatePromiseSpeciesProtector() {
3973 : DCHECK(factory()->promise_species_protector()->value()->IsSmi());
3974 : DCHECK(IsPromiseSpeciesLookupChainIntact());
3975 59 : PropertyCell::SetValueWithInvalidation(
3976 : this, factory()->promise_species_protector(),
3977 59 : handle(Smi::FromInt(kProtectorInvalid), this));
3978 : DCHECK(!IsPromiseSpeciesLookupChainIntact());
3979 59 : }
3980 :
3981 143 : void Isolate::InvalidateStringLengthOverflowProtector() {
3982 : DCHECK(factory()->string_length_protector()->value()->IsSmi());
3983 : DCHECK(IsStringLengthOverflowIntact());
3984 286 : factory()->string_length_protector()->set_value(
3985 429 : Smi::FromInt(kProtectorInvalid));
3986 : DCHECK(!IsStringLengthOverflowIntact());
3987 143 : }
3988 :
3989 107 : void Isolate::InvalidateArrayIteratorProtector() {
3990 : DCHECK(factory()->array_iterator_protector()->value()->IsSmi());
3991 : DCHECK(IsArrayIteratorLookupChainIntact());
3992 107 : PropertyCell::SetValueWithInvalidation(
3993 : this, factory()->array_iterator_protector(),
3994 107 : handle(Smi::FromInt(kProtectorInvalid), this));
3995 : DCHECK(!IsArrayIteratorLookupChainIntact());
3996 107 : }
3997 :
3998 55 : void Isolate::InvalidateMapIteratorProtector() {
3999 : DCHECK(factory()->map_iterator_protector()->value()->IsSmi());
4000 : DCHECK(IsMapIteratorLookupChainIntact());
4001 55 : PropertyCell::SetValueWithInvalidation(
4002 : this, factory()->map_iterator_protector(),
4003 55 : handle(Smi::FromInt(kProtectorInvalid), this));
4004 : DCHECK(!IsMapIteratorLookupChainIntact());
4005 55 : }
4006 :
4007 65 : void Isolate::InvalidateSetIteratorProtector() {
4008 : DCHECK(factory()->set_iterator_protector()->value()->IsSmi());
4009 : DCHECK(IsSetIteratorLookupChainIntact());
4010 65 : PropertyCell::SetValueWithInvalidation(
4011 : this, factory()->set_iterator_protector(),
4012 65 : handle(Smi::FromInt(kProtectorInvalid), this));
4013 : DCHECK(!IsSetIteratorLookupChainIntact());
4014 65 : }
4015 :
4016 25 : void Isolate::InvalidateStringIteratorProtector() {
4017 : DCHECK(factory()->string_iterator_protector()->value()->IsSmi());
4018 : DCHECK(IsStringIteratorLookupChainIntact());
4019 25 : PropertyCell::SetValueWithInvalidation(
4020 : this, factory()->string_iterator_protector(),
4021 25 : handle(Smi::FromInt(kProtectorInvalid), this));
4022 : DCHECK(!IsStringIteratorLookupChainIntact());
4023 25 : }
4024 :
4025 426 : void Isolate::InvalidateArrayBufferDetachingProtector() {
4026 : DCHECK(factory()->array_buffer_detaching_protector()->value()->IsSmi());
4027 : DCHECK(IsArrayBufferDetachingIntact());
4028 426 : PropertyCell::SetValueWithInvalidation(
4029 : this, factory()->array_buffer_detaching_protector(),
4030 426 : handle(Smi::FromInt(kProtectorInvalid), this));
4031 : DCHECK(!IsArrayBufferDetachingIntact());
4032 426 : }
4033 :
4034 2786 : void Isolate::InvalidatePromiseHookProtector() {
4035 : DCHECK(factory()->promise_hook_protector()->value()->IsSmi());
4036 : DCHECK(IsPromiseHookProtectorIntact());
4037 2786 : PropertyCell::SetValueWithInvalidation(
4038 : this, factory()->promise_hook_protector(),
4039 2786 : handle(Smi::FromInt(kProtectorInvalid), this));
4040 : DCHECK(!IsPromiseHookProtectorIntact());
4041 2786 : }
4042 :
4043 0 : void Isolate::InvalidatePromiseResolveProtector() {
4044 : DCHECK(factory()->promise_resolve_protector()->value()->IsSmi());
4045 : DCHECK(IsPromiseResolveLookupChainIntact());
4046 0 : factory()->promise_resolve_protector()->set_value(
4047 0 : Smi::FromInt(kProtectorInvalid));
4048 : DCHECK(!IsPromiseResolveLookupChainIntact());
4049 0 : }
4050 :
4051 103 : void Isolate::InvalidatePromiseThenProtector() {
4052 : DCHECK(factory()->promise_then_protector()->value()->IsSmi());
4053 : DCHECK(IsPromiseThenLookupChainIntact());
4054 103 : PropertyCell::SetValueWithInvalidation(
4055 : this, factory()->promise_then_protector(),
4056 103 : handle(Smi::FromInt(kProtectorInvalid), this));
4057 : DCHECK(!IsPromiseThenLookupChainIntact());
4058 103 : }
4059 :
4060 6497347 : bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) {
4061 : DisallowHeapAllocation no_gc;
4062 6497347 : return IsInAnyContext(*array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
4063 : }
4064 :
4065 128239 : static base::RandomNumberGenerator* ensure_rng_exists(
4066 : base::RandomNumberGenerator** rng, int seed) {
4067 128239 : if (*rng == nullptr) {
4068 62324 : if (seed != 0) {
4069 121688 : *rng = new base::RandomNumberGenerator(seed);
4070 : } else {
4071 1480 : *rng = new base::RandomNumberGenerator();
4072 : }
4073 : }
4074 128239 : return *rng;
4075 : }
4076 :
4077 74348 : base::RandomNumberGenerator* Isolate::random_number_generator() {
4078 : // TODO(bmeurer) Initialized lazily because it depends on flags; can
4079 : // be fixed once the default isolate cleanup is done.
4080 128239 : return ensure_rng_exists(&random_number_generator_, FLAG_random_seed);
4081 : }
4082 :
4083 0 : base::RandomNumberGenerator* Isolate::fuzzer_rng() {
4084 0 : if (fuzzer_rng_ == nullptr) {
4085 0 : int64_t seed = FLAG_fuzzer_random_seed;
4086 0 : if (seed == 0) {
4087 : seed = random_number_generator()->initial_seed();
4088 : }
4089 :
4090 0 : fuzzer_rng_ = new base::RandomNumberGenerator(seed);
4091 : }
4092 :
4093 0 : return fuzzer_rng_;
4094 : }
4095 :
4096 53891 : int Isolate::GenerateIdentityHash(uint32_t mask) {
4097 : int hash;
4098 : int attempts = 0;
4099 53890 : do {
4100 53890 : hash = random_number_generator()->NextInt() & mask;
4101 53890 : } while (hash == 0 && attempts++ < 30);
4102 53890 : return hash != 0 ? hash : 1;
4103 : }
4104 :
4105 20971 : Code Isolate::FindCodeObject(Address a) {
4106 20971 : return heap()->GcSafeFindCodeForInnerPointer(a);
4107 : }
4108 :
4109 :
4110 : #ifdef DEBUG
4111 : #define ISOLATE_FIELD_OFFSET(type, name, ignored) \
4112 : const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
4113 : ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
4114 : ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
4115 : #undef ISOLATE_FIELD_OFFSET
4116 : #endif
4117 :
4118 255007 : Handle<Symbol> Isolate::SymbolFor(RootIndex dictionary_index,
4119 : Handle<String> name, bool private_symbol) {
4120 255007 : Handle<String> key = factory()->InternalizeString(name);
4121 : Handle<NameDictionary> dictionary =
4122 : Handle<NameDictionary>::cast(root_handle(dictionary_index));
4123 255007 : int entry = dictionary->FindEntry(this, key);
4124 : Handle<Symbol> symbol;
4125 255007 : if (entry == NameDictionary::kNotFound) {
4126 : symbol =
4127 2723 : private_symbol ? factory()->NewPrivateSymbol() : factory()->NewSymbol();
4128 5446 : symbol->set_name(*key);
4129 : dictionary = NameDictionary::Add(this, dictionary, key, symbol,
4130 2723 : PropertyDetails::Empty(), &entry);
4131 2723 : switch (dictionary_index) {
4132 : case RootIndex::kPublicSymbolTable:
4133 : symbol->set_is_public(true);
4134 : heap()->set_public_symbol_table(*dictionary);
4135 : break;
4136 : case RootIndex::kApiSymbolTable:
4137 : heap()->set_api_symbol_table(*dictionary);
4138 : break;
4139 : case RootIndex::kApiPrivateSymbolTable:
4140 : heap()->set_api_private_symbol_table(*dictionary);
4141 : break;
4142 : default:
4143 0 : UNREACHABLE();
4144 : }
4145 : } else {
4146 : symbol = Handle<Symbol>(Symbol::cast(dictionary->ValueAt(entry)), this);
4147 : }
4148 255007 : return symbol;
4149 : }
4150 :
4151 15 : void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) {
4152 : auto pos = std::find(before_call_entered_callbacks_.begin(),
4153 15 : before_call_entered_callbacks_.end(), callback);
4154 20 : if (pos != before_call_entered_callbacks_.end()) return;
4155 10 : before_call_entered_callbacks_.push_back(callback);
4156 : }
4157 :
4158 5 : void Isolate::RemoveBeforeCallEnteredCallback(
4159 : BeforeCallEnteredCallback callback) {
4160 : auto pos = std::find(before_call_entered_callbacks_.begin(),
4161 5 : before_call_entered_callbacks_.end(), callback);
4162 5 : if (pos == before_call_entered_callbacks_.end()) return;
4163 5 : before_call_entered_callbacks_.erase(pos);
4164 : }
4165 :
4166 65 : void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
4167 : auto pos = std::find(call_completed_callbacks_.begin(),
4168 65 : call_completed_callbacks_.end(), callback);
4169 70 : if (pos != call_completed_callbacks_.end()) return;
4170 60 : call_completed_callbacks_.push_back(callback);
4171 : }
4172 :
4173 3730 : void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
4174 : auto pos = std::find(call_completed_callbacks_.begin(),
4175 3730 : call_completed_callbacks_.end(), callback);
4176 3730 : if (pos == call_completed_callbacks_.end()) return;
4177 45 : call_completed_callbacks_.erase(pos);
4178 : }
4179 :
4180 5427901 : void Isolate::FireCallCompletedCallback(MicrotaskQueue* microtask_queue) {
4181 10855773 : if (!handle_scope_implementer()->CallDepthIsZero()) return;
4182 :
4183 : bool run_microtasks =
4184 547508 : microtask_queue && microtask_queue->size() &&
4185 574666 : !microtask_queue->HasMicrotasksSuppressions() &&
4186 : microtask_queue->microtasks_policy() == v8::MicrotasksPolicy::kAuto;
4187 :
4188 547510 : if (run_microtasks) {
4189 1988 : microtask_queue->RunMicrotasks(this);
4190 : } else {
4191 : // TODO(marja): (spec) The discussion about when to clear the KeepDuringJob
4192 : // set is still open (whether to clear it after every microtask or once
4193 : // during a microtask checkpoint). See also
4194 : // https://github.com/tc39/proposal-weakrefs/issues/39 .
4195 545522 : heap()->ClearKeepDuringJobSet();
4196 : }
4197 :
4198 547511 : if (call_completed_callbacks_.empty()) return;
4199 : // Fire callbacks. Increase call depth to prevent recursive callbacks.
4200 : v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this);
4201 60 : v8::Isolate::SuppressMicrotaskExecutionScope suppress(isolate);
4202 30 : std::vector<CallCompletedCallback> callbacks(call_completed_callbacks_);
4203 65 : for (auto& callback : callbacks) {
4204 35 : callback(reinterpret_cast<v8::Isolate*>(this));
4205 : }
4206 : }
4207 :
4208 8483 : void Isolate::PromiseHookStateUpdated() {
4209 : bool promise_hook_or_async_event_delegate =
4210 8483 : promise_hook_ || async_event_delegate_;
4211 : bool promise_hook_or_debug_is_active_or_async_event_delegate =
4212 8483 : promise_hook_or_async_event_delegate || debug()->is_active();
4213 12975 : if (promise_hook_or_debug_is_active_or_async_event_delegate &&
4214 : IsPromiseHookProtectorIntact()) {
4215 : HandleScope scope(this);
4216 2785 : InvalidatePromiseHookProtector();
4217 : }
4218 8483 : promise_hook_or_async_event_delegate_ = promise_hook_or_async_event_delegate;
4219 : promise_hook_or_debug_is_active_or_async_event_delegate_ =
4220 8483 : promise_hook_or_debug_is_active_or_async_event_delegate;
4221 8483 : }
4222 :
4223 : namespace {
4224 :
4225 72 : MaybeHandle<JSPromise> NewRejectedPromise(Isolate* isolate,
4226 : v8::Local<v8::Context> api_context,
4227 : Handle<Object> exception) {
4228 : v8::Local<v8::Promise::Resolver> resolver;
4229 144 : ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
4230 : isolate, resolver, v8::Promise::Resolver::New(api_context),
4231 : MaybeHandle<JSPromise>());
4232 :
4233 144 : RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
4234 : isolate, resolver->Reject(api_context, v8::Utils::ToLocal(exception)),
4235 : MaybeHandle<JSPromise>());
4236 :
4237 72 : v8::Local<v8::Promise> promise = resolver->GetPromise();
4238 72 : return v8::Utils::OpenHandle(*promise);
4239 : }
4240 :
4241 : } // namespace
4242 :
4243 482 : MaybeHandle<JSPromise> Isolate::RunHostImportModuleDynamicallyCallback(
4244 : Handle<Script> referrer, Handle<Object> specifier) {
4245 : v8::Local<v8::Context> api_context =
4246 482 : v8::Utils::ToLocal(Handle<Context>(native_context()));
4247 :
4248 482 : if (host_import_module_dynamically_callback_ == nullptr) {
4249 : Handle<Object> exception =
4250 0 : factory()->NewError(error_function(), MessageTemplate::kUnsupported);
4251 0 : return NewRejectedPromise(this, api_context, exception);
4252 : }
4253 :
4254 : Handle<String> specifier_str;
4255 482 : MaybeHandle<String> maybe_specifier = Object::ToString(this, specifier);
4256 482 : if (!maybe_specifier.ToHandle(&specifier_str)) {
4257 : Handle<Object> exception(pending_exception(), this);
4258 : clear_pending_exception();
4259 :
4260 72 : return NewRejectedPromise(this, api_context, exception);
4261 : }
4262 : DCHECK(!has_pending_exception());
4263 :
4264 : v8::Local<v8::Promise> promise;
4265 820 : ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
4266 : this, promise,
4267 : host_import_module_dynamically_callback_(
4268 : api_context, v8::Utils::ScriptOrModuleToLocal(referrer),
4269 : v8::Utils::ToLocal(specifier_str)),
4270 : MaybeHandle<JSPromise>());
4271 410 : return v8::Utils::OpenHandle(*promise);
4272 : }
4273 :
4274 30797 : void Isolate::SetHostImportModuleDynamicallyCallback(
4275 : HostImportModuleDynamicallyCallback callback) {
4276 30797 : host_import_module_dynamically_callback_ = callback;
4277 30797 : }
4278 :
4279 39 : Handle<JSObject> Isolate::RunHostInitializeImportMetaObjectCallback(
4280 : Handle<Module> module) {
4281 : Handle<Object> host_meta(module->import_meta(), this);
4282 39 : if (host_meta->IsTheHole(this)) {
4283 23 : host_meta = factory()->NewJSObjectWithNullProto();
4284 23 : if (host_initialize_import_meta_object_callback_ != nullptr) {
4285 : v8::Local<v8::Context> api_context =
4286 23 : v8::Utils::ToLocal(Handle<Context>(native_context()));
4287 23 : host_initialize_import_meta_object_callback_(
4288 : api_context, Utils::ToLocal(module),
4289 23 : v8::Local<v8::Object>::Cast(v8::Utils::ToLocal(host_meta)));
4290 : }
4291 23 : module->set_import_meta(*host_meta);
4292 : }
4293 39 : return Handle<JSObject>::cast(host_meta);
4294 : }
4295 :
4296 30797 : void Isolate::SetHostInitializeImportMetaObjectCallback(
4297 : HostInitializeImportMetaObjectCallback callback) {
4298 30797 : host_initialize_import_meta_object_callback_ = callback;
4299 30797 : }
4300 :
4301 12 : MaybeHandle<Object> Isolate::RunPrepareStackTraceCallback(
4302 : Handle<Context> context, Handle<JSObject> error, Handle<JSArray> sites) {
4303 12 : v8::Local<v8::Context> api_context = Utils::ToLocal(context);
4304 :
4305 : v8::Local<v8::Value> stack;
4306 42 : ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
4307 : this, stack,
4308 : prepare_stack_trace_callback_(api_context, Utils::ToLocal(error),
4309 : Utils::ToLocal(sites)),
4310 : MaybeHandle<Object>());
4311 6 : return Utils::OpenHandle(*stack);
4312 : }
4313 :
4314 859504 : int Isolate::LookupOrAddExternallyCompiledFilename(const char* filename) {
4315 859504 : if (embedded_file_writer_ != nullptr) {
4316 : return embedded_file_writer_->LookupOrAddExternallyCompiledFilename(
4317 15214 : filename);
4318 : }
4319 : return 0;
4320 : }
4321 :
4322 0 : const char* Isolate::GetExternallyCompiledFilename(int index) const {
4323 0 : if (embedded_file_writer_ != nullptr) {
4324 0 : return embedded_file_writer_->GetExternallyCompiledFilename(index);
4325 : }
4326 : return "";
4327 : }
4328 :
4329 0 : int Isolate::GetExternallyCompiledFilenameCount() const {
4330 0 : if (embedded_file_writer_ != nullptr) {
4331 0 : return embedded_file_writer_->GetExternallyCompiledFilenameCount();
4332 : }
4333 : return 0;
4334 : }
4335 :
4336 0 : void Isolate::PrepareBuiltinSourcePositionMap() {
4337 56 : if (embedded_file_writer_ != nullptr) {
4338 : return embedded_file_writer_->PrepareBuiltinSourcePositionMap(
4339 2 : this->builtins());
4340 : }
4341 : }
4342 :
4343 : #if defined(V8_OS_WIN_X64)
4344 : void Isolate::SetBuiltinUnwindData(
4345 : int builtin_index,
4346 : const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) {
4347 : if (embedded_file_writer_ != nullptr) {
4348 : embedded_file_writer_->SetBuiltinUnwindData(builtin_index, unwinding_info);
4349 : }
4350 : }
4351 : #endif
4352 :
4353 12 : void Isolate::SetPrepareStackTraceCallback(PrepareStackTraceCallback callback) {
4354 12 : prepare_stack_trace_callback_ = callback;
4355 12 : }
4356 :
4357 15311 : bool Isolate::HasPrepareStackTraceCallback() const {
4358 15311 : return prepare_stack_trace_callback_ != nullptr;
4359 : }
4360 :
4361 13 : void Isolate::SetAtomicsWaitCallback(v8::Isolate::AtomicsWaitCallback callback,
4362 : void* data) {
4363 13 : atomics_wait_callback_ = callback;
4364 13 : atomics_wait_callback_data_ = data;
4365 13 : }
4366 :
4367 1838 : void Isolate::RunAtomicsWaitCallback(v8::Isolate::AtomicsWaitEvent event,
4368 : Handle<JSArrayBuffer> array_buffer,
4369 : size_t offset_in_bytes, int64_t value,
4370 : double timeout_in_ms,
4371 : AtomicsWaitWakeHandle* stop_handle) {
4372 : DCHECK(array_buffer->is_shared());
4373 1838 : if (atomics_wait_callback_ == nullptr) return;
4374 : HandleScope handle_scope(this);
4375 169 : atomics_wait_callback_(
4376 : event, v8::Utils::ToLocalShared(array_buffer), offset_in_bytes, value,
4377 : timeout_in_ms,
4378 : reinterpret_cast<v8::Isolate::AtomicsWaitWakeHandle*>(stop_handle),
4379 169 : atomics_wait_callback_data_);
4380 : }
4381 :
4382 119 : void Isolate::SetPromiseHook(PromiseHook hook) {
4383 119 : promise_hook_ = hook;
4384 119 : PromiseHookStateUpdated();
4385 119 : }
4386 :
4387 99547 : void Isolate::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
4388 : Handle<Object> parent) {
4389 99547 : RunPromiseHookForAsyncEventDelegate(type, promise);
4390 99547 : if (promise_hook_ == nullptr) return;
4391 : promise_hook_(type, v8::Utils::PromiseToLocal(promise),
4392 1145 : v8::Utils::ToLocal(parent));
4393 : }
4394 :
4395 99547 : void Isolate::RunPromiseHookForAsyncEventDelegate(PromiseHookType type,
4396 : Handle<JSPromise> promise) {
4397 99547 : if (!async_event_delegate_) return;
4398 37191 : if (type == PromiseHookType::kResolve) return;
4399 :
4400 21848 : if (type == PromiseHookType::kBefore) {
4401 3655 : if (!promise->async_task_id()) return;
4402 6345 : async_event_delegate_->AsyncEventOccurred(debug::kDebugWillHandle,
4403 4230 : promise->async_task_id(), false);
4404 18193 : } else if (type == PromiseHookType::kAfter) {
4405 3650 : if (!promise->async_task_id()) return;
4406 6300 : async_event_delegate_->AsyncEventOccurred(debug::kDebugDidHandle,
4407 4200 : promise->async_task_id(), false);
4408 : } else {
4409 : DCHECK(type == PromiseHookType::kInit);
4410 : debug::DebugAsyncActionType type = debug::kDebugPromiseThen;
4411 : bool last_frame_was_promise_builtin = false;
4412 14543 : JavaScriptFrameIterator it(this);
4413 28701 : while (!it.done()) {
4414 : std::vector<Handle<SharedFunctionInfo>> infos;
4415 26526 : it.frame()->GetFunctions(&infos);
4416 54842 : for (size_t i = 1; i <= infos.size(); ++i) {
4417 53052 : Handle<SharedFunctionInfo> info = infos[infos.size() - i];
4418 26526 : if (info->IsUserJavaScript()) {
4419 : // We should not report PromiseThen and PromiseCatch which is called
4420 : // indirectly, e.g. Promise.all calls Promise.then internally.
4421 12368 : if (last_frame_was_promise_builtin) {
4422 1855 : if (!promise->async_task_id()) {
4423 3710 : promise->set_async_task_id(++async_task_count_);
4424 : }
4425 7420 : async_event_delegate_->AsyncEventOccurred(
4426 3710 : type, promise->async_task_id(), debug()->IsBlackboxed(info));
4427 : }
4428 : return;
4429 : }
4430 : last_frame_was_promise_builtin = false;
4431 14158 : if (info->HasBuiltinId()) {
4432 14158 : if (info->builtin_id() == Builtins::kPromisePrototypeThen) {
4433 : type = debug::kDebugPromiseThen;
4434 : last_frame_was_promise_builtin = true;
4435 10808 : } else if (info->builtin_id() == Builtins::kPromisePrototypeCatch) {
4436 : type = debug::kDebugPromiseCatch;
4437 : last_frame_was_promise_builtin = true;
4438 10508 : } else if (info->builtin_id() == Builtins::kPromisePrototypeFinally) {
4439 : type = debug::kDebugPromiseFinally;
4440 : last_frame_was_promise_builtin = true;
4441 : }
4442 : }
4443 : }
4444 14158 : it.Advance();
4445 : }
4446 : }
4447 : }
4448 :
4449 3692 : void Isolate::OnAsyncFunctionStateChanged(Handle<JSPromise> promise,
4450 : debug::DebugAsyncActionType event) {
4451 3692 : if (!async_event_delegate_) return;
4452 440 : if (!promise->async_task_id()) {
4453 370 : promise->set_async_task_id(++async_task_count_);
4454 : }
4455 1320 : async_event_delegate_->AsyncEventOccurred(event, promise->async_task_id(),
4456 880 : false);
4457 : }
4458 :
4459 1154 : void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
4460 1154 : promise_reject_callback_ = callback;
4461 1154 : }
4462 :
4463 15707 : void Isolate::ReportPromiseReject(Handle<JSPromise> promise,
4464 : Handle<Object> value,
4465 : v8::PromiseRejectEvent event) {
4466 15707 : if (promise_reject_callback_ == nullptr) return;
4467 490 : promise_reject_callback_(v8::PromiseRejectMessage(
4468 490 : v8::Utils::PromiseToLocal(promise), event, v8::Utils::ToLocal(value)));
4469 : }
4470 :
4471 60 : void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) {
4472 : DCHECK(!use_counter_callback_);
4473 60 : use_counter_callback_ = callback;
4474 60 : }
4475 :
4476 :
4477 2341742 : void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) {
4478 : // The counter callback may cause the embedder to call into V8, which is not
4479 : // generally possible during GC.
4480 2341742 : if (heap_.gc_state() == Heap::NOT_IN_GC) {
4481 2341742 : if (use_counter_callback_) {
4482 : HandleScope handle_scope(this);
4483 199 : use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature);
4484 : }
4485 : } else {
4486 0 : heap_.IncrementDeferredCount(feature);
4487 : }
4488 2341742 : }
4489 :
4490 : // static
4491 55 : std::string Isolate::GetTurboCfgFileName(Isolate* isolate) {
4492 55 : if (FLAG_trace_turbo_cfg_file == nullptr) {
4493 0 : std::ostringstream os;
4494 0 : os << "turbo-" << base::OS::GetCurrentProcessId() << "-";
4495 0 : if (isolate != nullptr) {
4496 0 : os << isolate->id();
4497 : } else {
4498 0 : os << "any";
4499 : }
4500 0 : os << ".cfg";
4501 : return os.str();
4502 : } else {
4503 55 : return FLAG_trace_turbo_cfg_file;
4504 : }
4505 : }
4506 :
4507 : // Heap::detached_contexts tracks detached contexts as pairs
4508 : // (number of GC since the context was detached, the context).
4509 126 : void Isolate::AddDetachedContext(Handle<Context> context) {
4510 : HandleScope scope(this);
4511 : Handle<WeakArrayList> detached_contexts = factory()->detached_contexts();
4512 : detached_contexts = WeakArrayList::AddToEnd(
4513 126 : this, detached_contexts, MaybeObjectHandle(Smi::kZero, this));
4514 : detached_contexts = WeakArrayList::AddToEnd(this, detached_contexts,
4515 126 : MaybeObjectHandle::Weak(context));
4516 : heap()->set_detached_contexts(*detached_contexts);
4517 126 : }
4518 :
4519 :
4520 68846 : void Isolate::CheckDetachedContextsAfterGC() {
4521 : HandleScope scope(this);
4522 : Handle<WeakArrayList> detached_contexts = factory()->detached_contexts();
4523 : int length = detached_contexts->length();
4524 68846 : if (length == 0) return;
4525 : int new_length = 0;
4526 655 : for (int i = 0; i < length; i += 2) {
4527 : int mark_sweeps = detached_contexts->Get(i).ToSmi().value();
4528 : MaybeObject context = detached_contexts->Get(i + 1);
4529 : DCHECK(context->IsWeakOrCleared());
4530 297 : if (!context->IsCleared()) {
4531 729 : detached_contexts->Set(
4532 243 : new_length, MaybeObject::FromSmi(Smi::FromInt(mark_sweeps + 1)));
4533 486 : detached_contexts->Set(new_length + 1, context);
4534 243 : new_length += 2;
4535 : }
4536 : }
4537 : detached_contexts->set_length(new_length);
4538 277 : while (new_length < length) {
4539 108 : detached_contexts->Set(new_length, MaybeObject::FromSmi(Smi::zero()));
4540 108 : ++new_length;
4541 : }
4542 :
4543 61 : if (FLAG_trace_detached_contexts) {
4544 0 : PrintF("%d detached contexts are collected out of %d\n",
4545 0 : length - new_length, length);
4546 0 : for (int i = 0; i < new_length; i += 2) {
4547 : int mark_sweeps = detached_contexts->Get(i).ToSmi().value();
4548 : MaybeObject context = detached_contexts->Get(i + 1);
4549 : DCHECK(context->IsWeakOrCleared());
4550 0 : if (mark_sweeps > 3) {
4551 0 : PrintF("detached context %p\n survived %d GCs (leak?)\n",
4552 0 : reinterpret_cast<void*>(context.ptr()), mark_sweeps);
4553 : }
4554 : }
4555 : }
4556 : }
4557 :
4558 0 : double Isolate::LoadStartTimeMs() {
4559 0 : base::MutexGuard guard(&rail_mutex_);
4560 0 : return load_start_time_ms_;
4561 : }
4562 :
4563 0 : void Isolate::SetRAILMode(RAILMode rail_mode) {
4564 : RAILMode old_rail_mode = rail_mode_.load();
4565 0 : if (old_rail_mode != PERFORMANCE_LOAD && rail_mode == PERFORMANCE_LOAD) {
4566 0 : base::MutexGuard guard(&rail_mutex_);
4567 0 : load_start_time_ms_ = heap()->MonotonicallyIncreasingTimeInMs();
4568 : }
4569 : rail_mode_.store(rail_mode);
4570 0 : if (old_rail_mode == PERFORMANCE_LOAD && rail_mode != PERFORMANCE_LOAD) {
4571 : heap()->incremental_marking()->incremental_marking_job()->ScheduleTask(
4572 0 : heap());
4573 : }
4574 0 : if (FLAG_trace_rail) {
4575 0 : PrintIsolate(this, "RAIL mode: %s\n", RAILModeName(rail_mode));
4576 : }
4577 0 : }
4578 :
4579 0 : void Isolate::IsolateInBackgroundNotification() {
4580 0 : is_isolate_in_background_ = true;
4581 0 : heap()->ActivateMemoryReducerIfNeeded();
4582 0 : }
4583 :
4584 0 : void Isolate::IsolateInForegroundNotification() {
4585 0 : is_isolate_in_background_ = false;
4586 0 : }
4587 :
4588 104 : void Isolate::PrintWithTimestamp(const char* format, ...) {
4589 104 : base::OS::Print("[%d:%p] %8.0f ms: ", base::OS::GetCurrentProcessId(),
4590 104 : static_cast<void*>(this), time_millis_since_init());
4591 : va_list arguments;
4592 104 : va_start(arguments, format);
4593 104 : base::OS::VPrint(format, arguments);
4594 104 : va_end(arguments);
4595 104 : }
4596 :
4597 10 : void Isolate::SetIdle(bool is_idle) {
4598 10 : if (!is_profiling()) return;
4599 : StateTag state = current_vm_state();
4600 : DCHECK(state == EXTERNAL || state == IDLE);
4601 10 : if (js_entry_sp() != kNullAddress) return;
4602 10 : if (is_idle) {
4603 : set_current_vm_state(IDLE);
4604 5 : } else if (state == IDLE) {
4605 : set_current_vm_state(EXTERNAL);
4606 : }
4607 : }
4608 :
4609 : #ifdef V8_INTL_SUPPORT
4610 64958 : icu::UObject* Isolate::get_cached_icu_object(ICUObjectCacheType cache_type) {
4611 64958 : return icu_object_cache_[cache_type].get();
4612 : }
4613 :
4614 149 : void Isolate::set_icu_object_in_cache(ICUObjectCacheType cache_type,
4615 : std::shared_ptr<icu::UObject> obj) {
4616 : icu_object_cache_[cache_type] = obj;
4617 149 : }
4618 :
4619 0 : void Isolate::clear_cached_icu_object(ICUObjectCacheType cache_type) {
4620 : icu_object_cache_.erase(cache_type);
4621 0 : }
4622 : #endif // V8_INTL_SUPPORT
4623 :
4624 2580007 : bool StackLimitCheck::JsHasOverflowed(uintptr_t gap) const {
4625 2580007 : StackGuard* stack_guard = isolate_->stack_guard();
4626 : #ifdef USE_SIMULATOR
4627 : // The simulator uses a separate JS stack.
4628 : Address jssp_address = Simulator::current(isolate_)->get_sp();
4629 : uintptr_t jssp = static_cast<uintptr_t>(jssp_address);
4630 : if (jssp - gap < stack_guard->real_jslimit()) return true;
4631 : #endif // USE_SIMULATOR
4632 2580007 : return GetCurrentStackPosition() - gap < stack_guard->real_climit();
4633 : }
4634 :
4635 20603103 : SaveContext::SaveContext(Isolate* isolate) : isolate_(isolate) {
4636 20603103 : if (!isolate->context().is_null()) {
4637 20395964 : context_ = Handle<Context>(isolate->context(), isolate);
4638 : }
4639 :
4640 20603103 : c_entry_fp_ = isolate->c_entry_fp(isolate->thread_local_top());
4641 20603103 : }
4642 :
4643 41206260 : SaveContext::~SaveContext() {
4644 41206260 : isolate_->set_context(context_.is_null() ? Context() : *context_);
4645 20603130 : }
4646 :
4647 0 : bool SaveContext::IsBelowFrame(StandardFrame* frame) {
4648 0 : return (c_entry_fp_ == 0) || (c_entry_fp_ > frame->sp());
4649 : }
4650 :
4651 382005 : SaveAndSwitchContext::SaveAndSwitchContext(Isolate* isolate,
4652 : Context new_context)
4653 382005 : : SaveContext(isolate) {
4654 : isolate->set_context(new_context);
4655 382005 : }
4656 :
4657 : #ifdef DEBUG
4658 : AssertNoContextChange::AssertNoContextChange(Isolate* isolate)
4659 : : isolate_(isolate), context_(isolate->context(), isolate) {}
4660 : #endif // DEBUG
4661 :
4662 76634 : bool InterruptsScope::Intercept(StackGuard::InterruptFlag flag) {
4663 : InterruptsScope* last_postpone_scope = nullptr;
4664 230258 : for (InterruptsScope* current = this; current; current = current->prev_) {
4665 : // We only consider scopes related to passed flag.
4666 77013 : if (!(current->intercept_mask_ & flag)) continue;
4667 76350 : if (current->mode_ == kRunInterrupts) {
4668 : // If innermost scope is kRunInterrupts scope, prevent interrupt from
4669 : // being intercepted.
4670 : break;
4671 : } else {
4672 : DCHECK_EQ(current->mode_, kPostponeInterrupts);
4673 : last_postpone_scope = current;
4674 : }
4675 : }
4676 : // If there is no postpone scope for passed flag then we should not intercept.
4677 76634 : if (!last_postpone_scope) return false;
4678 75911 : last_postpone_scope->intercepted_flags_ |= flag;
4679 75911 : return true;
4680 : }
4681 :
4682 : #undef TRACE_ISOLATE
4683 :
4684 : } // namespace internal
4685 122036 : } // namespace v8
|