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