Line data Source code
1 : // Copyright 2014 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/execution.h"
6 :
7 : #include "src/api-inl.h"
8 : #include "src/bootstrapper.h"
9 : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
10 : #include "src/debug/debug.h"
11 : #include "src/isolate-inl.h"
12 : #include "src/runtime-profiler.h"
13 : #include "src/vm-state-inl.h"
14 : #include "src/wasm/wasm-engine.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 1173589 : void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
20 : DCHECK_NOT_NULL(isolate_);
21 : thread_local_.set_jslimit(kInterruptLimit);
22 : thread_local_.set_climit(kInterruptLimit);
23 2347178 : isolate_->heap()->SetStackLimits();
24 1173589 : }
25 :
26 15759456 : void StackGuard::reset_limits(const ExecutionAccess& lock) {
27 : DCHECK_NOT_NULL(isolate_);
28 15759456 : thread_local_.set_jslimit(thread_local_.real_jslimit_);
29 15759456 : thread_local_.set_climit(thread_local_.real_climit_);
30 31518912 : isolate_->heap()->SetStackLimits();
31 15759416 : }
32 :
33 : namespace {
34 :
35 17960434 : Handle<Object> NormalizeReceiver(Isolate* isolate, Handle<Object> receiver) {
36 : // Convert calls on global objects to be calls on the global
37 : // receiver instead to avoid having a 'this' pointer which refers
38 : // directly to a global object.
39 17960434 : if (receiver->IsJSGlobalObject()) {
40 : return handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(),
41 38396 : isolate);
42 : }
43 17922040 : return receiver;
44 : }
45 :
46 : struct InvokeParams {
47 : static InvokeParams SetUpForNew(Isolate* isolate, Handle<Object> constructor,
48 : Handle<Object> new_target, int argc,
49 : Handle<Object>* argv);
50 :
51 : static InvokeParams SetUpForCall(Isolate* isolate, Handle<Object> callable,
52 : Handle<Object> receiver, int argc,
53 : Handle<Object>* argv);
54 :
55 : static InvokeParams SetUpForTryCall(
56 : Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
57 : int argc, Handle<Object>* argv,
58 : Execution::MessageHandling message_handling,
59 : MaybeHandle<Object>* exception_out);
60 :
61 : static InvokeParams SetUpForRunMicrotasks(Isolate* isolate,
62 : MicrotaskQueue* microtask_queue,
63 : MaybeHandle<Object>* exception_out);
64 :
65 : Handle<Object> target;
66 : Handle<Object> receiver;
67 : int argc;
68 : Handle<Object>* argv;
69 : Handle<Object> new_target;
70 :
71 : MicrotaskQueue* microtask_queue;
72 :
73 : Execution::MessageHandling message_handling;
74 : MaybeHandle<Object>* exception_out;
75 :
76 : bool is_construct;
77 : Execution::Target execution_target;
78 : };
79 :
80 : // static
81 : InvokeParams InvokeParams::SetUpForNew(Isolate* isolate,
82 : Handle<Object> constructor,
83 : Handle<Object> new_target, int argc,
84 : Handle<Object>* argv) {
85 : InvokeParams params;
86 1865 : params.target = constructor;
87 1865 : params.receiver = isolate->factory()->undefined_value();
88 1865 : params.argc = argc;
89 1865 : params.argv = argv;
90 1865 : params.new_target = new_target;
91 1865 : params.microtask_queue = nullptr;
92 1865 : params.message_handling = Execution::MessageHandling::kReport;
93 1865 : params.exception_out = nullptr;
94 1865 : params.is_construct = true;
95 1865 : params.execution_target = Execution::Target::kCallable;
96 : return params;
97 : }
98 :
99 : // static
100 : InvokeParams InvokeParams::SetUpForCall(Isolate* isolate,
101 : Handle<Object> callable,
102 : Handle<Object> receiver, int argc,
103 : Handle<Object>* argv) {
104 : InvokeParams params;
105 17947415 : params.target = callable;
106 17947415 : params.receiver = NormalizeReceiver(isolate, receiver);
107 17947414 : params.argc = argc;
108 17947414 : params.argv = argv;
109 17947414 : params.new_target = isolate->factory()->undefined_value();
110 17947414 : params.microtask_queue = nullptr;
111 17947414 : params.message_handling = Execution::MessageHandling::kReport;
112 17947414 : params.exception_out = nullptr;
113 17947414 : params.is_construct = false;
114 17947414 : params.execution_target = Execution::Target::kCallable;
115 : return params;
116 : }
117 :
118 : // static
119 : InvokeParams InvokeParams::SetUpForTryCall(
120 : Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
121 : int argc, Handle<Object>* argv, Execution::MessageHandling message_handling,
122 : MaybeHandle<Object>* exception_out) {
123 : InvokeParams params;
124 13016 : params.target = callable;
125 13016 : params.receiver = NormalizeReceiver(isolate, receiver);
126 13021 : params.argc = argc;
127 13021 : params.argv = argv;
128 13021 : params.new_target = isolate->factory()->undefined_value();
129 13021 : params.microtask_queue = nullptr;
130 13021 : params.message_handling = message_handling;
131 13021 : params.exception_out = exception_out;
132 13021 : params.is_construct = false;
133 13021 : params.execution_target = Execution::Target::kCallable;
134 : return params;
135 : }
136 :
137 : // static
138 : InvokeParams InvokeParams::SetUpForRunMicrotasks(
139 : Isolate* isolate, MicrotaskQueue* microtask_queue,
140 : MaybeHandle<Object>* exception_out) {
141 : auto undefined = isolate->factory()->undefined_value();
142 : InvokeParams params;
143 38104 : params.target = undefined;
144 38104 : params.receiver = undefined;
145 38104 : params.argc = 0;
146 38104 : params.argv = nullptr;
147 38104 : params.new_target = undefined;
148 38104 : params.microtask_queue = microtask_queue;
149 38104 : params.message_handling = Execution::MessageHandling::kReport;
150 38104 : params.exception_out = exception_out;
151 38104 : params.is_construct = false;
152 38104 : params.execution_target = Execution::Target::kRunMicrotasks;
153 : return params;
154 : }
155 :
156 17987552 : Handle<Code> JSEntry(Isolate* isolate, Execution::Target execution_target,
157 : bool is_construct) {
158 17987552 : if (is_construct) {
159 : DCHECK_EQ(Execution::Target::kCallable, execution_target);
160 1097 : return BUILTIN_CODE(isolate, JSConstructEntry);
161 17986455 : } else if (execution_target == Execution::Target::kCallable) {
162 : DCHECK(!is_construct);
163 17948351 : return BUILTIN_CODE(isolate, JSEntry);
164 38104 : } else if (execution_target == Execution::Target::kRunMicrotasks) {
165 : DCHECK(!is_construct);
166 38104 : return BUILTIN_CODE(isolate, JSRunMicrotasksEntry);
167 : }
168 0 : UNREACHABLE();
169 : }
170 :
171 18000388 : V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(Isolate* isolate,
172 : const InvokeParams& params) {
173 18000388 : RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kInvoke);
174 : DCHECK(!params.receiver->IsJSGlobalObject());
175 : DCHECK_LE(params.argc, FixedArray::kMaxLength);
176 :
177 : #ifdef USE_SIMULATOR
178 : // Simulators use separate stacks for C++ and JS. JS stack overflow checks
179 : // are performed whenever a JS function is called. However, it can be the case
180 : // that the C++ stack grows faster than the JS stack, resulting in an overflow
181 : // there. Add a check here to make that less likely.
182 : StackLimitCheck check(isolate);
183 : if (check.HasOverflowed()) {
184 : isolate->StackOverflow();
185 : if (params.message_handling == Execution::MessageHandling::kReport) {
186 : isolate->ReportPendingMessages();
187 : }
188 : return MaybeHandle<Object>();
189 : }
190 : #endif
191 :
192 : // api callbacks can be called directly, unless we want to take the detour
193 : // through JS to set up a frame for break-at-entry.
194 18000385 : if (params.target->IsJSFunction()) {
195 : Handle<JSFunction> function = Handle<JSFunction>::cast(params.target);
196 53511547 : if ((!params.is_construct || function->IsConstructor()) &&
197 53522727 : function->shared()->IsApiFunction() &&
198 17849609 : !function->shared()->BreakAtEntry()) {
199 12826 : SaveAndSwitchContext save(isolate, function->context());
200 : DCHECK(function->context()->global_object()->IsJSGlobalObject());
201 :
202 12826 : Handle<Object> receiver = params.is_construct
203 : ? isolate->factory()->the_hole_value()
204 24884 : : params.receiver;
205 : auto value = Builtins::InvokeApiFunction(
206 12826 : isolate, params.is_construct, function, receiver, params.argc,
207 25652 : params.argv, Handle<HeapObject>::cast(params.new_target));
208 : bool has_exception = value.is_null();
209 : DCHECK(has_exception == isolate->has_pending_exception());
210 12826 : if (has_exception) {
211 230 : if (params.message_handling == Execution::MessageHandling::kReport) {
212 230 : isolate->ReportPendingMessages();
213 : }
214 230 : return MaybeHandle<Object>();
215 : } else {
216 : isolate->clear_pending_message();
217 : }
218 12596 : return value;
219 : }
220 : }
221 :
222 : // Entering JavaScript.
223 : VMState<JS> state(isolate);
224 17987560 : CHECK(AllowJavascriptExecution::IsAllowed(isolate));
225 17987558 : if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
226 5 : isolate->ThrowIllegalOperation();
227 5 : if (params.message_handling == Execution::MessageHandling::kReport) {
228 5 : isolate->ReportPendingMessages();
229 : }
230 4 : return MaybeHandle<Object>();
231 : }
232 17987548 : if (!DumpOnJavascriptExecution::IsAllowed(isolate)) {
233 5 : V8::GetCurrentPlatform()->DumpWithoutCrashing();
234 5 : return isolate->factory()->undefined_value();
235 : }
236 :
237 : // Placeholder for return value.
238 : Object value;
239 :
240 : Handle<Code> code =
241 17987544 : JSEntry(isolate, params.execution_target, params.is_construct);
242 : {
243 : // Save and restore context around invocation and block the
244 : // allocation of handles without explicit handle scopes.
245 35975111 : SaveContext save(isolate);
246 : SealHandleScope shs(isolate);
247 :
248 17987545 : if (FLAG_clear_exceptions_on_js_entry) isolate->clear_pending_exception();
249 :
250 17987545 : if (params.execution_target == Execution::Target::kCallable) {
251 : // clang-format off
252 : // {new_target}, {target}, {receiver}, return value: tagged pointers
253 : // {argv}: pointer to array of tagged pointers
254 : using JSEntryFunction = GeneratedCode<Address(
255 : Address root_register_value, Address new_target, Address target,
256 : Address receiver, intptr_t argc, Address** argv)>;
257 : // clang-format on
258 : JSEntryFunction stub_entry =
259 35898876 : JSEntryFunction::FromAddress(isolate, code->InstructionStart());
260 :
261 : Address orig_func = params.new_target->ptr();
262 : Address func = params.target->ptr();
263 : Address recv = params.receiver->ptr();
264 17949435 : Address** argv = reinterpret_cast<Address**>(params.argv);
265 17949435 : RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kJS_Execution);
266 : value = Object(stub_entry.Call(isolate->isolate_data()->isolate_root(),
267 17949434 : orig_func, func, recv, params.argc, argv));
268 : } else {
269 : DCHECK_EQ(Execution::Target::kRunMicrotasks, params.execution_target);
270 :
271 : // clang-format off
272 : // return value: tagged pointers
273 : // {microtask_queue}: pointer to a C++ object
274 : using JSEntryFunction = GeneratedCode<Address(
275 : Address root_register_value, MicrotaskQueue* microtask_queue)>;
276 : // clang-format on
277 : JSEntryFunction stub_entry =
278 76208 : JSEntryFunction::FromAddress(isolate, code->InstructionStart());
279 :
280 38104 : RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kJS_Execution);
281 : value = Object(stub_entry.Call(isolate->isolate_data()->isolate_root(),
282 38104 : params.microtask_queue));
283 : }
284 : }
285 :
286 : #ifdef VERIFY_HEAP
287 : if (FLAG_verify_heap) {
288 : value->ObjectVerify(isolate);
289 : }
290 : #endif
291 :
292 : // Update the pending exception flag and return the value.
293 : bool has_exception = value->IsException(isolate);
294 : DCHECK(has_exception == isolate->has_pending_exception());
295 17987561 : if (has_exception) {
296 120477 : if (params.message_handling == Execution::MessageHandling::kReport) {
297 120472 : isolate->ReportPendingMessages();
298 : }
299 120477 : return MaybeHandle<Object>();
300 : } else {
301 : isolate->clear_pending_message();
302 : }
303 :
304 17867084 : return Handle<Object>(value, isolate);
305 : }
306 :
307 51125 : MaybeHandle<Object> InvokeWithTryCatch(Isolate* isolate,
308 : const InvokeParams& params) {
309 : bool is_termination = false;
310 : MaybeHandle<Object> maybe_result;
311 51125 : if (params.exception_out != nullptr) {
312 38358 : *params.exception_out = MaybeHandle<Object>();
313 : }
314 : DCHECK_IMPLIES(
315 : params.message_handling == Execution::MessageHandling::kKeepPending,
316 : params.exception_out == nullptr);
317 : // Enter a try-block while executing the JavaScript code. To avoid
318 : // duplicate error printing it must be non-verbose. Also, to avoid
319 : // creating message objects during stack overflow we shouldn't
320 : // capture messages.
321 : {
322 102249 : v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
323 51124 : catcher.SetVerbose(false);
324 51124 : catcher.SetCaptureMessage(false);
325 :
326 51124 : maybe_result = Invoke(isolate, params);
327 :
328 51124 : if (maybe_result.is_null()) {
329 : DCHECK(isolate->has_pending_exception());
330 2386 : if (isolate->pending_exception() ==
331 : ReadOnlyRoots(isolate).termination_exception()) {
332 : is_termination = true;
333 : } else {
334 2361 : if (params.exception_out != nullptr) {
335 : DCHECK(catcher.HasCaught());
336 : DCHECK(isolate->external_caught_exception());
337 120 : *params.exception_out = v8::Utils::OpenHandle(*catcher.Exception());
338 : }
339 : }
340 2386 : if (params.message_handling == Execution::MessageHandling::kReport) {
341 2381 : isolate->OptionalRescheduleException(true);
342 : }
343 : }
344 : }
345 :
346 : // Re-request terminate execution interrupt to trigger later.
347 51124 : if (is_termination) isolate->stack_guard()->RequestTerminateExecution();
348 :
349 51124 : return maybe_result;
350 : }
351 :
352 : } // namespace
353 :
354 : // static
355 17947415 : MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
356 : Handle<Object> receiver, int argc,
357 : Handle<Object> argv[]) {
358 17947411 : return Invoke(isolate, InvokeParams::SetUpForCall(isolate, callable, receiver,
359 35894825 : argc, argv));
360 : }
361 :
362 : // static
363 773 : MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
364 : int argc, Handle<Object> argv[]) {
365 773 : return New(isolate, constructor, constructor, argc, argv);
366 : }
367 :
368 : // static
369 1865 : MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
370 : Handle<Object> new_target, int argc,
371 : Handle<Object> argv[]) {
372 1865 : return Invoke(isolate, InvokeParams::SetUpForNew(isolate, constructor,
373 3730 : new_target, argc, argv));
374 : }
375 :
376 : // static
377 13016 : MaybeHandle<Object> Execution::TryCall(Isolate* isolate,
378 : Handle<Object> callable,
379 : Handle<Object> receiver, int argc,
380 : Handle<Object> argv[],
381 : MessageHandling message_handling,
382 : MaybeHandle<Object>* exception_out) {
383 : return InvokeWithTryCatch(
384 : isolate,
385 13020 : InvokeParams::SetUpForTryCall(isolate, callable, receiver, argc, argv,
386 26041 : message_handling, exception_out));
387 : }
388 :
389 : // static
390 38104 : MaybeHandle<Object> Execution::TryRunMicrotasks(
391 : Isolate* isolate, MicrotaskQueue* microtask_queue,
392 : MaybeHandle<Object>* exception_out) {
393 : return InvokeWithTryCatch(
394 38104 : isolate, InvokeParams::SetUpForRunMicrotasks(isolate, microtask_queue,
395 76208 : exception_out));
396 : }
397 :
398 1871 : void StackGuard::SetStackLimit(uintptr_t limit) {
399 1871 : ExecutionAccess access(isolate_);
400 : // If the current limits are special (e.g. due to a pending interrupt) then
401 : // leave them alone.
402 : uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
403 1871 : if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
404 : thread_local_.set_jslimit(jslimit);
405 : }
406 1871 : if (thread_local_.climit() == thread_local_.real_climit_) {
407 : thread_local_.set_climit(limit);
408 : }
409 1871 : thread_local_.real_climit_ = limit;
410 1871 : thread_local_.real_jslimit_ = jslimit;
411 1871 : }
412 :
413 :
414 0 : void StackGuard::AdjustStackLimitForSimulator() {
415 0 : ExecutionAccess access(isolate_);
416 0 : uintptr_t climit = thread_local_.real_climit_;
417 : // If the current limits are special (e.g. due to a pending interrupt) then
418 : // leave them alone.
419 : uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, climit);
420 0 : if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
421 : thread_local_.set_jslimit(jslimit);
422 0 : isolate_->heap()->SetStackLimits();
423 : }
424 0 : }
425 :
426 :
427 0 : void StackGuard::EnableInterrupts() {
428 0 : ExecutionAccess access(isolate_);
429 0 : if (has_pending_interrupts(access)) {
430 0 : set_interrupt_limits(access);
431 : }
432 0 : }
433 :
434 :
435 0 : void StackGuard::DisableInterrupts() {
436 0 : ExecutionAccess access(isolate_);
437 0 : reset_limits(access);
438 0 : }
439 :
440 4403717 : void StackGuard::PushInterruptsScope(InterruptsScope* scope) {
441 4403717 : ExecutionAccess access(isolate_);
442 : DCHECK_NE(scope->mode_, InterruptsScope::kNoop);
443 4403747 : if (scope->mode_ == InterruptsScope::kPostponeInterrupts) {
444 : // Intercept already requested interrupts.
445 4372322 : int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
446 4372322 : scope->intercepted_flags_ = intercepted;
447 4372322 : thread_local_.interrupt_flags_ &= ~intercepted;
448 : } else {
449 : DCHECK_EQ(scope->mode_, InterruptsScope::kRunInterrupts);
450 : // Restore postponed interrupts.
451 : int restored_flags = 0;
452 47762 : for (InterruptsScope* current = thread_local_.interrupt_scopes_;
453 47762 : current != nullptr; current = current->prev_) {
454 16337 : restored_flags |= (current->intercepted_flags_ & scope->intercept_mask_);
455 16337 : current->intercepted_flags_ &= ~scope->intercept_mask_;
456 : }
457 31425 : thread_local_.interrupt_flags_ |= restored_flags;
458 : }
459 4403747 : if (!has_pending_interrupts(access)) reset_limits(access);
460 : // Add scope to the chain.
461 4403728 : scope->prev_ = thread_local_.interrupt_scopes_;
462 4403728 : thread_local_.interrupt_scopes_ = scope;
463 4403747 : }
464 :
465 4403708 : void StackGuard::PopInterruptsScope() {
466 4403708 : ExecutionAccess access(isolate_);
467 4403740 : InterruptsScope* top = thread_local_.interrupt_scopes_;
468 : DCHECK_NE(top->mode_, InterruptsScope::kNoop);
469 4403740 : if (top->mode_ == InterruptsScope::kPostponeInterrupts) {
470 : // Make intercepted interrupts active.
471 : DCHECK_EQ(thread_local_.interrupt_flags_ & top->intercept_mask_, 0);
472 4372315 : thread_local_.interrupt_flags_ |= top->intercepted_flags_;
473 : } else {
474 : DCHECK_EQ(top->mode_, InterruptsScope::kRunInterrupts);
475 : // Postpone existing interupts if needed.
476 31425 : if (top->prev_) {
477 227385 : for (int interrupt = 1; interrupt < ALL_INTERRUPTS;
478 : interrupt = interrupt << 1) {
479 106113 : InterruptFlag flag = static_cast<InterruptFlag>(interrupt);
480 106143 : if ((thread_local_.interrupt_flags_ & flag) &&
481 30 : top->prev_->Intercept(flag)) {
482 24 : thread_local_.interrupt_flags_ &= ~flag;
483 : }
484 : }
485 : }
486 : }
487 4403740 : if (has_pending_interrupts(access)) set_interrupt_limits(access);
488 : // Remove scope from chain.
489 4403740 : thread_local_.interrupt_scopes_ = top->prev_;
490 4403740 : }
491 :
492 :
493 3 : bool StackGuard::CheckInterrupt(InterruptFlag flag) {
494 3 : ExecutionAccess access(isolate_);
495 6 : return thread_local_.interrupt_flags_ & flag;
496 : }
497 :
498 :
499 1108614 : void StackGuard::RequestInterrupt(InterruptFlag flag) {
500 1108614 : ExecutionAccess access(isolate_);
501 : // Check the chain of InterruptsScope for interception.
502 1185218 : if (thread_local_.interrupt_scopes_ &&
503 76604 : thread_local_.interrupt_scopes_->Intercept(flag)) {
504 : return;
505 : }
506 :
507 : // Not intercepted. Set as active interrupt flag.
508 1032727 : thread_local_.interrupt_flags_ |= flag;
509 1032727 : set_interrupt_limits(access);
510 :
511 : // If this isolate is waiting in a futex, notify it to wake up.
512 2065454 : isolate_->futex_wait_list_node()->NotifyWake();
513 : }
514 :
515 :
516 25294 : void StackGuard::ClearInterrupt(InterruptFlag flag) {
517 25294 : ExecutionAccess access(isolate_);
518 : // Clear the interrupt flag from the chain of InterruptsScope.
519 48917 : for (InterruptsScope* current = thread_local_.interrupt_scopes_;
520 48917 : current != nullptr; current = current->prev_) {
521 23623 : current->intercepted_flags_ &= ~flag;
522 : }
523 :
524 : // Clear the interrupt flag from the active interrupt flags.
525 25294 : thread_local_.interrupt_flags_ &= ~flag;
526 25294 : if (!has_pending_interrupts(access)) reset_limits(access);
527 25294 : }
528 :
529 :
530 11375108 : bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
531 11375108 : ExecutionAccess access(isolate_);
532 11375108 : bool result = (thread_local_.interrupt_flags_ & flag);
533 11375108 : thread_local_.interrupt_flags_ &= ~flag;
534 11375108 : if (!has_pending_interrupts(access)) reset_limits(access);
535 11375108 : return result;
536 : }
537 :
538 :
539 32424 : char* StackGuard::ArchiveStackGuard(char* to) {
540 32424 : ExecutionAccess access(isolate_);
541 32424 : MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
542 : ThreadLocal blank;
543 :
544 : // Set the stack limits using the old thread_local_.
545 : // TODO(isolates): This was the old semantics of constructing a ThreadLocal
546 : // (as the ctor called SetStackLimits, which looked at the
547 : // current thread_local_ from StackGuard)-- but is this
548 : // really what was intended?
549 64848 : isolate_->heap()->SetStackLimits();
550 32424 : thread_local_ = blank;
551 :
552 64848 : return to + sizeof(ThreadLocal);
553 : }
554 :
555 :
556 32424 : char* StackGuard::RestoreStackGuard(char* from) {
557 32424 : ExecutionAccess access(isolate_);
558 32424 : MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
559 64848 : isolate_->heap()->SetStackLimits();
560 64848 : return from + sizeof(ThreadLocal);
561 : }
562 :
563 :
564 5918 : void StackGuard::FreeThreadResources() {
565 : Isolate::PerIsolateThreadData* per_thread =
566 5918 : isolate_->FindOrAllocatePerThreadDataForThisThread();
567 5918 : per_thread->set_stack_limit(thread_local_.real_climit_);
568 5918 : }
569 :
570 :
571 100783 : void StackGuard::ThreadLocal::Clear() {
572 100783 : real_jslimit_ = kIllegalLimit;
573 : set_jslimit(kIllegalLimit);
574 100783 : real_climit_ = kIllegalLimit;
575 : set_climit(kIllegalLimit);
576 100783 : interrupt_scopes_ = nullptr;
577 100783 : interrupt_flags_ = 0;
578 100783 : }
579 :
580 :
581 74278 : bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
582 : bool should_set_stack_limits = false;
583 74278 : if (real_climit_ == kIllegalLimit) {
584 69605 : const uintptr_t kLimitSize = FLAG_stack_size * KB;
585 : DCHECK_GT(GetCurrentStackPosition(), kLimitSize);
586 69605 : uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
587 69605 : real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
588 : set_jslimit(SimulatorStack::JsLimitFromCLimit(isolate, limit));
589 69605 : real_climit_ = limit;
590 : set_climit(limit);
591 : should_set_stack_limits = true;
592 : }
593 74278 : interrupt_scopes_ = nullptr;
594 74278 : interrupt_flags_ = 0;
595 74278 : return should_set_stack_limits;
596 : }
597 :
598 :
599 5918 : void StackGuard::ClearThread(const ExecutionAccess& lock) {
600 5918 : thread_local_.Clear();
601 11836 : isolate_->heap()->SetStackLimits();
602 5918 : }
603 :
604 :
605 74278 : void StackGuard::InitThread(const ExecutionAccess& lock) {
606 143883 : if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
607 : Isolate::PerIsolateThreadData* per_thread =
608 74278 : isolate_->FindOrAllocatePerThreadDataForThisThread();
609 : uintptr_t stored_limit = per_thread->stack_limit();
610 : // You should hold the ExecutionAccess lock when you call this.
611 74278 : if (stored_limit != 0) {
612 190 : SetStackLimit(stored_limit);
613 : }
614 74278 : }
615 :
616 :
617 : // --- C a l l s t o n a t i v e s ---
618 :
619 1625744 : Object StackGuard::HandleInterrupts() {
620 4877232 : TRACE_EVENT0("v8.execute", "V8.HandleInterrupts");
621 :
622 : if (FLAG_verify_predictable) {
623 : // Advance synthetic time by making a time request.
624 : isolate_->heap()->MonotonicallyIncreasingTimeInMs();
625 : }
626 :
627 1625744 : if (CheckAndClearInterrupt(GC_REQUEST)) {
628 55161 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.gc"), "V8.GCHandleGCRequest");
629 36774 : isolate_->heap()->HandleGCRequest();
630 : }
631 :
632 1625744 : if (CheckAndClearInterrupt(GROW_SHARED_MEMORY)) {
633 408 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
634 : "V8.WasmGrowSharedMemory");
635 136 : isolate_->wasm_engine()->memory_tracker()->UpdateSharedMemoryInstances(
636 136 : isolate_);
637 : }
638 :
639 1625744 : if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
640 3825 : TRACE_EVENT0("v8.execute", "V8.TerminateExecution");
641 1275 : return isolate_->TerminateExecution();
642 : }
643 :
644 1624469 : if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
645 102 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.gc"),
646 : "V8.GCDeoptMarkedAllocationSites");
647 68 : isolate_->heap()->DeoptMarkedAllocationSites();
648 : }
649 :
650 1624469 : if (CheckAndClearInterrupt(INSTALL_CODE)) {
651 17868 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
652 : "V8.InstallOptimizedFunctions");
653 : DCHECK(isolate_->concurrent_recompilation_enabled());
654 5956 : isolate_->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
655 : }
656 :
657 1624469 : if (CheckAndClearInterrupt(API_INTERRUPT)) {
658 6495 : TRACE_EVENT0("v8.execute", "V8.InvokeApiInterruptCallbacks");
659 : // Callbacks must be invoked outside of ExecutionAccess lock.
660 2165 : isolate_->InvokeApiInterruptCallbacks();
661 : }
662 :
663 1624469 : if (CheckAndClearInterrupt(LOG_WASM_CODE)) {
664 12 : TRACE_EVENT0("v8.wasm", "LogCode");
665 4 : isolate_->wasm_engine()->LogOutstandingCodesForIsolate(isolate_);
666 : }
667 :
668 3248938 : isolate_->counters()->stack_interrupts()->Increment();
669 3248938 : isolate_->counters()->runtime_profiler_ticks()->Increment();
670 1624469 : isolate_->runtime_profiler()->MarkCandidatesForOptimization();
671 :
672 3248938 : return ReadOnlyRoots(isolate_).undefined_value();
673 : }
674 :
675 : } // namespace internal
676 122036 : } // namespace v8
|