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 1373370 : 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 1373370 : isolate_->heap()->SetStackLimits();
23 1373370 : }
24 :
25 5676169 : void StackGuard::reset_limits(const ExecutionAccess& lock) {
26 : DCHECK_NOT_NULL(isolate_);
27 5676169 : thread_local_.set_jslimit(thread_local_.real_jslimit_);
28 5676169 : thread_local_.set_climit(thread_local_.real_climit_);
29 5676169 : isolate_->heap()->SetStackLimits();
30 5676165 : }
31 :
32 : namespace {
33 :
34 21612620 : 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 43225247 : if (receiver->IsJSGlobalObject()) {
39 83782 : return handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(),
40 83782 : isolate);
41 : }
42 21570735 : 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 2013 : params.target = constructor;
86 2013 : params.receiver = isolate->factory()->undefined_value();
87 2013 : params.argc = argc;
88 2013 : params.argv = argv;
89 2013 : params.new_target = new_target;
90 2013 : params.microtask_queue = nullptr;
91 2013 : params.message_handling = Execution::MessageHandling::kReport;
92 2013 : params.exception_out = nullptr;
93 2013 : params.is_construct = true;
94 2013 : 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 21607624 : params.target = callable;
105 21607624 : params.receiver = NormalizeReceiver(isolate, receiver);
106 21607623 : params.argc = argc;
107 21607623 : params.argv = argv;
108 21607623 : params.new_target = isolate->factory()->undefined_value();
109 21607623 : params.microtask_queue = nullptr;
110 21607623 : params.message_handling = Execution::MessageHandling::kReport;
111 21607623 : params.exception_out = nullptr;
112 21607623 : params.is_construct = false;
113 21607623 : 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 4998 : params.target = callable;
124 4998 : params.receiver = NormalizeReceiver(isolate, receiver);
125 5003 : params.argc = argc;
126 5003 : params.argv = argv;
127 5003 : params.new_target = isolate->factory()->undefined_value();
128 5003 : params.microtask_queue = nullptr;
129 5003 : params.message_handling = message_handling;
130 5003 : params.exception_out = exception_out;
131 5003 : params.is_construct = false;
132 5003 : 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 52430 : params.target = undefined;
143 52430 : params.receiver = undefined;
144 52430 : params.argc = 0;
145 52430 : params.argv = nullptr;
146 52430 : params.new_target = undefined;
147 52430 : params.microtask_queue = microtask_queue;
148 52430 : params.message_handling = Execution::MessageHandling::kReport;
149 52430 : params.exception_out = exception_out;
150 52430 : params.is_construct = false;
151 52430 : params.execution_target = Execution::Target::kRunMicrotasks;
152 : return params;
153 : }
154 :
155 21652818 : Handle<Code> JSEntry(Isolate* isolate, Execution::Target execution_target,
156 : bool is_construct) {
157 21652818 : if (is_construct) {
158 : DCHECK_EQ(Execution::Target::kCallable, execution_target);
159 1106 : return BUILTIN_CODE(isolate, JSConstructEntry);
160 21651712 : } else if (execution_target == Execution::Target::kCallable) {
161 : DCHECK(!is_construct);
162 21599282 : return BUILTIN_CODE(isolate, JSEntry);
163 52430 : } else if (execution_target == Execution::Target::kRunMicrotasks) {
164 : DCHECK(!is_construct);
165 52430 : return BUILTIN_CODE(isolate, JSRunMicrotasksEntry);
166 : }
167 0 : UNREACHABLE();
168 : }
169 :
170 21667064 : V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(Isolate* isolate,
171 : const InvokeParams& params) {
172 21667064 : 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 43334142 : if (params.target->IsJSFunction()) {
194 21471413 : Handle<JSFunction> function = Handle<JSFunction>::cast(params.target);
195 64418246 : if ((!params.is_construct || function->IsConstructor()) &&
196 64428693 : function->shared()->IsApiFunction() &&
197 21485878 : !function->shared()->BreakAtEntry()) {
198 14236 : SaveContext save(isolate);
199 28472 : isolate->set_context(function->context());
200 : DCHECK(function->context()->global_object()->IsJSGlobalObject());
201 :
202 : Handle<Object> receiver = params.is_construct
203 : ? isolate->factory()->the_hole_value()
204 27565 : : params.receiver;
205 : auto value = Builtins::InvokeApiFunction(
206 : isolate, params.is_construct, function, receiver, params.argc,
207 28472 : params.argv, Handle<HeapObject>::cast(params.new_target));
208 : bool has_exception = value.is_null();
209 : DCHECK(has_exception == isolate->has_pending_exception());
210 14236 : if (has_exception) {
211 216 : if (params.message_handling == Execution::MessageHandling::kReport) {
212 216 : isolate->ReportPendingMessages();
213 : }
214 216 : return MaybeHandle<Object>();
215 : } else {
216 14020 : isolate->clear_pending_message();
217 : }
218 14020 : return value;
219 : }
220 : }
221 :
222 : // Entering JavaScript.
223 : VMState<JS> state(isolate);
224 21652827 : CHECK(AllowJavascriptExecution::IsAllowed(isolate));
225 21652825 : 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 21652827 : if (!DumpOnJavascriptExecution::IsAllowed(isolate)) {
233 5 : V8::GetCurrentPlatform()->DumpWithoutCrashing();
234 5 : return isolate->factory()->undefined_value();
235 : }
236 :
237 : // Placeholder for return value.
238 21652823 : Object value;
239 :
240 : Handle<Code> code =
241 21652823 : 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 21652820 : SaveContext save(isolate);
246 : SealHandleScope shs(isolate);
247 :
248 21652822 : if (FLAG_clear_exceptions_on_js_entry) isolate->clear_pending_exception();
249 :
250 21652823 : 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 43200786 : 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 21600395 : Address** argv = reinterpret_cast<Address**>(params.argv);
265 21600395 : RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kJS_Execution);
266 : value = Object(stub_entry.Call(isolate->isolate_data()->isolate_root(),
267 43200795 : 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 104860 : JSEntryFunction::FromAddress(isolate, code->InstructionStart());
279 :
280 52430 : RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kJS_Execution);
281 : value = Object(stub_entry.Call(isolate->isolate_data()->isolate_root(),
282 104860 : params.microtask_queue));
283 21652828 : }
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 21652819 : if (has_exception) {
296 109358 : if (params.message_handling == Execution::MessageHandling::kReport) {
297 109353 : isolate->ReportPendingMessages();
298 : }
299 109358 : return MaybeHandle<Object>();
300 : } else {
301 21543461 : isolate->clear_pending_message();
302 : }
303 :
304 21543452 : return Handle<Object>(value, isolate);
305 : }
306 :
307 57433 : MaybeHandle<Object> InvokeWithTryCatch(Isolate* isolate,
308 : const InvokeParams& params) {
309 : bool is_termination = false;
310 : MaybeHandle<Object> maybe_result;
311 57433 : if (params.exception_out != nullptr) {
312 52705 : *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 57433 : v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
323 57432 : catcher.SetVerbose(false);
324 57432 : catcher.SetCaptureMessage(false);
325 :
326 57431 : maybe_result = Invoke(isolate, params);
327 :
328 57437 : if (maybe_result.is_null()) {
329 : DCHECK(isolate->has_pending_exception());
330 120 : if (isolate->pending_exception() ==
331 : ReadOnlyRoots(isolate).termination_exception()) {
332 : is_termination = true;
333 : } else {
334 95 : if (params.exception_out != nullptr) {
335 : DCHECK(catcher.HasCaught());
336 : DCHECK(isolate->external_caught_exception());
337 180 : *params.exception_out = v8::Utils::OpenHandle(*catcher.Exception());
338 : }
339 : }
340 120 : if (params.message_handling == Execution::MessageHandling::kReport) {
341 115 : isolate->OptionalRescheduleException(true);
342 : }
343 57437 : }
344 : }
345 :
346 : // Re-request terminate execution interrupt to trigger later.
347 57431 : if (is_termination) isolate->stack_guard()->RequestTerminateExecution();
348 :
349 57431 : return maybe_result;
350 : }
351 :
352 : } // namespace
353 :
354 : // static
355 21607624 : MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
356 : Handle<Object> receiver, int argc,
357 : Handle<Object> argv[]) {
358 : return Invoke(isolate, InvokeParams::SetUpForCall(isolate, callable, receiver,
359 21607623 : argc, argv));
360 : }
361 :
362 : // static
363 782 : MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
364 : int argc, Handle<Object> argv[]) {
365 782 : return New(isolate, constructor, constructor, argc, argv);
366 : }
367 :
368 : // static
369 2013 : MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
370 : Handle<Object> new_target, int argc,
371 : Handle<Object> argv[]) {
372 : return Invoke(isolate, InvokeParams::SetUpForNew(isolate, constructor,
373 2013 : new_target, argc, argv));
374 : }
375 :
376 : // static
377 4998 : 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 : InvokeParams::SetUpForTryCall(isolate, callable, receiver, argc, argv,
386 5003 : message_handling, exception_out));
387 : }
388 :
389 : // static
390 52430 : MaybeHandle<Object> Execution::TryRunMicrotasks(
391 : Isolate* isolate, MicrotaskQueue* microtask_queue,
392 : MaybeHandle<Object>* exception_out) {
393 : return InvokeWithTryCatch(
394 : isolate, InvokeParams::SetUpForRunMicrotasks(isolate, microtask_queue,
395 52430 : exception_out));
396 : }
397 :
398 1851 : void StackGuard::SetStackLimit(uintptr_t limit) {
399 1851 : 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 1851 : if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
404 : thread_local_.set_jslimit(jslimit);
405 : }
406 1851 : if (thread_local_.climit() == thread_local_.real_climit_) {
407 : thread_local_.set_climit(limit);
408 : }
409 1851 : thread_local_.real_climit_ = limit;
410 1851 : thread_local_.real_jslimit_ = jslimit;
411 1851 : }
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 8876232 : void StackGuard::PushInterruptsScope(InterruptsScope* scope) {
441 4438102 : ExecutionAccess access(isolate_);
442 : DCHECK_NE(scope->mode_, InterruptsScope::kNoop);
443 4438130 : if (scope->mode_ == InterruptsScope::kPostponeInterrupts) {
444 : // Intercept already requested interrupts.
445 4407361 : int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
446 4407361 : scope->intercepted_flags_ = intercepted;
447 4407361 : thread_local_.interrupt_flags_ &= ~intercepted;
448 : } else {
449 : DCHECK_EQ(scope->mode_, InterruptsScope::kRunInterrupts);
450 : // Restore postponed interrupts.
451 : int restored_flags = 0;
452 46648 : for (InterruptsScope* current = thread_local_.interrupt_scopes_;
453 : current != nullptr; current = current->prev_) {
454 15879 : restored_flags |= (current->intercepted_flags_ & scope->intercept_mask_);
455 15879 : current->intercepted_flags_ &= ~scope->intercept_mask_;
456 : }
457 30769 : thread_local_.interrupt_flags_ |= restored_flags;
458 : }
459 4438130 : if (!has_pending_interrupts(access)) reset_limits(access);
460 : // Add scope to the chain.
461 4438126 : scope->prev_ = thread_local_.interrupt_scopes_;
462 4438126 : thread_local_.interrupt_scopes_ = scope;
463 4438138 : }
464 :
465 8876240 : void StackGuard::PopInterruptsScope() {
466 4438107 : ExecutionAccess access(isolate_);
467 4438133 : InterruptsScope* top = thread_local_.interrupt_scopes_;
468 : DCHECK_NE(top->mode_, InterruptsScope::kNoop);
469 4438133 : if (top->mode_ == InterruptsScope::kPostponeInterrupts) {
470 : // Make intercepted interrupts active.
471 : DCHECK_EQ(thread_local_.interrupt_flags_ & top->intercept_mask_, 0);
472 4407364 : thread_local_.interrupt_flags_ |= top->intercepted_flags_;
473 : } else {
474 : DCHECK_EQ(top->mode_, InterruptsScope::kRunInterrupts);
475 : // Postpone existing interupts if needed.
476 30769 : if (top->prev_) {
477 74770 : for (int interrupt = 1; interrupt < ALL_INTERRUPTS;
478 : interrupt = interrupt << 1) {
479 74770 : InterruptFlag flag = static_cast<InterruptFlag>(interrupt);
480 74807 : if ((thread_local_.interrupt_flags_ & flag) &&
481 37 : top->prev_->Intercept(flag)) {
482 27 : thread_local_.interrupt_flags_ &= ~flag;
483 : }
484 : }
485 : }
486 : }
487 4438133 : if (has_pending_interrupts(access)) set_interrupt_limits(access);
488 : // Remove scope from chain.
489 4438133 : thread_local_.interrupt_scopes_ = top->prev_;
490 4438130 : }
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 1308468 : void StackGuard::RequestInterrupt(InterruptFlag flag) {
500 1308468 : ExecutionAccess access(isolate_);
501 : // Check the chain of InterruptsScope for interception.
502 1384695 : if (thread_local_.interrupt_scopes_ &&
503 76227 : thread_local_.interrupt_scopes_->Intercept(flag)) {
504 1308468 : return;
505 : }
506 :
507 : // Not intercepted. Set as active interrupt flag.
508 1232884 : thread_local_.interrupt_flags_ |= flag;
509 1232884 : set_interrupt_limits(access);
510 :
511 : // If this isolate is waiting in a futex, notify it to wake up.
512 1232884 : isolate_->futex_wait_list_node()->NotifyWake();
513 : }
514 :
515 :
516 31178 : void StackGuard::ClearInterrupt(InterruptFlag flag) {
517 31178 : ExecutionAccess access(isolate_);
518 : // Clear the interrupt flag from the chain of InterruptsScope.
519 59622 : for (InterruptsScope* current = thread_local_.interrupt_scopes_;
520 : current != nullptr; current = current->prev_) {
521 28444 : current->intercepted_flags_ &= ~flag;
522 : }
523 :
524 : // Clear the interrupt flag from the active interrupt flags.
525 31178 : thread_local_.interrupt_flags_ &= ~flag;
526 31178 : if (!has_pending_interrupts(access)) reset_limits(access);
527 31178 : }
528 :
529 :
530 1241433 : bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
531 1241433 : ExecutionAccess access(isolate_);
532 1241433 : bool result = (thread_local_.interrupt_flags_ & flag);
533 1241433 : thread_local_.interrupt_flags_ &= ~flag;
534 1241433 : if (!has_pending_interrupts(access)) reset_limits(access);
535 1241433 : return result;
536 : }
537 :
538 :
539 24256 : char* StackGuard::ArchiveStackGuard(char* to) {
540 24256 : ExecutionAccess access(isolate_);
541 24256 : 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 24256 : isolate_->heap()->SetStackLimits();
550 24256 : thread_local_ = blank;
551 :
552 48512 : return to + sizeof(ThreadLocal);
553 : }
554 :
555 :
556 24256 : char* StackGuard::RestoreStackGuard(char* from) {
557 24256 : ExecutionAccess access(isolate_);
558 24256 : MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
559 24256 : isolate_->heap()->SetStackLimits();
560 48512 : 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 93056 : void StackGuard::ThreadLocal::Clear() {
572 93056 : real_jslimit_ = kIllegalLimit;
573 : set_jslimit(kIllegalLimit);
574 93056 : real_climit_ = kIllegalLimit;
575 : set_climit(kIllegalLimit);
576 93056 : interrupt_scopes_ = nullptr;
577 93056 : interrupt_flags_ = 0;
578 93056 : }
579 :
580 :
581 74719 : bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
582 : bool should_set_stack_limits = false;
583 74719 : if (real_climit_ == kIllegalLimit) {
584 70028 : const uintptr_t kLimitSize = FLAG_stack_size * KB;
585 : DCHECK_GT(GetCurrentStackPosition(), kLimitSize);
586 70028 : uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
587 70028 : real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
588 : set_jslimit(SimulatorStack::JsLimitFromCLimit(isolate, limit));
589 70028 : real_climit_ = limit;
590 : set_climit(limit);
591 : should_set_stack_limits = true;
592 : }
593 74719 : interrupt_scopes_ = nullptr;
594 74719 : interrupt_flags_ = 0;
595 74719 : return should_set_stack_limits;
596 : }
597 :
598 :
599 5918 : void StackGuard::ClearThread(const ExecutionAccess& lock) {
600 5918 : thread_local_.Clear();
601 5918 : isolate_->heap()->SetStackLimits();
602 5918 : }
603 :
604 :
605 74719 : void StackGuard::InitThread(const ExecutionAccess& lock) {
606 74719 : if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
607 74719 : Isolate::PerIsolateThreadData* per_thread =
608 74719 : isolate_->FindOrAllocatePerThreadDataForThisThread();
609 : uintptr_t stored_limit = per_thread->stack_limit();
610 : // You should hold the ExecutionAccess lock when you call this.
611 74719 : if (stored_limit != 0) {
612 190 : SetStackLimit(stored_limit);
613 : }
614 74719 : }
615 :
616 :
617 : // --- C a l l s t o n a t i v e s ---
618 :
619 249030 : Object StackGuard::HandleInterrupts() {
620 : if (FLAG_verify_predictable) {
621 : // Advance synthetic time by making a time request.
622 254187 : isolate_->heap()->MonotonicallyIncreasingTimeInMs();
623 : }
624 :
625 : bool any_interrupt_handled = false;
626 249030 : if (FLAG_trace_interrupts) {
627 0 : PrintF("[Handling interrupts: ");
628 : }
629 :
630 249030 : if (CheckAndClearInterrupt(GC_REQUEST)) {
631 18500 : if (FLAG_trace_interrupts) {
632 0 : PrintF("GC_REQUEST");
633 : any_interrupt_handled = true;
634 : }
635 18500 : isolate_->heap()->HandleGCRequest();
636 : }
637 :
638 249030 : if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
639 1239 : if (FLAG_trace_interrupts) {
640 0 : if (any_interrupt_handled) PrintF(", ");
641 0 : PrintF("TERMINATE_EXECUTION");
642 : any_interrupt_handled = true;
643 : }
644 1239 : return isolate_->TerminateExecution();
645 : }
646 :
647 247791 : if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
648 34 : if (FLAG_trace_interrupts) {
649 0 : if (any_interrupt_handled) PrintF(", ");
650 0 : PrintF("DEOPT_MARKED_ALLOCATION_SITES");
651 : any_interrupt_handled = true;
652 : }
653 34 : isolate_->heap()->DeoptMarkedAllocationSites();
654 : }
655 :
656 247791 : if (CheckAndClearInterrupt(INSTALL_CODE)) {
657 6396 : if (FLAG_trace_interrupts) {
658 0 : if (any_interrupt_handled) PrintF(", ");
659 0 : PrintF("INSTALL_CODE");
660 : any_interrupt_handled = true;
661 : }
662 : DCHECK(isolate_->concurrent_recompilation_enabled());
663 12792 : isolate_->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
664 : }
665 :
666 247791 : if (CheckAndClearInterrupt(API_INTERRUPT)) {
667 2126 : if (FLAG_trace_interrupts) {
668 0 : if (any_interrupt_handled) PrintF(", ");
669 0 : PrintF("API_INTERRUPT");
670 : any_interrupt_handled = true;
671 : }
672 : // Callbacks must be invoked outside of ExecusionAccess lock.
673 2126 : isolate_->InvokeApiInterruptCallbacks();
674 : }
675 :
676 247791 : if (FLAG_trace_interrupts) {
677 0 : if (!any_interrupt_handled) {
678 0 : PrintF("No interrupt flags set");
679 : }
680 0 : PrintF("]\n");
681 : }
682 :
683 495582 : isolate_->counters()->stack_interrupts()->Increment();
684 495582 : isolate_->counters()->runtime_profiler_ticks()->Increment();
685 495582 : isolate_->runtime_profiler()->MarkCandidatesForOptimization();
686 :
687 495582 : return ReadOnlyRoots(isolate_).undefined_value();
688 : }
689 :
690 : } // namespace internal
691 183867 : } // namespace v8
|