| OLD | NEW |
| 1 // Copyright 2007-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2007-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 5640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5651 context1->Global()->Set(v8_str("other"), context0->Global()); | 5651 context1->Global()->Set(v8_str("other"), context0->Global()); |
| 5652 Local<Value> value = CompileRun("var instance = new other.C(); instance.x"); | 5652 Local<Value> value = CompileRun("var instance = new other.C(); instance.x"); |
| 5653 CHECK(value->IsInt32()); | 5653 CHECK(value->IsInt32()); |
| 5654 CHECK_EQ(42, value->Int32Value()); | 5654 CHECK_EQ(42, value->Int32Value()); |
| 5655 context1->Exit(); | 5655 context1->Exit(); |
| 5656 | 5656 |
| 5657 // Dispose the contexts to allow them to be garbage collected. | 5657 // Dispose the contexts to allow them to be garbage collected. |
| 5658 context0.Dispose(); | 5658 context0.Dispose(); |
| 5659 context1.Dispose(); | 5659 context1.Dispose(); |
| 5660 } | 5660 } |
| 5661 |
| 5662 |
| 5663 class RegExpInterruptTest { |
| 5664 public: |
| 5665 void RunTest() { |
| 5666 block_ = i::OS::CreateSemaphore(0); |
| 5667 gc_count_ = 0; |
| 5668 gc_during_regexp_ = 0; |
| 5669 regexp_success_ = false; |
| 5670 gc_success_ = false; |
| 5671 GCThread gc_thread(this); |
| 5672 gc_thread.Start(); |
| 5673 v8::Locker::StartPreemption(1); |
| 5674 |
| 5675 LongRunningRegExp(); |
| 5676 { |
| 5677 v8::Unlocker unlock; |
| 5678 gc_thread.Join(); |
| 5679 } |
| 5680 v8::Locker::StopPreemption(); |
| 5681 CHECK(regexp_success_); |
| 5682 CHECK(gc_success_); |
| 5683 } |
| 5684 private: |
| 5685 // Number of garbage collections required. |
| 5686 static const int kRequiredGCs = 5; |
| 5687 |
| 5688 class GCThread : public i::Thread { |
| 5689 public: |
| 5690 explicit GCThread(RegExpInterruptTest* test) |
| 5691 : test_(test) {} |
| 5692 virtual void Run() { |
| 5693 test_->CollectGarbage(); |
| 5694 } |
| 5695 private: |
| 5696 RegExpInterruptTest* test_; |
| 5697 }; |
| 5698 |
| 5699 void CollectGarbage() { |
| 5700 block_->Wait(); |
| 5701 while (gc_during_regexp_ < kRequiredGCs) { |
| 5702 { |
| 5703 v8::Locker lock; |
| 5704 // TODO(lrn): Perhaps create some garbage before collecting. |
| 5705 i::Heap::CollectAllGarbage(); |
| 5706 gc_count_++; |
| 5707 } |
| 5708 i::OS::Sleep(1); |
| 5709 } |
| 5710 gc_success_ = true; |
| 5711 } |
| 5712 |
| 5713 void LongRunningRegExp() { |
| 5714 block_->Signal(); // Enable garbage collection thread on next preemption. |
| 5715 int rounds = 0; |
| 5716 while (gc_during_regexp_ < kRequiredGCs) { |
| 5717 int gc_before = gc_count_; |
| 5718 { |
| 5719 // match 15-30 "a"'s against 14 and a "b". |
| 5720 const char* c_source = |
| 5721 "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/" |
| 5722 ".exec('aaaaaaaaaaaaaaab') === null"; |
| 5723 Local<String> source = String::New(c_source); |
| 5724 Local<Script> script = Script::Compile(source); |
| 5725 Local<Value> result = script->Run(); |
| 5726 if (!result->BooleanValue()) { |
| 5727 gc_during_regexp_ = kRequiredGCs; // Allow gc thread to exit. |
| 5728 return; |
| 5729 } |
| 5730 } |
| 5731 { |
| 5732 // match 15-30 "a"'s against 15 and a "b". |
| 5733 const char* c_source = |
| 5734 "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/" |
| 5735 ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'"; |
| 5736 Local<String> source = String::New(c_source); |
| 5737 Local<Script> script = Script::Compile(source); |
| 5738 Local<Value> result = script->Run(); |
| 5739 if (!result->BooleanValue()) { |
| 5740 gc_during_regexp_ = kRequiredGCs; |
| 5741 return; |
| 5742 } |
| 5743 } |
| 5744 int gc_after = gc_count_; |
| 5745 gc_during_regexp_ += gc_after - gc_before; |
| 5746 rounds++; |
| 5747 i::OS::Sleep(1); |
| 5748 } |
| 5749 regexp_success_ = true; |
| 5750 } |
| 5751 |
| 5752 i::Semaphore* block_; |
| 5753 int gc_count_; |
| 5754 int gc_during_regexp_; |
| 5755 bool regexp_success_; |
| 5756 bool gc_success_; |
| 5757 }; |
| 5758 |
| 5759 |
| 5760 // Test that a regular expression execution can be interrupted and |
| 5761 // survive a garbage collection. |
| 5762 TEST(RegExpInterruption) { |
| 5763 v8::Locker lock; |
| 5764 v8::V8::Initialize(); |
| 5765 v8::HandleScope scope; |
| 5766 Local<Context> local_env; |
| 5767 { |
| 5768 LocalContext env; |
| 5769 local_env = env.local(); |
| 5770 } |
| 5771 |
| 5772 // Local context should still be live. |
| 5773 CHECK(!local_env.IsEmpty()); |
| 5774 local_env->Enter(); |
| 5775 |
| 5776 // Should complete without problems. |
| 5777 RegExpInterruptTest().RunTest(); |
| 5778 |
| 5779 local_env->Exit(); |
| 5780 } |
| OLD | NEW |