Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: src/execution.cc

Issue 359963004: Reland "Add mechanism to postpone interrupts selectively." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/execution.h ('k') | src/isolate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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;
25 thread_local_.jslimit_ = kInterruptLimit; 23 thread_local_.jslimit_ = kInterruptLimit;
26 thread_local_.climit_ = kInterruptLimit; 24 thread_local_.climit_ = kInterruptLimit;
27 isolate_->heap()->SetStackLimits(); 25 isolate_->heap()->SetStackLimits();
28 } 26 }
29 27
30 28
31 void StackGuard::reset_limits(const ExecutionAccess& lock) { 29 void StackGuard::reset_limits(const ExecutionAccess& lock) {
32 ASSERT(isolate_ != NULL); 30 ASSERT(isolate_ != NULL);
33 thread_local_.jslimit_ = thread_local_.real_jslimit_; 31 thread_local_.jslimit_ = thread_local_.real_jslimit_;
34 thread_local_.climit_ = thread_local_.real_climit_; 32 thread_local_.climit_ = thread_local_.real_climit_;
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 thread_local_.real_jslimit_ = jslimit; 328 thread_local_.real_jslimit_ = jslimit;
331 } 329 }
332 330
333 331
334 void StackGuard::DisableInterrupts() { 332 void StackGuard::DisableInterrupts() {
335 ExecutionAccess access(isolate_); 333 ExecutionAccess access(isolate_);
336 reset_limits(access); 334 reset_limits(access);
337 } 335 }
338 336
339 337
340 bool StackGuard::CheckInterrupt(int flagbit) { 338 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
341 ExecutionAccess access(isolate_); 339 ExecutionAccess access(isolate_);
342 return thread_local_.interrupt_flags_ & flagbit; 340 // Intercept already requested interrupts.
341 int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
342 scope->intercepted_flags_ = intercepted;
343 thread_local_.interrupt_flags_ &= ~intercepted;
344 if (!has_pending_interrupts(access)) reset_limits(access);
345 // Add scope to the chain.
346 scope->prev_ = thread_local_.postpone_interrupts_;
347 thread_local_.postpone_interrupts_ = scope;
343 } 348 }
344 349
345 350
346 void StackGuard::RequestInterrupt(int flagbit) { 351 void StackGuard::PopPostponeInterruptsScope() {
347 ExecutionAccess access(isolate_); 352 ExecutionAccess access(isolate_);
348 thread_local_.interrupt_flags_ |= flagbit; 353 PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
354 // Make intercepted interrupts active.
355 ASSERT((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
356 thread_local_.interrupt_flags_ |= top->intercepted_flags_;
357 if (has_pending_interrupts(access)) set_interrupt_limits(access);
358 // Remove scope from chain.
359 thread_local_.postpone_interrupts_ = top->prev_;
360 }
361
362
363 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
364 ExecutionAccess access(isolate_);
365 return thread_local_.interrupt_flags_ & flag;
366 }
367
368
369 void StackGuard::RequestInterrupt(InterruptFlag flag) {
370 ExecutionAccess access(isolate_);
371 // Check the chain of PostponeInterruptsScopes for interception.
372 if (thread_local_.postpone_interrupts_ &&
373 thread_local_.postpone_interrupts_->Intercept(flag)) {
374 return;
375 }
376
377 // Not intercepted. Set as active interrupt flag.
378 thread_local_.interrupt_flags_ |= flag;
349 set_interrupt_limits(access); 379 set_interrupt_limits(access);
350 } 380 }
351 381
352 382
353 void StackGuard::ClearInterrupt(int flagbit) { 383 void StackGuard::ClearInterrupt(InterruptFlag flag) {
354 ExecutionAccess access(isolate_); 384 ExecutionAccess access(isolate_);
355 thread_local_.interrupt_flags_ &= ~flagbit; 385 // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
356 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { 386 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
357 reset_limits(access); 387 current != NULL;
388 current = current->prev_) {
389 current->intercepted_flags_ &= ~flag;
358 } 390 }
391
392 // Clear the interrupt flag from the active interrupt flags.
393 thread_local_.interrupt_flags_ &= ~flag;
394 if (!has_pending_interrupts(access)) reset_limits(access);
359 } 395 }
360 396
361 397
362 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) { 398 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
363 ExecutionAccess access(isolate_); 399 ExecutionAccess access(isolate_);
364 int flagbit = 1 << flag; 400 bool result = (thread_local_.interrupt_flags_ & flag);
365 bool result = (thread_local_.interrupt_flags_ & flagbit); 401 thread_local_.interrupt_flags_ &= ~flag;
366 thread_local_.interrupt_flags_ &= ~flagbit; 402 if (!has_pending_interrupts(access)) reset_limits(access);
367 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
368 reset_limits(access);
369 }
370 return result; 403 return result;
371 } 404 }
372 405
373 406
374 char* StackGuard::ArchiveStackGuard(char* to) { 407 char* StackGuard::ArchiveStackGuard(char* to) {
375 ExecutionAccess access(isolate_); 408 ExecutionAccess access(isolate_);
376 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); 409 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
377 ThreadLocal blank; 410 ThreadLocal blank;
378 411
379 // Set the stack limits using the old thread_local_. 412 // Set the stack limits using the old thread_local_.
(...skipping 21 matching lines...) Expand all
401 isolate_->FindOrAllocatePerThreadDataForThisThread(); 434 isolate_->FindOrAllocatePerThreadDataForThisThread();
402 per_thread->set_stack_limit(thread_local_.real_climit_); 435 per_thread->set_stack_limit(thread_local_.real_climit_);
403 } 436 }
404 437
405 438
406 void StackGuard::ThreadLocal::Clear() { 439 void StackGuard::ThreadLocal::Clear() {
407 real_jslimit_ = kIllegalLimit; 440 real_jslimit_ = kIllegalLimit;
408 jslimit_ = kIllegalLimit; 441 jslimit_ = kIllegalLimit;
409 real_climit_ = kIllegalLimit; 442 real_climit_ = kIllegalLimit;
410 climit_ = kIllegalLimit; 443 climit_ = kIllegalLimit;
411 nesting_ = 0; 444 postpone_interrupts_ = NULL;
412 postpone_interrupts_nesting_ = 0;
413 interrupt_flags_ = 0; 445 interrupt_flags_ = 0;
414 } 446 }
415 447
416 448
417 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { 449 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
418 bool should_set_stack_limits = false; 450 bool should_set_stack_limits = false;
419 if (real_climit_ == kIllegalLimit) { 451 if (real_climit_ == kIllegalLimit) {
420 // Takes the address of the limit variable in order to find out where 452 // Takes the address of the limit variable in order to find out where
421 // the top of stack is right now. 453 // the top of stack is right now.
422 const uintptr_t kLimitSize = FLAG_stack_size * KB; 454 const uintptr_t kLimitSize = FLAG_stack_size * KB;
423 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; 455 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
424 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); 456 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
425 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 457 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
426 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 458 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
427 real_climit_ = limit; 459 real_climit_ = limit;
428 climit_ = limit; 460 climit_ = limit;
429 should_set_stack_limits = true; 461 should_set_stack_limits = true;
430 } 462 }
431 nesting_ = 0; 463 postpone_interrupts_ = NULL;
432 postpone_interrupts_nesting_ = 0;
433 interrupt_flags_ = 0; 464 interrupt_flags_ = 0;
434 return should_set_stack_limits; 465 return should_set_stack_limits;
435 } 466 }
436 467
437 468
438 void StackGuard::ClearThread(const ExecutionAccess& lock) { 469 void StackGuard::ClearThread(const ExecutionAccess& lock) {
439 thread_local_.Clear(); 470 thread_local_.Clear();
440 isolate_->heap()->SetStackLimits(); 471 isolate_->heap()->SetStackLimits();
441 } 472 }
442 473
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 Handle<Object> result; 672 Handle<Object> result;
642 if (!maybe_result.ToHandle(&result) || !result->IsString()) { 673 if (!maybe_result.ToHandle(&result) || !result->IsString()) {
643 return isolate->factory()->empty_string(); 674 return isolate->factory()->empty_string();
644 } 675 }
645 676
646 return Handle<String>::cast(result); 677 return Handle<String>::cast(result);
647 } 678 }
648 679
649 680
650 Object* StackGuard::HandleInterrupts() { 681 Object* StackGuard::HandleInterrupts() {
651 {
652 ExecutionAccess access(isolate_);
653 if (should_postpone_interrupts(access)) {
654 return isolate_->heap()->undefined_value();
655 }
656 }
657
658 if (CheckAndClearInterrupt(GC_REQUEST)) { 682 if (CheckAndClearInterrupt(GC_REQUEST)) {
659 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt"); 683 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt");
660 } 684 }
661 685
662 if (CheckDebugBreak() || CheckDebugCommand()) { 686 if (CheckDebugBreak() || CheckDebugCommand()) {
663 isolate_->debug()->HandleDebugBreak(); 687 isolate_->debug()->HandleDebugBreak();
664 } 688 }
665 689
666 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) { 690 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
667 return isolate_->TerminateExecution(); 691 return isolate_->TerminateExecution();
(...skipping 14 matching lines...) Expand all
682 } 706 }
683 707
684 isolate_->counters()->stack_interrupts()->Increment(); 708 isolate_->counters()->stack_interrupts()->Increment();
685 isolate_->counters()->runtime_profiler_ticks()->Increment(); 709 isolate_->counters()->runtime_profiler_ticks()->Increment();
686 isolate_->runtime_profiler()->OptimizeNow(); 710 isolate_->runtime_profiler()->OptimizeNow();
687 711
688 return isolate_->heap()->undefined_value(); 712 return isolate_->heap()->undefined_value();
689 } 713 }
690 714
691 } } // namespace v8::internal 715 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/execution.h ('k') | src/isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698