OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/execution.h" | 5 #include "src/execution.h" |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
11 #include "src/vm-state-inl.h" | 11 #include "src/vm-state-inl.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 StackGuard::StackGuard() | 16 StackGuard::StackGuard() |
17 : isolate_(NULL) { | 17 : isolate_(NULL) { |
18 } | 18 } |
19 | 19 |
20 | 20 |
21 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) { | 21 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) { |
22 ASSERT(isolate_ != NULL); | 22 ASSERT(isolate_ != NULL); |
| 23 // Ignore attempts to interrupt when interrupts are postponed. |
| 24 if (should_postpone_interrupts(lock)) return; |
23 thread_local_.jslimit_ = kInterruptLimit; | 25 thread_local_.jslimit_ = kInterruptLimit; |
24 thread_local_.climit_ = kInterruptLimit; | 26 thread_local_.climit_ = kInterruptLimit; |
25 isolate_->heap()->SetStackLimits(); | 27 isolate_->heap()->SetStackLimits(); |
26 } | 28 } |
27 | 29 |
28 | 30 |
29 void StackGuard::reset_limits(const ExecutionAccess& lock) { | 31 void StackGuard::reset_limits(const ExecutionAccess& lock) { |
30 ASSERT(isolate_ != NULL); | 32 ASSERT(isolate_ != NULL); |
31 thread_local_.jslimit_ = thread_local_.real_jslimit_; | 33 thread_local_.jslimit_ = thread_local_.real_jslimit_; |
32 thread_local_.climit_ = thread_local_.real_climit_; | 34 thread_local_.climit_ = thread_local_.real_climit_; |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 thread_local_.real_jslimit_ = jslimit; | 330 thread_local_.real_jslimit_ = jslimit; |
329 } | 331 } |
330 | 332 |
331 | 333 |
332 void StackGuard::DisableInterrupts() { | 334 void StackGuard::DisableInterrupts() { |
333 ExecutionAccess access(isolate_); | 335 ExecutionAccess access(isolate_); |
334 reset_limits(access); | 336 reset_limits(access); |
335 } | 337 } |
336 | 338 |
337 | 339 |
338 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) { | 340 bool StackGuard::CheckInterrupt(int flagbit) { |
339 ExecutionAccess access(isolate_); | 341 ExecutionAccess access(isolate_); |
340 scope->prev_ = thread_local_.postpone_interrupts_; | 342 return thread_local_.interrupt_flags_ & flagbit; |
341 thread_local_.postpone_interrupts_ = scope; | |
342 } | 343 } |
343 | 344 |
344 | 345 |
345 void StackGuard::PopPostponeInterruptsScope() { | 346 void StackGuard::RequestInterrupt(int flagbit) { |
346 ExecutionAccess access(isolate_); | 347 ExecutionAccess access(isolate_); |
347 PostponeInterruptsScope* top = thread_local_.postpone_interrupts_; | 348 thread_local_.interrupt_flags_ |= flagbit; |
348 thread_local_.interrupt_flags_ |= top->intercepted_flags_; | |
349 thread_local_.postpone_interrupts_ = top->prev_; | |
350 if (has_pending_interrupts(access)) set_interrupt_limits(access); | |
351 } | |
352 | |
353 | |
354 bool StackGuard::CheckInterrupt(InterruptFlag flag) { | |
355 ExecutionAccess access(isolate_); | |
356 return thread_local_.interrupt_flags_ & flag; | |
357 } | |
358 | |
359 | |
360 void StackGuard::RequestInterrupt(InterruptFlag flag) { | |
361 ExecutionAccess access(isolate_); | |
362 // Check the chain of PostponeInterruptsScopes for interception. | |
363 if (thread_local_.postpone_interrupts_ && | |
364 thread_local_.postpone_interrupts_->Intercept(flag)) { | |
365 return; | |
366 } | |
367 | |
368 // Not intercepted. Set as active interrupt flag. | |
369 thread_local_.interrupt_flags_ |= flag; | |
370 set_interrupt_limits(access); | 349 set_interrupt_limits(access); |
371 } | 350 } |
372 | 351 |
373 | 352 |
374 void StackGuard::ClearInterrupt(InterruptFlag flag) { | 353 void StackGuard::ClearInterrupt(int flagbit) { |
375 ExecutionAccess access(isolate_); | 354 ExecutionAccess access(isolate_); |
376 // Clear the interrupt flag from the chain of PostponeInterruptsScopes. | 355 thread_local_.interrupt_flags_ &= ~flagbit; |
377 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_; | 356 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { |
378 current != NULL; | 357 reset_limits(access); |
379 current = current->prev_) { | |
380 current->intercepted_flags_ &= ~flag; | |
381 } | 358 } |
382 | |
383 // Clear the interrupt flag from the active interrupt flags. | |
384 thread_local_.interrupt_flags_ &= ~flag; | |
385 if (!has_pending_interrupts(access)) reset_limits(access); | |
386 } | 359 } |
387 | 360 |
388 | 361 |
389 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) { | 362 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) { |
390 ExecutionAccess access(isolate_); | 363 ExecutionAccess access(isolate_); |
391 bool result = (thread_local_.interrupt_flags_ & flag); | 364 int flagbit = 1 << flag; |
392 thread_local_.interrupt_flags_ &= ~flag; | 365 bool result = (thread_local_.interrupt_flags_ & flagbit); |
393 if (!has_pending_interrupts(access)) reset_limits(access); | 366 thread_local_.interrupt_flags_ &= ~flagbit; |
| 367 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { |
| 368 reset_limits(access); |
| 369 } |
394 return result; | 370 return result; |
395 } | 371 } |
396 | 372 |
397 | 373 |
398 char* StackGuard::ArchiveStackGuard(char* to) { | 374 char* StackGuard::ArchiveStackGuard(char* to) { |
399 ExecutionAccess access(isolate_); | 375 ExecutionAccess access(isolate_); |
400 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 376 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
401 ThreadLocal blank; | 377 ThreadLocal blank; |
402 | 378 |
403 // Set the stack limits using the old thread_local_. | 379 // Set the stack limits using the old thread_local_. |
(...skipping 21 matching lines...) Expand all Loading... |
425 isolate_->FindOrAllocatePerThreadDataForThisThread(); | 401 isolate_->FindOrAllocatePerThreadDataForThisThread(); |
426 per_thread->set_stack_limit(thread_local_.real_climit_); | 402 per_thread->set_stack_limit(thread_local_.real_climit_); |
427 } | 403 } |
428 | 404 |
429 | 405 |
430 void StackGuard::ThreadLocal::Clear() { | 406 void StackGuard::ThreadLocal::Clear() { |
431 real_jslimit_ = kIllegalLimit; | 407 real_jslimit_ = kIllegalLimit; |
432 jslimit_ = kIllegalLimit; | 408 jslimit_ = kIllegalLimit; |
433 real_climit_ = kIllegalLimit; | 409 real_climit_ = kIllegalLimit; |
434 climit_ = kIllegalLimit; | 410 climit_ = kIllegalLimit; |
435 postpone_interrupts_ = NULL; | 411 nesting_ = 0; |
| 412 postpone_interrupts_nesting_ = 0; |
436 interrupt_flags_ = 0; | 413 interrupt_flags_ = 0; |
437 } | 414 } |
438 | 415 |
439 | 416 |
440 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { | 417 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { |
441 bool should_set_stack_limits = false; | 418 bool should_set_stack_limits = false; |
442 if (real_climit_ == kIllegalLimit) { | 419 if (real_climit_ == kIllegalLimit) { |
443 // Takes the address of the limit variable in order to find out where | 420 // Takes the address of the limit variable in order to find out where |
444 // the top of stack is right now. | 421 // the top of stack is right now. |
445 const uintptr_t kLimitSize = FLAG_stack_size * KB; | 422 const uintptr_t kLimitSize = FLAG_stack_size * KB; |
446 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; | 423 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; |
447 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); | 424 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); |
448 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); | 425 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); |
449 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); | 426 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); |
450 real_climit_ = limit; | 427 real_climit_ = limit; |
451 climit_ = limit; | 428 climit_ = limit; |
452 should_set_stack_limits = true; | 429 should_set_stack_limits = true; |
453 } | 430 } |
454 postpone_interrupts_ = NULL; | 431 nesting_ = 0; |
| 432 postpone_interrupts_nesting_ = 0; |
455 interrupt_flags_ = 0; | 433 interrupt_flags_ = 0; |
456 return should_set_stack_limits; | 434 return should_set_stack_limits; |
457 } | 435 } |
458 | 436 |
459 | 437 |
460 void StackGuard::ClearThread(const ExecutionAccess& lock) { | 438 void StackGuard::ClearThread(const ExecutionAccess& lock) { |
461 thread_local_.Clear(); | 439 thread_local_.Clear(); |
462 isolate_->heap()->SetStackLimits(); | 440 isolate_->heap()->SetStackLimits(); |
463 } | 441 } |
464 | 442 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 Handle<Object> result; | 641 Handle<Object> result; |
664 if (!maybe_result.ToHandle(&result) || !result->IsString()) { | 642 if (!maybe_result.ToHandle(&result) || !result->IsString()) { |
665 return isolate->factory()->empty_string(); | 643 return isolate->factory()->empty_string(); |
666 } | 644 } |
667 | 645 |
668 return Handle<String>::cast(result); | 646 return Handle<String>::cast(result); |
669 } | 647 } |
670 | 648 |
671 | 649 |
672 Object* StackGuard::HandleInterrupts() { | 650 Object* StackGuard::HandleInterrupts() { |
| 651 { |
| 652 ExecutionAccess access(isolate_); |
| 653 if (should_postpone_interrupts(access)) { |
| 654 return isolate_->heap()->undefined_value(); |
| 655 } |
| 656 } |
| 657 |
673 if (CheckAndClearInterrupt(GC_REQUEST)) { | 658 if (CheckAndClearInterrupt(GC_REQUEST)) { |
674 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt"); | 659 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt"); |
675 } | 660 } |
676 | 661 |
677 if (CheckDebugBreak() || CheckDebugCommand()) { | 662 if (CheckDebugBreak() || CheckDebugCommand()) { |
678 isolate_->debug()->HandleDebugBreak(); | 663 isolate_->debug()->HandleDebugBreak(); |
679 } | 664 } |
680 | 665 |
681 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) { | 666 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) { |
682 return isolate_->TerminateExecution(); | 667 return isolate_->TerminateExecution(); |
(...skipping 14 matching lines...) Expand all Loading... |
697 } | 682 } |
698 | 683 |
699 isolate_->counters()->stack_interrupts()->Increment(); | 684 isolate_->counters()->stack_interrupts()->Increment(); |
700 isolate_->counters()->runtime_profiler_ticks()->Increment(); | 685 isolate_->counters()->runtime_profiler_ticks()->Increment(); |
701 isolate_->runtime_profiler()->OptimizeNow(); | 686 isolate_->runtime_profiler()->OptimizeNow(); |
702 | 687 |
703 return isolate_->heap()->undefined_value(); | 688 return isolate_->heap()->undefined_value(); |
704 } | 689 } |
705 | 690 |
706 } } // namespace v8::internal | 691 } } // namespace v8::internal |
OLD | NEW |