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