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