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