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 <fstream> // NOLINT(readability/streams)
10 : #include <sstream>
11 :
12 : #include "src/api.h"
13 : #include "src/assembler-inl.h"
14 : #include "src/ast/ast-value-factory.h"
15 : #include "src/ast/context-slot-cache.h"
16 : #include "src/base/adapters.h"
17 : #include "src/base/hashmap.h"
18 : #include "src/base/platform/platform.h"
19 : #include "src/base/sys-info.h"
20 : #include "src/base/utils/random-number-generator.h"
21 : #include "src/basic-block-profiler.h"
22 : #include "src/bootstrapper.h"
23 : #include "src/cancelable-task.h"
24 : #include "src/code-stubs.h"
25 : #include "src/compilation-cache.h"
26 : #include "src/compilation-statistics.h"
27 : #include "src/compiler-dispatcher/compiler-dispatcher.h"
28 : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
29 : #include "src/debug/debug.h"
30 : #include "src/deoptimizer.h"
31 : #include "src/elements.h"
32 : #include "src/external-reference-table.h"
33 : #include "src/frames-inl.h"
34 : #include "src/ic/access-compiler-data.h"
35 : #include "src/ic/stub-cache.h"
36 : #include "src/interface-descriptors.h"
37 : #include "src/interpreter/interpreter.h"
38 : #include "src/isolate-inl.h"
39 : #include "src/libsampler/sampler.h"
40 : #include "src/log.h"
41 : #include "src/messages.h"
42 : #include "src/objects/frame-array-inl.h"
43 : #include "src/profiler/cpu-profiler.h"
44 : #include "src/prototype.h"
45 : #include "src/regexp/regexp-stack.h"
46 : #include "src/runtime-profiler.h"
47 : #include "src/setup-isolate.h"
48 : #include "src/simulator.h"
49 : #include "src/snapshot/startup-deserializer.h"
50 : #include "src/tracing/tracing-category-observer.h"
51 : #include "src/unicode-cache.h"
52 : #include "src/v8.h"
53 : #include "src/version.h"
54 : #include "src/visitors.h"
55 : #include "src/vm-state-inl.h"
56 : #include "src/wasm/compilation-manager.h"
57 : #include "src/wasm/wasm-objects.h"
58 : #include "src/zone/accounting-allocator.h"
59 :
60 : namespace v8 {
61 : namespace internal {
62 :
63 : base::Atomic32 ThreadId::highest_thread_id_ = 0;
64 :
65 0 : int ThreadId::AllocateThreadId() {
66 : int new_id = base::Relaxed_AtomicIncrement(&highest_thread_id_, 1);
67 : return new_id;
68 : }
69 :
70 :
71 3698536 : int ThreadId::GetCurrentThreadId() {
72 3698536 : int thread_id = base::Thread::GetThreadLocalInt(Isolate::thread_id_key_);
73 3698577 : if (thread_id == 0) {
74 : thread_id = AllocateThreadId();
75 65147 : base::Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
76 : }
77 3698575 : return thread_id;
78 : }
79 :
80 :
81 54999 : ThreadLocalTop::ThreadLocalTop() {
82 54999 : InitializeInternal();
83 54999 : }
84 :
85 :
86 134160 : void ThreadLocalTop::InitializeInternal() {
87 134160 : c_entry_fp_ = 0;
88 134160 : c_function_ = 0;
89 134160 : handler_ = 0;
90 : #ifdef USE_SIMULATOR
91 : simulator_ = nullptr;
92 : #endif
93 134160 : js_entry_sp_ = nullptr;
94 134160 : external_callback_scope_ = nullptr;
95 134160 : current_vm_state_ = EXTERNAL;
96 134160 : try_catch_handler_ = nullptr;
97 134160 : context_ = nullptr;
98 134160 : thread_id_ = ThreadId::Invalid();
99 134160 : external_caught_exception_ = false;
100 134160 : failed_access_check_callback_ = nullptr;
101 134160 : save_context_ = nullptr;
102 134160 : promise_on_stack_ = nullptr;
103 :
104 : // These members are re-initialized later after deserialization
105 : // is complete.
106 134160 : pending_exception_ = nullptr;
107 134160 : wasm_caught_exception_ = nullptr;
108 134160 : rethrowing_message_ = false;
109 134160 : pending_message_obj_ = nullptr;
110 134160 : scheduled_exception_ = nullptr;
111 134160 : }
112 :
113 :
114 79161 : void ThreadLocalTop::Initialize() {
115 79161 : InitializeInternal();
116 : #ifdef USE_SIMULATOR
117 : simulator_ = Simulator::current(isolate_);
118 : #endif
119 79161 : thread_id_ = ThreadId::Current();
120 79162 : }
121 :
122 :
123 5856 : void ThreadLocalTop::Free() {
124 59221 : wasm_caught_exception_ = nullptr;
125 : // Match unmatched PopPromise calls.
126 5874 : while (promise_on_stack_) isolate_->PopPromise();
127 5856 : }
128 :
129 :
130 : base::Thread::LocalStorageKey Isolate::isolate_key_;
131 : base::Thread::LocalStorageKey Isolate::thread_id_key_;
132 : base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
133 : base::LazyMutex Isolate::thread_data_table_mutex_ = LAZY_MUTEX_INITIALIZER;
134 : Isolate::ThreadDataTable* Isolate::thread_data_table_ = nullptr;
135 : base::Atomic32 Isolate::isolate_counter_ = 0;
136 : #if DEBUG
137 : base::Atomic32 Isolate::isolate_key_created_ = 0;
138 : #endif
139 :
140 : Isolate::PerIsolateThreadData*
141 276462 : Isolate::FindOrAllocatePerThreadDataForThisThread() {
142 276462 : ThreadId thread_id = ThreadId::Current();
143 : PerIsolateThreadData* per_thread = nullptr;
144 : {
145 : base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
146 276471 : per_thread = thread_data_table_->Lookup(this, thread_id);
147 276471 : if (per_thread == nullptr) {
148 60505 : per_thread = new PerIsolateThreadData(this, thread_id);
149 60505 : thread_data_table_->Insert(per_thread);
150 : }
151 : DCHECK(thread_data_table_->Lookup(this, thread_id) == per_thread);
152 : }
153 276471 : return per_thread;
154 : }
155 :
156 :
157 1500 : void Isolate::DiscardPerThreadDataForThisThread() {
158 1500 : int thread_id_int = base::Thread::GetThreadLocalInt(Isolate::thread_id_key_);
159 1499 : if (thread_id_int) {
160 : ThreadId thread_id = ThreadId(thread_id_int);
161 : DCHECK(!thread_manager_->mutex_owner_.Equals(thread_id));
162 : base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
163 : PerIsolateThreadData* per_thread =
164 1000 : thread_data_table_->Lookup(this, thread_id);
165 1000 : if (per_thread) {
166 : DCHECK(!per_thread->thread_state_);
167 500 : thread_data_table_->Remove(per_thread);
168 : }
169 : }
170 1499 : }
171 :
172 :
173 32005 : Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
174 32005 : ThreadId thread_id = ThreadId::Current();
175 32005 : return FindPerThreadDataForThread(thread_id);
176 : }
177 :
178 :
179 32005 : Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread(
180 : ThreadId thread_id) {
181 : PerIsolateThreadData* per_thread = nullptr;
182 : {
183 : base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
184 32005 : per_thread = thread_data_table_->Lookup(this, thread_id);
185 : }
186 32005 : return per_thread;
187 : }
188 :
189 :
190 53977 : void Isolate::InitializeOncePerProcess() {
191 : base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
192 53977 : CHECK_NULL(thread_data_table_);
193 53977 : isolate_key_ = base::Thread::CreateThreadLocalKey();
194 : #if DEBUG
195 : base::Relaxed_Store(&isolate_key_created_, 1);
196 : #endif
197 53977 : thread_id_key_ = base::Thread::CreateThreadLocalKey();
198 53977 : per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey();
199 107954 : thread_data_table_ = new Isolate::ThreadDataTable();
200 53977 : }
201 :
202 858674 : Address Isolate::get_address_from_id(IsolateAddressId id) {
203 858674 : return isolate_addresses_[id];
204 : }
205 :
206 5994 : char* Isolate::Iterate(RootVisitor* v, char* thread_storage) {
207 : ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
208 5994 : Iterate(v, thread);
209 5994 : return thread_storage + sizeof(ThreadLocalTop);
210 : }
211 :
212 :
213 92526 : void Isolate::IterateThread(ThreadVisitor* v, char* t) {
214 : ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
215 92526 : v->VisitThread(this, thread);
216 92526 : }
217 :
218 476834 : void Isolate::Iterate(RootVisitor* v, ThreadLocalTop* thread) {
219 : // Visit the roots from the top for a given thread.
220 238417 : v->VisitRootPointer(Root::kTop, &thread->pending_exception_);
221 238417 : v->VisitRootPointer(Root::kTop, &thread->wasm_caught_exception_);
222 238417 : v->VisitRootPointer(Root::kTop, &thread->pending_message_obj_);
223 238417 : v->VisitRootPointer(Root::kTop, bit_cast<Object**>(&(thread->context_)));
224 238417 : v->VisitRootPointer(Root::kTop, &thread->scheduled_exception_);
225 :
226 376778 : for (v8::TryCatch* block = thread->try_catch_handler(); block != nullptr;
227 : block = block->next_) {
228 138361 : v->VisitRootPointer(Root::kTop, bit_cast<Object**>(&(block->exception_)));
229 138361 : v->VisitRootPointer(Root::kTop, bit_cast<Object**>(&(block->message_obj_)));
230 : }
231 :
232 : // Iterate over pointers on native execution stack.
233 3102053 : for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
234 2863636 : it.frame()->Iterate(v);
235 : }
236 238417 : }
237 :
238 232423 : void Isolate::Iterate(RootVisitor* v) {
239 232423 : ThreadLocalTop* current_t = thread_local_top();
240 232423 : Iterate(v, current_t);
241 232423 : }
242 :
243 232423 : void Isolate::IterateDeferredHandles(RootVisitor* visitor) {
244 234772 : for (DeferredHandles* deferred = deferred_handles_head_; deferred != nullptr;
245 : deferred = deferred->next_) {
246 2349 : deferred->Iterate(visitor);
247 : }
248 232423 : }
249 :
250 :
251 : #ifdef DEBUG
252 : bool Isolate::IsDeferredHandle(Object** handle) {
253 : // Each DeferredHandles instance keeps the handles to one job in the
254 : // concurrent recompilation queue, containing a list of blocks. Each block
255 : // contains kHandleBlockSize handles except for the first block, which may
256 : // not be fully filled.
257 : // We iterate through all the blocks to see whether the argument handle
258 : // belongs to one of the blocks. If so, it is deferred.
259 : for (DeferredHandles* deferred = deferred_handles_head_; deferred != nullptr;
260 : deferred = deferred->next_) {
261 : std::vector<Object**>* blocks = &deferred->blocks_;
262 : for (size_t i = 0; i < blocks->size(); i++) {
263 : Object** block_limit = (i == 0) ? deferred->first_block_limit_
264 : : blocks->at(i) + kHandleBlockSize;
265 : if (blocks->at(i) <= handle && handle < block_limit) return true;
266 : }
267 : }
268 : return false;
269 : }
270 : #endif // DEBUG
271 :
272 :
273 16796015 : void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
274 : thread_local_top()->set_try_catch_handler(that);
275 16796015 : }
276 :
277 :
278 16796058 : void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
279 : DCHECK(thread_local_top()->try_catch_handler() == that);
280 16796058 : thread_local_top()->set_try_catch_handler(that->next_);
281 16796058 : }
282 :
283 :
284 0 : Handle<String> Isolate::StackTraceString() {
285 0 : if (stack_trace_nesting_level_ == 0) {
286 0 : stack_trace_nesting_level_++;
287 : HeapStringAllocator allocator;
288 0 : StringStream::ClearMentionedObjectCache(this);
289 : StringStream accumulator(&allocator);
290 0 : incomplete_message_ = &accumulator;
291 0 : PrintStack(&accumulator);
292 0 : Handle<String> stack_trace = accumulator.ToString(this);
293 0 : incomplete_message_ = nullptr;
294 0 : stack_trace_nesting_level_ = 0;
295 0 : return stack_trace;
296 0 : } else if (stack_trace_nesting_level_ == 1) {
297 0 : stack_trace_nesting_level_++;
298 : base::OS::PrintError(
299 0 : "\n\nAttempt to print stack while printing stack (double fault)\n");
300 : base::OS::PrintError(
301 0 : "If you are lucky you may find a partial stack dump on stdout.\n\n");
302 0 : incomplete_message_->OutputToStdOut();
303 : return factory()->empty_string();
304 : } else {
305 0 : base::OS::Abort();
306 : // Unreachable
307 : return factory()->empty_string();
308 : }
309 : }
310 :
311 0 : void Isolate::PushStackTraceAndDie(unsigned int magic1, void* ptr1, void* ptr2,
312 : unsigned int magic2) {
313 : PushStackTraceAndDie(magic1, ptr1, ptr2, nullptr, nullptr, nullptr, nullptr,
314 0 : nullptr, nullptr, magic2);
315 : }
316 :
317 0 : void Isolate::PushStackTraceAndDie(unsigned int magic1, void* ptr1, void* ptr2,
318 : void* ptr3, void* ptr4, void* ptr5,
319 : void* ptr6, void* ptr7, void* ptr8,
320 : unsigned int magic2) {
321 : const int kMaxStackTraceSize = 32 * KB;
322 0 : Handle<String> trace = StackTraceString();
323 : uint8_t buffer[kMaxStackTraceSize];
324 : int length = Min(kMaxStackTraceSize - 1, trace->length());
325 0 : String::WriteToFlat(*trace, buffer, 0, length);
326 0 : buffer[length] = '\0';
327 : // TODO(dcarney): convert buffer to utf8?
328 : base::OS::PrintError(
329 : "Stacktrace:"
330 : "\n magic1=%x magic2=%x ptr1=%p ptr2=%p ptr3=%p ptr4=%p ptr5=%p "
331 : "ptr6=%p ptr7=%p ptr8=%p\n\n%s",
332 : magic1, magic2, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, ptr7, ptr8,
333 0 : reinterpret_cast<char*>(buffer));
334 : PushCodeObjectsAndDie(0xdeadc0de, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, ptr7,
335 0 : ptr8, 0xdeadc0de);
336 : }
337 :
338 0 : void Isolate::PushCodeObjectsAndDie(unsigned int magic1, void* ptr1, void* ptr2,
339 : void* ptr3, void* ptr4, void* ptr5,
340 : void* ptr6, void* ptr7, void* ptr8,
341 : unsigned int magic2) {
342 : const int kMaxCodeObjects = 16;
343 : // Mark as volatile to lower the probability of optimizing code_objects
344 : // away. The first and last entries are set to the magic markers, making it
345 : // easier to spot the array on the stack.
346 : void* volatile code_objects[kMaxCodeObjects + 2];
347 0 : code_objects[0] = reinterpret_cast<void*>(magic1);
348 0 : code_objects[kMaxCodeObjects + 1] = reinterpret_cast<void*>(magic2);
349 0 : StackFrameIterator it(this);
350 : int numCodeObjects = 0;
351 0 : for (; !it.done() && numCodeObjects < kMaxCodeObjects; it.Advance()) {
352 0 : code_objects[1 + numCodeObjects++] = it.frame()->unchecked_code();
353 : }
354 :
355 : // Keep the top raw code object pointers on the stack in the hope that the
356 : // corresponding pages end up more frequently in the minidump.
357 : base::OS::PrintError(
358 : "\nCodeObjects (%p length=%i): 1:%p 2:%p 3:%p 4:%p..."
359 : "\n magic1=%x magic2=%x ptr1=%p ptr2=%p ptr3=%p ptr4=%p ptr5=%p "
360 : "ptr6=%p ptr7=%p ptr8=%p\n\n",
361 0 : static_cast<void*>(code_objects[0]), numCodeObjects,
362 0 : static_cast<void*>(code_objects[1]), static_cast<void*>(code_objects[2]),
363 0 : static_cast<void*>(code_objects[3]), static_cast<void*>(code_objects[4]),
364 0 : magic1, magic2, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, ptr7, ptr8);
365 0 : base::OS::Abort();
366 : }
367 :
368 : namespace {
369 :
370 : class FrameArrayBuilder {
371 : public:
372 1059983 : FrameArrayBuilder(Isolate* isolate, FrameSkipMode mode, int limit,
373 : Handle<Object> caller)
374 1059983 : : isolate_(isolate), mode_(mode), limit_(limit), caller_(caller) {
375 1059983 : switch (mode_) {
376 : case SKIP_FIRST:
377 : skip_next_frame_ = true;
378 : break;
379 : case SKIP_UNTIL_SEEN:
380 : DCHECK(caller_->IsJSFunction());
381 : skip_next_frame_ = true;
382 : break;
383 : case SKIP_NONE:
384 1045482 : skip_next_frame_ = false;
385 1045482 : break;
386 : }
387 :
388 1059983 : elements_ = isolate->factory()->NewFrameArray(Min(limit, 10));
389 1059983 : }
390 :
391 4482094 : void AppendStandardFrame(StandardFrame* frame) {
392 : std::vector<FrameSummary> frames;
393 4482094 : frames.reserve(FLAG_max_inlining_levels + 1);
394 4482094 : frame->Summarize(&frames);
395 : // A standard frame may include many summarized frames (due to inlining).
396 17968750 : for (size_t i = frames.size(); i != 0 && !full(); i--) {
397 4522468 : const auto& summ = frames[i - 1];
398 4522468 : if (summ.IsJavaScript()) {
399 : //====================================================================
400 : // Handle a JavaScript frame.
401 : //====================================================================
402 4331466 : const auto& summary = summ.AsJavaScript();
403 :
404 : // Filter out internal frames that we do not want to show.
405 4477384 : if (!IsVisibleInStackTrace(summary.function())) continue;
406 :
407 : Handle<AbstractCode> abstract_code = summary.abstract_code();
408 : const int offset = summary.code_offset();
409 :
410 : bool is_constructor = summary.is_constructor();
411 : // Help CallSite::IsConstructor correctly detect hand-written
412 : // construct stubs.
413 4475301 : if (abstract_code->IsCode() &&
414 : Code::cast(*abstract_code)->is_construct_stub()) {
415 : is_constructor = true;
416 : }
417 :
418 : int flags = 0;
419 : Handle<JSFunction> function = summary.function();
420 4331466 : if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
421 4331466 : if (is_constructor) flags |= FrameArray::kIsConstructor;
422 :
423 : elements_ = FrameArray::AppendJSFrame(
424 : elements_, TheHoleToUndefined(isolate_, summary.receiver()),
425 4331466 : function, abstract_code, offset, flags);
426 45084 : } else if (summ.IsWasmCompiled()) {
427 : //====================================================================
428 : // Handle a WASM compiled frame.
429 : //====================================================================
430 87518 : const auto& summary = summ.AsWasmCompiled();
431 : Handle<WasmInstanceObject> instance = summary.wasm_instance();
432 : int flags = 0;
433 43759 : if (instance->compiled_module()->is_asm_js()) {
434 : flags |= FrameArray::kIsAsmJsWasmFrame;
435 490 : if (WasmCompiledFrame::cast(frame)->at_to_number_conversion()) {
436 : flags |= FrameArray::kAsmJsAtNumberConversion;
437 : }
438 : } else {
439 : flags |= FrameArray::kIsWasmFrame;
440 : }
441 :
442 : elements_ = FrameArray::AppendWasmFrame(
443 43759 : elements_, instance, summary.function_index(),
444 : Handle<AbstractCode>::cast(summary.code()), summary.code_offset(),
445 43759 : flags);
446 1325 : } else if (summ.IsWasmInterpreted()) {
447 : //====================================================================
448 : // Handle a WASM interpreted frame.
449 : //====================================================================
450 1325 : const auto& summary = summ.AsWasmInterpreted();
451 1325 : Handle<WasmInstanceObject> instance = summary.wasm_instance();
452 : int flags = FrameArray::kIsWasmInterpretedFrame;
453 : DCHECK(!instance->compiled_module()->is_asm_js());
454 : elements_ = FrameArray::AppendWasmFrame(
455 : elements_, instance, summary.function_index(),
456 1325 : Handle<AbstractCode>::null(), summary.byte_offset(), flags);
457 : }
458 4482094 : }
459 4482094 : }
460 :
461 68416 : void AppendBuiltinExitFrame(BuiltinExitFrame* exit_frame) {
462 68416 : Handle<JSFunction> function = handle(exit_frame->function(), isolate_);
463 :
464 : // Filter out internal frames that we do not want to show.
465 99397 : if (!IsVisibleInStackTrace(function)) return;
466 :
467 37435 : Handle<Object> receiver(exit_frame->receiver(), isolate_);
468 37435 : Handle<Code> code(exit_frame->LookupCode(), isolate_);
469 : const int offset =
470 74870 : static_cast<int>(exit_frame->pc() - code->instruction_start());
471 :
472 : int flags = 0;
473 37435 : if (IsStrictFrame(function)) flags |= FrameArray::kIsStrict;
474 37435 : if (exit_frame->IsConstructor()) flags |= FrameArray::kIsConstructor;
475 :
476 : elements_ = FrameArray::AppendJSFrame(elements_, receiver, function,
477 : Handle<AbstractCode>::cast(code),
478 37435 : offset, flags);
479 : }
480 :
481 25739290 : bool full() { return elements_->FrameCount() >= limit_; }
482 :
483 : Handle<FrameArray> GetElements() {
484 1059983 : elements_->ShrinkToFit();
485 1059983 : return elements_;
486 : }
487 :
488 : private:
489 : // Poison stack frames below the first strict mode frame.
490 : // The stack trace API should not expose receivers and function
491 : // objects on frames deeper than the top-most one with a strict mode
492 : // function.
493 : bool IsStrictFrame(Handle<JSFunction> function) {
494 4368901 : if (!encountered_strict_function_) {
495 : encountered_strict_function_ =
496 3178171 : is_strict(function->shared()->language_mode());
497 : }
498 4368901 : return encountered_strict_function_;
499 : }
500 :
501 : // Determines whether the given stack frame should be displayed in a stack
502 : // trace.
503 8972497 : bool IsVisibleInStackTrace(Handle<JSFunction> function) {
504 8972497 : return ShouldIncludeFrame(function) && IsNotHidden(function) &&
505 4545800 : IsInSameSecurityContext(function);
506 : }
507 :
508 : // This mechanism excludes a number of uninteresting frames from the stack
509 : // trace. This can be be the first frame (which will be a builtin-exit frame
510 : // for the error constructor builtin) or every frame until encountering a
511 : // user-specified function.
512 4545800 : bool ShouldIncludeFrame(Handle<JSFunction> function) {
513 4545800 : switch (mode_) {
514 : case SKIP_NONE:
515 : return true;
516 : case SKIP_FIRST:
517 2882 : if (!skip_next_frame_) return true;
518 648 : skip_next_frame_ = false;
519 648 : return false;
520 : case SKIP_UNTIL_SEEN:
521 120577 : if (skip_next_frame_ && (*function == *caller_)) {
522 13591 : skip_next_frame_ = false;
523 13591 : return false;
524 : }
525 89939 : return !skip_next_frame_;
526 : }
527 0 : UNREACHABLE();
528 : }
529 :
530 4528105 : bool IsNotHidden(Handle<JSFunction> function) {
531 : // Functions defined not in user scripts are not visible unless directly
532 : // exposed, in which case the native flag is set.
533 : // The --builtins-in-stack-traces command line flag allows including
534 : // internal call sites in the stack trace for debugging purposes.
535 9055960 : if (!FLAG_builtins_in_stack_traces &&
536 4527855 : !function->shared()->IsUserJavaScript()) {
537 : return function->shared()->native();
538 : }
539 : return true;
540 : }
541 :
542 : bool IsInSameSecurityContext(Handle<JSFunction> function) {
543 4426697 : return isolate_->context()->HasSameSecurityTokenAs(function->context());
544 : }
545 :
546 : // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the
547 : // receiver in RegExp constructor frames.
548 4331466 : Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) {
549 : return (in->IsTheHole(isolate))
550 : ? Handle<Object>::cast(isolate->factory()->undefined_value())
551 8661747 : : in;
552 : }
553 :
554 : Isolate* isolate_;
555 : const FrameSkipMode mode_;
556 : int limit_;
557 : const Handle<Object> caller_;
558 : bool skip_next_frame_ = true;
559 : bool encountered_strict_function_ = false;
560 : Handle<FrameArray> elements_;
561 : };
562 :
563 1067267 : bool GetStackTraceLimit(Isolate* isolate, int* result) {
564 1067267 : Handle<JSObject> error = isolate->error_function();
565 :
566 : Handle<String> key = isolate->factory()->stackTraceLimit_string();
567 1067267 : Handle<Object> stack_trace_limit = JSReceiver::GetDataProperty(error, key);
568 1067267 : if (!stack_trace_limit->IsNumber()) return false;
569 :
570 : // Ensure that limit is not negative.
571 1059983 : *result = Max(FastD2IChecked(stack_trace_limit->Number()), 0);
572 1059983 : return true;
573 : }
574 :
575 303405 : bool NoExtension(const v8::FunctionCallbackInfo<v8::Value>&) { return false; }
576 : } // namespace
577 :
578 1067267 : Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
579 : FrameSkipMode mode,
580 : Handle<Object> caller) {
581 1067267 : DisallowJavascriptExecution no_js(this);
582 :
583 : int limit;
584 1074551 : if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value();
585 :
586 1059983 : FrameArrayBuilder builder(this, mode, limit, caller);
587 :
588 10238065 : for (StackFrameIterator iter(this); !iter.done() && !builder.full();
589 8118099 : iter.Advance()) {
590 8118099 : StackFrame* frame = iter.frame();
591 :
592 8118099 : switch (frame->type()) {
593 : case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION:
594 : case StackFrame::OPTIMIZED:
595 : case StackFrame::INTERPRETED:
596 : case StackFrame::BUILTIN:
597 4437350 : builder.AppendStandardFrame(JavaScriptFrame::cast(frame));
598 4437350 : break;
599 : case StackFrame::BUILTIN_EXIT:
600 : // BuiltinExitFrames are not standard frames, so they do not have
601 : // Summarize(). However, they may have one JS frame worth showing.
602 68416 : builder.AppendBuiltinExitFrame(BuiltinExitFrame::cast(frame));
603 68416 : break;
604 : case StackFrame::WASM_COMPILED:
605 43759 : builder.AppendStandardFrame(WasmCompiledFrame::cast(frame));
606 43759 : break;
607 : case StackFrame::WASM_INTERPRETER_ENTRY:
608 985 : builder.AppendStandardFrame(WasmInterpreterEntryFrame::cast(frame));
609 985 : break;
610 :
611 : default:
612 : break;
613 : }
614 : }
615 :
616 : // TODO(yangguo): Queue this structured stack trace for preprocessing on GC.
617 1059983 : return factory()->NewJSArrayWithElements(builder.GetElements());
618 : }
619 :
620 995775 : MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace(
621 : Handle<JSReceiver> error_object) {
622 995775 : if (capture_stack_trace_for_uncaught_exceptions_) {
623 : // Capture stack trace for a detailed exception message.
624 : Handle<Name> key = factory()->detailed_stack_trace_symbol();
625 : Handle<FixedArray> stack_trace = CaptureCurrentStackTrace(
626 : stack_trace_for_uncaught_exceptions_frame_limit_,
627 257 : stack_trace_for_uncaught_exceptions_options_);
628 514 : RETURN_ON_EXCEPTION(this,
629 : JSReceiver::SetProperty(error_object, key, stack_trace,
630 : LanguageMode::kStrict),
631 : JSReceiver);
632 : }
633 995775 : return error_object;
634 : }
635 :
636 1067267 : MaybeHandle<JSReceiver> Isolate::CaptureAndSetSimpleStackTrace(
637 : Handle<JSReceiver> error_object, FrameSkipMode mode,
638 : Handle<Object> caller) {
639 : // Capture stack trace for simple stack trace string formatting.
640 : Handle<Name> key = factory()->stack_trace_symbol();
641 : Handle<Object> stack_trace =
642 1067267 : CaptureSimpleStackTrace(error_object, mode, caller);
643 2134534 : RETURN_ON_EXCEPTION(this,
644 : JSReceiver::SetProperty(error_object, key, stack_trace,
645 : LanguageMode::kStrict),
646 : JSReceiver);
647 1067267 : return error_object;
648 : }
649 :
650 475 : Handle<FixedArray> Isolate::GetDetailedStackTrace(
651 : Handle<JSObject> error_object) {
652 : Handle<Name> key_detailed = factory()->detailed_stack_trace_symbol();
653 : Handle<Object> stack_trace =
654 475 : JSReceiver::GetDataProperty(error_object, key_detailed);
655 475 : if (stack_trace->IsFixedArray()) return Handle<FixedArray>::cast(stack_trace);
656 96 : return Handle<FixedArray>();
657 : }
658 :
659 :
660 : class CaptureStackTraceHelper {
661 : public:
662 82805 : explicit CaptureStackTraceHelper(Isolate* isolate) : isolate_(isolate) {}
663 :
664 70514 : Handle<StackFrameInfo> NewStackFrameObject(FrameSummary& summ) {
665 70514 : if (summ.IsJavaScript()) return NewStackFrameObject(summ.AsJavaScript());
666 718 : if (summ.IsWasm()) return NewStackFrameObject(summ.AsWasm());
667 0 : UNREACHABLE();
668 : }
669 :
670 70155 : Handle<StackFrameInfo> NewStackFrameObject(
671 80125 : const FrameSummary::JavaScriptFrameSummary& summ) {
672 : int code_offset;
673 : Handle<ByteArray> source_position_table;
674 : Handle<Object> maybe_cache;
675 : Handle<UnseededNumberDictionary> cache;
676 70155 : if (!FLAG_optimize_for_size) {
677 : code_offset = summ.code_offset();
678 : source_position_table =
679 140310 : handle(summ.abstract_code()->source_position_table(), isolate_);
680 140310 : maybe_cache = handle(summ.abstract_code()->stack_frame_cache(), isolate_);
681 70155 : if (maybe_cache->IsUnseededNumberDictionary()) {
682 : cache = Handle<UnseededNumberDictionary>::cast(maybe_cache);
683 : } else {
684 6871 : cache = UnseededNumberDictionary::New(isolate_, 1);
685 : }
686 70155 : int entry = cache->FindEntry(code_offset);
687 70155 : if (entry != UnseededNumberDictionary::kNotFound) {
688 : Handle<StackFrameInfo> frame(
689 60205 : StackFrameInfo::cast(cache->ValueAt(entry)));
690 : DCHECK(frame->function_name()->IsString());
691 60205 : Handle<String> function_name = summ.FunctionName();
692 60205 : if (function_name->Equals(String::cast(frame->function_name()))) {
693 60185 : return frame;
694 : }
695 : }
696 : }
697 :
698 9970 : Handle<StackFrameInfo> frame = factory()->NewStackFrameInfo();
699 9970 : Handle<Script> script = Handle<Script>::cast(summ.script());
700 : Script::PositionInfo info;
701 : bool valid_pos = Script::GetPositionInfo(script, summ.SourcePosition(),
702 9970 : &info, Script::WITH_OFFSET);
703 9970 : if (valid_pos) {
704 9970 : frame->set_line_number(info.line + 1);
705 9970 : frame->set_column_number(info.column + 1);
706 : }
707 : frame->set_script_id(script->id());
708 9970 : frame->set_script_name(script->name());
709 19940 : frame->set_script_name_or_source_url(script->GetNameOrSourceURL());
710 : frame->set_is_eval(script->compilation_type() ==
711 19940 : Script::COMPILATION_TYPE_EVAL);
712 9970 : Handle<String> function_name = summ.FunctionName();
713 9970 : frame->set_function_name(*function_name);
714 19940 : frame->set_is_constructor(summ.is_constructor());
715 9970 : frame->set_is_wasm(false);
716 9970 : if (!FLAG_optimize_for_size) {
717 9970 : auto new_cache = UnseededNumberDictionary::Set(cache, code_offset, frame);
718 19379 : if (*new_cache != *cache || !maybe_cache->IsUnseededNumberDictionary()) {
719 7432 : AbstractCode::SetStackFrameCache(summ.abstract_code(), new_cache);
720 : }
721 : }
722 : frame->set_id(next_id());
723 9970 : return frame;
724 : }
725 :
726 359 : Handle<StackFrameInfo> NewStackFrameObject(
727 : const FrameSummary::WasmFrameSummary& summ) {
728 359 : Handle<StackFrameInfo> info = factory()->NewStackFrameInfo();
729 :
730 : Handle<WasmCompiledModule> compiled_module(
731 359 : summ.wasm_instance()->compiled_module(), isolate_);
732 : Handle<String> name = WasmCompiledModule::GetFunctionName(
733 359 : isolate_, compiled_module, summ.function_index());
734 359 : info->set_function_name(*name);
735 : // Encode the function index as line number (1-based).
736 359 : info->set_line_number(summ.function_index() + 1);
737 : // Encode the byte offset as column (1-based).
738 359 : int position = summ.byte_offset();
739 : // Make position 1-based.
740 359 : if (position >= 0) ++position;
741 : info->set_column_number(position);
742 718 : info->set_script_id(summ.script()->id());
743 359 : info->set_is_wasm(true);
744 : info->set_id(next_id());
745 359 : return info;
746 : }
747 :
748 : private:
749 10329 : inline Factory* factory() { return isolate_->factory(); }
750 :
751 : int next_id() const {
752 10329 : int id = isolate_->last_stack_frame_info_id() + 1;
753 : isolate_->set_last_stack_frame_info_id(id);
754 : return id;
755 : }
756 :
757 : Isolate* isolate_;
758 : };
759 :
760 82805 : Handle<FixedArray> Isolate::CaptureCurrentStackTrace(
761 10825 : int frame_limit, StackTrace::StackTraceOptions options) {
762 82805 : DisallowJavascriptExecution no_js(this);
763 : CaptureStackTraceHelper helper(this);
764 :
765 : // Ensure no negative values.
766 : int limit = Max(frame_limit, 0);
767 82805 : Handle<FixedArray> stack_trace_elems = factory()->NewFixedArray(limit);
768 :
769 : int frames_seen = 0;
770 246114 : for (StackTraceFrameIterator it(this); !it.done() && (frames_seen < limit);
771 80504 : it.Advance()) {
772 : StandardFrame* frame = it.frame();
773 : // Set initial size to the maximum inlining level + 1 for the outermost
774 : // function.
775 : std::vector<FrameSummary> frames;
776 80504 : frames.reserve(FLAG_max_inlining_levels + 1);
777 80504 : frame->Summarize(&frames);
778 322016 : for (size_t i = frames.size(); i != 0 && frames_seen < limit; i--) {
779 80504 : FrameSummary& frame = frames[i - 1];
780 90494 : if (!frame.is_subject_to_debugging()) continue;
781 : // Filter frames from other security contexts.
782 241512 : if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) &&
783 112979 : !this->context()->HasSameSecurityTokenAs(*frame.native_context()))
784 : continue;
785 70514 : Handle<StackFrameInfo> new_frame_obj = helper.NewStackFrameObject(frame);
786 70514 : stack_trace_elems->set(frames_seen, *new_frame_obj);
787 70514 : frames_seen++;
788 : }
789 80504 : }
790 82805 : stack_trace_elems->Shrink(frames_seen);
791 82805 : return stack_trace_elems;
792 : }
793 :
794 :
795 10 : void Isolate::PrintStack(FILE* out, PrintStackMode mode) {
796 10 : if (stack_trace_nesting_level_ == 0) {
797 10 : stack_trace_nesting_level_++;
798 10 : StringStream::ClearMentionedObjectCache(this);
799 : HeapStringAllocator allocator;
800 : StringStream accumulator(&allocator);
801 10 : incomplete_message_ = &accumulator;
802 10 : PrintStack(&accumulator, mode);
803 10 : accumulator.OutputToFile(out);
804 10 : InitializeLoggingAndCounters();
805 10 : accumulator.Log(this);
806 10 : incomplete_message_ = nullptr;
807 10 : stack_trace_nesting_level_ = 0;
808 0 : } else if (stack_trace_nesting_level_ == 1) {
809 0 : stack_trace_nesting_level_++;
810 : base::OS::PrintError(
811 0 : "\n\nAttempt to print stack while printing stack (double fault)\n");
812 : base::OS::PrintError(
813 0 : "If you are lucky you may find a partial stack dump on stdout.\n\n");
814 0 : incomplete_message_->OutputToFile(out);
815 : }
816 10 : }
817 :
818 :
819 10 : static void PrintFrames(Isolate* isolate,
820 : StringStream* accumulator,
821 : StackFrame::PrintMode mode) {
822 10 : StackFrameIterator it(isolate);
823 50 : for (int i = 0; !it.done(); it.Advance()) {
824 40 : it.frame()->Print(accumulator, mode, i++);
825 : }
826 10 : }
827 :
828 28 : void Isolate::PrintStack(StringStream* accumulator, PrintStackMode mode) {
829 : // The MentionedObjectCache is not GC-proof at the moment.
830 : DisallowHeapAllocation no_gc;
831 : HandleScope scope(this);
832 : DCHECK(accumulator->IsMentionedObjectCacheClear(this));
833 :
834 : // Avoid printing anything if there are no frames.
835 56 : if (c_entry_fp(thread_local_top()) == 0) return;
836 :
837 : accumulator->Add(
838 10 : "\n==== JS stack trace =========================================\n\n");
839 10 : PrintFrames(this, accumulator, StackFrame::OVERVIEW);
840 10 : if (mode == kPrintStackVerbose) {
841 : accumulator->Add(
842 0 : "\n==== Details ================================================\n\n");
843 0 : PrintFrames(this, accumulator, StackFrame::DETAILS);
844 0 : accumulator->PrintMentionedObjectCache(this);
845 : }
846 10 : accumulator->Add("=====================\n\n");
847 : }
848 :
849 :
850 27 : void Isolate::SetFailedAccessCheckCallback(
851 : v8::FailedAccessCheckCallback callback) {
852 27 : thread_local_top()->failed_access_check_callback_ = callback;
853 27 : }
854 :
855 :
856 1898 : void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver) {
857 1898 : if (!thread_local_top()->failed_access_check_callback_) {
858 5223 : return ScheduleThrow(*factory()->NewTypeError(MessageTemplate::kNoAccess));
859 : }
860 :
861 : DCHECK(receiver->IsAccessCheckNeeded());
862 : DCHECK(context());
863 :
864 : // Get the data object from access check info.
865 : HandleScope scope(this);
866 : Handle<Object> data;
867 : { DisallowHeapAllocation no_gc;
868 157 : AccessCheckInfo* access_check_info = AccessCheckInfo::Get(this, receiver);
869 157 : if (!access_check_info) {
870 : AllowHeapAllocation doesnt_matter_anymore;
871 : return ScheduleThrow(
872 0 : *factory()->NewTypeError(MessageTemplate::kNoAccess));
873 : }
874 : data = handle(access_check_info->data(), this);
875 : }
876 :
877 : // Leaving JavaScript.
878 314 : VMState<EXTERNAL> state(this);
879 : thread_local_top()->failed_access_check_callback_(
880 157 : v8::Utils::ToLocal(receiver), v8::ACCESS_HAS, v8::Utils::ToLocal(data));
881 : }
882 :
883 :
884 5815411 : bool Isolate::MayAccess(Handle<Context> accessing_context,
885 5817950 : Handle<JSObject> receiver) {
886 : DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
887 :
888 : // Check for compatibility between the security tokens in the
889 : // current lexical context and the accessed object.
890 :
891 : // During bootstrapping, callback functions are not enabled yet.
892 5815411 : if (bootstrapper()->IsActive()) return true;
893 : {
894 : DisallowHeapAllocation no_gc;
895 :
896 5815183 : if (receiver->IsJSGlobalProxy()) {
897 : Object* receiver_context =
898 : JSGlobalProxy::cast(*receiver)->native_context();
899 5813302 : if (!receiver_context->IsContext()) return false;
900 :
901 : // Get the native context of current top context.
902 : // avoid using Isolate::native_context() because it uses Handle.
903 : Context* native_context =
904 5813117 : accessing_context->global_object()->native_context();
905 5813117 : if (receiver_context == native_context) return true;
906 :
907 3688 : if (Context::cast(receiver_context)->security_token() ==
908 : native_context->security_token())
909 : return true;
910 : }
911 : }
912 :
913 : HandleScope scope(this);
914 : Handle<Object> data;
915 : v8::AccessCheckCallback callback = nullptr;
916 : { DisallowHeapAllocation no_gc;
917 4439 : AccessCheckInfo* access_check_info = AccessCheckInfo::Get(this, receiver);
918 4439 : if (!access_check_info) return false;
919 : Object* fun_obj = access_check_info->callback();
920 : callback = v8::ToCData<v8::AccessCheckCallback>(fun_obj);
921 : data = handle(access_check_info->data(), this);
922 : }
923 :
924 2539 : LOG(this, ApiSecurityCheck());
925 :
926 : {
927 : // Leaving JavaScript.
928 2539 : VMState<EXTERNAL> state(this);
929 : return callback(v8::Utils::ToLocal(accessing_context),
930 2539 : v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(data));
931 : }
932 : }
933 :
934 :
935 71492 : Object* Isolate::StackOverflow() {
936 71492 : if (FLAG_abort_on_stack_or_string_length_overflow) {
937 0 : FATAL("Aborting on stack overflow");
938 : }
939 :
940 71492 : DisallowJavascriptExecution no_js(this);
941 : HandleScope scope(this);
942 :
943 71492 : Handle<JSFunction> fun = range_error_function();
944 : Handle<Object> msg = factory()->NewStringFromAsciiChecked(
945 71492 : MessageTemplate::TemplateString(MessageTemplate::kStackOverflow));
946 : Handle<Object> no_caller;
947 : Handle<Object> exception;
948 142984 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
949 : this, exception,
950 : ErrorUtils::Construct(this, fun, fun, msg, SKIP_NONE, no_caller, true));
951 :
952 71492 : Throw(*exception, nullptr);
953 :
954 : #ifdef VERIFY_HEAP
955 : if (FLAG_verify_heap && FLAG_stress_compaction) {
956 : heap()->CollectAllGarbage(Heap::kNoGCFlags,
957 : GarbageCollectionReason::kTesting);
958 : }
959 : #endif // VERIFY_HEAP
960 :
961 142984 : return heap()->exception();
962 : }
963 :
964 :
965 4301 : Object* Isolate::TerminateExecution() {
966 4301 : return Throw(heap_.termination_exception(), nullptr);
967 : }
968 :
969 :
970 6410 : void Isolate::CancelTerminateExecution() {
971 3211 : if (try_catch_handler()) {
972 730 : try_catch_handler()->has_terminated_ = false;
973 : }
974 6410 : if (has_pending_exception() &&
975 3205 : pending_exception() == heap_.termination_exception()) {
976 3199 : thread_local_top()->external_caught_exception_ = false;
977 : clear_pending_exception();
978 : }
979 3217 : if (has_scheduled_exception() &&
980 : scheduled_exception() == heap_.termination_exception()) {
981 6 : thread_local_top()->external_caught_exception_ = false;
982 : clear_scheduled_exception();
983 : }
984 3211 : }
985 :
986 :
987 123 : void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
988 : ExecutionAccess access(this);
989 123 : api_interrupts_queue_.push(InterruptEntry(callback, data));
990 123 : stack_guard()->RequestApiInterrupt();
991 123 : }
992 :
993 :
994 78 : void Isolate::InvokeApiInterruptCallbacks() {
995 : RuntimeCallTimerScope runtimeTimer(
996 78 : this, &RuntimeCallStats::InvokeApiInterruptCallbacks);
997 : // Note: callback below should be called outside of execution access lock.
998 : while (true) {
999 : InterruptEntry entry;
1000 : {
1001 : ExecutionAccess access(this);
1002 279 : if (api_interrupts_queue_.empty()) return;
1003 : entry = api_interrupts_queue_.front();
1004 : api_interrupts_queue_.pop();
1005 : }
1006 123 : VMState<EXTERNAL> state(this);
1007 : HandleScope handle_scope(this);
1008 123 : entry.first(reinterpret_cast<v8::Isolate*>(this), entry.second);
1009 123 : }
1010 : }
1011 :
1012 :
1013 1150 : void ReportBootstrappingException(Handle<Object> exception,
1014 1150 : MessageLocation* location) {
1015 1150 : base::OS::PrintError("Exception thrown during bootstrapping\n");
1016 2300 : if (location == nullptr || location->script().is_null()) return;
1017 : // We are bootstrapping and caught an error where the location is set
1018 : // and we have a script for the location.
1019 : // In this case we could have an extension (or an internal error
1020 : // somewhere) and we print out the line number at which the error occurred
1021 : // to the console for easier debugging.
1022 : int line_number =
1023 1150 : location->script()->GetLineNumber(location->start_pos()) + 1;
1024 1180 : if (exception->IsString() && location->script()->name()->IsString()) {
1025 : base::OS::PrintError(
1026 : "Extension or internal compilation error: %s in %s at line %d.\n",
1027 : String::cast(*exception)->ToCString().get(),
1028 : String::cast(location->script()->name())->ToCString().get(),
1029 150 : line_number);
1030 1120 : } else if (location->script()->name()->IsString()) {
1031 : base::OS::PrintError(
1032 : "Extension or internal compilation error in %s at line %d.\n",
1033 : String::cast(location->script()->name())->ToCString().get(),
1034 3360 : line_number);
1035 0 : } else if (exception->IsString()) {
1036 : base::OS::PrintError("Extension or internal compilation error: %s.\n",
1037 0 : String::cast(*exception)->ToCString().get());
1038 : } else {
1039 0 : base::OS::PrintError("Extension or internal compilation error.\n");
1040 : }
1041 : #ifdef OBJECT_PRINT
1042 : // Since comments and empty lines have been stripped from the source of
1043 : // builtins, print the actual source here so that line numbers match.
1044 : if (location->script()->source()->IsString()) {
1045 : Handle<String> src(String::cast(location->script()->source()));
1046 : PrintF("Failing script:");
1047 : int len = src->length();
1048 : if (len == 0) {
1049 : PrintF(" <not available>\n");
1050 : } else {
1051 : PrintF("\n");
1052 : int line_number = 1;
1053 : PrintF("%5d: ", line_number);
1054 : for (int i = 0; i < len; i++) {
1055 : uint16_t character = src->Get(i);
1056 : PrintF("%c", character);
1057 : if (character == '\n' && i < len - 2) {
1058 : PrintF("%5d: ", ++line_number);
1059 : }
1060 : }
1061 : PrintF("\n");
1062 : }
1063 : }
1064 : #endif
1065 : }
1066 :
1067 280 : bool Isolate::is_catchable_by_wasm(Object* exception) {
1068 560 : if (!is_catchable_by_javascript(exception) || !exception->IsJSError())
1069 : return false;
1070 : HandleScope scope(this);
1071 : Handle<Object> exception_handle(exception, this);
1072 : return JSReceiver::HasProperty(Handle<JSReceiver>::cast(exception_handle),
1073 : factory()->InternalizeUtf8String(
1074 560 : wasm::WasmException::kRuntimeIdStr))
1075 280 : .IsJust();
1076 : }
1077 :
1078 3638102 : Object* Isolate::Throw(Object* exception, MessageLocation* location) {
1079 : DCHECK(!has_pending_exception());
1080 :
1081 : HandleScope scope(this);
1082 : Handle<Object> exception_handle(exception, this);
1083 :
1084 1229925 : if (FLAG_print_all_exceptions) {
1085 : printf("=========================================================\n");
1086 : printf("Exception thrown:\n");
1087 0 : if (location) {
1088 : Handle<Script> script = location->script();
1089 0 : Handle<Object> name(script->GetNameOrSourceURL(), this);
1090 : printf("at ");
1091 0 : if (name->IsString() && String::cast(*name)->length() > 0)
1092 0 : String::cast(*name)->PrintOn(stdout);
1093 : else
1094 : printf("<anonymous>");
1095 : // Script::GetLineNumber and Script::GetColumnNumber can allocate on the heap to
1096 : // initialize the line_ends array, so be careful when calling them.
1097 : #ifdef DEBUG
1098 : if (AllowHeapAllocation::IsAllowed()) {
1099 : #else
1100 : if (false) {
1101 : #endif
1102 : printf(", %d:%d - %d:%d\n",
1103 : Script::GetLineNumber(script, location->start_pos()) + 1,
1104 : Script::GetColumnNumber(script, location->start_pos()),
1105 : Script::GetLineNumber(script, location->end_pos()) + 1,
1106 : Script::GetColumnNumber(script, location->end_pos()));
1107 : } else {
1108 0 : printf(", line %d\n", script->GetLineNumber(location->start_pos()) + 1);
1109 : }
1110 : }
1111 : exception->Print();
1112 : printf("Stack Trace:\n");
1113 0 : PrintStack(stdout);
1114 : printf("=========================================================\n");
1115 : }
1116 :
1117 : // Determine whether a message needs to be created for the given exception
1118 : // depending on the following criteria:
1119 : // 1) External v8::TryCatch missing: Always create a message because any
1120 : // JavaScript handler for a finally-block might re-throw to top-level.
1121 : // 2) External v8::TryCatch exists: Only create a message if the handler
1122 : // captures messages or is verbose (which reports despite the catch).
1123 : // 3) ReThrow from v8::TryCatch: The message from a previous throw still
1124 : // exists and we preserve it instead of creating a new message.
1125 1011674 : bool requires_message = try_catch_handler() == nullptr ||
1126 1283208 : try_catch_handler()->is_verbose_ ||
1127 : try_catch_handler()->capture_message_;
1128 1229925 : bool rethrowing_message = thread_local_top()->rethrowing_message_;
1129 :
1130 1229925 : thread_local_top()->rethrowing_message_ = false;
1131 :
1132 : // Notify debugger of exception.
1133 1229925 : if (is_catchable_by_javascript(exception)) {
1134 1225624 : debug()->OnThrow(exception_handle);
1135 : }
1136 :
1137 : // Generate the message if required.
1138 1229925 : if (requires_message && !rethrowing_message) {
1139 1182553 : MessageLocation computed_location;
1140 : // If no location was specified we try to use a computed one instead.
1141 1182553 : if (location == nullptr && ComputeLocation(&computed_location)) {
1142 : location = &computed_location;
1143 : }
1144 :
1145 1182553 : if (bootstrapper()->IsActive()) {
1146 : // It's not safe to try to make message objects or collect stack traces
1147 : // while the bootstrapper is active since the infrastructure may not have
1148 : // been properly initialized.
1149 1150 : ReportBootstrappingException(exception_handle, location);
1150 : } else {
1151 1181403 : Handle<Object> message_obj = CreateMessage(exception_handle, location);
1152 1181403 : thread_local_top()->pending_message_obj_ = *message_obj;
1153 :
1154 : // For any exception not caught by JavaScript, even when an external
1155 : // handler is present:
1156 : // If the abort-on-uncaught-exception flag is specified, and if the
1157 : // embedder didn't specify a custom uncaught exception callback,
1158 : // or if the custom callback determined that V8 should abort, then
1159 : // abort.
1160 1181403 : if (FLAG_abort_on_uncaught_exception) {
1161 5 : CatchType prediction = PredictExceptionCatcher();
1162 15 : if ((prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) &&
1163 10 : (!abort_on_uncaught_exception_callback_ ||
1164 : abort_on_uncaught_exception_callback_(
1165 5 : reinterpret_cast<v8::Isolate*>(this)))) {
1166 : // Prevent endless recursion.
1167 0 : FLAG_abort_on_uncaught_exception = false;
1168 : // This flag is intended for use by JavaScript developers, so
1169 : // print a user-friendly stack trace (not an internal one).
1170 : PrintF(stderr, "%s\n\nFROM\n",
1171 0 : MessageHandler::GetLocalizedMessage(this, message_obj).get());
1172 0 : PrintCurrentStackTrace(stderr);
1173 0 : base::OS::Abort();
1174 : }
1175 : }
1176 : }
1177 : }
1178 :
1179 : // Set the exception being thrown.
1180 : set_pending_exception(*exception_handle);
1181 2459850 : return heap()->exception();
1182 : }
1183 :
1184 :
1185 23288 : Object* Isolate::ReThrow(Object* exception) {
1186 : DCHECK(!has_pending_exception());
1187 :
1188 : // Set the exception being re-thrown.
1189 : set_pending_exception(exception);
1190 50892 : return heap()->exception();
1191 : }
1192 :
1193 :
1194 1083701 : Object* Isolate::UnwindAndFindHandler() {
1195 1083701 : Object* exception = pending_exception();
1196 :
1197 : auto FoundHandler = [&](Context* context, Code* code, intptr_t offset,
1198 : Address handler_sp, Address handler_fp) {
1199 : // Store information to be consumed by the CEntryStub.
1200 1083701 : thread_local_top()->pending_handler_context_ = context;
1201 1083701 : thread_local_top()->pending_handler_code_ = code;
1202 1083701 : thread_local_top()->pending_handler_offset_ = offset;
1203 1083701 : thread_local_top()->pending_handler_fp_ = handler_fp;
1204 1083701 : thread_local_top()->pending_handler_sp_ = handler_sp;
1205 :
1206 : // Return and clear pending exception.
1207 : clear_pending_exception();
1208 1083541 : return exception;
1209 : };
1210 :
1211 : // Special handling of termination exceptions, uncatchable by JavaScript and
1212 : // Wasm code, we unwind the handlers until the top ENTRY handler is found.
1213 : bool catchable_by_js = is_catchable_by_javascript(exception);
1214 :
1215 : // Compute handler and stack unwinding information by performing a full walk
1216 : // over the stack and dispatching according to the frame type.
1217 22705552 : for (StackFrameIterator iter(this);; iter.Advance()) {
1218 : // Handler must exist.
1219 : DCHECK(!iter.done());
1220 :
1221 27433285 : StackFrame* frame = iter.frame();
1222 :
1223 22705552 : switch (frame->type()) {
1224 : case StackFrame::ENTRY:
1225 : case StackFrame::CONSTRUCT_ENTRY: {
1226 : // For JSEntryStub frames we always have a handler.
1227 : StackHandler* handler = frame->top_handler();
1228 :
1229 : // Restore the next handler.
1230 61393 : thread_local_top()->handler_ = handler->next()->address();
1231 :
1232 : // Gather information from the handler.
1233 61393 : Code* code = frame->LookupCode();
1234 : return FoundHandler(
1235 : nullptr, code, Smi::ToInt(code->handler_table()->get(0)),
1236 184179 : handler->address() + StackHandlerConstants::kSize, 0);
1237 : }
1238 :
1239 : case StackFrame::WASM_COMPILED: {
1240 2807288 : if (trap_handler::IsThreadInWasm()) {
1241 : trap_handler::ClearThreadInWasm();
1242 : }
1243 :
1244 2807288 : if (!FLAG_experimental_wasm_eh || !is_catchable_by_wasm(exception)) {
1245 : break;
1246 : }
1247 280 : int stack_slots = 0; // Will contain stack slot count of frame.
1248 : WasmCompiledFrame* wasm_frame = static_cast<WasmCompiledFrame*>(frame);
1249 280 : int offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots);
1250 280 : if (offset < 0) break;
1251 : // Compute the stack pointer from the frame pointer. This ensures that
1252 : // argument slots on the stack are dropped as returning would.
1253 : Address return_sp = frame->fp() +
1254 : StandardFrameConstants::kFixedFrameSizeAboveFp -
1255 160 : stack_slots * kPointerSize;
1256 :
1257 : // This is going to be handled by Wasm, so we need to set the TLS flag
1258 : // again.
1259 : trap_handler::SetThreadInWasm();
1260 :
1261 160 : set_wasm_caught_exception(exception);
1262 : return FoundHandler(nullptr, frame->LookupCode(), offset, return_sp,
1263 320 : frame->fp());
1264 : }
1265 :
1266 : case StackFrame::OPTIMIZED: {
1267 : // For optimized frames we perform a lookup in the handler table.
1268 2851800 : if (!catchable_by_js) break;
1269 : OptimizedFrame* js_frame = static_cast<OptimizedFrame*>(frame);
1270 2851008 : int stack_slots = 0; // Will contain stack slot count of frame.
1271 : int offset =
1272 2851008 : js_frame->LookupExceptionHandlerInTable(&stack_slots, nullptr);
1273 2851008 : if (offset < 0) break;
1274 : // Compute the stack pointer from the frame pointer. This ensures
1275 : // that argument slots on the stack are dropped as returning would.
1276 : Address return_sp = frame->fp() +
1277 : StandardFrameConstants::kFixedFrameSizeAboveFp -
1278 230231 : stack_slots * kPointerSize;
1279 :
1280 : // Gather information from the frame.
1281 230231 : Code* code = frame->LookupCode();
1282 :
1283 : // TODO(bmeurer): Turbofanned BUILTIN frames appear as OPTIMIZED,
1284 : // but do not have a code kind of OPTIMIZED_FUNCTION.
1285 407508 : if (code->kind() == Code::OPTIMIZED_FUNCTION &&
1286 : code->marked_for_deoptimization()) {
1287 : // If the target code is lazy deoptimized, we jump to the original
1288 : // return address, but we make a note that we are throwing, so
1289 : // that the deoptimizer can do the right thing.
1290 3129 : offset = static_cast<int>(frame->pc() - code->entry());
1291 : set_deoptimizer_lazy_throw(true);
1292 : }
1293 :
1294 460462 : return FoundHandler(nullptr, code, offset, return_sp, frame->fp());
1295 : }
1296 :
1297 : case StackFrame::STUB: {
1298 : // Some stubs are able to handle exceptions.
1299 695993 : if (!catchable_by_js) break;
1300 : StubFrame* stub_frame = static_cast<StubFrame*>(frame);
1301 695402 : Code* code = stub_frame->LookupCode();
1302 1461398 : if (!code->IsCode() || code->kind() != Code::BUILTIN ||
1303 695457 : !code->handler_table()->length() || !code->is_turbofanned()) {
1304 : break;
1305 : }
1306 :
1307 55 : int stack_slots = 0; // Will contain stack slot count of frame.
1308 55 : int offset = stub_frame->LookupExceptionHandlerInTable(&stack_slots);
1309 55 : if (offset < 0) break;
1310 :
1311 : // Compute the stack pointer from the frame pointer. This ensures
1312 : // that argument slots on the stack are dropped as returning would.
1313 : Address return_sp = frame->fp() +
1314 : StandardFrameConstants::kFixedFrameSizeAboveFp -
1315 55 : stack_slots * kPointerSize;
1316 :
1317 110 : return FoundHandler(nullptr, code, offset, return_sp, frame->fp());
1318 : }
1319 :
1320 : case StackFrame::INTERPRETED: {
1321 : // For interpreted frame we perform a range lookup in the handler table.
1322 14250258 : if (!catchable_by_js) break;
1323 : InterpretedFrame* js_frame = static_cast<InterpretedFrame*>(frame);
1324 : int register_slots = InterpreterFrameConstants::RegisterStackSlotCount(
1325 28495690 : js_frame->GetBytecodeArray()->register_count());
1326 14247845 : int context_reg = 0; // Will contain register index holding context.
1327 : int offset =
1328 14247845 : js_frame->LookupExceptionHandlerInTable(&context_reg, nullptr);
1329 14247845 : if (offset < 0) break;
1330 : // Compute the stack pointer from the frame pointer. This ensures that
1331 : // argument slots on the stack are dropped as returning would.
1332 : // Note: This is only needed for interpreted frames that have been
1333 : // materialized by the deoptimizer. If there is a handler frame
1334 : // in between then {frame->sp()} would already be correct.
1335 : Address return_sp = frame->fp() -
1336 : InterpreterFrameConstants::kFixedFrameSizeFromFp -
1337 791862 : register_slots * kPointerSize;
1338 :
1339 : // Patch the bytecode offset in the interpreted frame to reflect the
1340 : // position of the exception handler. The special builtin below will
1341 : // take care of continuing to dispatch at that position. Also restore
1342 : // the correct context for the handler from the interpreter register.
1343 : Context* context =
1344 791862 : Context::cast(js_frame->ReadInterpreterRegister(context_reg));
1345 791862 : js_frame->PatchBytecodeOffset(static_cast<int>(offset));
1346 :
1347 : Code* code =
1348 : builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
1349 791862 : return FoundHandler(context, code, 0, return_sp, frame->fp());
1350 : }
1351 :
1352 : case StackFrame::BUILTIN:
1353 : // For builtin frames we are guaranteed not to find a handler.
1354 0 : if (catchable_by_js) {
1355 0 : CHECK_EQ(-1,
1356 : JavaScriptFrame::cast(frame)->LookupExceptionHandlerInTable(
1357 : nullptr, nullptr));
1358 : }
1359 : break;
1360 :
1361 : case StackFrame::WASM_INTERPRETER_ENTRY: {
1362 210 : if (trap_handler::IsThreadInWasm()) {
1363 : trap_handler::ClearThreadInWasm();
1364 : }
1365 : WasmInterpreterEntryFrame* interpreter_frame =
1366 : WasmInterpreterEntryFrame::cast(frame);
1367 : // TODO(wasm): Implement try-catch in the interpreter.
1368 420 : interpreter_frame->wasm_instance()->debug_info()->Unwind(frame->fp());
1369 210 : } break;
1370 :
1371 : default:
1372 : // All other types can not handle exception.
1373 : break;
1374 : }
1375 :
1376 21621851 : if (frame->is_optimized()) {
1377 : // Remove per-frame stored materialized objects.
1378 2621569 : bool removed = materialized_object_store_->Remove(frame->fp());
1379 : USE(removed);
1380 : // If there were any materialized objects, the code should be
1381 : // marked for deopt.
1382 : DCHECK_IMPLIES(removed, frame->LookupCode()->marked_for_deoptimization());
1383 : }
1384 : }
1385 :
1386 : UNREACHABLE();
1387 : }
1388 :
1389 : namespace {
1390 318291 : HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) {
1391 : HandlerTable::CatchPrediction prediction;
1392 636582 : if (frame->is_optimized()) {
1393 54672 : if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) {
1394 : // This optimized frame will catch. It's handler table does not include
1395 : // exception prediction, and we need to use the corresponding handler
1396 : // tables on the unoptimized code objects.
1397 : std::vector<FrameSummary> summaries;
1398 2282 : frame->Summarize(&summaries);
1399 6962 : for (size_t i = summaries.size(); i != 0; i--) {
1400 2289 : const FrameSummary& summary = summaries[i - 1];
1401 : Handle<AbstractCode> code = summary.AsJavaScript().abstract_code();
1402 3766 : if (code->IsCode() && code->kind() == AbstractCode::BUILTIN) {
1403 1477 : prediction = code->GetCode()->GetBuiltinCatchPrediction();
1404 1477 : if (prediction == HandlerTable::UNCAUGHT) continue;
1405 : return prediction;
1406 : }
1407 :
1408 : // Must have been constructed from a bytecode array.
1409 812 : CHECK_EQ(AbstractCode::INTERPRETED_FUNCTION, code->kind());
1410 812 : int code_offset = summary.code_offset();
1411 : BytecodeArray* bytecode = code->GetBytecodeArray();
1412 : HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
1413 812 : int index = table->LookupRange(code_offset, nullptr, &prediction);
1414 812 : if (index <= 0) continue;
1415 805 : if (prediction == HandlerTable::UNCAUGHT) continue;
1416 : return prediction;
1417 109 : }
1418 : }
1419 263619 : } else if (frame->LookupExceptionHandlerInTable(nullptr, &prediction) > 0) {
1420 6115 : return prediction;
1421 : }
1422 : return HandlerTable::UNCAUGHT;
1423 : }
1424 :
1425 162391 : Isolate::CatchType ToCatchType(HandlerTable::CatchPrediction prediction) {
1426 162391 : switch (prediction) {
1427 : case HandlerTable::UNCAUGHT:
1428 : return Isolate::NOT_CAUGHT;
1429 : case HandlerTable::CAUGHT:
1430 2241 : return Isolate::CAUGHT_BY_JAVASCRIPT;
1431 : case HandlerTable::PROMISE:
1432 1171 : return Isolate::CAUGHT_BY_PROMISE;
1433 : case HandlerTable::DESUGARING:
1434 0 : return Isolate::CAUGHT_BY_DESUGARING;
1435 : case HandlerTable::ASYNC_AWAIT:
1436 2069 : return Isolate::CAUGHT_BY_ASYNC_AWAIT;
1437 : default:
1438 0 : UNREACHABLE();
1439 : }
1440 : }
1441 : } // anonymous namespace
1442 :
1443 6055 : Isolate::CatchType Isolate::PredictExceptionCatcher() {
1444 : Address external_handler = thread_local_top()->try_catch_handler_address();
1445 6055 : if (IsExternalHandlerOnTop(nullptr)) return CAUGHT_BY_EXTERNAL;
1446 :
1447 : // Search for an exception handler by performing a full walk over the stack.
1448 175434 : for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) {
1449 508 : StackFrame* frame = iter.frame();
1450 :
1451 174998 : switch (frame->type()) {
1452 : case StackFrame::ENTRY:
1453 : case StackFrame::CONSTRUCT_ENTRY: {
1454 : Address entry_handler = frame->top_handler()->next()->address();
1455 : // The exception has been externally caught if and only if there is an
1456 : // external handler which is on top of the top-most JS_ENTRY handler.
1457 731 : if (external_handler != nullptr && !try_catch_handler()->is_verbose_) {
1458 88 : if (entry_handler == nullptr || entry_handler > external_handler) {
1459 : return CAUGHT_BY_EXTERNAL;
1460 : }
1461 : }
1462 : } break;
1463 :
1464 : // For JavaScript frames we perform a lookup in the handler table.
1465 : case StackFrame::OPTIMIZED:
1466 : case StackFrame::INTERPRETED:
1467 : case StackFrame::BUILTIN: {
1468 : JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
1469 162290 : Isolate::CatchType prediction = ToCatchType(PredictException(js_frame));
1470 162290 : if (prediction == NOT_CAUGHT) break;
1471 : return prediction;
1472 : } break;
1473 :
1474 : case StackFrame::STUB: {
1475 4557 : Handle<Code> code(frame->LookupCode());
1476 9243 : if (!code->IsCode() || code->kind() != Code::BUILTIN ||
1477 4658 : !code->handler_table()->length() || !code->is_turbofanned()) {
1478 : break;
1479 : }
1480 :
1481 101 : CatchType prediction = ToCatchType(code->GetBuiltinCatchPrediction());
1482 101 : if (prediction != NOT_CAUGHT) return prediction;
1483 : } break;
1484 :
1485 : default:
1486 : // All other types can not handle exception.
1487 : break;
1488 : }
1489 : }
1490 :
1491 : // Handler not found.
1492 436 : return NOT_CAUGHT;
1493 : }
1494 :
1495 70 : Object* Isolate::ThrowIllegalOperation() {
1496 70 : if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
1497 70 : return Throw(heap()->illegal_access_string());
1498 : }
1499 :
1500 :
1501 52222 : void Isolate::ScheduleThrow(Object* exception) {
1502 : // When scheduling a throw we first throw the exception to get the
1503 : // error reporting if it is uncaught before rescheduling it.
1504 26111 : Throw(exception);
1505 26111 : PropagatePendingExceptionToExternalTryCatch();
1506 26111 : if (has_pending_exception()) {
1507 26111 : thread_local_top()->scheduled_exception_ = pending_exception();
1508 26111 : thread_local_top()->external_caught_exception_ = false;
1509 : clear_pending_exception();
1510 : }
1511 26111 : }
1512 :
1513 :
1514 121 : void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) {
1515 : DCHECK(handler == try_catch_handler());
1516 : DCHECK(handler->HasCaught());
1517 : DCHECK(handler->rethrow_);
1518 : DCHECK(handler->capture_message_);
1519 121 : Object* message = reinterpret_cast<Object*>(handler->message_obj_);
1520 : DCHECK(message->IsJSMessageObject() || message->IsTheHole(this));
1521 121 : thread_local_top()->pending_message_obj_ = message;
1522 121 : }
1523 :
1524 :
1525 148 : void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) {
1526 : DCHECK(has_scheduled_exception());
1527 148 : if (scheduled_exception() == handler->exception_) {
1528 : DCHECK(scheduled_exception() != heap()->termination_exception());
1529 : clear_scheduled_exception();
1530 : }
1531 148 : if (thread_local_top_.pending_message_obj_ == handler->message_obj_) {
1532 : clear_pending_message();
1533 : }
1534 148 : }
1535 :
1536 :
1537 27786 : Object* Isolate::PromoteScheduledException() {
1538 : Object* thrown = scheduled_exception();
1539 : clear_scheduled_exception();
1540 : // Re-throw the exception to avoid getting repeated error reporting.
1541 27604 : return ReThrow(thrown);
1542 : }
1543 :
1544 :
1545 0 : void Isolate::PrintCurrentStackTrace(FILE* out) {
1546 0 : for (StackTraceFrameIterator it(this); !it.done(); it.Advance()) {
1547 0 : if (!it.is_javascript()) continue;
1548 :
1549 : HandleScope scope(this);
1550 : JavaScriptFrame* frame = it.javascript_frame();
1551 :
1552 0 : Handle<Object> receiver(frame->receiver(), this);
1553 0 : Handle<JSFunction> function(frame->function(), this);
1554 0 : Handle<AbstractCode> code(AbstractCode::cast(frame->LookupCode()), this);
1555 : const int offset =
1556 0 : static_cast<int>(frame->pc() - code->instruction_start());
1557 :
1558 0 : JSStackFrame site(this, receiver, function, code, offset);
1559 0 : Handle<String> line = site.ToString().ToHandleChecked();
1560 0 : if (line->length() > 0) {
1561 0 : line->PrintOn(out);
1562 0 : PrintF(out, "\n");
1563 : }
1564 : }
1565 0 : }
1566 :
1567 874883 : bool Isolate::ComputeLocation(MessageLocation* target) {
1568 874883 : StackTraceFrameIterator it(this);
1569 874883 : if (it.done()) return false;
1570 : StandardFrame* frame = it.frame();
1571 : // Compute the location from the function and the relocation info of the
1572 : // baseline code. For optimized code this will use the deoptimization
1573 : // information to get canonical location information.
1574 864172 : std::vector<FrameSummary> frames;
1575 864172 : frames.reserve(FLAG_max_inlining_levels + 1);
1576 864172 : frame->Summarize(&frames);
1577 864172 : FrameSummary& summary = frames.back();
1578 864172 : int pos = summary.SourcePosition();
1579 : Handle<SharedFunctionInfo> shared;
1580 864172 : Handle<Object> script = summary.script();
1581 1728304 : if (!script->IsScript() ||
1582 : (Script::cast(*script)->source()->IsUndefined(this))) {
1583 : return false;
1584 : }
1585 :
1586 864132 : if (summary.IsJavaScript()) {
1587 824312 : shared = handle(summary.AsJavaScript().function()->shared());
1588 : }
1589 864132 : *target = MessageLocation(Handle<Script>::cast(script), pos, pos + 1, shared);
1590 864132 : return true;
1591 : }
1592 :
1593 5614 : bool Isolate::ComputeLocationFromException(MessageLocation* target,
1594 : Handle<Object> exception) {
1595 5614 : if (!exception->IsJSObject()) return false;
1596 :
1597 : Handle<Name> start_pos_symbol = factory()->error_start_pos_symbol();
1598 : Handle<Object> start_pos = JSReceiver::GetDataProperty(
1599 2954 : Handle<JSObject>::cast(exception), start_pos_symbol);
1600 2954 : if (!start_pos->IsSmi()) return false;
1601 : int start_pos_value = Handle<Smi>::cast(start_pos)->value();
1602 :
1603 : Handle<Name> end_pos_symbol = factory()->error_end_pos_symbol();
1604 : Handle<Object> end_pos = JSReceiver::GetDataProperty(
1605 25 : Handle<JSObject>::cast(exception), end_pos_symbol);
1606 25 : if (!end_pos->IsSmi()) return false;
1607 : int end_pos_value = Handle<Smi>::cast(end_pos)->value();
1608 :
1609 : Handle<Name> script_symbol = factory()->error_script_symbol();
1610 : Handle<Object> script = JSReceiver::GetDataProperty(
1611 25 : Handle<JSObject>::cast(exception), script_symbol);
1612 25 : if (!script->IsScript()) return false;
1613 :
1614 : Handle<Script> cast_script(Script::cast(*script));
1615 25 : *target = MessageLocation(cast_script, start_pos_value, end_pos_value);
1616 25 : return true;
1617 : }
1618 :
1619 :
1620 5613 : bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
1621 : Handle<Object> exception) {
1622 5613 : if (!exception->IsJSObject()) return false;
1623 : Handle<Name> key = factory()->stack_trace_symbol();
1624 : Handle<Object> property =
1625 2953 : JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key);
1626 2953 : if (!property->IsJSArray()) return false;
1627 : Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property);
1628 :
1629 : Handle<FrameArray> elements(FrameArray::cast(simple_stack_trace->elements()));
1630 :
1631 : const int frame_count = elements->FrameCount();
1632 2953 : for (int i = 0; i < frame_count; i++) {
1633 404 : if (elements->IsWasmFrame(i) || elements->IsAsmJsWasmFrame(i)) {
1634 : Handle<WasmCompiledModule> compiled_module(
1635 : WasmInstanceObject::cast(elements->WasmInstance(i))
1636 : ->compiled_module());
1637 : int func_index = elements->WasmFunctionIndex(i)->value();
1638 : int code_offset = elements->Offset(i)->value();
1639 : // TODO(wasm): Clean this up (bug 5007).
1640 : int byte_offset = code_offset < 0
1641 : ? (-1 - code_offset)
1642 72 : : elements->Code(i)->SourcePosition(code_offset);
1643 : bool is_at_number_conversion =
1644 36 : elements->IsAsmJsWasmFrame(i) &&
1645 0 : elements->Flags(i)->value() & FrameArray::kAsmJsAtNumberConversion;
1646 : int pos = WasmCompiledModule::GetSourcePosition(
1647 36 : compiled_module, func_index, byte_offset, is_at_number_conversion);
1648 : Handle<Script> script(compiled_module->script());
1649 :
1650 36 : *target = MessageLocation(script, pos, pos + 1);
1651 : return true;
1652 : }
1653 :
1654 : Handle<JSFunction> fun = handle(elements->Function(i), this);
1655 184 : if (!fun->shared()->IsSubjectToDebugging()) continue;
1656 :
1657 : Object* script = fun->shared()->script();
1658 278 : if (script->IsScript() &&
1659 : !(Script::cast(script)->source()->IsUndefined(this))) {
1660 : AbstractCode* abstract_code = elements->Code(i);
1661 : const int code_offset = elements->Offset(i)->value();
1662 139 : const int pos = abstract_code->SourcePosition(code_offset);
1663 :
1664 : Handle<Script> casted_script(Script::cast(script));
1665 139 : *target = MessageLocation(casted_script, pos, pos + 1);
1666 : return true;
1667 : }
1668 : }
1669 : return false;
1670 : }
1671 :
1672 :
1673 1181654 : Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception,
1674 : MessageLocation* location) {
1675 : Handle<FixedArray> stack_trace_object;
1676 1181654 : if (capture_stack_trace_for_uncaught_exceptions_) {
1677 366 : if (exception->IsJSError()) {
1678 : // We fetch the stack trace that corresponds to this error object.
1679 : // If the lookup fails, the exception is probably not a valid Error
1680 : // object. In that case, we fall through and capture the stack trace
1681 : // at this throw site.
1682 : stack_trace_object =
1683 264 : GetDetailedStackTrace(Handle<JSObject>::cast(exception));
1684 : }
1685 366 : if (stack_trace_object.is_null()) {
1686 : // Not an error object, we capture stack and location at throw site.
1687 : stack_trace_object = CaptureCurrentStackTrace(
1688 : stack_trace_for_uncaught_exceptions_frame_limit_,
1689 107 : stack_trace_for_uncaught_exceptions_options_);
1690 : }
1691 : }
1692 1181654 : MessageLocation computed_location;
1693 2368922 : if (location == nullptr &&
1694 11203 : (ComputeLocationFromException(&computed_location, exception) ||
1695 11027 : ComputeLocationFromStackTrace(&computed_location, exception) ||
1696 5438 : ComputeLocation(&computed_location))) {
1697 : location = &computed_location;
1698 : }
1699 :
1700 : return MessageHandler::MakeMessageObject(
1701 : this, MessageTemplate::kUncaughtException, location, exception,
1702 1181654 : stack_trace_object);
1703 : }
1704 :
1705 :
1706 0 : bool Isolate::IsJavaScriptHandlerOnTop(Object* exception) {
1707 : DCHECK_NE(heap()->the_hole_value(), exception);
1708 :
1709 : // For uncatchable exceptions, the JavaScript handler cannot be on top.
1710 106600 : if (!is_catchable_by_javascript(exception)) return false;
1711 :
1712 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
1713 103435 : Address entry_handler = Isolate::handler(thread_local_top());
1714 103435 : if (entry_handler == nullptr) return false;
1715 :
1716 : // Get the address of the external handler so we can compare the address to
1717 : // determine which one is closer to the top of the stack.
1718 : Address external_handler = thread_local_top()->try_catch_handler_address();
1719 91681 : if (external_handler == nullptr) return true;
1720 :
1721 : // The exception has been externally caught if and only if there is an
1722 : // external handler which is on top of the top-most JS_ENTRY handler.
1723 : //
1724 : // Note, that finally clauses would re-throw an exception unless it's aborted
1725 : // by jumps in control flow (like return, break, etc.) and we'll have another
1726 : // chance to set proper v8::TryCatch later.
1727 90283 : return (entry_handler < external_handler);
1728 : }
1729 :
1730 :
1731 0 : bool Isolate::IsExternalHandlerOnTop(Object* exception) {
1732 : DCHECK_NE(heap()->the_hole_value(), exception);
1733 :
1734 : // Get the address of the external handler so we can compare the address to
1735 : // determine which one is closer to the top of the stack.
1736 : Address external_handler = thread_local_top()->try_catch_handler_address();
1737 47279 : if (external_handler == nullptr) return false;
1738 :
1739 : // For uncatchable exceptions, the external handler is always on top.
1740 41253 : if (!is_catchable_by_javascript(exception)) return true;
1741 :
1742 : // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
1743 40238 : Address entry_handler = Isolate::handler(thread_local_top());
1744 40238 : if (entry_handler == nullptr) return true;
1745 :
1746 : // The exception has been externally caught if and only if there is an
1747 : // external handler which is on top of the top-most JS_ENTRY handler.
1748 : //
1749 : // Note, that finally clauses would re-throw an exception unless it's aborted
1750 : // by jumps in control flow (like return, break, etc.) and we'll have another
1751 : // chance to set proper v8::TryCatch later.
1752 27868 : return (entry_handler > external_handler);
1753 : }
1754 :
1755 :
1756 63031 : void Isolate::ReportPendingMessages() {
1757 : DCHECK(AllowExceptions::IsAllowed(this));
1758 :
1759 : // The embedder might run script in response to an exception.
1760 : AllowJavascriptExecutionDebugOnly allow_script(this);
1761 :
1762 : Object* exception = pending_exception();
1763 :
1764 : // Try to propagate the exception to an external v8::TryCatch handler. If
1765 : // propagation was unsuccessful, then we will get another chance at reporting
1766 : // the pending message if the exception is re-thrown.
1767 63031 : bool has_been_propagated = PropagatePendingExceptionToExternalTryCatch();
1768 63031 : if (!has_been_propagated) return;
1769 :
1770 : // Clear the pending message object early to avoid endless recursion.
1771 13872 : Object* message_obj = thread_local_top_.pending_message_obj_;
1772 : clear_pending_message();
1773 :
1774 : // For uncatchable exceptions we do nothing. If needed, the exception and the
1775 : // message have already been propagated to v8::TryCatch.
1776 13872 : if (!is_catchable_by_javascript(exception)) return;
1777 :
1778 : // Determine whether the message needs to be reported to all message handlers
1779 : // depending on whether and external v8::TryCatch or an internal JavaScript
1780 : // handler is on top.
1781 : bool should_report_exception;
1782 11932 : if (IsExternalHandlerOnTop(exception)) {
1783 : // Only report the exception if the external handler is verbose.
1784 10783 : should_report_exception = try_catch_handler()->is_verbose_;
1785 : } else {
1786 : // Report the exception if it isn't caught by JavaScript code.
1787 1149 : should_report_exception = !IsJavaScriptHandlerOnTop(exception);
1788 : }
1789 :
1790 : // Actually report the pending message to all message handlers.
1791 11932 : if (!message_obj->IsTheHole(this) && should_report_exception) {
1792 : HandleScope scope(this);
1793 : Handle<JSMessageObject> message(JSMessageObject::cast(message_obj), this);
1794 : Handle<JSValue> script_wrapper(JSValue::cast(message->script()), this);
1795 : Handle<Script> script(Script::cast(script_wrapper->value()), this);
1796 : int start_pos = message->start_position();
1797 : int end_pos = message->end_position();
1798 9654 : MessageLocation location(script, start_pos, end_pos);
1799 9654 : MessageHandler::ReportMessage(this, &location, message);
1800 : }
1801 : }
1802 :
1803 :
1804 19 : MessageLocation Isolate::GetMessageLocation() {
1805 : DCHECK(has_pending_exception());
1806 :
1807 38 : if (thread_local_top_.pending_exception_ != heap()->termination_exception() &&
1808 19 : !thread_local_top_.pending_message_obj_->IsTheHole(this)) {
1809 : Handle<JSMessageObject> message_obj(
1810 19 : JSMessageObject::cast(thread_local_top_.pending_message_obj_), this);
1811 : Handle<JSValue> script_wrapper(JSValue::cast(message_obj->script()), this);
1812 : Handle<Script> script(Script::cast(script_wrapper->value()), this);
1813 : int start_pos = message_obj->start_position();
1814 : int end_pos = message_obj->end_position();
1815 19 : return MessageLocation(script, start_pos, end_pos);
1816 : }
1817 :
1818 0 : return MessageLocation();
1819 : }
1820 :
1821 :
1822 34443 : bool Isolate::OptionalRescheduleException(bool is_bottom_call) {
1823 : DCHECK(has_pending_exception());
1824 16309 : PropagatePendingExceptionToExternalTryCatch();
1825 :
1826 : bool is_termination_exception =
1827 16309 : pending_exception() == heap_.termination_exception();
1828 :
1829 : // Do not reschedule the exception if this is the bottom call.
1830 : bool clear_exception = is_bottom_call;
1831 :
1832 16309 : if (is_termination_exception) {
1833 1225 : if (is_bottom_call) {
1834 1096 : thread_local_top()->external_caught_exception_ = false;
1835 : clear_pending_exception();
1836 1096 : return false;
1837 : }
1838 15084 : } else if (thread_local_top()->external_caught_exception_) {
1839 : // If the exception is externally caught, clear it if there are no
1840 : // JavaScript frames on the way to the C++ frame that has the
1841 : // external handler.
1842 : DCHECK_NOT_NULL(thread_local_top()->try_catch_handler_address());
1843 : Address external_handler_address =
1844 : thread_local_top()->try_catch_handler_address();
1845 12245 : JavaScriptFrameIterator it(this);
1846 12245 : if (it.done() || (it.frame()->sp() > external_handler_address)) {
1847 : clear_exception = true;
1848 : }
1849 : }
1850 :
1851 : // Clear the exception if needed.
1852 15213 : if (clear_exception) {
1853 13388 : thread_local_top()->external_caught_exception_ = false;
1854 : clear_pending_exception();
1855 13388 : return false;
1856 : }
1857 :
1858 : // Reschedule the exception.
1859 1825 : thread_local_top()->scheduled_exception_ = pending_exception();
1860 : clear_pending_exception();
1861 1825 : return true;
1862 : }
1863 :
1864 39130 : void Isolate::PushPromise(Handle<JSObject> promise) {
1865 : ThreadLocalTop* tltop = thread_local_top();
1866 19565 : PromiseOnStack* prev = tltop->promise_on_stack_;
1867 : Handle<JSObject> global_promise = global_handles()->Create(*promise);
1868 39130 : tltop->promise_on_stack_ = new PromiseOnStack(global_promise, prev);
1869 19565 : }
1870 :
1871 :
1872 19545 : void Isolate::PopPromise() {
1873 : ThreadLocalTop* tltop = thread_local_top();
1874 39090 : if (tltop->promise_on_stack_ == nullptr) return;
1875 : PromiseOnStack* prev = tltop->promise_on_stack_->prev();
1876 : Handle<Object> global_promise = tltop->promise_on_stack_->promise();
1877 19545 : delete tltop->promise_on_stack_;
1878 19545 : tltop->promise_on_stack_ = prev;
1879 19545 : global_handles()->Destroy(global_promise.location());
1880 : }
1881 :
1882 : namespace {
1883 : bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
1884 : Handle<JSPromise> promise);
1885 :
1886 975 : bool PromiseHandlerCheck(Isolate* isolate, Handle<JSReceiver> handler,
1887 : Handle<JSReceiver> deferred_promise) {
1888 : // Recurse to the forwarding Promise, if any. This may be due to
1889 : // - await reaction forwarding to the throwaway Promise, which has
1890 : // a dependency edge to the outer Promise.
1891 : // - PromiseIdResolveHandler forwarding to the output of .then
1892 : // - Promise.all/Promise.race forwarding to a throwaway Promise, which
1893 : // has a dependency edge to the generated outer Promise.
1894 : // Otherwise, this is a real reject handler for the Promise.
1895 : Handle<Symbol> key = isolate->factory()->promise_forwarding_handler_symbol();
1896 975 : Handle<Object> forwarding_handler = JSReceiver::GetDataProperty(handler, key);
1897 975 : if (forwarding_handler->IsUndefined(isolate)) {
1898 : return true;
1899 : }
1900 :
1901 365 : if (!deferred_promise->IsJSPromise()) {
1902 : return true;
1903 : }
1904 :
1905 : return InternalPromiseHasUserDefinedRejectHandler(
1906 365 : isolate, Handle<JSPromise>::cast(deferred_promise));
1907 : }
1908 :
1909 5089 : bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
1910 : Handle<JSPromise> promise) {
1911 : // If this promise was marked as being handled by a catch block
1912 : // in an async function, then it has a user-defined reject handler.
1913 5089 : if (promise->handled_hint()) return true;
1914 :
1915 : // If this Promise is subsumed by another Promise (a Promise resolved
1916 : // with another Promise, or an intermediate, hidden, throwaway Promise
1917 : // within async/await), then recurse on the outer Promise.
1918 : // In this case, the dependency is one possible way that the Promise
1919 : // could be resolved, so it does not subsume the other following cases.
1920 : Handle<Symbol> key = isolate->factory()->promise_handled_by_symbol();
1921 4543 : Handle<Object> outer_promise_obj = JSObject::GetDataProperty(promise, key);
1922 5866 : if (outer_promise_obj->IsJSPromise() &&
1923 : InternalPromiseHasUserDefinedRejectHandler(
1924 1323 : isolate, Handle<JSPromise>::cast(outer_promise_obj))) {
1925 : return true;
1926 : }
1927 :
1928 : Handle<Object> queue(promise->reject_reactions(), isolate);
1929 : Handle<Object> deferred_promise(promise->deferred_promise(), isolate);
1930 :
1931 3644 : if (queue->IsUndefined(isolate)) {
1932 : return false;
1933 : }
1934 :
1935 1066 : if (queue->IsCallable()) {
1936 : return PromiseHandlerCheck(isolate, Handle<JSReceiver>::cast(queue),
1937 965 : Handle<JSReceiver>::cast(deferred_promise));
1938 : }
1939 :
1940 101 : if (queue->IsSymbol()) {
1941 : return InternalPromiseHasUserDefinedRejectHandler(
1942 91 : isolate, Handle<JSPromise>::cast(deferred_promise));
1943 : }
1944 :
1945 : Handle<FixedArray> queue_arr = Handle<FixedArray>::cast(queue);
1946 : Handle<FixedArray> deferred_promise_arr =
1947 : Handle<FixedArray>::cast(deferred_promise);
1948 30 : for (int i = 0; i < deferred_promise_arr->length(); i++) {
1949 : Handle<JSReceiver> deferred_promise_item(
1950 : JSReceiver::cast(deferred_promise_arr->get(i)));
1951 20 : if (queue_arr->get(i)->IsSymbol()) {
1952 10 : if (InternalPromiseHasUserDefinedRejectHandler(
1953 : isolate, Handle<JSPromise>::cast(deferred_promise_item))) {
1954 : return true;
1955 : }
1956 : } else {
1957 : Handle<JSReceiver> queue_item(JSReceiver::cast(queue_arr->get(i)));
1958 10 : if (PromiseHandlerCheck(isolate, queue_item, deferred_promise_item)) {
1959 10 : return true;
1960 : }
1961 : }
1962 : }
1963 :
1964 : return false;
1965 : }
1966 :
1967 : } // namespace
1968 :
1969 3309 : bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) {
1970 3309 : if (!promise->IsJSPromise()) return false;
1971 : return InternalPromiseHasUserDefinedRejectHandler(
1972 3300 : this, Handle<JSPromise>::cast(promise));
1973 : }
1974 :
1975 4059 : Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
1976 : Handle<Object> undefined = factory()->undefined_value();
1977 : ThreadLocalTop* tltop = thread_local_top();
1978 4059 : if (tltop->promise_on_stack_ == nullptr) return undefined;
1979 : // Find the top-most try-catch or try-finally handler.
1980 1527 : CatchType prediction = PredictExceptionCatcher();
1981 1527 : if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) {
1982 14 : return undefined;
1983 : }
1984 : Handle<Object> retval = undefined;
1985 2744 : PromiseOnStack* promise_on_stack = tltop->promise_on_stack_;
1986 312822 : for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) {
1987 156001 : switch (PredictException(it.frame())) {
1988 : case HandlerTable::UNCAUGHT:
1989 : continue;
1990 : case HandlerTable::CAUGHT:
1991 : case HandlerTable::DESUGARING:
1992 471 : if (retval->IsJSPromise()) {
1993 : // Caught the result of an inner async/await invocation.
1994 : // Mark the inner promise as caught in the "synchronous case" so
1995 : // that Debug::OnException will see. In the synchronous case,
1996 : // namely in the code in an async function before the first
1997 : // await, the function which has this exception event has not yet
1998 : // returned, so the generated Promise has not yet been marked
1999 : // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol.
2000 325 : Handle<JSPromise>::cast(retval)->set_handled_hint(true);
2001 : }
2002 471 : return retval;
2003 : case HandlerTable::PROMISE:
2004 : return promise_on_stack
2005 : ? Handle<Object>::cast(promise_on_stack->promise())
2006 398 : : undefined;
2007 : case HandlerTable::ASYNC_AWAIT: {
2008 : // If in the initial portion of async/await, continue the loop to pop up
2009 : // successive async/await stack frames until an asynchronous one with
2010 : // dependents is found, or a non-async stack frame is encountered, in
2011 : // order to handle the synchronous async/await catch prediction case:
2012 : // assume that async function calls are awaited.
2013 1465 : if (!promise_on_stack) return retval;
2014 : retval = promise_on_stack->promise();
2015 1465 : if (PromiseHasUserDefinedRejectHandler(retval)) {
2016 234 : return retval;
2017 : }
2018 : promise_on_stack = promise_on_stack->prev();
2019 1231 : continue;
2020 : }
2021 : }
2022 : }
2023 410 : return retval;
2024 : }
2025 :
2026 :
2027 1236 : void Isolate::SetCaptureStackTraceForUncaughtExceptions(
2028 : bool capture,
2029 : int frame_limit,
2030 : StackTrace::StackTraceOptions options) {
2031 1236 : capture_stack_trace_for_uncaught_exceptions_ = capture;
2032 1236 : stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
2033 1236 : stack_trace_for_uncaught_exceptions_options_ = options;
2034 1236 : }
2035 :
2036 :
2037 5 : void Isolate::SetAbortOnUncaughtExceptionCallback(
2038 : v8::Isolate::AbortOnUncaughtExceptionCallback callback) {
2039 5 : abort_on_uncaught_exception_callback_ = callback;
2040 5 : }
2041 :
2042 : namespace {
2043 0 : void AdvanceWhileDebugContext(JavaScriptFrameIterator& it, Debug* debug) {
2044 0 : if (!debug->in_debug_scope()) return;
2045 :
2046 0 : while (!it.done()) {
2047 0 : Context* context = Context::cast(it.frame()->context());
2048 0 : if (context->native_context() == *debug->debug_context()) {
2049 0 : it.Advance();
2050 : } else {
2051 : break;
2052 : }
2053 : }
2054 : }
2055 : } // namespace
2056 :
2057 0 : Handle<Context> Isolate::GetCallingNativeContext() {
2058 0 : JavaScriptFrameIterator it(this);
2059 0 : AdvanceWhileDebugContext(it, debug_);
2060 0 : if (it.done()) return Handle<Context>::null();
2061 : JavaScriptFrame* frame = it.frame();
2062 0 : Context* context = Context::cast(frame->context());
2063 0 : return Handle<Context>(context->native_context(), this);
2064 : }
2065 :
2066 0 : Handle<Context> Isolate::GetIncumbentContext() {
2067 0 : JavaScriptFrameIterator it(this);
2068 0 : AdvanceWhileDebugContext(it, debug_);
2069 :
2070 : // 1st candidate: most-recently-entered author function's context
2071 : // if it's newer than the last Context::BackupIncumbentScope entry.
2072 0 : if (!it.done() &&
2073 : static_cast<const void*>(it.frame()) >
2074 : static_cast<const void*>(top_backup_incumbent_scope())) {
2075 0 : Context* context = Context::cast(it.frame()->context());
2076 0 : return Handle<Context>(context->native_context(), this);
2077 : }
2078 :
2079 : // 2nd candidate: the last Context::Scope's incumbent context if any.
2080 0 : if (top_backup_incumbent_scope()) {
2081 : return Utils::OpenHandle(
2082 : *top_backup_incumbent_scope()->backup_incumbent_context_);
2083 : }
2084 :
2085 : // Last candidate: the entered context.
2086 : // Given that there is no other author function is running, there must be
2087 : // no cross-context function running, then the incumbent realm must match
2088 : // the entry realm.
2089 : v8::Local<v8::Context> entered_context =
2090 0 : reinterpret_cast<v8::Isolate*>(this)->GetEnteredContext();
2091 : return Utils::OpenHandle(*entered_context);
2092 : }
2093 :
2094 24163 : char* Isolate::ArchiveThread(char* to) {
2095 24163 : MemCopy(to, reinterpret_cast<char*>(thread_local_top()),
2096 : sizeof(ThreadLocalTop));
2097 : InitializeThreadLocal();
2098 : clear_pending_exception();
2099 : clear_pending_message();
2100 : clear_scheduled_exception();
2101 24163 : return to + sizeof(ThreadLocalTop);
2102 : }
2103 :
2104 :
2105 24163 : char* Isolate::RestoreThread(char* from) {
2106 24163 : MemCopy(reinterpret_cast<char*>(thread_local_top()), from,
2107 : sizeof(ThreadLocalTop));
2108 : // This might be just paranoia, but it seems to be needed in case a
2109 : // thread_local_top_ is restored on a separate OS thread.
2110 : #ifdef USE_SIMULATOR
2111 : thread_local_top()->simulator_ = Simulator::current(this);
2112 : #endif
2113 : DCHECK(context() == nullptr || context()->IsContext());
2114 24163 : return from + sizeof(ThreadLocalTop);
2115 : }
2116 :
2117 53977 : Isolate::ThreadDataTable::ThreadDataTable() : list_(nullptr) {}
2118 :
2119 0 : Isolate::ThreadDataTable::~ThreadDataTable() {
2120 : // TODO(svenpanne) The assertion below would fire if an embedder does not
2121 : // cleanly dispose all Isolates before disposing v8, so we are conservative
2122 : // and leave it out for now.
2123 : // DCHECK_NULL(list_);
2124 0 : }
2125 :
2126 0 : void Isolate::ReleaseManagedObjects() {
2127 : Isolate::ManagedObjectFinalizer* current =
2128 53365 : managed_object_finalizers_list_.next_;
2129 53365 : managed_object_finalizers_list_.next_ = nullptr;
2130 304356 : while (current != nullptr) {
2131 250991 : Isolate::ManagedObjectFinalizer* next = current->next_;
2132 : current->Dispose();
2133 : current = next;
2134 : }
2135 : // No new managed objects should pop up during finalization.
2136 : DCHECK_NULL(managed_object_finalizers_list_.next_);
2137 0 : }
2138 :
2139 361401 : void Isolate::RegisterForReleaseAtTeardown(
2140 : Isolate::ManagedObjectFinalizer* finalizer) {
2141 : DCHECK_NOT_NULL(finalizer->value_);
2142 : DCHECK_NOT_NULL(finalizer->deleter_);
2143 : DCHECK_NULL(finalizer->prev_);
2144 : DCHECK_NULL(finalizer->next_);
2145 :
2146 : // Insert at head. We keep the head alive for the lifetime of the Isolate
2147 : // because otherwise we can't reset the head, should we delete it before
2148 : // the isolate expires
2149 361401 : Isolate::ManagedObjectFinalizer* next = managed_object_finalizers_list_.next_;
2150 361401 : managed_object_finalizers_list_.next_ = finalizer;
2151 361401 : finalizer->prev_ = &managed_object_finalizers_list_;
2152 361401 : finalizer->next_ = next;
2153 361401 : if (next != nullptr) next->prev_ = finalizer;
2154 361401 : }
2155 :
2156 110270 : void Isolate::UnregisterFromReleaseAtTeardown(
2157 : Isolate::ManagedObjectFinalizer* finalizer) {
2158 : DCHECK_NOT_NULL(finalizer);
2159 : DCHECK_NOT_NULL(finalizer->prev_);
2160 :
2161 110270 : finalizer->prev_->next_ = finalizer->next_;
2162 110270 : if (finalizer->next_ != nullptr) finalizer->next_->prev_ = finalizer->prev_;
2163 110270 : }
2164 :
2165 0 : Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
2166 : #if defined(USE_SIMULATOR)
2167 : delete simulator_;
2168 : #endif
2169 0 : }
2170 :
2171 :
2172 : Isolate::PerIsolateThreadData*
2173 309476 : Isolate::ThreadDataTable::Lookup(Isolate* isolate,
2174 : ThreadId thread_id) {
2175 3161923 : for (PerIsolateThreadData* data = list_; data != nullptr;
2176 : data = data->next_) {
2177 3095412 : if (data->Matches(isolate, thread_id)) return data;
2178 : }
2179 : return nullptr;
2180 : }
2181 :
2182 :
2183 0 : void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
2184 60505 : if (list_ != nullptr) list_->prev_ = data;
2185 60505 : data->next_ = list_;
2186 60505 : list_ = data;
2187 0 : }
2188 :
2189 :
2190 58871 : void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
2191 58871 : if (list_ == data) list_ = data->next_;
2192 58871 : if (data->next_ != nullptr) data->next_->prev_ = data->prev_;
2193 58871 : if (data->prev_ != nullptr) data->prev_->next_ = data->next_;
2194 58871 : delete data;
2195 58871 : }
2196 :
2197 :
2198 53365 : void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) {
2199 118019 : PerIsolateThreadData* data = list_;
2200 171384 : while (data != nullptr) {
2201 64654 : PerIsolateThreadData* next = data->next_;
2202 64654 : if (data->isolate() == isolate) Remove(data);
2203 : data = next;
2204 : }
2205 53365 : }
2206 :
2207 :
2208 : #ifdef DEBUG
2209 : #define TRACE_ISOLATE(tag) \
2210 : do { \
2211 : if (FLAG_trace_isolates) { \
2212 : PrintF("Isolate %p (id %d)" #tag "\n", \
2213 : reinterpret_cast<void*>(this), id()); \
2214 : } \
2215 : } while (false)
2216 : #else
2217 : #define TRACE_ISOLATE(tag)
2218 : #endif
2219 :
2220 0 : class VerboseAccountingAllocator : public AccountingAllocator {
2221 : public:
2222 : VerboseAccountingAllocator(Heap* heap, size_t allocation_sample_bytes,
2223 : size_t pool_sample_bytes)
2224 : : heap_(heap),
2225 : last_memory_usage_(0),
2226 : last_pool_size_(0),
2227 : nesting_deepth_(0),
2228 : allocation_sample_bytes_(allocation_sample_bytes),
2229 0 : pool_sample_bytes_(pool_sample_bytes) {}
2230 :
2231 0 : v8::internal::Segment* GetSegment(size_t size) override {
2232 0 : v8::internal::Segment* memory = AccountingAllocator::GetSegment(size);
2233 0 : if (memory) {
2234 0 : size_t malloced_current = GetCurrentMemoryUsage();
2235 0 : size_t pooled_current = GetCurrentPoolSize();
2236 :
2237 0 : if (last_memory_usage_.Value() + allocation_sample_bytes_ <
2238 0 : malloced_current ||
2239 0 : last_pool_size_.Value() + pool_sample_bytes_ < pooled_current) {
2240 0 : PrintMemoryJSON(malloced_current, pooled_current);
2241 : last_memory_usage_.SetValue(malloced_current);
2242 : last_pool_size_.SetValue(pooled_current);
2243 : }
2244 : }
2245 0 : return memory;
2246 : }
2247 :
2248 0 : void ReturnSegment(v8::internal::Segment* memory) override {
2249 0 : AccountingAllocator::ReturnSegment(memory);
2250 0 : size_t malloced_current = GetCurrentMemoryUsage();
2251 0 : size_t pooled_current = GetCurrentPoolSize();
2252 :
2253 0 : if (malloced_current + allocation_sample_bytes_ <
2254 0 : last_memory_usage_.Value() ||
2255 0 : pooled_current + pool_sample_bytes_ < last_pool_size_.Value()) {
2256 0 : PrintMemoryJSON(malloced_current, pooled_current);
2257 : last_memory_usage_.SetValue(malloced_current);
2258 : last_pool_size_.SetValue(pooled_current);
2259 : }
2260 0 : }
2261 :
2262 0 : void ZoneCreation(const Zone* zone) override {
2263 0 : double time = heap_->isolate()->time_millis_since_init();
2264 : PrintF(
2265 : "{"
2266 : "\"type\": \"zonecreation\", "
2267 : "\"isolate\": \"%p\", "
2268 : "\"time\": %f, "
2269 : "\"ptr\": \"%p\", "
2270 : "\"name\": \"%s\","
2271 : "\"nesting\": %" PRIuS "}\n",
2272 0 : reinterpret_cast<void*>(heap_->isolate()), time,
2273 : reinterpret_cast<const void*>(zone), zone->name(),
2274 0 : nesting_deepth_.Value());
2275 : nesting_deepth_.Increment(1);
2276 0 : }
2277 :
2278 0 : void ZoneDestruction(const Zone* zone) override {
2279 : nesting_deepth_.Decrement(1);
2280 0 : double time = heap_->isolate()->time_millis_since_init();
2281 : PrintF(
2282 : "{"
2283 : "\"type\": \"zonedestruction\", "
2284 : "\"isolate\": \"%p\", "
2285 : "\"time\": %f, "
2286 : "\"ptr\": \"%p\", "
2287 : "\"name\": \"%s\", "
2288 : "\"size\": %" PRIuS
2289 : ","
2290 : "\"nesting\": %" PRIuS "}\n",
2291 0 : reinterpret_cast<void*>(heap_->isolate()), time,
2292 : reinterpret_cast<const void*>(zone), zone->name(),
2293 0 : zone->allocation_size(), nesting_deepth_.Value());
2294 0 : }
2295 :
2296 : private:
2297 0 : void PrintMemoryJSON(size_t malloced, size_t pooled) {
2298 : // Note: Neither isolate, nor heap is locked, so be careful with accesses
2299 : // as the allocator is potentially used on a concurrent thread.
2300 0 : double time = heap_->isolate()->time_millis_since_init();
2301 : PrintF(
2302 : "{"
2303 : "\"type\": \"zone\", "
2304 : "\"isolate\": \"%p\", "
2305 : "\"time\": %f, "
2306 : "\"allocated\": %" PRIuS
2307 : ","
2308 : "\"pooled\": %" PRIuS "}\n",
2309 0 : reinterpret_cast<void*>(heap_->isolate()), time, malloced, pooled);
2310 0 : }
2311 :
2312 : Heap* heap_;
2313 : base::AtomicNumber<size_t> last_memory_usage_;
2314 : base::AtomicNumber<size_t> last_pool_size_;
2315 : base::AtomicNumber<size_t> nesting_deepth_;
2316 : size_t allocation_sample_bytes_, pool_sample_bytes_;
2317 : };
2318 :
2319 : #ifdef DEBUG
2320 : base::AtomicNumber<size_t> Isolate::non_disposed_isolates_;
2321 : #endif // DEBUG
2322 :
2323 54999 : Isolate::Isolate(bool enable_serializer)
2324 : : embedder_data_(),
2325 : entry_stack_(nullptr),
2326 : stack_trace_nesting_level_(0),
2327 : incomplete_message_(nullptr),
2328 : bootstrapper_(nullptr),
2329 : runtime_profiler_(nullptr),
2330 : compilation_cache_(nullptr),
2331 : logger_(nullptr),
2332 : load_stub_cache_(nullptr),
2333 : store_stub_cache_(nullptr),
2334 : deoptimizer_data_(nullptr),
2335 : deoptimizer_lazy_throw_(false),
2336 : materialized_object_store_(nullptr),
2337 : capture_stack_trace_for_uncaught_exceptions_(false),
2338 : stack_trace_for_uncaught_exceptions_frame_limit_(0),
2339 : stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
2340 : context_slot_cache_(nullptr),
2341 : descriptor_lookup_cache_(nullptr),
2342 : handle_scope_implementer_(nullptr),
2343 : unicode_cache_(nullptr),
2344 : allocator_(FLAG_trace_gc_object_stats ? new VerboseAccountingAllocator(
2345 : &heap_, 256 * KB, 128 * KB)
2346 : : new AccountingAllocator()),
2347 : inner_pointer_to_code_cache_(nullptr),
2348 : global_handles_(nullptr),
2349 : eternal_handles_(nullptr),
2350 : thread_manager_(nullptr),
2351 : setup_delegate_(nullptr),
2352 : regexp_stack_(nullptr),
2353 : date_cache_(nullptr),
2354 : call_descriptor_data_(nullptr),
2355 : // TODO(bmeurer) Initialized lazily because it depends on flags; can
2356 : // be fixed once the default isolate cleanup is done.
2357 : random_number_generator_(nullptr),
2358 : rail_mode_(PERFORMANCE_ANIMATION),
2359 : promise_hook_or_debug_is_active_(false),
2360 : promise_hook_(nullptr),
2361 : load_start_time_ms_(0),
2362 : serializer_enabled_(enable_serializer),
2363 : has_fatal_error_(false),
2364 : initialized_from_snapshot_(false),
2365 : is_tail_call_elimination_enabled_(true),
2366 : is_isolate_in_background_(false),
2367 : cpu_profiler_(nullptr),
2368 : heap_profiler_(nullptr),
2369 : code_event_dispatcher_(new CodeEventDispatcher()),
2370 : function_entry_hook_(nullptr),
2371 : deferred_handles_head_(nullptr),
2372 : optimizing_compile_dispatcher_(nullptr),
2373 : stress_deopt_count_(0),
2374 : next_optimization_id_(0),
2375 : #if V8_SFI_HAS_UNIQUE_ID
2376 : next_unique_sfi_id_(0),
2377 : #endif
2378 : is_running_microtasks_(false),
2379 : use_counter_callback_(nullptr),
2380 : basic_block_profiler_(nullptr),
2381 : cancelable_task_manager_(new CancelableTaskManager()),
2382 : wasm_compilation_manager_(new wasm::CompilationManager()),
2383 : abort_on_uncaught_exception_callback_(nullptr),
2384 604989 : total_regexp_code_generated_(0) {
2385 : {
2386 : base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
2387 54999 : CHECK(thread_data_table_);
2388 : }
2389 54999 : id_ = base::Relaxed_AtomicIncrement(&isolate_counter_, 1);
2390 : TRACE_ISOLATE(constructor);
2391 :
2392 : memset(isolate_addresses_, 0,
2393 54999 : sizeof(isolate_addresses_[0]) * (kIsolateAddressCount + 1));
2394 :
2395 54999 : heap_.isolate_ = this;
2396 54999 : stack_guard_.isolate_ = this;
2397 :
2398 : // ThreadManager is initialized early to support locking an isolate
2399 : // before it is entered.
2400 54999 : thread_manager_ = new ThreadManager();
2401 54999 : thread_manager_->isolate_ = this;
2402 :
2403 : #ifdef DEBUG
2404 : // heap_histograms_ initializes itself.
2405 : memset(&js_spill_information_, 0, sizeof(js_spill_information_));
2406 :
2407 : non_disposed_isolates_.Increment(1);
2408 : #endif // DEBUG
2409 :
2410 : handle_scope_data_.Initialize();
2411 :
2412 : #define ISOLATE_INIT_EXECUTE(type, name, initial_value) \
2413 : name##_ = (initial_value);
2414 54999 : ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
2415 : #undef ISOLATE_INIT_EXECUTE
2416 :
2417 : #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \
2418 : memset(name##_, 0, sizeof(type) * length);
2419 219996 : ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
2420 : #undef ISOLATE_INIT_ARRAY_EXECUTE
2421 :
2422 54999 : InitializeLoggingAndCounters();
2423 54999 : debug_ = new Debug(this);
2424 :
2425 54999 : init_memcopy_functions(this);
2426 54999 : }
2427 :
2428 :
2429 53365 : void Isolate::TearDown() {
2430 : TRACE_ISOLATE(tear_down);
2431 :
2432 : // Temporarily set this isolate as current so that various parts of
2433 : // the isolate can access it in their destructors without having a
2434 : // direct pointer. We don't use Enter/Exit here to avoid
2435 : // initializing the thread data.
2436 : PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
2437 : DCHECK_EQ(base::Relaxed_Load(&isolate_key_created_), 1);
2438 : Isolate* saved_isolate =
2439 53365 : reinterpret_cast<Isolate*>(base::Thread::GetThreadLocal(isolate_key_));
2440 53365 : SetIsolateThreadLocals(this, nullptr);
2441 :
2442 53365 : Deinit();
2443 :
2444 : {
2445 : base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
2446 53365 : thread_data_table_->RemoveAllThreads(this);
2447 : }
2448 :
2449 : #ifdef DEBUG
2450 : non_disposed_isolates_.Decrement(1);
2451 : #endif // DEBUG
2452 :
2453 53365 : delete this;
2454 :
2455 : // Restore the previous current isolate.
2456 53365 : SetIsolateThreadLocals(saved_isolate, saved_data);
2457 53365 : }
2458 :
2459 :
2460 29500 : void Isolate::GlobalTearDown() {
2461 29500 : delete thread_data_table_;
2462 29500 : thread_data_table_ = nullptr;
2463 29500 : }
2464 :
2465 :
2466 59948 : void Isolate::ClearSerializerData() {
2467 113659 : delete external_reference_table_;
2468 59948 : external_reference_table_ = nullptr;
2469 60466 : delete external_reference_map_;
2470 59948 : external_reference_map_ = nullptr;
2471 59948 : }
2472 :
2473 :
2474 160095 : void Isolate::Deinit() {
2475 : TRACE_ISOLATE(deinit);
2476 :
2477 53365 : debug()->Unload();
2478 :
2479 53365 : if (concurrent_recompilation_enabled()) {
2480 53242 : optimizing_compile_dispatcher_->Stop();
2481 53242 : delete optimizing_compile_dispatcher_;
2482 53242 : optimizing_compile_dispatcher_ = nullptr;
2483 : }
2484 :
2485 53365 : wasm_compilation_manager_->TearDown();
2486 :
2487 53365 : heap_.mark_compact_collector()->EnsureSweepingCompleted();
2488 53365 : heap_.memory_allocator()->unmapper()->WaitUntilCompleted();
2489 :
2490 53365 : DumpAndResetStats();
2491 :
2492 53365 : if (FLAG_print_deopt_stress) {
2493 0 : PrintF(stdout, "=== Stress deopt counter: %u\n", stress_deopt_count_);
2494 : }
2495 :
2496 53365 : if (cpu_profiler_) {
2497 53365 : cpu_profiler_->DeleteAllProfiles();
2498 : }
2499 :
2500 : // We must stop the logger before we tear down other components.
2501 53365 : sampler::Sampler* sampler = logger_->sampler();
2502 106709 : if (sampler && sampler->IsActive()) sampler->Stop();
2503 :
2504 : FreeThreadResources();
2505 : // Release managed objects before shutting down the heap. The finalizer might
2506 : // need to access heap objects.
2507 : ReleaseManagedObjects();
2508 :
2509 53365 : delete deoptimizer_data_;
2510 53365 : deoptimizer_data_ = nullptr;
2511 53365 : builtins_.TearDown();
2512 53365 : bootstrapper_->TearDown();
2513 :
2514 53365 : if (runtime_profiler_ != nullptr) {
2515 53365 : delete runtime_profiler_;
2516 53365 : runtime_profiler_ = nullptr;
2517 : }
2518 :
2519 53365 : delete basic_block_profiler_;
2520 53365 : basic_block_profiler_ = nullptr;
2521 :
2522 53365 : delete heap_profiler_;
2523 53365 : heap_profiler_ = nullptr;
2524 :
2525 53365 : compiler_dispatcher_->AbortAll(CompilerDispatcher::BlockingBehavior::kBlock);
2526 53365 : delete compiler_dispatcher_;
2527 53365 : compiler_dispatcher_ = nullptr;
2528 :
2529 53365 : cancelable_task_manager()->CancelAndWait();
2530 :
2531 53365 : heap_.TearDown();
2532 53365 : logger_->TearDown();
2533 :
2534 53365 : delete interpreter_;
2535 53365 : interpreter_ = nullptr;
2536 :
2537 106730 : delete ast_string_constants_;
2538 53365 : ast_string_constants_ = nullptr;
2539 :
2540 53365 : delete cpu_profiler_;
2541 53365 : cpu_profiler_ = nullptr;
2542 :
2543 : code_event_dispatcher_.reset();
2544 :
2545 70846 : delete root_index_map_;
2546 53365 : root_index_map_ = nullptr;
2547 :
2548 53365 : ClearSerializerData();
2549 53365 : }
2550 :
2551 :
2552 462212 : void Isolate::SetIsolateThreadLocals(Isolate* isolate,
2553 : PerIsolateThreadData* data) {
2554 462212 : base::Thread::SetThreadLocal(isolate_key_, isolate);
2555 462180 : base::Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
2556 462189 : }
2557 :
2558 :
2559 320190 : Isolate::~Isolate() {
2560 : TRACE_ISOLATE(destructor);
2561 :
2562 : // The entry stack must be empty when we get here.
2563 : DCHECK(entry_stack_ == nullptr || entry_stack_->previous_item == nullptr);
2564 :
2565 53365 : delete entry_stack_;
2566 53365 : entry_stack_ = nullptr;
2567 :
2568 53365 : delete unicode_cache_;
2569 53365 : unicode_cache_ = nullptr;
2570 :
2571 53365 : delete date_cache_;
2572 53365 : date_cache_ = nullptr;
2573 :
2574 53365 : delete[] call_descriptor_data_;
2575 53365 : call_descriptor_data_ = nullptr;
2576 :
2577 53365 : delete access_compiler_data_;
2578 53365 : access_compiler_data_ = nullptr;
2579 :
2580 53365 : delete regexp_stack_;
2581 53365 : regexp_stack_ = nullptr;
2582 :
2583 53365 : delete descriptor_lookup_cache_;
2584 53365 : descriptor_lookup_cache_ = nullptr;
2585 53365 : delete context_slot_cache_;
2586 53365 : context_slot_cache_ = nullptr;
2587 :
2588 53365 : delete load_stub_cache_;
2589 53365 : load_stub_cache_ = nullptr;
2590 53365 : delete store_stub_cache_;
2591 53365 : store_stub_cache_ = nullptr;
2592 :
2593 106730 : delete materialized_object_store_;
2594 53365 : materialized_object_store_ = nullptr;
2595 :
2596 53365 : delete logger_;
2597 53365 : logger_ = nullptr;
2598 :
2599 53365 : delete handle_scope_implementer_;
2600 53365 : handle_scope_implementer_ = nullptr;
2601 :
2602 : delete code_tracer();
2603 : set_code_tracer(nullptr);
2604 :
2605 53365 : delete compilation_cache_;
2606 53365 : compilation_cache_ = nullptr;
2607 53365 : delete bootstrapper_;
2608 53365 : bootstrapper_ = nullptr;
2609 53365 : delete inner_pointer_to_code_cache_;
2610 53365 : inner_pointer_to_code_cache_ = nullptr;
2611 :
2612 53365 : delete thread_manager_;
2613 53365 : thread_manager_ = nullptr;
2614 :
2615 53365 : delete global_handles_;
2616 53365 : global_handles_ = nullptr;
2617 53365 : delete eternal_handles_;
2618 53365 : eternal_handles_ = nullptr;
2619 :
2620 53377 : delete string_stream_debug_object_cache_;
2621 53365 : string_stream_debug_object_cache_ = nullptr;
2622 :
2623 53365 : delete random_number_generator_;
2624 53365 : random_number_generator_ = nullptr;
2625 :
2626 53365 : delete debug_;
2627 53365 : debug_ = nullptr;
2628 :
2629 53365 : delete cancelable_task_manager_;
2630 53365 : cancelable_task_manager_ = nullptr;
2631 :
2632 53365 : delete allocator_;
2633 53365 : allocator_ = nullptr;
2634 :
2635 : #if USE_SIMULATOR
2636 : Simulator::TearDown(simulator_i_cache_, simulator_redirection_);
2637 : simulator_i_cache_ = nullptr;
2638 : simulator_redirection_ = nullptr;
2639 : #endif
2640 53365 : }
2641 :
2642 :
2643 0 : void Isolate::InitializeThreadLocal() {
2644 79162 : thread_local_top_.isolate_ = this;
2645 79162 : thread_local_top_.Initialize();
2646 0 : }
2647 :
2648 :
2649 129276 : bool Isolate::PropagatePendingExceptionToExternalTryCatch() {
2650 : Object* exception = pending_exception();
2651 :
2652 105451 : if (IsJavaScriptHandlerOnTop(exception)) {
2653 76159 : thread_local_top_.external_caught_exception_ = false;
2654 76159 : return false;
2655 : }
2656 :
2657 29292 : if (!IsExternalHandlerOnTop(exception)) {
2658 4452 : thread_local_top_.external_caught_exception_ = false;
2659 4452 : return true;
2660 : }
2661 :
2662 24840 : thread_local_top_.external_caught_exception_ = true;
2663 24840 : if (!is_catchable_by_javascript(exception)) {
2664 1015 : try_catch_handler()->can_continue_ = false;
2665 1015 : try_catch_handler()->has_terminated_ = true;
2666 1015 : try_catch_handler()->exception_ = heap()->null_value();
2667 : } else {
2668 : v8::TryCatch* handler = try_catch_handler();
2669 : DCHECK(thread_local_top_.pending_message_obj_->IsJSMessageObject() ||
2670 : thread_local_top_.pending_message_obj_->IsTheHole(this));
2671 23825 : handler->can_continue_ = true;
2672 23825 : handler->has_terminated_ = false;
2673 23825 : handler->exception_ = pending_exception();
2674 : // Propagate to the external try-catch only if we got an actual message.
2675 47650 : if (thread_local_top_.pending_message_obj_->IsTheHole(this)) return true;
2676 :
2677 12985 : handler->message_obj_ = thread_local_top_.pending_message_obj_;
2678 : }
2679 : return true;
2680 : }
2681 :
2682 55387 : bool Isolate::InitializeCounters() {
2683 55387 : if (async_counters_) return false;
2684 109998 : async_counters_ = std::make_shared<Counters>(this);
2685 54999 : return true;
2686 : }
2687 :
2688 55387 : void Isolate::InitializeLoggingAndCounters() {
2689 55387 : if (logger_ == nullptr) {
2690 54999 : logger_ = new Logger(this);
2691 : }
2692 55387 : InitializeCounters();
2693 55387 : }
2694 :
2695 : namespace {
2696 : void PrintBuiltinSizes(Isolate* isolate) {
2697 : Builtins* builtins = isolate->builtins();
2698 : for (int i = 0; i < Builtins::builtin_count; i++) {
2699 : const char* name = builtins->name(i);
2700 : const char* kind = Builtins::KindNameOf(i);
2701 : Code* code = builtins->builtin(i);
2702 : PrintF(stdout, "%s Builtin, %s, %d\n", kind, name,
2703 : code->instruction_size());
2704 : }
2705 : }
2706 : } // namespace
2707 :
2708 109998 : bool Isolate::Init(StartupDeserializer* des) {
2709 : TRACE_ISOLATE(init);
2710 :
2711 54999 : stress_deopt_count_ = FLAG_deopt_every_n_times;
2712 :
2713 54999 : has_fatal_error_ = false;
2714 :
2715 : if (function_entry_hook() != nullptr) {
2716 : // When function entry hooking is in effect, we have to create the code
2717 : // stubs from scratch to get entry hooks, rather than loading the previously
2718 : // generated stubs from disk.
2719 : // If this assert fires, the initialization path has regressed.
2720 : DCHECK_NULL(des);
2721 : }
2722 :
2723 : // The initialization process does not handle memory exhaustion.
2724 : AlwaysAllocateScope always_allocate(this);
2725 :
2726 : // Safe after setting Heap::isolate_, and initializing StackGuard
2727 55030 : heap_.SetStackLimits();
2728 :
2729 : #define ASSIGN_ELEMENT(CamelName, hacker_name) \
2730 : isolate_addresses_[IsolateAddressId::k##CamelName##Address] = \
2731 : reinterpret_cast<Address>(hacker_name##_address());
2732 54998 : FOR_EACH_ISOLATE_ADDRESS_NAME(ASSIGN_ELEMENT)
2733 : #undef ASSIGN_ELEMENT
2734 :
2735 54998 : compilation_cache_ = new CompilationCache(this);
2736 109998 : context_slot_cache_ = new ContextSlotCache();
2737 109998 : descriptor_lookup_cache_ = new DescriptorLookupCache();
2738 54999 : unicode_cache_ = new UnicodeCache();
2739 54999 : inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this);
2740 54999 : global_handles_ = new GlobalHandles(this);
2741 54999 : eternal_handles_ = new EternalHandles();
2742 54999 : bootstrapper_ = new Bootstrapper(this);
2743 109998 : handle_scope_implementer_ = new HandleScopeImplementer(this);
2744 54999 : load_stub_cache_ = new StubCache(this);
2745 54999 : store_stub_cache_ = new StubCache(this);
2746 109998 : materialized_object_store_ = new MaterializedObjectStore(this);
2747 54999 : regexp_stack_ = new RegExpStack();
2748 54999 : regexp_stack_->isolate_ = this;
2749 54999 : date_cache_ = new DateCache();
2750 : call_descriptor_data_ =
2751 5994862 : new CallInterfaceDescriptorData[CallDescriptors::NUMBER_OF_DESCRIPTORS];
2752 109998 : access_compiler_data_ = new AccessCompilerData();
2753 54999 : cpu_profiler_ = new CpuProfiler(this);
2754 54999 : heap_profiler_ = new HeapProfiler(heap());
2755 54999 : interpreter_ = new interpreter::Interpreter(this);
2756 : compiler_dispatcher_ =
2757 54999 : new CompilerDispatcher(this, V8::GetCurrentPlatform(), FLAG_stack_size);
2758 :
2759 : // Enable logging before setting up the heap
2760 54999 : logger_->SetUp(this);
2761 :
2762 : // Initialize other runtime facilities
2763 : #if defined(USE_SIMULATOR)
2764 : #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_MIPS || \
2765 : V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390
2766 : Simulator::Initialize(this);
2767 : #endif
2768 : #endif
2769 :
2770 : { // NOLINT
2771 : // Ensure that the thread has a valid stack guard. The v8::Locker object
2772 : // will ensure this too, but we don't have to use lockers if we are only
2773 : // using one thread.
2774 : ExecutionAccess lock(this);
2775 54998 : stack_guard_.InitThread(lock);
2776 : }
2777 :
2778 : // SetUp the object heap.
2779 : DCHECK(!heap_.HasBeenSetUp());
2780 54999 : if (!heap_.SetUp()) {
2781 0 : V8::FatalProcessOutOfMemory("heap setup");
2782 0 : return false;
2783 : }
2784 :
2785 : // Initialize the interface descriptors ahead of time.
2786 : #define INTERFACE_DESCRIPTOR(Name, ...) \
2787 : { Name##Descriptor(this); }
2788 5939892 : INTERFACE_DESCRIPTOR_LIST(INTERFACE_DESCRIPTOR)
2789 : #undef INTERFACE_DESCRIPTOR
2790 :
2791 54999 : deoptimizer_data_ = new DeoptimizerData(heap()->memory_allocator());
2792 :
2793 54999 : const bool create_heap_objects = (des == nullptr);
2794 54999 : if (setup_delegate_ == nullptr) {
2795 109688 : setup_delegate_ = new SetupIsolateDelegate(create_heap_objects);
2796 : }
2797 :
2798 54999 : if (!setup_delegate_->SetupHeap(&heap_)) {
2799 0 : V8::FatalProcessOutOfMemory("heap object creation");
2800 0 : return false;
2801 : }
2802 :
2803 54999 : if (create_heap_objects) {
2804 : // Terminate the partial snapshot cache so we can iterate.
2805 62 : partial_snapshot_cache_.push_back(heap_.undefined_value());
2806 : }
2807 :
2808 : InitializeThreadLocal();
2809 :
2810 54999 : bootstrapper_->Initialize(create_heap_objects);
2811 54999 : setup_delegate_->SetupBuiltins(this);
2812 54999 : if (create_heap_objects) heap_.CreateFixedStubs();
2813 :
2814 54999 : if (FLAG_log_internal_timer_events) {
2815 : set_event_logger(Logger::DefaultEventLoggerSentinel);
2816 : }
2817 :
2818 54999 : if (FLAG_trace_turbo || FLAG_trace_turbo_graph) {
2819 0 : PrintF("Concurrent recompilation has been disabled for tracing.\n");
2820 54999 : } else if (OptimizingCompileDispatcher::Enabled()) {
2821 54876 : optimizing_compile_dispatcher_ = new OptimizingCompileDispatcher(this);
2822 : }
2823 :
2824 : // Initialize runtime profiler before deserialization, because collections may
2825 : // occur, clearing/updating ICs.
2826 54999 : runtime_profiler_ = new RuntimeProfiler(this);
2827 :
2828 : // If we are deserializing, read the state into the now-empty heap.
2829 : {
2830 : AlwaysAllocateScope always_allocate(this);
2831 :
2832 54999 : if (!create_heap_objects) des->DeserializeInto(this);
2833 54999 : load_stub_cache_->Initialize();
2834 54999 : store_stub_cache_->Initialize();
2835 54999 : setup_delegate_->SetupInterpreter(interpreter_);
2836 :
2837 54999 : heap_.NotifyDeserializationComplete();
2838 : }
2839 54999 : delete setup_delegate_;
2840 54999 : setup_delegate_ = nullptr;
2841 :
2842 : if (FLAG_print_builtin_size) PrintBuiltinSizes(this);
2843 :
2844 : // Finish initialization of ThreadLocal after deserialization is done.
2845 : clear_pending_exception();
2846 : clear_pending_message();
2847 : clear_scheduled_exception();
2848 :
2849 : // Deserializing may put strange things in the root array's copy of the
2850 : // stack guard.
2851 54999 : heap_.SetStackLimits();
2852 :
2853 : // Quiet the heap NaN if needed on target platform.
2854 : if (!create_heap_objects) Assembler::QuietNaN(heap_.nan_value());
2855 :
2856 54999 : if (FLAG_trace_turbo) {
2857 : // Create an empty file.
2858 0 : std::ofstream(GetTurboCfgFileName().c_str(), std::ios_base::trunc);
2859 : }
2860 :
2861 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)),
2862 : Internals::kIsolateEmbedderDataOffset);
2863 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)),
2864 : Internals::kIsolateRootsOffset);
2865 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_)),
2866 : Internals::kExternalMemoryOffset);
2867 : CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_limit_)),
2868 : Internals::kExternalMemoryLimitOffset);
2869 : CHECK_EQ(static_cast<int>(
2870 : OFFSET_OF(Isolate, heap_.external_memory_at_last_mark_compact_)),
2871 : Internals::kExternalMemoryAtLastMarkCompactOffset);
2872 :
2873 54999 : time_millis_at_init_ = heap_.MonotonicallyIncreasingTimeInMs();
2874 :
2875 : {
2876 : HandleScope scope(this);
2877 54999 : ast_string_constants_ = new AstStringConstants(this, heap()->HashSeed());
2878 : }
2879 :
2880 54999 : if (!serializer_enabled()) {
2881 : // Ensure that all stubs which need to be generated ahead of time, but
2882 : // cannot be serialized into the snapshot have been generated.
2883 : HandleScope scope(this);
2884 54848 : CodeStub::GenerateFPStubs(this);
2885 54848 : StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(this);
2886 : }
2887 :
2888 54999 : initialized_from_snapshot_ = (des != nullptr);
2889 :
2890 54999 : if (!FLAG_inline_new) heap_.DisableInlineAllocation();
2891 :
2892 : return true;
2893 : }
2894 :
2895 :
2896 185565 : void Isolate::Enter() {
2897 : Isolate* current_isolate = nullptr;
2898 : PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
2899 185564 : if (current_data != nullptr) {
2900 9524 : current_isolate = current_data->isolate_;
2901 : DCHECK_NOT_NULL(current_isolate);
2902 9524 : if (current_isolate == this) {
2903 : DCHECK(Current() == this);
2904 : DCHECK_NOT_NULL(entry_stack_);
2905 : DCHECK(entry_stack_->previous_thread_data == nullptr ||
2906 : entry_stack_->previous_thread_data->thread_id().Equals(
2907 : ThreadId::Current()));
2908 : // Same thread re-enters the isolate, no need to re-init anything.
2909 7811 : entry_stack_->entry_count++;
2910 193364 : return;
2911 : }
2912 : }
2913 :
2914 177753 : PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
2915 : DCHECK_NOT_NULL(data);
2916 : DCHECK(data->isolate_ == this);
2917 :
2918 : EntryStackItem* item = new EntryStackItem(current_data,
2919 : current_isolate,
2920 177755 : entry_stack_);
2921 177754 : entry_stack_ = item;
2922 :
2923 177754 : SetIsolateThreadLocals(this, data);
2924 :
2925 : // In case it's the first time some thread enters the isolate.
2926 : set_thread_id(data->thread_id());
2927 : }
2928 :
2929 :
2930 185548 : void Isolate::Exit() {
2931 : DCHECK_NOT_NULL(entry_stack_);
2932 : DCHECK(entry_stack_->previous_thread_data == nullptr ||
2933 : entry_stack_->previous_thread_data->thread_id().Equals(
2934 : ThreadId::Current()));
2935 :
2936 371096 : if (--entry_stack_->entry_count > 0) return;
2937 :
2938 : DCHECK_NOT_NULL(CurrentPerIsolateThreadData());
2939 : DCHECK(CurrentPerIsolateThreadData()->isolate_ == this);
2940 :
2941 : // Pop the stack.
2942 177736 : EntryStackItem* item = entry_stack_;
2943 177736 : entry_stack_ = item->previous_item;
2944 :
2945 177736 : PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
2946 177736 : Isolate* previous_isolate = item->previous_isolate;
2947 :
2948 177736 : delete item;
2949 :
2950 : // Reinit the current thread for the isolate it was running before this one.
2951 177736 : SetIsolateThreadLocals(previous_isolate, previous_thread_data);
2952 : }
2953 :
2954 :
2955 9393 : void Isolate::LinkDeferredHandles(DeferredHandles* deferred) {
2956 9393 : deferred->next_ = deferred_handles_head_;
2957 9393 : if (deferred_handles_head_ != nullptr) {
2958 2853 : deferred_handles_head_->previous_ = deferred;
2959 : }
2960 9393 : deferred_handles_head_ = deferred;
2961 9393 : }
2962 :
2963 :
2964 9390 : void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) {
2965 : #ifdef DEBUG
2966 : // In debug mode assert that the linked list is well-formed.
2967 : DeferredHandles* deferred_iterator = deferred;
2968 : while (deferred_iterator->previous_ != nullptr) {
2969 : deferred_iterator = deferred_iterator->previous_;
2970 : }
2971 : DCHECK(deferred_handles_head_ == deferred_iterator);
2972 : #endif
2973 9390 : if (deferred_handles_head_ == deferred) {
2974 6844 : deferred_handles_head_ = deferred_handles_head_->next_;
2975 : }
2976 9390 : if (deferred->next_ != nullptr) {
2977 579 : deferred->next_->previous_ = deferred->previous_;
2978 : }
2979 9390 : if (deferred->previous_ != nullptr) {
2980 2546 : deferred->previous_->next_ = deferred->next_;
2981 : }
2982 9390 : }
2983 :
2984 53365 : void Isolate::DumpAndResetStats() {
2985 53365 : if (turbo_statistics() != nullptr) {
2986 : DCHECK(FLAG_turbo_stats || FLAG_turbo_stats_nvp);
2987 :
2988 0 : OFStream os(stdout);
2989 0 : if (FLAG_turbo_stats) {
2990 0 : AsPrintableStatistics ps = {*turbo_statistics(), false};
2991 0 : os << ps << std::endl;
2992 : }
2993 0 : if (FLAG_turbo_stats_nvp) {
2994 0 : AsPrintableStatistics ps = {*turbo_statistics(), true};
2995 0 : os << ps << std::endl;
2996 0 : }
2997 : }
2998 53365 : delete turbo_statistics_;
2999 53365 : turbo_statistics_ = nullptr;
3000 53365 : if (V8_UNLIKELY(FLAG_runtime_stats ==
3001 : v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) {
3002 0 : OFStream os(stdout);
3003 0 : counters()->runtime_call_stats()->Print(os);
3004 0 : counters()->runtime_call_stats()->Reset();
3005 : }
3006 53365 : }
3007 :
3008 :
3009 0 : CompilationStatistics* Isolate::GetTurboStatistics() {
3010 0 : if (turbo_statistics() == nullptr)
3011 0 : set_turbo_statistics(new CompilationStatistics());
3012 0 : return turbo_statistics();
3013 : }
3014 :
3015 :
3016 0 : CodeTracer* Isolate::GetCodeTracer() {
3017 0 : if (code_tracer() == nullptr) set_code_tracer(new CodeTracer(id()));
3018 0 : return code_tracer();
3019 : }
3020 :
3021 293577 : bool Isolate::use_optimizer() {
3022 187196 : return FLAG_opt && !serializer_enabled_ &&
3023 187168 : CpuFeatures::SupportsCrankshaft() &&
3024 480745 : !is_precise_count_code_coverage() && !is_block_count_code_coverage();
3025 : }
3026 :
3027 3156307 : bool Isolate::NeedsSourcePositionsForProfiling() const {
3028 1578145 : return FLAG_trace_deopt || FLAG_trace_turbo || FLAG_trace_turbo_graph ||
3029 4734099 : FLAG_turbo_profiling || FLAG_perf_prof || is_profiling() ||
3030 4687857 : debug_->is_active() || logger_->is_logging();
3031 : }
3032 :
3033 1631 : void Isolate::SetFeedbackVectorsForProfilingTools(Object* value) {
3034 : DCHECK(value->IsUndefined(this) || value->IsArrayList());
3035 : heap()->set_feedback_vectors_for_profiling_tools(value);
3036 1631 : }
3037 :
3038 184 : void Isolate::InitializeVectorListFromHeap() {
3039 : // Collect existing feedback vectors.
3040 : std::vector<Handle<FeedbackVector>> vectors;
3041 : {
3042 184 : HeapIterator heap_iterator(heap());
3043 1719682 : while (HeapObject* current_obj = heap_iterator.next()) {
3044 1719498 : if (current_obj->IsSharedFunctionInfo()) {
3045 : SharedFunctionInfo* shared = SharedFunctionInfo::cast(current_obj);
3046 167605 : shared->set_has_reported_binary_coverage(false);
3047 1551893 : } else if (current_obj->IsFeedbackVector()) {
3048 23018 : FeedbackVector* vector = FeedbackVector::cast(current_obj);
3049 : SharedFunctionInfo* shared = vector->shared_function_info();
3050 45383 : if (!shared->IsSubjectToDebugging()) continue;
3051 653 : vector->clear_invocation_count();
3052 653 : vectors.emplace_back(vector, this);
3053 1528875 : } else if (current_obj->IsJSFunction()) {
3054 : JSFunction* function = JSFunction::cast(current_obj);
3055 172134 : function->set_code(function->shared()->code());
3056 : }
3057 184 : }
3058 : }
3059 :
3060 : // Add collected feedback vectors to the root list lest we lose them to
3061 : // GC.
3062 : Handle<ArrayList> list =
3063 368 : ArrayList::New(this, static_cast<int>(vectors.size()));
3064 1674 : for (const auto& vector : vectors) list = ArrayList::Add(list, vector);
3065 : SetFeedbackVectorsForProfilingTools(*list);
3066 184 : }
3067 :
3068 15638 : bool Isolate::IsArrayOrObjectPrototype(Object* object) {
3069 15638 : Object* context = heap()->native_contexts_list();
3070 56527 : while (!context->IsUndefined(this)) {
3071 : Context* current_context = Context::cast(context);
3072 51522 : if (current_context->initial_object_prototype() == object ||
3073 : current_context->initial_array_prototype() == object) {
3074 : return true;
3075 : }
3076 : context = current_context->next_context_link();
3077 : }
3078 : return false;
3079 : }
3080 :
3081 6357186 : bool Isolate::IsInAnyContext(Object* object, uint32_t index) {
3082 : DisallowHeapAllocation no_gc;
3083 6357186 : Object* context = heap()->native_contexts_list();
3084 24969190 : while (!context->IsUndefined(this)) {
3085 : Context* current_context = Context::cast(context);
3086 24519164 : if (current_context->get(index) == object) {
3087 : return true;
3088 : }
3089 : context = current_context->next_context_link();
3090 : }
3091 : return false;
3092 : }
3093 :
3094 33536 : bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
3095 49777 : PropertyCell* no_elements_cell = heap()->array_protector();
3096 : bool cell_reports_intact =
3097 99554 : no_elements_cell->value()->IsSmi() &&
3098 : Smi::ToInt(no_elements_cell->value()) == kProtectorValid;
3099 :
3100 : #ifdef DEBUG
3101 : Map* root_array_map =
3102 : raw_native_context()->GetInitialJSArrayMap(GetInitialFastElementsKind());
3103 : Context* native_context = context()->native_context();
3104 : JSObject* initial_array_proto = JSObject::cast(
3105 : native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
3106 : JSObject* initial_object_proto = JSObject::cast(
3107 : native_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX));
3108 :
3109 : if (root_array_map == nullptr ||
3110 : initial_array_proto == initial_object_proto) {
3111 : // We are in the bootstrapping process, and the entire check sequence
3112 : // shouldn't be performed.
3113 : return cell_reports_intact;
3114 : }
3115 :
3116 : // Check that the array prototype hasn't been altered WRT empty elements.
3117 : if (root_array_map->prototype() != initial_array_proto) {
3118 : DCHECK_EQ(false, cell_reports_intact);
3119 : return cell_reports_intact;
3120 : }
3121 :
3122 : FixedArrayBase* elements = initial_array_proto->elements();
3123 : if (elements != heap()->empty_fixed_array() &&
3124 : elements != heap()->empty_slow_element_dictionary()) {
3125 : DCHECK_EQ(false, cell_reports_intact);
3126 : return cell_reports_intact;
3127 : }
3128 :
3129 : // Check that the object prototype hasn't been altered WRT empty elements.
3130 : PrototypeIterator iter(this, initial_array_proto);
3131 : if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) {
3132 : DCHECK_EQ(false, cell_reports_intact);
3133 : return cell_reports_intact;
3134 : }
3135 :
3136 : elements = initial_object_proto->elements();
3137 : if (elements != heap()->empty_fixed_array() &&
3138 : elements != heap()->empty_slow_element_dictionary()) {
3139 : DCHECK_EQ(false, cell_reports_intact);
3140 : return cell_reports_intact;
3141 : }
3142 :
3143 : iter.Advance();
3144 : if (!iter.IsAtEnd()) {
3145 : DCHECK_EQ(false, cell_reports_intact);
3146 : return cell_reports_intact;
3147 : }
3148 :
3149 : #endif
3150 :
3151 33536 : return cell_reports_intact;
3152 : }
3153 :
3154 302957 : bool Isolate::IsIsConcatSpreadableLookupChainIntact() {
3155 313255 : Cell* is_concat_spreadable_cell = heap()->is_concat_spreadable_protector();
3156 : bool is_is_concat_spreadable_set =
3157 : Smi::ToInt(is_concat_spreadable_cell->value()) == kProtectorInvalid;
3158 : #ifdef DEBUG
3159 : Map* root_array_map =
3160 : raw_native_context()->GetInitialJSArrayMap(GetInitialFastElementsKind());
3161 : if (root_array_map == nullptr) {
3162 : // Ignore the value of is_concat_spreadable during bootstrap.
3163 : return !is_is_concat_spreadable_set;
3164 : }
3165 : Handle<Object> array_prototype(array_function()->prototype(), this);
3166 : Handle<Symbol> key = factory()->is_concat_spreadable_symbol();
3167 : Handle<Object> value;
3168 : LookupIterator it(array_prototype, key);
3169 : if (it.IsFound() && !JSReceiver::GetDataProperty(&it)->IsUndefined(this)) {
3170 : // TODO(cbruni): Currently we do not revert if we unset the
3171 : // @@isConcatSpreadable property on Array.prototype or Object.prototype
3172 : // hence the reverse implication doesn't hold.
3173 : DCHECK(is_is_concat_spreadable_set);
3174 : return false;
3175 : }
3176 : #endif // DEBUG
3177 :
3178 302957 : return !is_is_concat_spreadable_set;
3179 : }
3180 :
3181 10298 : bool Isolate::IsIsConcatSpreadableLookupChainIntact(JSReceiver* receiver) {
3182 10298 : if (!IsIsConcatSpreadableLookupChainIntact()) return false;
3183 4247 : return !receiver->HasProxyInPrototype(this);
3184 : }
3185 :
3186 3750138 : void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
3187 : DisallowHeapAllocation no_gc;
3188 3750138 : if (!object->map()->is_prototype_map()) return;
3189 16241 : if (!IsFastArrayConstructorPrototypeChainIntact()) return;
3190 15638 : if (!IsArrayOrObjectPrototype(*object)) return;
3191 : PropertyCell::SetValueWithInvalidation(
3192 : factory()->array_protector(),
3193 574 : handle(Smi::FromInt(kProtectorInvalid), this));
3194 : }
3195 :
3196 58 : void Isolate::InvalidateIsConcatSpreadableProtector() {
3197 : DCHECK(factory()->is_concat_spreadable_protector()->value()->IsSmi());
3198 : DCHECK(IsIsConcatSpreadableLookupChainIntact());
3199 : factory()->is_concat_spreadable_protector()->set_value(
3200 58 : Smi::FromInt(kProtectorInvalid));
3201 : DCHECK(!IsIsConcatSpreadableLookupChainIntact());
3202 58 : }
3203 :
3204 216 : void Isolate::InvalidateArrayConstructorProtector() {
3205 : DCHECK(factory()->array_constructor_protector()->value()->IsSmi());
3206 : DCHECK(IsArrayConstructorIntact());
3207 : factory()->array_constructor_protector()->set_value(
3208 216 : Smi::FromInt(kProtectorInvalid));
3209 : DCHECK(!IsArrayConstructorIntact());
3210 216 : }
3211 :
3212 81 : void Isolate::InvalidateArraySpeciesProtector() {
3213 : DCHECK(factory()->species_protector()->value()->IsSmi());
3214 : DCHECK(IsArraySpeciesLookupChainIntact());
3215 81 : factory()->species_protector()->set_value(Smi::FromInt(kProtectorInvalid));
3216 : DCHECK(!IsArraySpeciesLookupChainIntact());
3217 81 : }
3218 :
3219 142 : void Isolate::InvalidateStringLengthOverflowProtector() {
3220 : DCHECK(factory()->string_length_protector()->value()->IsSmi());
3221 : DCHECK(IsStringLengthOverflowIntact());
3222 : factory()->string_length_protector()->set_value(
3223 142 : Smi::FromInt(kProtectorInvalid));
3224 : DCHECK(!IsStringLengthOverflowIntact());
3225 142 : }
3226 :
3227 46 : void Isolate::InvalidateArrayIteratorProtector() {
3228 : DCHECK(factory()->array_iterator_protector()->value()->IsSmi());
3229 : DCHECK(IsArrayIteratorLookupChainIntact());
3230 : PropertyCell::SetValueWithInvalidation(
3231 : factory()->array_iterator_protector(),
3232 46 : handle(Smi::FromInt(kProtectorInvalid), this));
3233 : DCHECK(!IsArrayIteratorLookupChainIntact());
3234 46 : }
3235 :
3236 236 : void Isolate::InvalidateArrayBufferNeuteringProtector() {
3237 : DCHECK(factory()->array_buffer_neutering_protector()->value()->IsSmi());
3238 : DCHECK(IsArrayBufferNeuteringIntact());
3239 : PropertyCell::SetValueWithInvalidation(
3240 : factory()->array_buffer_neutering_protector(),
3241 236 : handle(Smi::FromInt(kProtectorInvalid), this));
3242 : DCHECK(!IsArrayBufferNeuteringIntact());
3243 236 : }
3244 :
3245 6265252 : bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) {
3246 : DisallowHeapAllocation no_gc;
3247 6265252 : return IsInAnyContext(*array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
3248 : }
3249 :
3250 :
3251 5829226 : CallInterfaceDescriptorData* Isolate::call_descriptor_data(int index) {
3252 : DCHECK(0 <= index && index < CallDescriptors::NUMBER_OF_DESCRIPTORS);
3253 17709006 : return &call_descriptor_data_[index];
3254 : }
3255 :
3256 :
3257 291299 : base::RandomNumberGenerator* Isolate::random_number_generator() {
3258 291299 : if (random_number_generator_ == nullptr) {
3259 54979 : if (FLAG_random_seed != 0) {
3260 : random_number_generator_ =
3261 109956 : new base::RandomNumberGenerator(FLAG_random_seed);
3262 : } else {
3263 1 : random_number_generator_ = new base::RandomNumberGenerator();
3264 : }
3265 : }
3266 291299 : return random_number_generator_;
3267 : }
3268 :
3269 26949 : int Isolate::GenerateIdentityHash(uint32_t mask) {
3270 : int hash;
3271 : int attempts = 0;
3272 26949 : do {
3273 53898 : hash = random_number_generator()->NextInt() & mask;
3274 26949 : } while (hash == 0 && attempts++ < 30);
3275 26949 : return hash != 0 ? hash : 1;
3276 : }
3277 :
3278 25698 : Code* Isolate::FindCodeObject(Address a) {
3279 25698 : return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a);
3280 : }
3281 :
3282 :
3283 : #ifdef DEBUG
3284 : #define ISOLATE_FIELD_OFFSET(type, name, ignored) \
3285 : const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
3286 : ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
3287 : ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
3288 : #undef ISOLATE_FIELD_OFFSET
3289 : #endif
3290 :
3291 9635019 : Handle<Symbol> Isolate::SymbolFor(Heap::RootListIndex dictionary_index,
3292 : Handle<String> name, bool private_symbol) {
3293 9635019 : Handle<String> key = factory()->InternalizeString(name);
3294 : Handle<NameDictionary> dictionary =
3295 : Handle<NameDictionary>::cast(heap()->root_handle(dictionary_index));
3296 9635019 : int entry = dictionary->FindEntry(key);
3297 : Handle<Symbol> symbol;
3298 9635019 : if (entry == NameDictionary::kNotFound) {
3299 : symbol =
3300 5571 : private_symbol ? factory()->NewPrivateSymbol() : factory()->NewSymbol();
3301 5571 : symbol->set_name(*key);
3302 : dictionary = NameDictionary::Add(dictionary, key, symbol,
3303 5571 : PropertyDetails::Empty(), &entry);
3304 5571 : switch (dictionary_index) {
3305 : case Heap::kPublicSymbolTableRootIndex:
3306 51 : symbol->set_is_public(true);
3307 : heap()->set_public_symbol_table(*dictionary);
3308 : break;
3309 : case Heap::kApiSymbolTableRootIndex:
3310 : heap()->set_api_symbol_table(*dictionary);
3311 : break;
3312 : case Heap::kApiPrivateSymbolTableRootIndex:
3313 : heap()->set_api_private_symbol_table(*dictionary);
3314 : break;
3315 : default:
3316 0 : UNREACHABLE();
3317 : }
3318 : } else {
3319 9629448 : symbol = Handle<Symbol>(Symbol::cast(dictionary->ValueAt(entry)));
3320 : }
3321 9635019 : return symbol;
3322 : }
3323 :
3324 15 : void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) {
3325 : auto pos = std::find(before_call_entered_callbacks_.begin(),
3326 : before_call_entered_callbacks_.end(), callback);
3327 30 : if (pos != before_call_entered_callbacks_.end()) return;
3328 10 : before_call_entered_callbacks_.push_back(callback);
3329 : }
3330 :
3331 5 : void Isolate::RemoveBeforeCallEnteredCallback(
3332 : BeforeCallEnteredCallback callback) {
3333 : auto pos = std::find(before_call_entered_callbacks_.begin(),
3334 : before_call_entered_callbacks_.end(), callback);
3335 10 : if (pos == before_call_entered_callbacks_.end()) return;
3336 5 : before_call_entered_callbacks_.erase(pos);
3337 : }
3338 :
3339 25 : void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
3340 : auto pos = std::find(call_completed_callbacks_.begin(),
3341 : call_completed_callbacks_.end(), callback);
3342 50 : if (pos != call_completed_callbacks_.end()) return;
3343 20 : call_completed_callbacks_.push_back(callback);
3344 : }
3345 :
3346 5 : void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
3347 : auto pos = std::find(call_completed_callbacks_.begin(),
3348 : call_completed_callbacks_.end(), callback);
3349 10 : if (pos == call_completed_callbacks_.end()) return;
3350 5 : call_completed_callbacks_.erase(pos);
3351 : }
3352 :
3353 5 : void Isolate::AddMicrotasksCompletedCallback(
3354 : MicrotasksCompletedCallback callback) {
3355 : auto pos = std::find(microtasks_completed_callbacks_.begin(),
3356 : microtasks_completed_callbacks_.end(), callback);
3357 10 : if (pos != microtasks_completed_callbacks_.end()) return;
3358 5 : microtasks_completed_callbacks_.push_back(callback);
3359 : }
3360 :
3361 5 : void Isolate::RemoveMicrotasksCompletedCallback(
3362 : MicrotasksCompletedCallback callback) {
3363 : auto pos = std::find(microtasks_completed_callbacks_.begin(),
3364 : microtasks_completed_callbacks_.end(), callback);
3365 10 : if (pos == microtasks_completed_callbacks_.end()) return;
3366 5 : microtasks_completed_callbacks_.erase(pos);
3367 : }
3368 :
3369 11175018 : void Isolate::FireCallCompletedCallback() {
3370 21434142 : if (!handle_scope_implementer()->CallDepthIsZero()) return;
3371 :
3372 : bool run_microtasks =
3373 20846 : pending_microtask_count() &&
3374 478782 : !handle_scope_implementer()->HasMicrotasksSuppressions() &&
3375 20846 : handle_scope_implementer()->microtasks_policy() ==
3376 : v8::MicrotasksPolicy::kAuto;
3377 :
3378 457936 : if (run_microtasks) RunMicrotasks();
3379 :
3380 457939 : if (call_completed_callbacks_.empty()) return;
3381 : // Fire callbacks. Increase call depth to prevent recursive callbacks.
3382 : v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this);
3383 25 : v8::Isolate::SuppressMicrotaskExecutionScope suppress(isolate);
3384 80 : for (auto& callback : call_completed_callbacks_) {
3385 30 : callback(reinterpret_cast<v8::Isolate*>(this));
3386 25 : }
3387 : }
3388 :
3389 664437 : void Isolate::DebugStateUpdated() {
3390 664459 : promise_hook_or_debug_is_active_ = promise_hook_ || debug()->is_active();
3391 332213 : }
3392 :
3393 : namespace {
3394 :
3395 130 : MaybeHandle<JSPromise> NewRejectedPromise(Isolate* isolate,
3396 : v8::Local<v8::Context> api_context,
3397 : Handle<Object> exception) {
3398 : v8::Local<v8::Promise::Resolver> resolver;
3399 336 : ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
3400 : isolate, resolver, v8::Promise::Resolver::New(api_context),
3401 : MaybeHandle<JSPromise>());
3402 :
3403 54 : RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
3404 : isolate, resolver->Reject(api_context, v8::Utils::ToLocal(exception)),
3405 : MaybeHandle<JSPromise>());
3406 :
3407 54 : v8::Local<v8::Promise> promise = resolver->GetPromise();
3408 54 : return v8::Utils::OpenHandle(*promise);
3409 : }
3410 :
3411 : } // namespace
3412 :
3413 587 : MaybeHandle<JSPromise> Isolate::RunHostImportModuleDynamicallyCallback(
3414 130 : Handle<Script> referrer, Handle<Object> specifier) {
3415 587 : v8::Local<v8::Context> api_context = v8::Utils::ToLocal(native_context());
3416 :
3417 587 : if (host_import_module_dynamically_callback_ == nullptr) {
3418 : Handle<Object> exception =
3419 0 : factory()->NewError(error_function(), MessageTemplate::kUnsupported);
3420 0 : return NewRejectedPromise(this, api_context, exception);
3421 : }
3422 :
3423 : Handle<String> specifier_str;
3424 587 : MaybeHandle<String> maybe_specifier = Object::ToString(this, specifier);
3425 587 : if (!maybe_specifier.ToHandle(&specifier_str)) {
3426 : Handle<Object> exception(pending_exception(), this);
3427 : clear_pending_exception();
3428 :
3429 130 : return NewRejectedPromise(this, api_context, exception);
3430 : }
3431 : DCHECK(!has_pending_exception());
3432 :
3433 : v8::Local<v8::Promise> promise;
3434 1020 : ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
3435 : this, promise,
3436 : host_import_module_dynamically_callback_(
3437 : api_context, v8::Utils::ScriptOrModuleToLocal(referrer),
3438 : v8::Utils::ToLocal(specifier_str)),
3439 : MaybeHandle<JSPromise>());
3440 351 : return v8::Utils::OpenHandle(*promise);
3441 : }
3442 :
3443 27400 : void Isolate::SetHostImportModuleDynamicallyCallback(
3444 : HostImportModuleDynamicallyCallback callback) {
3445 27400 : host_import_module_dynamically_callback_ = callback;
3446 27400 : }
3447 :
3448 118 : Handle<JSObject> Isolate::RunHostInitializeImportMetaObjectCallback(
3449 : Handle<Module> module) {
3450 : Handle<Object> host_meta(module->import_meta(), this);
3451 118 : if (host_meta->IsTheHole(this)) {
3452 23 : host_meta = factory()->NewJSObjectWithNullProto();
3453 23 : if (host_initialize_import_meta_object_callback_ != nullptr) {
3454 23 : v8::Local<v8::Context> api_context = v8::Utils::ToLocal(native_context());
3455 : host_initialize_import_meta_object_callback_(
3456 : api_context, Utils::ToLocal(module),
3457 23 : v8::Local<v8::Object>::Cast(v8::Utils::ToLocal(host_meta)));
3458 : }
3459 23 : module->set_import_meta(*host_meta);
3460 : }
3461 118 : return Handle<JSObject>::cast(host_meta);
3462 : }
3463 :
3464 27400 : void Isolate::SetHostInitializeImportMetaObjectCallback(
3465 : HostInitializeImportMetaObjectCallback callback) {
3466 27400 : host_initialize_import_meta_object_callback_ = callback;
3467 27400 : }
3468 :
3469 22 : void Isolate::SetPromiseHook(PromiseHook hook) {
3470 22 : promise_hook_ = hook;
3471 : DebugStateUpdated();
3472 22 : }
3473 :
3474 117793 : void Isolate::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
3475 117793 : Handle<Object> parent) {
3476 117793 : if (debug()->is_active()) debug()->RunPromiseHook(type, promise, parent);
3477 235586 : if (promise_hook_ == nullptr) return;
3478 : promise_hook_(type, v8::Utils::PromiseToLocal(promise),
3479 285 : v8::Utils::ToLocal(parent));
3480 : }
3481 :
3482 813 : void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
3483 813 : promise_reject_callback_ = callback;
3484 813 : }
3485 :
3486 17685 : void Isolate::ReportPromiseReject(Handle<JSPromise> promise,
3487 : Handle<Object> value,
3488 : v8::PromiseRejectEvent event) {
3489 : DCHECK_EQ(v8::Promise::kRejected, promise->status());
3490 35370 : if (promise_reject_callback_ == nullptr) return;
3491 : Handle<FixedArray> stack_trace;
3492 560 : if (event == v8::kPromiseRejectWithNoHandler && value->IsJSObject()) {
3493 130 : stack_trace = GetDetailedStackTrace(Handle<JSObject>::cast(value));
3494 : }
3495 : promise_reject_callback_(v8::PromiseRejectMessage(
3496 : v8::Utils::PromiseToLocal(promise), event, v8::Utils::ToLocal(value),
3497 670 : v8::Utils::StackTraceToLocal(stack_trace)));
3498 : }
3499 :
3500 175557 : void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info,
3501 : MaybeHandle<Object>* result,
3502 : MaybeHandle<Object>* maybe_exception) {
3503 : Handle<Object> value(info->value(), this);
3504 : Handle<Object> tasks(info->tasks(), this);
3505 175557 : Handle<JSFunction> promise_handle_fn = promise_handle();
3506 : Handle<Object> undefined = factory()->undefined_value();
3507 : Handle<Object> deferred_promise(info->deferred_promise(), this);
3508 :
3509 175558 : if (deferred_promise->IsFixedArray()) {
3510 : DCHECK(tasks->IsFixedArray());
3511 : Handle<FixedArray> deferred_promise_arr =
3512 : Handle<FixedArray>::cast(deferred_promise);
3513 : Handle<FixedArray> deferred_on_resolve_arr(
3514 : FixedArray::cast(info->deferred_on_resolve()), this);
3515 : Handle<FixedArray> deferred_on_reject_arr(
3516 : FixedArray::cast(info->deferred_on_reject()), this);
3517 : Handle<FixedArray> tasks_arr = Handle<FixedArray>::cast(tasks);
3518 4618 : for (int i = 0; i < deferred_promise_arr->length(); i++) {
3519 : Handle<Object> argv[] = {value, handle(tasks_arr->get(i), this),
3520 : handle(deferred_promise_arr->get(i), this),
3521 : handle(deferred_on_resolve_arr->get(i), this),
3522 8840 : handle(deferred_on_reject_arr->get(i), this)};
3523 : *result = Execution::TryCall(
3524 : this, promise_handle_fn, undefined, arraysize(argv), argv,
3525 1768 : Execution::MessageHandling::kReport, maybe_exception);
3526 : // If execution is terminating, just bail out.
3527 1768 : if (result->is_null() && maybe_exception->is_null()) {
3528 175558 : return;
3529 : }
3530 : }
3531 : } else {
3532 : Handle<Object> argv[] = {value, tasks, deferred_promise,
3533 : handle(info->deferred_on_resolve(), this),
3534 525051 : handle(info->deferred_on_reject(), this)};
3535 : *result = Execution::TryCall(
3536 : this, promise_handle_fn, undefined, arraysize(argv), argv,
3537 175017 : Execution::MessageHandling::kReport, maybe_exception);
3538 : }
3539 : }
3540 :
3541 25662 : void Isolate::PromiseResolveThenableJob(
3542 : Handle<PromiseResolveThenableJobInfo> info, MaybeHandle<Object>* result,
3543 : MaybeHandle<Object>* maybe_exception) {
3544 : Handle<JSReceiver> thenable(info->thenable(), this);
3545 : Handle<JSFunction> resolve(info->resolve(), this);
3546 : Handle<JSFunction> reject(info->reject(), this);
3547 : Handle<JSReceiver> then(info->then(), this);
3548 : Handle<Object> argv[] = {resolve, reject};
3549 : *result =
3550 : Execution::TryCall(this, then, thenable, arraysize(argv), argv,
3551 25662 : Execution::MessageHandling::kReport, maybe_exception);
3552 :
3553 : Handle<Object> reason;
3554 25662 : if (maybe_exception->ToHandle(&reason)) {
3555 : DCHECK(result->is_null());
3556 18 : Handle<Object> reason_arg[] = {reason};
3557 : *result = Execution::TryCall(
3558 : this, reject, factory()->undefined_value(), arraysize(reason_arg),
3559 18 : reason_arg, Execution::MessageHandling::kReport, maybe_exception);
3560 : }
3561 25662 : }
3562 :
3563 403964 : void Isolate::EnqueueMicrotask(Handle<Object> microtask) {
3564 : DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo() ||
3565 : microtask->IsPromiseResolveThenableJobInfo() ||
3566 : microtask->IsPromiseReactionJobInfo());
3567 201982 : Handle<FixedArray> queue(heap()->microtask_queue(), this);
3568 : int num_tasks = pending_microtask_count();
3569 : DCHECK(num_tasks <= queue->length());
3570 201982 : if (num_tasks == 0) {
3571 186722 : queue = factory()->NewFixedArray(8);
3572 : heap()->set_microtask_queue(*queue);
3573 15260 : } else if (num_tasks == queue->length()) {
3574 173 : queue = factory()->CopyFixedArrayAndGrow(queue, num_tasks);
3575 : heap()->set_microtask_queue(*queue);
3576 : }
3577 : DCHECK(queue->get(num_tasks)->IsUndefined(this));
3578 201982 : queue->set(num_tasks, *microtask);
3579 201982 : set_pending_microtask_count(num_tasks + 1);
3580 201982 : }
3581 :
3582 :
3583 98323 : void Isolate::RunMicrotasks() {
3584 : // Increase call depth to prevent recursive callbacks.
3585 : v8::Isolate::SuppressMicrotaskExecutionScope suppress(
3586 98323 : reinterpret_cast<v8::Isolate*>(this));
3587 98322 : is_running_microtasks_ = true;
3588 98322 : RunMicrotasksInternal();
3589 98323 : is_running_microtasks_ = false;
3590 98323 : FireMicrotasksCompletedCallback();
3591 98322 : }
3592 :
3593 :
3594 313580 : void Isolate::RunMicrotasksInternal() {
3595 168103 : if (!pending_microtask_count()) return;
3596 57096 : TRACE_EVENT0("v8.execute", "RunMicrotasks");
3597 85638 : TRACE_EVENT_CALL_STATS_SCOPED(this, "v8", "V8.RunMicrotasks");
3598 215258 : while (pending_microtask_count() > 0) {
3599 : HandleScope scope(this);
3600 : int num_tasks = pending_microtask_count();
3601 : // Do not use factory()->microtask_queue() here; we need a fresh handle!
3602 186716 : Handle<FixedArray> queue(heap()->microtask_queue(), this);
3603 : DCHECK(num_tasks <= queue->length());
3604 : set_pending_microtask_count(0);
3605 186716 : heap()->set_microtask_queue(heap()->empty_fixed_array());
3606 :
3607 : Isolate* isolate = this;
3608 2173753 : FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < num_tasks, i++, {
3609 : Handle<Object> microtask(queue->get(i), this);
3610 :
3611 : if (microtask->IsCallHandlerInfo()) {
3612 : Handle<CallHandlerInfo> callback_info =
3613 : Handle<CallHandlerInfo>::cast(microtask);
3614 : v8::MicrotaskCallback callback =
3615 : v8::ToCData<v8::MicrotaskCallback>(callback_info->callback());
3616 : void* data = v8::ToCData<void*>(callback_info->data());
3617 : callback(data);
3618 : } else {
3619 : SaveContext save(this);
3620 : Context* context;
3621 : if (microtask->IsJSFunction()) {
3622 : context = Handle<JSFunction>::cast(microtask)->context();
3623 : } else if (microtask->IsPromiseResolveThenableJobInfo()) {
3624 : context =
3625 : Handle<PromiseResolveThenableJobInfo>::cast(microtask)->context();
3626 : } else {
3627 : context = Handle<PromiseReactionJobInfo>::cast(microtask)->context();
3628 : }
3629 :
3630 : set_context(context->native_context());
3631 : handle_scope_implementer_->EnterMicrotaskContext(
3632 : Handle<Context>(context, this));
3633 :
3634 : MaybeHandle<Object> result;
3635 : MaybeHandle<Object> maybe_exception;
3636 :
3637 : if (microtask->IsJSFunction()) {
3638 : Handle<JSFunction> microtask_function =
3639 : Handle<JSFunction>::cast(microtask);
3640 : result = Execution::TryCall(
3641 : this, microtask_function, factory()->undefined_value(), 0,
3642 : nullptr, Execution::MessageHandling::kReport, &maybe_exception);
3643 : } else if (microtask->IsPromiseResolveThenableJobInfo()) {
3644 : PromiseResolveThenableJob(
3645 : Handle<PromiseResolveThenableJobInfo>::cast(microtask), &result,
3646 : &maybe_exception);
3647 : } else {
3648 : PromiseReactionJob(Handle<PromiseReactionJobInfo>::cast(microtask),
3649 : &result, &maybe_exception);
3650 : }
3651 :
3652 : handle_scope_implementer_->LeaveMicrotaskContext();
3653 :
3654 : // If execution is terminating, just bail out.
3655 : if (result.is_null() && maybe_exception.is_null()) {
3656 : // Clear out any remaining callbacks in the queue.
3657 : heap()->set_microtask_queue(heap()->empty_fixed_array());
3658 : set_pending_microtask_count(0);
3659 : return;
3660 : }
3661 : }
3662 : });
3663 28542 : }
3664 : }
3665 :
3666 65 : void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) {
3667 : DCHECK(!use_counter_callback_);
3668 65 : use_counter_callback_ = callback;
3669 65 : }
3670 :
3671 :
3672 2485418 : void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) {
3673 : // The counter callback may cause the embedder to call into V8, which is not
3674 : // generally possible during GC.
3675 2485418 : if (heap_.gc_state() == Heap::NOT_IN_GC) {
3676 2485418 : if (use_counter_callback_) {
3677 : HandleScope handle_scope(this);
3678 518 : use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature);
3679 : }
3680 : } else {
3681 0 : heap_.IncrementDeferredCount(feature);
3682 : }
3683 2485418 : }
3684 :
3685 :
3686 12 : BasicBlockProfiler* Isolate::GetOrCreateBasicBlockProfiler() {
3687 12 : if (basic_block_profiler_ == nullptr) {
3688 12 : basic_block_profiler_ = new BasicBlockProfiler();
3689 : }
3690 12 : return basic_block_profiler_;
3691 : }
3692 :
3693 :
3694 0 : std::string Isolate::GetTurboCfgFileName() {
3695 0 : if (FLAG_trace_turbo_cfg_file == nullptr) {
3696 0 : std::ostringstream os;
3697 0 : os << "turbo-" << base::OS::GetCurrentProcessId() << "-" << id() << ".cfg";
3698 0 : return os.str();
3699 : } else {
3700 0 : return FLAG_trace_turbo_cfg_file;
3701 : }
3702 : }
3703 :
3704 : // Heap::detached_contexts tracks detached contexts as pairs
3705 : // (number of GC since the context was detached, the context).
3706 55 : void Isolate::AddDetachedContext(Handle<Context> context) {
3707 : HandleScope scope(this);
3708 55 : Handle<WeakCell> cell = factory()->NewWeakCell(context);
3709 : Handle<FixedArray> detached_contexts =
3710 55 : factory()->CopyFixedArrayAndGrow(factory()->detached_contexts(), 2);
3711 : int new_length = detached_contexts->length();
3712 : detached_contexts->set(new_length - 2, Smi::kZero);
3713 110 : detached_contexts->set(new_length - 1, *cell);
3714 : heap()->set_detached_contexts(*detached_contexts);
3715 55 : }
3716 :
3717 :
3718 56800 : void Isolate::CheckDetachedContextsAfterGC() {
3719 : HandleScope scope(this);
3720 : Handle<FixedArray> detached_contexts = factory()->detached_contexts();
3721 : int length = detached_contexts->length();
3722 113600 : if (length == 0) return;
3723 : int new_length = 0;
3724 12 : for (int i = 0; i < length; i += 2) {
3725 : int mark_sweeps = Smi::ToInt(detached_contexts->get(i));
3726 : DCHECK(detached_contexts->get(i + 1)->IsWeakCell());
3727 12 : WeakCell* cell = WeakCell::cast(detached_contexts->get(i + 1));
3728 12 : if (!cell->cleared()) {
3729 9 : detached_contexts->set(new_length, Smi::FromInt(mark_sweeps + 1));
3730 18 : detached_contexts->set(new_length + 1, cell);
3731 : new_length += 2;
3732 : }
3733 24 : counters()->detached_context_age_in_gc()->AddSample(mark_sweeps + 1);
3734 : }
3735 10 : if (FLAG_trace_detached_contexts) {
3736 : PrintF("%d detached contexts are collected out of %d\n",
3737 0 : length - new_length, length);
3738 0 : for (int i = 0; i < new_length; i += 2) {
3739 : int mark_sweeps = Smi::ToInt(detached_contexts->get(i));
3740 : DCHECK(detached_contexts->get(i + 1)->IsWeakCell());
3741 0 : WeakCell* cell = WeakCell::cast(detached_contexts->get(i + 1));
3742 0 : if (mark_sweeps > 3) {
3743 : PrintF("detached context %p\n survived %d GCs (leak?)\n",
3744 0 : static_cast<void*>(cell->value()), mark_sweeps);
3745 : }
3746 : }
3747 : }
3748 10 : if (new_length == 0) {
3749 2 : heap()->set_detached_contexts(heap()->empty_fixed_array());
3750 8 : } else if (new_length < length) {
3751 0 : heap()->RightTrimFixedArray(*detached_contexts, length - new_length);
3752 : }
3753 : }
3754 :
3755 0 : double Isolate::LoadStartTimeMs() {
3756 0 : base::LockGuard<base::Mutex> guard(&rail_mutex_);
3757 0 : return load_start_time_ms_;
3758 : }
3759 :
3760 0 : void Isolate::SetRAILMode(RAILMode rail_mode) {
3761 : RAILMode old_rail_mode = rail_mode_.Value();
3762 0 : if (old_rail_mode != PERFORMANCE_LOAD && rail_mode == PERFORMANCE_LOAD) {
3763 0 : base::LockGuard<base::Mutex> guard(&rail_mutex_);
3764 0 : load_start_time_ms_ = heap()->MonotonicallyIncreasingTimeInMs();
3765 : }
3766 : rail_mode_.SetValue(rail_mode);
3767 0 : if (old_rail_mode == PERFORMANCE_LOAD && rail_mode != PERFORMANCE_LOAD) {
3768 : heap()->incremental_marking()->incremental_marking_job()->ScheduleTask(
3769 0 : heap());
3770 : }
3771 0 : if (FLAG_trace_rail) {
3772 0 : PrintIsolate(this, "RAIL mode: %s\n", RAILModeName(rail_mode));
3773 : }
3774 0 : }
3775 :
3776 0 : void Isolate::IsolateInBackgroundNotification() {
3777 0 : is_isolate_in_background_ = true;
3778 0 : heap()->ActivateMemoryReducerIfNeeded();
3779 0 : }
3780 :
3781 0 : void Isolate::IsolateInForegroundNotification() {
3782 0 : is_isolate_in_background_ = false;
3783 0 : }
3784 :
3785 87 : void Isolate::PrintWithTimestamp(const char* format, ...) {
3786 : base::OS::Print("[%d:%p] %8.0f ms: ", base::OS::GetCurrentProcessId(),
3787 87 : static_cast<void*>(this), time_millis_since_init());
3788 : va_list arguments;
3789 87 : va_start(arguments, format);
3790 87 : base::OS::VPrint(format, arguments);
3791 87 : va_end(arguments);
3792 87 : }
3793 :
3794 7359495 : bool StackLimitCheck::JsHasOverflowed(uintptr_t gap) const {
3795 14718990 : StackGuard* stack_guard = isolate_->stack_guard();
3796 : #ifdef USE_SIMULATOR
3797 : // The simulator uses a separate JS stack.
3798 : Address jssp_address = Simulator::current(isolate_)->get_sp();
3799 : uintptr_t jssp = reinterpret_cast<uintptr_t>(jssp_address);
3800 : if (jssp - gap < stack_guard->real_jslimit()) return true;
3801 : #endif // USE_SIMULATOR
3802 14718990 : return GetCurrentStackPosition() - gap < stack_guard->real_climit();
3803 : }
3804 :
3805 76334694 : SaveContext::SaveContext(Isolate* isolate)
3806 50889796 : : isolate_(isolate), prev_(isolate->save_context()) {
3807 25444898 : if (isolate->context() != nullptr) {
3808 25228994 : context_ = Handle<Context>(isolate->context());
3809 : }
3810 : isolate->set_save_context(this);
3811 :
3812 25444907 : c_entry_fp_ = isolate->c_entry_fp(isolate->thread_local_top());
3813 25444907 : }
3814 :
3815 25243318 : SaveContext::~SaveContext() {
3816 50889864 : isolate_->set_context(context_.is_null() ? nullptr : *context_);
3817 25444932 : isolate_->set_save_context(prev_);
3818 25243318 : }
3819 :
3820 120822 : bool SaveContext::IsBelowFrame(StandardFrame* frame) {
3821 120822 : return (c_entry_fp_ == 0) || (c_entry_fp_ > frame->sp());
3822 : }
3823 :
3824 : #ifdef DEBUG
3825 : AssertNoContextChange::AssertNoContextChange(Isolate* isolate)
3826 : : isolate_(isolate), context_(isolate->context(), isolate) {}
3827 : #endif // DEBUG
3828 :
3829 :
3830 39427 : bool PostponeInterruptsScope::Intercept(StackGuard::InterruptFlag flag) {
3831 : // First check whether the previous scope intercepts.
3832 39427 : if (prev_ && prev_->Intercept(flag)) return true;
3833 : // Then check whether this scope intercepts.
3834 34136 : if ((flag & intercept_mask_)) {
3835 19907 : intercepted_flags_ |= flag;
3836 19907 : return true;
3837 : }
3838 : return false;
3839 : }
3840 :
3841 : } // namespace internal
3842 : } // namespace v8
|