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