1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2008 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h" 318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "isolate.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "cctest.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Preemption) { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Locker locker; 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::V8::Initialize(); 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Context::Scope context_scope(v8::Context::New()); 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Locker::StartPreemption(100); 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Script> script = v8::Script::Compile( 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::String::New("var count = 0; var obj = new Object(); count++;\n")); 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block script->Run(); 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Locker::StopPreemption(); 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::OS::Sleep(500); // Make sure the timer fires. 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block script->Run(); 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 566ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockenum Turn { 576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FILL_CACHE, 586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CLEAN_CACHE, 596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SECOND_TIME_FILL_CACHE, 606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DONE 616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 636ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Turn turn = FILL_CACHE; 646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass ThreadA : public v8::internal::Thread { 676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ThreadA() : Thread("ThreadA") { } 696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Run() { 706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::Locker locker; 716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::HandleScope scope; 726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::Context::Scope context_scope(v8::Context::New()); 736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CHECK_EQ(FILL_CACHE, turn); 756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Fill String.search cache. 776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::Handle<v8::Script> script = v8::Script::Compile( 786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::String::New( 796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block "for (var i = 0; i < 3; i++) {" 806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block " var result = \"a\".search(\"a\");" 816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block " if (result != 0) throw \"result: \" + result + \" @\" + i;" 826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block "};" 836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block "true")); 846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CHECK(script->Run()->IsTrue()); 856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block turn = CLEAN_CACHE; 876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block do { 886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block { 896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::Unlocker unlocker; 906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Thread::YieldCPU(); 916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } while (turn != SECOND_TIME_FILL_CACHE); 936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Rerun the script. 956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CHECK(script->Run()->IsTrue()); 966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block turn = DONE; 986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass ThreadB : public v8::internal::Thread { 1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 1043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ThreadB() : Thread("ThreadB") { } 1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Run() { 1066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block do { 1076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block { 1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::Locker locker; 1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (turn == CLEAN_CACHE) { 1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::HandleScope scope; 1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::Context::Scope context_scope(v8::Context::New()); 1126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Clear the caches by forcing major GC. 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HEAP->CollectAllGarbage(v8::internal::Heap::kNoGCFlags); 1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block turn = SECOND_TIME_FILL_CACHE; 1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 1176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Thread::YieldCPU(); 1216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } while (true); 1226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 1246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1266ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTEST(JSFunctionResultCachesInTwoThreads) { 1276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::V8::Initialize(); 1286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ThreadA threadA; 1303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ThreadB threadB; 1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block threadA.Start(); 1336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block threadB.Start(); 1346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block threadA.Join(); 1366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block threadB.Join(); 1376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CHECK_EQ(DONE, turn); 1396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 1408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass ThreadIdValidationThread : public v8::internal::Thread { 1428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public: 1438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadIdValidationThread(i::Thread* thread_to_start, 1448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::List<i::ThreadId>* refs, 1458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch unsigned int thread_no, 1468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::Semaphore* semaphore) 1473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : Thread("ThreadRefValidationThread"), 1488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch refs_(refs), thread_no_(thread_no), thread_to_start_(thread_to_start), 1498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch semaphore_(semaphore) { 1508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void Run() { 1538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::ThreadId thread_id = i::ThreadId::Current(); 1548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (int i = 0; i < thread_no_; i++) { 1558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK(!(*refs_)[i].Equals(thread_id)); 1568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK(thread_id.IsValid()); 1588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch (*refs_)[thread_no_] = thread_id; 1598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (thread_to_start_ != NULL) { 1608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch thread_to_start_->Start(); 1618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch semaphore_->Signal(); 1638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 1668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::List<i::ThreadId>* refs_; 1678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int thread_no_; 1688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::Thread* thread_to_start_; 1698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::Semaphore* semaphore_; 1708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}; 1718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1728b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTEST(ThreadIdValidation) { 1738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const int kNThreads = 100; 1748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::List<ThreadIdValidationThread*> threads(kNThreads); 1758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::List<i::ThreadId> refs(kNThreads); 1768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::Semaphore* semaphore = i::OS::CreateSemaphore(0); 1778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadIdValidationThread* prev = NULL; 1788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (int i = kNThreads - 1; i >= 0; i--) { 1798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadIdValidationThread* newThread = 1808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new ThreadIdValidationThread(prev, &refs, i, semaphore); 1818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch threads.Add(newThread); 1828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch prev = newThread; 1838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch refs.Add(i::ThreadId::Invalid()); 1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch prev->Start(); 1868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (int i = 0; i < kNThreads; i++) { 1878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch semaphore->Wait(); 1888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (int i = 0; i < kNThreads; i++) { 1908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete threads[i]; 1918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass ThreadC : public v8::internal::Thread { 1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ThreadC() : Thread("ThreadC") { } 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Run() { 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Join(); 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}; 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(ThreadJoinSelf) { 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ThreadC thread; 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch thread.Start(); 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch thread.Join(); 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 209