Move V8 to external/v8

Change-Id: If68025d67453785a651c5dfb34fad298c16676a4
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
new file mode 100644
index 0000000..f430cbd
--- /dev/null
+++ b/test/cctest/test-api.cc
@@ -0,0 +1,7995 @@
+// Copyright 2007-2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "api.h"
+#include "compilation-cache.h"
+#include "execution.h"
+#include "snapshot.h"
+#include "platform.h"
+#include "top.h"
+#include "cctest.h"
+
+static bool IsNaN(double x) {
+#ifdef WIN32
+  return _isnan(x);
+#else
+  return isnan(x);
+#endif
+}
+
+using ::v8::ObjectTemplate;
+using ::v8::Value;
+using ::v8::Context;
+using ::v8::Local;
+using ::v8::String;
+using ::v8::Script;
+using ::v8::Function;
+using ::v8::AccessorInfo;
+using ::v8::Extension;
+
+namespace i = ::v8::internal;
+
+static Local<Value> v8_num(double x) {
+  return v8::Number::New(x);
+}
+
+
+static Local<String> v8_str(const char* x) {
+  return String::New(x);
+}
+
+
+static Local<Script> v8_compile(const char* x) {
+  return Script::Compile(v8_str(x));
+}
+
+
+// A LocalContext holds a reference to a v8::Context.
+class LocalContext {
+ public:
+  LocalContext(v8::ExtensionConfiguration* extensions = 0,
+               v8::Handle<ObjectTemplate> global_template =
+                   v8::Handle<ObjectTemplate>(),
+               v8::Handle<Value> global_object = v8::Handle<Value>())
+    : context_(Context::New(extensions, global_template, global_object)) {
+    context_->Enter();
+  }
+
+  virtual ~LocalContext() {
+    context_->Exit();
+    context_.Dispose();
+  }
+
+  Context* operator->() { return *context_; }
+  Context* operator*() { return *context_; }
+  Local<Context> local() { return Local<Context>::New(context_); }
+  bool IsReady() { return !context_.IsEmpty(); }
+
+ private:
+  v8::Persistent<Context> context_;
+};
+
+
+// Switches between all the Api tests using the threading support.
+// In order to get a surprising but repeatable pattern of thread
+// switching it has extra semaphores to control the order in which
+// the tests alternate, not relying solely on the big V8 lock.
+//
+// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
+// callbacks.  This will have no effect when we are not running the
+// thread fuzzing test.  In the thread fuzzing test it will
+// pseudorandomly select a successor thread and switch execution
+// to that thread, suspending the current test.
+class ApiTestFuzzer: public v8::internal::Thread {
+ public:
+  void CallTest();
+  explicit ApiTestFuzzer(int num)
+      : test_number_(num),
+        gate_(v8::internal::OS::CreateSemaphore(0)),
+        active_(true) {
+  }
+  ~ApiTestFuzzer() { delete gate_; }
+
+  // The ApiTestFuzzer is also a Thread, so it has a Run method.
+  virtual void Run();
+
+  enum PartOfTest { FIRST_PART, SECOND_PART };
+
+  static void Setup(PartOfTest part);
+  static void RunAllTests();
+  static void TearDown();
+  // This method switches threads if we are running the Threading test.
+  // Otherwise it does nothing.
+  static void Fuzz();
+ private:
+  static bool fuzzing_;
+  static int tests_being_run_;
+  static int current_;
+  static int active_tests_;
+  static bool NextThread();
+  int test_number_;
+  v8::internal::Semaphore* gate_;
+  bool active_;
+  void ContextSwitch();
+  static int GetNextTestNumber();
+  static v8::internal::Semaphore* all_tests_done_;
+};
+
+
+#define THREADED_TEST(Name)                                          \
+  static void Test##Name();                                          \
+  RegisterThreadedTest register_##Name(Test##Name);                  \
+  /* */ TEST(Name)
+
+
+class RegisterThreadedTest {
+ public:
+  explicit RegisterThreadedTest(CcTest::TestFunction* callback)
+      : fuzzer_(NULL), callback_(callback) {
+    prev_ = first_;
+    first_ = this;
+    count_++;
+  }
+  static int count() { return count_; }
+  static RegisterThreadedTest* nth(int i) {
+    CHECK(i < count());
+    RegisterThreadedTest* current = first_;
+    while (i > 0) {
+      i--;
+      current = current->prev_;
+    }
+    return current;
+  }
+  CcTest::TestFunction* callback() { return callback_; }
+  ApiTestFuzzer* fuzzer_;
+
+ private:
+  static RegisterThreadedTest* first_;
+  static int count_;
+  CcTest::TestFunction* callback_;
+  RegisterThreadedTest* prev_;
+};
+
+
+RegisterThreadedTest *RegisterThreadedTest::first_ = NULL;
+int RegisterThreadedTest::count_ = 0;
+
+
+static int signature_callback_count;
+static v8::Handle<Value> IncrementingSignatureCallback(
+    const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  signature_callback_count++;
+  v8::Handle<v8::Array> result = v8::Array::New(args.Length());
+  for (int i = 0; i < args.Length(); i++)
+    result->Set(v8::Integer::New(i), args[i]);
+  return result;
+}
+
+
+static v8::Handle<Value> SignatureCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  v8::Handle<v8::Array> result = v8::Array::New(args.Length());
+  for (int i = 0; i < args.Length(); i++) {
+    result->Set(v8::Integer::New(i), args[i]);
+  }
+  return result;
+}
+
+
+THREADED_TEST(Handles) {
+  v8::HandleScope scope;
+  Local<Context> local_env;
+  {
+    LocalContext env;
+    local_env = env.local();
+  }
+
+  // Local context should still be live.
+  CHECK(!local_env.IsEmpty());
+  local_env->Enter();
+
+  v8::Handle<v8::Primitive> undef = v8::Undefined();
+  CHECK(!undef.IsEmpty());
+  CHECK(undef->IsUndefined());
+
+  const char* c_source = "1 + 2 + 3";
+  Local<String> source = String::New(c_source);
+  Local<Script> script = Script::Compile(source);
+  CHECK_EQ(6, script->Run()->Int32Value());
+
+  local_env->Exit();
+}
+
+
+// Helper function that compiles and runs the source.
+static Local<Value> CompileRun(const char* source) {
+  return Script::Compile(String::New(source))->Run();
+}
+
+THREADED_TEST(ReceiverSignature) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
+  v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
+  fun->PrototypeTemplate()->Set(
+      v8_str("m"),
+      v8::FunctionTemplate::New(IncrementingSignatureCallback,
+                                v8::Handle<Value>(),
+                                sig));
+  env->Global()->Set(v8_str("Fun"), fun->GetFunction());
+  signature_callback_count = 0;
+  CompileRun(
+      "var o = new Fun();"
+      "o.m();");
+  CHECK_EQ(1, signature_callback_count);
+  v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
+  sub_fun->Inherit(fun);
+  env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction());
+  CompileRun(
+      "var o = new SubFun();"
+      "o.m();");
+  CHECK_EQ(2, signature_callback_count);
+
+  v8::TryCatch try_catch;
+  CompileRun(
+      "var o = { };"
+      "o.m = Fun.prototype.m;"
+      "o.m();");
+  CHECK_EQ(2, signature_callback_count);
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
+  sub_fun->Inherit(fun);
+  env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
+  CompileRun(
+      "var o = new UnrelFun();"
+      "o.m = Fun.prototype.m;"
+      "o.m();");
+  CHECK_EQ(2, signature_callback_count);
+  CHECK(try_catch.HasCaught());
+}
+
+
+
+
+THREADED_TEST(ArgumentSignature) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
+  cons->SetClassName(v8_str("Cons"));
+  v8::Handle<v8::Signature> sig =
+      v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 1, &cons);
+  v8::Handle<v8::FunctionTemplate> fun =
+      v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
+  env->Global()->Set(v8_str("Cons"), cons->GetFunction());
+  env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
+
+  v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
+  CHECK(value1->IsTrue());
+
+  v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
+  CHECK(value2->IsTrue());
+
+  v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
+  CHECK(value3->IsTrue());
+
+  v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
+  cons1->SetClassName(v8_str("Cons1"));
+  v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
+  cons2->SetClassName(v8_str("Cons2"));
+  v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
+  cons3->SetClassName(v8_str("Cons3"));
+
+  v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
+  v8::Handle<v8::Signature> wsig =
+      v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 3, args);
+  v8::Handle<v8::FunctionTemplate> fun2 =
+      v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
+
+  env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
+  env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
+  env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
+  env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
+  v8::Handle<Value> value4 = CompileRun(
+      "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
+      "'[object Cons1],[object Cons2],[object Cons3]'");
+  CHECK(value4->IsTrue());
+
+  v8::Handle<Value> value5 = CompileRun(
+      "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
+  CHECK(value5->IsTrue());
+
+  v8::Handle<Value> value6 = CompileRun(
+      "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
+  CHECK(value6->IsTrue());
+
+  v8::Handle<Value> value7 = CompileRun(
+      "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
+      "'[object Cons1],[object Cons2],[object Cons3],d';");
+  CHECK(value7->IsTrue());
+
+  v8::Handle<Value> value8 = CompileRun(
+      "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
+  CHECK(value8->IsTrue());
+}
+
+
+THREADED_TEST(HulIgennem) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::Primitive> undef = v8::Undefined();
+  Local<String> undef_str = undef->ToString();
+  char* value = i::NewArray<char>(undef_str->Length() + 1);
+  undef_str->WriteAscii(value);
+  CHECK_EQ(0, strcmp(value, "undefined"));
+  i::DeleteArray(value);
+}
+
+
+THREADED_TEST(Access) {
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<v8::Object> obj = v8::Object::New();
+  Local<Value> foo_before = obj->Get(v8_str("foo"));
+  CHECK(foo_before->IsUndefined());
+  Local<String> bar_str = v8_str("bar");
+  obj->Set(v8_str("foo"), bar_str);
+  Local<Value> foo_after = obj->Get(v8_str("foo"));
+  CHECK(!foo_after->IsUndefined());
+  CHECK(foo_after->IsString());
+  CHECK_EQ(bar_str, foo_after);
+}
+
+
+THREADED_TEST(Script) {
+  v8::HandleScope scope;
+  LocalContext env;
+  const char* c_source = "1 + 2 + 3";
+  Local<String> source = String::New(c_source);
+  Local<Script> script = Script::Compile(source);
+  CHECK_EQ(6, script->Run()->Int32Value());
+}
+
+
+static uint16_t* AsciiToTwoByteString(const char* source) {
+  size_t array_length = strlen(source) + 1;
+  uint16_t* converted = i::NewArray<uint16_t>(array_length);
+  for (size_t i = 0; i < array_length; i++) converted[i] = source[i];
+  return converted;
+}
+
+
+class TestResource: public String::ExternalStringResource {
+ public:
+  static int dispose_count;
+
+  explicit TestResource(uint16_t* data)
+      : data_(data), length_(0) {
+    while (data[length_]) ++length_;
+  }
+
+  ~TestResource() {
+    i::DeleteArray(data_);
+    ++dispose_count;
+  }
+
+  const uint16_t* data() const {
+    return data_;
+  }
+
+  size_t length() const {
+    return length_;
+  }
+ private:
+  uint16_t* data_;
+  size_t length_;
+};
+
+
+int TestResource::dispose_count = 0;
+
+
+class TestAsciiResource: public String::ExternalAsciiStringResource {
+ public:
+  static int dispose_count;
+
+  explicit TestAsciiResource(const char* data)
+      : data_(data),
+        length_(strlen(data)) { }
+
+  ~TestAsciiResource() {
+    i::DeleteArray(data_);
+    ++dispose_count;
+  }
+
+  const char* data() const {
+    return data_;
+  }
+
+  size_t length() const {
+    return length_;
+  }
+ private:
+  const char* data_;
+  size_t length_;
+};
+
+
+int TestAsciiResource::dispose_count = 0;
+
+
+THREADED_TEST(ScriptUsingStringResource) {
+  TestResource::dispose_count = 0;
+  const char* c_source = "1 + 2 * 3";
+  uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    TestResource* resource = new TestResource(two_byte_source);
+    Local<String> source = String::NewExternal(resource);
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    CHECK(source->IsExternal());
+    CHECK_EQ(resource,
+             static_cast<TestResource*>(source->GetExternalStringResource()));
+    v8::internal::Heap::CollectAllGarbage(false);
+    CHECK_EQ(0, TestResource::dispose_count);
+  }
+  v8::internal::CompilationCache::Clear();
+  v8::internal::Heap::CollectAllGarbage(false);
+  CHECK_EQ(1, TestResource::dispose_count);
+}
+
+
+THREADED_TEST(ScriptUsingAsciiStringResource) {
+  TestAsciiResource::dispose_count = 0;
+  const char* c_source = "1 + 2 * 3";
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<String> source =
+        String::NewExternal(new TestAsciiResource(i::StrDup(c_source)));
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    v8::internal::Heap::CollectAllGarbage(false);
+    CHECK_EQ(0, TestAsciiResource::dispose_count);
+  }
+  v8::internal::CompilationCache::Clear();
+  v8::internal::Heap::CollectAllGarbage(false);
+  CHECK_EQ(1, TestAsciiResource::dispose_count);
+}
+
+
+THREADED_TEST(ScriptMakingExternalString) {
+  TestResource::dispose_count = 0;
+  uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<String> source = String::New(two_byte_source);
+    bool success = source->MakeExternal(new TestResource(two_byte_source));
+    CHECK(success);
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    v8::internal::Heap::CollectAllGarbage(false);
+    CHECK_EQ(0, TestResource::dispose_count);
+  }
+  v8::internal::CompilationCache::Clear();
+  v8::internal::Heap::CollectAllGarbage(false);
+  CHECK_EQ(1, TestResource::dispose_count);
+}
+
+
+THREADED_TEST(ScriptMakingExternalAsciiString) {
+  TestAsciiResource::dispose_count = 0;
+  const char* c_source = "1 + 2 * 3";
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<String> source = v8_str(c_source);
+    bool success = source->MakeExternal(
+        new TestAsciiResource(i::StrDup(c_source)));
+    CHECK(success);
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    v8::internal::Heap::CollectAllGarbage(false);
+    CHECK_EQ(0, TestAsciiResource::dispose_count);
+  }
+  v8::internal::CompilationCache::Clear();
+  v8::internal::Heap::CollectAllGarbage(false);
+  CHECK_EQ(1, TestAsciiResource::dispose_count);
+}
+
+
+THREADED_TEST(UsingExternalString) {
+  {
+    v8::HandleScope scope;
+    uint16_t* two_byte_string = AsciiToTwoByteString("test string");
+    Local<String> string =
+        String::NewExternal(new TestResource(two_byte_string));
+    i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
+    // Trigger GCs so that the newly allocated string moves to old gen.
+    i::Heap::CollectGarbage(0, i::NEW_SPACE);  // in survivor space now
+    i::Heap::CollectGarbage(0, i::NEW_SPACE);  // in old gen now
+    i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring);
+    CHECK(isymbol->IsSymbol());
+  }
+  i::Heap::CollectAllGarbage(false);
+  i::Heap::CollectAllGarbage(false);
+}
+
+
+THREADED_TEST(UsingExternalAsciiString) {
+  {
+    v8::HandleScope scope;
+    const char* one_byte_string = "test string";
+    Local<String> string = String::NewExternal(
+        new TestAsciiResource(i::StrDup(one_byte_string)));
+    i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
+    // Trigger GCs so that the newly allocated string moves to old gen.
+    i::Heap::CollectGarbage(0, i::NEW_SPACE);  // in survivor space now
+    i::Heap::CollectGarbage(0, i::NEW_SPACE);  // in old gen now
+    i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring);
+    CHECK(isymbol->IsSymbol());
+  }
+  i::Heap::CollectAllGarbage(false);
+  i::Heap::CollectAllGarbage(false);
+}
+
+
+THREADED_TEST(GlobalProperties) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::Object> global = env->Global();
+  global->Set(v8_str("pi"), v8_num(3.1415926));
+  Local<Value> pi = global->Get(v8_str("pi"));
+  CHECK_EQ(3.1415926, pi->NumberValue());
+}
+
+
+static v8::Handle<Value> handle_call(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(102);
+}
+
+
+static v8::Handle<Value> construct_call(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  args.This()->Set(v8_str("x"), v8_num(1));
+  args.This()->Set(v8_str("y"), v8_num(2));
+  return args.This();
+}
+
+THREADED_TEST(FunctionTemplate) {
+  v8::HandleScope scope;
+  LocalContext env;
+  {
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(handle_call);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("obj"), fun);
+    Local<Script> script = v8_compile("obj()");
+    CHECK_EQ(102, script->Run()->Int32Value());
+  }
+  // Use SetCallHandler to initialize a function template, should work like the
+  // previous one.
+  {
+    Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+    fun_templ->SetCallHandler(handle_call);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("obj"), fun);
+    Local<Script> script = v8_compile("obj()");
+    CHECK_EQ(102, script->Run()->Int32Value());
+  }
+  // Test constructor calls.
+  {
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(construct_call);
+    fun_templ->SetClassName(v8_str("funky"));
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("obj"), fun);
+    Local<Script> script = v8_compile("var s = new obj(); s.x");
+    CHECK_EQ(1, script->Run()->Int32Value());
+
+    Local<Value> result = v8_compile("(new obj()).toString()")->Run();
+    CHECK_EQ(v8_str("[object funky]"), result);
+  }
+}
+
+
+THREADED_TEST(FindInstanceInPrototypeChain) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
+  Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
+  Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
+  derived->Inherit(base);
+
+  Local<v8::Function> base_function = base->GetFunction();
+  Local<v8::Function> derived_function = derived->GetFunction();
+  Local<v8::Function> other_function = other->GetFunction();
+
+  Local<v8::Object> base_instance = base_function->NewInstance();
+  Local<v8::Object> derived_instance = derived_function->NewInstance();
+  Local<v8::Object> derived_instance2 = derived_function->NewInstance();
+  Local<v8::Object> other_instance = other_function->NewInstance();
+  derived_instance2->Set(v8_str("__proto__"), derived_instance);
+  other_instance->Set(v8_str("__proto__"), derived_instance2);
+
+  // base_instance is only an instance of base.
+  CHECK_EQ(base_instance,
+           base_instance->FindInstanceInPrototypeChain(base));
+  CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
+  CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
+
+  // derived_instance is an instance of base and derived.
+  CHECK_EQ(derived_instance,
+           derived_instance->FindInstanceInPrototypeChain(base));
+  CHECK_EQ(derived_instance,
+           derived_instance->FindInstanceInPrototypeChain(derived));
+  CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
+
+  // other_instance is an instance of other and its immediate
+  // prototype derived_instance2 is an instance of base and derived.
+  // Note, derived_instance is an instance of base and derived too,
+  // but it comes after derived_instance2 in the prototype chain of
+  // other_instance.
+  CHECK_EQ(derived_instance2,
+           other_instance->FindInstanceInPrototypeChain(base));
+  CHECK_EQ(derived_instance2,
+           other_instance->FindInstanceInPrototypeChain(derived));
+  CHECK_EQ(other_instance,
+           other_instance->FindInstanceInPrototypeChain(other));
+}
+
+
+static v8::Handle<Value> handle_property(Local<String> name,
+                                         const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(900);
+}
+
+
+THREADED_TEST(PropertyHandler) {
+  v8::HandleScope scope;
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+  fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
+  LocalContext env;
+  Local<Function> fun = fun_templ->GetFunction();
+  env->Global()->Set(v8_str("Fun"), fun);
+  Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
+  CHECK_EQ(900, getter->Run()->Int32Value());
+  Local<Script> setter = v8_compile("obj.foo = 901;");
+  CHECK_EQ(901, setter->Run()->Int32Value());
+}
+
+
+THREADED_TEST(Number) {
+  v8::HandleScope scope;
+  LocalContext env;
+  double PI = 3.1415926;
+  Local<v8::Number> pi_obj = v8::Number::New(PI);
+  CHECK_EQ(PI, pi_obj->NumberValue());
+}
+
+
+THREADED_TEST(ToNumber) {
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<String> str = v8_str("3.1415926");
+  CHECK_EQ(3.1415926, str->NumberValue());
+  v8::Handle<v8::Boolean> t = v8::True();
+  CHECK_EQ(1.0, t->NumberValue());
+  v8::Handle<v8::Boolean> f = v8::False();
+  CHECK_EQ(0.0, f->NumberValue());
+}
+
+
+THREADED_TEST(Date) {
+  v8::HandleScope scope;
+  LocalContext env;
+  double PI = 3.1415926;
+  Local<Value> date_obj = v8::Date::New(PI);
+  CHECK_EQ(3.0, date_obj->NumberValue());
+}
+
+
+THREADED_TEST(Boolean) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::Boolean> t = v8::True();
+  CHECK(t->Value());
+  v8::Handle<v8::Boolean> f = v8::False();
+  CHECK(!f->Value());
+  v8::Handle<v8::Primitive> u = v8::Undefined();
+  CHECK(!u->BooleanValue());
+  v8::Handle<v8::Primitive> n = v8::Null();
+  CHECK(!n->BooleanValue());
+  v8::Handle<String> str1 = v8_str("");
+  CHECK(!str1->BooleanValue());
+  v8::Handle<String> str2 = v8_str("x");
+  CHECK(str2->BooleanValue());
+  CHECK(!v8::Number::New(0)->BooleanValue());
+  CHECK(v8::Number::New(-1)->BooleanValue());
+  CHECK(v8::Number::New(1)->BooleanValue());
+  CHECK(v8::Number::New(42)->BooleanValue());
+  CHECK(!v8_compile("NaN")->Run()->BooleanValue());
+}
+
+
+static v8::Handle<Value> DummyCallHandler(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(13.4);
+}
+
+
+static v8::Handle<Value> GetM(Local<String> name, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(876);
+}
+
+
+THREADED_TEST(GlobalPrototype) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
+  func_templ->PrototypeTemplate()->Set(
+      "dummy",
+      v8::FunctionTemplate::New(DummyCallHandler));
+  v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
+  templ->Set("x", v8_num(200));
+  templ->SetAccessor(v8_str("m"), GetM);
+  LocalContext env(0, templ);
+  v8::Handle<v8::Object> obj = env->Global();
+  v8::Handle<Script> script = v8_compile("dummy()");
+  v8::Handle<Value> result = script->Run();
+  CHECK_EQ(13.4, result->NumberValue());
+  CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
+  CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
+}
+
+
+static v8::Handle<Value> GetIntValue(Local<String> property,
+                                     const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  int* value =
+      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+  return v8_num(*value);
+}
+
+static void SetIntValue(Local<String> property,
+                        Local<Value> value,
+                        const AccessorInfo& info) {
+  int* field =
+      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+  *field = value->Int32Value();
+}
+
+int foo, bar, baz;
+
+THREADED_TEST(GlobalVariableAccess) {
+  foo = 0;
+  bar = -4;
+  baz = 10;
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
+                                         GetIntValue,
+                                         SetIntValue,
+                                         v8::External::New(&foo));
+  templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
+                                         GetIntValue,
+                                         SetIntValue,
+                                         v8::External::New(&bar));
+  templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
+                                         GetIntValue,
+                                         SetIntValue,
+                                         v8::External::New(&baz));
+  LocalContext env(0, templ->InstanceTemplate());
+  v8_compile("foo = (++bar) + baz")->Run();
+  CHECK_EQ(bar, -3);
+  CHECK_EQ(foo, 7);
+}
+
+
+THREADED_TEST(ObjectTemplate) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ1 = ObjectTemplate::New();
+  templ1->Set("x", v8_num(10));
+  templ1->Set("y", v8_num(13));
+  LocalContext env;
+  Local<v8::Object> instance1 = templ1->NewInstance();
+  env->Global()->Set(v8_str("p"), instance1);
+  CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
+  CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
+  Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
+  fun->PrototypeTemplate()->Set("nirk", v8_num(123));
+  Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
+  templ2->Set("a", v8_num(12));
+  templ2->Set("b", templ1);
+  Local<v8::Object> instance2 = templ2->NewInstance();
+  env->Global()->Set(v8_str("q"), instance2);
+  CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
+  CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
+  CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
+  CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
+}
+
+
+static v8::Handle<Value> GetFlabby(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(17.2);
+}
+
+
+static v8::Handle<Value> GetKnurd(Local<String> property, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(15.2);
+}
+
+
+THREADED_TEST(DescriptorInheritance) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
+  super->PrototypeTemplate()->Set("flabby",
+                                  v8::FunctionTemplate::New(GetFlabby));
+  super->PrototypeTemplate()->Set("PI", v8_num(3.14));
+
+  super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
+
+  v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
+  base1->Inherit(super);
+  base1->PrototypeTemplate()->Set("v1", v8_num(20.1));
+
+  v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
+  base2->Inherit(super);
+  base2->PrototypeTemplate()->Set("v2", v8_num(10.1));
+
+  LocalContext env;
+
+  env->Global()->Set(v8_str("s"), super->GetFunction());
+  env->Global()->Set(v8_str("base1"), base1->GetFunction());
+  env->Global()->Set(v8_str("base2"), base2->GetFunction());
+
+  // Checks right __proto__ chain.
+  CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
+  CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
+
+  CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
+
+  // Instance accessor should not be visible on function object or its prototype
+  CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
+  CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
+  CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
+
+  env->Global()->Set(v8_str("obj"),
+                     base1->GetFunction()->NewInstance());
+  CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
+  CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
+  CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
+  CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
+  CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
+
+  env->Global()->Set(v8_str("obj2"),
+                     base2->GetFunction()->NewInstance());
+  CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
+  CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
+  CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
+  CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
+  CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
+
+  // base1 and base2 cannot cross reference to each's prototype
+  CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
+  CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
+}
+
+
+int echo_named_call_count;
+
+
+static v8::Handle<Value> EchoNamedProperty(Local<String> name,
+                                           const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(v8_str("data"), info.Data());
+  echo_named_call_count++;
+  return name;
+}
+
+
+THREADED_TEST(NamedPropertyHandlerGetter) {
+  echo_named_call_count = 0;
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
+                                                     0, 0, 0, 0,
+                                                     v8_str("data"));
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"),
+                     templ->GetFunction()->NewInstance());
+  CHECK_EQ(echo_named_call_count, 0);
+  v8_compile("obj.x")->Run();
+  CHECK_EQ(echo_named_call_count, 1);
+  const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
+  v8::Handle<Value> str = CompileRun(code);
+  String::AsciiValue value(str);
+  CHECK_EQ(*value, "oddlepoddle");
+  // Check default behavior
+  CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
+  CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
+  CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
+}
+
+
+int echo_indexed_call_count = 0;
+
+
+static v8::Handle<Value> EchoIndexedProperty(uint32_t index,
+                                             const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(v8_num(637), info.Data());
+  echo_indexed_call_count++;
+  return v8_num(index);
+}
+
+
+THREADED_TEST(IndexedPropertyHandlerGetter) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
+                                                       0, 0, 0, 0,
+                                                       v8_num(637));
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"),
+                     templ->GetFunction()->NewInstance());
+  Local<Script> script = v8_compile("obj[900]");
+  CHECK_EQ(script->Run()->Int32Value(), 900);
+}
+
+
+v8::Handle<v8::Object> bottom;
+
+static v8::Handle<Value> CheckThisIndexedPropertyHandler(
+    uint32_t index,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<Value>();
+}
+
+static v8::Handle<Value> CheckThisNamedPropertyHandler(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<Value>();
+}
+
+
+v8::Handle<Value> CheckThisIndexedPropertySetter(uint32_t index,
+                                                 Local<Value> value,
+                                                 const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<Value>();
+}
+
+
+v8::Handle<Value> CheckThisNamedPropertySetter(Local<String> property,
+                                               Local<Value> value,
+                                               const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<Value>();
+}
+
+v8::Handle<v8::Boolean> CheckThisIndexedPropertyQuery(
+    uint32_t index,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Boolean>();
+}
+
+
+v8::Handle<v8::Boolean> CheckThisNamedPropertyQuery(Local<String> property,
+                                                    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Boolean>();
+}
+
+
+v8::Handle<v8::Boolean> CheckThisIndexedPropertyDeleter(
+    uint32_t index,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Boolean>();
+}
+
+
+v8::Handle<v8::Boolean> CheckThisNamedPropertyDeleter(
+    Local<String> property,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Boolean>();
+}
+
+
+v8::Handle<v8::Array> CheckThisIndexedPropertyEnumerator(
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Array>();
+}
+
+
+v8::Handle<v8::Array> CheckThisNamedPropertyEnumerator(
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Array>();
+}
+
+
+THREADED_TEST(PropertyHandlerInPrototype) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  // Set up a prototype chain with three interceptors.
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetIndexedPropertyHandler(
+      CheckThisIndexedPropertyHandler,
+      CheckThisIndexedPropertySetter,
+      CheckThisIndexedPropertyQuery,
+      CheckThisIndexedPropertyDeleter,
+      CheckThisIndexedPropertyEnumerator);
+
+  templ->InstanceTemplate()->SetNamedPropertyHandler(
+      CheckThisNamedPropertyHandler,
+      CheckThisNamedPropertySetter,
+      CheckThisNamedPropertyQuery,
+      CheckThisNamedPropertyDeleter,
+      CheckThisNamedPropertyEnumerator);
+
+  bottom = templ->GetFunction()->NewInstance();
+  Local<v8::Object> top = templ->GetFunction()->NewInstance();
+  Local<v8::Object> middle = templ->GetFunction()->NewInstance();
+
+  bottom->Set(v8_str("__proto__"), middle);
+  middle->Set(v8_str("__proto__"), top);
+  env->Global()->Set(v8_str("obj"), bottom);
+
+  // Indexed and named get.
+  Script::Compile(v8_str("obj[0]"))->Run();
+  Script::Compile(v8_str("obj.x"))->Run();
+
+  // Indexed and named set.
+  Script::Compile(v8_str("obj[1] = 42"))->Run();
+  Script::Compile(v8_str("obj.y = 42"))->Run();
+
+  // Indexed and named query.
+  Script::Compile(v8_str("0 in obj"))->Run();
+  Script::Compile(v8_str("'x' in obj"))->Run();
+
+  // Indexed and named deleter.
+  Script::Compile(v8_str("delete obj[0]"))->Run();
+  Script::Compile(v8_str("delete obj.x"))->Run();
+
+  // Enumerators.
+  Script::Compile(v8_str("for (var p in obj) ;"))->Run();
+}
+
+
+static v8::Handle<Value> PrePropertyHandlerGet(Local<String> key,
+                                               const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (v8_str("pre")->Equals(key)) {
+    return v8_str("PrePropertyHandler: pre");
+  }
+  return v8::Handle<String>();
+}
+
+
+static v8::Handle<v8::Boolean> PrePropertyHandlerHas(Local<String> key,
+                                                     const AccessorInfo&) {
+  if (v8_str("pre")->Equals(key)) {
+    return v8::True();
+  }
+
+  return v8::Handle<v8::Boolean>();  // do not intercept the call
+}
+
+
+THREADED_TEST(PrePropertyHandler) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
+  desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
+                                                    0,
+                                                    PrePropertyHandlerHas);
+  LocalContext env(NULL, desc->InstanceTemplate());
+  Script::Compile(v8_str(
+      "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
+  v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
+  CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
+  v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
+  CHECK_EQ(v8_str("Object: on"), result_on);
+  v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
+  CHECK(result_post.IsEmpty());
+}
+
+
+THREADED_TEST(UndefinedIsNotEnumerable) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<Value> result = Script::Compile(v8_str(
+      "this.propertyIsEnumerable(undefined)"))->Run();
+  CHECK(result->IsFalse());
+}
+
+
+v8::Handle<Script> call_recursively_script;
+static const int kTargetRecursionDepth = 300;  // near maximum
+
+
+static v8::Handle<Value> CallScriptRecursivelyCall(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
+  if (depth == kTargetRecursionDepth) return v8::Undefined();
+  args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
+  return call_recursively_script->Run();
+}
+
+
+static v8::Handle<Value> CallFunctionRecursivelyCall(
+    const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
+  if (depth == kTargetRecursionDepth) {
+    printf("[depth = %d]\n", depth);
+    return v8::Undefined();
+  }
+  args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
+  v8::Handle<Value> function =
+      args.This()->Get(v8_str("callFunctionRecursively"));
+  return v8::Handle<Function>::Cast(function)->Call(args.This(), 0, NULL);
+}
+
+
+THREADED_TEST(DeepCrossLanguageRecursion) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
+  global->Set(v8_str("callScriptRecursively"),
+              v8::FunctionTemplate::New(CallScriptRecursivelyCall));
+  global->Set(v8_str("callFunctionRecursively"),
+              v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
+  LocalContext env(NULL, global);
+
+  env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
+  call_recursively_script = v8_compile("callScriptRecursively()");
+  v8::Handle<Value> result = call_recursively_script->Run();
+  call_recursively_script = v8::Handle<Script>();
+
+  env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
+  Script::Compile(v8_str("callFunctionRecursively()"))->Run();
+}
+
+
+static v8::Handle<Value>
+    ThrowingPropertyHandlerGet(Local<String> key, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8::ThrowException(key);
+}
+
+
+static v8::Handle<Value> ThrowingPropertyHandlerSet(Local<String> key,
+                                                    Local<Value>,
+                                                    const AccessorInfo&) {
+  v8::ThrowException(key);
+  return v8::Undefined();  // not the same as v8::Handle<v8::Value>()
+}
+
+
+THREADED_TEST(CallbackExceptionRegression) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
+                               ThrowingPropertyHandlerSet);
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"), obj->NewInstance());
+  v8::Handle<Value> otto = Script::Compile(v8_str(
+      "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
+  CHECK_EQ(v8_str("otto"), otto);
+  v8::Handle<Value> netto = Script::Compile(v8_str(
+      "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
+  CHECK_EQ(v8_str("netto"), netto);
+}
+
+
+static v8::Handle<Value> ThrowingGetAccessor(Local<String> name,
+                                             const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::ThrowException(v8_str("g"));
+}
+
+
+static void ThrowingSetAccessor(Local<String> name,
+                                Local<Value> value,
+                                const AccessorInfo& info) {
+  v8::ThrowException(value);
+}
+
+
+THREADED_TEST(Regress1054726) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("x"),
+                   ThrowingGetAccessor,
+                   ThrowingSetAccessor,
+                   Local<Value>());
+
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"), obj->NewInstance());
+
+  // Use the throwing property setter/getter in a loop to force
+  // the accessor ICs to be initialized.
+  v8::Handle<Value> result;
+  result = Script::Compile(v8_str(
+      "var result = '';"
+      "for (var i = 0; i < 5; i++) {"
+      "  try { obj.x; } catch (e) { result += e; }"
+      "}; result"))->Run();
+  CHECK_EQ(v8_str("ggggg"), result);
+
+  result = Script::Compile(String::New(
+      "var result = '';"
+      "for (var i = 0; i < 5; i++) {"
+      "  try { obj.x = i; } catch (e) { result += e; }"
+      "}; result"))->Run();
+  CHECK_EQ(v8_str("01234"), result);
+}
+
+
+THREADED_TEST(FunctionPrototype) {
+  v8::HandleScope scope;
+  Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
+  Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
+  LocalContext env;
+  env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
+  Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
+  CHECK_EQ(script->Run()->Int32Value(), 321);
+}
+
+
+THREADED_TEST(InternalFields) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
+  instance_templ->SetInternalFieldCount(1);
+  Local<v8::Object> obj = templ->GetFunction()->NewInstance();
+  CHECK_EQ(1, obj->InternalFieldCount());
+  CHECK(obj->GetInternalField(0)->IsUndefined());
+  obj->SetInternalField(0, v8_num(17));
+  CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
+}
+
+
+THREADED_TEST(InternalFieldsNativePointers) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
+  instance_templ->SetInternalFieldCount(1);
+  Local<v8::Object> obj = templ->GetFunction()->NewInstance();
+  CHECK_EQ(1, obj->InternalFieldCount());
+  CHECK(obj->GetPointerFromInternalField(0) == NULL);
+
+  char* data = new char[100];
+
+  void* aligned = data;
+  CHECK_EQ(0, reinterpret_cast<uintptr_t>(aligned) & 0x1);
+  void* unaligned = data + 1;
+  CHECK_EQ(1, reinterpret_cast<uintptr_t>(unaligned) & 0x1);
+
+  // Check reading and writing aligned pointers.
+  obj->SetPointerInInternalField(0, aligned);
+  i::Heap::CollectAllGarbage(false);
+  CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
+
+  // Check reading and writing unaligned pointers.
+  obj->SetPointerInInternalField(0, unaligned);
+  i::Heap::CollectAllGarbage(false);
+  CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
+
+  delete[] data;
+}
+
+
+THREADED_TEST(IdentityHash) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  // Ensure that the test starts with an fresh heap to test whether the hash
+  // code is based on the address.
+  i::Heap::CollectAllGarbage(false);
+  Local<v8::Object> obj = v8::Object::New();
+  int hash = obj->GetIdentityHash();
+  int hash1 = obj->GetIdentityHash();
+  CHECK_EQ(hash, hash1);
+  int hash2 = v8::Object::New()->GetIdentityHash();
+  // Since the identity hash is essentially a random number two consecutive
+  // objects should not be assigned the same hash code. If the test below fails
+  // the random number generator should be evaluated.
+  CHECK_NE(hash, hash2);
+  i::Heap::CollectAllGarbage(false);
+  int hash3 = v8::Object::New()->GetIdentityHash();
+  // Make sure that the identity hash is not based on the initial address of
+  // the object alone. If the test below fails the random number generator
+  // should be evaluated.
+  CHECK_NE(hash, hash3);
+  int hash4 = obj->GetIdentityHash();
+  CHECK_EQ(hash, hash4);
+}
+
+
+THREADED_TEST(HiddenProperties) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  v8::Local<v8::Object> obj = v8::Object::New();
+  v8::Local<v8::String> key = v8_str("api-test::hidden-key");
+  v8::Local<v8::String> empty = v8_str("");
+  v8::Local<v8::String> prop_name = v8_str("prop_name");
+
+  i::Heap::CollectAllGarbage(false);
+
+  // Make sure delete of a non-existent hidden value works
+  CHECK(obj->DeleteHiddenValue(key));
+
+  CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
+  CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
+  CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+
+  i::Heap::CollectAllGarbage(false);
+
+  // Make sure we do not find the hidden property.
+  CHECK(!obj->Has(empty));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK(obj->Get(empty)->IsUndefined());
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK(obj->Set(empty, v8::Integer::New(2003)));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK_EQ(2003, obj->Get(empty)->Int32Value());
+
+  i::Heap::CollectAllGarbage(false);
+
+  // Add another property and delete it afterwards to force the object in
+  // slow case.
+  CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK(obj->Delete(prop_name));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+
+  i::Heap::CollectAllGarbage(false);
+
+  CHECK(obj->DeleteHiddenValue(key));
+  CHECK(obj->GetHiddenValue(key).IsEmpty());
+}
+
+
+static v8::Handle<Value> InterceptorForHiddenProperties(
+    Local<String> name, const AccessorInfo& info) {
+  // Make sure objects move.
+  bool saved_always_compact = i::FLAG_always_compact;
+  if (!i::FLAG_never_compact) {
+    i::FLAG_always_compact = true;
+  }
+  // The whole goal of this interceptor is to cause a GC during local property
+  // lookup.
+  i::Heap::CollectAllGarbage(false);
+  i::FLAG_always_compact = saved_always_compact;
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(HiddenPropertiesWithInterceptors) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  v8::Local<v8::String> key = v8_str("api-test::hidden-key");
+
+  // Associate an interceptor with an object and start setting hidden values.
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
+  instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
+  Local<v8::Function> function = fun_templ->GetFunction();
+  Local<v8::Object> obj = function->NewInstance();
+  CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
+  CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
+}
+
+
+THREADED_TEST(External) {
+  v8::HandleScope scope;
+  int x = 3;
+  Local<v8::External> ext = v8::External::New(&x);
+  LocalContext env;
+  env->Global()->Set(v8_str("ext"), ext);
+  Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
+  v8::Handle<v8::External> reext = v8::Handle<v8::External>::Cast(reext_obj);
+  int* ptr = static_cast<int*>(reext->Value());
+  CHECK_EQ(x, 3);
+  *ptr = 10;
+  CHECK_EQ(x, 10);
+
+  // Make sure unaligned pointers are wrapped properly.
+  char* data = i::StrDup("0123456789");
+  Local<v8::Value> zero = v8::External::Wrap(&data[0]);
+  Local<v8::Value> one = v8::External::Wrap(&data[1]);
+  Local<v8::Value> two = v8::External::Wrap(&data[2]);
+  Local<v8::Value> three = v8::External::Wrap(&data[3]);
+
+  char* char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(zero));
+  CHECK_EQ('0', *char_ptr);
+  char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(one));
+  CHECK_EQ('1', *char_ptr);
+  char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(two));
+  CHECK_EQ('2', *char_ptr);
+  char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(three));
+  CHECK_EQ('3', *char_ptr);
+  i::DeleteArray(data);
+}
+
+
+THREADED_TEST(GlobalHandle) {
+  v8::Persistent<String> global;
+  {
+    v8::HandleScope scope;
+    Local<String> str = v8_str("str");
+    global = v8::Persistent<String>::New(str);
+  }
+  CHECK_EQ(global->Length(), 3);
+  global.Dispose();
+}
+
+
+THREADED_TEST(ScriptException) {
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
+  v8::TryCatch try_catch;
+  Local<Value> result = script->Run();
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  String::AsciiValue exception_value(try_catch.Exception());
+  CHECK_EQ(*exception_value, "panama!");
+}
+
+
+bool message_received;
+
+
+static void check_message(v8::Handle<v8::Message> message,
+                          v8::Handle<Value> data) {
+  CHECK_EQ(5.76, data->NumberValue());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
+  message_received = true;
+}
+
+
+THREADED_TEST(MessageHandlerData) {
+  message_received = false;
+  v8::HandleScope scope;
+  CHECK(!message_received);
+  v8::V8::AddMessageListener(check_message, v8_num(5.76));
+  LocalContext context;
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8_str("6.75"));
+  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
+                                                  &origin);
+  script->SetData(v8_str("7.56"));
+  script->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message);
+}
+
+
+THREADED_TEST(GetSetProperty) {
+  v8::HandleScope scope;
+  LocalContext context;
+  context->Global()->Set(v8_str("foo"), v8_num(14));
+  context->Global()->Set(v8_str("12"), v8_num(92));
+  context->Global()->Set(v8::Integer::New(16), v8_num(32));
+  context->Global()->Set(v8_num(13), v8_num(56));
+  Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
+  CHECK_EQ(14, foo->Int32Value());
+  Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
+  CHECK_EQ(92, twelve->Int32Value());
+  Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
+  CHECK_EQ(32, sixteen->Int32Value());
+  Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
+  CHECK_EQ(56, thirteen->Int32Value());
+  CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
+  CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
+  CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
+  CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
+  CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
+  CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
+  CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
+  CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
+  CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
+}
+
+
+THREADED_TEST(PropertyAttributes) {
+  v8::HandleScope scope;
+  LocalContext context;
+  // read-only
+  Local<String> prop = v8_str("read_only");
+  context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
+  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
+  Script::Compile(v8_str("read_only = 9"))->Run();
+  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
+  context->Global()->Set(prop, v8_num(10));
+  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
+  // dont-delete
+  prop = v8_str("dont_delete");
+  context->Global()->Set(prop, v8_num(13), v8::DontDelete);
+  CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
+  Script::Compile(v8_str("delete dont_delete"))->Run();
+  CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
+}
+
+
+THREADED_TEST(Array) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<v8::Array> array = v8::Array::New();
+  CHECK_EQ(0, array->Length());
+  CHECK(array->Get(v8::Integer::New(0))->IsUndefined());
+  CHECK(!array->Has(0));
+  CHECK(array->Get(v8::Integer::New(100))->IsUndefined());
+  CHECK(!array->Has(100));
+  array->Set(v8::Integer::New(2), v8_num(7));
+  CHECK_EQ(3, array->Length());
+  CHECK(!array->Has(0));
+  CHECK(!array->Has(1));
+  CHECK(array->Has(2));
+  CHECK_EQ(7, array->Get(v8::Integer::New(2))->Int32Value());
+  Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
+  Local<v8::Array> arr = Local<v8::Array>::Cast(obj);
+  CHECK_EQ(3, arr->Length());
+  CHECK_EQ(1, arr->Get(v8::Integer::New(0))->Int32Value());
+  CHECK_EQ(2, arr->Get(v8::Integer::New(1))->Int32Value());
+  CHECK_EQ(3, arr->Get(v8::Integer::New(2))->Int32Value());
+}
+
+
+v8::Handle<Value> HandleF(const v8::Arguments& args) {
+  v8::HandleScope scope;
+  ApiTestFuzzer::Fuzz();
+  Local<v8::Array> result = v8::Array::New(args.Length());
+  for (int i = 0; i < args.Length(); i++)
+    result->Set(v8::Integer::New(i), args[i]);
+  return scope.Close(result);
+}
+
+
+THREADED_TEST(Vector) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> global = ObjectTemplate::New();
+  global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
+  LocalContext context(0, global);
+
+  const char* fun = "f()";
+  Local<v8::Array> a0 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun))->Run());
+  CHECK_EQ(0, a0->Length());
+
+  const char* fun2 = "f(11)";
+  Local<v8::Array> a1 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun2))->Run());
+  CHECK_EQ(1, a1->Length());
+  CHECK_EQ(11, a1->Get(v8::Integer::New(0))->Int32Value());
+
+  const char* fun3 = "f(12, 13)";
+  Local<v8::Array> a2 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun3))->Run());
+  CHECK_EQ(2, a2->Length());
+  CHECK_EQ(12, a2->Get(v8::Integer::New(0))->Int32Value());
+  CHECK_EQ(13, a2->Get(v8::Integer::New(1))->Int32Value());
+
+  const char* fun4 = "f(14, 15, 16)";
+  Local<v8::Array> a3 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun4))->Run());
+  CHECK_EQ(3, a3->Length());
+  CHECK_EQ(14, a3->Get(v8::Integer::New(0))->Int32Value());
+  CHECK_EQ(15, a3->Get(v8::Integer::New(1))->Int32Value());
+  CHECK_EQ(16, a3->Get(v8::Integer::New(2))->Int32Value());
+
+  const char* fun5 = "f(17, 18, 19, 20)";
+  Local<v8::Array> a4 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun5))->Run());
+  CHECK_EQ(4, a4->Length());
+  CHECK_EQ(17, a4->Get(v8::Integer::New(0))->Int32Value());
+  CHECK_EQ(18, a4->Get(v8::Integer::New(1))->Int32Value());
+  CHECK_EQ(19, a4->Get(v8::Integer::New(2))->Int32Value());
+  CHECK_EQ(20, a4->Get(v8::Integer::New(3))->Int32Value());
+}
+
+
+THREADED_TEST(FunctionCall) {
+  v8::HandleScope scope;
+  LocalContext context;
+  CompileRun(
+    "function Foo() {"
+    "  var result = [];"
+    "  for (var i = 0; i < arguments.length; i++) {"
+    "    result.push(arguments[i]);"
+    "  }"
+    "  return result;"
+    "}");
+  Local<Function> Foo =
+      Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
+
+  v8::Handle<Value>* args0 = NULL;
+  Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
+  CHECK_EQ(0, a0->Length());
+
+  v8::Handle<Value> args1[] = { v8_num(1.1) };
+  Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
+  CHECK_EQ(1, a1->Length());
+  CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
+
+  v8::Handle<Value> args2[] = { v8_num(2.2),
+                                v8_num(3.3) };
+  Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
+  CHECK_EQ(2, a2->Length());
+  CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
+
+  v8::Handle<Value> args3[] = { v8_num(4.4),
+                                v8_num(5.5),
+                                v8_num(6.6) };
+  Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
+  CHECK_EQ(3, a3->Length());
+  CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
+  CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
+
+  v8::Handle<Value> args4[] = { v8_num(7.7),
+                                v8_num(8.8),
+                                v8_num(9.9),
+                                v8_num(10.11) };
+  Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
+  CHECK_EQ(4, a4->Length());
+  CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
+  CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
+  CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
+}
+
+
+static const char* js_code_causing_out_of_memory =
+    "var a = new Array(); while(true) a.push(a);";
+
+
+// These tests run for a long time and prevent us from running tests
+// that come after them so they cannot run in parallel.
+TEST(OutOfMemory) {
+  // It's not possible to read a snapshot into a heap with different dimensions.
+  if (v8::internal::Snapshot::IsEnabled()) return;
+  // Set heap limits.
+  static const int K = 1024;
+  v8::ResourceConstraints constraints;
+  constraints.set_max_young_space_size(256 * K);
+  constraints.set_max_old_space_size(4 * K * K);
+  v8::SetResourceConstraints(&constraints);
+
+  // Execute a script that causes out of memory.
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::V8::IgnoreOutOfMemoryException();
+  Local<Script> script =
+      Script::Compile(String::New(js_code_causing_out_of_memory));
+  Local<Value> result = script->Run();
+
+  // Check for out of memory state.
+  CHECK(result.IsEmpty());
+  CHECK(context->HasOutOfMemoryException());
+}
+
+
+v8::Handle<Value> ProvokeOutOfMemory(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<Script> script =
+      Script::Compile(String::New(js_code_causing_out_of_memory));
+  Local<Value> result = script->Run();
+
+  // Check for out of memory state.
+  CHECK(result.IsEmpty());
+  CHECK(context->HasOutOfMemoryException());
+
+  return result;
+}
+
+
+TEST(OutOfMemoryNested) {
+  // It's not possible to read a snapshot into a heap with different dimensions.
+  if (v8::internal::Snapshot::IsEnabled()) return;
+  // Set heap limits.
+  static const int K = 1024;
+  v8::ResourceConstraints constraints;
+  constraints.set_max_young_space_size(256 * K);
+  constraints.set_max_old_space_size(4 * K * K);
+  v8::SetResourceConstraints(&constraints);
+
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ProvokeOutOfMemory"),
+             v8::FunctionTemplate::New(ProvokeOutOfMemory));
+  LocalContext context(0, templ);
+  v8::V8::IgnoreOutOfMemoryException();
+  Local<Value> result = CompileRun(
+    "var thrown = false;"
+    "try {"
+    "  ProvokeOutOfMemory();"
+    "} catch (e) {"
+    "  thrown = true;"
+    "}");
+  // Check for out of memory state.
+  CHECK(result.IsEmpty());
+  CHECK(context->HasOutOfMemoryException());
+}
+
+
+TEST(HugeConsStringOutOfMemory) {
+  // It's not possible to read a snapshot into a heap with different dimensions.
+  if (v8::internal::Snapshot::IsEnabled()) return;
+  v8::HandleScope scope;
+  LocalContext context;
+  // Set heap limits.
+  static const int K = 1024;
+  v8::ResourceConstraints constraints;
+  constraints.set_max_young_space_size(256 * K);
+  constraints.set_max_old_space_size(2 * K * K);
+  v8::SetResourceConstraints(&constraints);
+
+  // Execute a script that causes out of memory.
+  v8::V8::IgnoreOutOfMemoryException();
+
+  // Build huge string. This should fail with out of memory exception.
+  Local<Value> result = CompileRun(
+    "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
+    "for (var i = 0; i < 21; i++) { str = str + str; }");
+
+  // Check for out of memory state.
+  CHECK(result.IsEmpty());
+  CHECK(context->HasOutOfMemoryException());
+}
+
+
+THREADED_TEST(ConstructCall) {
+  v8::HandleScope scope;
+  LocalContext context;
+  CompileRun(
+    "function Foo() {"
+    "  var result = [];"
+    "  for (var i = 0; i < arguments.length; i++) {"
+    "    result.push(arguments[i]);"
+    "  }"
+    "  return result;"
+    "}");
+  Local<Function> Foo =
+      Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
+
+  v8::Handle<Value>* args0 = NULL;
+  Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
+  CHECK_EQ(0, a0->Length());
+
+  v8::Handle<Value> args1[] = { v8_num(1.1) };
+  Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
+  CHECK_EQ(1, a1->Length());
+  CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
+
+  v8::Handle<Value> args2[] = { v8_num(2.2),
+                                v8_num(3.3) };
+  Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
+  CHECK_EQ(2, a2->Length());
+  CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
+
+  v8::Handle<Value> args3[] = { v8_num(4.4),
+                                v8_num(5.5),
+                                v8_num(6.6) };
+  Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
+  CHECK_EQ(3, a3->Length());
+  CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
+  CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
+
+  v8::Handle<Value> args4[] = { v8_num(7.7),
+                                v8_num(8.8),
+                                v8_num(9.9),
+                                v8_num(10.11) };
+  Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
+  CHECK_EQ(4, a4->Length());
+  CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
+  CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
+  CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
+}
+
+
+static void CheckUncle(v8::TryCatch* try_catch) {
+  CHECK(try_catch->HasCaught());
+  String::AsciiValue str_value(try_catch->Exception());
+  CHECK_EQ(*str_value, "uncle?");
+  try_catch->Reset();
+}
+
+
+THREADED_TEST(ConversionException) {
+  v8::HandleScope scope;
+  LocalContext env;
+  CompileRun(
+    "function TestClass() { };"
+    "TestClass.prototype.toString = function () { throw 'uncle?'; };"
+    "var obj = new TestClass();");
+  Local<Value> obj = env->Global()->Get(v8_str("obj"));
+
+  v8::TryCatch try_catch;
+
+  Local<Value> to_string_result = obj->ToString();
+  CHECK(to_string_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_number_result = obj->ToNumber();
+  CHECK(to_number_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_integer_result = obj->ToInteger();
+  CHECK(to_integer_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_uint32_result = obj->ToUint32();
+  CHECK(to_uint32_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_int32_result = obj->ToInt32();
+  CHECK(to_int32_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_object_result = v8::Undefined()->ToObject();
+  CHECK(to_object_result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  int32_t int32_value = obj->Int32Value();
+  CHECK_EQ(0, int32_value);
+  CheckUncle(&try_catch);
+
+  uint32_t uint32_value = obj->Uint32Value();
+  CHECK_EQ(0, uint32_value);
+  CheckUncle(&try_catch);
+
+  double number_value = obj->NumberValue();
+  CHECK_NE(0, IsNaN(number_value));
+  CheckUncle(&try_catch);
+
+  int64_t integer_value = obj->IntegerValue();
+  CHECK_EQ(0.0, static_cast<double>(integer_value));
+  CheckUncle(&try_catch);
+}
+
+
+v8::Handle<Value> ThrowFromC(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8::ThrowException(v8_str("konto"));
+}
+
+
+v8::Handle<Value> CCatcher(const v8::Arguments& args) {
+  if (args.Length() < 1) return v8::Boolean::New(false);
+  v8::HandleScope scope;
+  v8::TryCatch try_catch;
+  Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
+  CHECK(!try_catch.HasCaught() || result.IsEmpty());
+  return v8::Boolean::New(try_catch.HasCaught());
+}
+
+
+THREADED_TEST(APICatch) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+  CompileRun(
+    "var thrown = false;"
+    "try {"
+    "  ThrowFromC();"
+    "} catch (e) {"
+    "  thrown = true;"
+    "}");
+  Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
+  CHECK(thrown->BooleanValue());
+}
+
+
+THREADED_TEST(APIThrowTryCatch) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+  v8::TryCatch try_catch;
+  CompileRun("ThrowFromC();");
+  CHECK(try_catch.HasCaught());
+}
+
+
+// Test that a try-finally block doesn't shadow a try-catch block
+// when setting up an external handler.
+//
+// BUG(271): Some of the exception propagation does not work on the
+// ARM simulator because the simulator separates the C++ stack and the
+// JS stack.  This test therefore fails on the simulator.  The test is
+// not threaded to allow the threading tests to run on the simulator.
+TEST(TryCatchInTryFinally) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("CCatcher"),
+             v8::FunctionTemplate::New(CCatcher));
+  LocalContext context(0, templ);
+  Local<Value> result = CompileRun("try {"
+                                   "  try {"
+                                   "    CCatcher('throw 7;');"
+                                   "  } finally {"
+                                   "  }"
+                                   "} catch (e) {"
+                                   "}");
+  CHECK(result->IsTrue());
+}
+
+
+static void receive_message(v8::Handle<v8::Message> message,
+                            v8::Handle<v8::Value> data) {
+  message->Get();
+  message_received = true;
+}
+
+
+TEST(APIThrowMessage) {
+  message_received = false;
+  v8::HandleScope scope;
+  v8::V8::AddMessageListener(receive_message);
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+  CompileRun("ThrowFromC();");
+  CHECK(message_received);
+  v8::V8::RemoveMessageListeners(check_message);
+}
+
+
+TEST(APIThrowMessageAndVerboseTryCatch) {
+  message_received = false;
+  v8::HandleScope scope;
+  v8::V8::AddMessageListener(receive_message);
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+  v8::TryCatch try_catch;
+  try_catch.SetVerbose(true);
+  Local<Value> result = CompileRun("ThrowFromC();");
+  CHECK(try_catch.HasCaught());
+  CHECK(result.IsEmpty());
+  CHECK(message_received);
+  v8::V8::RemoveMessageListeners(check_message);
+}
+
+
+THREADED_TEST(ExternalScriptException) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+
+  v8::TryCatch try_catch;
+  Local<Script> script
+      = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
+  Local<Value> result = script->Run();
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  String::AsciiValue exception_value(try_catch.Exception());
+  CHECK_EQ("konto", *exception_value);
+}
+
+
+
+v8::Handle<Value> CThrowCountDown(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(4, args.Length());
+  int count = args[0]->Int32Value();
+  int cInterval = args[2]->Int32Value();
+  if (count == 0) {
+    return v8::ThrowException(v8_str("FromC"));
+  } else {
+    Local<v8::Object> global = Context::GetCurrent()->Global();
+    Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
+    v8::Handle<Value> argv[] = { v8_num(count - 1),
+                                 args[1],
+                                 args[2],
+                                 args[3] };
+    if (count % cInterval == 0) {
+      v8::TryCatch try_catch;
+      Local<Value> result =
+          v8::Handle<Function>::Cast(fun)->Call(global, 4, argv);
+      int expected = args[3]->Int32Value();
+      if (try_catch.HasCaught()) {
+        CHECK_EQ(expected, count);
+        CHECK(result.IsEmpty());
+        CHECK(!i::Top::has_scheduled_exception());
+      } else {
+        CHECK_NE(expected, count);
+      }
+      return result;
+    } else {
+      return v8::Handle<Function>::Cast(fun)->Call(global, 4, argv);
+    }
+  }
+}
+
+
+v8::Handle<Value> JSCheck(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(3, args.Length());
+  bool equality = args[0]->BooleanValue();
+  int count = args[1]->Int32Value();
+  int expected = args[2]->Int32Value();
+  if (equality) {
+    CHECK_EQ(count, expected);
+  } else {
+    CHECK_NE(count, expected);
+  }
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(EvalInTryFinally) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  CompileRun("(function() {"
+             "  try {"
+             "    eval('asldkf (*&^&*^');"
+             "  } finally {"
+             "    return;"
+             "  }"
+             "})()");
+  CHECK(!try_catch.HasCaught());
+}
+
+
+// This test works by making a stack of alternating JavaScript and C
+// activations.  These activations set up exception handlers with regular
+// intervals, one interval for C activations and another for JavaScript
+// activations.  When enough activations have been created an exception is
+// thrown and we check that the right activation catches the exception and that
+// no other activations do.  The right activation is always the topmost one with
+// a handler, regardless of whether it is in JavaScript or C.
+//
+// The notation used to describe a test case looks like this:
+//
+//    *JS[4] *C[3] @JS[2] C[1] JS[0]
+//
+// Each entry is an activation, either JS or C.  The index is the count at that
+// level.  Stars identify activations with exception handlers, the @ identifies
+// the exception handler that should catch the exception.
+//
+// BUG(271): Some of the exception propagation does not work on the
+// ARM simulator because the simulator separates the C++ stack and the
+// JS stack.  This test therefore fails on the simulator.  The test is
+// not threaded to allow the threading tests to run on the simulator.
+TEST(ExceptionOrder) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
+  templ->Set(v8_str("CThrowCountDown"),
+             v8::FunctionTemplate::New(CThrowCountDown));
+  LocalContext context(0, templ);
+  CompileRun(
+    "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
+    "  if (count == 0) throw 'FromJS';"
+    "  if (count % jsInterval == 0) {"
+    "    try {"
+    "      var value = CThrowCountDown(count - 1,"
+    "                                  jsInterval,"
+    "                                  cInterval,"
+    "                                  expected);"
+    "      check(false, count, expected);"
+    "      return value;"
+    "    } catch (e) {"
+    "      check(true, count, expected);"
+    "    }"
+    "  } else {"
+    "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
+    "  }"
+    "}");
+  Local<Function> fun =
+      Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
+
+  const int argc = 4;
+  //                             count      jsInterval cInterval  expected
+
+  // *JS[4] *C[3] @JS[2] C[1] JS[0]
+  v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
+  fun->Call(fun, argc, a0);
+
+  // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
+  v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
+  fun->Call(fun, argc, a1);
+
+  // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
+  v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
+  fun->Call(fun, argc, a2);
+
+  // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
+  v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
+  fun->Call(fun, argc, a3);
+
+  // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
+  v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
+  fun->Call(fun, argc, a4);
+
+  // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
+  v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
+  fun->Call(fun, argc, a5);
+}
+
+
+v8::Handle<Value> ThrowValue(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(1, args.Length());
+  return v8::ThrowException(args[0]);
+}
+
+
+THREADED_TEST(ThrowValues) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
+  LocalContext context(0, templ);
+  v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
+    "function Run(obj) {"
+    "  try {"
+    "    Throw(obj);"
+    "  } catch (e) {"
+    "    return e;"
+    "  }"
+    "  return 'no exception';"
+    "}"
+    "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
+  CHECK_EQ(5, result->Length());
+  CHECK(result->Get(v8::Integer::New(0))->IsString());
+  CHECK(result->Get(v8::Integer::New(1))->IsNumber());
+  CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
+  CHECK(result->Get(v8::Integer::New(2))->IsNumber());
+  CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
+  CHECK(result->Get(v8::Integer::New(3))->IsNull());
+  CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
+}
+
+
+THREADED_TEST(CatchZero) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("throw 10"))->Run();
+  CHECK(try_catch.HasCaught());
+  CHECK_EQ(10, try_catch.Exception()->Int32Value());
+  try_catch.Reset();
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("throw 0"))->Run();
+  CHECK(try_catch.HasCaught());
+  CHECK_EQ(0, try_catch.Exception()->Int32Value());
+}
+
+
+THREADED_TEST(CatchExceptionFromWith) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
+  CHECK(try_catch.HasCaught());
+}
+
+
+THREADED_TEST(Equality) {
+  v8::HandleScope scope;
+  LocalContext context;
+  // Check that equality works at all before relying on CHECK_EQ
+  CHECK(v8_str("a")->Equals(v8_str("a")));
+  CHECK(!v8_str("a")->Equals(v8_str("b")));
+
+  CHECK_EQ(v8_str("a"), v8_str("a"));
+  CHECK_NE(v8_str("a"), v8_str("b"));
+  CHECK_EQ(v8_num(1), v8_num(1));
+  CHECK_EQ(v8_num(1.00), v8_num(1));
+  CHECK_NE(v8_num(1), v8_num(2));
+
+  // Assume String is not symbol.
+  CHECK(v8_str("a")->StrictEquals(v8_str("a")));
+  CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
+  CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
+  CHECK(v8_num(1)->StrictEquals(v8_num(1)));
+  CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
+  CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
+  Local<Value> not_a_number = v8_num(i::OS::nan_value());
+  CHECK(!not_a_number->StrictEquals(not_a_number));
+  CHECK(v8::False()->StrictEquals(v8::False()));
+  CHECK(!v8::False()->StrictEquals(v8::Undefined()));
+
+  v8::Handle<v8::Object> obj = v8::Object::New();
+  v8::Persistent<v8::Object> alias = v8::Persistent<v8::Object>::New(obj);
+  CHECK(alias->StrictEquals(obj));
+  alias.Dispose();
+}
+
+
+THREADED_TEST(MultiRun) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<Script> script = Script::Compile(v8_str("x"));
+  for (int i = 0; i < 10; i++)
+    script->Run();
+}
+
+
+static v8::Handle<Value> GetXValue(Local<String> name,
+                                   const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(info.Data(), v8_str("donut"));
+  CHECK_EQ(name, v8_str("x"));
+  return name;
+}
+
+
+THREADED_TEST(SimplePropertyRead) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
+  LocalContext context;
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  Local<Script> script = Script::Compile(v8_str("obj.x"));
+  for (int i = 0; i < 10; i++) {
+    Local<Value> result = script->Run();
+    CHECK_EQ(result, v8_str("x"));
+  }
+}
+
+
+v8::Persistent<Value> xValue;
+
+
+static void SetXValue(Local<String> name,
+                      Local<Value> value,
+                      const AccessorInfo& info) {
+  CHECK_EQ(value, v8_num(4));
+  CHECK_EQ(info.Data(), v8_str("donut"));
+  CHECK_EQ(name, v8_str("x"));
+  CHECK(xValue.IsEmpty());
+  xValue = v8::Persistent<Value>::New(value);
+}
+
+
+THREADED_TEST(SimplePropertyWrite) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
+  LocalContext context;
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
+  for (int i = 0; i < 10; i++) {
+    CHECK(xValue.IsEmpty());
+    script->Run();
+    CHECK_EQ(v8_num(4), xValue);
+    xValue.Dispose();
+    xValue = v8::Persistent<Value>();
+  }
+}
+
+
+static v8::Handle<Value> XPropertyGetter(Local<String> property,
+                                         const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.Data()->IsUndefined());
+  return property;
+}
+
+
+THREADED_TEST(NamedInterceptorPropertyRead) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(XPropertyGetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  Local<Script> script = Script::Compile(v8_str("obj.x"));
+  for (int i = 0; i < 10; i++) {
+    Local<Value> result = script->Run();
+    CHECK_EQ(result, v8_str("x"));
+  }
+}
+
+
+static v8::Handle<Value> IndexedPropertyGetter(uint32_t index,
+                                               const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (index == 37) {
+    return v8::Handle<Value>(v8_num(625));
+  }
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> IndexedPropertySetter(uint32_t index,
+                                               Local<Value> value,
+                                               const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (index == 39) {
+    return value;
+  }
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
+                                   IndexedPropertySetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  Local<Script> getter_script = Script::Compile(v8_str(
+      "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
+  Local<Script> setter_script = Script::Compile(v8_str(
+      "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
+      "obj[17] = 23;"
+      "obj.foo;"));
+  Local<Script> interceptor_setter_script = Script::Compile(v8_str(
+      "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
+      "obj[39] = 47;"
+      "obj.foo;"));  // This setter should not run, due to the interceptor.
+  Local<Script> interceptor_getter_script = Script::Compile(v8_str(
+      "obj[37];"));
+  Local<Value> result = getter_script->Run();
+  CHECK_EQ(v8_num(5), result);
+  result = setter_script->Run();
+  CHECK_EQ(v8_num(23), result);
+  result = interceptor_setter_script->Run();
+  CHECK_EQ(v8_num(23), result);
+  result = interceptor_getter_script->Run();
+  CHECK_EQ(v8_num(625), result);
+}
+
+
+THREADED_TEST(MultiContexts) {
+  v8::HandleScope scope;
+  v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
+
+  Local<String> password = v8_str("Password");
+
+  // Create an environment
+  LocalContext context0(0, templ);
+  context0->SetSecurityToken(password);
+  v8::Handle<v8::Object> global0 = context0->Global();
+  global0->Set(v8_str("custom"), v8_num(1234));
+  CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
+
+  // Create an independent environment
+  LocalContext context1(0, templ);
+  context1->SetSecurityToken(password);
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("custom"), v8_num(1234));
+  CHECK_NE(global0, global1);
+  CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
+  CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
+
+  // Now create a new context with the old global
+  LocalContext context2(0, templ, global1);
+  context2->SetSecurityToken(password);
+  v8::Handle<v8::Object> global2 = context2->Global();
+  CHECK_EQ(global1, global2);
+  CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
+  CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
+}
+
+
+THREADED_TEST(FunctionPrototypeAcrossContexts) {
+  // Make sure that functions created by cloning boilerplates cannot
+  // communicate through their __proto__ field.
+
+  v8::HandleScope scope;
+
+  LocalContext env0;
+  v8::Handle<v8::Object> global0 =
+      env0->Global();
+  v8::Handle<v8::Object> object0 =
+      v8::Handle<v8::Object>::Cast(global0->Get(v8_str("Object")));
+  v8::Handle<v8::Object> tostring0 =
+      v8::Handle<v8::Object>::Cast(object0->Get(v8_str("toString")));
+  v8::Handle<v8::Object> proto0 =
+      v8::Handle<v8::Object>::Cast(tostring0->Get(v8_str("__proto__")));
+  proto0->Set(v8_str("custom"), v8_num(1234));
+
+  LocalContext env1;
+  v8::Handle<v8::Object> global1 =
+      env1->Global();
+  v8::Handle<v8::Object> object1 =
+      v8::Handle<v8::Object>::Cast(global1->Get(v8_str("Object")));
+  v8::Handle<v8::Object> tostring1 =
+      v8::Handle<v8::Object>::Cast(object1->Get(v8_str("toString")));
+  v8::Handle<v8::Object> proto1 =
+      v8::Handle<v8::Object>::Cast(tostring1->Get(v8_str("__proto__")));
+  CHECK(!proto1->Has(v8_str("custom")));
+}
+
+
+THREADED_TEST(Regress892105) {
+  // Make sure that object and array literals created by cloning
+  // boilerplates cannot communicate through their __proto__
+  // field. This is rather difficult to check, but we try to add stuff
+  // to Object.prototype and Array.prototype and create a new
+  // environment. This should succeed.
+
+  v8::HandleScope scope;
+
+  Local<String> source = v8_str("Object.prototype.obj = 1234;"
+                                "Array.prototype.arr = 4567;"
+                                "8901");
+
+  LocalContext env0;
+  Local<Script> script0 = Script::Compile(source);
+  CHECK_EQ(8901.0, script0->Run()->NumberValue());
+
+  LocalContext env1;
+  Local<Script> script1 = Script::Compile(source);
+  CHECK_EQ(8901.0, script1->Run()->NumberValue());
+}
+
+
+static void ExpectString(const char* code, const char* expected) {
+  Local<Value> result = CompileRun(code);
+  CHECK(result->IsString());
+  String::AsciiValue ascii(result);
+  CHECK_EQ(0, strcmp(*ascii, expected));
+}
+
+
+static void ExpectBoolean(const char* code, bool expected) {
+  Local<Value> result = CompileRun(code);
+  CHECK(result->IsBoolean());
+  CHECK_EQ(expected, result->BooleanValue());
+}
+
+
+static void ExpectObject(const char* code, Local<Value> expected) {
+  Local<Value> result = CompileRun(code);
+  CHECK(result->Equals(expected));
+}
+
+
+THREADED_TEST(UndetectableObject) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  Local<v8::FunctionTemplate> desc =
+      v8::FunctionTemplate::New(0, v8::Handle<Value>());
+  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
+
+  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
+  env->Global()->Set(v8_str("undetectable"), obj);
+
+  ExpectString("undetectable.toString()", "[object Object]");
+  ExpectString("typeof undetectable", "undefined");
+  ExpectString("typeof(undetectable)", "undefined");
+  ExpectBoolean("typeof undetectable == 'undefined'", true);
+  ExpectBoolean("typeof undetectable == 'object'", false);
+  ExpectBoolean("if (undetectable) { true; } else { false; }", false);
+  ExpectBoolean("!undetectable", true);
+
+  ExpectObject("true&&undetectable", obj);
+  ExpectBoolean("false&&undetectable", false);
+  ExpectBoolean("true||undetectable", true);
+  ExpectObject("false||undetectable", obj);
+
+  ExpectObject("undetectable&&true", obj);
+  ExpectObject("undetectable&&false", obj);
+  ExpectBoolean("undetectable||true", true);
+  ExpectBoolean("undetectable||false", false);
+
+  ExpectBoolean("undetectable==null", true);
+  ExpectBoolean("null==undetectable", true);
+  ExpectBoolean("undetectable==undefined", true);
+  ExpectBoolean("undefined==undetectable", true);
+  ExpectBoolean("undetectable==undetectable", true);
+
+
+  ExpectBoolean("undetectable===null", false);
+  ExpectBoolean("null===undetectable", false);
+  ExpectBoolean("undetectable===undefined", false);
+  ExpectBoolean("undefined===undetectable", false);
+  ExpectBoolean("undetectable===undetectable", true);
+}
+
+
+THREADED_TEST(UndetectableString) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  Local<String> obj = String::NewUndetectable("foo");
+  env->Global()->Set(v8_str("undetectable"), obj);
+
+  ExpectString("undetectable", "foo");
+  ExpectString("typeof undetectable", "undefined");
+  ExpectString("typeof(undetectable)", "undefined");
+  ExpectBoolean("typeof undetectable == 'undefined'", true);
+  ExpectBoolean("typeof undetectable == 'string'", false);
+  ExpectBoolean("if (undetectable) { true; } else { false; }", false);
+  ExpectBoolean("!undetectable", true);
+
+  ExpectObject("true&&undetectable", obj);
+  ExpectBoolean("false&&undetectable", false);
+  ExpectBoolean("true||undetectable", true);
+  ExpectObject("false||undetectable", obj);
+
+  ExpectObject("undetectable&&true", obj);
+  ExpectObject("undetectable&&false", obj);
+  ExpectBoolean("undetectable||true", true);
+  ExpectBoolean("undetectable||false", false);
+
+  ExpectBoolean("undetectable==null", true);
+  ExpectBoolean("null==undetectable", true);
+  ExpectBoolean("undetectable==undefined", true);
+  ExpectBoolean("undefined==undetectable", true);
+  ExpectBoolean("undetectable==undetectable", true);
+
+
+  ExpectBoolean("undetectable===null", false);
+  ExpectBoolean("null===undetectable", false);
+  ExpectBoolean("undetectable===undefined", false);
+  ExpectBoolean("undefined===undetectable", false);
+  ExpectBoolean("undetectable===undetectable", true);
+}
+
+
+template <typename T> static void USE(T) { }
+
+
+// This test is not intended to be run, just type checked.
+static void PersistentHandles() {
+  USE(PersistentHandles);
+  Local<String> str = v8_str("foo");
+  v8::Persistent<String> p_str = v8::Persistent<String>::New(str);
+  USE(p_str);
+  Local<Script> scr = Script::Compile(v8_str(""));
+  v8::Persistent<Script> p_scr = v8::Persistent<Script>::New(scr);
+  USE(p_scr);
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  v8::Persistent<ObjectTemplate> p_templ =
+    v8::Persistent<ObjectTemplate>::New(templ);
+  USE(p_templ);
+}
+
+
+static v8::Handle<Value> HandleLogDelegator(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(GlobalObjectTemplate) {
+  v8::HandleScope handle_scope;
+  Local<ObjectTemplate> global_template = ObjectTemplate::New();
+  global_template->Set(v8_str("JSNI_Log"),
+                       v8::FunctionTemplate::New(HandleLogDelegator));
+  v8::Persistent<Context> context = Context::New(0, global_template);
+  Context::Scope context_scope(context);
+  Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
+  context.Dispose();
+}
+
+
+static const char* kSimpleExtensionSource =
+  "function Foo() {"
+  "  return 4;"
+  "}";
+
+
+THREADED_TEST(SimpleExtensions) {
+  v8::HandleScope handle_scope;
+  v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
+  const char* extension_names[] = { "simpletest" };
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(&extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(4));
+}
+
+
+static const char* kEvalExtensionSource1 =
+  "function UseEval1() {"
+  "  var x = 42;"
+  "  return eval('x');"
+  "}";
+
+
+static const char* kEvalExtensionSource2 =
+  "(function() {"
+  "  var x = 42;"
+  "  function e() {"
+  "    return eval('x');"
+  "  }"
+  "  this.UseEval2 = e;"
+  "})()";
+
+
+THREADED_TEST(UseEvalFromExtension) {
+  v8::HandleScope handle_scope;
+  v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
+  v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
+  const char* extension_names[] = { "evaltest1", "evaltest2" };
+  v8::ExtensionConfiguration extensions(2, extension_names);
+  v8::Handle<Context> context = Context::New(&extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(42));
+  result = Script::Compile(v8_str("UseEval2()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(42));
+}
+
+
+static const char* kWithExtensionSource1 =
+  "function UseWith1() {"
+  "  var x = 42;"
+  "  with({x:87}) { return x; }"
+  "}";
+
+
+
+static const char* kWithExtensionSource2 =
+  "(function() {"
+  "  var x = 42;"
+  "  function e() {"
+  "    with ({x:87}) { return x; }"
+  "  }"
+  "  this.UseWith2 = e;"
+  "})()";
+
+
+THREADED_TEST(UseWithFromExtension) {
+  v8::HandleScope handle_scope;
+  v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
+  v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
+  const char* extension_names[] = { "withtest1", "withtest2" };
+  v8::ExtensionConfiguration extensions(2, extension_names);
+  v8::Handle<Context> context = Context::New(&extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(87));
+  result = Script::Compile(v8_str("UseWith2()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(87));
+}
+
+
+THREADED_TEST(AutoExtensions) {
+  v8::HandleScope handle_scope;
+  Extension* extension = new Extension("autotest", kSimpleExtensionSource);
+  extension->set_auto_enable(true);
+  v8::RegisterExtension(extension);
+  v8::Handle<Context> context = Context::New();
+  Context::Scope lock(context);
+  v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(4));
+}
+
+
+static void CheckDependencies(const char* name, const char* expected) {
+  v8::HandleScope handle_scope;
+  v8::ExtensionConfiguration config(1, &name);
+  LocalContext context(&config);
+  CHECK_EQ(String::New(expected), context->Global()->Get(v8_str("loaded")));
+}
+
+
+/*
+ * Configuration:
+ *
+ *     /-- B <--\
+ * A <-          -- D <-- E
+ *     \-- C <--/
+ */
+THREADED_TEST(ExtensionDependency) {
+  static const char* kEDeps[] = { "D" };
+  v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
+  static const char* kDDeps[] = { "B", "C" };
+  v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
+  static const char* kBCDeps[] = { "A" };
+  v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
+  v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
+  v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
+  CheckDependencies("A", "undefinedA");
+  CheckDependencies("B", "undefinedAB");
+  CheckDependencies("C", "undefinedAC");
+  CheckDependencies("D", "undefinedABCD");
+  CheckDependencies("E", "undefinedABCDE");
+  v8::HandleScope handle_scope;
+  static const char* exts[2] = { "C", "E" };
+  v8::ExtensionConfiguration config(2, exts);
+  LocalContext context(&config);
+  CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
+}
+
+
+static const char* kExtensionTestScript =
+  "native function A();"
+  "native function B();"
+  "native function C();"
+  "function Foo(i) {"
+  "  if (i == 0) return A();"
+  "  if (i == 1) return B();"
+  "  if (i == 2) return C();"
+  "}";
+
+
+static v8::Handle<Value> CallFun(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return args.Data();
+}
+
+
+class FunctionExtension : public Extension {
+ public:
+  FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+      v8::Handle<String> name);
+};
+
+
+static int lookup_count = 0;
+v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunction(
+      v8::Handle<String> name) {
+  lookup_count++;
+  if (name->Equals(v8_str("A"))) {
+    return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
+  } else if (name->Equals(v8_str("B"))) {
+    return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
+  } else if (name->Equals(v8_str("C"))) {
+    return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
+  } else {
+    return v8::Handle<v8::FunctionTemplate>();
+  }
+}
+
+
+THREADED_TEST(FunctionLookup) {
+  v8::RegisterExtension(new FunctionExtension());
+  v8::HandleScope handle_scope;
+  static const char* exts[1] = { "functiontest" };
+  v8::ExtensionConfiguration config(1, exts);
+  LocalContext context(&config);
+  CHECK_EQ(3, lookup_count);
+  CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
+  CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
+  CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
+}
+
+
+static const char* last_location;
+static const char* last_message;
+void StoringErrorCallback(const char* location, const char* message) {
+  if (last_location == NULL) {
+    last_location = location;
+    last_message = message;
+  }
+}
+
+
+// ErrorReporting creates a circular extensions configuration and
+// tests that the fatal error handler gets called.  This renders V8
+// unusable and therefore this test cannot be run in parallel.
+TEST(ErrorReporting) {
+  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+  static const char* aDeps[] = { "B" };
+  v8::RegisterExtension(new Extension("A", "", 1, aDeps));
+  static const char* bDeps[] = { "A" };
+  v8::RegisterExtension(new Extension("B", "", 1, bDeps));
+  last_location = NULL;
+  v8::ExtensionConfiguration config(1, bDeps);
+  v8::Handle<Context> context = Context::New(&config);
+  CHECK(context.IsEmpty());
+  CHECK_NE(last_location, NULL);
+}
+
+
+static const char* js_code_causing_huge_string_flattening =
+    "var str = 'X';"
+    "for (var i = 0; i < 30; i++) {"
+    "  str = str + str;"
+    "}"
+    "str.match(/X/);";
+
+
+void OOMCallback(const char* location, const char* message) {
+  exit(0);
+}
+
+
+TEST(RegexpOutOfMemory) {
+  // Execute a script that causes out of memory when flattening a string.
+  v8::HandleScope scope;
+  v8::V8::SetFatalErrorHandler(OOMCallback);
+  LocalContext context;
+  Local<Script> script =
+      Script::Compile(String::New(js_code_causing_huge_string_flattening));
+  last_location = NULL;
+  Local<Value> result = script->Run();
+
+  CHECK(false);  // Should not return.
+}
+
+
+static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
+                                             v8::Handle<Value> data) {
+  CHECK_EQ(v8::Undefined(), data);
+  CHECK(message->GetScriptResourceName()->IsUndefined());
+  CHECK_EQ(v8::Undefined(), message->GetScriptResourceName());
+  message->GetLineNumber();
+  message->GetSourceLine();
+}
+
+
+THREADED_TEST(ErrorWithMissingScriptInfo) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
+  Script::Compile(v8_str("throw Error()"))->Run();
+  v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
+}
+
+
+int global_index = 0;
+
+class Snorkel {
+ public:
+  Snorkel() { index_ = global_index++; }
+  int index_;
+};
+
+class Whammy {
+ public:
+  Whammy() {
+    cursor_ = 0;
+  }
+  ~Whammy() {
+    script_.Dispose();
+  }
+  v8::Handle<Script> getScript() {
+    if (script_.IsEmpty())
+      script_ = v8::Persistent<Script>::New(v8_compile("({}).blammo"));
+    return Local<Script>(*script_);
+  }
+
+ public:
+  static const int kObjectCount = 256;
+  int cursor_;
+  v8::Persistent<v8::Object> objects_[kObjectCount];
+  v8::Persistent<Script> script_;
+};
+
+static void HandleWeakReference(v8::Persistent<v8::Value> obj, void* data) {
+  Snorkel* snorkel = reinterpret_cast<Snorkel*>(data);
+  delete snorkel;
+  obj.ClearWeak();
+}
+
+v8::Handle<Value> WhammyPropertyGetter(Local<String> name,
+                                       const AccessorInfo& info) {
+  Whammy* whammy =
+    static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+
+  v8::Persistent<v8::Object> prev = whammy->objects_[whammy->cursor_];
+
+  v8::Handle<v8::Object> obj = v8::Object::New();
+  v8::Persistent<v8::Object> global = v8::Persistent<v8::Object>::New(obj);
+  if (!prev.IsEmpty()) {
+    prev->Set(v8_str("next"), obj);
+    prev.MakeWeak(new Snorkel(), &HandleWeakReference);
+    whammy->objects_[whammy->cursor_].Clear();
+  }
+  whammy->objects_[whammy->cursor_] = global;
+  whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
+  return whammy->getScript()->Run();
+}
+
+THREADED_TEST(WeakReference) {
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(WhammyPropertyGetter,
+                                 0, 0, 0, 0,
+                                 v8::External::New(new Whammy()));
+  const char* extension_list[] = { "v8/gc" };
+  v8::ExtensionConfiguration extensions(1, extension_list);
+  v8::Persistent<Context> context = Context::New(&extensions);
+  Context::Scope context_scope(context);
+
+  v8::Handle<v8::Object> interceptor = templ->NewInstance();
+  context->Global()->Set(v8_str("whammy"), interceptor);
+  const char* code =
+      "var last;"
+      "for (var i = 0; i < 10000; i++) {"
+      "  var obj = whammy.length;"
+      "  if (last) last.next = obj;"
+      "  last = obj;"
+      "}"
+      "gc();"
+      "4";
+  v8::Handle<Value> result = CompileRun(code);
+  CHECK_EQ(4.0, result->NumberValue());
+
+  context.Dispose();
+}
+
+
+v8::Handle<Function> args_fun;
+
+
+static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(args_fun, args.Callee());
+  CHECK_EQ(3, args.Length());
+  CHECK_EQ(v8::Integer::New(1), args[0]);
+  CHECK_EQ(v8::Integer::New(2), args[1]);
+  CHECK_EQ(v8::Integer::New(3), args[2]);
+  CHECK_EQ(v8::Undefined(), args[3]);
+  v8::HandleScope scope;
+  i::Heap::CollectAllGarbage(false);
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(Arguments) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
+  global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
+  LocalContext context(NULL, global);
+  args_fun = v8::Handle<Function>::Cast(context->Global()->Get(v8_str("f")));
+  v8_compile("f(1, 2, 3)")->Run();
+}
+
+
+static int x_register = 0;
+static v8::Handle<v8::Object> x_receiver;
+static v8::Handle<v8::Object> x_holder;
+
+
+static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(x_receiver, info.This());
+  CHECK_EQ(x_holder, info.Holder());
+  return v8_num(x_register);
+}
+
+
+static void XSetter(Local<String> name,
+                    Local<Value> value,
+                    const AccessorInfo& info) {
+  CHECK_EQ(x_holder, info.This());
+  CHECK_EQ(x_holder, info.Holder());
+  x_register = value->Int32Value();
+}
+
+
+THREADED_TEST(AccessorIC) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("x"), XGetter, XSetter);
+  LocalContext context;
+  x_holder = obj->NewInstance();
+  context->Global()->Set(v8_str("holder"), x_holder);
+  x_receiver = v8::Object::New();
+  context->Global()->Set(v8_str("obj"), x_receiver);
+  v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
+    "obj.__proto__ = holder;"
+    "var result = [];"
+    "for (var i = 0; i < 10; i++) {"
+    "  holder.x = i;"
+    "  result.push(obj.x);"
+    "}"
+    "result"));
+  CHECK_EQ(10, array->Length());
+  for (int i = 0; i < 10; i++) {
+    v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
+    CHECK_EQ(v8::Integer::New(i), entry);
+  }
+}
+
+
+static v8::Handle<Value> NoBlockGetterX(Local<String> name,
+                                        const AccessorInfo&) {
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> NoBlockGetterI(uint32_t index,
+                                        const AccessorInfo&) {
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<v8::Boolean> PDeleter(Local<String> name,
+                                        const AccessorInfo&) {
+  if (!name->Equals(v8_str("foo"))) {
+    return v8::Handle<v8::Boolean>();  // not intercepted
+  }
+
+  return v8::False();  // intercepted, and don't delete the property
+}
+
+
+static v8::Handle<v8::Boolean> IDeleter(uint32_t index, const AccessorInfo&) {
+  if (index != 2) {
+    return v8::Handle<v8::Boolean>();  // not intercepted
+  }
+
+  return v8::False();  // intercepted, and don't delete the property
+}
+
+
+THREADED_TEST(Deleter) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
+  obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
+  LocalContext context;
+  context->Global()->Set(v8_str("k"), obj->NewInstance());
+  CompileRun(
+    "k.foo = 'foo';"
+    "k.bar = 'bar';"
+    "k[2] = 2;"
+    "k[4] = 4;");
+  CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
+  CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
+
+  CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
+  CHECK(v8_compile("k.bar")->Run()->IsUndefined());
+
+  CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
+  CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
+
+  CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
+  CHECK(v8_compile("k[4]")->Run()->IsUndefined());
+}
+
+
+static v8::Handle<Value> GetK(Local<String> name, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  if (name->Equals(v8_str("foo")) ||
+      name->Equals(v8_str("bar")) ||
+      name->Equals(v8_str("baz"))) {
+    return v8::Undefined();
+  }
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> IndexedGetK(uint32_t index, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  if (index == 0 || index == 1) return v8::Undefined();
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<v8::Array> NamedEnum(const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  v8::Handle<v8::Array> result = v8::Array::New(3);
+  result->Set(v8::Integer::New(0), v8_str("foo"));
+  result->Set(v8::Integer::New(1), v8_str("bar"));
+  result->Set(v8::Integer::New(2), v8_str("baz"));
+  return result;
+}
+
+
+static v8::Handle<v8::Array> IndexedEnum(const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  v8::Handle<v8::Array> result = v8::Array::New(2);
+  result->Set(v8::Integer::New(0), v8_str("0"));
+  result->Set(v8::Integer::New(1), v8_str("1"));
+  return result;
+}
+
+
+THREADED_TEST(Enumerators) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
+  obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
+  LocalContext context;
+  context->Global()->Set(v8_str("k"), obj->NewInstance());
+  v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
+    "k[10] = 0;"
+    "k.a = 0;"
+    "k[5] = 0;"
+    "k.b = 0;"
+    "k[4294967295] = 0;"
+    "k.c = 0;"
+    "k[4294967296] = 0;"
+    "k.d = 0;"
+    "k[140000] = 0;"
+    "k.e = 0;"
+    "k[30000000000] = 0;"
+    "k.f = 0;"
+    "var result = [];"
+    "for (var prop in k) {"
+    "  result.push(prop);"
+    "}"
+    "result"));
+  // Check that we get all the property names returned including the
+  // ones from the enumerators in the right order: indexed properties
+  // in numerical order, indexed interceptor properties, named
+  // properties in insertion order, named interceptor properties.
+  // This order is not mandated by the spec, so this test is just
+  // documenting our behavior.
+  CHECK_EQ(17, result->Length());
+  // Indexed properties in numerical order.
+  CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
+  CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
+  CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
+  CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
+  // Indexed interceptor properties in the order they are returned
+  // from the enumerator interceptor.
+  CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
+  CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
+  // Named properties in insertion order.
+  CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
+  CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
+  CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
+  CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
+  CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
+  CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
+  CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
+  CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
+  // Named interceptor properties.
+  CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
+  CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
+  CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
+}
+
+
+int p_getter_count;
+int p_getter_count2;
+
+
+static v8::Handle<Value> PGetter(Local<String> name, const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  p_getter_count++;
+  v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
+  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
+  if (name->Equals(v8_str("p1"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o1")));
+  } else if (name->Equals(v8_str("p2"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o2")));
+  } else if (name->Equals(v8_str("p3"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o3")));
+  } else if (name->Equals(v8_str("p4"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o4")));
+  }
+  return v8::Undefined();
+}
+
+
+static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
+  ApiTestFuzzer::Fuzz();
+  LocalContext context;
+  context->Global()->Set(v8_str("o1"), obj->NewInstance());
+  CompileRun(
+    "o1.__proto__ = { };"
+    "var o2 = { __proto__: o1 };"
+    "var o3 = { __proto__: o2 };"
+    "var o4 = { __proto__: o3 };"
+    "for (var i = 0; i < 10; i++) o4.p4;"
+    "for (var i = 0; i < 10; i++) o3.p3;"
+    "for (var i = 0; i < 10; i++) o2.p2;"
+    "for (var i = 0; i < 10; i++) o1.p1;");
+}
+
+
+static v8::Handle<Value> PGetter2(Local<String> name,
+                                  const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  p_getter_count2++;
+  v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
+  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
+  if (name->Equals(v8_str("p1"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o1")));
+  } else if (name->Equals(v8_str("p2"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o2")));
+  } else if (name->Equals(v8_str("p3"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o3")));
+  } else if (name->Equals(v8_str("p4"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o4")));
+  }
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(GetterHolders) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("p1"), PGetter);
+  obj->SetAccessor(v8_str("p2"), PGetter);
+  obj->SetAccessor(v8_str("p3"), PGetter);
+  obj->SetAccessor(v8_str("p4"), PGetter);
+  p_getter_count = 0;
+  RunHolderTest(obj);
+  CHECK_EQ(40, p_getter_count);
+}
+
+
+THREADED_TEST(PreInterceptorHolders) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetNamedPropertyHandler(PGetter2);
+  p_getter_count2 = 0;
+  RunHolderTest(obj);
+  CHECK_EQ(40, p_getter_count2);
+}
+
+
+THREADED_TEST(ObjectInstantiation) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("t"), PGetter2);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  for (int i = 0; i < 100; i++) {
+    v8::HandleScope inner_scope;
+    v8::Handle<v8::Object> obj = templ->NewInstance();
+    CHECK_NE(obj, context->Global()->Get(v8_str("o")));
+    context->Global()->Set(v8_str("o2"), obj);
+    v8::Handle<Value> value =
+        Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
+    CHECK_EQ(v8::True(), value);
+    context->Global()->Set(v8_str("o"), obj);
+  }
+}
+
+
+THREADED_TEST(StringWrite) {
+  v8::HandleScope scope;
+  v8::Handle<String> str = v8_str("abcde");
+
+  char buf[100];
+  int len;
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf);
+  CHECK_EQ(len, 5);
+  CHECK_EQ(strncmp("abcde\0", buf, 6), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 0, 4);
+  CHECK_EQ(len, 4);
+  CHECK_EQ(strncmp("abcd\1", buf, 5), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 0, 5);
+  CHECK_EQ(len, 5);
+  CHECK_EQ(strncmp("abcde\1", buf, 6), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 0, 6);
+  CHECK_EQ(len, 5);
+  CHECK_EQ(strncmp("abcde\0", buf, 6), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 4, -1);
+  CHECK_EQ(len, 1);
+  CHECK_EQ(strncmp("e\0", buf, 2), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 4, 6);
+  CHECK_EQ(len, 1);
+  CHECK_EQ(strncmp("e\0", buf, 2), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 4, 1);
+  CHECK_EQ(len, 1);
+  CHECK_EQ(strncmp("e\1", buf, 2), 0);
+}
+
+
+THREADED_TEST(ToArrayIndex) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  v8::Handle<String> str = v8_str("42");
+  v8::Handle<v8::Uint32> index = str->ToArrayIndex();
+  CHECK(!index.IsEmpty());
+  CHECK_EQ(42.0, index->Uint32Value());
+  str = v8_str("42asdf");
+  index = str->ToArrayIndex();
+  CHECK(index.IsEmpty());
+  str = v8_str("-42");
+  index = str->ToArrayIndex();
+  CHECK(index.IsEmpty());
+  str = v8_str("4294967295");
+  index = str->ToArrayIndex();
+  CHECK(!index.IsEmpty());
+  CHECK_EQ(4294967295.0, index->Uint32Value());
+  v8::Handle<v8::Number> num = v8::Number::New(1);
+  index = num->ToArrayIndex();
+  CHECK(!index.IsEmpty());
+  CHECK_EQ(1.0, index->Uint32Value());
+  num = v8::Number::New(-1);
+  index = num->ToArrayIndex();
+  CHECK(index.IsEmpty());
+  v8::Handle<v8::Object> obj = v8::Object::New();
+  index = obj->ToArrayIndex();
+  CHECK(index.IsEmpty());
+}
+
+
+THREADED_TEST(ErrorConstruction) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  v8::Handle<String> foo = v8_str("foo");
+  v8::Handle<String> message = v8_str("message");
+  v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
+  CHECK(range_error->IsObject());
+  v8::Handle<v8::Object> range_obj(v8::Handle<v8::Object>::Cast(range_error));
+  CHECK(v8::Handle<v8::Object>::Cast(range_error)->Get(message)->Equals(foo));
+  v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
+  CHECK(reference_error->IsObject());
+  CHECK(
+      v8::Handle<v8::Object>::Cast(reference_error)->Get(message)->Equals(foo));
+  v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
+  CHECK(syntax_error->IsObject());
+  CHECK(v8::Handle<v8::Object>::Cast(syntax_error)->Get(message)->Equals(foo));
+  v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
+  CHECK(type_error->IsObject());
+  CHECK(v8::Handle<v8::Object>::Cast(type_error)->Get(message)->Equals(foo));
+  v8::Handle<Value> error = v8::Exception::Error(foo);
+  CHECK(error->IsObject());
+  CHECK(v8::Handle<v8::Object>::Cast(error)->Get(message)->Equals(foo));
+}
+
+
+static v8::Handle<Value> YGetter(Local<String> name, const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(10);
+}
+
+
+static void YSetter(Local<String> name,
+                    Local<Value> value,
+                    const AccessorInfo& info) {
+  if (info.This()->Has(name)) {
+    info.This()->Delete(name);
+  }
+  info.This()->Set(name, value);
+}
+
+
+THREADED_TEST(DeleteAccessor) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("y"), YGetter, YSetter);
+  LocalContext context;
+  v8::Handle<v8::Object> holder = obj->NewInstance();
+  context->Global()->Set(v8_str("holder"), holder);
+  v8::Handle<Value> result = CompileRun(
+      "holder.y = 11; holder.y = 12; holder.y");
+  CHECK_EQ(12, result->Uint32Value());
+}
+
+
+THREADED_TEST(TypeSwitch) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
+  v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
+  v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
+  v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
+  v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
+  LocalContext context;
+  v8::Handle<v8::Object> obj0 = v8::Object::New();
+  v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
+  v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
+  v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
+  for (int i = 0; i < 10; i++) {
+    CHECK_EQ(0, type_switch->match(obj0));
+    CHECK_EQ(1, type_switch->match(obj1));
+    CHECK_EQ(2, type_switch->match(obj2));
+    CHECK_EQ(3, type_switch->match(obj3));
+    CHECK_EQ(3, type_switch->match(obj3));
+    CHECK_EQ(2, type_switch->match(obj2));
+    CHECK_EQ(1, type_switch->match(obj1));
+    CHECK_EQ(0, type_switch->match(obj0));
+  }
+}
+
+
+// For use within the TestSecurityHandler() test.
+static bool g_security_callback_result = false;
+static bool NamedSecurityTestCallback(Local<v8::Object> global,
+                                      Local<Value> name,
+                                      v8::AccessType type,
+                                      Local<Value> data) {
+  // Always allow read access.
+  if (type == v8::ACCESS_GET)
+    return true;
+
+  // Sometimes allow other access.
+  return g_security_callback_result;
+}
+
+
+static bool IndexedSecurityTestCallback(Local<v8::Object> global,
+                                        uint32_t key,
+                                        v8::AccessType type,
+                                        Local<Value> data) {
+  // Always allow read access.
+  if (type == v8::ACCESS_GET)
+    return true;
+
+  // Sometimes allow other access.
+  return g_security_callback_result;
+}
+
+
+static int trouble_nesting = 0;
+static v8::Handle<Value> TroubleCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  trouble_nesting++;
+
+  // Call a JS function that throws an uncaught exception.
+  Local<v8::Object> arg_this = Context::GetCurrent()->Global();
+  Local<Value> trouble_callee = (trouble_nesting == 3) ?
+    arg_this->Get(v8_str("trouble_callee")) :
+    arg_this->Get(v8_str("trouble_caller"));
+  CHECK(trouble_callee->IsFunction());
+  return Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL);
+}
+
+
+static int report_count = 0;
+static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
+                                             v8::Handle<Value>) {
+  report_count++;
+}
+
+
+// Counts uncaught exceptions, but other tests running in parallel
+// also have uncaught exceptions.
+TEST(ApiUncaughtException) {
+  report_count = 0;
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
+
+  Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
+  v8::Local<v8::Object> global = env->Global();
+  global->Set(v8_str("trouble"), fun->GetFunction());
+
+  Script::Compile(v8_str("function trouble_callee() {"
+                         "  var x = null;"
+                         "  return x.foo;"
+                         "};"
+                         "function trouble_caller() {"
+                         "  trouble();"
+                         "};"))->Run();
+  Local<Value> trouble = global->Get(v8_str("trouble"));
+  CHECK(trouble->IsFunction());
+  Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
+  CHECK(trouble_callee->IsFunction());
+  Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
+  CHECK(trouble_caller->IsFunction());
+  Function::Cast(*trouble_caller)->Call(global, 0, NULL);
+  CHECK_EQ(1, report_count);
+  v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
+}
+
+
+TEST(CompilationErrorUsingTryCatchHandler) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::TryCatch try_catch;
+  Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
+  CHECK_NE(NULL, *try_catch.Exception());
+  CHECK(try_catch.HasCaught());
+}
+
+
+TEST(TryCatchFinallyUsingTryCatchHandler) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::TryCatch try_catch;
+  Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  Script::Compile(v8_str("(function() {"
+                         "try { throw ''; } finally { return; }"
+                         "})()"))->Run();
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("(function()"
+                         "  { try { throw ''; } finally { throw 0; }"
+                         "})()"))->Run();
+  CHECK(try_catch.HasCaught());
+}
+
+
+// SecurityHandler can't be run twice
+TEST(SecurityHandler) {
+  v8::HandleScope scope0;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
+                                           IndexedSecurityTestCallback);
+  // Create an environment
+  v8::Persistent<Context> context0 =
+    Context::New(NULL, global_template);
+  context0->Enter();
+
+  v8::Handle<v8::Object> global0 = context0->Global();
+  v8::Handle<Script> script0 = v8_compile("foo = 111");
+  script0->Run();
+  global0->Set(v8_str("0"), v8_num(999));
+  v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
+  CHECK_EQ(111, foo0->Int32Value());
+  v8::Handle<Value> z0 = global0->Get(v8_str("0"));
+  CHECK_EQ(999, z0->Int32Value());
+
+  // Create another environment, should fail security checks.
+  v8::HandleScope scope1;
+
+  v8::Persistent<Context> context1 =
+    Context::New(NULL, global_template);
+  context1->Enter();
+
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("othercontext"), global0);
+  // This set will fail the security check.
+  v8::Handle<Script> script1 =
+    v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
+  script1->Run();
+  // This read will pass the security check.
+  v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
+  CHECK_EQ(111, foo1->Int32Value());
+  // This read will pass the security check.
+  v8::Handle<Value> z1 = global0->Get(v8_str("0"));
+  CHECK_EQ(999, z1->Int32Value());
+
+  // Create another environment, should pass security checks.
+  { g_security_callback_result = true;  // allow security handler to pass.
+    v8::HandleScope scope2;
+    LocalContext context2;
+    v8::Handle<v8::Object> global2 = context2->Global();
+    global2->Set(v8_str("othercontext"), global0);
+    v8::Handle<Script> script2 =
+        v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
+    script2->Run();
+    v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
+    CHECK_EQ(333, foo2->Int32Value());
+    v8::Handle<Value> z2 = global0->Get(v8_str("0"));
+    CHECK_EQ(888, z2->Int32Value());
+  }
+
+  context1->Exit();
+  context1.Dispose();
+
+  context0->Exit();
+  context0.Dispose();
+}
+
+
+THREADED_TEST(SecurityChecks) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<Value> foo = v8_str("foo");
+  Local<Value> bar = v8_str("bar");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+
+  // Create a function in env1.
+  Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
+  Local<Value> spy = env1->Global()->Get(v8_str("spy"));
+  CHECK(spy->IsFunction());
+
+  // Create another function accessing global objects.
+  Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
+  Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
+  CHECK(spy2->IsFunction());
+
+  // Switch to env2 in the same domain and invoke spy on env2.
+  {
+    env2->SetSecurityToken(foo);
+    // Enter env2
+    Context::Scope scope_env2(env2);
+    Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
+    CHECK(result->IsFunction());
+  }
+
+  {
+    env2->SetSecurityToken(bar);
+    Context::Scope scope_env2(env2);
+
+    // Call cross_domain_call, it should throw an exception
+    v8::TryCatch try_catch;
+    Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
+    CHECK(try_catch.HasCaught());
+  }
+
+  env2.Dispose();
+}
+
+
+// Regression test case for issue 1183439.
+THREADED_TEST(SecurityChecksForPrototypeChain) {
+  v8::HandleScope scope;
+  LocalContext current;
+  v8::Persistent<Context> other = Context::New();
+
+  // Change context to be able to get to the Object function in the
+  // other context without hitting the security checks.
+  v8::Local<Value> other_object;
+  { Context::Scope scope(other);
+    other_object = other->Global()->Get(v8_str("Object"));
+    other->Global()->Set(v8_num(42), v8_num(87));
+  }
+
+  current->Global()->Set(v8_str("other"), other->Global());
+  CHECK(v8_compile("other")->Run()->Equals(other->Global()));
+
+  // Make sure the security check fails here and we get an undefined
+  // result instead of getting the Object function. Repeat in a loop
+  // to make sure to exercise the IC code.
+  v8::Local<Script> access_other0 = v8_compile("other.Object");
+  v8::Local<Script> access_other1 = v8_compile("other[42]");
+  for (int i = 0; i < 5; i++) {
+    CHECK(!access_other0->Run()->Equals(other_object));
+    CHECK(access_other0->Run()->IsUndefined());
+    CHECK(!access_other1->Run()->Equals(v8_num(87)));
+    CHECK(access_other1->Run()->IsUndefined());
+  }
+
+  // Create an object that has 'other' in its prototype chain and make
+  // sure we cannot access the Object function indirectly through
+  // that. Repeat in a loop to make sure to exercise the IC code.
+  v8_compile("function F() { };"
+             "F.prototype = other;"
+             "var f = new F();")->Run();
+  v8::Local<Script> access_f0 = v8_compile("f.Object");
+  v8::Local<Script> access_f1 = v8_compile("f[42]");
+  for (int j = 0; j < 5; j++) {
+    CHECK(!access_f0->Run()->Equals(other_object));
+    CHECK(access_f0->Run()->IsUndefined());
+    CHECK(!access_f1->Run()->Equals(v8_num(87)));
+    CHECK(access_f1->Run()->IsUndefined());
+  }
+
+  // Now it gets hairy: Set the prototype for the other global object
+  // to be the current global object. The prototype chain for 'f' now
+  // goes through 'other' but ends up in the current global object.
+  { Context::Scope scope(other);
+    other->Global()->Set(v8_str("__proto__"), current->Global());
+  }
+  // Set a named and an index property on the current global
+  // object. To force the lookup to go through the other global object,
+  // the properties must not exist in the other global object.
+  current->Global()->Set(v8_str("foo"), v8_num(100));
+  current->Global()->Set(v8_num(99), v8_num(101));
+  // Try to read the properties from f and make sure that the access
+  // gets stopped by the security checks on the other global object.
+  Local<Script> access_f2 = v8_compile("f.foo");
+  Local<Script> access_f3 = v8_compile("f[99]");
+  for (int k = 0; k < 5; k++) {
+    CHECK(!access_f2->Run()->Equals(v8_num(100)));
+    CHECK(access_f2->Run()->IsUndefined());
+    CHECK(!access_f3->Run()->Equals(v8_num(101)));
+    CHECK(access_f3->Run()->IsUndefined());
+  }
+  other.Dispose();
+}
+
+
+THREADED_TEST(CrossDomainDelete) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<Value> foo = v8_str("foo");
+  Local<Value> bar = v8_str("bar");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  env1->Global()->Set(v8_str("prop"), v8_num(3));
+  env2->Global()->Set(v8_str("env1"), env1->Global());
+
+  // Change env2 to a different domain and delete env1.prop.
+  env2->SetSecurityToken(bar);
+  {
+    Context::Scope scope_env2(env2);
+    Local<Value> result =
+        Script::Compile(v8_str("delete env1.prop"))->Run();
+    CHECK(result->IsFalse());
+  }
+
+  // Check that env1.prop still exists.
+  Local<Value> v = env1->Global()->Get(v8_str("prop"));
+  CHECK(v->IsNumber());
+  CHECK_EQ(3, v->Int32Value());
+
+  env2.Dispose();
+}
+
+
+THREADED_TEST(CrossDomainIsPropertyEnumerable) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<Value> foo = v8_str("foo");
+  Local<Value> bar = v8_str("bar");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  env1->Global()->Set(v8_str("prop"), v8_num(3));
+  env2->Global()->Set(v8_str("env1"), env1->Global());
+
+  // env1.prop is enumerable in env2.
+  Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
+  {
+    Context::Scope scope_env2(env2);
+    Local<Value> result = Script::Compile(test)->Run();
+    CHECK(result->IsTrue());
+  }
+
+  // Change env2 to a different domain and test again.
+  env2->SetSecurityToken(bar);
+  {
+    Context::Scope scope_env2(env2);
+    Local<Value> result = Script::Compile(test)->Run();
+    CHECK(result->IsFalse());
+  }
+
+  env2.Dispose();
+}
+
+
+THREADED_TEST(CrossDomainForIn) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<Value> foo = v8_str("foo");
+  Local<Value> bar = v8_str("bar");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  env1->Global()->Set(v8_str("prop"), v8_num(3));
+  env2->Global()->Set(v8_str("env1"), env1->Global());
+
+  // Change env2 to a different domain and set env1's global object
+  // as the __proto__ of an object in env2 and enumerate properties
+  // in for-in. It shouldn't enumerate properties on env1's global
+  // object.
+  env2->SetSecurityToken(bar);
+  {
+    Context::Scope scope_env2(env2);
+    Local<Value> result =
+        CompileRun("(function(){var obj = {'__proto__':env1};"
+                   "for (var p in obj)"
+                   "   if (p == 'prop') return false;"
+                   "return true;})()");
+    CHECK(result->IsTrue());
+  }
+  env2.Dispose();
+}
+
+
+TEST(ContextDetachGlobal) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<v8::Object> global1 = env1->Global();
+
+  Local<Value> foo = v8_str("foo");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  // Enter env2
+  env2->Enter();
+
+  // Create a function in env1
+  Local<v8::Object> global2 = env2->Global();
+  global2->Set(v8_str("prop"), v8::Integer::New(1));
+  CompileRun("function getProp() {return prop;}");
+
+  env1->Global()->Set(v8_str("getProp"),
+                      global2->Get(v8_str("getProp")));
+
+  // Detach env1's global, and reuse the global object of env1
+  env2->Exit();
+  env2->DetachGlobal();
+  // env2 has a new global object.
+  CHECK(!env2->Global()->Equals(global2));
+
+  v8::Persistent<Context> env3 =
+      Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
+  env3->SetSecurityToken(v8_str("bar"));
+  env3->Enter();
+
+  Local<v8::Object> global3 = env3->Global();
+  CHECK_EQ(global2, global3);
+  CHECK(global3->Get(v8_str("prop"))->IsUndefined());
+  CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
+  global3->Set(v8_str("prop"), v8::Integer::New(-1));
+  global3->Set(v8_str("prop2"), v8::Integer::New(2));
+  env3->Exit();
+
+  // Call getProp in env1, and it should return the value 1
+  {
+    Local<Value> get_prop = global1->Get(v8_str("getProp"));
+    CHECK(get_prop->IsFunction());
+    v8::TryCatch try_catch;
+    Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(1, r->Int32Value());
+  }
+
+  // Check that env3 is not accessible from env1
+  {
+    Local<Value> r = global3->Get(v8_str("prop2"));
+    CHECK(r->IsUndefined());
+  }
+
+  env2.Dispose();
+  env3.Dispose();
+}
+
+
+static bool NamedAccessBlocker(Local<v8::Object> global,
+                               Local<Value> name,
+                               v8::AccessType type,
+                               Local<Value> data) {
+  return Context::GetCurrent()->Global()->Equals(global);
+}
+
+
+static bool IndexedAccessBlocker(Local<v8::Object> global,
+                                 uint32_t key,
+                                 v8::AccessType type,
+                                 Local<Value> data) {
+  return Context::GetCurrent()->Global()->Equals(global);
+}
+
+
+static int g_echo_value = -1;
+static v8::Handle<Value> EchoGetter(Local<String> name,
+                                    const AccessorInfo& info) {
+  return v8_num(g_echo_value);
+}
+
+
+static void EchoSetter(Local<String> name,
+                       Local<Value> value,
+                       const AccessorInfo&) {
+  if (value->IsNumber())
+    g_echo_value = value->Int32Value();
+}
+
+
+static v8::Handle<Value> UnreachableGetter(Local<String> name,
+                                           const AccessorInfo& info) {
+  CHECK(false);  // This function should not be called..
+  return v8::Undefined();
+}
+
+
+static void UnreachableSetter(Local<String>, Local<Value>,
+                              const AccessorInfo&) {
+  CHECK(false);  // This function should nto be called.
+}
+
+
+THREADED_TEST(AccessControl) {
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+
+  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
+                                           IndexedAccessBlocker);
+
+  // Add an accessor accessible by cross-domain JS code.
+  global_template->SetAccessor(
+      v8_str("accessible_prop"),
+      EchoGetter, EchoSetter,
+      v8::Handle<Value>(),
+      v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
+
+  // Add an accessor that is not accessible by cross-domain JS code.
+  global_template->SetAccessor(v8_str("blocked_prop"),
+                               UnreachableGetter, UnreachableSetter,
+                               v8::Handle<Value>(),
+                               v8::DEFAULT);
+
+  // Create an environment
+  v8::Persistent<Context> context0 = Context::New(NULL, global_template);
+  context0->Enter();
+
+  v8::Handle<v8::Object> global0 = context0->Global();
+
+  v8::HandleScope scope1;
+
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("other"), global0);
+
+  v8::Handle<Value> value;
+
+  // Access blocked property
+  value = v8_compile("other.blocked_prop = 1")->Run();
+  value = v8_compile("other.blocked_prop")->Run();
+  CHECK(value->IsUndefined());
+
+  value = v8_compile("propertyIsEnumerable.call(other, 'blocked_prop')")->Run();
+  CHECK(value->IsFalse());
+
+  // Access accessible property
+  value = v8_compile("other.accessible_prop = 3")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+
+  value = v8_compile("other.accessible_prop")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+
+  value =
+    v8_compile("propertyIsEnumerable.call(other, 'accessible_prop')")->Run();
+  CHECK(value->IsTrue());
+
+  // Enumeration doesn't enumerate accessors from inaccessible objects in
+  // the prototype chain even if the accessors are in themselves accessible.
+  Local<Value> result =
+      CompileRun("(function(){var obj = {'__proto__':other};"
+                 "for (var p in obj)"
+                 "   if (p == 'accessible_prop' || p == 'blocked_prop') {"
+                 "     return false;"
+                 "   }"
+                 "return true;})()");
+  CHECK(result->IsTrue());
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+static v8::Handle<Value> ConstTenGetter(Local<String> name,
+                                        const AccessorInfo& info) {
+  return v8_num(10);
+}
+
+
+THREADED_TEST(CrossDomainAccessors) {
+  v8::HandleScope handle_scope;
+
+  v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
+
+  v8::Handle<v8::ObjectTemplate> global_template =
+      func_template->InstanceTemplate();
+
+  v8::Handle<v8::ObjectTemplate> proto_template =
+      func_template->PrototypeTemplate();
+
+  // Add an accessor to proto that's accessible by cross-domain JS code.
+  proto_template->SetAccessor(v8_str("accessible"),
+                              ConstTenGetter, 0,
+                              v8::Handle<Value>(),
+                              v8::ALL_CAN_READ);
+
+  // Add an accessor that is not accessible by cross-domain JS code.
+  global_template->SetAccessor(v8_str("unreachable"),
+                               UnreachableGetter, 0,
+                               v8::Handle<Value>(),
+                               v8::DEFAULT);
+
+  v8::Persistent<Context> context0 = Context::New(NULL, global_template);
+  context0->Enter();
+
+  Local<v8::Object> global = context0->Global();
+  // Add a normal property that shadows 'accessible'
+  global->Set(v8_str("accessible"), v8_num(11));
+
+  // Enter a new context.
+  v8::HandleScope scope1;
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("other"), global);
+
+  // Should return 10, instead of 11
+  v8::Handle<Value> value = v8_compile("other.accessible")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(10, value->Int32Value());
+
+  value = v8_compile("other.unreachable")->Run();
+  CHECK(value->IsUndefined());
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+static int named_access_count = 0;
+static int indexed_access_count = 0;
+
+static bool NamedAccessCounter(Local<v8::Object> global,
+                               Local<Value> name,
+                               v8::AccessType type,
+                               Local<Value> data) {
+  named_access_count++;
+  return true;
+}
+
+
+static bool IndexedAccessCounter(Local<v8::Object> global,
+                                 uint32_t key,
+                                 v8::AccessType type,
+                                 Local<Value> data) {
+  indexed_access_count++;
+  return true;
+}
+
+
+// This one is too easily disturbed by other tests.
+TEST(AccessControlIC) {
+  named_access_count = 0;
+  indexed_access_count = 0;
+
+  v8::HandleScope handle_scope;
+
+  // Create an environment.
+  v8::Persistent<Context> context0 = Context::New();
+  context0->Enter();
+
+  // Create an object that requires access-check functions to be
+  // called for cross-domain access.
+  v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
+  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
+                                           IndexedAccessCounter);
+  Local<v8::Object> object = object_template->NewInstance();
+
+  v8::HandleScope scope1;
+
+  // Create another environment.
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  // Make easy access to the object from the other environment.
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("obj"), object);
+
+  v8::Handle<Value> value;
+
+  // Check that the named access-control function is called every time.
+  CompileRun("function testProp(obj) {"
+             "  for (var i = 0; i < 10; i++) obj.prop = 1;"
+             "  for (var j = 0; j < 10; j++) obj.prop;"
+             "  return obj.prop"
+             "}");
+  value = CompileRun("testProp(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(21, named_access_count);
+
+  // Check that the named access-control function is called every time.
+  CompileRun("var p = 'prop';"
+             "function testKeyed(obj) {"
+             "  for (var i = 0; i < 10; i++) obj[p] = 1;"
+             "  for (var j = 0; j < 10; j++) obj[p];"
+             "  return obj[p];"
+             "}");
+  // Use obj which requires access checks.  No inline caching is used
+  // in that case.
+  value = CompileRun("testKeyed(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(42, named_access_count);
+  // Force the inline caches into generic state and try again.
+  CompileRun("testKeyed({ a: 0 })");
+  CompileRun("testKeyed({ b: 0 })");
+  value = CompileRun("testKeyed(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(63, named_access_count);
+
+  // Check that the indexed access-control function is called every time.
+  CompileRun("function testIndexed(obj) {"
+             "  for (var i = 0; i < 10; i++) obj[0] = 1;"
+             "  for (var j = 0; j < 10; j++) obj[0];"
+             "  return obj[0]"
+             "}");
+  value = CompileRun("testIndexed(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(21, indexed_access_count);
+  // Force the inline caches into generic state.
+  CompileRun("testIndexed(new Array(1))");
+  // Test that the indexed access check is called.
+  value = CompileRun("testIndexed(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(42, indexed_access_count);
+
+  // Check that the named access check is called when invoking
+  // functions on an object that requires access checks.
+  CompileRun("obj.f = function() {}");
+  CompileRun("function testCallNormal(obj) {"
+             "  for (var i = 0; i < 10; i++) obj.f();"
+             "}");
+  CompileRun("testCallNormal(obj)");
+  CHECK_EQ(74, named_access_count);
+
+  // Force obj into slow case.
+  value = CompileRun("delete obj.prop");
+  CHECK(value->BooleanValue());
+  // Force inline caches into dictionary probing mode.
+  CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
+  // Test that the named access check is called.
+  value = CompileRun("testProp(obj);");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(96, named_access_count);
+
+  // Force the call inline cache into dictionary probing mode.
+  CompileRun("o.f = function() {}; testCallNormal(o)");
+  // Test that the named access check is still called for each
+  // invocation of the function.
+  value = CompileRun("testCallNormal(obj)");
+  CHECK_EQ(106, named_access_count);
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+static bool NamedAccessFlatten(Local<v8::Object> global,
+                               Local<Value> name,
+                               v8::AccessType type,
+                               Local<Value> data) {
+  char buf[100];
+  int len;
+
+  CHECK(name->IsString());
+
+  memset(buf, 0x1, sizeof(buf));
+  len = Local<String>::Cast(name)->WriteAscii(buf);
+  CHECK_EQ(4, len);
+
+  uint16_t buf2[100];
+
+  memset(buf, 0x1, sizeof(buf));
+  len = Local<String>::Cast(name)->Write(buf2);
+  CHECK_EQ(4, len);
+
+  return true;
+}
+
+
+static bool IndexedAccessFlatten(Local<v8::Object> global,
+                                 uint32_t key,
+                                 v8::AccessType type,
+                                 Local<Value> data) {
+  return true;
+}
+
+
+// Regression test.  In access checks, operations that may cause
+// garbage collection are not allowed.  It used to be the case that
+// using the Write operation on a string could cause a garbage
+// collection due to flattening of the string.  This is no longer the
+// case.
+THREADED_TEST(AccessControlFlatten) {
+  named_access_count = 0;
+  indexed_access_count = 0;
+
+  v8::HandleScope handle_scope;
+
+  // Create an environment.
+  v8::Persistent<Context> context0 = Context::New();
+  context0->Enter();
+
+  // Create an object that requires access-check functions to be
+  // called for cross-domain access.
+  v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
+  object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
+                                           IndexedAccessFlatten);
+  Local<v8::Object> object = object_template->NewInstance();
+
+  v8::HandleScope scope1;
+
+  // Create another environment.
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  // Make easy access to the object from the other environment.
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("obj"), object);
+
+  v8::Handle<Value> value;
+
+  value = v8_compile("var p = 'as' + 'df';")->Run();
+  value = v8_compile("obj[p];")->Run();
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+static v8::Handle<Value> AccessControlNamedGetter(
+    Local<String>, const AccessorInfo&) {
+  return v8::Integer::New(42);
+}
+
+
+static v8::Handle<Value> AccessControlNamedSetter(
+    Local<String>, Local<Value> value, const AccessorInfo&) {
+  return value;
+}
+
+
+static v8::Handle<Value> AccessControlIndexedGetter(
+      uint32_t index,
+      const AccessorInfo& info) {
+  return v8_num(42);
+}
+
+
+static v8::Handle<Value> AccessControlIndexedSetter(
+    uint32_t, Local<Value> value, const AccessorInfo&) {
+  return value;
+}
+
+
+THREADED_TEST(AccessControlInterceptorIC) {
+  named_access_count = 0;
+  indexed_access_count = 0;
+
+  v8::HandleScope handle_scope;
+
+  // Create an environment.
+  v8::Persistent<Context> context0 = Context::New();
+  context0->Enter();
+
+  // Create an object that requires access-check functions to be
+  // called for cross-domain access.  The object also has interceptors
+  // interceptor.
+  v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
+  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
+                                           IndexedAccessCounter);
+  object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
+                                           AccessControlNamedSetter);
+  object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
+                                             AccessControlIndexedSetter);
+  Local<v8::Object> object = object_template->NewInstance();
+
+  v8::HandleScope scope1;
+
+  // Create another environment.
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  // Make easy access to the object from the other environment.
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("obj"), object);
+
+  v8::Handle<Value> value;
+
+  // Check that the named access-control function is called every time
+  // eventhough there is an interceptor on the object.
+  value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
+  value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
+                     "obj.x")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(42, value->Int32Value());
+  CHECK_EQ(21, named_access_count);
+
+  value = v8_compile("var p = 'x';")->Run();
+  value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
+  value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
+                     "obj[p]")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(42, value->Int32Value());
+  CHECK_EQ(42, named_access_count);
+
+  // Check that the indexed access-control function is called every
+  // time eventhough there is an interceptor on the object.
+  value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
+  value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
+                     "obj[0]")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(42, value->Int32Value());
+  CHECK_EQ(21, indexed_access_count);
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+THREADED_TEST(Version) {
+  v8::V8::GetVersion();
+}
+
+
+static v8::Handle<Value> InstanceFunctionCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(12);
+}
+
+
+THREADED_TEST(InstanceProperties) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+
+  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+  Local<ObjectTemplate> instance = t->InstanceTemplate();
+
+  instance->Set(v8_str("x"), v8_num(42));
+  instance->Set(v8_str("f"),
+                v8::FunctionTemplate::New(InstanceFunctionCallback));
+
+  Local<Value> o = t->GetFunction()->NewInstance();
+
+  context->Global()->Set(v8_str("i"), o);
+  Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
+  CHECK_EQ(42, value->Int32Value());
+
+  value = Script::Compile(v8_str("i.f()"))->Run();
+  CHECK_EQ(12, value->Int32Value());
+}
+
+
+static v8::Handle<Value>
+GlobalObjectInstancePropertiesGet(Local<String> key, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(GlobalObjectInstanceProperties) {
+  v8::HandleScope handle_scope;
+
+  Local<Value> global_object;
+
+  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+  t->InstanceTemplate()->SetNamedPropertyHandler(
+      GlobalObjectInstancePropertiesGet);
+  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
+  instance_template->Set(v8_str("x"), v8_num(42));
+  instance_template->Set(v8_str("f"),
+                         v8::FunctionTemplate::New(InstanceFunctionCallback));
+
+  {
+    LocalContext env(NULL, instance_template);
+    // Hold on to the global object so it can be used again in another
+    // environment initialization.
+    global_object = env->Global();
+
+    Local<Value> value = Script::Compile(v8_str("x"))->Run();
+    CHECK_EQ(42, value->Int32Value());
+    value = Script::Compile(v8_str("f()"))->Run();
+    CHECK_EQ(12, value->Int32Value());
+  }
+
+  {
+    // Create new environment reusing the global object.
+    LocalContext env(NULL, instance_template, global_object);
+    Local<Value> value = Script::Compile(v8_str("x"))->Run();
+    CHECK_EQ(42, value->Int32Value());
+    value = Script::Compile(v8_str("f()"))->Run();
+    CHECK_EQ(12, value->Int32Value());
+  }
+}
+
+
+static v8::Handle<Value> ShadowFunctionCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(42);
+}
+
+
+static int shadow_y;
+static int shadow_y_setter_call_count;
+static int shadow_y_getter_call_count;
+
+
+static void ShadowYSetter(Local<String>, Local<Value>, const AccessorInfo&) {
+  shadow_y_setter_call_count++;
+  shadow_y = 42;
+}
+
+
+static v8::Handle<Value> ShadowYGetter(Local<String> name,
+                                       const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  shadow_y_getter_call_count++;
+  return v8_num(shadow_y);
+}
+
+
+static v8::Handle<Value> ShadowIndexedGet(uint32_t index,
+                                          const AccessorInfo& info) {
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> ShadowNamedGet(Local<String> key,
+                                        const AccessorInfo&) {
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(ShadowObject) {
+  shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
+  v8::HandleScope handle_scope;
+
+  Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  LocalContext context(NULL, global_template);
+
+  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+  t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
+  t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
+  Local<ObjectTemplate> proto = t->PrototypeTemplate();
+  Local<ObjectTemplate> instance = t->InstanceTemplate();
+
+  // Only allow calls of f on instances of t.
+  Local<v8::Signature> signature = v8::Signature::New(t);
+  proto->Set(v8_str("f"),
+             v8::FunctionTemplate::New(ShadowFunctionCallback,
+                                       Local<Value>(),
+                                       signature));
+  proto->Set(v8_str("x"), v8_num(12));
+
+  instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
+
+  Local<Value> o = t->GetFunction()->NewInstance();
+  context->Global()->Set(v8_str("__proto__"), o);
+
+  Local<Value> value =
+      Script::Compile(v8_str("propertyIsEnumerable(0)"))->Run();
+  CHECK(value->IsBoolean());
+  CHECK(!value->BooleanValue());
+
+  value = Script::Compile(v8_str("x"))->Run();
+  CHECK_EQ(12, value->Int32Value());
+
+  value = Script::Compile(v8_str("f()"))->Run();
+  CHECK_EQ(42, value->Int32Value());
+
+  Script::Compile(v8_str("y = 42"))->Run();
+  CHECK_EQ(1, shadow_y_setter_call_count);
+  value = Script::Compile(v8_str("y"))->Run();
+  CHECK_EQ(1, shadow_y_getter_call_count);
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+THREADED_TEST(HiddenPrototype) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+
+  Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
+  t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
+  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
+  t1->SetHiddenPrototype(true);
+  t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
+  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
+  t2->SetHiddenPrototype(true);
+  t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
+  Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
+  t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
+
+  Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
+  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
+  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
+  Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
+
+  // Setting the prototype on an object skips hidden prototypes.
+  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+  o0->Set(v8_str("__proto__"), o1);
+  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
+  o0->Set(v8_str("__proto__"), o2);
+  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
+  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
+  o0->Set(v8_str("__proto__"), o3);
+  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
+  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
+  CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
+
+  // Getting the prototype of o0 should get the first visible one
+  // which is o3.  Therefore, z should not be defined on the prototype
+  // object.
+  Local<Value> proto = o0->Get(v8_str("__proto__"));
+  CHECK(proto->IsObject());
+  CHECK(Local<v8::Object>::Cast(proto)->Get(v8_str("z"))->IsUndefined());
+}
+
+
+THREADED_TEST(GetterSetterExceptions) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+  CompileRun(
+    "function Foo() { };"
+    "function Throw() { throw 5; };"
+    "var x = { };"
+    "x.__defineSetter__('set', Throw);"
+    "x.__defineGetter__('get', Throw);");
+  Local<v8::Object> x =
+      Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
+  v8::TryCatch try_catch;
+  x->Set(v8_str("set"), v8::Integer::New(8));
+  x->Get(v8_str("get"));
+  x->Set(v8_str("set"), v8::Integer::New(8));
+  x->Get(v8_str("get"));
+  x->Set(v8_str("set"), v8::Integer::New(8));
+  x->Get(v8_str("get"));
+  x->Set(v8_str("set"), v8::Integer::New(8));
+  x->Get(v8_str("get"));
+}
+
+
+THREADED_TEST(Constructor) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->SetClassName(v8_str("Fun"));
+  Local<Function> cons = templ->GetFunction();
+  context->Global()->Set(v8_str("Fun"), cons);
+  Local<v8::Object> inst = cons->NewInstance();
+  i::Handle<i::JSObject> obj = v8::Utils::OpenHandle(*inst);
+  Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
+  CHECK(value->BooleanValue());
+}
+
+THREADED_TEST(FunctionDescriptorException) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->SetClassName(v8_str("Fun"));
+  Local<Function> cons = templ->GetFunction();
+  context->Global()->Set(v8_str("Fun"), cons);
+  Local<Value> value = CompileRun(
+    "function test() {"
+    "  try {"
+    "    (new Fun()).blah()"
+    "  } catch (e) {"
+    "    var str = String(e);"
+    "    if (str.indexOf('TypeError') == -1) return 1;"
+    "    if (str.indexOf('[object Fun]') != -1) return 2;"
+    "    if (str.indexOf('#<a Fun>') == -1) return 3;"
+    "    return 0;"
+    "  }"
+    "  return 4;"
+    "}"
+    "test();");
+  CHECK_EQ(0, value->Int32Value());
+}
+
+
+THREADED_TEST(EvalAliasedDynamic) {
+  v8::HandleScope scope;
+  LocalContext current;
+
+  // Tests where aliased eval can only be resolved dynamically.
+  Local<Script> script =
+      Script::Compile(v8_str("function f(x) { "
+                             "  var foo = 2;"
+                             "  with (x) { return eval('foo'); }"
+                             "}"
+                             "foo = 0;"
+                             "result1 = f(new Object());"
+                             "result2 = f(this);"
+                             "var x = new Object();"
+                             "x.eval = function(x) { return 1; };"
+                             "result3 = f(x);"));
+  script->Run();
+  CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
+  CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
+  CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
+
+  v8::TryCatch try_catch;
+  script =
+    Script::Compile(v8_str("function f(x) { "
+                           "  var bar = 2;"
+                           "  with (x) { return eval('bar'); }"
+                           "}"
+                           "f(this)"));
+  script->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+}
+
+
+THREADED_TEST(CrossEval) {
+  v8::HandleScope scope;
+  LocalContext other;
+  LocalContext current;
+
+  Local<String> token = v8_str("<security token>");
+  other->SetSecurityToken(token);
+  current->SetSecurityToken(token);
+
+  // Setup reference from current to other.
+  current->Global()->Set(v8_str("other"), other->Global());
+
+  // Check that new variables are introduced in other context.
+  Local<Script> script =
+      Script::Compile(v8_str("other.eval('var foo = 1234')"));
+  script->Run();
+  Local<Value> foo = other->Global()->Get(v8_str("foo"));
+  CHECK_EQ(1234, foo->Int32Value());
+  CHECK(!current->Global()->Has(v8_str("foo")));
+
+  // Check that writing to non-existing properties introduces them in
+  // the other context.
+  script =
+      Script::Compile(v8_str("other.eval('na = 1234')"));
+  script->Run();
+  CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
+  CHECK(!current->Global()->Has(v8_str("na")));
+
+  // Check that global variables in current context are not visible in other
+  // context.
+  v8::TryCatch try_catch;
+  script =
+      Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
+  Local<Value> result = script->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Check that local variables in current context are not visible in other
+  // context.
+  script =
+      Script::Compile(v8_str("(function() { "
+                             "  var baz = 87;"
+                             "  return other.eval('baz');"
+                             "})();"));
+  result = script->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Check that global variables in the other environment are visible
+  // when evaluting code.
+  other->Global()->Set(v8_str("bis"), v8_num(1234));
+  script = Script::Compile(v8_str("other.eval('bis')"));
+  CHECK_EQ(1234, script->Run()->Int32Value());
+  CHECK(!try_catch.HasCaught());
+
+  // Check that the 'this' pointer points to the global object evaluating
+  // code.
+  other->Global()->Set(v8_str("t"), other->Global());
+  script = Script::Compile(v8_str("other.eval('this == t')"));
+  result = script->Run();
+  CHECK(result->IsTrue());
+  CHECK(!try_catch.HasCaught());
+
+  // Check that variables introduced in with-statement are not visible in
+  // other context.
+  script =
+      Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
+  result = script->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Check that you cannot use 'eval.call' with another object than the
+  // current global object.
+  script =
+      Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
+  result = script->Run();
+  CHECK(try_catch.HasCaught());
+}
+
+
+// Test that calling eval in a context which has been detached from
+// its global throws an exception.  This behavior is consistent with
+// other JavaScript implementations.
+THREADED_TEST(EvalInDetachedGlobal) {
+  v8::HandleScope scope;
+
+  v8::Persistent<Context> context0 = Context::New();
+  v8::Persistent<Context> context1 = Context::New();
+
+  // Setup function in context0 that uses eval from context0.
+  context0->Enter();
+  v8::Handle<v8::Value> fun =
+      CompileRun("var x = 42;"
+                 "(function() {"
+                 "  var e = eval;"
+                 "  return function(s) { return e(s); }"
+                 "})()");
+  context0->Exit();
+
+  // Put the function into context1 and call it before and after
+  // detaching the global.  Before detaching, the call succeeds and
+  // after detaching and exception is thrown.
+  context1->Enter();
+  context1->Global()->Set(v8_str("fun"), fun);
+  v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
+  CHECK_EQ(42, x_value->Int32Value());
+  context0->DetachGlobal();
+  v8::TryCatch catcher;
+  x_value = CompileRun("fun('x')");
+  CHECK(x_value.IsEmpty());
+  CHECK(catcher.HasCaught());
+  context1->Exit();
+
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+THREADED_TEST(CrossLazyLoad) {
+  v8::HandleScope scope;
+  LocalContext other;
+  LocalContext current;
+
+  Local<String> token = v8_str("<security token>");
+  other->SetSecurityToken(token);
+  current->SetSecurityToken(token);
+
+  // Setup reference from current to other.
+  current->Global()->Set(v8_str("other"), other->Global());
+
+  // Trigger lazy loading in other context.
+  Local<Script> script =
+      Script::Compile(v8_str("other.eval('new Date(42)')"));
+  Local<Value> value = script->Run();
+  CHECK_EQ(42.0, value->NumberValue());
+}
+
+
+static v8::Handle<Value> call_as_function(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  if (args.IsConstructCall()) {
+    if (args[0]->IsInt32()) {
+       return v8_num(-args[0]->Int32Value());
+    }
+  }
+
+  return args[0];
+}
+
+
+// Test that a call handler can be set for objects which will allow
+// non-function objects created through the API to be called as
+// functions.
+THREADED_TEST(CallAsFunction) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
+  instance_template->SetCallAsFunctionHandler(call_as_function);
+  Local<v8::Object> instance = t->GetFunction()->NewInstance();
+  context->Global()->Set(v8_str("obj"), instance);
+  v8::TryCatch try_catch;
+  Local<Value> value;
+  CHECK(!try_catch.HasCaught());
+
+  value = CompileRun("obj(42)");
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(42, value->Int32Value());
+
+  value = CompileRun("(function(o){return o(49)})(obj)");
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(49, value->Int32Value());
+
+  // test special case of call as function
+  value = CompileRun("[obj]['0'](45)");
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(45, value->Int32Value());
+
+  value = CompileRun("obj.call = Function.prototype.call;"
+                     "obj.call(null, 87)");
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(87, value->Int32Value());
+
+  // Regression tests for bug #1116356: Calling call through call/apply
+  // must work for non-function receivers.
+  const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
+  value = CompileRun(apply_99);
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(99, value->Int32Value());
+
+  const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
+  value = CompileRun(call_17);
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(17, value->Int32Value());
+
+  // Check that the call-as-function handler can be called through
+  // new.  Currently, there is no way to check in the call-as-function
+  // handler if it has been called through new or not.
+  value = CompileRun("new obj(43)");
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(-43, value->Int32Value());
+}
+
+
+static int CountHandles() {
+  return v8::HandleScope::NumberOfHandles();
+}
+
+
+static int Recurse(int depth, int iterations) {
+  v8::HandleScope scope;
+  if (depth == 0) return CountHandles();
+  for (int i = 0; i < iterations; i++) {
+    Local<v8::Number> n = v8::Integer::New(42);
+  }
+  return Recurse(depth - 1, iterations);
+}
+
+
+THREADED_TEST(HandleIteration) {
+  static const int kIterations = 500;
+  static const int kNesting = 200;
+  CHECK_EQ(0, CountHandles());
+  {
+    v8::HandleScope scope1;
+    CHECK_EQ(0, CountHandles());
+    for (int i = 0; i < kIterations; i++) {
+      Local<v8::Number> n = v8::Integer::New(42);
+      CHECK_EQ(i + 1, CountHandles());
+    }
+
+    CHECK_EQ(kIterations, CountHandles());
+    {
+      v8::HandleScope scope2;
+      for (int j = 0; j < kIterations; j++) {
+        Local<v8::Number> n = v8::Integer::New(42);
+        CHECK_EQ(j + 1 + kIterations, CountHandles());
+      }
+    }
+    CHECK_EQ(kIterations, CountHandles());
+  }
+  CHECK_EQ(0, CountHandles());
+  CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
+}
+
+
+static v8::Handle<Value> InterceptorHasOwnPropertyGetter(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(InterceptorHasOwnProperty) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
+  instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
+  Local<Function> function = fun_templ->GetFunction();
+  context->Global()->Set(v8_str("constructor"), function);
+  v8::Handle<Value> value = CompileRun(
+      "var o = new constructor();"
+      "o.hasOwnProperty('ostehaps');");
+  CHECK_EQ(false, value->BooleanValue());
+  value = CompileRun(
+      "o.ostehaps = 42;"
+      "o.hasOwnProperty('ostehaps');");
+  CHECK_EQ(true, value->BooleanValue());
+  value = CompileRun(
+      "var p = new constructor();"
+      "p.hasOwnProperty('ostehaps');");
+  CHECK_EQ(false, value->BooleanValue());
+}
+
+
+static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  i::Heap::CollectAllGarbage(false);
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
+  instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
+  Local<Function> function = fun_templ->GetFunction();
+  context->Global()->Set(v8_str("constructor"), function);
+  // Let's first make some stuff so we can be sure to get a good GC.
+  CompileRun(
+      "function makestr(size) {"
+      "  switch (size) {"
+      "    case 1: return 'f';"
+      "    case 2: return 'fo';"
+      "    case 3: return 'foo';"
+      "  }"
+      "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
+      "}"
+      "var x = makestr(12345);"
+      "x = makestr(31415);"
+      "x = makestr(23456);");
+  v8::Handle<Value> value = CompileRun(
+      "var o = new constructor();"
+      "o.__proto__ = new String(x);"
+      "o.hasOwnProperty('ostehaps');");
+  CHECK_EQ(false, value->BooleanValue());
+}
+
+
+typedef v8::Handle<Value> (*NamedPropertyGetter)(Local<String> property,
+                                                 const AccessorInfo& info);
+
+
+static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
+                                   const char* source,
+                                   int expected) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(getter);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(source);
+  CHECK_EQ(expected, value->Int32Value());
+}
+
+
+static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
+                                                 const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(v8_str("x")->Equals(name));
+  return v8::Integer::New(42);
+}
+
+
+// This test should hit the load IC for the interceptor case.
+THREADED_TEST(InterceptorLoadIC) {
+  CheckInterceptorLoadIC(InterceptorLoadICGetter,
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.x;"
+    "}",
+    42);
+}
+
+
+// Below go several tests which verify that JITing for various
+// configurations of interceptor and explicit fields works fine
+// (those cases are special cased to get better performance).
+
+static v8::Handle<Value> InterceptorLoadXICGetter(Local<String> name,
+                                                 const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8_str("x")->Equals(name)
+      ? v8::Integer::New(42) : v8::Handle<v8::Value>();
+}
+
+
+THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
+  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
+    "var result = 0;"
+    "o.y = 239;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.y;"
+    "}",
+    239);
+}
+
+
+THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
+  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
+    "var result = 0;"
+    "o.__proto__ = { 'y': 239 };"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.y + o.x;"
+    "}",
+    239 + 42);
+}
+
+
+THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
+  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
+    "var result = 0;"
+    "o.__proto__.y = 239;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.y + o.x;"
+    "}",
+    239 + 42);
+}
+
+
+THREADED_TEST(InterceptorLoadICUndefined) {
+  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = (o.y == undefined) ? 239 : 42;"
+    "}",
+    239);
+}
+
+
+THREADED_TEST(InterceptorLoadICWithOverride) {
+  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
+    "fst = new Object();  fst.__proto__ = o;"
+    "snd = new Object();  snd.__proto__ = fst;"
+    "var result1 = 0;"
+    "for (var i = 0; i < 1000;  i++) {"
+    "  result1 = snd.x;"
+    "}"
+    "fst.x = 239;"
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = snd.x;"
+    "}"
+    "result + result1",
+    239 + 42);
+}
+
+
+// Test the case when we stored field into
+// a stub, but interceptor produced value on its own.
+THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
+  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
+    "proto = new Object();"
+    "o.__proto__ = proto;"
+    "proto.x = 239;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  o.x;"
+    // Now it should be ICed and keep a reference to x defined on proto
+    "}"
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result += o.x;"
+    "}"
+    "result;",
+    42 * 1000);
+}
+
+
+// Test the case when we stored field into
+// a stub, but it got invalidated later on.
+THREADED_TEST(InterceptorLoadICInvalidatedField) {
+  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
+    "proto1 = new Object();"
+    "proto2 = new Object();"
+    "o.__proto__ = proto1;"
+    "proto1.__proto__ = proto2;"
+    "proto2.y = 239;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  o.y;"
+    // Now it should be ICed and keep a reference to y defined on proto2
+    "}"
+    "proto1.y = 42;"
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result += o.y;"
+    "}"
+    "result;",
+    42 * 1000);
+}
+
+
+// Test the case when we stored field into
+// a stub, but it got invalidated later on due to override on
+// global object which is between interceptor and fields' holders.
+THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
+  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
+    "o.__proto__ = this;"  // set a global to be a proto of o.
+    "this.__proto__.y = 239;"
+    "for (var i = 0; i < 10; i++) {"
+    "  if (o.y != 239) throw 'oops: ' + o.y;"
+    // Now it should be ICed and keep a reference to y defined on field_holder.
+    "}"
+    "this.y = 42;"  // Assign on a global.
+    "var result = 0;"
+    "for (var i = 0; i < 10; i++) {"
+    "  result += o.y;"
+    "}"
+    "result;",
+    42 * 10);
+}
+
+
+static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(239);
+}
+
+
+static void SetOnThis(Local<String> name,
+                      Local<Value> value,
+                      const AccessorInfo& info) {
+  info.This()->ForceSet(name, value);
+}
+
+
+THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+  templ->SetAccessor(v8_str("y"), Return239);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+      "var result = 0;"
+      "for (var i = 0; i < 7; i++) {"
+      "  result = o.y;"
+      "}");
+  CHECK_EQ(239, value->Int32Value());
+}
+
+
+THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
+  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
+  templ_p->SetAccessor(v8_str("y"), Return239);
+
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
+  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
+
+  v8::Handle<Value> value = CompileRun(
+      "o.__proto__ = p;"
+      "var result = 0;"
+      "for (var i = 0; i < 7; i++) {"
+      "  result = o.x + o.y;"
+      "}");
+  CHECK_EQ(239 + 42, value->Int32Value());
+}
+
+
+THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+  templ->SetAccessor(v8_str("y"), Return239);
+
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+
+  v8::Handle<Value> value = CompileRun(
+    "fst = new Object();  fst.__proto__ = o;"
+    "snd = new Object();  snd.__proto__ = fst;"
+    "var result1 = 0;"
+    "for (var i = 0; i < 7;  i++) {"
+    "  result1 = snd.x;"
+    "}"
+    "fst.x = 239;"
+    "var result = 0;"
+    "for (var i = 0; i < 7; i++) {"
+    "  result = snd.x;"
+    "}"
+    "result + result1");
+  CHECK_EQ(239 + 42, value->Int32Value());
+}
+
+
+// Test the case when we stored callback into
+// a stub, but interceptor produced value on its own.
+THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
+  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
+  templ_p->SetAccessor(v8_str("y"), Return239);
+
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
+  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
+
+  v8::Handle<Value> value = CompileRun(
+    "o.__proto__ = p;"
+    "for (var i = 0; i < 7; i++) {"
+    "  o.x;"
+    // Now it should be ICed and keep a reference to x defined on p
+    "}"
+    "var result = 0;"
+    "for (var i = 0; i < 7; i++) {"
+    "  result += o.x;"
+    "}"
+    "result");
+  CHECK_EQ(42 * 7, value->Int32Value());
+}
+
+
+// Test the case when we stored callback into
+// a stub, but it got invalidated later on.
+THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
+  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
+  templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
+
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
+  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
+
+  v8::Handle<Value> value = CompileRun(
+    "inbetween = new Object();"
+    "o.__proto__ = inbetween;"
+    "inbetween.__proto__ = p;"
+    "for (var i = 0; i < 10; i++) {"
+    "  o.y;"
+    // Now it should be ICed and keep a reference to y defined on p
+    "}"
+    "inbetween.y = 42;"
+    "var result = 0;"
+    "for (var i = 0; i < 10; i++) {"
+    "  result += o.y;"
+    "}"
+    "result");
+  CHECK_EQ(42 * 10, value->Int32Value());
+}
+
+
+// Test the case when we stored callback into
+// a stub, but it got invalidated later on due to override on
+// global object which is between interceptor and callbacks' holders.
+THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
+  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
+  templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
+
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
+  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
+
+  v8::Handle<Value> value = CompileRun(
+    "o.__proto__ = this;"
+    "this.__proto__ = p;"
+    "for (var i = 0; i < 10; i++) {"
+    "  if (o.y != 239) throw 'oops: ' + o.y;"
+    // Now it should be ICed and keep a reference to y defined on p
+    "}"
+    "this.y = 42;"
+    "var result = 0;"
+    "for (var i = 0; i < 10; i++) {"
+    "  result += o.y;"
+    "}"
+    "result");
+  CHECK_EQ(42 * 10, value->Int32Value());
+}
+
+
+static v8::Handle<Value> InterceptorLoadICGetter0(Local<String> name,
+                                                  const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(v8_str("x")->Equals(name));
+  return v8::Integer::New(0);
+}
+
+
+THREADED_TEST(InterceptorReturningZero) {
+  CheckInterceptorLoadIC(InterceptorLoadICGetter0,
+     "o.x == undefined ? 1 : 0",
+     0);
+}
+
+
+static v8::Handle<Value> InterceptorStoreICSetter(
+    Local<String> key, Local<Value> value, const AccessorInfo&) {
+  CHECK(v8_str("x")->Equals(key));
+  CHECK_EQ(42, value->Int32Value());
+  return value;
+}
+
+
+// This test should hit the store IC for the interceptor case.
+THREADED_TEST(InterceptorStoreIC) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
+                                 InterceptorStoreICSetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "for (var i = 0; i < 1000; i++) {"
+    "  o.x = 42;"
+    "}");
+}
+
+
+THREADED_TEST(InterceptorStoreICWithNoSetter) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "for (var i = 0; i < 1000; i++) {"
+    "  o.y = 239;"
+    "}"
+    "42 + o.y");
+  CHECK_EQ(239 + 42, value->Int32Value());
+}
+
+
+
+
+v8::Handle<Value> call_ic_function;
+v8::Handle<Value> call_ic_function2;
+v8::Handle<Value> call_ic_function3;
+
+static v8::Handle<Value> InterceptorCallICGetter(Local<String> name,
+                                                 const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(v8_str("x")->Equals(name));
+  return call_ic_function;
+}
+
+
+// This test should hit the call IC for the interceptor case.
+THREADED_TEST(InterceptorCallIC) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorCallICGetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  call_ic_function =
+      v8_compile("function f(x) { return x + 1; }; f")->Run();
+  v8::Handle<Value> value = CompileRun(
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.x(41);"
+    "}");
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+// This test checks that if interceptor doesn't provide
+// a value, we can fetch regular value.
+THREADED_TEST(InterceptorCallICSeesOthers) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "o.x = function f(x) { return x + 1; };"
+    "var result = 0;"
+    "for (var i = 0; i < 7; i++) {"
+    "  result = o.x(41);"
+    "}");
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+static v8::Handle<Value> call_ic_function4;
+static v8::Handle<Value> InterceptorCallICGetter4(Local<String> name,
+                                                  const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(v8_str("x")->Equals(name));
+  return call_ic_function4;
+}
+
+
+// This test checks that if interceptor provides a function,
+// even if we cached shadowed variant, interceptor's function
+// is invoked
+THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  call_ic_function4 =
+      v8_compile("function f(x) { return x - 1; }; f")->Run();
+  v8::Handle<Value> value = CompileRun(
+    "o.__proto__.x = function(x) { return x + 1; };"
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.x(42);"
+    "}");
+  CHECK_EQ(41, value->Int32Value());
+}
+
+
+// Test the case when we stored cacheable lookup into
+// a stub, but it got invalidated later on
+THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "proto1 = new Object();"
+    "proto2 = new Object();"
+    "o.__proto__ = proto1;"
+    "proto1.__proto__ = proto2;"
+    "proto2.y = function(x) { return x + 1; };"
+    // Invoke it many times to compile a stub
+    "for (var i = 0; i < 7; i++) {"
+    "  o.y(42);"
+    "}"
+    "proto1.y = function(x) { return x - 1; };"
+    "var result = 0;"
+    "for (var i = 0; i < 7; i++) {"
+    "  result += o.y(42);"
+    "}");
+  CHECK_EQ(41 * 7, value->Int32Value());
+}
+
+
+static v8::Handle<Value> call_ic_function5;
+static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name,
+                                                  const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (v8_str("x")->Equals(name))
+    return call_ic_function5;
+  else
+    return Local<Value>();
+}
+
+
+// This test checks that if interceptor doesn't provide a function,
+// cached constant function is used
+THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "function inc(x) { return x + 1; };"
+    "inc(1);"
+    "o.x = inc;"
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.x(42);"
+    "}");
+  CHECK_EQ(43, value->Int32Value());
+}
+
+
+// This test checks that if interceptor provides a function,
+// even if we cached constant function, interceptor's function
+// is invoked
+THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  call_ic_function5 =
+      v8_compile("function f(x) { return x - 1; }; f")->Run();
+  v8::Handle<Value> value = CompileRun(
+    "function inc(x) { return x + 1; };"
+    "inc(1);"
+    "o.x = inc;"
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.x(42);"
+    "}");
+  CHECK_EQ(41, value->Int32Value());
+}
+
+
+// Test the case when we stored constant function into
+// a stub, but it got invalidated later on
+THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "function inc(x) { return x + 1; };"
+    "inc(1);"
+    "proto1 = new Object();"
+    "proto2 = new Object();"
+    "o.__proto__ = proto1;"
+    "proto1.__proto__ = proto2;"
+    "proto2.y = inc;"
+    // Invoke it many times to compile a stub
+    "for (var i = 0; i < 7; i++) {"
+    "  o.y(42);"
+    "}"
+    "proto1.y = function(x) { return x - 1; };"
+    "var result = 0;"
+    "for (var i = 0; i < 7; i++) {"
+    "  result += o.y(42);"
+    "}");
+  CHECK_EQ(41 * 7, value->Int32Value());
+}
+
+
+// Test the case when we stored constant function into
+// a stub, but it got invalidated later on due to override on
+// global object which is between interceptor and constant function' holders.
+THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "function inc(x) { return x + 1; };"
+    "inc(1);"
+    "o.__proto__ = this;"
+    "this.__proto__.y = inc;"
+    // Invoke it many times to compile a stub
+    "for (var i = 0; i < 7; i++) {"
+    "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
+    "}"
+    "this.y = function(x) { return x - 1; };"
+    "var result = 0;"
+    "for (var i = 0; i < 7; i++) {"
+    "  result += o.y(42);"
+    "}");
+  CHECK_EQ(41 * 7, value->Int32Value());
+}
+
+
+static int interceptor_call_count = 0;
+
+static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name,
+                                                     const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
+    return call_ic_function2;
+  }
+  return v8::Handle<Value>();
+}
+
+
+// This test should hit load and call ICs for the interceptor case.
+// Once in a while, the interceptor will reply that a property was not
+// found in which case we should get a reference error.
+THREADED_TEST(InterceptorICReferenceErrors) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
+  LocalContext context(0, templ, v8::Handle<Value>());
+  call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
+  v8::Handle<Value> value = CompileRun(
+    "function f() {"
+    "  for (var i = 0; i < 1000; i++) {"
+    "    try { x; } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "f();");
+  CHECK_EQ(true, value->BooleanValue());
+  interceptor_call_count = 0;
+  value = CompileRun(
+    "function g() {"
+    "  for (var i = 0; i < 1000; i++) {"
+    "    try { x(42); } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "g();");
+  CHECK_EQ(true, value->BooleanValue());
+}
+
+
+static int interceptor_ic_exception_get_count = 0;
+
+static v8::Handle<Value> InterceptorICExceptionGetter(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
+    return call_ic_function3;
+  }
+  if (interceptor_ic_exception_get_count == 20) {
+    return v8::ThrowException(v8_num(42));
+  }
+  // Do not handle get for properties other than x.
+  return v8::Handle<Value>();
+}
+
+// Test interceptor load/call IC where the interceptor throws an
+// exception once in a while.
+THREADED_TEST(InterceptorICGetterExceptions) {
+  interceptor_ic_exception_get_count = 0;
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
+  LocalContext context(0, templ, v8::Handle<Value>());
+  call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
+  v8::Handle<Value> value = CompileRun(
+    "function f() {"
+    "  for (var i = 0; i < 100; i++) {"
+    "    try { x; } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "f();");
+  CHECK_EQ(true, value->BooleanValue());
+  interceptor_ic_exception_get_count = 0;
+  value = CompileRun(
+    "function f() {"
+    "  for (var i = 0; i < 100; i++) {"
+    "    try { x(42); } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "f();");
+  CHECK_EQ(true, value->BooleanValue());
+}
+
+
+static int interceptor_ic_exception_set_count = 0;
+
+static v8::Handle<Value> InterceptorICExceptionSetter(
+      Local<String> key, Local<Value> value, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  if (++interceptor_ic_exception_set_count > 20) {
+    return v8::ThrowException(v8_num(42));
+  }
+  // Do not actually handle setting.
+  return v8::Handle<Value>();
+}
+
+// Test interceptor store IC where the interceptor throws an exception
+// once in a while.
+THREADED_TEST(InterceptorICSetterExceptions) {
+  interceptor_ic_exception_set_count = 0;
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
+  LocalContext context(0, templ, v8::Handle<Value>());
+  v8::Handle<Value> value = CompileRun(
+    "function f() {"
+    "  for (var i = 0; i < 100; i++) {"
+    "    try { x = 42; } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "f();");
+  CHECK_EQ(true, value->BooleanValue());
+}
+
+
+// Test that we ignore null interceptors.
+THREADED_TEST(NullNamedInterceptor) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(0);
+  LocalContext context;
+  templ->Set("x", v8_num(42));
+  v8::Handle<v8::Object> obj = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), obj);
+  v8::Handle<Value> value = CompileRun("obj.x");
+  CHECK(value->IsInt32());
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+// Test that we ignore null interceptors.
+THREADED_TEST(NullIndexedInterceptor) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetIndexedPropertyHandler(0);
+  LocalContext context;
+  templ->Set("42", v8_num(42));
+  v8::Handle<v8::Object> obj = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), obj);
+  v8::Handle<Value> value = CompileRun("obj[42]");
+  CHECK(value->IsInt32());
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+static v8::Handle<Value> ParentGetter(Local<String> name,
+                                      const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(1);
+}
+
+
+static v8::Handle<Value> ChildGetter(Local<String> name,
+                                     const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(42);
+}
+
+
+THREADED_TEST(Overriding) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  // Parent template.
+  Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
+  Local<ObjectTemplate> parent_instance_templ =
+      parent_templ->InstanceTemplate();
+  parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
+
+  // Template that inherits from the parent template.
+  Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
+  Local<ObjectTemplate> child_instance_templ =
+      child_templ->InstanceTemplate();
+  child_templ->Inherit(parent_templ);
+  // Override 'f'.  The child version of 'f' should get called for child
+  // instances.
+  child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
+  // Add 'g' twice.  The 'g' added last should get called for instances.
+  child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
+  child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
+
+  // Add 'h' as an accessor to the proto template with ReadOnly attributes
+  // so 'h' can be shadowed on the instance object.
+  Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
+  child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
+      v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
+
+  // Add 'i' as an accessor to the instance template with ReadOnly attributes
+  // but the attribute does not have effect because it is duplicated with
+  // NULL setter.
+  child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
+      v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
+
+
+
+  // Instantiate the child template.
+  Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
+
+  // Check that the child function overrides the parent one.
+  context->Global()->Set(v8_str("o"), instance);
+  Local<Value> value = v8_compile("o.f")->Run();
+  // Check that the 'g' that was added last is hit.
+  CHECK_EQ(42, value->Int32Value());
+  value = v8_compile("o.g")->Run();
+  CHECK_EQ(42, value->Int32Value());
+
+  // Check 'h' can be shadowed.
+  value = v8_compile("o.h = 3; o.h")->Run();
+  CHECK_EQ(3, value->Int32Value());
+
+  // Check 'i' is cannot be shadowed or changed.
+  value = v8_compile("o.i = 3; o.i")->Run();
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+static v8::Handle<Value> IsConstructHandler(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  if (args.IsConstructCall()) {
+    return v8::Boolean::New(true);
+  }
+  return v8::Boolean::New(false);
+}
+
+
+THREADED_TEST(IsConstructCall) {
+  v8::HandleScope scope;
+
+  // Function template with call handler.
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->SetCallHandler(IsConstructHandler);
+
+  LocalContext context;
+
+  context->Global()->Set(v8_str("f"), templ->GetFunction());
+  Local<Value> value = v8_compile("f()")->Run();
+  CHECK(!value->BooleanValue());
+  value = v8_compile("new f()")->Run();
+  CHECK(value->BooleanValue());
+}
+
+
+THREADED_TEST(ObjectProtoToString) {
+  v8::HandleScope scope;
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->SetClassName(v8_str("MyClass"));
+
+  LocalContext context;
+
+  Local<String> customized_tostring = v8_str("customized toString");
+
+  // Replace Object.prototype.toString
+  v8_compile("Object.prototype.toString = function() {"
+                  "  return 'customized toString';"
+                  "}")->Run();
+
+  // Normal ToString call should call replaced Object.prototype.toString
+  Local<v8::Object> instance = templ->GetFunction()->NewInstance();
+  Local<String> value = instance->ToString();
+  CHECK(value->IsString() && value->Equals(customized_tostring));
+
+  // ObjectProtoToString should not call replace toString function.
+  value = instance->ObjectProtoToString();
+  CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
+
+  // Check global
+  value = context->Global()->ObjectProtoToString();
+  CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
+
+  // Check ordinary object
+  Local<Value> object = v8_compile("new Object()")->Run();
+  value = Local<v8::Object>::Cast(object)->ObjectProtoToString();
+  CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
+}
+
+
+bool ApiTestFuzzer::fuzzing_ = false;
+v8::internal::Semaphore* ApiTestFuzzer::all_tests_done_=
+  v8::internal::OS::CreateSemaphore(0);
+int ApiTestFuzzer::active_tests_;
+int ApiTestFuzzer::tests_being_run_;
+int ApiTestFuzzer::current_;
+
+
+// We are in a callback and want to switch to another thread (if we
+// are currently running the thread fuzzing test).
+void ApiTestFuzzer::Fuzz() {
+  if (!fuzzing_) return;
+  ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
+  test->ContextSwitch();
+}
+
+
+// Let the next thread go.  Since it is also waiting on the V8 lock it may
+// not start immediately.
+bool ApiTestFuzzer::NextThread() {
+  int test_position = GetNextTestNumber();
+  int test_number = RegisterThreadedTest::nth(current_)->fuzzer_->test_number_;
+  if (test_position == current_) {
+    printf("Stay with %d\n", test_number);
+    return false;
+  }
+  printf("Switch from %d to %d\n",
+         current_ < 0 ? 0 : test_number, test_position < 0 ? 0 : test_number);
+  current_ = test_position;
+  RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
+  return true;
+}
+
+
+void ApiTestFuzzer::Run() {
+  // When it is our turn...
+  gate_->Wait();
+  {
+    // ... get the V8 lock and start running the test.
+    v8::Locker locker;
+    CallTest();
+  }
+  // This test finished.
+  active_ = false;
+  active_tests_--;
+  // If it was the last then signal that fact.
+  if (active_tests_ == 0) {
+    all_tests_done_->Signal();
+  } else {
+    // Otherwise select a new test and start that.
+    NextThread();
+  }
+}
+
+
+static unsigned linear_congruential_generator;
+
+
+void ApiTestFuzzer::Setup(PartOfTest part) {
+  linear_congruential_generator = i::FLAG_testing_prng_seed;
+  fuzzing_ = true;
+  int start = (part == FIRST_PART) ? 0 : (RegisterThreadedTest::count() >> 1);
+  int end = (part == FIRST_PART)
+      ? (RegisterThreadedTest::count() >> 1)
+      : RegisterThreadedTest::count();
+  active_tests_ = tests_being_run_ = end - start;
+  for (int i = 0; i < tests_being_run_; i++) {
+    RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
+  }
+  for (int i = 0; i < active_tests_; i++) {
+    RegisterThreadedTest::nth(i)->fuzzer_->Start();
+  }
+}
+
+
+static void CallTestNumber(int test_number) {
+  (RegisterThreadedTest::nth(test_number)->callback())();
+}
+
+
+void ApiTestFuzzer::RunAllTests() {
+  // Set off the first test.
+  current_ = -1;
+  NextThread();
+  // Wait till they are all done.
+  all_tests_done_->Wait();
+}
+
+
+int ApiTestFuzzer::GetNextTestNumber() {
+  int next_test;
+  do {
+    next_test = (linear_congruential_generator >> 16) % tests_being_run_;
+    linear_congruential_generator *= 1664525u;
+    linear_congruential_generator += 1013904223u;
+  } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
+  return next_test;
+}
+
+
+void ApiTestFuzzer::ContextSwitch() {
+  // If the new thread is the same as the current thread there is nothing to do.
+  if (NextThread()) {
+    // Now it can start.
+    v8::Unlocker unlocker;
+    // Wait till someone starts us again.
+    gate_->Wait();
+    // And we're off.
+  }
+}
+
+
+void ApiTestFuzzer::TearDown() {
+  fuzzing_ = false;
+  for (int i = 0; i < RegisterThreadedTest::count(); i++) {
+    ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
+    if (fuzzer != NULL) fuzzer->Join();
+  }
+}
+
+
+// Lets not be needlessly self-referential.
+TEST(Threading) {
+  ApiTestFuzzer::Setup(ApiTestFuzzer::FIRST_PART);
+  ApiTestFuzzer::RunAllTests();
+  ApiTestFuzzer::TearDown();
+}
+
+TEST(Threading2) {
+  ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART);
+  ApiTestFuzzer::RunAllTests();
+  ApiTestFuzzer::TearDown();
+}
+
+
+void ApiTestFuzzer::CallTest() {
+  printf("Start test %d\n", test_number_);
+  CallTestNumber(test_number_);
+  printf("End test %d\n", test_number_);
+}
+
+
+static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) {
+  CHECK(v8::Locker::IsLocked());
+  ApiTestFuzzer::Fuzz();
+  v8::Unlocker unlocker;
+  const char* code = "throw 7;";
+  {
+    v8::Locker nested_locker;
+    v8::HandleScope scope;
+    v8::Handle<Value> exception;
+    { v8::TryCatch try_catch;
+      v8::Handle<Value> value = CompileRun(code);
+      CHECK(value.IsEmpty());
+      CHECK(try_catch.HasCaught());
+      // Make sure to wrap the exception in a new handle because
+      // the handle returned from the TryCatch is destroyed
+      // when the TryCatch is destroyed.
+      exception = Local<Value>::New(try_catch.Exception());
+    }
+    return v8::ThrowException(exception);
+  }
+}
+
+
+static v8::Handle<Value> ThrowInJSNoCatch(const v8::Arguments& args) {
+  CHECK(v8::Locker::IsLocked());
+  ApiTestFuzzer::Fuzz();
+  v8::Unlocker unlocker;
+  const char* code = "throw 7;";
+  {
+    v8::Locker nested_locker;
+    v8::HandleScope scope;
+    v8::Handle<Value> value = CompileRun(code);
+    CHECK(value.IsEmpty());
+    return v8_str("foo");
+  }
+}
+
+
+// These are locking tests that don't need to be run again
+// as part of the locking aggregation tests.
+TEST(NestedLockers) {
+  v8::Locker locker;
+  CHECK(v8::Locker::IsLocked());
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
+  Local<Function> fun = fun_templ->GetFunction();
+  env->Global()->Set(v8_str("throw_in_js"), fun);
+  Local<Script> script = v8_compile("(function () {"
+                                    "  try {"
+                                    "    throw_in_js();"
+                                    "    return 42;"
+                                    "  } catch (e) {"
+                                    "    return e * 13;"
+                                    "  }"
+                                    "})();");
+  CHECK_EQ(91, script->Run()->Int32Value());
+}
+
+
+// These are locking tests that don't need to be run again
+// as part of the locking aggregation tests.
+TEST(NestedLockersNoTryCatch) {
+  v8::Locker locker;
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(ThrowInJSNoCatch);
+  Local<Function> fun = fun_templ->GetFunction();
+  env->Global()->Set(v8_str("throw_in_js"), fun);
+  Local<Script> script = v8_compile("(function () {"
+                                    "  try {"
+                                    "    throw_in_js();"
+                                    "    return 42;"
+                                    "  } catch (e) {"
+                                    "    return e * 13;"
+                                    "  }"
+                                    "})();");
+  CHECK_EQ(91, script->Run()->Int32Value());
+}
+
+
+THREADED_TEST(RecursiveLocking) {
+  v8::Locker locker;
+  {
+    v8::Locker locker2;
+    CHECK(v8::Locker::IsLocked());
+  }
+}
+
+
+static v8::Handle<Value> UnlockForAMoment(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  v8::Unlocker unlocker;
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(LockUnlockLock) {
+  {
+    v8::Locker locker;
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(UnlockForAMoment);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
+    Local<Script> script = v8_compile("(function () {"
+                                      "  unlock_for_a_moment();"
+                                      "  return 42;"
+                                      "})();");
+    CHECK_EQ(42, script->Run()->Int32Value());
+  }
+  {
+    v8::Locker locker;
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(UnlockForAMoment);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
+    Local<Script> script = v8_compile("(function () {"
+                                      "  unlock_for_a_moment();"
+                                      "  return 42;"
+                                      "})();");
+    CHECK_EQ(42, script->Run()->Int32Value());
+  }
+}
+
+
+static int GetSurvivingGlobalObjectsCount() {
+  int count = 0;
+  // We need to collect all garbage twice to be sure that everything
+  // has been collected.  This is because inline caches are cleared in
+  // the first garbage collection but some of the maps have already
+  // been marked at that point.  Therefore some of the maps are not
+  // collected until the second garbage collection.
+  v8::internal::Heap::CollectAllGarbage(false);
+  v8::internal::Heap::CollectAllGarbage(false);
+  v8::internal::HeapIterator it;
+  while (it.has_next()) {
+    v8::internal::HeapObject* object = it.next();
+    if (object->IsJSGlobalObject()) {
+      count++;
+    }
+  }
+#ifdef DEBUG
+  if (count > 0) v8::internal::Heap::TracePathToGlobal();
+#endif
+  return count;
+}
+
+
+TEST(DontLeakGlobalObjects) {
+  // Regression test for issues 1139850 and 1174891.
+
+  v8::V8::Initialize();
+
+  int count = GetSurvivingGlobalObjectsCount();
+
+  for (int i = 0; i < 5; i++) {
+    { v8::HandleScope scope;
+      LocalContext context;
+    }
+    CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+
+    { v8::HandleScope scope;
+      LocalContext context;
+      v8_compile("Date")->Run();
+    }
+    CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+
+    { v8::HandleScope scope;
+      LocalContext context;
+      v8_compile("/aaa/")->Run();
+    }
+    CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+
+    { v8::HandleScope scope;
+      const char* extension_list[] = { "v8/gc" };
+      v8::ExtensionConfiguration extensions(1, extension_list);
+      LocalContext context(&extensions);
+      v8_compile("gc();")->Run();
+    }
+    CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+  }
+}
+
+
+v8::Persistent<v8::Object> some_object;
+v8::Persistent<v8::Object> bad_handle;
+
+void NewPersistentHandleCallback(v8::Persistent<v8::Value>, void*) {
+  v8::HandleScope scope;
+  bad_handle = v8::Persistent<v8::Object>::New(some_object);
+}
+
+
+THREADED_TEST(NewPersistentHandleFromWeakCallback) {
+  LocalContext context;
+
+  v8::Persistent<v8::Object> handle1, handle2;
+  {
+    v8::HandleScope scope;
+    some_object = v8::Persistent<v8::Object>::New(v8::Object::New());
+    handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
+    handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
+  }
+  // Note: order is implementation dependent alas: currently
+  // global handle nodes are processed by PostGarbageCollectionProcessing
+  // in reverse allocation order, so if second allocated handle is deleted,
+  // weak callback of the first handle would be able to 'reallocate' it.
+  handle1.MakeWeak(NULL, NewPersistentHandleCallback);
+  handle2.Dispose();
+  i::Heap::CollectAllGarbage(false);
+}
+
+
+v8::Persistent<v8::Object> to_be_disposed;
+
+void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) {
+  to_be_disposed.Dispose();
+  i::Heap::CollectAllGarbage(false);
+}
+
+
+THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
+  LocalContext context;
+
+  v8::Persistent<v8::Object> handle1, handle2;
+  {
+    v8::HandleScope scope;
+    handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
+    handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
+  }
+  handle1.MakeWeak(NULL, DisposeAndForceGcCallback);
+  to_be_disposed = handle2;
+  i::Heap::CollectAllGarbage(false);
+}
+
+
+THREADED_TEST(CheckForCrossContextObjectLiterals) {
+  v8::V8::Initialize();
+
+  const int nof = 2;
+  const char* sources[nof] = {
+    "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
+    "Object()"
+  };
+
+  for (int i = 0; i < nof; i++) {
+    const char* source = sources[i];
+    { v8::HandleScope scope;
+      LocalContext context;
+      CompileRun(source);
+    }
+    { v8::HandleScope scope;
+      LocalContext context;
+      CompileRun(source);
+    }
+  }
+}
+
+
+static v8::Handle<Value> NestedScope(v8::Persistent<Context> env) {
+  v8::HandleScope inner;
+  env->Enter();
+  v8::Handle<Value> three = v8_num(3);
+  v8::Handle<Value> value = inner.Close(three);
+  env->Exit();
+  return value;
+}
+
+
+THREADED_TEST(NestedHandleScopeAndContexts) {
+  v8::HandleScope outer;
+  v8::Persistent<Context> env = Context::New();
+  env->Enter();
+  v8::Handle<Value> value = NestedScope(env);
+  v8::Handle<String> str = value->ToString();
+  env->Exit();
+  env.Dispose();
+}
+
+
+THREADED_TEST(ExternalAllocatedMemory) {
+  v8::HandleScope outer;
+  v8::Persistent<Context> env = Context::New();
+  const int kSize = 1024*1024;
+  CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize);
+  CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0);
+}
+
+
+THREADED_TEST(DisposeEnteredContext) {
+  v8::HandleScope scope;
+  LocalContext outer;
+  { v8::Persistent<v8::Context> inner = v8::Context::New();
+    inner->Enter();
+    inner.Dispose();
+    inner.Clear();
+    inner->Exit();
+  }
+}
+
+
+// Regression test for issue 54, object templates with internal fields
+// but no accessors or interceptors did not get their internal field
+// count set on instances.
+THREADED_TEST(Regress54) {
+  v8::HandleScope outer;
+  LocalContext context;
+  static v8::Persistent<v8::ObjectTemplate> templ;
+  if (templ.IsEmpty()) {
+    v8::HandleScope inner;
+    v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
+    local->SetInternalFieldCount(1);
+    templ = v8::Persistent<v8::ObjectTemplate>::New(inner.Close(local));
+  }
+  v8::Handle<v8::Object> result = templ->NewInstance();
+  CHECK_EQ(1, result->InternalFieldCount());
+}
+
+
+// If part of the threaded tests, this test makes ThreadingTest fail
+// on mac.
+TEST(CatchStackOverflow) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
+    "function f() {"
+    "  return f();"
+    "}"
+    ""
+    "f();"));
+  v8::Handle<v8::Value> result = script->Run();
+  CHECK(result.IsEmpty());
+}
+
+
+static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
+                                    const char* resource_name,
+                                    int line_offset) {
+  v8::HandleScope scope;
+  v8::TryCatch try_catch;
+  v8::Handle<v8::Value> result = script->Run();
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  v8::Handle<v8::Message> message = try_catch.Message();
+  CHECK(!message.IsEmpty());
+  CHECK_EQ(10 + line_offset, message->GetLineNumber());
+  CHECK_EQ(91, message->GetStartPosition());
+  CHECK_EQ(92, message->GetEndPosition());
+  CHECK_EQ(2, message->GetStartColumn());
+  CHECK_EQ(3, message->GetEndColumn());
+  v8::String::AsciiValue line(message->GetSourceLine());
+  CHECK_EQ("  throw 'nirk';", *line);
+  v8::String::AsciiValue name(message->GetScriptResourceName());
+  CHECK_EQ(resource_name, *name);
+}
+
+
+THREADED_TEST(TryCatchSourceInfo) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::String> source = v8::String::New(
+      "function Foo() {\n"
+      "  return Bar();\n"
+      "}\n"
+      "\n"
+      "function Bar() {\n"
+      "  return Baz();\n"
+      "}\n"
+      "\n"
+      "function Baz() {\n"
+      "  throw 'nirk';\n"
+      "}\n"
+      "\n"
+      "Foo();\n");
+
+  const char* resource_name;
+  v8::Handle<v8::Script> script;
+  resource_name = "test.js";
+  script = v8::Script::Compile(source, v8::String::New(resource_name));
+  CheckTryCatchSourceInfo(script, resource_name, 0);
+
+  resource_name = "test1.js";
+  v8::ScriptOrigin origin1(v8::String::New(resource_name));
+  script = v8::Script::Compile(source, &origin1);
+  CheckTryCatchSourceInfo(script, resource_name, 0);
+
+  resource_name = "test2.js";
+  v8::ScriptOrigin origin2(v8::String::New(resource_name), v8::Integer::New(7));
+  script = v8::Script::Compile(source, &origin2);
+  CheckTryCatchSourceInfo(script, resource_name, 7);
+}
+
+
+THREADED_TEST(CompilationCache) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::String> source0 = v8::String::New("1234");
+  v8::Handle<v8::String> source1 = v8::String::New("1234");
+  v8::Handle<v8::Script> script0 =
+      v8::Script::Compile(source0, v8::String::New("test.js"));
+  v8::Handle<v8::Script> script1 =
+      v8::Script::Compile(source1, v8::String::New("test.js"));
+  v8::Handle<v8::Script> script2 =
+      v8::Script::Compile(source0);  // different origin
+  CHECK_EQ(1234, script0->Run()->Int32Value());
+  CHECK_EQ(1234, script1->Run()->Int32Value());
+  CHECK_EQ(1234, script2->Run()->Int32Value());
+}
+
+
+static v8::Handle<Value> FunctionNameCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(42);
+}
+
+
+THREADED_TEST(CallbackFunctionName) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> t = ObjectTemplate::New();
+  t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
+  context->Global()->Set(v8_str("obj"), t->NewInstance());
+  v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
+  CHECK(value->IsString());
+  v8::String::AsciiValue name(value);
+  CHECK_EQ("asdf", *name);
+}
+
+
+THREADED_TEST(DateAccess) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
+  CHECK(date->IsDate());
+  CHECK_EQ(1224744689038.0, v8::Handle<v8::Date>::Cast(date)->NumberValue());
+}
+
+
+void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
+  v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val);
+  v8::Handle<v8::Array> props = obj->GetPropertyNames();
+  CHECK_EQ(elmc, props->Length());
+  for (int i = 0; i < elmc; i++) {
+    v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
+    CHECK_EQ(elmv[i], *elm);
+  }
+}
+
+
+THREADED_TEST(PropertyEnumeration) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
+      "var result = [];"
+      "result[0] = {};"
+      "result[1] = {a: 1, b: 2};"
+      "result[2] = [1, 2, 3];"
+      "var proto = {x: 1, y: 2, z: 3};"
+      "var x = { __proto__: proto, w: 0, z: 1 };"
+      "result[3] = x;"
+      "result;"))->Run();
+  v8::Handle<v8::Array> elms = v8::Handle<v8::Array>::Cast(obj);
+  CHECK_EQ(4, elms->Length());
+  int elmc0 = 0;
+  const char** elmv0 = NULL;
+  CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
+  int elmc1 = 2;
+  const char* elmv1[] = {"a", "b"};
+  CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
+  int elmc2 = 3;
+  const char* elmv2[] = {"0", "1", "2"};
+  CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
+  int elmc3 = 4;
+  const char* elmv3[] = {"w", "z", "x", "y"};
+  CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
+}
+
+
+static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::True();
+}
+
+
+THREADED_TEST(AccessorProhibitsOverwriting) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("x"),
+                     AccessorProhibitsOverwritingGetter,
+                     0,
+                     v8::Handle<Value>(),
+                     v8::PROHIBITS_OVERWRITING,
+                     v8::ReadOnly);
+  Local<v8::Object> instance = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), instance);
+  Local<Value> value = CompileRun(
+      "obj.__defineGetter__('x', function() { return false; });"
+      "obj.x");
+  CHECK(value->BooleanValue());
+  value = CompileRun(
+      "var setter_called = false;"
+      "obj.__defineSetter__('x', function() { setter_called = true; });"
+      "obj.x = 42;"
+      "setter_called");
+  CHECK(!value->BooleanValue());
+  value = CompileRun(
+      "obj2 = {};"
+      "obj2.__proto__ = obj;"
+      "obj2.__defineGetter__('x', function() { return false; });"
+      "obj2.x");
+  CHECK(value->BooleanValue());
+  value = CompileRun(
+      "var setter_called = false;"
+      "obj2 = {};"
+      "obj2.__proto__ = obj;"
+      "obj2.__defineSetter__('x', function() { setter_called = true; });"
+      "obj2.x = 42;"
+      "setter_called");
+  CHECK(!value->BooleanValue());
+}
+
+
+static bool NamedSetAccessBlocker(Local<v8::Object> obj,
+                                  Local<Value> name,
+                                  v8::AccessType type,
+                                  Local<Value> data) {
+  return type != v8::ACCESS_SET;
+}
+
+
+static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
+                                    uint32_t key,
+                                    v8::AccessType type,
+                                    Local<Value> data) {
+  return type != v8::ACCESS_SET;
+}
+
+
+THREADED_TEST(DisableAccessChecksWhileConfiguring) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
+                                 IndexedSetAccessBlocker);
+  templ->Set(v8_str("x"), v8::True());
+  Local<v8::Object> instance = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), instance);
+  Local<Value> value = CompileRun("obj.x");
+  CHECK(value->BooleanValue());
+}
+
+
+static bool NamedGetAccessBlocker(Local<v8::Object> obj,
+                                  Local<Value> name,
+                                  v8::AccessType type,
+                                  Local<Value> data) {
+  return false;
+}
+
+
+static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
+                                    uint32_t key,
+                                    v8::AccessType type,
+                                    Local<Value> data) {
+  return false;
+}
+
+
+
+THREADED_TEST(AccessChecksReenabledCorrectly) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
+                                 IndexedGetAccessBlocker);
+  templ->Set(v8_str("a"), v8_str("a"));
+  // Add more than 8 (see kMaxFastProperties) properties
+  // so that the constructor will force copying map.
+  // Cannot sprintf, gcc complains unsafety.
+  char buf[4];
+  for (char i = '0'; i <= '9' ; i++) {
+    buf[0] = i;
+    for (char j = '0'; j <= '9'; j++) {
+      buf[1] = j;
+      for (char k = '0'; k <= '9'; k++) {
+        buf[2] = k;
+        buf[3] = 0;
+        templ->Set(v8_str(buf), v8::Number::New(k));
+      }
+    }
+  }
+
+  Local<v8::Object> instance_1 = templ->NewInstance();
+  context->Global()->Set(v8_str("obj_1"), instance_1);
+
+  Local<Value> value_1 = CompileRun("obj_1.a");
+  CHECK(value_1->IsUndefined());
+
+  Local<v8::Object> instance_2 = templ->NewInstance();
+  context->Global()->Set(v8_str("obj_2"), instance_2);
+
+  Local<Value> value_2 = CompileRun("obj_2.a");
+  CHECK(value_2->IsUndefined());
+}
+
+
+// This tests that access check information remains on the global
+// object template when creating contexts.
+THREADED_TEST(AccessControlRepeatedContextCreation) {
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
+                                           IndexedSetAccessBlocker);
+  i::Handle<i::ObjectTemplateInfo> internal_template =
+      v8::Utils::OpenHandle(*global_template);
+  CHECK(!internal_template->constructor()->IsUndefined());
+  i::Handle<i::FunctionTemplateInfo> constructor(
+      i::FunctionTemplateInfo::cast(internal_template->constructor()));
+  CHECK(!constructor->access_check_info()->IsUndefined());
+  v8::Persistent<Context> context0 = Context::New(NULL, global_template);
+  CHECK(!constructor->access_check_info()->IsUndefined());
+}
+
+
+THREADED_TEST(TurnOnAccessCheck) {
+  v8::HandleScope handle_scope;
+
+  // Create an environment with access check to the global object disabled by
+  // default.
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
+                                           IndexedGetAccessBlocker,
+                                           v8::Handle<v8::Value>(),
+                                           false);
+  v8::Persistent<Context> context = Context::New(NULL, global_template);
+  Context::Scope context_scope(context);
+
+  // Set up a property and a number of functions.
+  context->Global()->Set(v8_str("a"), v8_num(1));
+  CompileRun("function f1() {return a;}"
+             "function f2() {return a;}"
+             "function g1() {return h();}"
+             "function g2() {return h();}"
+             "function h() {return 1;}");
+  Local<Function> f1 =
+      Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
+  Local<Function> f2 =
+      Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
+  Local<Function> g1 =
+      Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
+  Local<Function> g2 =
+      Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
+  Local<Function> h =
+      Local<Function>::Cast(context->Global()->Get(v8_str("h")));
+
+  // Get the global object.
+  v8::Handle<v8::Object> global = context->Global();
+
+  // Call f1 one time and f2 a number of times. This will ensure that f1 still
+  // uses the runtime system to retreive property a whereas f2 uses global load
+  // inline cache.
+  CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
+  for (int i = 0; i < 4; i++) {
+    CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
+  }
+
+  // Same for g1 and g2.
+  CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
+  for (int i = 0; i < 4; i++) {
+    CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
+  }
+
+  // Detach the global and turn on access check.
+  context->DetachGlobal();
+  context->Global()->TurnOnAccessCheck();
+
+  // Failing access check to property get results in undefined.
+  CHECK(f1->Call(global, 0, NULL)->IsUndefined());
+  CHECK(f2->Call(global, 0, NULL)->IsUndefined());
+
+  // Failing access check to function call results in exception.
+  CHECK(g1->Call(global, 0, NULL).IsEmpty());
+  CHECK(g2->Call(global, 0, NULL).IsEmpty());
+
+  // No failing access check when just returning a constant.
+  CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
+}
+
+
+// This test verifies that pre-compilation (aka preparsing) can be called
+// without initializing the whole VM. Thus we cannot run this test in a
+// multi-threaded setup.
+TEST(PreCompile) {
+  // TODO(155): This test would break without the initialization of V8. This is
+  // a workaround for now to make this test not fail.
+  v8::V8::Initialize();
+  const char *script = "function foo(a) { return a+1; }";
+  v8::ScriptData *sd = v8::ScriptData::PreCompile(script, strlen(script));
+  CHECK_NE(sd->Length(), 0);
+  CHECK_NE(sd->Data(), NULL);
+  delete sd;
+}
+
+
+// This tests that we do not allow dictionary load/call inline caches
+// to use functions that have not yet been compiled.  The potential
+// problem of loading a function that has not yet been compiled can
+// arise because we share code between contexts via the compilation
+// cache.
+THREADED_TEST(DictionaryICLoadedFunction) {
+  v8::HandleScope scope;
+  // Test LoadIC.
+  for (int i = 0; i < 2; i++) {
+    LocalContext context;
+    context->Global()->Set(v8_str("tmp"), v8::True());
+    context->Global()->Delete(v8_str("tmp"));
+    CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
+  }
+  // Test CallIC.
+  for (int i = 0; i < 2; i++) {
+    LocalContext context;
+    context->Global()->Set(v8_str("tmp"), v8::True());
+    context->Global()->Delete(v8_str("tmp"));
+    CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
+  }
+}
+
+
+// Test that cross-context new calls use the context of the callee to
+// create the new JavaScript object.
+THREADED_TEST(CrossContextNew) {
+  v8::HandleScope scope;
+  v8::Persistent<Context> context0 = Context::New();
+  v8::Persistent<Context> context1 = Context::New();
+
+  // Allow cross-domain access.
+  Local<String> token = v8_str("<security token>");
+  context0->SetSecurityToken(token);
+  context1->SetSecurityToken(token);
+
+  // Set an 'x' property on the Object prototype and define a
+  // constructor function in context0.
+  context0->Enter();
+  CompileRun("Object.prototype.x = 42; function C() {};");
+  context0->Exit();
+
+  // Call the constructor function from context0 and check that the
+  // result has the 'x' property.
+  context1->Enter();
+  context1->Global()->Set(v8_str("other"), context0->Global());
+  Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
+  CHECK(value->IsInt32());
+  CHECK_EQ(42, value->Int32Value());
+  context1->Exit();
+
+  // Dispose the contexts to allow them to be garbage collected.
+  context0.Dispose();
+  context1.Dispose();
+}
+
+
+class RegExpInterruptTest {
+ public:
+  RegExpInterruptTest() : block_(NULL) {}
+  ~RegExpInterruptTest() { delete block_; }
+  void RunTest() {
+    block_ = i::OS::CreateSemaphore(0);
+    gc_count_ = 0;
+    gc_during_regexp_ = 0;
+    regexp_success_ = false;
+    gc_success_ = false;
+    GCThread gc_thread(this);
+    gc_thread.Start();
+    v8::Locker::StartPreemption(1);
+
+    LongRunningRegExp();
+    {
+      v8::Unlocker unlock;
+      gc_thread.Join();
+    }
+    v8::Locker::StopPreemption();
+    CHECK(regexp_success_);
+    CHECK(gc_success_);
+  }
+ private:
+  // Number of garbage collections required.
+  static const int kRequiredGCs = 5;
+
+  class GCThread : public i::Thread {
+   public:
+    explicit GCThread(RegExpInterruptTest* test)
+        : test_(test) {}
+    virtual void Run() {
+      test_->CollectGarbage();
+    }
+   private:
+     RegExpInterruptTest* test_;
+  };
+
+  void CollectGarbage() {
+    block_->Wait();
+    while (gc_during_regexp_ < kRequiredGCs) {
+      {
+        v8::Locker lock;
+        // TODO(lrn): Perhaps create some garbage before collecting.
+        i::Heap::CollectAllGarbage(false);
+        gc_count_++;
+      }
+      i::OS::Sleep(1);
+    }
+    gc_success_ = true;
+  }
+
+  void LongRunningRegExp() {
+    block_->Signal();  // Enable garbage collection thread on next preemption.
+    int rounds = 0;
+    while (gc_during_regexp_ < kRequiredGCs) {
+      int gc_before = gc_count_;
+      {
+        // Match 15-30 "a"'s against 14 and a "b".
+        const char* c_source =
+            "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
+            ".exec('aaaaaaaaaaaaaaab') === null";
+        Local<String> source = String::New(c_source);
+        Local<Script> script = Script::Compile(source);
+        Local<Value> result = script->Run();
+        if (!result->BooleanValue()) {
+          gc_during_regexp_ = kRequiredGCs;  // Allow gc thread to exit.
+          return;
+        }
+      }
+      {
+        // Match 15-30 "a"'s against 15 and a "b".
+        const char* c_source =
+            "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
+            ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
+        Local<String> source = String::New(c_source);
+        Local<Script> script = Script::Compile(source);
+        Local<Value> result = script->Run();
+        if (!result->BooleanValue()) {
+          gc_during_regexp_ = kRequiredGCs;
+          return;
+        }
+      }
+      int gc_after = gc_count_;
+      gc_during_regexp_ += gc_after - gc_before;
+      rounds++;
+      i::OS::Sleep(1);
+    }
+    regexp_success_ = true;
+  }
+
+  i::Semaphore* block_;
+  int gc_count_;
+  int gc_during_regexp_;
+  bool regexp_success_;
+  bool gc_success_;
+};
+
+
+// Test that a regular expression execution can be interrupted and
+// survive a garbage collection.
+TEST(RegExpInterruption) {
+  v8::Locker lock;
+  v8::V8::Initialize();
+  v8::HandleScope scope;
+  Local<Context> local_env;
+  {
+    LocalContext env;
+    local_env = env.local();
+  }
+
+  // Local context should still be live.
+  CHECK(!local_env.IsEmpty());
+  local_env->Enter();
+
+  // Should complete without problems.
+  RegExpInterruptTest().RunTest();
+
+  local_env->Exit();
+}
+
+
+class ApplyInterruptTest {
+ public:
+  ApplyInterruptTest() : block_(NULL) {}
+  ~ApplyInterruptTest() { delete block_; }
+  void RunTest() {
+    block_ = i::OS::CreateSemaphore(0);
+    gc_count_ = 0;
+    gc_during_apply_ = 0;
+    apply_success_ = false;
+    gc_success_ = false;
+    GCThread gc_thread(this);
+    gc_thread.Start();
+    v8::Locker::StartPreemption(1);
+
+    LongRunningApply();
+    {
+      v8::Unlocker unlock;
+      gc_thread.Join();
+    }
+    v8::Locker::StopPreemption();
+    CHECK(apply_success_);
+    CHECK(gc_success_);
+  }
+ private:
+  // Number of garbage collections required.
+  static const int kRequiredGCs = 2;
+
+  class GCThread : public i::Thread {
+   public:
+    explicit GCThread(ApplyInterruptTest* test)
+        : test_(test) {}
+    virtual void Run() {
+      test_->CollectGarbage();
+    }
+   private:
+     ApplyInterruptTest* test_;
+  };
+
+  void CollectGarbage() {
+    block_->Wait();
+    while (gc_during_apply_ < kRequiredGCs) {
+      {
+        v8::Locker lock;
+        i::Heap::CollectAllGarbage(false);
+        gc_count_++;
+      }
+      i::OS::Sleep(1);
+    }
+    gc_success_ = true;
+  }
+
+  void LongRunningApply() {
+    block_->Signal();
+    int rounds = 0;
+    while (gc_during_apply_ < kRequiredGCs) {
+      int gc_before = gc_count_;
+      {
+        const char* c_source =
+            "function do_very_little(bar) {"
+            "  this.foo = bar;"
+            "}"
+            "for (var i = 0; i < 100000; i++) {"
+            "  do_very_little.apply(this, ['bar']);"
+            "}";
+        Local<String> source = String::New(c_source);
+        Local<Script> script = Script::Compile(source);
+        Local<Value> result = script->Run();
+        // Check that no exception was thrown.
+        CHECK(!result.IsEmpty());
+      }
+      int gc_after = gc_count_;
+      gc_during_apply_ += gc_after - gc_before;
+      rounds++;
+    }
+    apply_success_ = true;
+  }
+
+  i::Semaphore* block_;
+  int gc_count_;
+  int gc_during_apply_;
+  bool apply_success_;
+  bool gc_success_;
+};
+
+
+// Test that nothing bad happens if we get a preemption just when we were
+// about to do an apply().
+TEST(ApplyInterruption) {
+  v8::Locker lock;
+  v8::V8::Initialize();
+  v8::HandleScope scope;
+  Local<Context> local_env;
+  {
+    LocalContext env;
+    local_env = env.local();
+  }
+
+  // Local context should still be live.
+  CHECK(!local_env.IsEmpty());
+  local_env->Enter();
+
+  // Should complete without problems.
+  ApplyInterruptTest().RunTest();
+
+  local_env->Exit();
+}
+
+
+// Verify that we can clone an object
+TEST(ObjectClone) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  const char* sample =
+    "var rv = {};"      \
+    "rv.alpha = 'hello';" \
+    "rv.beta = 123;"     \
+    "rv;";
+
+  // Create an object, verify basics.
+  Local<Value> val = CompileRun(sample);
+  CHECK(val->IsObject());
+  Local<v8::Object> obj = Local<v8::Object>::Cast(val);
+  obj->Set(v8_str("gamma"), v8_str("cloneme"));
+
+  CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
+  CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
+  CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
+
+  // Clone it.
+  Local<v8::Object> clone = obj->Clone();
+  CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
+  CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
+  CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
+
+  // Set a property on the clone, verify each object.
+  clone->Set(v8_str("beta"), v8::Integer::New(456));
+  CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
+  CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
+}
+
+
+class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
+ public:
+  explicit AsciiVectorResource(i::Vector<const char> vector)
+      : data_(vector) {}
+  virtual ~AsciiVectorResource() {}
+  virtual size_t length() const { return data_.length(); }
+  virtual const char* data() const { return data_.start(); }
+ private:
+  i::Vector<const char> data_;
+};
+
+
+class UC16VectorResource : public v8::String::ExternalStringResource {
+ public:
+  explicit UC16VectorResource(i::Vector<const i::uc16> vector)
+      : data_(vector) {}
+  virtual ~UC16VectorResource() {}
+  virtual size_t length() const { return data_.length(); }
+  virtual const i::uc16* data() const { return data_.start(); }
+ private:
+  i::Vector<const i::uc16> data_;
+};
+
+
+static void MorphAString(i::String* string,
+                         AsciiVectorResource* ascii_resource,
+                         UC16VectorResource* uc16_resource) {
+  CHECK(i::StringShape(string).IsExternal());
+  if (string->IsAsciiRepresentation()) {
+    // Check old map is not symbol or long.
+    CHECK(string->map() == i::Heap::short_external_ascii_string_map() ||
+          string->map() == i::Heap::medium_external_ascii_string_map());
+    // Morph external string to be TwoByte string.
+    if (string->length() <= i::String::kMaxShortStringSize) {
+      string->set_map(i::Heap::short_external_string_map());
+    } else {
+      string->set_map(i::Heap::medium_external_string_map());
+    }
+    i::ExternalTwoByteString* morphed =
+         i::ExternalTwoByteString::cast(string);
+    morphed->set_resource(uc16_resource);
+  } else {
+    // Check old map is not symbol or long.
+    CHECK(string->map() == i::Heap::short_external_string_map() ||
+          string->map() == i::Heap::medium_external_string_map());
+    // Morph external string to be ASCII string.
+    if (string->length() <= i::String::kMaxShortStringSize) {
+      string->set_map(i::Heap::short_external_ascii_string_map());
+    } else {
+      string->set_map(i::Heap::medium_external_ascii_string_map());
+    }
+    i::ExternalAsciiString* morphed =
+         i::ExternalAsciiString::cast(string);
+    morphed->set_resource(ascii_resource);
+  }
+}
+
+
+// Test that we can still flatten a string if the components it is built up
+// from have been turned into 16 bit strings in the mean time.
+THREADED_TEST(MorphCompositeStringTest) {
+  const char* c_string = "Now is the time for all good men"
+                         " to come to the aid of the party";
+  uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    AsciiVectorResource ascii_resource(
+        i::Vector<const char>(c_string, strlen(c_string)));
+    UC16VectorResource uc16_resource(
+        i::Vector<const uint16_t>(two_byte_string, strlen(c_string)));
+
+    Local<String> lhs(v8::Utils::ToLocal(
+        i::Factory::NewExternalStringFromAscii(&ascii_resource)));
+    Local<String> rhs(v8::Utils::ToLocal(
+        i::Factory::NewExternalStringFromAscii(&ascii_resource)));
+
+    env->Global()->Set(v8_str("lhs"), lhs);
+    env->Global()->Set(v8_str("rhs"), rhs);
+
+    CompileRun(
+        "var cons = lhs + rhs;"
+        "var slice = lhs.substring(1, lhs.length - 1);"
+        "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
+
+    MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
+    MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
+
+    // Now do some stuff to make sure the strings are flattened, etc.
+    CompileRun(
+        "/[^a-z]/.test(cons);"
+        "/[^a-z]/.test(slice);"
+        "/[^a-z]/.test(slice_on_cons);");
+    const char* expected_cons =
+        "Now is the time for all good men to come to the aid of the party"
+        "Now is the time for all good men to come to the aid of the party";
+    const char* expected_slice =
+        "ow is the time for all good men to come to the aid of the part";
+    const char* expected_slice_on_cons =
+        "ow is the time for all good men to come to the aid of the party"
+        "Now is the time for all good men to come to the aid of the part";
+    CHECK_EQ(String::New(expected_cons),
+             env->Global()->Get(v8_str("cons")));
+    CHECK_EQ(String::New(expected_slice),
+             env->Global()->Get(v8_str("slice")));
+    CHECK_EQ(String::New(expected_slice_on_cons),
+             env->Global()->Get(v8_str("slice_on_cons")));
+  }
+}
+
+
+TEST(CompileExternalTwoByteSource) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  // This is a very short list of sources, which currently is to check for a
+  // regression caused by r2703.
+  const char* ascii_sources[] = {
+    "0.5",
+    "-0.5",   // This mainly testes PushBack in the Scanner.
+    "--0.5",  // This mainly testes PushBack in the Scanner.
+    NULL
+  };
+
+  // Compile the sources as external two byte strings.
+  for (int i = 0; ascii_sources[i] != NULL; i++) {
+    uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
+    UC16VectorResource uc16_resource(
+        i::Vector<const uint16_t>(two_byte_string, strlen(ascii_sources[i])));
+    v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
+    v8::Script::Compile(source);
+  }
+}
+
+
+class RegExpStringModificationTest {
+ public:
+  RegExpStringModificationTest()
+      : block_(i::OS::CreateSemaphore(0)),
+        morphs_(0),
+        morphs_during_regexp_(0),
+        ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
+        uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
+  ~RegExpStringModificationTest() { delete block_; }
+  void RunTest() {
+    regexp_success_ = false;
+    morph_success_ = false;
+
+    // Initialize the contents of two_byte_content_ to be a uc16 representation
+    // of "aaaaaaaaaaaaaab".
+    for (int i = 0; i < 14; i++) {
+      two_byte_content_[i] = 'a';
+    }
+    two_byte_content_[14] = 'b';
+
+    // Create the input string for the regexp - the one we are going to change
+    // properties of.
+    input_ = i::Factory::NewExternalStringFromAscii(&ascii_resource_);
+
+    // Inject the input as a global variable.
+    i::Handle<i::String> input_name =
+        i::Factory::NewStringFromAscii(i::Vector<const char>("input", 5));
+    i::Top::global_context()->global()->SetProperty(*input_name, *input_, NONE);
+
+
+    MorphThread morph_thread(this);
+    morph_thread.Start();
+    v8::Locker::StartPreemption(1);
+    LongRunningRegExp();
+    {
+      v8::Unlocker unlock;
+      morph_thread.Join();
+    }
+    v8::Locker::StopPreemption();
+    CHECK(regexp_success_);
+    CHECK(morph_success_);
+  }
+ private:
+
+  // Number of string modifications required.
+  static const int kRequiredModifications = 5;
+  static const int kMaxModifications = 100;
+
+  class MorphThread : public i::Thread {
+   public:
+    explicit MorphThread(RegExpStringModificationTest* test)
+        : test_(test) {}
+    virtual void Run() {
+      test_->MorphString();
+    }
+   private:
+     RegExpStringModificationTest* test_;
+  };
+
+  void MorphString() {
+    block_->Wait();
+    while (morphs_during_regexp_ < kRequiredModifications &&
+           morphs_ < kMaxModifications) {
+      {
+        v8::Locker lock;
+        // Swap string between ascii and two-byte representation.
+        i::String* string = *input_;
+        MorphAString(string, &ascii_resource_, &uc16_resource_);
+        morphs_++;
+      }
+      i::OS::Sleep(1);
+    }
+    morph_success_ = true;
+  }
+
+  void LongRunningRegExp() {
+    block_->Signal();  // Enable morphing thread on next preemption.
+    while (morphs_during_regexp_ < kRequiredModifications &&
+           morphs_ < kMaxModifications) {
+      int morphs_before = morphs_;
+      {
+        // Match 15-30 "a"'s against 14 and a "b".
+        const char* c_source =
+            "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
+            ".exec(input) === null";
+        Local<String> source = String::New(c_source);
+        Local<Script> script = Script::Compile(source);
+        Local<Value> result = script->Run();
+        CHECK(result->IsTrue());
+      }
+      int morphs_after = morphs_;
+      morphs_during_regexp_ += morphs_after - morphs_before;
+    }
+    regexp_success_ = true;
+  }
+
+  i::uc16 two_byte_content_[15];
+  i::Semaphore* block_;
+  int morphs_;
+  int morphs_during_regexp_;
+  bool regexp_success_;
+  bool morph_success_;
+  i::Handle<i::String> input_;
+  AsciiVectorResource ascii_resource_;
+  UC16VectorResource uc16_resource_;
+};
+
+
+// Test that a regular expression execution can be interrupted and
+// the string changed without failing.
+TEST(RegExpStringModification) {
+  v8::Locker lock;
+  v8::V8::Initialize();
+  v8::HandleScope scope;
+  Local<Context> local_env;
+  {
+    LocalContext env;
+    local_env = env.local();
+  }
+
+  // Local context should still be live.
+  CHECK(!local_env.IsEmpty());
+  local_env->Enter();
+
+  // Should complete without problems.
+  RegExpStringModificationTest().RunTest();
+
+  local_env->Exit();
+}
+
+
+// Test that we can set a property on the global object even if there
+// is a read-only property in the prototype chain.
+TEST(ReadOnlyPropertyInGlobalProto) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+  LocalContext context(0, templ);
+  v8::Handle<v8::Object> global = context->Global();
+  v8::Handle<v8::Object> global_proto =
+      v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
+  global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
+  global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
+  // Check without 'eval' or 'with'.
+  v8::Handle<v8::Value> res =
+      CompileRun("function f() { x = 42; return x; }; f()");
+  // Check with 'eval'.
+  res = CompileRun("function f() { eval('1'); y = 42; return y; }; f()");
+  CHECK_EQ(v8::Integer::New(42), res);
+  // Check with 'with'.
+  res = CompileRun("function f() { with (this) { y = 42 }; return y; }; f()");
+  CHECK_EQ(v8::Integer::New(42), res);
+}
+
+static int force_set_set_count = 0;
+static int force_set_get_count = 0;
+bool pass_on_get = false;
+
+static v8::Handle<v8::Value> ForceSetGetter(v8::Local<v8::String> name,
+                                            const v8::AccessorInfo& info) {
+  force_set_get_count++;
+  if (pass_on_get) {
+    return v8::Handle<v8::Value>();
+  } else {
+    return v8::Int32::New(3);
+  }
+}
+
+static void ForceSetSetter(v8::Local<v8::String> name,
+                           v8::Local<v8::Value> value,
+                           const v8::AccessorInfo& info) {
+  force_set_set_count++;
+}
+
+static v8::Handle<v8::Value> ForceSetInterceptSetter(
+    v8::Local<v8::String> name,
+    v8::Local<v8::Value> value,
+    const v8::AccessorInfo& info) {
+  force_set_set_count++;
+  return v8::Undefined();
+}
+
+TEST(ForceSet) {
+  force_set_get_count = 0;
+  force_set_set_count = 0;
+  pass_on_get = false;
+
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+  v8::Handle<v8::String> access_property = v8::String::New("a");
+  templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
+  LocalContext context(NULL, templ);
+  v8::Handle<v8::Object> global = context->Global();
+
+  // Ordinary properties
+  v8::Handle<v8::String> simple_property = v8::String::New("p");
+  global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
+  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
+  // This should fail because the property is read-only
+  global->Set(simple_property, v8::Int32::New(5));
+  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
+  // This should succeed even though the property is read-only
+  global->ForceSet(simple_property, v8::Int32::New(6));
+  CHECK_EQ(6, global->Get(simple_property)->Int32Value());
+
+  // Accessors
+  CHECK_EQ(0, force_set_set_count);
+  CHECK_EQ(0, force_set_get_count);
+  CHECK_EQ(3, global->Get(access_property)->Int32Value());
+  // CHECK_EQ the property shouldn't override it, just call the setter
+  // which in this case does nothing.
+  global->Set(access_property, v8::Int32::New(7));
+  CHECK_EQ(3, global->Get(access_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(2, force_set_get_count);
+  // Forcing the property to be set should override the accessor without
+  // calling it
+  global->ForceSet(access_property, v8::Int32::New(8));
+  CHECK_EQ(8, global->Get(access_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(2, force_set_get_count);
+}
+
+TEST(ForceSetWithInterceptor) {
+  force_set_get_count = 0;
+  force_set_set_count = 0;
+  pass_on_get = false;
+
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
+  LocalContext context(NULL, templ);
+  v8::Handle<v8::Object> global = context->Global();
+
+  v8::Handle<v8::String> some_property = v8::String::New("a");
+  CHECK_EQ(0, force_set_set_count);
+  CHECK_EQ(0, force_set_get_count);
+  CHECK_EQ(3, global->Get(some_property)->Int32Value());
+  // Setting the property shouldn't override it, just call the setter
+  // which in this case does nothing.
+  global->Set(some_property, v8::Int32::New(7));
+  CHECK_EQ(3, global->Get(some_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(2, force_set_get_count);
+  // Getting the property when the interceptor returns an empty handle
+  // should yield undefined, since the property isn't present on the
+  // object itself yet.
+  pass_on_get = true;
+  CHECK(global->Get(some_property)->IsUndefined());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(3, force_set_get_count);
+  // Forcing the property to be set should cause the value to be
+  // set locally without calling the interceptor.
+  global->ForceSet(some_property, v8::Int32::New(8));
+  CHECK_EQ(8, global->Get(some_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(4, force_set_get_count);
+  // Reenabling the interceptor should cause it to take precedence over
+  // the property
+  pass_on_get = false;
+  CHECK_EQ(3, global->Get(some_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(5, force_set_get_count);
+  // The interceptor should also work for other properties
+  CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(6, force_set_get_count);
+}
+
+
+THREADED_TEST(ForceDelete) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+  LocalContext context(NULL, templ);
+  v8::Handle<v8::Object> global = context->Global();
+
+  // Ordinary properties
+  v8::Handle<v8::String> simple_property = v8::String::New("p");
+  global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
+  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
+  // This should fail because the property is dont-delete.
+  CHECK(!global->Delete(simple_property));
+  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
+  // This should succeed even though the property is dont-delete.
+  CHECK(global->ForceDelete(simple_property));
+  CHECK(global->Get(simple_property)->IsUndefined());
+}
+
+
+static int force_delete_interceptor_count = 0;
+static bool pass_on_delete = false;
+
+
+static v8::Handle<v8::Boolean> ForceDeleteDeleter(
+    v8::Local<v8::String> name,
+    const v8::AccessorInfo& info) {
+  force_delete_interceptor_count++;
+  if (pass_on_delete) {
+    return v8::Handle<v8::Boolean>();
+  } else {
+    return v8::True();
+  }
+}
+
+
+THREADED_TEST(ForceDeleteWithInterceptor) {
+  force_delete_interceptor_count = 0;
+  pass_on_delete = false;
+
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
+  LocalContext context(NULL, templ);
+  v8::Handle<v8::Object> global = context->Global();
+
+  v8::Handle<v8::String> some_property = v8::String::New("a");
+  global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
+
+  // Deleting a property should get intercepted and nothing should
+  // happen.
+  CHECK_EQ(0, force_delete_interceptor_count);
+  CHECK(global->Delete(some_property));
+  CHECK_EQ(1, force_delete_interceptor_count);
+  CHECK_EQ(42, global->Get(some_property)->Int32Value());
+  // Deleting the property when the interceptor returns an empty
+  // handle should not delete the property since it is DontDelete.
+  pass_on_delete = true;
+  CHECK(!global->Delete(some_property));
+  CHECK_EQ(2, force_delete_interceptor_count);
+  CHECK_EQ(42, global->Get(some_property)->Int32Value());
+  // Forcing the property to be deleted should delete the value
+  // without calling the interceptor.
+  CHECK(global->ForceDelete(some_property));
+  CHECK(global->Get(some_property)->IsUndefined());
+  CHECK_EQ(2, force_delete_interceptor_count);
+}
+
+
+// Make sure that forcing a delete invalidates any IC stubs, so we
+// don't read the hole value.
+THREADED_TEST(ForceDeleteIC) {
+  v8::HandleScope scope;
+  LocalContext context;
+  // Create a DontDelete variable on the global object.
+  CompileRun("this.__proto__ = { foo: 'horse' };"
+             "var foo = 'fish';"
+             "function f() { return foo.length; }");
+  // Initialize the IC for foo in f.
+  CompileRun("for (var i = 0; i < 4; i++) f();");
+  // Make sure the value of foo is correct before the deletion.
+  CHECK_EQ(4, CompileRun("f()")->Int32Value());
+  // Force the deletion of foo.
+  CHECK(context->Global()->ForceDelete(v8_str("foo")));
+  // Make sure the value for foo is read from the prototype, and that
+  // we don't get in trouble with reading the deleted cell value
+  // sentinel.
+  CHECK_EQ(5, CompileRun("f()")->Int32Value());
+}
+
+
+v8::Persistent<Context> calling_context0;
+v8::Persistent<Context> calling_context1;
+v8::Persistent<Context> calling_context2;
+
+
+// Check that the call to the callback is initiated in
+// calling_context2, the directly calling context is calling_context1
+// and the callback itself is in calling_context0.
+static v8::Handle<Value> GetCallingContextCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(Context::GetCurrent() == calling_context0);
+  CHECK(Context::GetCalling() == calling_context1);
+  CHECK(Context::GetEntered() == calling_context2);
+  return v8::Integer::New(42);
+}
+
+
+THREADED_TEST(GetCallingContext) {
+  v8::HandleScope scope;
+
+  calling_context0 = Context::New();
+  calling_context1 = Context::New();
+  calling_context2 = Context::New();
+
+  // Allow cross-domain access.
+  Local<String> token = v8_str("<security token>");
+  calling_context0->SetSecurityToken(token);
+  calling_context1->SetSecurityToken(token);
+  calling_context2->SetSecurityToken(token);
+
+  // Create an object with a C++ callback in context0.
+  calling_context0->Enter();
+  Local<v8::FunctionTemplate> callback_templ =
+      v8::FunctionTemplate::New(GetCallingContextCallback);
+  calling_context0->Global()->Set(v8_str("callback"),
+                                  callback_templ->GetFunction());
+  calling_context0->Exit();
+
+  // Expose context0 in context1 and setup a function that calls the
+  // callback function.
+  calling_context1->Enter();
+  calling_context1->Global()->Set(v8_str("context0"),
+                                  calling_context0->Global());
+  CompileRun("function f() { context0.callback() }");
+  calling_context1->Exit();
+
+  // Expose context1 in context2 and call the callback function in
+  // context0 indirectly through f in context1.
+  calling_context2->Enter();
+  calling_context2->Global()->Set(v8_str("context1"),
+                                  calling_context1->Global());
+  CompileRun("context1.f()");
+  calling_context2->Exit();
+
+  // Dispose the contexts to allow them to be garbage collected.
+  calling_context0.Dispose();
+  calling_context1.Dispose();
+  calling_context2.Dispose();
+  calling_context0.Clear();
+  calling_context1.Clear();
+  calling_context2.Clear();
+}
+
+
+// Check that a variable declaration with no explicit initialization
+// value does not shadow an existing property in the prototype chain.
+//
+// This is consistent with Firefox and Safari.
+//
+// See http://crbug.com/12548.
+THREADED_TEST(InitGlobalVarInProtoChain) {
+  v8::HandleScope scope;
+  LocalContext context;
+  // Introduce a variable in the prototype chain.
+  CompileRun("__proto__.x = 42");
+  v8::Handle<v8::Value> result = CompileRun("var x; x");
+  CHECK(!result->IsUndefined());
+  CHECK_EQ(42, result->Int32Value());
+}
+
+
+// Regression test for issue 398.
+// If a function is added to an object, creating a constant function
+// field, and the result is cloned, replacing the constant function on the
+// original should not affect the clone.
+// See http://code.google.com/p/v8/issues/detail?id=398
+THREADED_TEST(ReplaceConstantFunction) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::Object> obj = v8::Object::New();
+  v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
+  v8::Handle<v8::String> foo_string = v8::String::New("foo");
+  obj->Set(foo_string, func_templ->GetFunction());
+  v8::Handle<v8::Object> obj_clone = obj->Clone();
+  obj_clone->Set(foo_string, v8::String::New("Hello"));
+  CHECK(!obj->Get(foo_string)->IsUndefined());
+}
+
+
+// Regression test for http://crbug.com/16276.
+THREADED_TEST(Regress16276) {
+  v8::HandleScope scope;
+  LocalContext context;
+  // Force the IC in f to be a dictionary load IC.
+  CompileRun("function f(obj) { return obj.x; }\n"
+             "var obj = { x: { foo: 42 }, y: 87 };\n"
+             "var x = obj.x;\n"
+             "delete obj.y;\n"
+             "for (var i = 0; i < 5; i++) f(obj);");
+  // Detach the global object to make 'this' refer directly to the
+  // global object (not the proxy), and make sure that the dictionary
+  // load IC doesn't mess up loading directly from the global object.
+  context->DetachGlobal();
+  CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
+}
+
+
+THREADED_TEST(PixelArray) {
+  v8::HandleScope scope;
+  LocalContext context;
+  const int kElementCount = 40;
+  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
+  i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(kElementCount,
+                                                              pixel_data);
+  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+  for (int i = 0; i < kElementCount; i++) {
+    pixels->set(i, i);
+  }
+  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+  for (int i = 0; i < kElementCount; i++) {
+    CHECK_EQ(i, pixels->get(i));
+    CHECK_EQ(i, pixel_data[i]);
+  }
+
+  v8::Handle<v8::Object> obj = v8::Object::New();
+  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
+  // Set the elements to be the pixels.
+  // jsobj->set_elements(*pixels);
+  obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
+  CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1))->value());
+  obj->Set(v8_str("field"), v8::Int32::New(1503));
+  context->Global()->Set(v8_str("pixels"), obj);
+  v8::Handle<v8::Value> result = CompileRun("pixels.field");
+  CHECK_EQ(1503, result->Int32Value());
+  result = CompileRun("pixels[1]");
+  CHECK_EQ(1, result->Int32Value());
+
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += pixels[i] = pixels[i] = -i;"
+                      "}"
+                      "sum;");
+  CHECK_EQ(-28, result->Int32Value());
+
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += pixels[i] = pixels[i] = 0;"
+                      "}"
+                      "sum;");
+  CHECK_EQ(0, result->Int32Value());
+
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += pixels[i] = pixels[i] = 255;"
+                      "}"
+                      "sum;");
+  CHECK_EQ(8 * 255, result->Int32Value());
+
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += pixels[i] = pixels[i] = 256 + i;"
+                      "}"
+                      "sum;");
+  CHECK_EQ(2076, result->Int32Value());
+
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += pixels[i] = pixels[i] = i;"
+                      "}"
+                      "sum;");
+  CHECK_EQ(28, result->Int32Value());
+
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += pixels[i];"
+                      "}"
+                      "sum;");
+  CHECK_EQ(28, result->Int32Value());
+
+  i::Handle<i::Smi> value(i::Smi::FromInt(2));
+  i::SetElement(jsobj, 1, value);
+  CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1))->value());
+  *value.location() = i::Smi::FromInt(256);
+  i::SetElement(jsobj, 1, value);
+  CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(1))->value());
+  *value.location() = i::Smi::FromInt(-1);
+  i::SetElement(jsobj, 1, value);
+  CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1))->value());
+
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  pixels[i] = (i * 65) - 109;"
+                      "}"
+                      "pixels[1] + pixels[6];");
+  CHECK_EQ(255, result->Int32Value());
+  CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0))->value());
+  CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1))->value());
+  CHECK_EQ(21, i::Smi::cast(jsobj->GetElement(2))->value());
+  CHECK_EQ(86, i::Smi::cast(jsobj->GetElement(3))->value());
+  CHECK_EQ(151, i::Smi::cast(jsobj->GetElement(4))->value());
+  CHECK_EQ(216, i::Smi::cast(jsobj->GetElement(5))->value());
+  CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(6))->value());
+  CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(7))->value());
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += pixels[i];"
+                      "}"
+                      "sum;");
+  CHECK_EQ(984, result->Int32Value());
+
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  pixels[i] = (i * 1.1);"
+                      "}"
+                      "pixels[1] + pixels[6];");
+  CHECK_EQ(8, result->Int32Value());
+  CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0))->value());
+  CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1))->value());
+  CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2))->value());
+  CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3))->value());
+  CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4))->value());
+  CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5))->value());
+  CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6))->value());
+  CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7))->value());
+
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  pixels[7] = undefined;"
+                      "}"
+                      "pixels[7];");
+  CHECK_EQ(0, result->Int32Value());
+  CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7))->value());
+
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  pixels[6] = '2.3';"
+                      "}"
+                      "pixels[6];");
+  CHECK_EQ(2, result->Int32Value());
+  CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6))->value());
+
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  pixels[5] = NaN;"
+                      "}"
+                      "pixels[5];");
+  CHECK_EQ(0, result->Int32Value());
+  CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value());
+
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  pixels[8] = Infinity;"
+                      "}"
+                      "pixels[8];");
+  CHECK_EQ(255, result->Int32Value());
+  CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(8))->value());
+
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  pixels[9] = -Infinity;"
+                      "}"
+                      "pixels[9];");
+  CHECK_EQ(0, result->Int32Value());
+  CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9))->value());
+
+  result = CompileRun("pixels[3] = 33;"
+                      "delete pixels[3];"
+                      "pixels[3];");
+  CHECK_EQ(33, result->Int32Value());
+
+  result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
+                      "pixels[2] = 12; pixels[3] = 13;"
+                      "pixels.__defineGetter__('2',"
+                      "function() { return 120; });"
+                      "pixels[2];");
+  CHECK_EQ(12, result->Int32Value());
+
+  result = CompileRun("var js_array = new Array(40);"
+                      "js_array[0] = 77;"
+                      "js_array;");
+  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
+
+  result = CompileRun("pixels[1] = 23;"
+                      "pixels.__proto__ = [];"
+                      "js_array.__proto__ = pixels;"
+                      "js_array.concat(pixels);");
+  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
+  CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
+
+  result = CompileRun("pixels[1] = 23;");
+  CHECK_EQ(23, result->Int32Value());
+
+  free(pixel_data);
+}
+
+
+THREADED_TEST(ScriptContextDependence) {
+  v8::HandleScope scope;
+  LocalContext c1;
+  const char *source = "foo";
+  v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
+  v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
+  c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
+  CHECK_EQ(dep->Run()->Int32Value(), 100);
+  CHECK_EQ(indep->Run()->Int32Value(), 100);
+  LocalContext c2;
+  c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
+  CHECK_EQ(dep->Run()->Int32Value(), 100);
+  CHECK_EQ(indep->Run()->Int32Value(), 101);
+}
+
+
+THREADED_TEST(StackTrace) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  const char *source = "function foo() { FAIL.FAIL; }; foo();";
+  v8::Handle<v8::String> src = v8::String::New(source);
+  v8::Handle<v8::String> origin = v8::String::New("stack-trace-test");
+  v8::Script::New(src, origin)->Run();
+  CHECK(try_catch.HasCaught());
+  v8::String::Utf8Value stack(try_catch.StackTrace());
+  CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
+}
+
+
+// Test that idle notification can be handled when V8 has not yet been
+// set up.
+THREADED_TEST(IdleNotification) {
+  for (int i = 0; i < 100; i++) v8::V8::IdleNotification(true);
+  for (int i = 0; i < 100; i++) v8::V8::IdleNotification(false);
+}
+
+
+static uint32_t* stack_limit;
+
+static v8::Handle<Value> GetStackLimitCallback(const v8::Arguments& args) {
+  stack_limit = reinterpret_cast<uint32_t*>(i::StackGuard::climit());
+  return v8::Undefined();
+}
+
+
+// Uses the address of a local variable to determine the stack top now.
+// Given a size, returns an address that is that far from the current
+// top of stack.
+static uint32_t* ComputeStackLimit(uint32_t size) {
+  uint32_t* answer = &size - (size / sizeof(size));
+  // If the size is very large and the stack is very near the bottom of
+  // memory then the calculation above may wrap around and give an address
+  // that is above the (downwards-growing) stack.  In that case we return
+  // a very low address.
+  if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
+  return answer;
+}
+
+
+TEST(SetResourceConstraints) {
+  static const int K = 1024;
+  uint32_t* set_limit = ComputeStackLimit(128 * K);
+
+  // Set stack limit.
+  v8::ResourceConstraints constraints;
+  constraints.set_stack_limit(set_limit);
+  CHECK(v8::SetResourceConstraints(&constraints));
+
+  // Execute a script.
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(GetStackLimitCallback);
+  Local<Function> fun = fun_templ->GetFunction();
+  env->Global()->Set(v8_str("get_stack_limit"), fun);
+  CompileRun("get_stack_limit();");
+
+  CHECK(stack_limit == set_limit);
+}
+
+
+TEST(SetResourceConstraintsInThread) {
+  uint32_t* set_limit;
+  {
+    v8::Locker locker;
+    static const int K = 1024;
+    set_limit = ComputeStackLimit(128 * K);
+
+    // Set stack limit.
+    v8::ResourceConstraints constraints;
+    constraints.set_stack_limit(set_limit);
+    CHECK(v8::SetResourceConstraints(&constraints));
+
+    // Execute a script.
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(GetStackLimitCallback);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("get_stack_limit"), fun);
+    CompileRun("get_stack_limit();");
+
+    CHECK(stack_limit == set_limit);
+  }
+  {
+    v8::Locker locker;
+    CHECK(stack_limit == set_limit);
+  }
+}