1c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// Copyright 2009 the V8 project authors. All rights reserved.
2c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// Redistribution and use in source and binary forms, with or without
3c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// modification, are permitted provided that the following conditions are
4c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// met:
5c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//
6c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//     * Redistributions of source code must retain the above copyright
7c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//       notice, this list of conditions and the following disclaimer.
8c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//     * Redistributions in binary form must reproduce the above
9c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//       copyright notice, this list of conditions and the following
10c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//       disclaimer in the documentation and/or other materials provided
11c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//       with the distribution.
12c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//     * Neither the name of Google Inc. nor the names of its
13c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//       contributors may be used to endorse or promote products derived
14c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//       from this software without specific prior written permission.
15c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org//
16c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
28196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
29196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/cctest.h"
30c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
315de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/platform.h"
324b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org
33c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
345de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgv8::base::Semaphore* semaphore = NULL;
35c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
36c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
371510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid Signal(const v8::FunctionCallbackInfo<v8::Value>& args) {
38c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  semaphore->Signal();
39c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org}
40c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
41c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
421510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid TerminateCurrentThread(const v8::FunctionCallbackInfo<v8::Value>& args) {
43528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
44528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  v8::V8::TerminateExecution(args.GetIsolate());
45c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org}
46c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
47c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
481510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
49c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  CHECK(false);
50c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org}
51c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
52c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
531510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid Loop(const v8::FunctionCallbackInfo<v8::Value>& args) {
54528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
55f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::String> source = v8::String::NewFromUtf8(
56f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      args.GetIsolate(), "try { doloop(); fail(); } catch(e) { fail(); }");
572ab99526496cda7ff426115c76a1c475a1b4f4a5sgjesse@chromium.org  v8::Handle<v8::Value> result = v8::Script::Compile(source)->Run();
582ab99526496cda7ff426115c76a1c475a1b4f4a5sgjesse@chromium.org  CHECK(result.IsEmpty());
59528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate()));
60c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org}
61c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
62c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid DoLoop(const v8::FunctionCallbackInfo<v8::Value>& args) {
64c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  v8::TryCatch try_catch;
65528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
66f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(),
67f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "function f() {"
68f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  var term = true;"
69f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  try {"
70f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "    while(true) {"
71f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "      if (term) terminate();"
72f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "      term = false;"
73f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "    }"
74f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "    fail();"
75f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  } catch(e) {"
76f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "    fail();"
77f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  }"
78f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "}"
79f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "f()"))->Run();
80c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  CHECK(try_catch.HasCaught());
81c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  CHECK(try_catch.Exception()->IsNull());
82c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  CHECK(try_catch.Message().IsEmpty());
83c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  CHECK(!try_catch.CanContinue());
84528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate()));
85c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org}
86c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
87c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
881510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid DoLoopNoCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
8901beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  v8::TryCatch try_catch;
90528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
91f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(),
92f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "var term = true;"
93f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "while(true) {"
94f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  if (term) terminate();"
95f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  term = false;"
96f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "}"))->Run();
9701beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  CHECK(try_catch.HasCaught());
9801beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  CHECK(try_catch.Exception()->IsNull());
9901beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  CHECK(try_catch.Message().IsEmpty());
10001beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  CHECK(!try_catch.CanContinue());
101528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate()));
10201beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org}
10301beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org
10401beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org
105c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.orgv8::Handle<v8::ObjectTemplate> CreateGlobalTemplate(
106f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    v8::Isolate* isolate,
1071510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    v8::FunctionCallback terminate,
1081510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    v8::FunctionCallback doloop) {
1099cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
110f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  global->Set(v8::String::NewFromUtf8(isolate, "terminate"),
1114f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org              v8::FunctionTemplate::New(isolate, terminate));
112f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  global->Set(v8::String::NewFromUtf8(isolate, "fail"),
1134f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org              v8::FunctionTemplate::New(isolate, Fail));
114f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  global->Set(v8::String::NewFromUtf8(isolate, "loop"),
1154f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org              v8::FunctionTemplate::New(isolate, Loop));
116f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  global->Set(v8::String::NewFromUtf8(isolate, "doloop"),
1174f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org              v8::FunctionTemplate::New(isolate, doloop));
118c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  return global;
119c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org}
120c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
121c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
122c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// Test that a single thread of JavaScript execution can terminate
123c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// itself.
124c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.orgTEST(TerminateOnlyV8ThreadFromThreadItself) {
125528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  v8::HandleScope scope(CcTest::isolate());
126c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  v8::Handle<v8::ObjectTemplate> global =
127f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      CreateGlobalTemplate(CcTest::isolate(), TerminateCurrentThread, DoLoop);
12857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  v8::Handle<v8::Context> context =
129528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      v8::Context::New(CcTest::isolate(), NULL, global);
13001beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  v8::Context::Scope context_scope(context);
131528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate()));
13201beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  // Run a loop that will be infinite if thread termination does not work.
133f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::String> source = v8::String::NewFromUtf8(
134f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      CcTest::isolate(), "try { loop(); fail(); } catch(e) { fail(); }");
13501beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  v8::Script::Compile(source)->Run();
13601beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  // Test that we can run the code again after thread termination.
137528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate()));
13801beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org  v8::Script::Compile(source)->Run();
13901beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org}
14001beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org
14101beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org
14201beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org// Test that a single thread of JavaScript execution can terminate
14301beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org// itself in a loop that performs no calls.
14401beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.orgTEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) {
145528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  v8::HandleScope scope(CcTest::isolate());
146f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(
147f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      CcTest::isolate(), TerminateCurrentThread, DoLoopNoCall);
14857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  v8::Handle<v8::Context> context =
149528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      v8::Context::New(CcTest::isolate(), NULL, global);
150c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  v8::Context::Scope context_scope(context);
151528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate()));
152c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  // Run a loop that will be infinite if thread termination does not work.
153f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::String> source = v8::String::NewFromUtf8(
154f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      CcTest::isolate(), "try { loop(); fail(); } catch(e) { fail(); }");
155c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  v8::Script::Compile(source)->Run();
156528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate()));
157c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  // Test that we can run the code again after thread termination.
158c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  v8::Script::Compile(source)->Run();
159c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org}
160c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
161c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
1625de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgclass TerminatorThread : public v8::base::Thread {
163ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org public:
164ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  explicit TerminatorThread(i::Isolate* isolate)
1655e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      : Thread(Options("TerminatorThread")),
1665e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        isolate_(reinterpret_cast<v8::Isolate*>(isolate)) {}
167c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  void Run() {
168c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org    semaphore->Wait();
1696d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    CHECK(!v8::V8::IsExecutionTerminating(isolate_));
1706d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    v8::V8::TerminateExecution(isolate_);
171c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  }
1726d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org
1736d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org private:
1746d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  v8::Isolate* isolate_;
175c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org};
176c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
177c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
178c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// Test that a single thread of JavaScript execution can be terminated
179c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org// from the side by another thread.
180c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.orgTEST(TerminateOnlyV8ThreadFromOtherThread) {
1815de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  semaphore = new v8::base::Semaphore(0);
182528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  TerminatorThread thread(CcTest::i_isolate());
183c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  thread.Start();
184c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
185528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  v8::HandleScope scope(CcTest::isolate());
186f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::ObjectTemplate> global =
187f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      CreateGlobalTemplate(CcTest::isolate(), Signal, DoLoop);
18857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  v8::Handle<v8::Context> context =
189528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      v8::Context::New(CcTest::isolate(), NULL, global);
190c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  v8::Context::Scope context_scope(context);
191528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate()));
192c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  // Run a loop that will be infinite if thread termination does not work.
193f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::String> source = v8::String::NewFromUtf8(
194f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      CcTest::isolate(), "try { loop(); fail(); } catch(e) { fail(); }");
195c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  v8::Script::Compile(source)->Run();
196c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
197c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  thread.Join();
198c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  delete semaphore;
199c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  semaphore = NULL;
200c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org}
201c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
202c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org
20318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgint call_count = 0;
20418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
20518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
2061510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid TerminateOrReturnObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
20718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (++call_count == 10) {
208528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
209528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    v8::V8::TerminateExecution(args.GetIsolate());
2101510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    return;
21118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
2120f13e74b7310d8b14f19c6b93b36ff95059f97f6ulan@chromium.org  v8::Local<v8::Object> result = v8::Object::New(args.GetIsolate());
213f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  result->Set(v8::String::NewFromUtf8(args.GetIsolate(), "x"),
2140f13e74b7310d8b14f19c6b93b36ff95059f97f6ulan@chromium.org              v8::Integer::New(args.GetIsolate(), 42));
2151510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  args.GetReturnValue().Set(result);
21618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
21718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
21818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
2191510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid LoopGetProperty(const v8::FunctionCallbackInfo<v8::Value>& args) {
22018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  v8::TryCatch try_catch;
221528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
222f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Script::Compile(
223f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      v8::String::NewFromUtf8(args.GetIsolate(),
224f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "function f() {"
225f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "  try {"
226f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "    while(true) {"
227f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "      terminate_or_return_object().x;"
228f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "    }"
229f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "    fail();"
230f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "  } catch(e) {"
231f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "    fail();"
232f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "  }"
233f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "}"
234f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "f()"))->Run();
23518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  CHECK(try_catch.HasCaught());
23618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  CHECK(try_catch.Exception()->IsNull());
23718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  CHECK(try_catch.Message().IsEmpty());
23818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  CHECK(!try_catch.CanContinue());
239528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate()));
24018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
24118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
24218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
24318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org// Test that we correctly handle termination exceptions if they are
24418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org// triggered by the creation of error objects in connection with ICs.
24518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgTEST(TerminateLoadICException) {
2464f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  v8::Isolate* isolate = CcTest::isolate();
2474f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  v8::HandleScope scope(isolate);
2489cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
249f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  global->Set(
2504f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org      v8::String::NewFromUtf8(isolate, "terminate_or_return_object"),
2514f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org      v8::FunctionTemplate::New(isolate, TerminateOrReturnObject));
2524f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  global->Set(v8::String::NewFromUtf8(isolate, "fail"),
2534f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org              v8::FunctionTemplate::New(isolate, Fail));
2544f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  global->Set(v8::String::NewFromUtf8(isolate, "loop"),
2554f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org              v8::FunctionTemplate::New(isolate, LoopGetProperty));
25618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
25757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  v8::Handle<v8::Context> context =
2584f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org      v8::Context::New(isolate, NULL, global);
25918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  v8::Context::Scope context_scope(context);
2604f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(isolate));
26118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Run a loop that will be infinite if thread termination does not work.
262f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::String> source = v8::String::NewFromUtf8(
2634f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org      isolate, "try { loop(); fail(); } catch(e) { fail(); }");
26418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  call_count = 0;
26518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  v8::Script::Compile(source)->Run();
26618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Test that we can run the code again after thread termination.
2674f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(isolate));
26818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  call_count = 0;
26918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  v8::Script::Compile(source)->Run();
27018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
2719155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org
272e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
2731510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid ReenterAfterTermination(const v8::FunctionCallbackInfo<v8::Value>& args) {
2749155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  v8::TryCatch try_catch;
275528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
276f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(),
277f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "function f() {"
278f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  var term = true;"
279f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  try {"
280f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "    while(true) {"
281f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "      if (term) terminate();"
282f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "      term = false;"
283f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "    }"
284f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "    fail();"
285f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  } catch(e) {"
286f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "    fail();"
287f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  }"
288f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "}"
289f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "f()"))->Run();
2909155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  CHECK(try_catch.HasCaught());
2919155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  CHECK(try_catch.Exception()->IsNull());
2929155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  CHECK(try_catch.Message().IsEmpty());
2939155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  CHECK(!try_catch.CanContinue());
294528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate()));
295f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(),
296f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "function f() { fail(); } f()"))
297f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      ->Run();
2989155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org}
2999155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org
300e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
3019155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org// Test that reentry into V8 while the termination exception is still pending
3029155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org// (has not yet unwound the 0-level JS frame) does not crash.
3039155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.orgTEST(TerminateAndReenterFromThreadItself) {
3044f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  v8::Isolate* isolate = CcTest::isolate();
3054f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  v8::HandleScope scope(isolate);
306f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(
3074f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org      isolate, TerminateCurrentThread, ReenterAfterTermination);
30857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  v8::Handle<v8::Context> context =
3094f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org      v8::Context::New(isolate, NULL, global);
3109155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  v8::Context::Scope context_scope(context);
3119155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  CHECK(!v8::V8::IsExecutionTerminating());
312f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::String> source = v8::String::NewFromUtf8(
3134f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org      isolate, "try { loop(); fail(); } catch(e) { fail(); }");
3149155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  v8::Script::Compile(source)->Run();
3154f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(isolate));
3169155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  // Check we can run JS again after termination.
317f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  CHECK(v8::Script::Compile(
3184f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org      v8::String::NewFromUtf8(isolate,
319f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "function f() { return true; }"
320f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                              "f()"))
321f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            ->Run()
322f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            ->IsTrue());
3239155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org}
32432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org
325e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
3261510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid DoLoopCancelTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
32732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  v8::TryCatch try_catch;
32832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  CHECK(!v8::V8::IsExecutionTerminating());
329f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(),
330f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "var term = true;"
331f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "while(true) {"
332f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  if (term) terminate();"
333f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "  term = false;"
334f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "}"
335f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                              "fail();"))->Run();
33632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  CHECK(try_catch.HasCaught());
33732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  CHECK(try_catch.Exception()->IsNull());
33832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  CHECK(try_catch.Message().IsEmpty());
33932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  CHECK(!try_catch.CanContinue());
34032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  CHECK(v8::V8::IsExecutionTerminating());
34132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  CHECK(try_catch.HasTerminated());
342528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  v8::V8::CancelTerminateExecution(CcTest::isolate());
34332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  CHECK(!v8::V8::IsExecutionTerminating());
34432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org}
34532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org
346e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
34732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// Test that a single thread of JavaScript execution can terminate
34832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// itself and then resume execution.
34932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.orgTEST(TerminateCancelTerminateFromThreadItself) {
350528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  v8::Isolate* isolate = CcTest::isolate();
351c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  v8::HandleScope scope(isolate);
352f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(
353f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      isolate, TerminateCurrentThread, DoLoopCancelTerminate);
354c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  v8::Handle<v8::Context> context = v8::Context::New(isolate, NULL, global);
35532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  v8::Context::Scope context_scope(context);
356528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate()));
357f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::String> source = v8::String::NewFromUtf8(
358f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      isolate, "try { doloop(); } catch(e) { fail(); } 'completed';");
35932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  // Check that execution completed with correct return value.
36032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  CHECK(v8::Script::Compile(source)->Run()->Equals(v8_str("completed")));
36132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org}
362e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
363e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
364e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.orgvoid MicrotaskShouldNotRun(const v8::FunctionCallbackInfo<v8::Value>& info) {
365e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  CHECK(false);
366e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org}
367e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
368e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
369e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.orgvoid MicrotaskLoopForever(const v8::FunctionCallbackInfo<v8::Value>& info) {
370e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  v8::Isolate* isolate = info.GetIsolate();
371e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  v8::HandleScope scope(isolate);
372e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  // Enqueue another should-not-run task to ensure we clean out the queue
373e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  // when we terminate.
374e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  isolate->EnqueueMicrotask(v8::Function::New(isolate, MicrotaskShouldNotRun));
375e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  CompileRun("terminate(); while (true) { }");
376e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  CHECK(v8::V8::IsExecutionTerminating());
377e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org}
378e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
379e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
380e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.orgTEST(TerminateFromOtherThreadWhileMicrotaskRunning) {
3815de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  semaphore = new v8::base::Semaphore(0);
382e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  TerminatorThread thread(CcTest::i_isolate());
383e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  thread.Start();
384e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
385e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  v8::Isolate* isolate = CcTest::isolate();
386e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  isolate->SetAutorunMicrotasks(false);
387e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  v8::HandleScope scope(isolate);
388e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  v8::Handle<v8::ObjectTemplate> global =
389e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org      CreateGlobalTemplate(CcTest::isolate(), Signal, DoLoop);
390e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  v8::Handle<v8::Context> context =
391e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org      v8::Context::New(CcTest::isolate(), NULL, global);
392e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  v8::Context::Scope context_scope(context);
393e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  isolate->EnqueueMicrotask(v8::Function::New(isolate, MicrotaskLoopForever));
394e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  // The second task should never be run because we bail out if we're
395e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  // terminating.
396e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  isolate->EnqueueMicrotask(v8::Function::New(isolate, MicrotaskShouldNotRun));
397e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  isolate->RunMicrotasks();
398e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
399e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  v8::V8::CancelTerminateExecution(isolate);
400e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  isolate->RunMicrotasks();  // should not run MicrotaskShouldNotRun
401e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
402e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  thread.Join();
403e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  delete semaphore;
404e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  semaphore = NULL;
405e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org}
406d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
407d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
408d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgstatic int callback_counter = 0;
409d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
410d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
411d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgstatic void CounterCallback(v8::Isolate* isolate, void* data) {
412d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  callback_counter++;
413d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org}
414d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
415d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
416d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgTEST(PostponeTerminateException) {
417d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  v8::Isolate* isolate = CcTest::isolate();
418d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  v8::HandleScope scope(isolate);
419d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  v8::Handle<v8::ObjectTemplate> global =
420d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      CreateGlobalTemplate(CcTest::isolate(), TerminateCurrentThread, DoLoop);
421d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  v8::Handle<v8::Context> context =
422d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      v8::Context::New(CcTest::isolate(), NULL, global);
423d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  v8::Context::Scope context_scope(context);
424d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
425d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  v8::TryCatch try_catch;
426d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  static const char* terminate_and_loop =
427d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      "terminate(); for (var i = 0; i < 10000; i++);";
428d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
429d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  { // Postpone terminate execution interrupts.
430d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    i::PostponeInterruptsScope p1(CcTest::i_isolate(),
431d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org                                  i::StackGuard::TERMINATE_EXECUTION) ;
432d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
433d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    // API interrupts should still be triggered.
434d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    CcTest::isolate()->RequestInterrupt(&CounterCallback, NULL);
435d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    CHECK_EQ(0, callback_counter);
436d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    CompileRun(terminate_and_loop);
437d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    CHECK(!try_catch.HasTerminated());
438d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    CHECK_EQ(1, callback_counter);
439d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
440d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    { // Postpone API interrupts as well.
441d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      i::PostponeInterruptsScope p2(CcTest::i_isolate(),
442d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org                                    i::StackGuard::API_INTERRUPT);
443d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
444d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      // None of the two interrupts should trigger.
445d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      CcTest::isolate()->RequestInterrupt(&CounterCallback, NULL);
446d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      CompileRun(terminate_and_loop);
447d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      CHECK(!try_catch.HasTerminated());
448d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      CHECK_EQ(1, callback_counter);
449d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    }
450d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
451d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    // Now the previously requested API interrupt should trigger.
452d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    CompileRun(terminate_and_loop);
453d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    CHECK(!try_catch.HasTerminated());
454d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    CHECK_EQ(2, callback_counter);
455d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  }
456d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
457d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  // Now the previously requested terminate execution interrupt should trigger.
458d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  CompileRun("for (var i = 0; i < 10000; i++);");
459d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  CHECK(try_catch.HasTerminated());
460d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  CHECK_EQ(2, callback_counter);
461d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org}
462ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org
463ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org
464ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgTEST(ErrorObjectAfterTermination) {
465ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  v8::Isolate* isolate = CcTest::isolate();
466ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  v8::HandleScope scope(isolate);
467ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
468ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  v8::Context::Scope context_scope(context);
469ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  v8::V8::TerminateExecution(isolate);
470ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  v8::Local<v8::Value> error = v8::Exception::Error(v8_str("error"));
471ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  // TODO(yangguo): crbug/403509. Check for empty handle instead.
472ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  CHECK(error->IsUndefined());
473ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org}
474