| 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 |