deps: backport 1ee712a from V8 upstream
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-api.cc
index e586127..88d4aef 100644 (file)
 
 #include <climits>
 #include <csignal>
-#include <string>
 #include <map>
+#include <string>
 
-#include "v8.h"
+#include "test/cctest/test-api.h"
 
 #if V8_OS_POSIX
 #include <unistd.h>  // NOLINT
 #endif
 
-#include "api.h"
-#include "arguments.h"
-#include "cctest.h"
-#include "compilation-cache.h"
-#include "cpu-profiler.h"
-#include "execution.h"
-#include "isolate.h"
-#include "objects.h"
-#include "parser.h"
-#include "platform.h"
-#include "snapshot.h"
-#include "unicode-inl.h"
-#include "utils.h"
-#include "vm-state.h"
+#include "include/v8-util.h"
+#include "src/api.h"
+#include "src/arguments.h"
+#include "src/base/platform/platform.h"
+#include "src/compilation-cache.h"
+#include "src/debug.h"
+#include "src/execution.h"
+#include "src/objects.h"
+#include "src/parser.h"
+#include "src/smart-pointers.h"
+#include "src/unicode-inl.h"
+#include "src/utils.h"
+#include "src/vm-state.h"
 
 static const bool kLogThreading = false;
 
@@ -62,14 +61,19 @@ using ::v8::FunctionTemplate;
 using ::v8::Handle;
 using ::v8::HandleScope;
 using ::v8::Local;
+using ::v8::Maybe;
 using ::v8::Message;
 using ::v8::MessageCallback;
+using ::v8::Name;
+using ::v8::None;
 using ::v8::Object;
 using ::v8::ObjectTemplate;
 using ::v8::Persistent;
+using ::v8::PropertyAttribute;
 using ::v8::Script;
 using ::v8::StackTrace;
 using ::v8::String;
+using ::v8::Symbol;
 using ::v8::TryCatch;
 using ::v8::Undefined;
 using ::v8::UniqueId;
@@ -92,64 +96,20 @@ void RunWithProfiler(void (*test)()) {
       v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
 
-  cpu_profiler->StartCpuProfiling(profile_name);
+  cpu_profiler->StartProfiling(profile_name);
   (*test)();
   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
 }
 
 
-static void ExpectString(const char* code, const char* expected) {
-  Local<Value> result = CompileRun(code);
-  CHECK(result->IsString());
-  String::Utf8Value utf8(result);
-  CHECK_EQ(expected, *utf8);
-}
-
-
-static void ExpectInt32(const char* code, int expected) {
-  Local<Value> result = CompileRun(code);
-  CHECK(result->IsInt32());
-  CHECK_EQ(expected, result->Int32Value());
-}
-
-
-static void ExpectBoolean(const char* code, bool expected) {
-  Local<Value> result = CompileRun(code);
-  CHECK(result->IsBoolean());
-  CHECK_EQ(expected, result->BooleanValue());
-}
-
-
-static void ExpectTrue(const char* code) {
-  ExpectBoolean(code, true);
-}
-
-
-static void ExpectFalse(const char* code) {
-  ExpectBoolean(code, false);
-}
-
-
-static void ExpectObject(const char* code, Local<Value> expected) {
-  Local<Value> result = CompileRun(code);
-  CHECK(result->Equals(expected));
-}
-
-
-static void ExpectUndefined(const char* code) {
-  Local<Value> result = CompileRun(code);
-  CHECK(result->IsUndefined());
-}
-
-
 static int signature_callback_count;
 static Local<Value> signature_expected_receiver;
 static void IncrementingSignatureCallback(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
   signature_callback_count++;
-  CHECK_EQ(signature_expected_receiver, args.Holder());
-  CHECK_EQ(signature_expected_receiver, args.This());
+  CHECK(signature_expected_receiver->Equals(args.Holder()));
+  CHECK(signature_expected_receiver->Equals(args.This()));
   v8::Handle<v8::Array> result =
       v8::Array::New(args.GetIsolate(), args.Length());
   for (int i = 0; i < args.Length(); i++)
@@ -158,32 +118,24 @@ static void IncrementingSignatureCallback(
 }
 
 
-static void SignatureCallback(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-  v8::Handle<v8::Array> result =
-      v8::Array::New(args.GetIsolate(), args.Length());
-  for (int i = 0; i < args.Length(); i++) {
-    result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
-  }
-  args.GetReturnValue().Set(result);
+static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(42);
 }
 
 
 // Tests that call v8::V8::Dispose() cannot be threaded.
-TEST(InitializeAndDisposeOnce) {
+UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
   CHECK(v8::V8::Initialize());
   CHECK(v8::V8::Dispose());
 }
 
 
 // Tests that call v8::V8::Dispose() cannot be threaded.
-TEST(InitializeAndDisposeMultiple) {
+UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
-  // TODO(mstarzinger): This should fail gracefully instead of asserting.
-  // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
+  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
 }
 
@@ -204,9 +156,8 @@ THREADED_TEST(Handles) {
   CHECK(!undef.IsEmpty());
   CHECK(undef->IsUndefined());
 
-  const char* c_source = "1 + 2 + 3";
-  Local<String> source = String::NewFromUtf8(CcTest::isolate(), c_source);
-  Local<Script> script = Script::Compile(source);
+  const char* source = "1 + 2 + 3";
+  Local<Script> script = v8_compile(source);
   CHECK_EQ(6, script->Run()->Int32Value());
 
   local_env->Exit();
@@ -228,24 +179,25 @@ THREADED_TEST(IsolateOfContext) {
 }
 
 
-static void TestSignature(const char* loop_js, Local<Value> receiver) {
+static void TestSignature(const char* loop_js, Local<Value> receiver,
+                          v8::Isolate* isolate) {
   i::ScopedVector<char> source(200);
-  i::OS::SNPrintF(source,
-                  "for (var i = 0; i < 10; i++) {"
-                  "  %s"
-                  "}",
-                  loop_js);
+  i::SNPrintF(source,
+              "for (var i = 0; i < 10; i++) {"
+              "  %s"
+              "}",
+              loop_js);
   signature_callback_count = 0;
   signature_expected_receiver = receiver;
   bool expected_to_throw = receiver.IsEmpty();
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
   CompileRun(source.start());
   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
   if (!expected_to_throw) {
     CHECK_EQ(10, signature_callback_count);
   } else {
-    CHECK_EQ(v8_str("TypeError: Illegal invocation"),
-             try_catch.Exception()->ToString());
+    CHECK(v8_str("TypeError: Illegal invocation")
+              ->Equals(try_catch.Exception()->ToString(isolate)));
   }
 }
 
@@ -305,101 +257,32 @@ THREADED_TEST(ReceiverSignature) {
   const char* test_objects[] = {
       "fun_instance", "sub_fun_instance", "obj", "unrel" };
   unsigned bad_signature_start_offset = 2;
-  for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
+  for (unsigned i = 0; i < arraysize(test_objects); i++) {
     i::ScopedVector<char> source(200);
-    i::OS::SNPrintF(
+    i::SNPrintF(
         source, "var test_object = %s; test_object", test_objects[i]);
     Local<Value> test_object = CompileRun(source.start());
-    TestSignature("test_object.prop();", test_object);
-    TestSignature("test_object.accessor;", test_object);
-    TestSignature("test_object[accessor_key];", test_object);
-    TestSignature("test_object.accessor = 1;", test_object);
-    TestSignature("test_object[accessor_key] = 1;", test_object);
+    TestSignature("test_object.prop();", test_object, isolate);
+    TestSignature("test_object.accessor;", test_object, isolate);
+    TestSignature("test_object[accessor_key];", test_object, isolate);
+    TestSignature("test_object.accessor = 1;", test_object, isolate);
+    TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
     if (i >= bad_signature_start_offset) test_object = Local<Value>();
-    TestSignature("test_object.prop_sig();", test_object);
-    TestSignature("test_object.accessor_sig;", test_object);
-    TestSignature("test_object[accessor_sig_key];", test_object);
-    TestSignature("test_object.accessor_sig = 1;", test_object);
-    TestSignature("test_object[accessor_sig_key] = 1;", test_object);
+    TestSignature("test_object.prop_sig();", test_object, isolate);
+    TestSignature("test_object.accessor_sig;", test_object, isolate);
+    TestSignature("test_object[accessor_sig_key];", test_object, isolate);
+    TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
+    TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
   }
 }
 
 
-THREADED_TEST(ArgumentSignature) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New(isolate);
-  cons->SetClassName(v8_str("Cons"));
-  v8::Handle<v8::Signature> sig = v8::Signature::New(
-      isolate, v8::Handle<v8::FunctionTemplate>(), 1, &cons);
-  v8::Handle<v8::FunctionTemplate> fun =
-      v8::FunctionTemplate::New(isolate,
-                                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(isolate);
-  cons1->SetClassName(v8_str("Cons1"));
-  v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New(isolate);
-  cons2->SetClassName(v8_str("Cons2"));
-  v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New(isolate);
-  cons3->SetClassName(v8_str("Cons3"));
-
-  v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
-  v8::Handle<v8::Signature> wsig = v8::Signature::New(
-      isolate, v8::Handle<v8::FunctionTemplate>(), 3, args);
-  v8::Handle<v8::FunctionTemplate> fun2 =
-      v8::FunctionTemplate::New(isolate,
-                                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) {
   LocalContext env;
   v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
   v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
-  Local<String> undef_str = undef->ToString();
+  Local<String> undef_str = undef->ToString(isolate);
   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
   undef_str->WriteUtf8(value);
   CHECK_EQ(0, strcmp(value, "undefined"));
@@ -419,7 +302,7 @@ THREADED_TEST(Access) {
   Local<Value> foo_after = obj->Get(v8_str("foo"));
   CHECK(!foo_after->IsUndefined());
   CHECK(foo_after->IsString());
-  CHECK_EQ(bar_str, foo_after);
+  CHECK(bar_str->Equals(foo_after));
 }
 
 
@@ -434,35 +317,27 @@ THREADED_TEST(AccessElement) {
   Local<Value> after = obj->Get(1);
   CHECK(!after->IsUndefined());
   CHECK(after->IsString());
-  CHECK_EQ(bar_str, after);
+  CHECK(bar_str->Equals(after));
 
   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
-  CHECK_EQ(v8_str("a"), value->Get(0));
-  CHECK_EQ(v8_str("b"), value->Get(1));
+  CHECK(v8_str("a")->Equals(value->Get(0)));
+  CHECK(v8_str("b")->Equals(value->Get(1)));
 }
 
 
 THREADED_TEST(Script) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
-  const char* c_source = "1 + 2 + 3";
-  Local<String> source = String::NewFromUtf8(env->GetIsolate(), c_source);
-  Local<Script> script = Script::Compile(source);
+  const char* source = "1 + 2 + 3";
+  Local<Script> script = v8_compile(source);
   CHECK_EQ(6, script->Run()->Int32Value());
 }
 
 
-static uint16_t* AsciiToTwoByteString(const char* source) {
-  int array_length = i::StrLength(source) + 1;
-  uint16_t* converted = i::NewArray<uint16_t>(array_length);
-  for (int i = 0; i < array_length; i++) converted[i] = source[i];
-  return converted;
-}
-
-
 class TestResource: public String::ExternalStringResource {
  public:
-  TestResource(uint16_t* data, int* counter = NULL, bool owning_data = true)
+  explicit TestResource(uint16_t* data, int* counter = NULL,
+                        bool owning_data = true)
       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
     while (data[length_]) ++length_;
   }
@@ -488,15 +363,16 @@ class TestResource: public String::ExternalStringResource {
 };
 
 
-class TestAsciiResource: public String::ExternalAsciiStringResource {
+class TestOneByteResource : public String::ExternalOneByteStringResource {
  public:
-  TestAsciiResource(const char* data, int* counter = NULL, size_t offset = 0)
+  explicit TestOneByteResource(const char* data, int* counter = NULL,
+                               size_t offset = 0)
       : orig_data_(data),
         data_(data + offset),
         length_(strlen(data) - offset),
-        counter_(counter) { }
+        counter_(counter) {}
 
-  ~TestAsciiResource() {
+  ~TestOneByteResource() {
     i::DeleteArray(orig_data_);
     if (counter_ != NULL) ++*counter_;
   }
@@ -526,7 +402,7 @@ THREADED_TEST(ScriptUsingStringResource) {
     v8::HandleScope scope(env->GetIsolate());
     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
-    Local<Script> script = Script::Compile(source);
+    Local<Script> script = v8_compile(source);
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
@@ -537,7 +413,7 @@ THREADED_TEST(ScriptUsingStringResource) {
     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
              source->GetExternalStringResourceBase(&encoding));
     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
-    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+    CcTest::heap()->CollectAllGarbage();
     CHECK_EQ(0, dispose_count);
   }
   CcTest::i_isolate()->compilation_cache()->Clear();
@@ -546,27 +422,27 @@ THREADED_TEST(ScriptUsingStringResource) {
 }
 
 
-THREADED_TEST(ScriptUsingAsciiStringResource) {
+THREADED_TEST(ScriptUsingOneByteStringResource) {
   int dispose_count = 0;
   const char* c_source = "1 + 2 * 3";
   {
     LocalContext env;
     v8::HandleScope scope(env->GetIsolate());
-    TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
-                                                        &dispose_count);
+    TestOneByteResource* resource =
+        new TestOneByteResource(i::StrDup(c_source), &dispose_count);
     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
-    CHECK(source->IsExternalAscii());
+    CHECK(source->IsExternalOneByte());
     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
-             source->GetExternalAsciiStringResource());
+             source->GetExternalOneByteStringResource());
     String::Encoding encoding = String::UNKNOWN_ENCODING;
     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
              source->GetExternalStringResourceBase(&encoding));
-    CHECK_EQ(String::ASCII_ENCODING, encoding);
-    Local<Script> script = Script::Compile(source);
+    CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
+    Local<Script> script = v8_compile(source);
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+    CcTest::heap()->CollectAllGarbage();
     CHECK_EQ(0, dispose_count);
   }
   CcTest::i_isolate()->compilation_cache()->Clear();
@@ -587,27 +463,27 @@ THREADED_TEST(ScriptMakingExternalString) {
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
     CHECK_EQ(source->IsExternal(), false);
-    CHECK_EQ(source->IsExternalAscii(), false);
+    CHECK_EQ(source->IsExternalOneByte(), false);
     String::Encoding encoding = String::UNKNOWN_ENCODING;
-    CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
-    CHECK_EQ(String::ASCII_ENCODING, encoding);
+    CHECK(!source->GetExternalStringResourceBase(&encoding));
+    CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
     bool success = source->MakeExternal(new TestResource(two_byte_source,
                                                          &dispose_count));
     CHECK(success);
-    Local<Script> script = Script::Compile(source);
+    Local<Script> script = v8_compile(source);
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+    CcTest::heap()->CollectAllGarbage();
     CHECK_EQ(0, dispose_count);
   }
   CcTest::i_isolate()->compilation_cache()->Clear();
-  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  CcTest::heap()->CollectAllGarbage();
   CHECK_EQ(1, dispose_count);
 }
 
 
-THREADED_TEST(ScriptMakingExternalAsciiString) {
+THREADED_TEST(ScriptMakingExternalOneByteString) {
   int dispose_count = 0;
   const char* c_source = "1 + 2 * 3";
   {
@@ -618,17 +494,17 @@ THREADED_TEST(ScriptMakingExternalAsciiString) {
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
     bool success = source->MakeExternal(
-        new TestAsciiResource(i::StrDup(c_source), &dispose_count));
+        new TestOneByteResource(i::StrDup(c_source), &dispose_count));
     CHECK(success);
-    Local<Script> script = Script::Compile(source);
+    Local<Script> script = v8_compile(source);
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+    CcTest::heap()->CollectAllGarbage();
     CHECK_EQ(0, dispose_count);
   }
   CcTest::i_isolate()->compilation_cache()->Clear();
-  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  CcTest::heap()->CollectAllGarbage();
   CHECK_EQ(1, dispose_count);
 }
 
@@ -681,7 +557,7 @@ TEST(MakingExternalStringConditions) {
 }
 
 
-TEST(MakingExternalAsciiStringConditions) {
+TEST(MakingExternalOneByteStringConditions) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -718,7 +594,7 @@ TEST(MakingExternalAsciiStringConditions) {
 }
 
 
-TEST(MakingExternalUnalignedAsciiString) {
+TEST(MakingExternalUnalignedOneByteString) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -732,22 +608,22 @@ TEST(MakingExternalUnalignedAsciiString) {
       "slice('abcdefghijklmnopqrstuvwxyz');"));
 
   // Trigger GCs so that the newly allocated string moves to old gen.
-  SimulateFullSpace(CcTest::heap()->old_pointer_space());
+  SimulateFullSpace(CcTest::heap()->old_space());
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
 
   // Turn into external string with unaligned resource data.
   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
-  bool success = cons->MakeExternal(
-      new TestAsciiResource(i::StrDup(c_cons), NULL, 1));
+  bool success =
+      cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
   CHECK(success);
   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
-  success = slice->MakeExternal(
-      new TestAsciiResource(i::StrDup(c_slice), NULL, 1));
+  success =
+      slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
   CHECK(success);
 
   // Trigger GCs and force evacuation.
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
 }
 
@@ -764,31 +640,78 @@ THREADED_TEST(UsingExternalString) {
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
     i::Handle<i::String> isymbol =
-        factory->InternalizedStringFromString(istring);
+        factory->InternalizeString(istring);
     CHECK(isymbol->IsInternalizedString());
   }
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
+  CcTest::heap()->CollectAllGarbage();
 }
 
 
-THREADED_TEST(UsingExternalAsciiString) {
+THREADED_TEST(UsingExternalOneByteString) {
   i::Factory* factory = CcTest::i_isolate()->factory();
   {
     v8::HandleScope scope(CcTest::isolate());
     const char* one_byte_string = "test string";
     Local<String> string = String::NewExternal(
-        CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string)));
+        CcTest::isolate(), new TestOneByteResource(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.
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
     i::Handle<i::String> isymbol =
-        factory->InternalizedStringFromString(istring);
+        factory->InternalizeString(istring);
     CHECK(isymbol->IsInternalizedString());
   }
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
+  CcTest::heap()->CollectAllGarbage();
+}
+
+
+class RandomLengthResource : public v8::String::ExternalStringResource {
+ public:
+  explicit RandomLengthResource(int length) : length_(length) {}
+  virtual const uint16_t* data() const { return string_; }
+  virtual size_t length() const { return length_; }
+
+ private:
+  uint16_t string_[10];
+  int length_;
+};
+
+
+class RandomLengthOneByteResource
+    : public v8::String::ExternalOneByteStringResource {
+ public:
+  explicit RandomLengthOneByteResource(int length) : length_(length) {}
+  virtual const char* data() const { return string_; }
+  virtual size_t length() const { return length_; }
+
+ private:
+  char string_[10];
+  int length_;
+};
+
+
+THREADED_TEST(NewExternalForVeryLongString) {
+  auto isolate = CcTest::isolate();
+  {
+    v8::HandleScope scope(isolate);
+    v8::TryCatch try_catch(isolate);
+    RandomLengthOneByteResource r(1 << 30);
+    v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
+    CHECK(str.IsEmpty());
+    CHECK(!try_catch.HasCaught());
+  }
+
+  {
+    v8::HandleScope scope(isolate);
+    v8::TryCatch try_catch(isolate);
+    RandomLengthResource r(1 << 30);
+    v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
+    CHECK(str.IsEmpty());
+    CHECK(!try_catch.HasCaught());
+  }
 }
 
 
@@ -805,16 +728,15 @@ THREADED_TEST(ScavengeExternalString) {
     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
     in_new_space = CcTest::heap()->InNewSpace(*istring);
-    CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
+    CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
     CHECK_EQ(0, dispose_count);
   }
-  CcTest::heap()->CollectGarbage(
-      in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
+  CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
   CHECK_EQ(1, dispose_count);
 }
 
 
-THREADED_TEST(ScavengeExternalAsciiString) {
+THREADED_TEST(ScavengeExternalOneByteString) {
   i::FLAG_stress_compaction = false;
   i::FLAG_gc_global = false;
   int dispose_count = 0;
@@ -824,28 +746,26 @@ THREADED_TEST(ScavengeExternalAsciiString) {
     const char* one_byte_string = "test string";
     Local<String> string = String::NewExternal(
         CcTest::isolate(),
-        new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
+        new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count));
     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
     in_new_space = CcTest::heap()->InNewSpace(*istring);
-    CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
+    CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
     CHECK_EQ(0, dispose_count);
   }
-  CcTest::heap()->CollectGarbage(
-      in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
+  CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
   CHECK_EQ(1, dispose_count);
 }
 
 
-class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
+class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
  public:
   // Only used by non-threaded tests, so it can use static fields.
   static int dispose_calls;
   static int dispose_count;
 
-  TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
-      : TestAsciiResource(data, &dispose_count),
-        dispose_(dispose) { }
+  TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
+      : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
 
   void Dispose() {
     ++dispose_calls;
@@ -856,53 +776,53 @@ class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
 };
 
 
-int TestAsciiResourceWithDisposeControl::dispose_count = 0;
-int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
+int TestOneByteResourceWithDisposeControl::dispose_count = 0;
+int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
 
 
 TEST(ExternalStringWithDisposeHandling) {
   const char* c_source = "1 + 2 * 3";
 
   // Use a stack allocated external string resource allocated object.
-  TestAsciiResourceWithDisposeControl::dispose_count = 0;
-  TestAsciiResourceWithDisposeControl::dispose_calls = 0;
-  TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
+  TestOneByteResourceWithDisposeControl::dispose_count = 0;
+  TestOneByteResourceWithDisposeControl::dispose_calls = 0;
+  TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
   {
     LocalContext env;
     v8::HandleScope scope(env->GetIsolate());
     Local<String> source =  String::NewExternal(env->GetIsolate(), &res_stack);
-    Local<Script> script = Script::Compile(source);
+    Local<Script> script = v8_compile(source);
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
     CcTest::heap()->CollectAllAvailableGarbage();
-    CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
+    CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
   }
   CcTest::i_isolate()->compilation_cache()->Clear();
   CcTest::heap()->CollectAllAvailableGarbage();
-  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
-  CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
+  CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
+  CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
 
   // Use a heap allocated external string resource allocated object.
-  TestAsciiResourceWithDisposeControl::dispose_count = 0;
-  TestAsciiResourceWithDisposeControl::dispose_calls = 0;
-  TestAsciiResource* res_heap =
-      new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
+  TestOneByteResourceWithDisposeControl::dispose_count = 0;
+  TestOneByteResourceWithDisposeControl::dispose_calls = 0;
+  TestOneByteResource* res_heap =
+      new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
   {
     LocalContext env;
     v8::HandleScope scope(env->GetIsolate());
     Local<String> source =  String::NewExternal(env->GetIsolate(), res_heap);
-    Local<Script> script = Script::Compile(source);
+    Local<Script> script = v8_compile(source);
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
     CcTest::heap()->CollectAllAvailableGarbage();
-    CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
+    CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
   }
   CcTest::i_isolate()->compilation_cache()->Clear();
   CcTest::heap()->CollectAllAvailableGarbage();
-  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
-  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
+  CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
+  CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
 }
 
 
@@ -926,7 +846,8 @@ THREADED_TEST(StringConcat) {
 
     Local<String> source = String::Concat(left, right);
     right = String::NewExternal(
-        env->GetIsolate(), new TestAsciiResource(i::StrDup(one_byte_extern_1)));
+        env->GetIsolate(),
+        new TestOneByteResource(i::StrDup(one_byte_extern_1)));
     source = String::Concat(source, right);
     right = String::NewExternal(
         env->GetIsolate(),
@@ -944,14 +865,14 @@ THREADED_TEST(StringConcat) {
         env->GetIsolate(),
         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
     source = String::Concat(source, right);
-    Local<Script> script = Script::Compile(source);
+    Local<Script> script = v8_compile(source);
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(68, value->Int32Value());
   }
   CcTest::i_isolate()->compilation_cache()->Clear();
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
+  CcTest::heap()->CollectAllGarbage();
 }
 
 
@@ -965,32 +886,6 @@ THREADED_TEST(GlobalProperties) {
 }
 
 
-template<typename T>
-static void CheckReturnValue(const T& t, i::Address callback) {
-  v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
-  i::Object** o = *reinterpret_cast<i::Object***>(&rv);
-  CHECK_EQ(CcTest::isolate(), t.GetIsolate());
-  CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
-  CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
-  // Verify reset
-  bool is_runtime = (*o)->IsTheHole();
-  rv.Set(true);
-  CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
-  rv.Set(v8::Handle<v8::Object>());
-  CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
-  CHECK_EQ(is_runtime, (*o)->IsTheHole());
-
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
-  // If CPU profiler is active check that when API callback is invoked
-  // VMState is set to EXTERNAL.
-  if (isolate->cpu_profiler()->is_profiling()) {
-    CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
-    CHECK(isolate->external_callback_scope());
-    CHECK_EQ(callback, isolate->external_callback_scope()->callback());
-  }
-}
-
-
 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
                                  i::Address callback) {
   ApiTestFuzzer::Fuzz();
@@ -1079,7 +974,7 @@ static void TestFunctionTemplateAccessor(Constructor constructor,
   Local<Function> fun = fun_templ->GetFunction();
   env->Global()->Set(v8_str("obj"), fun);
   Local<Value> result = v8_compile("(new obj()).toString()")->Run();
-  CHECK_EQ(v8_str("[object funky]"), result);
+  CHECK(v8_str("[object funky]")->Equals(result));
   CompileRun("var obj_instance = new obj();");
   Local<Script> script;
   script = v8_compile("obj_instance.x");
@@ -1231,14 +1126,15 @@ Handle<Value> TestFastReturnValues() {
 
 THREADED_PROFILED_TEST(FastReturnValues) {
   LocalContext env;
-  v8::HandleScope scope(CcTest::isolate());
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
   v8::Handle<v8::Value> value;
   // check int32_t and uint32_t
   int32_t int_values[] = {
       0, 234, -723,
       i::Smi::kMinValue, i::Smi::kMaxValue
   };
-  for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
+  for (size_t i = 0; i < arraysize(int_values); i++) {
     for (int modifier = -1; modifier <= 1; modifier++) {
       int int_value = int_values[i] + modifier;
       // check int32_t
@@ -1256,13 +1152,13 @@ THREADED_PROFILED_TEST(FastReturnValues) {
   // check double
   value = TestFastReturnValues<double>();
   CHECK(value->IsNumber());
-  CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
+  CHECK_EQ(kFastReturnValueDouble, value->ToNumber(isolate)->Value());
   // check bool values
   for (int i = 0; i < 2; i++) {
     fast_return_value_bool = i == 0;
     value = TestFastReturnValues<bool>();
     CHECK(value->IsBoolean());
-    CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
+    CHECK_EQ(fast_return_value_bool, value->ToBoolean(isolate)->Value());
   }
   // check oddballs
   ReturnValueOddball oddballs[] = {
@@ -1270,7 +1166,7 @@ THREADED_PROFILED_TEST(FastReturnValues) {
       kUndefinedReturnValue,
       kEmptyStringReturnValue
   };
-  for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
+  for (size_t i = 0; i < arraysize(oddballs); i++) {
     fast_return_value_void = oddballs[i];
     value = TestFastReturnValues<void>();
     switch (fast_return_value_void) {
@@ -1430,16 +1326,16 @@ THREADED_TEST(FindInstanceInPrototypeChain) {
   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->Equals(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->Equals(
+      derived_instance->FindInstanceInPrototypeChain(base)));
+  CHECK(derived_instance->Equals(
+      derived_instance->FindInstanceInPrototypeChain(derived)));
   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
 
   // other_instance is an instance of other and its immediate
@@ -1447,12 +1343,12 @@ THREADED_TEST(FindInstanceInPrototypeChain) {
   // 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));
+  CHECK(derived_instance2->Equals(
+      other_instance->FindInstanceInPrototypeChain(base)));
+  CHECK(derived_instance2->Equals(
+      other_instance->FindInstanceInPrototypeChain(derived)));
+  CHECK(other_instance->Equals(
+      other_instance->FindInstanceInPrototypeChain(other)));
 }
 
 
@@ -1592,6 +1488,83 @@ THREADED_TEST(IsNativeError) {
 }
 
 
+THREADED_TEST(IsGeneratorFunctionOrObject) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+
+  CompileRun("function *gen() { yield 1; }\nfunction func() {}");
+  v8::Handle<Value> gen = CompileRun("gen");
+  v8::Handle<Value> genObj = CompileRun("gen()");
+  v8::Handle<Value> object = CompileRun("{a:42}");
+  v8::Handle<Value> func = CompileRun("func");
+
+  CHECK(gen->IsGeneratorFunction());
+  CHECK(gen->IsFunction());
+  CHECK(!gen->IsGeneratorObject());
+
+  CHECK(!genObj->IsGeneratorFunction());
+  CHECK(!genObj->IsFunction());
+  CHECK(genObj->IsGeneratorObject());
+
+  CHECK(!object->IsGeneratorFunction());
+  CHECK(!object->IsFunction());
+  CHECK(!object->IsGeneratorObject());
+
+  CHECK(!func->IsGeneratorFunction());
+  CHECK(func->IsFunction());
+  CHECK(!func->IsGeneratorObject());
+}
+
+
+THREADED_TEST(ArgumentsObject) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::Handle<Value> arguments_object =
+      CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
+  CHECK(arguments_object->IsArgumentsObject());
+  v8::Handle<Value> array = CompileRun("[1,2,3]");
+  CHECK(!array->IsArgumentsObject());
+  v8::Handle<Value> object = CompileRun("{a:42}");
+  CHECK(!object->IsArgumentsObject());
+}
+
+
+THREADED_TEST(IsMapOrSet) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::Handle<Value> map = CompileRun("new Map()");
+  v8::Handle<Value> set = CompileRun("new Set()");
+  v8::Handle<Value> weak_map = CompileRun("new WeakMap()");
+  v8::Handle<Value> weak_set = CompileRun("new WeakSet()");
+  CHECK(map->IsMap());
+  CHECK(set->IsSet());
+  CHECK(weak_map->IsWeakMap());
+  CHECK(weak_set->IsWeakSet());
+
+  CHECK(!map->IsSet());
+  CHECK(!map->IsWeakMap());
+  CHECK(!map->IsWeakSet());
+
+  CHECK(!set->IsMap());
+  CHECK(!set->IsWeakMap());
+  CHECK(!set->IsWeakSet());
+
+  CHECK(!weak_map->IsMap());
+  CHECK(!weak_map->IsSet());
+  CHECK(!weak_map->IsWeakSet());
+
+  CHECK(!weak_set->IsMap());
+  CHECK(!weak_set->IsSet());
+  CHECK(!weak_set->IsWeakMap());
+
+  v8::Handle<Value> object = CompileRun("{a:42}");
+  CHECK(!object->IsMap());
+  CHECK(!object->IsSet());
+  CHECK(!object->IsWeakMap());
+  CHECK(!object->IsWeakSet());
+}
+
+
 THREADED_TEST(StringObject) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -1617,6 +1590,17 @@ THREADED_TEST(StringObject) {
 }
 
 
+TEST(StringObjectDelete) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
+  CHECK(boxed_string->IsStringObject());
+  v8::Handle<v8::Object> str_obj = boxed_string.As<v8::Object>();
+  CHECK(!str_obj->Delete(2));
+  CHECK(!str_obj->Delete(v8_num(2)));
+}
+
+
 THREADED_TEST(NumberObject) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -1809,17 +1793,22 @@ THREADED_TEST(GlobalPrototype) {
 THREADED_TEST(ObjectTemplate) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
+  Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
+  v8::Local<v8::String> class_name =
+      v8::String::NewFromUtf8(isolate, "the_class_name");
+  fun->SetClassName(class_name);
+  Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
   templ1->Set(isolate, "x", v8_num(10));
   templ1->Set(isolate, "y", v8_num(13));
   LocalContext env;
   Local<v8::Object> instance1 = templ1->NewInstance();
+  CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
   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(isolate);
-  fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
-  Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
+  Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
+  fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
+  Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
   templ2->Set(isolate, "a", v8_num(12));
   templ2->Set(isolate, "b", templ1);
   Local<v8::Object> instance2 = templ2->NewInstance();
@@ -1902,679 +1891,191 @@ THREADED_TEST(DescriptorInheritance) {
 }
 
 
-int echo_named_call_count;
-
-
-static void EchoNamedProperty(Local<String> name,
-                              const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  CHECK_EQ(v8_str("data"), info.Data());
-  echo_named_call_count++;
-  info.GetReturnValue().Set(name);
-}
-
-
 // Helper functions for Interceptor/Accessor interaction tests
 
 void SimpleAccessorGetter(Local<String> name,
                           const v8::PropertyCallbackInfo<v8::Value>& info) {
-  Handle<Object> self = info.This();
+  Handle<Object> self = Handle<Object>::Cast(info.This());
   info.GetReturnValue().Set(
       self->Get(String::Concat(v8_str("accessor_"), name)));
 }
 
 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
                           const v8::PropertyCallbackInfo<void>& info) {
-  Handle<Object> self = info.This();
+  Handle<Object> self = Handle<Object>::Cast(info.This());
   self->Set(String::Concat(v8_str("accessor_"), name), value);
 }
 
-void EmptyInterceptorGetter(Local<String> name,
-                            const v8::PropertyCallbackInfo<v8::Value>& info) {
+void SymbolAccessorGetter(Local<Name> name,
+                          const v8::PropertyCallbackInfo<v8::Value>& info) {
+  CHECK(name->IsSymbol());
+  Local<Symbol> sym = Local<Symbol>::Cast(name);
+  if (sym->Name()->IsUndefined())
+    return;
+  SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
 }
 
-void EmptyInterceptorSetter(Local<String> name,
-                            Local<Value> value,
-                            const v8::PropertyCallbackInfo<v8::Value>& info) {
+void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
+                          const v8::PropertyCallbackInfo<void>& info) {
+  CHECK(name->IsSymbol());
+  Local<Symbol> sym = Local<Symbol>::Cast(name);
+  if (sym->Name()->IsUndefined())
+    return;
+  SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
 }
 
-void InterceptorGetter(Local<String> name,
-                       const v8::PropertyCallbackInfo<v8::Value>& info) {
-  // Intercept names that start with 'interceptor_'.
-  String::Utf8Value utf8(name);
-  char* name_str = *utf8;
-  char prefix[] = "interceptor_";
-  int i;
-  for (i = 0; name_str[i] && prefix[i]; ++i) {
-    if (name_str[i] != prefix[i]) return;
-  }
-  Handle<Object> self = info.This();
-  info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
+void SymbolAccessorGetterReturnsDefault(
+    Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  CHECK(name->IsSymbol());
+  Local<Symbol> sym = Local<Symbol>::Cast(name);
+  if (sym->Name()->IsUndefined()) return;
+  info.GetReturnValue().Set(info.Data());
 }
 
-void InterceptorSetter(Local<String> name,
-                       Local<Value> value,
-                       const v8::PropertyCallbackInfo<v8::Value>& info) {
-  // Intercept accesses that set certain integer values, for which the name does
-  // not start with 'accessor_'.
-  String::Utf8Value utf8(name);
-  char* name_str = *utf8;
-  char prefix[] = "accessor_";
-  int i;
-  for (i = 0; name_str[i] && prefix[i]; ++i) {
-    if (name_str[i] != prefix[i]) break;
-  }
-  if (!prefix[i]) return;
-
-  if (value->IsInt32() && value->Int32Value() < 10000) {
-    Handle<Object> self = info.This();
-    self->SetHiddenValue(name, value);
-    info.GetReturnValue().Set(value);
-  }
+static void ThrowingSymbolAccessorGetter(
+    Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
 }
 
-void AddAccessor(Handle<FunctionTemplate> templ,
-                 Handle<String> name,
-                 v8::AccessorGetterCallback getter,
-                 v8::AccessorSetterCallback setter) {
-  templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
-}
 
-void AddInterceptor(Handle<FunctionTemplate> templ,
-                    v8::NamedPropertyGetterCallback getter,
-                    v8::NamedPropertySetterCallback setter) {
-  templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
+THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  LocalContext env;
+  v8::Local<v8::Value> res = CompileRun("var a = []; a;");
+  i::Handle<i::JSObject> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
+  CHECK(a->map()->instance_descriptors()->IsFixedArray());
+  CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
+  CompileRun("Object.defineProperty(a, 'length', { writable: false });");
+  CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
+  // But we should still have an ExecutableAccessorInfo.
+  i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
+  i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
+  CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
+  CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
 }
 
 
-THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
-  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
-  child->Inherit(parent);
-  AddAccessor(parent, v8_str("age"),
-              SimpleAccessorGetter, SimpleAccessorSetter);
-  AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
+THREADED_TEST(UndefinedIsNotEnumerable) {
   LocalContext env;
-  env->Global()->Set(v8_str("Child"), child->GetFunction());
-  CompileRun("var child = new Child;"
-             "child.age = 10;");
-  ExpectBoolean("child.hasOwnProperty('age')", false);
-  ExpectInt32("child.age", 10);
-  ExpectInt32("child.accessor_age", 10);
+  v8::HandleScope scope(env->GetIsolate());
+  v8::Handle<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
+  CHECK(result->IsFalse());
 }
 
 
-THREADED_TEST(EmptyInterceptorBreakTransitions) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
-  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Constructor"), templ->GetFunction());
-  CompileRun("var o1 = new Constructor;"
-             "o1.a = 1;"  // Ensure a and x share the descriptor array.
-             "Object.defineProperty(o1, 'x', {value: 10});");
-  CompileRun("var o2 = new Constructor;"
-             "o2.a = 1;"
-             "Object.defineProperty(o2, 'x', {value: 10});");
+v8::Handle<Script> call_recursively_script;
+static const int kTargetRecursionDepth = 200;  // near maximum
+
+
+static void CallScriptRecursivelyCall(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
+  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
+  if (depth == kTargetRecursionDepth) return;
+  args.This()->Set(v8_str("depth"),
+                   v8::Integer::New(args.GetIsolate(), depth + 1));
+  args.GetReturnValue().Set(call_recursively_script->Run());
 }
 
 
-THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
-  Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
-  child->Inherit(parent);
-  AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Child"), child->GetFunction());
-  CompileRun("var child = new Child;"
-             "var parent = child.__proto__;"
-             "Object.defineProperty(parent, 'age', "
-             "  {get: function(){ return this.accessor_age; }, "
-             "   set: function(v){ this.accessor_age = v; }, "
-             "   enumerable: true, configurable: true});"
-             "child.age = 10;");
-  ExpectBoolean("child.hasOwnProperty('age')", false);
-  ExpectInt32("child.age", 10);
-  ExpectInt32("child.accessor_age", 10);
+static void CallFunctionRecursivelyCall(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
+  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
+  if (depth == kTargetRecursionDepth) {
+    printf("[depth = %d]\n", depth);
+    return;
+  }
+  args.This()->Set(v8_str("depth"),
+                   v8::Integer::New(args.GetIsolate(), depth + 1));
+  v8::Handle<Value> function =
+      args.This()->Get(v8_str("callFunctionRecursively"));
+  args.GetReturnValue().Set(
+      function.As<Function>()->Call(args.This(), 0, NULL));
 }
 
 
-THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
+THREADED_TEST(DeepCrossLanguageRecursion) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
-  Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
-  child->Inherit(parent);
-  AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Child"), child->GetFunction());
-  CompileRun("var child = new Child;"
-             "var parent = child.__proto__;"
-             "parent.name = 'Alice';");
-  ExpectBoolean("child.hasOwnProperty('name')", false);
-  ExpectString("child.name", "Alice");
-  CompileRun("child.name = 'Bob';");
-  ExpectString("child.name", "Bob");
-  ExpectBoolean("child.hasOwnProperty('name')", true);
-  ExpectString("parent.name", "Alice");
-}
+  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
+  global->Set(v8_str("callScriptRecursively"),
+              v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
+  global->Set(v8_str("callFunctionRecursively"),
+              v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
+  LocalContext env(NULL, global);
 
+  env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
+  call_recursively_script = v8_compile("callScriptRecursively()");
+  call_recursively_script->Run();
+  call_recursively_script = v8::Handle<Script>();
 
-THREADED_TEST(SwitchFromInterceptorToAccessor) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
-  AddAccessor(templ, v8_str("age"),
-              SimpleAccessorGetter, SimpleAccessorSetter);
-  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
-  CompileRun("var obj = new Obj;"
-             "function setAge(i){ obj.age = i; };"
-             "for(var i = 0; i <= 10000; i++) setAge(i);");
-  // All i < 10000 go to the interceptor.
-  ExpectInt32("obj.interceptor_age", 9999);
-  // The last i goes to the accessor.
-  ExpectInt32("obj.accessor_age", 10000);
+  env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
+  CompileRun("callFunctionRecursively()");
 }
 
 
-THREADED_TEST(SwitchFromAccessorToInterceptor) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
-  AddAccessor(templ, v8_str("age"),
-              SimpleAccessorGetter, SimpleAccessorSetter);
-  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
-  CompileRun("var obj = new Obj;"
-             "function setAge(i){ obj.age = i; };"
-             "for(var i = 20000; i >= 9999; i--) setAge(i);");
-  // All i >= 10000 go to the accessor.
-  ExpectInt32("obj.accessor_age", 10000);
-  // The last i goes to the interceptor.
-  ExpectInt32("obj.interceptor_age", 9999);
+static void ThrowingPropertyHandlerGet(
+    Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  // Since this interceptor is used on "with" objects, the runtime will look up
+  // @@unscopables.  Punt.
+  if (key->IsSymbol()) return;
+  ApiTestFuzzer::Fuzz();
+  info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
 }
 
 
-THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
-  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
-  child->Inherit(parent);
-  AddAccessor(parent, v8_str("age"),
-              SimpleAccessorGetter, SimpleAccessorSetter);
-  AddInterceptor(child, InterceptorGetter, InterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Child"), child->GetFunction());
-  CompileRun("var child = new Child;"
-             "function setAge(i){ child.age = i; };"
-             "for(var i = 0; i <= 10000; i++) setAge(i);");
-  // All i < 10000 go to the interceptor.
-  ExpectInt32("child.interceptor_age", 9999);
-  // The last i goes to the accessor.
-  ExpectInt32("child.accessor_age", 10000);
+static void ThrowingPropertyHandlerSet(
+    Local<Name> key, Local<Value>,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  info.GetIsolate()->ThrowException(key);
+  info.GetReturnValue().SetUndefined();  // not the same as empty handle
 }
 
 
-THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
-  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
-  child->Inherit(parent);
-  AddAccessor(parent, v8_str("age"),
-              SimpleAccessorGetter, SimpleAccessorSetter);
-  AddInterceptor(child, InterceptorGetter, InterceptorSetter);
+THREADED_TEST(CallbackExceptionRegression) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
+  obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
   LocalContext env;
-  env->Global()->Set(v8_str("Child"), child->GetFunction());
-  CompileRun("var child = new Child;"
-             "function setAge(i){ child.age = i; };"
-             "for(var i = 20000; i >= 9999; i--) setAge(i);");
-  // All i >= 10000 go to the accessor.
-  ExpectInt32("child.accessor_age", 10000);
-  // The last i goes to the interceptor.
-  ExpectInt32("child.interceptor_age", 9999);
+  env->Global()->Set(v8_str("obj"), obj->NewInstance());
+  v8::Handle<Value> otto =
+      CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
+  CHECK(v8_str("otto")->Equals(otto));
+  v8::Handle<Value> netto =
+      CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
+  CHECK(v8_str("netto")->Equals(netto));
 }
 
 
-THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
-  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
-  CompileRun("var obj = new Obj;"
-             "function setter(i) { this.accessor_age = i; };"
-             "function getter() { return this.accessor_age; };"
-             "function setAge(i) { obj.age = i; };"
-             "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
-             "for(var i = 0; i <= 10000; i++) setAge(i);");
-  // All i < 10000 go to the interceptor.
-  ExpectInt32("obj.interceptor_age", 9999);
-  // The last i goes to the JavaScript accessor.
-  ExpectInt32("obj.accessor_age", 10000);
-  // The installed JavaScript getter is still intact.
-  // This last part is a regression test for issue 1651 and relies on the fact
-  // that both interceptor and accessor are being installed on the same object.
-  ExpectInt32("obj.age", 10000);
-  ExpectBoolean("obj.hasOwnProperty('age')", true);
-  ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
-}
-
-
-THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
-  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
-  CompileRun("var obj = new Obj;"
-             "function setter(i) { this.accessor_age = i; };"
-             "function getter() { return this.accessor_age; };"
-             "function setAge(i) { obj.age = i; };"
-             "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
-             "for(var i = 20000; i >= 9999; i--) setAge(i);");
-  // All i >= 10000 go to the accessor.
-  ExpectInt32("obj.accessor_age", 10000);
-  // The last i goes to the interceptor.
-  ExpectInt32("obj.interceptor_age", 9999);
-  // The installed JavaScript getter is still intact.
-  // This last part is a regression test for issue 1651 and relies on the fact
-  // that both interceptor and accessor are being installed on the same object.
-  ExpectInt32("obj.age", 10000);
-  ExpectBoolean("obj.hasOwnProperty('age')", true);
-  ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
-}
-
-
-THREADED_TEST(SwitchFromInterceptorToProperty) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
-  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
-  child->Inherit(parent);
-  AddInterceptor(child, InterceptorGetter, InterceptorSetter);
+THREADED_TEST(FunctionPrototype) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
+  Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
   LocalContext env;
-  env->Global()->Set(v8_str("Child"), child->GetFunction());
-  CompileRun("var child = new Child;"
-             "function setAge(i){ child.age = i; };"
-             "for(var i = 0; i <= 10000; i++) setAge(i);");
-  // All i < 10000 go to the interceptor.
-  ExpectInt32("child.interceptor_age", 9999);
-  // The last i goes to child's own property.
-  ExpectInt32("child.age", 10000);
+  env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
+  Local<Script> script = v8_compile("Foo.prototype.plak");
+  CHECK_EQ(script->Run()->Int32Value(), 321);
 }
 
 
-THREADED_TEST(SwitchFromPropertyToInterceptor) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
-  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
-  child->Inherit(parent);
-  AddInterceptor(child, InterceptorGetter, InterceptorSetter);
+THREADED_TEST(InternalFields) {
   LocalContext env;
-  env->Global()->Set(v8_str("Child"), child->GetFunction());
-  CompileRun("var child = new Child;"
-             "function setAge(i){ child.age = i; };"
-             "for(var i = 20000; i >= 9999; i--) setAge(i);");
-  // All i >= 10000 go to child's own property.
-  ExpectInt32("child.age", 10000);
-  // The last i goes to the interceptor.
-  ExpectInt32("child.interceptor_age", 9999);
-}
-
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
 
-THREADED_TEST(NamedPropertyHandlerGetter) {
-  echo_named_call_count = 0;
-  v8::HandleScope scope(CcTest::isolate());
-  v8::Handle<v8::FunctionTemplate> templ =
-      v8::FunctionTemplate::New(CcTest::isolate());
-  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::Utf8Value 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 void EchoIndexedProperty(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  CHECK_EQ(v8_num(637), info.Data());
-  echo_indexed_call_count++;
-  info.GetReturnValue().Set(v8_num(index));
-}
-
-
-THREADED_TEST(IndexedPropertyHandlerGetter) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
-  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 void CheckThisIndexedPropertyHandler(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-static void CheckThisNamedPropertyHandler(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-void CheckThisIndexedPropertySetter(
-    uint32_t index,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-
-void CheckThisNamedPropertySetter(
-    Local<String> property,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-void CheckThisIndexedPropertyQuery(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Integer>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-
-void CheckThisNamedPropertyQuery(
-    Local<String> property,
-    const v8::PropertyCallbackInfo<v8::Integer>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-
-void CheckThisIndexedPropertyDeleter(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-
-void CheckThisNamedPropertyDeleter(
-    Local<String> property,
-    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-
-void CheckThisIndexedPropertyEnumerator(
-    const v8::PropertyCallbackInfo<v8::Array>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-
-void CheckThisNamedPropertyEnumerator(
-    const v8::PropertyCallbackInfo<v8::Array>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This()->Equals(bottom));
-}
-
-
-THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-
-  // Set up a prototype chain with three interceptors.
-  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
-  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->SetPrototype(middle);
-  middle->SetPrototype(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 void PrePropertyHandlerGet(
-    Local<String> key,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (v8_str("pre")->Equals(key)) {
-    info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
-  }
-}
-
-
-static void PrePropertyHandlerQuery(
-    Local<String> key,
-    const v8::PropertyCallbackInfo<v8::Integer>& info) {
-  if (v8_str("pre")->Equals(key)) {
-    info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
-  }
-}
-
-
-THREADED_TEST(PrePropertyHandler) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
-  desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
-                                                    0,
-                                                    PrePropertyHandlerQuery);
-  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) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  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 = 200;  // near maximum
-
-
-static void CallScriptRecursivelyCall(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
-  if (depth == kTargetRecursionDepth) return;
-  args.This()->Set(v8_str("depth"),
-                   v8::Integer::New(args.GetIsolate(), depth + 1));
-  args.GetReturnValue().Set(call_recursively_script->Run());
-}
-
-
-static void CallFunctionRecursivelyCall(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
-  if (depth == kTargetRecursionDepth) {
-    printf("[depth = %d]\n", depth);
-    return;
-  }
-  args.This()->Set(v8_str("depth"),
-                   v8::Integer::New(args.GetIsolate(), depth + 1));
-  v8::Handle<Value> function =
-      args.This()->Get(v8_str("callFunctionRecursively"));
-  args.GetReturnValue().Set(
-      function.As<Function>()->Call(args.This(), 0, NULL));
-}
-
-
-THREADED_TEST(DeepCrossLanguageRecursion) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
-  global->Set(v8_str("callScriptRecursively"),
-              v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
-  global->Set(v8_str("callFunctionRecursively"),
-              v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
-  LocalContext env(NULL, global);
-
-  env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
-  call_recursively_script = v8_compile("callScriptRecursively()");
-  call_recursively_script->Run();
-  call_recursively_script = v8::Handle<Script>();
-
-  env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
-  Script::Compile(v8_str("callFunctionRecursively()"))->Run();
-}
-
-
-static void ThrowingPropertyHandlerGet(
-    Local<String> key,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
-}
-
-
-static void ThrowingPropertyHandlerSet(
-    Local<String> key,
-    Local<Value>,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetIsolate()->ThrowException(key);
-  info.GetReturnValue().SetUndefined();  // not the same as empty handle
-}
-
-
-THREADED_TEST(CallbackExceptionRegression) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
-  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);
-}
-
-
-THREADED_TEST(FunctionPrototype) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
-  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) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-
-  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
-  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());
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
+  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());
 }
 
 
@@ -2607,7 +2108,7 @@ static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
                                                void* value) {
   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   obj->SetAlignedPointerInInternalField(0, value);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
 }
 
@@ -2634,15 +2135,18 @@ THREADED_TEST(InternalFieldsAlignedPointers) {
 
   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   CheckAlignedPointerInInternalField(obj, huge);
+
+  v8::Global<v8::Object> persistent(isolate, obj);
+  CHECK_EQ(1, Object::InternalFieldCount(persistent));
+  CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
 }
 
 
-static void CheckAlignedPointerInEmbedderData(LocalContext* env,
-                                              int index,
+static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
                                               void* value) {
   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   (*env)->SetAlignedPointerInEmbedderData(index, value);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
 }
 
@@ -2672,15 +2176,14 @@ THREADED_TEST(EmbedderDataAlignedPointers) {
   for (int i = 0; i < 100; i++) {
     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
   }
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
   for (int i = 0; i < 100; i++) {
     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
   }
 }
 
 
-static void CheckEmbedderData(LocalContext* env,
-                              int index,
+static void CheckEmbedderData(LocalContext* env, int index,
                               v8::Handle<Value> data) {
   (*env)->SetEmbedderData(index, data);
   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
@@ -2693,15 +2196,24 @@ THREADED_TEST(EmbedderData) {
   v8::HandleScope scope(isolate);
 
   CheckEmbedderData(
-      &env, 3,
-      v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
-  CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(isolate,
-                                                     "over the lazy dog."));
+      &env, 3, v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
+  CheckEmbedderData(&env, 2,
+                    v8::String::NewFromUtf8(isolate, "over the lazy dog."));
   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
 }
 
 
+THREADED_TEST(GetIsolate) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<v8::Object> obj = v8::Object::New(isolate);
+  CHECK_EQ(isolate, obj->GetIsolate());
+  CHECK_EQ(isolate, CcTest::global()->GetIsolate());
+}
+
+
 THREADED_TEST(IdentityHash) {
   LocalContext env;
   v8::Isolate* isolate = env->GetIsolate();
@@ -2709,7 +2221,7 @@ THREADED_TEST(IdentityHash) {
 
   // Ensure that the test starts with an fresh heap to test whether the hash
   // code is based on the address.
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
   Local<v8::Object> obj = v8::Object::New(isolate);
   int hash = obj->GetIdentityHash();
   int hash1 = obj->GetIdentityHash();
@@ -2719,7 +2231,7 @@ THREADED_TEST(IdentityHash) {
   // 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);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
   int hash3 = v8::Object::New(isolate)->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
@@ -2747,18 +2259,101 @@ THREADED_TEST(IdentityHash) {
 }
 
 
-THREADED_TEST(SymbolProperties) {
-  i::FLAG_harmony_symbols = true;
+void GlobalProxyIdentityHash(bool set_in_js) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  v8::HandleScope scope(isolate);
+  Handle<Object> global_proxy = env->Global();
+  i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
+  env->Global()->Set(v8_str("global"), global_proxy);
+  i::Handle<i::Object> original_hash;
+  if (set_in_js) {
+    CompileRun("var m = new Set(); m.add(global);");
+    original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
+  } else {
+    original_hash = i::Handle<i::Object>(
+        i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
+  }
+  CHECK(original_hash->IsSmi());
+  int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
+  // Hash should be retained after being detached.
+  env->DetachGlobal();
+  int hash2 = global_proxy->GetIdentityHash();
+  CHECK_EQ(hash1, hash2);
+  {
+    // Re-attach global proxy to a new context, hash should stay the same.
+    LocalContext env2(NULL, Handle<ObjectTemplate>(), global_proxy);
+    int hash3 = global_proxy->GetIdentityHash();
+    CHECK_EQ(hash1, hash3);
+  }
+}
+
+
+THREADED_TEST(GlobalProxyIdentityHash) {
+  GlobalProxyIdentityHash(true);
+  GlobalProxyIdentityHash(false);
+}
+
+
+TEST(SymbolIdentityHash) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+
+  {
+    Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
+    int hash = symbol->GetIdentityHash();
+    int hash1 = symbol->GetIdentityHash();
+    CHECK_EQ(hash, hash1);
+    CcTest::heap()->CollectAllGarbage();
+    int hash3 = symbol->GetIdentityHash();
+    CHECK_EQ(hash, hash3);
+  }
+
+  {
+    v8::Handle<v8::Symbol> js_symbol =
+        CompileRun("Symbol('foo')").As<v8::Symbol>();
+    int hash = js_symbol->GetIdentityHash();
+    int hash1 = js_symbol->GetIdentityHash();
+    CHECK_EQ(hash, hash1);
+    CcTest::heap()->CollectAllGarbage();
+    int hash3 = js_symbol->GetIdentityHash();
+    CHECK_EQ(hash, hash3);
+  }
+}
+
+
+TEST(StringIdentityHash) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+
+  Local<v8::String> str = v8::String::NewFromUtf8(isolate, "str1");
+  int hash = str->GetIdentityHash();
+  int hash1 = str->GetIdentityHash();
+  CHECK_EQ(hash, hash1);
+  CcTest::heap()->CollectAllGarbage();
+  int hash3 = str->GetIdentityHash();
+  CHECK_EQ(hash, hash3);
+
+  Local<v8::String> str2 = v8::String::NewFromUtf8(isolate, "str1");
+  int hash4 = str2->GetIdentityHash();
+  CHECK_EQ(hash, hash4);
+}
+
 
+THREADED_TEST(SymbolProperties) {
   LocalContext env;
   v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
 
   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
-  v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
+  v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
+  v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
 
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
 
   // Check basic symbol functionality.
   CHECK(sym1->IsSymbol());
@@ -2774,7 +2369,7 @@ THREADED_TEST(SymbolProperties) {
   CHECK(!sym1->StrictEquals(sym2));
   CHECK(!sym2->StrictEquals(sym1));
 
-  CHECK(sym2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-symbol")));
+  CHECK(sym2->Name()->Equals(v8_str("my-symbol")));
 
   v8::Local<v8::Value> sym_val = sym2;
   CHECK(sym_val->IsSymbol());
@@ -2786,7 +2381,7 @@ THREADED_TEST(SymbolProperties) {
   CHECK(sym_obj->IsSymbolObject());
   CHECK(!sym2->IsSymbolObject());
   CHECK(!obj->IsSymbolObject());
-  CHECK(sym_obj->Equals(sym2));
+  CHECK(!sym_obj->Equals(sym2));
   CHECK(!sym_obj->StrictEquals(sym2));
   CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
   CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
@@ -2803,14 +2398,21 @@ THREADED_TEST(SymbolProperties) {
   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
 
-  CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
-  int num_props = obj->GetPropertyNames()->Length();
+  CHECK_EQ(0u, obj->GetOwnPropertyNames()->Length());
+  unsigned num_props = obj->GetPropertyNames()->Length();
   CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
                  v8::Integer::New(isolate, 20)));
-  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
+  CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
 
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
+
+  CHECK(obj->SetAccessor(sym3, SymbolAccessorGetter, SymbolAccessorSetter));
+  CHECK(obj->Get(sym3)->IsUndefined());
+  CHECK(obj->Set(sym3, v8::Integer::New(isolate, 42)));
+  CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
+  CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
+            ->Equals(v8::Integer::New(isolate, 42)));
 
   // Add another property and delete it afterwards to force the object in
   // slow case.
@@ -2818,91 +2420,105 @@ THREADED_TEST(SymbolProperties) {
   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
-  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
+  CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
 
   CHECK(obj->Has(sym1));
   CHECK(obj->Has(sym2));
+  CHECK(obj->Has(sym3));
+  CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
   CHECK(obj->Delete(sym2));
   CHECK(obj->Has(sym1));
   CHECK(!obj->Has(sym2));
+  CHECK(obj->Has(sym3));
+  CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
-  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
+  CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
+  CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
+            ->Equals(v8::Integer::New(isolate, 42)));
+  CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
 
   // Symbol properties are inherited.
   v8::Local<v8::Object> child = v8::Object::New(isolate);
   child->SetPrototype(obj);
   CHECK(child->Has(sym1));
   CHECK_EQ(2002, child->Get(sym1)->Int32Value());
-  CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
+  CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
+  CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
+            ->Equals(v8::Integer::New(isolate, 42)));
+  CHECK_EQ(0u, child->GetOwnPropertyNames()->Length());
 }
 
 
-THREADED_TEST(PrivateProperties) {
+THREADED_TEST(SymbolTemplateProperties) {
   LocalContext env;
   v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
+  v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
+  v8::Local<v8::Name> name = v8::Symbol::New(isolate);
+  CHECK(!name.IsEmpty());
+  foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
+  v8::Local<v8::Object> new_instance = foo->InstanceTemplate()->NewInstance();
+  CHECK(!new_instance.IsEmpty());
+  CHECK(new_instance->Has(name));
+}
 
-  v8::Local<v8::Object> obj = v8::Object::New(isolate);
-  v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
-  v8::Local<v8::Private> priv2 = v8::Private::New(isolate, "my-private");
 
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+THREADED_TEST(GlobalSymbols) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
 
-  CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
+  v8::Local<String> name = v8_str("my-symbol");
+  v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
+  v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
+  CHECK(glob2->SameValue(glob));
 
-  // Make sure delete of a non-existent private symbol property works.
-  CHECK(obj->DeletePrivate(priv1));
-  CHECK(!obj->HasPrivate(priv1));
+  v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
+  v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
+  CHECK(glob_api2->SameValue(glob_api));
+  CHECK(!glob_api->SameValue(glob));
 
-  CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
-  CHECK(obj->HasPrivate(priv1));
-  CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
-  CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
-  CHECK(obj->HasPrivate(priv1));
-  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
+  v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
+  CHECK(!sym->SameValue(glob));
 
-  CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
-  int num_props = obj->GetPropertyNames()->Length();
-  CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
-                 v8::Integer::New(isolate, 20)));
-  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
-  CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
+  CompileRun("var sym2 = Symbol.for('my-symbol')");
+  v8::Local<Value> sym2 = env->Global()->Get(v8_str("sym2"));
+  CHECK(sym2->SameValue(glob));
+  CHECK(!sym2->SameValue(glob_api));
+}
 
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
 
-  // Add another property and delete it afterwards to force the object in
-  // slow case.
-  CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
-  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
-  CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
-  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
-  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
-
-  CHECK(obj->HasPrivate(priv1));
-  CHECK(obj->HasPrivate(priv2));
-  CHECK(obj->DeletePrivate(priv2));
-  CHECK(obj->HasPrivate(priv1));
-  CHECK(!obj->HasPrivate(priv2));
-  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
-  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
-
-  // Private properties are inherited (for the time being).
-  v8::Local<v8::Object> child = v8::Object::New(isolate);
-  child->SetPrototype(obj);
-  CHECK(child->HasPrivate(priv1));
-  CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
-  CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
+static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
+                                 const char* name) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+
+  v8::Local<v8::Symbol> symbol = getter(isolate);
+  std::string script = std::string("var sym = ") + name;
+  CompileRun(script.c_str());
+  v8::Local<Value> value = env->Global()->Get(v8_str("sym"));
+
+  CHECK(!value.IsEmpty());
+  CHECK(!symbol.IsEmpty());
+  CHECK(value->SameValue(symbol));
+}
+
+
+THREADED_TEST(WellKnownSymbols) {
+  CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
+  CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
 }
 
 
 class ScopedArrayBufferContents {
  public:
-  explicit ScopedArrayBufferContents(
-      const v8::ArrayBuffer::Contents& contents)
-    : contents_(contents) {}
+  explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
+      : contents_(contents) {}
   ~ScopedArrayBufferContents() { free(contents_.Data()); }
   void* Data() const { return contents_.Data(); }
   size_t ByteLength() const { return contents_.ByteLength(); }
+
  private:
   const v8::ArrayBuffer::Contents contents_;
 };
@@ -2925,23 +2541,24 @@ THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
   CheckInternalFieldsAreZero(ab);
   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
   CHECK(!ab->IsExternal());
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
 
   ScopedArrayBufferContents ab_contents(ab->Externalize());
   CHECK(ab->IsExternal());
 
   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
-  ASSERT(data != NULL);
+  DCHECK(data != NULL);
   env->Global()->Set(v8_str("ab"), ab);
 
   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
   CHECK_EQ(1024, result->Int32Value());
 
-  result = CompileRun("var u8 = new Uint8Array(ab);"
-                      "u8[0] = 0xFF;"
-                      "u8[1] = 0xAA;"
-                      "u8.length");
+  result = CompileRun(
+      "var u8 = new Uint8Array(ab);"
+      "u8[0] = 0xFF;"
+      "u8[1] = 0xAA;"
+      "u8.length");
   CHECK_EQ(1024, result->Int32Value());
   CHECK_EQ(0xFF, data[0]);
   CHECK_EQ(0xAA, data[1]);
@@ -2958,11 +2575,11 @@ THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
   v8::HandleScope handle_scope(isolate);
 
 
-  v8::Local<v8::Value> result =
-      CompileRun("var ab1 = new ArrayBuffer(2);"
-                 "var u8_a = new Uint8Array(ab1);"
-                 "u8_a[0] = 0xAA;"
-                 "u8_a[1] = 0xFF; u8_a.buffer");
+  v8::Local<v8::Value> result = CompileRun(
+      "var ab1 = new ArrayBuffer(2);"
+      "var u8_a = new Uint8Array(ab1);"
+      "u8_a[0] = 0xAA;"
+      "u8_a[1] = 0xFF; u8_a.buffer");
   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
   CheckInternalFieldsAreZero(ab1);
   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
@@ -2976,9 +2593,10 @@ THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
   CHECK_EQ(0xAA, result->Int32Value());
   result = CompileRun("u8_a[1]");
   CHECK_EQ(0xFF, result->Int32Value());
-  result = CompileRun("var u8_b = new Uint8Array(ab1);"
-                      "u8_b[0] = 0xBB;"
-                      "u8_a[0]");
+  result = CompileRun(
+      "var u8_b = new Uint8Array(ab1);"
+      "u8_b[0] = 0xBB;"
+      "u8_a[0]");
   CHECK_EQ(0xBB, result->Int32Value());
   result = CompileRun("u8_b[1]");
   CHECK_EQ(0xFF, result->Int32Value());
@@ -3012,10 +2630,11 @@ THREADED_TEST(ArrayBuffer_External) {
   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
   CHECK_EQ(100, result->Int32Value());
 
-  result = CompileRun("var u8_b = new Uint8Array(ab3);"
-                      "u8_b[0] = 0xBB;"
-                      "u8_b[1] = 0xCC;"
-                      "u8_b.length");
+  result = CompileRun(
+      "var u8_b = new Uint8Array(ab3);"
+      "u8_b[0] = 0xBB;"
+      "u8_b[1] = 0xCC;"
+      "u8_b.length");
   CHECK_EQ(100, result->Int32Value());
   CHECK_EQ(0xBB, my_data[0]);
   CHECK_EQ(0xCC, my_data[1]);
@@ -3026,6 +2645,24 @@ THREADED_TEST(ArrayBuffer_External) {
 }
 
 
+THREADED_TEST(ArrayBuffer_DisableNeuter) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+
+  i::ScopedVector<uint8_t> my_data(100);
+  memset(my_data.start(), 0, 100);
+  Local<v8::ArrayBuffer> ab =
+      v8::ArrayBuffer::New(isolate, my_data.start(), 100);
+  CHECK(ab->IsNeuterable());
+
+  i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
+  buf->set_is_neuterable(false);
+
+  CHECK(!ab->IsNeuterable());
+}
+
+
 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
@@ -3041,20 +2678,19 @@ static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
 
 static void CheckIsTypedArrayVarNeutered(const char* name) {
   i::ScopedVector<char> source(1024);
-  i::OS::SNPrintF(source,
-      "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
-      name, name, name);
+  i::SNPrintF(source,
+              "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
+              name, name, name);
   CHECK(CompileRun(source.start())->IsTrue());
   v8::Handle<v8::TypedArray> ta =
-    v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
+      v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
   CheckIsNeutered(ta);
 }
 
 
 template <typename TypedArray, int kElementSize>
 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
-                                         int byteOffset,
-                                         int length) {
+                                         int byteOffset, int length) {
   v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
@@ -3072,26 +2708,26 @@ THREADED_TEST(ArrayBuffer_NeuteringApi) {
   v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
 
   v8::Handle<v8::Uint8Array> u8a =
-    CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
+      CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
   v8::Handle<v8::Uint8ClampedArray> u8c =
-    CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
+      CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
   v8::Handle<v8::Int8Array> i8a =
-    CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
+      CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
 
   v8::Handle<v8::Uint16Array> u16a =
-    CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
+      CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
   v8::Handle<v8::Int16Array> i16a =
-    CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
+      CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
 
   v8::Handle<v8::Uint32Array> u32a =
-    CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
+      CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
   v8::Handle<v8::Int32Array> i32a =
-    CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
+      CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
 
   v8::Handle<v8::Float32Array> f32a =
-    CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
+      CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
   v8::Handle<v8::Float64Array> f64a =
-    CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
+      CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
 
   v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
@@ -3136,7 +2772,7 @@ THREADED_TEST(ArrayBuffer_NeuteringScript) {
       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
 
   v8::Handle<v8::DataView> dv =
-    v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
+      v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
 
   ScopedArrayBufferContents contents(ab->Externalize());
   ab->Neuter();
@@ -3158,6 +2794,135 @@ THREADED_TEST(ArrayBuffer_NeuteringScript) {
 }
 
 
+class ScopedSharedArrayBufferContents {
+ public:
+  explicit ScopedSharedArrayBufferContents(
+      const v8::SharedArrayBuffer::Contents& contents)
+      : contents_(contents) {}
+  ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
+  void* Data() const { return contents_.Data(); }
+  size_t ByteLength() const { return contents_.ByteLength(); }
+
+ private:
+  const v8::SharedArrayBuffer::Contents contents_;
+};
+
+
+THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+
+  Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
+  CheckInternalFieldsAreZero(ab);
+  CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
+  CHECK(!ab->IsExternal());
+  CcTest::heap()->CollectAllGarbage();
+
+  ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
+  CHECK(ab->IsExternal());
+
+  CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
+  uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
+  DCHECK(data != NULL);
+  env->Global()->Set(v8_str("ab"), ab);
+
+  v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
+  CHECK_EQ(1024, result->Int32Value());
+
+  result = CompileRun(
+      "var u8 = new Uint8Array(ab);"
+      "u8[0] = 0xFF;"
+      "u8[1] = 0xAA;"
+      "u8.length");
+  CHECK_EQ(1024, result->Int32Value());
+  CHECK_EQ(0xFF, data[0]);
+  CHECK_EQ(0xAA, data[1]);
+  data[0] = 0xCC;
+  data[1] = 0x11;
+  result = CompileRun("u8[0] + u8[1]");
+  CHECK_EQ(0xDD, result->Int32Value());
+}
+
+
+THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+
+
+  v8::Local<v8::Value> result = CompileRun(
+      "var ab1 = new SharedArrayBuffer(2);"
+      "var u8_a = new Uint8Array(ab1);"
+      "u8_a[0] = 0xAA;"
+      "u8_a[1] = 0xFF; u8_a.buffer");
+  Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
+  CheckInternalFieldsAreZero(ab1);
+  CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
+  CHECK(!ab1->IsExternal());
+  ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
+  CHECK(ab1->IsExternal());
+
+  result = CompileRun("ab1.byteLength");
+  CHECK_EQ(2, result->Int32Value());
+  result = CompileRun("u8_a[0]");
+  CHECK_EQ(0xAA, result->Int32Value());
+  result = CompileRun("u8_a[1]");
+  CHECK_EQ(0xFF, result->Int32Value());
+  result = CompileRun(
+      "var u8_b = new Uint8Array(ab1);"
+      "u8_b[0] = 0xBB;"
+      "u8_a[0]");
+  CHECK_EQ(0xBB, result->Int32Value());
+  result = CompileRun("u8_b[1]");
+  CHECK_EQ(0xFF, result->Int32Value());
+
+  CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
+  uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
+  CHECK_EQ(0xBB, ab1_data[0]);
+  CHECK_EQ(0xFF, ab1_data[1]);
+  ab1_data[0] = 0xCC;
+  ab1_data[1] = 0x11;
+  result = CompileRun("u8_a[0] + u8_a[1]");
+  CHECK_EQ(0xDD, result->Int32Value());
+}
+
+
+THREADED_TEST(SharedArrayBuffer_External) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+
+  i::ScopedVector<uint8_t> my_data(100);
+  memset(my_data.start(), 0, 100);
+  Local<v8::SharedArrayBuffer> ab3 =
+      v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
+  CheckInternalFieldsAreZero(ab3);
+  CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
+  CHECK(ab3->IsExternal());
+
+  env->Global()->Set(v8_str("ab3"), ab3);
+
+  v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
+  CHECK_EQ(100, result->Int32Value());
+
+  result = CompileRun(
+      "var u8_b = new Uint8Array(ab3);"
+      "u8_b[0] = 0xBB;"
+      "u8_b[1] = 0xCC;"
+      "u8_b.length");
+  CHECK_EQ(100, result->Int32Value());
+  CHECK_EQ(0xBB, my_data[0]);
+  CHECK_EQ(0xCC, my_data[1]);
+  my_data[0] = 0xCC;
+  my_data[1] = 0x11;
+  result = CompileRun("u8_b[0] + u8_b[1]");
+  CHECK_EQ(0xDD, result->Int32Value());
+}
+
 
 THREADED_TEST(HiddenProperties) {
   LocalContext env;
@@ -3169,7 +2934,7 @@ THREADED_TEST(HiddenProperties) {
   v8::Local<v8::String> empty = v8_str("");
   v8::Local<v8::String> prop_name = v8_str("prop_name");
 
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
 
   // Make sure delete of a non-existent hidden value works
   CHECK(obj->DeleteHiddenValue(key));
@@ -3179,7 +2944,7 @@ THREADED_TEST(HiddenProperties) {
   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
 
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
 
   // Make sure we do not find the hidden property.
   CHECK(!obj->Has(empty));
@@ -3190,7 +2955,7 @@ THREADED_TEST(HiddenProperties) {
   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
 
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
 
   // Add another property and delete it afterwards to force the object in
   // slow case.
@@ -3201,7 +2966,7 @@ THREADED_TEST(HiddenProperties) {
   CHECK(obj->Delete(prop_name));
   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
 
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
 
   CHECK(obj->SetHiddenValue(key, Handle<Value>()));
   CHECK(obj->GetHiddenValue(key).IsEmpty());
@@ -3240,41 +3005,13 @@ THREADED_TEST(Regress97784) {
 }
 
 
-static bool interceptor_for_hidden_properties_called;
-static void InterceptorForHiddenProperties(
-    Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
-  interceptor_for_hidden_properties_called = true;
-}
-
-
-THREADED_TEST(HiddenPropertiesWithInterceptors) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-
-  interceptor_for_hidden_properties_called = false;
-
-  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(isolate);
-  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(isolate, 2302)));
-  CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
-  CHECK(!interceptor_for_hidden_properties_called);
-}
-
-
 THREADED_TEST(External) {
   v8::HandleScope scope(CcTest::isolate());
   int x = 3;
   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
   LocalContext env;
   env->Global()->Set(v8_str("ext"), ext);
-  Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
+  Local<Value> reext_obj = CompileRun("this.ext");
   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
   int* ptr = static_cast<int*>(reext->Value());
   CHECK_EQ(x, 3);
@@ -3376,21 +3113,21 @@ THREADED_TEST(ResettingGlobalHandleToEmpty) {
 }
 
 
-template<class T>
-static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
+template <class T>
+static v8::Global<T> PassUnique(v8::Global<T> unique) {
   return unique.Pass();
 }
 
 
-template<class T>
-static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
-                                            const v8::Persistent<T> & global) {
-  v8::UniquePersistent<String> unique(isolate, global);
+template <class T>
+static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
+                                  const v8::Persistent<T>& global) {
+  v8::Global<String> unique(isolate, global);
   return unique.Pass();
 }
 
 
-THREADED_TEST(UniquePersistent) {
+THREADED_TEST(Global) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::Persistent<String> global;
   {
@@ -3401,11 +3138,11 @@ THREADED_TEST(UniquePersistent) {
       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   int initial_handle_count = global_handles->global_handles_count();
   {
-    v8::UniquePersistent<String> unique(isolate, global);
+    v8::Global<String> unique(isolate, global);
     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
     // Test assignment via Pass
     {
-      v8::UniquePersistent<String> copy = unique.Pass();
+      v8::Global<String> copy = unique.Pass();
       CHECK(unique.IsEmpty());
       CHECK(copy == global);
       CHECK_EQ(initial_handle_count + 1,
@@ -3414,7 +3151,7 @@ THREADED_TEST(UniquePersistent) {
     }
     // Test ctor via Pass
     {
-      v8::UniquePersistent<String> copy(unique.Pass());
+      v8::Global<String> copy(unique.Pass());
       CHECK(unique.IsEmpty());
       CHECK(copy == global);
       CHECK_EQ(initial_handle_count + 1,
@@ -3423,7 +3160,7 @@ THREADED_TEST(UniquePersistent) {
     }
     // Test pass through function call
     {
-      v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
+      v8::Global<String> copy = PassUnique(unique.Pass());
       CHECK(unique.IsEmpty());
       CHECK(copy == global);
       CHECK_EQ(initial_handle_count + 1,
@@ -3434,7 +3171,7 @@ THREADED_TEST(UniquePersistent) {
   }
   // Test pass from function call
   {
-    v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
+    v8::Global<String> unique = ReturnUnique(isolate, global);
     CHECK(unique == global);
     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   }
@@ -3443,6 +3180,300 @@ THREADED_TEST(UniquePersistent) {
 }
 
 
+namespace {
+
+class TwoPassCallbackData;
+void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
+void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
+
+
+class TwoPassCallbackData {
+ public:
+  TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
+      : first_pass_called_(false),
+        second_pass_called_(false),
+        trigger_gc_(false),
+        instance_counter_(instance_counter) {
+    HandleScope scope(isolate);
+    i::ScopedVector<char> buffer(40);
+    i::SNPrintF(buffer, "%p", static_cast<void*>(this));
+    auto string =
+        v8::String::NewFromUtf8(isolate, buffer.start(),
+                                v8::NewStringType::kNormal).ToLocalChecked();
+    cell_.Reset(isolate, string);
+    (*instance_counter_)++;
+  }
+
+  ~TwoPassCallbackData() {
+    CHECK(first_pass_called_);
+    CHECK(second_pass_called_);
+    CHECK(cell_.IsEmpty());
+    (*instance_counter_)--;
+  }
+
+  void FirstPass() {
+    CHECK(!first_pass_called_);
+    CHECK(!second_pass_called_);
+    CHECK(!cell_.IsEmpty());
+    cell_.Reset();
+    first_pass_called_ = true;
+  }
+
+  void SecondPass() {
+    CHECK(first_pass_called_);
+    CHECK(!second_pass_called_);
+    CHECK(cell_.IsEmpty());
+    second_pass_called_ = true;
+    delete this;
+  }
+
+  void SetWeak() {
+    cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
+  }
+
+  void MarkTriggerGc() { trigger_gc_ = true; }
+  bool trigger_gc() { return trigger_gc_; }
+
+  int* instance_counter() { return instance_counter_; }
+
+ private:
+  bool first_pass_called_;
+  bool second_pass_called_;
+  bool trigger_gc_;
+  v8::Global<v8::String> cell_;
+  int* instance_counter_;
+};
+
+
+void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
+  ApiTestFuzzer::Fuzz();
+  bool trigger_gc = data.GetParameter()->trigger_gc();
+  int* instance_counter = data.GetParameter()->instance_counter();
+  data.GetParameter()->SecondPass();
+  if (!trigger_gc) return;
+  auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
+  data_2->SetWeak();
+  CcTest::heap()->CollectAllGarbage();
+}
+
+
+void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
+  data.GetParameter()->FirstPass();
+  data.SetSecondPassCallback(SecondPassCallback);
+}
+
+}  // namespace
+
+
+TEST(TwoPassPhantomCallbacks) {
+  auto isolate = CcTest::isolate();
+  const size_t kLength = 20;
+  int instance_counter = 0;
+  for (size_t i = 0; i < kLength; ++i) {
+    auto data = new TwoPassCallbackData(isolate, &instance_counter);
+    data->SetWeak();
+  }
+  CHECK_EQ(static_cast<int>(kLength), instance_counter);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(0, instance_counter);
+}
+
+
+TEST(TwoPassPhantomCallbacksNestedGc) {
+  auto isolate = CcTest::isolate();
+  const size_t kLength = 20;
+  TwoPassCallbackData* array[kLength];
+  int instance_counter = 0;
+  for (size_t i = 0; i < kLength; ++i) {
+    array[i] = new TwoPassCallbackData(isolate, &instance_counter);
+    array[i]->SetWeak();
+  }
+  array[5]->MarkTriggerGc();
+  array[10]->MarkTriggerGc();
+  array[15]->MarkTriggerGc();
+  CHECK_EQ(static_cast<int>(kLength), instance_counter);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(0, instance_counter);
+}
+
+
+namespace {
+
+void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
+
+
+Local<v8::Object> NewObjectForIntKey(
+    v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
+    int key) {
+  auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
+  auto obj = local->NewInstance();
+  obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
+  return obj;
+}
+
+
+template <typename K, typename V>
+class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
+ public:
+  typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
+  static const v8::PersistentContainerCallbackType kCallbackType =
+      v8::kWeakWithInternalFields;
+  struct WeakCallbackDataType {
+    MapType* map;
+    K key;
+  };
+  static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
+                                                     Local<V> value) {
+    WeakCallbackDataType* data = new WeakCallbackDataType;
+    data->map = map;
+    data->key = key;
+    return data;
+  }
+  static MapType* MapFromWeakCallbackInfo(
+      const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
+    return data.GetParameter()->map;
+  }
+  static K KeyFromWeakCallbackInfo(
+      const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
+    return data.GetParameter()->key;
+  }
+  static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
+  static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
+    CHECK_EQ(IntKeyToVoidPointer(key),
+             v8::Object::GetAlignedPointerFromInternalField(value, 0));
+  }
+  static void DisposeWeak(
+      const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
+    K key = KeyFromWeakCallbackInfo(info);
+    CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
+    DisposeCallbackData(info.GetParameter());
+  }
+};
+
+
+template <typename Map>
+void TestGlobalValueMap() {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::Global<ObjectTemplate> templ;
+  {
+    HandleScope scope(isolate);
+    auto t = ObjectTemplate::New(isolate);
+    t->SetInternalFieldCount(1);
+    templ.Reset(isolate, t);
+  }
+  Map map(isolate);
+  v8::internal::GlobalHandles* global_handles =
+      reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
+  int initial_handle_count = global_handles->global_handles_count();
+  CHECK_EQ(0, static_cast<int>(map.Size()));
+  {
+    HandleScope scope(isolate);
+    Local<v8::Object> obj = map.Get(7);
+    CHECK(obj.IsEmpty());
+    Local<v8::Object> expected = v8::Object::New(isolate);
+    map.Set(7, expected);
+    CHECK_EQ(1, static_cast<int>(map.Size()));
+    obj = map.Get(7);
+    CHECK(expected->Equals(obj));
+    {
+      typename Map::PersistentValueReference ref = map.GetReference(7);
+      CHECK(expected->Equals(ref.NewLocal(isolate)));
+    }
+    v8::Global<v8::Object> removed = map.Remove(7);
+    CHECK_EQ(0, static_cast<int>(map.Size()));
+    CHECK(expected == removed);
+    removed = map.Remove(7);
+    CHECK(removed.IsEmpty());
+    map.Set(8, expected);
+    CHECK_EQ(1, static_cast<int>(map.Size()));
+    map.Set(8, expected);
+    CHECK_EQ(1, static_cast<int>(map.Size()));
+    {
+      typename Map::PersistentValueReference ref;
+      Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
+      removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
+      CHECK_EQ(1, static_cast<int>(map.Size()));
+      CHECK(expected == removed);
+      CHECK(expected2->Equals(ref.NewLocal(isolate)));
+    }
+  }
+  CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
+  if (map.IsWeak()) {
+    CcTest::i_isolate()->heap()->CollectAllGarbage(
+        i::Heap::kAbortIncrementalMarkingMask);
+  } else {
+    map.Clear();
+  }
+  CHECK_EQ(0, static_cast<int>(map.Size()));
+  CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
+  {
+    HandleScope scope(isolate);
+    Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
+    map.Set(9, value);
+    map.Clear();
+  }
+  CHECK_EQ(0, static_cast<int>(map.Size()));
+  CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
+}
+
+}  // namespace
+
+
+TEST(GlobalValueMap) {
+  // Default case, w/o weak callbacks:
+  TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
+
+  // Custom traits with weak callbacks:
+  typedef v8::GlobalValueMap<int, v8::Object,
+                             PhantomStdMapTraits<int, v8::Object>> WeakMap;
+  TestGlobalValueMap<WeakMap>();
+}
+
+
+TEST(PersistentValueVector) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::internal::GlobalHandles* global_handles =
+      reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
+  int handle_count = global_handles->global_handles_count();
+  HandleScope scope(isolate);
+
+  v8::PersistentValueVector<v8::Object> vector(isolate);
+
+  Local<v8::Object> obj1 = v8::Object::New(isolate);
+  Local<v8::Object> obj2 = v8::Object::New(isolate);
+  v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
+
+  CHECK(vector.IsEmpty());
+  CHECK_EQ(0, static_cast<int>(vector.Size()));
+
+  vector.ReserveCapacity(3);
+  CHECK(vector.IsEmpty());
+
+  vector.Append(obj1);
+  vector.Append(obj2);
+  vector.Append(obj1);
+  vector.Append(obj3.Pass());
+  vector.Append(obj1);
+
+  CHECK(!vector.IsEmpty());
+  CHECK_EQ(5, static_cast<int>(vector.Size()));
+  CHECK(obj3.IsEmpty());
+  CHECK(obj1->Equals(vector.Get(0)));
+  CHECK(obj1->Equals(vector.Get(2)));
+  CHECK(obj1->Equals(vector.Get(4)));
+  CHECK(obj2->Equals(vector.Get(1)));
+
+  CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
+
+  vector.Clear();
+  CHECK(vector.IsEmpty());
+  CHECK_EQ(0, static_cast<int>(vector.Size()));
+  CHECK_EQ(handle_count, global_handles->global_handles_count());
+}
+
+
 THREADED_TEST(GlobalHandleUpcast) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
@@ -3504,17 +3535,18 @@ THREADED_TEST(LocalHandle) {
 
 class WeakCallCounter {
  public:
-  explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
+  explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
   int id() { return id_; }
   void increment() { number_of_weak_calls_++; }
   int NumberOfWeakCalls() { return number_of_weak_calls_; }
+
  private:
   int id_;
   int number_of_weak_calls_;
 };
 
 
-template<typename T>
+template <typename T>
 struct WeakCallCounterAndPersistent {
   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
       : counter(counter) {}
@@ -3525,14 +3557,14 @@ struct WeakCallCounterAndPersistent {
 
 template <typename T>
 static void WeakPointerCallback(
-    const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T> >& data) {
+    const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
   CHECK_EQ(1234, data.GetParameter()->counter->id());
   data.GetParameter()->counter->increment();
   data.GetParameter()->handle.Reset();
 }
 
 
-template<typename T>
+template <typename T>
 static UniqueId MakeUniqueId(const Persistent<T>& p) {
   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
 }
@@ -3557,16 +3589,22 @@ THREADED_TEST(ApiObjectGroups) {
     g1s1.handle.Reset(iso, Object::New(iso));
     g1s2.handle.Reset(iso, Object::New(iso));
     g1c1.handle.Reset(iso, Object::New(iso));
-    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
-    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
-    g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
+    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
 
     g2s1.handle.Reset(iso, Object::New(iso));
     g2s2.handle.Reset(iso, Object::New(iso));
     g2c1.handle.Reset(iso, Object::New(iso));
-    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
-    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
-    g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
+    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
   }
 
   WeakCallCounterAndPersistent<Value> root(&counter);
@@ -3575,10 +3613,10 @@ THREADED_TEST(ApiObjectGroups) {
   // Connect group 1 and 2, make a cycle.
   {
     HandleScope scope(iso);
-    CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())->
-            Set(0, Local<Value>::New(iso, g2s2.handle)));
-    CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())->
-            Set(0, Local<Value>::New(iso, g1s1.handle)));
+    CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
+              ->Set(0, Local<Value>::New(iso, g2s2.handle)));
+    CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
+              ->Set(0, Local<Value>::New(iso, g1s1.handle)));
   }
 
   {
@@ -3592,15 +3630,16 @@ THREADED_TEST(ApiObjectGroups) {
     iso->SetReferenceFromGroup(id2, g2c1.handle);
   }
   // Do a single full GC, ensure incremental marking is stopped.
-  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
-      iso)->heap();
-  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  v8::internal::Heap* heap =
+      reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
+  heap->CollectAllGarbage();
 
   // All object should be alive.
   CHECK_EQ(0, counter.NumberOfWeakCalls());
 
   // Weaken the root.
-  root.handle.SetWeak(&root, &WeakPointerCallback);
+  root.handle.SetWeak(&root, &WeakPointerCallback,
+                      v8::WeakCallbackType::kParameter);
   // But make children strong roots---all the objects (except for children)
   // should be collectable now.
   g1c1.handle.ClearWeak();
@@ -3618,16 +3657,18 @@ THREADED_TEST(ApiObjectGroups) {
     iso->SetReferenceFromGroup(id2, g2c1.handle);
   }
 
-  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  heap->CollectAllGarbage();
 
   // All objects should be gone. 5 global handles in total.
   CHECK_EQ(5, counter.NumberOfWeakCalls());
 
   // And now make children weak again and collect them.
-  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
-  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
+  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
+                      v8::WeakCallbackType::kParameter);
+  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
+                      v8::WeakCallbackType::kParameter);
 
-  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  heap->CollectAllGarbage();
   CHECK_EQ(7, counter.NumberOfWeakCalls());
 }
 
@@ -3651,16 +3692,22 @@ THREADED_TEST(ApiObjectGroupsForSubtypes) {
     g1s1.handle.Reset(iso, Object::New(iso));
     g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
     g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
-    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
-    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
-    g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
+    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
 
     g2s1.handle.Reset(iso, Object::New(iso));
     g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
     g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
-    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
-    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
-    g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
+    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
   }
 
   WeakCallCounterAndPersistent<Value> root(&counter);
@@ -3686,15 +3733,16 @@ THREADED_TEST(ApiObjectGroupsForSubtypes) {
     iso->SetReferenceFromGroup(id2, g2c1.handle);
   }
   // Do a single full GC, ensure incremental marking is stopped.
-  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
-      iso)->heap();
-  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  v8::internal::Heap* heap =
+      reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
+  heap->CollectAllGarbage();
 
   // All object should be alive.
   CHECK_EQ(0, counter.NumberOfWeakCalls());
 
   // Weaken the root.
-  root.handle.SetWeak(&root, &WeakPointerCallback);
+  root.handle.SetWeak(&root, &WeakPointerCallback,
+                      v8::WeakCallbackType::kParameter);
   // But make children strong roots---all the objects (except for children)
   // should be collectable now.
   g1c1.handle.ClearWeak();
@@ -3712,16 +3760,18 @@ THREADED_TEST(ApiObjectGroupsForSubtypes) {
     iso->SetReferenceFromGroup(id2, g2c1.handle);
   }
 
-  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  heap->CollectAllGarbage();
 
   // All objects should be gone. 5 global handles in total.
   CHECK_EQ(5, counter.NumberOfWeakCalls());
 
   // And now make children weak again and collect them.
-  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
-  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
+  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
+                      v8::WeakCallbackType::kParameter);
+  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
+                      v8::WeakCallbackType::kParameter);
 
-  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  heap->CollectAllGarbage();
   CHECK_EQ(7, counter.NumberOfWeakCalls());
 }
 
@@ -3746,29 +3796,37 @@ THREADED_TEST(ApiObjectGroupsCycle) {
     HandleScope scope(iso);
     g1s1.handle.Reset(iso, Object::New(iso));
     g1s2.handle.Reset(iso, Object::New(iso));
-    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
-    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
+    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
     CHECK(g1s1.handle.IsWeak());
     CHECK(g1s2.handle.IsWeak());
 
     g2s1.handle.Reset(iso, Object::New(iso));
     g2s2.handle.Reset(iso, Object::New(iso));
-    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
-    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
+    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
     CHECK(g2s1.handle.IsWeak());
     CHECK(g2s2.handle.IsWeak());
 
     g3s1.handle.Reset(iso, Object::New(iso));
     g3s2.handle.Reset(iso, Object::New(iso));
-    g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
-    g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
+    g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
     CHECK(g3s1.handle.IsWeak());
     CHECK(g3s2.handle.IsWeak());
 
     g4s1.handle.Reset(iso, Object::New(iso));
     g4s2.handle.Reset(iso, Object::New(iso));
-    g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
-    g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
+    g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
     CHECK(g4s1.handle.IsWeak());
     CHECK(g4s2.handle.IsWeak());
   }
@@ -3798,15 +3856,16 @@ THREADED_TEST(ApiObjectGroupsCycle) {
     iso->SetReferenceFromGroup(id4, g1s1.handle);
   }
   // Do a single full GC
-  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
-      iso)->heap();
-  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  v8::internal::Heap* heap =
+      reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
+  heap->CollectAllGarbage();
 
   // All object should be alive.
   CHECK_EQ(0, counter.NumberOfWeakCalls());
 
   // Weaken the root.
-  root.handle.SetWeak(&root, &WeakPointerCallback);
+  root.handle.SetWeak(&root, &WeakPointerCallback,
+                      v8::WeakCallbackType::kParameter);
 
   // Groups are deleted, rebuild groups.
   {
@@ -3828,7 +3887,7 @@ THREADED_TEST(ApiObjectGroupsCycle) {
     iso->SetReferenceFromGroup(id4, g1s1.handle);
   }
 
-  heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  heap->CollectAllGarbage();
 
   // All objects should be gone. 9 global handles in total.
   CHECK_EQ(9, counter.NumberOfWeakCalls());
@@ -3857,18 +3916,24 @@ TEST(ApiObjectGroupsCycleForScavenger) {
     HandleScope scope(iso);
     g1s1.handle.Reset(iso, Object::New(iso));
     g1s2.handle.Reset(iso, Object::New(iso));
-    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
-    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
+    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
 
     g2s1.handle.Reset(iso, Object::New(iso));
     g2s2.handle.Reset(iso, Object::New(iso));
-    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
-    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
+    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
 
     g3s1.handle.Reset(iso, Object::New(iso));
     g3s2.handle.Reset(iso, Object::New(iso));
-    g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
-    g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
+    g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
+    g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
+                        v8::WeakCallbackType::kParameter);
   }
 
   // Make a root.
@@ -3889,27 +3954,28 @@ TEST(ApiObjectGroupsCycleForScavenger) {
     g3s2.handle.MarkPartiallyDependent();
     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
-    Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
-        v8_str("x"), Local<Value>::New(iso, g2s1.handle));
+    Local<Object>::New(iso, g1s1.handle.As<Object>())
+        ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
-    Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
-        v8_str("x"), Local<Value>::New(iso, g3s1.handle));
+    Local<Object>::New(iso, g2s1.handle.As<Object>())
+        ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
-    Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
-        v8_str("x"), Local<Value>::New(iso, g1s1.handle));
+    Local<Object>::New(iso, g3s1.handle.As<Object>())
+        ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
   }
 
-  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
-      iso)->heap();
-  heap->CollectGarbage(i::NEW_SPACE);
+  v8::internal::Heap* heap =
+      reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
+  heap->CollectAllGarbage();
 
   // All objects should be alive.
   CHECK_EQ(0, counter.NumberOfWeakCalls());
 
   // Weaken the root.
-  root.handle.SetWeak(&root, &WeakPointerCallback);
+  root.handle.SetWeak(&root, &WeakPointerCallback,
+                      v8::WeakCallbackType::kParameter);
   root.handle.MarkPartiallyDependent();
 
   // Groups are deleted, rebuild groups.
@@ -3923,19 +3989,19 @@ TEST(ApiObjectGroupsCycleForScavenger) {
     g3s2.handle.MarkPartiallyDependent();
     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
-    Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
-        v8_str("x"), Local<Value>::New(iso, g2s1.handle));
+    Local<Object>::New(iso, g1s1.handle.As<Object>())
+        ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
-    Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
-        v8_str("x"), Local<Value>::New(iso, g3s1.handle));
+    Local<Object>::New(iso, g2s1.handle.As<Object>())
+        ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
-    Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
-        v8_str("x"), Local<Value>::New(iso, g1s1.handle));
+    Local<Object>::New(iso, g3s1.handle.As<Object>())
+        ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
   }
 
-  heap->CollectGarbage(i::NEW_SPACE);
+  heap->CollectAllGarbage();
 
   // All objects should be gone. 7 global handles in total.
   CHECK_EQ(7, counter.NumberOfWeakCalls());
@@ -3945,25 +4011,29 @@ TEST(ApiObjectGroupsCycleForScavenger) {
 THREADED_TEST(ScriptException) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
-  Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
-  v8::TryCatch try_catch;
+  Local<Script> script = v8_compile("throw 'panama!';");
+  v8::TryCatch try_catch(env->GetIsolate());
   Local<Value> result = script->Run();
   CHECK(result.IsEmpty());
   CHECK(try_catch.HasCaught());
   String::Utf8Value exception_value(try_catch.Exception());
-  CHECK_EQ(*exception_value, "panama!");
+  CHECK_EQ(0, strcmp(*exception_value, "panama!"));
 }
 
 
 TEST(TryCatchCustomException) {
   LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::TryCatch try_catch;
-  CompileRun("function CustomError() { this.a = 'b'; }"
-             "(function f() { throw new CustomError(); })();");
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::TryCatch try_catch(isolate);
+  CompileRun(
+      "function CustomError() { this.a = 'b'; }"
+      "(function f() { throw new CustomError(); })();");
   CHECK(try_catch.HasCaught());
-  CHECK(try_catch.Exception()->ToObject()->
-            Get(v8_str("a"))->Equals(v8_str("b")));
+  CHECK(try_catch.Exception()
+            ->ToObject(isolate)
+            ->Get(v8_str("a"))
+            ->Equals(v8_str("b")));
 }
 
 
@@ -3973,8 +4043,7 @@ bool message_received;
 static void check_message_0(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());
+  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
   CHECK(!message->IsSharedCrossOrigin());
   message_received = true;
 }
@@ -3986,11 +4055,7 @@ THREADED_TEST(MessageHandler0) {
   CHECK(!message_received);
   LocalContext context;
   v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
-  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"));
+  v8::Handle<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
   script->Run();
   CHECK(message_received);
   // clear out the message listener
@@ -4039,8 +4104,8 @@ TEST(MessageHandler2) {
   v8::V8::AddMessageListener(check_message_2);
   LocalContext context;
   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
-  v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
-                                           v8_str("hidden value"));
+  v8::Object::Cast(*error)
+      ->SetHiddenValue(v8_str("hidden key"), v8_str("hidden value"));
   context->Global()->Set(v8_str("error"), error);
   CompileRun("throw error;");
   CHECK(message_received);
@@ -4052,7 +4117,11 @@ TEST(MessageHandler2) {
 static void check_message_3(v8::Handle<v8::Message> message,
                             v8::Handle<Value> data) {
   CHECK(message->IsSharedCrossOrigin());
-  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
+  CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
+  CHECK(message->GetScriptOrigin().Options().IsOpaque());
+  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
+  CHECK_EQ(7.40, message->GetScriptOrigin().SourceMapUrl()->NumberValue());
   message_received = true;
 }
 
@@ -4064,13 +4133,12 @@ TEST(MessageHandler3) {
   CHECK(!message_received);
   v8::V8::AddMessageListener(check_message_3);
   LocalContext context;
-  v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8_str("6.75"),
-                       v8::Integer::New(isolate, 1),
-                       v8::Integer::New(isolate, 2),
-                       v8::True(isolate));
-  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
-                                                  &origin);
+  v8::ScriptOrigin origin = v8::ScriptOrigin(
+      v8_str("6.75"), v8::Integer::New(isolate, 1),
+      v8::Integer::New(isolate, 2), v8::True(isolate), Handle<v8::Integer>(),
+      v8::True(isolate), v8_str("7.40"), v8::True(isolate));
+  v8::Handle<v8::Script> script =
+      Script::Compile(v8_str("throw 'error'"), &origin);
   script->Run();
   CHECK(message_received);
   // clear out the message listener
@@ -4081,7 +4149,7 @@ TEST(MessageHandler3) {
 static void check_message_4(v8::Handle<v8::Message> message,
                             v8::Handle<Value> data) {
   CHECK(!message->IsSharedCrossOrigin());
-  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
   message_received = true;
 }
 
@@ -4094,12 +4162,10 @@ TEST(MessageHandler4) {
   v8::V8::AddMessageListener(check_message_4);
   LocalContext context;
   v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8_str("6.75"),
-                       v8::Integer::New(isolate, 1),
-                       v8::Integer::New(isolate, 2),
-                       v8::False(isolate));
-  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
-                                                  &origin);
+      v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
+                       v8::Integer::New(isolate, 2), v8::False(isolate));
+  v8::Handle<v8::Script> script =
+      Script::Compile(v8_str("throw 'error'"), &origin);
   script->Run();
   CHECK(message_received);
   // clear out the message listener
@@ -4108,17 +4174,17 @@ TEST(MessageHandler4) {
 
 
 static void check_message_5a(v8::Handle<v8::Message> message,
-                            v8::Handle<Value> data) {
+                             v8::Handle<Value> data) {
   CHECK(message->IsSharedCrossOrigin());
-  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
   message_received = true;
 }
 
 
 static void check_message_5b(v8::Handle<v8::Message> message,
-                            v8::Handle<Value> data) {
+                             v8::Handle<Value> data) {
   CHECK(!message->IsSharedCrossOrigin());
-  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
   message_received = true;
 }
 
@@ -4130,13 +4196,11 @@ TEST(MessageHandler5) {
   CHECK(!message_received);
   v8::V8::AddMessageListener(check_message_5a);
   LocalContext context;
-  v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8_str("6.75"),
-                       v8::Integer::New(isolate, 1),
-                       v8::Integer::New(isolate, 2),
-                       v8::True(isolate));
-  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
-                                                  &origin);
+  v8::ScriptOrigin origin1 =
+      v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
+                       v8::Integer::New(isolate, 2), v8::True(isolate));
+  v8::Handle<v8::Script> script =
+      Script::Compile(v8_str("throw 'error'"), &origin1);
   script->Run();
   CHECK(message_received);
   // clear out the message listener
@@ -4144,13 +4208,10 @@ TEST(MessageHandler5) {
 
   message_received = false;
   v8::V8::AddMessageListener(check_message_5b);
-  origin =
-      v8::ScriptOrigin(v8_str("6.75"),
-                       v8::Integer::New(isolate, 1),
-                       v8::Integer::New(isolate, 2),
-                       v8::False(isolate));
-  script = Script::Compile(v8_str("throw 'error'"),
-                           &origin);
+  v8::ScriptOrigin origin2 =
+      v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
+                       v8::Integer::New(isolate, 2), v8::False(isolate));
+  script = Script::Compile(v8_str("throw 'error'"), &origin2);
   script->Run();
   CHECK(message_received);
   // clear out the message listener
@@ -4158,22 +4219,96 @@ TEST(MessageHandler5) {
 }
 
 
-THREADED_TEST(GetSetProperty) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  context->Global()->Set(v8_str("foo"), v8_num(14));
-  context->Global()->Set(v8_str("12"), v8_num(92));
-  context->Global()->Set(v8::Integer::New(isolate, 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());
+TEST(NativeWeakMap) {
+  v8::Isolate* isolate = CcTest::isolate();
+  HandleScope scope(isolate);
+  Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
+  CHECK(!weak_map.IsEmpty());
+
+  LocalContext env;
+  Local<Object> value = v8::Object::New(isolate);
+
+  Local<Object> local1 = v8::Object::New(isolate);
+  CHECK(!weak_map->Has(local1));
+  CHECK(weak_map->Get(local1)->IsUndefined());
+  weak_map->Set(local1, value);
+  CHECK(weak_map->Has(local1));
+  CHECK(value->Equals(weak_map->Get(local1)));
+
+  WeakCallCounter counter(1234);
+  WeakCallCounterAndPersistent<Value> o1(&counter);
+  WeakCallCounterAndPersistent<Value> o2(&counter);
+  WeakCallCounterAndPersistent<Value> s1(&counter);
+  {
+    HandleScope scope(isolate);
+    Local<v8::Object> obj1 = v8::Object::New(isolate);
+    Local<v8::Object> obj2 = v8::Object::New(isolate);
+    Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
+
+    weak_map->Set(obj1, value);
+    weak_map->Set(obj2, value);
+    weak_map->Set(sym1, value);
+
+    o1.handle.Reset(isolate, obj1);
+    o2.handle.Reset(isolate, obj2);
+    s1.handle.Reset(isolate, sym1);
+
+    CHECK(weak_map->Has(local1));
+    CHECK(weak_map->Has(obj1));
+    CHECK(weak_map->Has(obj2));
+    CHECK(weak_map->Has(sym1));
+
+    CHECK(value->Equals(weak_map->Get(local1)));
+    CHECK(value->Equals(weak_map->Get(obj1)));
+    CHECK(value->Equals(weak_map->Get(obj2)));
+    CHECK(value->Equals(weak_map->Get(sym1)));
+  }
+  CcTest::heap()->CollectAllGarbage();
+  {
+    HandleScope scope(isolate);
+    CHECK(value->Equals(weak_map->Get(local1)));
+    CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o1.handle))));
+    CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o2.handle))));
+    CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, s1.handle))));
+  }
+
+  o1.handle.SetWeak(&o1, &WeakPointerCallback,
+                    v8::WeakCallbackType::kParameter);
+  o2.handle.SetWeak(&o2, &WeakPointerCallback,
+                    v8::WeakCallbackType::kParameter);
+  s1.handle.SetWeak(&s1, &WeakPointerCallback,
+                    v8::WeakCallbackType::kParameter);
+
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(3, counter.NumberOfWeakCalls());
+
+  CHECK(o1.handle.IsEmpty());
+  CHECK(o2.handle.IsEmpty());
+  CHECK(s1.handle.IsEmpty());
+
+  CHECK(value->Equals(weak_map->Get(local1)));
+  CHECK(weak_map->Delete(local1));
+  CHECK(!weak_map->Has(local1));
+  CHECK(weak_map->Get(local1)->IsUndefined());
+}
+
+
+THREADED_TEST(GetSetProperty) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  context->Global()->Set(v8_str("foo"), v8_num(14));
+  context->Global()->Set(v8_str("12"), v8_num(92));
+  context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
+  context->Global()->Set(v8_num(13), v8_num(56));
+  Local<Value> foo = CompileRun("this.foo");
+  CHECK_EQ(14, foo->Int32Value());
+  Local<Value> twelve = CompileRun("this[12]");
+  CHECK_EQ(92, twelve->Int32Value());
+  Local<Value> sixteen = CompileRun("this[16]");
+  CHECK_EQ(32, sixteen->Int32Value());
+  Local<Value> thirteen = CompileRun("this[13]");
+  CHECK_EQ(56, thirteen->Int32Value());
   CHECK_EQ(92,
            context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
@@ -4198,23 +4333,23 @@ THREADED_TEST(PropertyAttributes) {
   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
   // read-only
   prop = v8_str("read_only");
-  context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
+  context->Global()->ForceSet(prop, v8_num(7), v8::ReadOnly);
   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
-  Script::Compile(v8_str("read_only = 9"))->Run();
+  CompileRun("read_only = 9");
   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);
+  context->Global()->ForceSet(prop, v8_num(13), v8::DontDelete);
   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
-  Script::Compile(v8_str("delete dont_delete"))->Run();
+  CompileRun("delete dont_delete");
   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
   // dont-enum
   prop = v8_str("dont_enum");
-  context->Global()->Set(prop, v8_num(28), v8::DontEnum);
+  context->Global()->ForceSet(prop, v8_num(28), v8::DontEnum);
   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
   // absent
   prop = v8_str("absent");
@@ -4222,13 +4357,13 @@ THREADED_TEST(PropertyAttributes) {
   Local<Value> fake_prop = v8_num(1);
   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
   // exception
-  TryCatch try_catch;
+  TryCatch try_catch(context->GetIsolate());
   Local<Value> exception =
       CompileRun("({ toString: function() { throw 'exception';} })");
   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
   CHECK(try_catch.HasCaught());
   String::Utf8Value exception_value(try_catch.Exception());
-  CHECK_EQ("exception", *exception_value);
+  CHECK_EQ(0, strcmp("exception", *exception_value));
   try_catch.Reset();
 }
 
@@ -4237,27 +4372,27 @@ THREADED_TEST(Array) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
-  CHECK_EQ(0, array->Length());
+  CHECK_EQ(0u, array->Length());
   CHECK(array->Get(0)->IsUndefined());
   CHECK(!array->Has(0));
   CHECK(array->Get(100)->IsUndefined());
   CHECK(!array->Has(100));
   array->Set(2, v8_num(7));
-  CHECK_EQ(3, array->Length());
+  CHECK_EQ(3u, array->Length());
   CHECK(!array->Has(0));
   CHECK(!array->Has(1));
   CHECK(array->Has(2));
   CHECK_EQ(7, array->Get(2)->Int32Value());
-  Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
+  Local<Value> obj = CompileRun("[1, 2, 3]");
   Local<v8::Array> arr = obj.As<v8::Array>();
-  CHECK_EQ(3, arr->Length());
+  CHECK_EQ(3u, arr->Length());
   CHECK_EQ(1, arr->Get(0)->Int32Value());
   CHECK_EQ(2, arr->Get(1)->Int32Value());
   CHECK_EQ(3, arr->Get(2)->Int32Value());
   array = v8::Array::New(context->GetIsolate(), 27);
-  CHECK_EQ(27, array->Length());
+  CHECK_EQ(27u, array->Length());
   array = v8::Array::New(context->GetIsolate(), -27);
-  CHECK_EQ(0, array->Length());
+  CHECK_EQ(0u, array->Length());
 }
 
 
@@ -4265,8 +4400,7 @@ void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
   v8::EscapableHandleScope scope(args.GetIsolate());
   ApiTestFuzzer::Fuzz();
   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
-  for (int i = 0; i < args.Length(); i++)
-    result->Set(i, args[i]);
+  for (int i = 0; i < args.Length(); i++) result->Set(i, args[i]);
   args.GetReturnValue().Set(scope.Escape(result));
 }
 
@@ -4280,29 +4414,29 @@ THREADED_TEST(Vector) {
 
   const char* fun = "f()";
   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
-  CHECK_EQ(0, a0->Length());
+  CHECK_EQ(0u, a0->Length());
 
   const char* fun2 = "f(11)";
   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
-  CHECK_EQ(1, a1->Length());
+  CHECK_EQ(1u, a1->Length());
   CHECK_EQ(11, a1->Get(0)->Int32Value());
 
   const char* fun3 = "f(12, 13)";
   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
-  CHECK_EQ(2, a2->Length());
+  CHECK_EQ(2u, a2->Length());
   CHECK_EQ(12, a2->Get(0)->Int32Value());
   CHECK_EQ(13, a2->Get(1)->Int32Value());
 
   const char* fun4 = "f(14, 15, 16)";
   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
-  CHECK_EQ(3, a3->Length());
+  CHECK_EQ(3u, a3->Length());
   CHECK_EQ(14, a3->Get(0)->Int32Value());
   CHECK_EQ(15, a3->Get(1)->Int32Value());
   CHECK_EQ(16, a3->Get(2)->Int32Value());
 
   const char* fun5 = "f(17, 18, 19, 20)";
   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
-  CHECK_EQ(4, a4->Length());
+  CHECK_EQ(4u, a4->Length());
   CHECK_EQ(17, a4->Get(0)->Int32Value());
   CHECK_EQ(18, a4->Get(1)->Int32Value());
   CHECK_EQ(19, a4->Get(2)->Int32Value());
@@ -4315,20 +4449,20 @@ THREADED_TEST(FunctionCall) {
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope scope(isolate);
   CompileRun(
-    "function Foo() {"
-    "  var result = [];"
-    "  for (var i = 0; i < arguments.length; i++) {"
-    "    result.push(arguments[i]);"
-    "  }"
-    "  return result;"
-    "}"
-    "function ReturnThisSloppy() {"
-    "  return this;"
-    "}"
-    "function ReturnThisStrict() {"
-    "  'use strict';"
-    "  return this;"
-    "}");
+      "function Foo() {"
+      "  var result = [];"
+      "  for (var i = 0; i < arguments.length; i++) {"
+      "    result.push(arguments[i]);"
+      "  }"
+      "  return result;"
+      "}"
+      "function ReturnThisSloppy() {"
+      "  return this;"
+      "}"
+      "function ReturnThisStrict() {"
+      "  'use strict';"
+      "  return this;"
+      "}");
   Local<Function> Foo =
       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   Local<Function> ReturnThisSloppy =
@@ -4338,35 +4472,30 @@ THREADED_TEST(FunctionCall) {
 
   v8::Handle<Value>* args0 = NULL;
   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
-  CHECK_EQ(0, a0->Length());
+  CHECK_EQ(0u, a0->Length());
 
-  v8::Handle<Value> args1[] = { v8_num(1.1) };
+  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(1u, a1->Length());
   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
 
-  v8::Handle<Value> args2[] = { v8_num(2.2),
-                                v8_num(3.3) };
+  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(2u, a2->Length());
   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
 
-  v8::Handle<Value> args3[] = { v8_num(4.4),
-                                v8_num(5.5),
-                                v8_num(6.6) };
+  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(3u, a3->Length());
   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
 
-  v8::Handle<Value> args4[] = { v8_num(7.7),
-                                v8_num(8.8),
-                                v8_num(9.9),
-                                v8_num(10.11) };
+  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(4u, a4->Length());
   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
@@ -4399,159 +4528,47 @@ THREADED_TEST(FunctionCall) {
 }
 
 
-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 (i::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(5 * K * K);
-  v8::SetResourceConstraints(CcTest::isolate(), &constraints);
-
-  // Execute a script that causes out of memory.
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  v8::V8::IgnoreOutOfMemoryException();
-  Local<Script> script = Script::Compile(String::NewFromUtf8(
-      context->GetIsolate(), js_code_causing_out_of_memory));
-  Local<Value> result = script->Run();
-
-  // Check for out of memory state.
-  CHECK(result.IsEmpty());
-  CHECK(context->HasOutOfMemoryException());
-}
-
-
-void ProvokeOutOfMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  Local<Script> script = Script::Compile(String::NewFromUtf8(
-      context->GetIsolate(), js_code_causing_out_of_memory));
-  Local<Value> result = script->Run();
-
-  // Check for out of memory state.
-  CHECK(result.IsEmpty());
-  CHECK(context->HasOutOfMemoryException());
-
-  args.GetReturnValue().Set(result);
-}
-
-
-TEST(OutOfMemoryNested) {
-  // It's not possible to read a snapshot into a heap with different dimensions.
-  if (i::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(5 * K * K);
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::SetResourceConstraints(isolate, &constraints);
-
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->Set(v8_str("ProvokeOutOfMemory"),
-             v8::FunctionTemplate::New(isolate, 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());
-}
-
-
-void OOMCallback(const char* location, const char* message) {
-  exit(0);
-}
-
-
-TEST(HugeConsStringOutOfMemory) {
-  // It's not possible to read a snapshot into a heap with different dimensions.
-  if (i::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(CcTest::isolate(), &constraints);
-
-  // Execute a script that causes out of memory.
-  v8::V8::SetFatalErrorHandler(OOMCallback);
-
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-
-  // Build huge string. This should fail with out of memory exception.
-  CompileRun(
-    "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
-    "for (var i = 0; i < 22; i++) { str = str + str; }");
-
-  CHECK(false);  // Should not return.
-}
-
-
 THREADED_TEST(ConstructCall) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope scope(isolate);
   CompileRun(
-    "function Foo() {"
-    "  var result = [];"
-    "  for (var i = 0; i < arguments.length; i++) {"
-    "    result.push(arguments[i]);"
-    "  }"
-    "  return result;"
-    "}");
+      "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());
+  CHECK_EQ(0u, a0->Length());
 
-  v8::Handle<Value> args1[] = { v8_num(1.1) };
+  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(1u, a1->Length());
   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
 
-  v8::Handle<Value> args2[] = { v8_num(2.2),
-                                v8_num(3.3) };
+  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(2u, a2->Length());
   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
 
-  v8::Handle<Value> args3[] = { v8_num(4.4),
-                                v8_num(5.5),
-                                v8_num(6.6) };
+  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(3u, a3->Length());
   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
 
-  v8::Handle<Value> args4[] = { v8_num(7.7),
-                                v8_num(8.8),
-                                v8_num(9.9),
-                                v8_num(10.11) };
+  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(4u, a4->Length());
   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
@@ -4562,56 +4579,58 @@ THREADED_TEST(ConstructCall) {
 static void CheckUncle(v8::TryCatch* try_catch) {
   CHECK(try_catch->HasCaught());
   String::Utf8Value str_value(try_catch->Exception());
-  CHECK_EQ(*str_value, "uncle?");
+  CHECK_EQ(0, strcmp(*str_value, "uncle?"));
   try_catch->Reset();
 }
 
 
 THREADED_TEST(ConversionNumber) {
   LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
   // Very large number.
   CompileRun("var obj = Math.pow(2,32) * 1237;");
   Local<Value> obj = env->Global()->Get(v8_str("obj"));
-  CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
-  CHECK_EQ(0, obj->ToInt32()->Value());
-  CHECK(0u == obj->ToUint32()->Value());  // NOLINT - no CHECK_EQ for unsigned.
+  CHECK_EQ(5312874545152.0, obj->ToNumber(isolate)->Value());
+  CHECK_EQ(0, obj->ToInt32(isolate)->Value());
+  CHECK(0u ==
+        obj->ToUint32(isolate)->Value());  // NOLINT - no CHECK_EQ for unsigned.
   // Large number.
   CompileRun("var obj = -1234567890123;");
   obj = env->Global()->Get(v8_str("obj"));
-  CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
-  CHECK_EQ(-1912276171, obj->ToInt32()->Value());
-  CHECK(2382691125u == obj->ToUint32()->Value());  // NOLINT
+  CHECK_EQ(-1234567890123.0, obj->ToNumber(isolate)->Value());
+  CHECK_EQ(-1912276171, obj->ToInt32(isolate)->Value());
+  CHECK(2382691125u == obj->ToUint32(isolate)->Value());  // NOLINT
   // Small positive integer.
   CompileRun("var obj = 42;");
   obj = env->Global()->Get(v8_str("obj"));
-  CHECK_EQ(42.0, obj->ToNumber()->Value());
-  CHECK_EQ(42, obj->ToInt32()->Value());
-  CHECK(42u == obj->ToUint32()->Value());  // NOLINT
+  CHECK_EQ(42.0, obj->ToNumber(isolate)->Value());
+  CHECK_EQ(42, obj->ToInt32(isolate)->Value());
+  CHECK(42u == obj->ToUint32(isolate)->Value());  // NOLINT
   // Negative integer.
   CompileRun("var obj = -37;");
   obj = env->Global()->Get(v8_str("obj"));
-  CHECK_EQ(-37.0, obj->ToNumber()->Value());
-  CHECK_EQ(-37, obj->ToInt32()->Value());
-  CHECK(4294967259u == obj->ToUint32()->Value());  // NOLINT
+  CHECK_EQ(-37.0, obj->ToNumber(isolate)->Value());
+  CHECK_EQ(-37, obj->ToInt32(isolate)->Value());
+  CHECK(4294967259u == obj->ToUint32(isolate)->Value());  // NOLINT
   // Positive non-int32 integer.
   CompileRun("var obj = 0x81234567;");
   obj = env->Global()->Get(v8_str("obj"));
-  CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
-  CHECK_EQ(-2128394905, obj->ToInt32()->Value());
-  CHECK(2166572391u == obj->ToUint32()->Value());  // NOLINT
+  CHECK_EQ(2166572391.0, obj->ToNumber(isolate)->Value());
+  CHECK_EQ(-2128394905, obj->ToInt32(isolate)->Value());
+  CHECK(2166572391u == obj->ToUint32(isolate)->Value());  // NOLINT
   // Fraction.
   CompileRun("var obj = 42.3;");
   obj = env->Global()->Get(v8_str("obj"));
-  CHECK_EQ(42.3, obj->ToNumber()->Value());
-  CHECK_EQ(42, obj->ToInt32()->Value());
-  CHECK(42u == obj->ToUint32()->Value());  // NOLINT
+  CHECK_EQ(42.3, obj->ToNumber(isolate)->Value());
+  CHECK_EQ(42, obj->ToInt32(isolate)->Value());
+  CHECK(42u == obj->ToUint32(isolate)->Value());  // NOLINT
   // Large negative fraction.
   CompileRun("var obj = -5726623061.75;");
   obj = env->Global()->Get(v8_str("obj"));
-  CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
-  CHECK_EQ(-1431655765, obj->ToInt32()->Value());
-  CHECK(2863311531u == obj->ToUint32()->Value());  // NOLINT
+  CHECK_EQ(-5726623061.75, obj->ToNumber(isolate)->Value());
+  CHECK_EQ(-1431655765, obj->ToInt32(isolate)->Value());
+  CHECK(2863311531u == obj->ToUint32(isolate)->Value());  // NOLINT
 }
 
 
@@ -4671,34 +4690,34 @@ THREADED_TEST(ConversionException) {
   v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
   CompileRun(
-    "function TestClass() { };"
-    "TestClass.prototype.toString = function () { throw 'uncle?'; };"
-    "var obj = new TestClass();");
+      "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;
+  v8::TryCatch try_catch(isolate);
 
-  Local<Value> to_string_result = obj->ToString();
+  Local<Value> to_string_result = obj->ToString(isolate);
   CHECK(to_string_result.IsEmpty());
   CheckUncle(&try_catch);
 
-  Local<Value> to_number_result = obj->ToNumber();
+  Local<Value> to_number_result = obj->ToNumber(isolate);
   CHECK(to_number_result.IsEmpty());
   CheckUncle(&try_catch);
 
-  Local<Value> to_integer_result = obj->ToInteger();
+  Local<Value> to_integer_result = obj->ToInteger(isolate);
   CHECK(to_integer_result.IsEmpty());
   CheckUncle(&try_catch);
 
-  Local<Value> to_uint32_result = obj->ToUint32();
+  Local<Value> to_uint32_result = obj->ToUint32(isolate);
   CHECK(to_uint32_result.IsEmpty());
   CheckUncle(&try_catch);
 
-  Local<Value> to_int32_result = obj->ToInt32();
+  Local<Value> to_int32_result = obj->ToInt32(isolate);
   CHECK(to_int32_result.IsEmpty());
   CheckUncle(&try_catch);
 
-  Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
+  Local<Value> to_object_result = v8::Undefined(isolate)->ToObject(isolate);
   CHECK(to_object_result.IsEmpty());
   CHECK(try_catch.HasCaught());
   try_catch.Reset();
@@ -4708,15 +4727,15 @@ THREADED_TEST(ConversionException) {
   CheckUncle(&try_catch);
 
   uint32_t uint32_value = obj->Uint32Value();
-  CHECK_EQ(0, uint32_value);
+  CHECK_EQ(0u, uint32_value);
   CheckUncle(&try_catch);
 
   double number_value = obj->NumberValue();
-  CHECK_NE(0, std::isnan(number_value));
+  CHECK(std::isnan(number_value));
   CheckUncle(&try_catch);
 
   int64_t integer_value = obj->IntegerValue();
-  CHECK_EQ(0.0, static_cast<double>(integer_value));
+  CHECK_EQ(0, integer_value);
   CheckUncle(&try_catch);
 }
 
@@ -4733,8 +4752,8 @@ void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
     return;
   }
   v8::HandleScope scope(args.GetIsolate());
-  v8::TryCatch try_catch;
-  Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
+  v8::TryCatch try_catch(args.GetIsolate());
+  Local<Value> result = CompileRun(args[0]->ToString(args.GetIsolate()));
   CHECK(!try_catch.HasCaught() || result.IsEmpty());
   args.GetReturnValue().Set(try_catch.HasCaught());
 }
@@ -4748,12 +4767,12 @@ THREADED_TEST(APICatch) {
              v8::FunctionTemplate::New(isolate, ThrowFromC));
   LocalContext context(0, templ);
   CompileRun(
-    "var thrown = false;"
-    "try {"
-    "  ThrowFromC();"
-    "} catch (e) {"
-    "  thrown = true;"
-    "}");
+      "var thrown = false;"
+      "try {"
+      "  ThrowFromC();"
+      "} catch (e) {"
+      "  thrown = true;"
+      "}");
   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
   CHECK(thrown->BooleanValue());
 }
@@ -4766,7 +4785,7 @@ THREADED_TEST(APIThrowTryCatch) {
   templ->Set(v8_str("ThrowFromC"),
              v8::FunctionTemplate::New(isolate, ThrowFromC));
   LocalContext context(0, templ);
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
   CompileRun("ThrowFromC();");
   CHECK(try_catch.HasCaught());
 }
@@ -4783,23 +4802,22 @@ TEST(TryCatchInTryFinally) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->Set(v8_str("CCatcher"),
-             v8::FunctionTemplate::New(isolate, CCatcher));
+  templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
   LocalContext context(0, templ);
-  Local<Value> result = CompileRun("try {"
-                                   "  try {"
-                                   "    CCatcher('throw 7;');"
-                                   "  } finally {"
-                                   "  }"
-                                   "} catch (e) {"
-                                   "}");
+  Local<Value> result = CompileRun(
+      "try {"
+      "  try {"
+      "    CCatcher('throw 7;');"
+      "  } finally {"
+      "  }"
+      "} catch (e) {"
+      "}");
   CHECK(result->IsTrue());
 }
 
 
-static void check_reference_error_message(
-    v8::Handle<v8::Message> message,
-    v8::Handle<v8::Value> data) {
+static void check_reference_error_message(v8::Handle<v8::Message> message,
+                                          v8::Handle<v8::Value> data) {
   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
   CHECK(message->Get()->Equals(v8_str(reference_error)));
 }
@@ -4822,17 +4840,19 @@ TEST(APIThrowMessageOverwrittenToString) {
   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
   LocalContext context(NULL, templ);
   CompileRun("asdf;");
-  CompileRun("var limit = {};"
-             "limit.valueOf = fail;"
-             "Error.stackTraceLimit = limit;");
+  CompileRun(
+      "var limit = {};"
+      "limit.valueOf = fail;"
+      "Error.stackTraceLimit = limit;");
   CompileRun("asdf");
   CompileRun("Array.prototype.pop = fail;");
   CompileRun("Object.prototype.hasOwnProperty = fail;");
   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
-  CompileRun("ReferenceError.prototype.toString ="
-             "  function() { return 'Whoops' }");
+  CompileRun(
+      "ReferenceError.prototype.toString ="
+      "  function() { return 'Whoops' }");
   CompileRun("asdf;");
   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
   CompileRun("asdf;");
@@ -4844,18 +4864,18 @@ TEST(APIThrowMessageOverwrittenToString) {
   CompileRun("asdf;");
   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
   CHECK(string->Equals(v8_str("Whoops")));
-  CompileRun("ReferenceError.prototype.constructor = new Object();"
-             "ReferenceError.prototype.constructor.name = 1;"
-             "Number.prototype.toString = function() { return 'Whoops'; };"
-             "ReferenceError.prototype.toString = Object.prototype.toString;");
+  CompileRun(
+      "ReferenceError.prototype.constructor = new Object();"
+      "ReferenceError.prototype.constructor.name = 1;"
+      "Number.prototype.toString = function() { return 'Whoops'; };"
+      "ReferenceError.prototype.toString = Object.prototype.toString;");
   CompileRun("asdf;");
   v8::V8::RemoveMessageListeners(check_reference_error_message);
 }
 
 
-static void check_custom_error_tostring(
-    v8::Handle<v8::Message> message,
-    v8::Handle<v8::Value> data) {
+static void check_custom_error_tostring(v8::Handle<v8::Message> message,
+                                        v8::Handle<v8::Value> data) {
   const char* uncaught_error = "Uncaught MyError toString";
   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
 }
@@ -4866,22 +4886,21 @@ TEST(CustomErrorToString) {
   v8::HandleScope scope(context->GetIsolate());
   v8::V8::AddMessageListener(check_custom_error_tostring);
   CompileRun(
-    "function MyError(name, message) {                   "
-    "  this.name = name;                                 "
-    "  this.message = message;                           "
-    "}                                                   "
-    "MyError.prototype = Object.create(Error.prototype); "
-    "MyError.prototype.toString = function() {           "
-    "  return 'MyError toString';                        "
-    "};                                                  "
-    "throw new MyError('my name', 'my message');         ");
+      "function MyError(name, message) {                   "
+      "  this.name = name;                                 "
+      "  this.message = message;                           "
+      "}                                                   "
+      "MyError.prototype = Object.create(Error.prototype); "
+      "MyError.prototype.toString = function() {           "
+      "  return 'MyError toString';                        "
+      "};                                                  "
+      "throw new MyError('my name', 'my message');         ");
   v8::V8::RemoveMessageListeners(check_custom_error_tostring);
 }
 
 
-static void check_custom_error_message(
-    v8::Handle<v8::Message> message,
-    v8::Handle<v8::Value> data) {
+static void check_custom_error_message(v8::Handle<v8::Message> message,
+                                       v8::Handle<v8::Value> data) {
   const char* uncaught_error = "Uncaught MyError: my message";
   printf("%s\n", *v8::String::Utf8Value(message->Get()));
   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
@@ -4895,42 +4914,62 @@ TEST(CustomErrorMessage) {
 
   // Handlebars.
   CompileRun(
-    "function MyError(msg) {                             "
-    "  this.name = 'MyError';                            "
-    "  this.message = msg;                               "
-    "}                                                   "
-    "MyError.prototype = new Error();                    "
-    "throw new MyError('my message');                    ");
+      "function MyError(msg) {                             "
+      "  this.name = 'MyError';                            "
+      "  this.message = msg;                               "
+      "}                                                   "
+      "MyError.prototype = new Error();                    "
+      "throw new MyError('my message');                    ");
 
   // Closure.
   CompileRun(
-    "function MyError(msg) {                             "
-    "  this.name = 'MyError';                            "
-    "  this.message = msg;                               "
-    "}                                                   "
-    "inherits = function(childCtor, parentCtor) {        "
-    "    function tempCtor() {};                         "
-    "    tempCtor.prototype = parentCtor.prototype;      "
-    "    childCtor.superClass_ = parentCtor.prototype;   "
-    "    childCtor.prototype = new tempCtor();           "
-    "    childCtor.prototype.constructor = childCtor;    "
-    "};                                                  "
-    "inherits(MyError, Error);                           "
-    "throw new MyError('my message');                    ");
+      "function MyError(msg) {                             "
+      "  this.name = 'MyError';                            "
+      "  this.message = msg;                               "
+      "}                                                   "
+      "inherits = function(childCtor, parentCtor) {        "
+      "    function tempCtor() {};                         "
+      "    tempCtor.prototype = parentCtor.prototype;      "
+      "    childCtor.superClass_ = parentCtor.prototype;   "
+      "    childCtor.prototype = new tempCtor();           "
+      "    childCtor.prototype.constructor = childCtor;    "
+      "};                                                  "
+      "inherits(MyError, Error);                           "
+      "throw new MyError('my message');                    ");
 
   // Object.create.
   CompileRun(
-    "function MyError(msg) {                             "
-    "  this.name = 'MyError';                            "
-    "  this.message = msg;                               "
-    "}                                                   "
-    "MyError.prototype = Object.create(Error.prototype); "
-    "throw new MyError('my message');                    ");
+      "function MyError(msg) {                             "
+      "  this.name = 'MyError';                            "
+      "  this.message = msg;                               "
+      "}                                                   "
+      "MyError.prototype = Object.create(Error.prototype); "
+      "throw new MyError('my message');                    ");
 
   v8::V8::RemoveMessageListeners(check_custom_error_message);
 }
 
 
+static void check_custom_rethrowing_message(v8::Handle<v8::Message> message,
+                                            v8::Handle<v8::Value> data) {
+  const char* uncaught_error = "Uncaught exception";
+  CHECK(message->Get()->Equals(v8_str(uncaught_error)));
+}
+
+
+TEST(CustomErrorRethrowsOnToString) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::V8::AddMessageListener(check_custom_rethrowing_message);
+
+  CompileRun(
+      "var e = { toString: function() { throw e; } };"
+      "try { throw e; } finally {}");
+
+  v8::V8::RemoveMessageListeners(check_custom_rethrowing_message);
+}
+
+
 static void receive_message(v8::Handle<v8::Message> message,
                             v8::Handle<v8::Value> data) {
   message->Get();
@@ -4962,7 +5001,7 @@ TEST(APIThrowMessageAndVerboseTryCatch) {
   templ->Set(v8_str("ThrowFromC"),
              v8::FunctionTemplate::New(isolate, ThrowFromC));
   LocalContext context(0, templ);
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
   try_catch.SetVerbose(true);
   Local<Value> result = CompileRun("ThrowFromC();");
   CHECK(try_catch.HasCaught());
@@ -4977,7 +5016,7 @@ TEST(APIStackOverflowAndVerboseTryCatch) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
   v8::V8::AddMessageListener(receive_message);
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(context->GetIsolate());
   try_catch.SetVerbose(true);
   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
   CHECK(try_catch.HasCaught());
@@ -4995,18 +5034,15 @@ THREADED_TEST(ExternalScriptException) {
              v8::FunctionTemplate::New(isolate, ThrowFromC));
   LocalContext context(0, templ);
 
-  v8::TryCatch try_catch;
-  Local<Script> script
-      = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
-  Local<Value> result = script->Run();
+  v8::TryCatch try_catch(isolate);
+  Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
   CHECK(result.IsEmpty());
   CHECK(try_catch.HasCaught());
   String::Utf8Value exception_value(try_catch.Exception());
-  CHECK_EQ("konto", *exception_value);
+  CHECK_EQ(0, strcmp("konto", *exception_value));
 }
 
 
-
 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
   CHECK_EQ(4, args.Length());
@@ -5016,15 +5052,11 @@ void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
     args.GetIsolate()->ThrowException(v8_str("FromC"));
     return;
   } else {
-    Local<v8::Object> global =
-        args.GetIsolate()->GetCurrentContext()->Global();
+    Local<v8::Object> global = args.GetIsolate()->GetCurrentContext()->Global();
     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
-    v8::Handle<Value> argv[] = { v8_num(count - 1),
-                                 args[1],
-                                 args[2],
-                                 args[3] };
+    v8::Handle<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
     if (count % cInterval == 0) {
-      v8::TryCatch try_catch;
+      v8::TryCatch try_catch(args.GetIsolate());
       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
       int expected = args[3]->Int32Value();
       if (try_catch.HasCaught()) {
@@ -5061,14 +5093,15 @@ void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
 THREADED_TEST(EvalInTryFinally) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
-  v8::TryCatch try_catch;
-  CompileRun("(function() {"
-             "  try {"
-             "    eval('asldkf (*&^&*^');"
-             "  } finally {"
-             "    return;"
-             "  }"
-             "})()");
+  v8::TryCatch try_catch(context->GetIsolate());
+  CompileRun(
+      "(function() {"
+      "  try {"
+      "    eval('asldkf (*&^&*^');"
+      "  } finally {"
+      "    return;"
+      "  }"
+      "})()");
   CHECK(!try_catch.HasCaught());
 }
 
@@ -5102,23 +5135,23 @@ TEST(ExceptionOrder) {
              v8::FunctionTemplate::New(isolate, 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);"
-    "  }"
-    "}");
+      "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")));
 
@@ -5126,27 +5159,27 @@ TEST(ExceptionOrder) {
   //                             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) };
+  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) };
+  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) };
+  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) };
+  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) };
+  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) };
+  v8::Handle<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
   fun->Call(fun, argc, a5);
 }
 
@@ -5165,16 +5198,16 @@ THREADED_TEST(ThrowValues) {
   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, 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());
+      "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(5u, result->Length());
   CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
   CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
   CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
@@ -5188,14 +5221,14 @@ THREADED_TEST(ThrowValues) {
 THREADED_TEST(CatchZero) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(context->GetIsolate());
   CHECK(!try_catch.HasCaught());
-  Script::Compile(v8_str("throw 10"))->Run();
+  CompileRun("throw 10");
   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();
+  CompileRun("throw 0");
   CHECK(try_catch.HasCaught());
   CHECK_EQ(0, try_catch.Exception()->Int32Value());
 }
@@ -5204,9 +5237,9 @@ THREADED_TEST(CatchZero) {
 THREADED_TEST(CatchExceptionFromWith) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(context->GetIsolate());
   CHECK(!try_catch.HasCaught());
-  Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
+  CompileRun("var o = {}; with (o) { throw 42; }");
   CHECK(try_catch.HasCaught());
 }
 
@@ -5214,7 +5247,7 @@ THREADED_TEST(CatchExceptionFromWith) {
 THREADED_TEST(TryCatchAndFinallyHidingException) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(context->GetIsolate());
   CHECK(!try_catch.HasCaught());
   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
   CompileRun("f({toString: function() { throw 42; }});");
@@ -5223,7 +5256,7 @@ THREADED_TEST(TryCatchAndFinallyHidingException) {
 
 
 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(args.GetIsolate());
 }
 
 
@@ -5234,7 +5267,7 @@ THREADED_TEST(TryCatchAndFinally) {
   context->Global()->Set(
       v8_str("native_with_try_catch"),
       v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
   CHECK(!try_catch.HasCaught());
   CompileRun(
       "try {\n"
@@ -5246,15 +5279,28 @@ THREADED_TEST(TryCatchAndFinally) {
 }
 
 
-static void TryCatchNestedHelper(int depth) {
+static void TryCatchNested1Helper(int depth) {
   if (depth > 0) {
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(CcTest::isolate());
+    try_catch.SetVerbose(true);
+    TryCatchNested1Helper(depth - 1);
+    CHECK(try_catch.HasCaught());
+    try_catch.ReThrow();
+  } else {
+    CcTest::isolate()->ThrowException(v8_str("E1"));
+  }
+}
+
+
+static void TryCatchNested2Helper(int depth) {
+  if (depth > 0) {
+    v8::TryCatch try_catch(CcTest::isolate());
     try_catch.SetVerbose(true);
-    TryCatchNestedHelper(depth - 1);
+    TryCatchNested2Helper(depth - 1);
     CHECK(try_catch.HasCaught());
     try_catch.ReThrow();
   } else {
-    CcTest::isolate()->ThrowException(v8_str("back"));
+    CompileRun("throw 'E2';");
   }
 }
 
@@ -5263,29 +5309,41 @@ TEST(TryCatchNested) {
   v8::V8::Initialize();
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
-  v8::TryCatch try_catch;
-  TryCatchNestedHelper(5);
-  CHECK(try_catch.HasCaught());
-  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
+
+  {
+    // Test nested try-catch with a native throw in the end.
+    v8::TryCatch try_catch(context->GetIsolate());
+    TryCatchNested1Helper(5);
+    CHECK(try_catch.HasCaught());
+    CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
+  }
+
+  {
+    // Test nested try-catch with a JavaScript throw in the end.
+    v8::TryCatch try_catch(context->GetIsolate());
+    TryCatchNested2Helper(5);
+    CHECK(try_catch.HasCaught());
+    CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
+  }
 }
 
 
 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
   CHECK(try_catch->HasCaught());
   Handle<Message> message = try_catch->Message();
-  Handle<Value> resource = message->GetScriptResourceName();
+  Handle<Value> resource = message->GetScriptOrigin().ResourceName();
   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
-  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
-                     "Uncaught Error: a"));
+  CHECK_EQ(0,
+           strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
   CHECK_EQ(1, message->GetLineNumber());
-  CHECK_EQ(6, message->GetStartColumn());
+  CHECK_EQ(0, message->GetStartColumn());
 }
 
 
 void TryCatchMixedNestingHelper(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(args.GetIsolate());
   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
   CHECK(try_catch.HasCaught());
   TryCatchMixedNestingCheck(&try_catch);
@@ -5302,7 +5360,7 @@ TEST(TryCatchMixedNesting) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
   v8::V8::Initialize();
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   templ->Set(v8_str("TryCatchMixedNestingHelper"),
              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
@@ -5312,6 +5370,53 @@ TEST(TryCatchMixedNesting) {
 }
 
 
+void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
+  v8::TryCatch try_catch(args.GetIsolate());
+  args.GetIsolate()->ThrowException(v8_str("boom"));
+  CHECK(try_catch.HasCaught());
+}
+
+
+TEST(TryCatchNative) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::V8::Initialize();
+  v8::TryCatch try_catch(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->Set(v8_str("TryCatchNativeHelper"),
+             v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
+  LocalContext context(0, templ);
+  CompileRun("TryCatchNativeHelper();");
+  CHECK(!try_catch.HasCaught());
+}
+
+
+void TryCatchNativeResetHelper(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
+  v8::TryCatch try_catch(args.GetIsolate());
+  args.GetIsolate()->ThrowException(v8_str("boom"));
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  CHECK(!try_catch.HasCaught());
+}
+
+
+TEST(TryCatchNativeReset) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::V8::Initialize();
+  v8::TryCatch try_catch(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->Set(v8_str("TryCatchNativeResetHelper"),
+             v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
+  LocalContext context(0, templ);
+  CompileRun("TryCatchNativeResetHelper();");
+  CHECK(!try_catch.HasCaught());
+}
+
+
 THREADED_TEST(Equality) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
@@ -5320,11 +5425,11 @@ THREADED_TEST(Equality) {
   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));
+  CHECK(v8_str("a")->Equals(v8_str("a")));
+  CHECK(!v8_str("a")->Equals(v8_str("b")));
+  CHECK(v8_num(1)->Equals(v8_num(1)));
+  CHECK(v8_num(1.00)->Equals(v8_num(1)));
+  CHECK(!v8_num(1)->Equals(v8_num(2)));
 
   // Assume String is not internalized.
   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
@@ -5333,7 +5438,7 @@ THREADED_TEST(Equality) {
   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
-  Local<Value> not_a_number = v8_num(i::OS::nan_value());
+  Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
   CHECK(!not_a_number->StrictEquals(not_a_number));
   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
@@ -5358,17 +5463,16 @@ THREADED_TEST(Equality) {
 THREADED_TEST(MultiRun) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
-  Local<Script> script = Script::Compile(v8_str("x"));
-  for (int i = 0; i < 10; i++)
-    script->Run();
+  Local<Script> script = v8_compile("x");
+  for (int i = 0; i < 10; i++) script->Run();
 }
 
 
 static void GetXValue(Local<String> name,
                       const v8::PropertyCallbackInfo<v8::Value>& info) {
   ApiTestFuzzer::Fuzz();
-  CHECK_EQ(info.Data(), v8_str("donut"));
-  CHECK_EQ(name, v8_str("x"));
+  CHECK(info.Data()->Equals(v8_str("donut")));
+  CHECK(name->Equals(v8_str("x")));
   info.GetReturnValue().Set(name);
 }
 
@@ -5380,10 +5484,10 @@ THREADED_TEST(SimplePropertyRead) {
   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   context->Global()->Set(v8_str("obj"), templ->NewInstance());
-  Local<Script> script = Script::Compile(v8_str("obj.x"));
+  Local<Script> script = v8_compile("obj.x");
   for (int i = 0; i < 10; i++) {
     Local<Value> result = script->Run();
-    CHECK_EQ(result, v8_str("x"));
+    CHECK(result->Equals(v8_str("x")));
   }
 }
 
@@ -5397,43 +5501,44 @@ THREADED_TEST(DefinePropertyOnAPIAccessor) {
   context->Global()->Set(v8_str("obj"), templ->NewInstance());
 
   // Uses getOwnPropertyDescriptor to check the configurable status
-  Local<Script> script_desc
-    = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
-                             "obj, 'x');"
-                             "prop.configurable;"));
+  Local<Script> script_desc = v8_compile(
+      "var prop = Object.getOwnPropertyDescriptor( "
+      "obj, 'x');"
+      "prop.configurable;");
   Local<Value> result = script_desc->Run();
   CHECK_EQ(result->BooleanValue(), true);
 
   // Redefine get - but still configurable
-  Local<Script> script_define
-    = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
-                             "            configurable: true };"
-                             "Object.defineProperty(obj, 'x', desc);"
-                             "obj.x"));
+  Local<Script> script_define = v8_compile(
+      "var desc = { get: function(){return 42; },"
+      "            configurable: true };"
+      "Object.defineProperty(obj, 'x', desc);"
+      "obj.x");
   result = script_define->Run();
-  CHECK_EQ(result, v8_num(42));
+  CHECK(result->Equals(v8_num(42)));
 
   // Check that the accessor is still configurable
   result = script_desc->Run();
   CHECK_EQ(result->BooleanValue(), true);
 
   // Redefine to a non-configurable
-  script_define
-    = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
-                             "             configurable: false };"
-                             "Object.defineProperty(obj, 'x', desc);"
-                             "obj.x"));
+  script_define = v8_compile(
+      "var desc = { get: function(){return 43; },"
+      "             configurable: false };"
+      "Object.defineProperty(obj, 'x', desc);"
+      "obj.x");
   result = script_define->Run();
-  CHECK_EQ(result, v8_num(43));
+  CHECK(result->Equals(v8_num(43)));
   result = script_desc->Run();
   CHECK_EQ(result->BooleanValue(), false);
 
   // Make sure that it is not possible to redefine again
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
   result = script_define->Run();
   CHECK(try_catch.HasCaught());
   String::Utf8Value exception_value(try_catch.Exception());
-  CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
+  CHECK_EQ(0,
+           strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
 }
 
 
@@ -5445,42 +5550,44 @@ THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
   LocalContext context;
   context->Global()->Set(v8_str("obj"), templ->NewInstance());
 
-  Local<Script> script_desc = Script::Compile(v8_str("var prop ="
-                                    "Object.getOwnPropertyDescriptor( "
-                                    "obj, 'x');"
-                                    "prop.configurable;"));
+  Local<Script> script_desc = v8_compile(
+      "var prop ="
+      "Object.getOwnPropertyDescriptor( "
+      "obj, 'x');"
+      "prop.configurable;");
   Local<Value> result = script_desc->Run();
   CHECK_EQ(result->BooleanValue(), true);
 
-  Local<Script> script_define =
-    Script::Compile(v8_str("var desc = {get: function(){return 42; },"
-                           "            configurable: true };"
-                           "Object.defineProperty(obj, 'x', desc);"
-                           "obj.x"));
+  Local<Script> script_define = v8_compile(
+      "var desc = {get: function(){return 42; },"
+      "            configurable: true };"
+      "Object.defineProperty(obj, 'x', desc);"
+      "obj.x");
   result = script_define->Run();
-  CHECK_EQ(result, v8_num(42));
+  CHECK(result->Equals(v8_num(42)));
 
 
   result = script_desc->Run();
   CHECK_EQ(result->BooleanValue(), true);
 
 
-  script_define =
-    Script::Compile(v8_str("var desc = {get: function(){return 43; },"
-                           "            configurable: false };"
-                           "Object.defineProperty(obj, 'x', desc);"
-                           "obj.x"));
+  script_define = v8_compile(
+      "var desc = {get: function(){return 43; },"
+      "            configurable: false };"
+      "Object.defineProperty(obj, 'x', desc);"
+      "obj.x");
   result = script_define->Run();
-  CHECK_EQ(result, v8_num(43));
+  CHECK(result->Equals(v8_num(43)));
   result = script_desc->Run();
 
   CHECK_EQ(result->BooleanValue(), false);
 
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
   result = script_define->Run();
   CHECK(try_catch.HasCaught());
   String::Utf8Value exception_value(try_catch.Exception());
-  CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
+  CHECK_EQ(0,
+           strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
 }
 
 
@@ -5502,14 +5609,14 @@ THREADED_TEST(DefineAPIAccessorOnObject) {
   CHECK(CompileRun("obj1.x")->IsUndefined());
   CHECK(CompileRun("obj2.x")->IsUndefined());
 
-  CHECK(GetGlobalProperty(&context, "obj1")->
-      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
+  CHECK(GetGlobalProperty(&context, "obj1")
+            ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
 
   ExpectString("obj1.x", "x");
   CHECK(CompileRun("obj2.x")->IsUndefined());
 
-  CHECK(GetGlobalProperty(&context, "obj2")->
-      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
+  CHECK(GetGlobalProperty(&context, "obj2")
+            ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
 
   ExpectString("obj1.x", "x");
   ExpectString("obj2.x", "x");
@@ -5517,14 +5624,16 @@ THREADED_TEST(DefineAPIAccessorOnObject) {
   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
 
-  CompileRun("Object.defineProperty(obj1, 'x',"
-             "{ get: function() { return 'y'; }, configurable: true })");
+  CompileRun(
+      "Object.defineProperty(obj1, 'x',"
+      "{ get: function() { return 'y'; }, configurable: true })");
 
   ExpectString("obj1.x", "y");
   ExpectString("obj2.x", "x");
 
-  CompileRun("Object.defineProperty(obj2, 'x',"
-             "{ get: function() { return 'y'; }, configurable: true })");
+  CompileRun(
+      "Object.defineProperty(obj2, 'x',"
+      "{ get: function() { return 'y'; }, configurable: true })");
 
   ExpectString("obj1.x", "y");
   ExpectString("obj2.x", "y");
@@ -5532,10 +5641,10 @@ THREADED_TEST(DefineAPIAccessorOnObject) {
   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
 
-  CHECK(GetGlobalProperty(&context, "obj1")->
-      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
-  CHECK(GetGlobalProperty(&context, "obj2")->
-      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
+  CHECK(GetGlobalProperty(&context, "obj1")
+            ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
+  CHECK(GetGlobalProperty(&context, "obj2")
+            ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
 
   ExpectString("obj1.x", "x");
   ExpectString("obj2.x", "x");
@@ -5544,10 +5653,12 @@ THREADED_TEST(DefineAPIAccessorOnObject) {
   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
 
   // Define getters/setters, but now make them not configurable.
-  CompileRun("Object.defineProperty(obj1, 'x',"
-             "{ get: function() { return 'z'; }, configurable: false })");
-  CompileRun("Object.defineProperty(obj2, 'x',"
-             "{ get: function() { return 'z'; }, configurable: false })");
+  CompileRun(
+      "Object.defineProperty(obj1, 'x',"
+      "{ get: function() { return 'z'; }, configurable: false })");
+  CompileRun(
+      "Object.defineProperty(obj2, 'x',"
+      "{ get: function() { return 'z'; }, configurable: false })");
 
   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
@@ -5555,10 +5666,10 @@ THREADED_TEST(DefineAPIAccessorOnObject) {
   ExpectString("obj1.x", "z");
   ExpectString("obj2.x", "z");
 
-  CHECK(!GetGlobalProperty(&context, "obj1")->
-      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
-  CHECK(!GetGlobalProperty(&context, "obj2")->
-      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
+  CHECK(!GetGlobalProperty(&context, "obj1")
+             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
+  CHECK(!GetGlobalProperty(&context, "obj2")
+             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
 
   ExpectString("obj1.x", "z");
   ExpectString("obj2.x", "z");
@@ -5574,14 +5685,12 @@ THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   CompileRun("var obj2 = {};");
 
-  CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
-        v8_str("x"),
-        GetXValue, NULL,
-        v8_str("donut"), v8::DEFAULT, v8::DontDelete));
-  CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
-        v8_str("x"),
-        GetXValue, NULL,
-        v8_str("donut"), v8::DEFAULT, v8::DontDelete));
+  CHECK(GetGlobalProperty(&context, "obj1")
+            ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
+                          v8::DEFAULT, v8::DontDelete));
+  CHECK(GetGlobalProperty(&context, "obj2")
+            ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
+                          v8::DEFAULT, v8::DontDelete));
 
   ExpectString("obj1.x", "x");
   ExpectString("obj2.x", "x");
@@ -5589,26 +5698,30 @@ THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
 
-  CHECK(!GetGlobalProperty(&context, "obj1")->
-      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
-  CHECK(!GetGlobalProperty(&context, "obj2")->
-      SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
+  CHECK(!GetGlobalProperty(&context, "obj1")
+             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
+  CHECK(!GetGlobalProperty(&context, "obj2")
+             ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
 
   {
-    v8::TryCatch try_catch;
-    CompileRun("Object.defineProperty(obj1, 'x',"
+    v8::TryCatch try_catch(isolate);
+    CompileRun(
+        "Object.defineProperty(obj1, 'x',"
         "{get: function() { return 'func'; }})");
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value(try_catch.Exception());
-    CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
+    CHECK_EQ(
+        0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   }
   {
-    v8::TryCatch try_catch;
-    CompileRun("Object.defineProperty(obj2, 'x',"
+    v8::TryCatch try_catch(isolate);
+    CompileRun(
+        "Object.defineProperty(obj2, 'x',"
         "{get: function() { return 'func'; }})");
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value(try_catch.Exception());
-    CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
+    CHECK_EQ(
+        0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   }
 }
 
@@ -5616,8 +5729,8 @@ THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
 static void Get239Value(Local<String> name,
                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   ApiTestFuzzer::Fuzz();
-  CHECK_EQ(info.Data(), v8_str("donut"));
-  CHECK_EQ(name, v8_str("239"));
+  CHECK(info.Data()->Equals(v8_str("donut")));
+  CHECK(name->Equals(v8_str("239")));
   info.GetReturnValue().Set(name);
 }
 
@@ -5631,14 +5744,10 @@ THREADED_TEST(ElementAPIAccessor) {
   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   CompileRun("var obj2 = {};");
 
-  CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
-        v8_str("239"),
-        Get239Value, NULL,
-        v8_str("donut")));
-  CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
-        v8_str("239"),
-        Get239Value, NULL,
-        v8_str("donut")));
+  CHECK(GetGlobalProperty(&context, "obj1")
+            ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
+  CHECK(GetGlobalProperty(&context, "obj2")
+            ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
 
   ExpectString("obj1[239]", "239");
   ExpectString("obj2[239]", "239");
@@ -5650,12 +5759,11 @@ THREADED_TEST(ElementAPIAccessor) {
 v8::Persistent<Value> xValue;
 
 
-static void SetXValue(Local<String> name,
-                      Local<Value> value,
+static void SetXValue(Local<String> name, Local<Value> value,
                       const v8::PropertyCallbackInfo<void>& info) {
-  CHECK_EQ(value, v8_num(4));
-  CHECK_EQ(info.Data(), v8_str("donut"));
-  CHECK_EQ(name, v8_str("x"));
+  CHECK(value->Equals(v8_num(4)));
+  CHECK(info.Data()->Equals(v8_str("donut")));
+  CHECK(name->Equals(v8_str("x")));
   CHECK(xValue.IsEmpty());
   xValue.Reset(info.GetIsolate(), value);
 }
@@ -5668,11 +5776,11 @@ THREADED_TEST(SimplePropertyWrite) {
   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"));
+  Local<Script> script = v8_compile("obj.x = 4");
   for (int i = 0; i < 10; i++) {
     CHECK(xValue.IsEmpty());
     script->Run();
-    CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
+    CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
     xValue.Reset();
   }
 }
@@ -5685,11 +5793,11 @@ THREADED_TEST(SetterOnly) {
   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
   LocalContext context;
   context->Global()->Set(v8_str("obj"), templ->NewInstance());
-  Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
+  Local<Script> script = v8_compile("obj.x = 4; obj.x");
   for (int i = 0; i < 10; i++) {
     CHECK(xValue.IsEmpty());
     script->Run();
-    CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
+    CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
     xValue.Reset();
   }
 }
@@ -5699,1385 +5807,898 @@ THREADED_TEST(NoAccessors) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetAccessor(v8_str("x"),
-                     static_cast<v8::AccessorGetterCallback>(NULL),
-                     NULL,
-                     v8_str("donut"));
+  templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
+                     NULL, v8_str("donut"));
   LocalContext context;
   context->Global()->Set(v8_str("obj"), templ->NewInstance());
-  Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
+  Local<Script> script = v8_compile("obj.x = 4; obj.x");
   for (int i = 0; i < 10; i++) {
     script->Run();
   }
 }
 
 
-static void XPropertyGetter(Local<String> property,
-                            const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.Data()->IsUndefined());
-  info.GetReturnValue().Set(property);
-}
-
-
-THREADED_TEST(NamedInterceptorPropertyRead) {
+THREADED_TEST(MultiContexts) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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"));
-  }
-}
+  v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->Set(v8_str("dummy"),
+             v8::FunctionTemplate::New(isolate, DummyCallHandler));
 
+  Local<String> password = v8_str("Password");
 
-THREADED_TEST(NamedInterceptorDictionaryIC) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(XPropertyGetter);
-  LocalContext context;
-  // Create an object with a named interceptor.
-  context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
-  Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
-  for (int i = 0; i < 10; i++) {
-    Local<Value> result = script->Run();
-    CHECK_EQ(result, v8_str("x"));
-  }
-  // Create a slow case object and a function accessing a property in
-  // that slow case object (with dictionary probing in generated
-  // code). Then force object with a named interceptor into slow-case,
-  // pass it to the function, and check that the interceptor is called
-  // instead of accessing the local property.
-  Local<Value> result =
-      CompileRun("function get_x(o) { return o.x; };"
-                 "var obj = { x : 42, y : 0 };"
-                 "delete obj.y;"
-                 "for (var i = 0; i < 10; i++) get_x(obj);"
-                 "interceptor_obj.x = 42;"
-                 "interceptor_obj.y = 10;"
-                 "delete interceptor_obj.y;"
-                 "get_x(interceptor_obj)");
-  CHECK_EQ(result, v8_str("x"));
-}
-
-
-THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> context1 = Context::New(isolate);
+  // 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());
 
-  context1->Enter();
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(XPropertyGetter);
-  // Create an object with a named interceptor.
-  v8::Local<v8::Object> object = templ->NewInstance();
-  context1->Global()->Set(v8_str("interceptor_obj"), object);
-
-  // Force the object into the slow case.
-  CompileRun("interceptor_obj.y = 0;"
-             "delete interceptor_obj.y;");
-  context1->Exit();
+  // 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(!global0->Equals(global1));
+  CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
+  CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
 
-  {
-    // Introduce the object into a different context.
-    // Repeat named loads to exercise ICs.
-    LocalContext context2;
-    context2->Global()->Set(v8_str("interceptor_obj"), object);
-    Local<Value> result =
-      CompileRun("function get_x(o) { return o.x; }"
-                 "interceptor_obj.x = 42;"
-                 "for (var i=0; i != 10; i++) {"
-                 "  get_x(interceptor_obj);"
-                 "}"
-                 "get_x(interceptor_obj)");
-    // Check that the interceptor was actually invoked.
-    CHECK_EQ(result, v8_str("x"));
-  }
-
-  // Return to the original context and force some object to the slow case
-  // to cause the NormalizedMapCache to verify.
-  context1->Enter();
-  CompileRun("var obj = { x : 0 }; delete obj.x;");
-  context1->Exit();
+  // 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(global1->Equals(global2));
+  CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
+  CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
 }
 
 
-static void SetXOnPrototypeGetter(
-    Local<String> property,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  // Set x on the prototype object and do not handle the get request.
-  v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
-  proto.As<v8::Object>()->Set(v8_str("x"),
-                              v8::Integer::New(info.GetIsolate(), 23));
-}
+THREADED_TEST(FunctionPrototypeAcrossContexts) {
+  // Make sure that functions created by cloning boilerplates cannot
+  // communicate through their __proto__ field.
 
+  v8::HandleScope scope(CcTest::isolate());
 
-// This is a regression test for http://crbug.com/20104. Map
-// transitions should not interfere with post interceptor lookup.
-THREADED_TEST(NamedInterceptorMapTransitionRead) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<v8::FunctionTemplate> function_template =
-      v8::FunctionTemplate::New(isolate);
-  Local<v8::ObjectTemplate> instance_template
-      = function_template->InstanceTemplate();
-  instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
-  LocalContext context;
-  context->Global()->Set(v8_str("F"), function_template->GetFunction());
-  // Create an instance of F and introduce a map transition for x.
-  CompileRun("var o = new F(); o.x = 23;");
-  // Create an instance of F and invoke the getter. The result should be 23.
-  Local<Value> result = CompileRun("o = new F(); o.x");
-  CHECK_EQ(result->Int32Value(), 23);
-}
-
+  LocalContext env0;
+  v8::Handle<v8::Object> global0 = env0->Global();
+  v8::Handle<v8::Object> object0 =
+      global0->Get(v8_str("Object")).As<v8::Object>();
+  v8::Handle<v8::Object> tostring0 =
+      object0->Get(v8_str("toString")).As<v8::Object>();
+  v8::Handle<v8::Object> proto0 =
+      tostring0->Get(v8_str("__proto__")).As<v8::Object>();
+  proto0->Set(v8_str("custom"), v8_num(1234));
 
-static void IndexedPropertyGetter(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (index == 37) {
-    info.GetReturnValue().Set(v8_num(625));
-  }
+  LocalContext env1;
+  v8::Handle<v8::Object> global1 = env1->Global();
+  v8::Handle<v8::Object> object1 =
+      global1->Get(v8_str("Object")).As<v8::Object>();
+  v8::Handle<v8::Object> tostring1 =
+      object1->Get(v8_str("toString")).As<v8::Object>();
+  v8::Handle<v8::Object> proto1 =
+      tostring1->Get(v8_str("__proto__")).As<v8::Object>();
+  CHECK(!proto1->Has(v8_str("custom")));
 }
 
 
-static void IndexedPropertySetter(
-    uint32_t index,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (index == 39) {
-    info.GetReturnValue().Set(value);
-  }
-}
+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(CcTest::isolate());
 
-THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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);
-}
-
-
-static void UnboxedDoubleIndexedPropertyGetter(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (index < 25) {
-    info.GetReturnValue().Set(v8_num(index));
-  }
-}
+  Local<String> source = v8_str(
+      "Object.prototype.obj = 1234;"
+      "Array.prototype.arr = 4567;"
+      "8901");
 
+  LocalContext env0;
+  Local<Script> script0 = v8_compile(source);
+  CHECK_EQ(8901.0, script0->Run()->NumberValue());
 
-static void UnboxedDoubleIndexedPropertySetter(
-    uint32_t index,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (index < 25) {
-    info.GetReturnValue().Set(v8_num(index));
-  }
+  LocalContext env1;
+  Local<Script> script1 = v8_compile(source);
+  CHECK_EQ(8901.0, script1->Run()->NumberValue());
 }
 
 
-void UnboxedDoubleIndexedPropertyEnumerator(
-    const v8::PropertyCallbackInfo<v8::Array>& info) {
-  // Force the list of returned keys to be stored in a FastDoubleArray.
-  Local<Script> indexed_property_names_script = Script::Compile(v8_str(
-      "keys = new Array(); keys[125000] = 1;"
-      "for(i = 0; i < 80000; i++) { keys[i] = i; };"
-      "keys.length = 25; keys;"));
-  Local<Value> result = indexed_property_names_script->Run();
-  info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
-}
+THREADED_TEST(UndetectableObject) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
 
+  Local<v8::FunctionTemplate> desc =
+      v8::FunctionTemplate::New(env->GetIsolate());
+  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
 
-// Make sure that the the interceptor code in the runtime properly handles
-// merging property name lists for double-array-backed arrays.
-THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
-                                   UnboxedDoubleIndexedPropertySetter,
-                                   0,
-                                   0,
-                                   UnboxedDoubleIndexedPropertyEnumerator);
-  LocalContext context;
-  context->Global()->Set(v8_str("obj"), templ->NewInstance());
-  // When obj is created, force it to be Stored in a FastDoubleArray.
-  Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
-      "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
-      "key_count = 0; "
-      "for (x in obj) {key_count++;};"
-      "obj;"));
-  Local<Value> result = create_unboxed_double_script->Run();
-  CHECK(result->ToObject()->HasRealIndexedProperty(2000));
-  Local<Script> key_count_check = Script::Compile(v8_str(
-      "key_count;"));
-  result = key_count_check->Run();
-  CHECK_EQ(v8_num(40013), result);
-}
-
-
-void NonStrictArgsIndexedPropertyEnumerator(
-    const v8::PropertyCallbackInfo<v8::Array>& info) {
-  // Force the list of returned keys to be stored in a Arguments object.
-  Local<Script> indexed_property_names_script = Script::Compile(v8_str(
-      "function f(w,x) {"
-      " return arguments;"
-      "}"
-      "keys = f(0, 1, 2, 3);"
-      "keys;"));
-  Local<Object> result =
-      Local<Object>::Cast(indexed_property_names_script->Run());
-  // Have to populate the handle manually, as it's not Cast-able.
-  i::Handle<i::JSObject> o =
-      v8::Utils::OpenHandle<Object, i::JSObject>(result);
-  i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
-  info.GetReturnValue().Set(v8::Utils::ToLocal(array));
-}
+  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);
 
-static void NonStrictIndexedPropertyGetter(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (index < 4) {
-    info.GetReturnValue().Set(v8_num(index));
-  }
-}
+  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);
 
-// Make sure that the the interceptor code in the runtime properly handles
-// merging property name lists for non-string arguments arrays.
-THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
-                                   0,
-                                   0,
-                                   0,
-                                   NonStrictArgsIndexedPropertyEnumerator);
-  LocalContext context;
-  context->Global()->Set(v8_str("obj"), templ->NewInstance());
-  Local<Script> create_args_script =
-      Script::Compile(v8_str(
-          "var key_count = 0;"
-          "for (x in obj) {key_count++;} key_count;"));
-  Local<Value> result = create_args_script->Run();
-  CHECK_EQ(v8_num(4), result);
-}
+  ExpectBoolean("undetectable==null", true);
+  ExpectBoolean("null==undetectable", true);
+  ExpectBoolean("undetectable==undefined", true);
+  ExpectBoolean("undefined==undetectable", true);
+  ExpectBoolean("undetectable==undetectable", true);
 
 
-static void IdentityIndexedPropertyGetter(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(index);
+  ExpectBoolean("undetectable===null", false);
+  ExpectBoolean("null===undetectable", false);
+  ExpectBoolean("undetectable===undefined", false);
+  ExpectBoolean("undefined===undetectable", false);
+  ExpectBoolean("undetectable===undetectable", true);
 }
 
 
-THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
-  v8::Isolate* isolate = CcTest::isolate();
+THREADED_TEST(VoidLiteral) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
-
-  LocalContext context;
-  context->Global()->Set(v8_str("obj"), templ->NewInstance());
 
-  // Check fast object case.
-  const char* fast_case_code =
-      "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
-  ExpectString(fast_case_code, "0");
-
-  // Check slow case.
-  const char* slow_case_code =
-      "obj.x = 1; delete obj.x;"
-      "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
-  ExpectString(slow_case_code, "1");
-}
+  Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
+  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
 
+  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
+  env->Global()->Set(v8_str("undetectable"), obj);
 
-THREADED_TEST(IndexedInterceptorWithNoSetter) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+  ExpectBoolean("undefined == void 0", true);
+  ExpectBoolean("undetectable == void 0", true);
+  ExpectBoolean("null == void 0", true);
+  ExpectBoolean("undefined === void 0", true);
+  ExpectBoolean("undetectable === void 0", false);
+  ExpectBoolean("null === void 0", false);
 
-  LocalContext context;
-  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  ExpectBoolean("void 0 == undefined", true);
+  ExpectBoolean("void 0 == undetectable", true);
+  ExpectBoolean("void 0 == null", true);
+  ExpectBoolean("void 0 === undefined", true);
+  ExpectBoolean("void 0 === undetectable", false);
+  ExpectBoolean("void 0 === null", false);
 
-  const char* code =
-      "try {"
-      "  obj[0] = 239;"
-      "  for (var i = 0; i < 100; i++) {"
-      "    var v = obj[0];"
-      "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
+  ExpectString(
+      "(function() {"
+      "  try {"
+      "    return x === void 0;"
+      "  } catch(e) {"
+      "    return e.toString();"
       "  }"
-      "  'PASSED'"
-      "} catch(e) {"
-      "  e"
-      "}";
-  ExpectString(code, "PASSED");
+      "})()",
+      "ReferenceError: x is not defined");
+  ExpectString(
+      "(function() {"
+      "  try {"
+      "    return void 0 === x;"
+      "  } catch(e) {"
+      "    return e.toString();"
+      "  }"
+      "})()",
+      "ReferenceError: x is not defined");
 }
 
 
-THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
-  v8::Isolate* isolate = CcTest::isolate();
+THREADED_TEST(ExtensibleOnUndetectable) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
 
-  LocalContext context;
-  Local<v8::Object> obj = templ->NewInstance();
-  obj->TurnOnAccessCheck();
-  context->Global()->Set(v8_str("obj"), obj);
+  Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
+  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
 
-  const char* code =
-      "try {"
-      "  for (var i = 0; i < 100; i++) {"
-      "    var v = obj[0];"
-      "    if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
-      "  }"
-      "  'PASSED'"
-      "} catch(e) {"
-      "  e"
-      "}";
-  ExpectString(code, "PASSED");
-}
+  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
+  env->Global()->Set(v8_str("undetectable"), obj);
 
+  Local<String> source = v8_str(
+      "undetectable.x = 42;"
+      "undetectable.x");
 
-THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
-  i::FLAG_allow_natives_syntax = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+  Local<Script> script = v8_compile(source);
 
-  LocalContext context;
-  Local<v8::Object> obj = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), obj);
+  CHECK(v8::Integer::New(isolate, 42)->Equals(script->Run()));
 
-  const char* code =
-      "try {"
-      "  for (var i = 0; i < 100; i++) {"
-      "    var expected = i;"
-      "    if (i == 5) {"
-      "      %EnableAccessChecks(obj);"
-      "      expected = undefined;"
-      "    }"
-      "    var v = obj[i];"
-      "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
-      "    if (i == 5) %DisableAccessChecks(obj);"
-      "  }"
-      "  'PASSED'"
-      "} catch(e) {"
-      "  e"
-      "}";
-  ExpectString(code, "PASSED");
+  ExpectBoolean("Object.isExtensible(undetectable)", true);
+
+  source = v8_str("Object.preventExtensions(undetectable);");
+  script = v8_compile(source);
+  script->Run();
+  ExpectBoolean("Object.isExtensible(undetectable)", false);
+
+  source = v8_str("undetectable.y = 2000;");
+  script = v8_compile(source);
+  script->Run();
+  ExpectBoolean("undetectable.y == undefined", true);
 }
 
 
-THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
+// The point of this test is type checking. We run it only so compilers
+// don't complain about an unused function.
+TEST(PersistentHandles) {
+  LocalContext env;
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
+  Local<String> str = v8_str("foo");
+  v8::Persistent<String> p_str(isolate, str);
+  p_str.Reset();
+  Local<Script> scr = v8_compile("");
+  v8::Persistent<Script> p_scr(isolate, scr);
+  p_scr.Reset();
   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+  v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
+  p_templ.Reset();
+}
 
-  LocalContext context;
-  Local<v8::Object> obj = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), obj);
 
-  const char* code =
-      "try {"
-      "  for (var i = 0; i < 100; i++) {"
-      "    var v = obj[i];"
-      "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
-      "  }"
-      "  'PASSED'"
-      "} catch(e) {"
-      "  e"
-      "}";
-  ExpectString(code, "PASSED");
+static void HandleLogDelegator(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
 }
 
 
-THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
+THREADED_TEST(GlobalObjectTemplate) {
   v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+  v8::HandleScope handle_scope(isolate);
+  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
+  global_template->Set(v8_str("JSNI_Log"),
+                       v8::FunctionTemplate::New(isolate, HandleLogDelegator));
+  v8::Local<Context> context = Context::New(isolate, 0, global_template);
+  Context::Scope context_scope(context);
+  CompileRun("JSNI_Log('LOG')");
+}
 
-  LocalContext context;
-  Local<v8::Object> obj = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), obj);
 
-  const char* code =
-      "try {"
-      "  for (var i = 0; i < 100; i++) {"
-      "    var expected = i;"
-      "    var key = i;"
-      "    if (i == 25) {"
-      "       key = -1;"
-      "       expected = undefined;"
-      "    }"
-      "    if (i == 50) {"
-      "       /* probe minimal Smi number on 32-bit platforms */"
-      "       key = -(1 << 30);"
-      "       expected = undefined;"
-      "    }"
-      "    if (i == 75) {"
-      "       /* probe minimal Smi number on 64-bit platforms */"
-      "       key = 1 << 31;"
-      "       expected = undefined;"
-      "    }"
-      "    var v = obj[key];"
-      "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
-      "  }"
-      "  'PASSED'"
-      "} catch(e) {"
-      "  e"
-      "}";
-  ExpectString(code, "PASSED");
+static const char* kSimpleExtensionSource =
+    "function Foo() {"
+    "  return 4;"
+    "}";
+
+
+TEST(SimpleExtensions) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
+  const char* extension_names[] = {"simpletest"};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = CompileRun("Foo()");
+  CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
 }
 
 
-THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+static const char* kStackTraceFromExtensionSource =
+    "function foo() {"
+    "  throw new Error();"
+    "}"
+    "function bar() {"
+    "  foo();"
+    "}";
 
-  LocalContext context;
-  Local<v8::Object> obj = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), obj);
 
-  const char* code =
-      "try {"
-      "  for (var i = 0; i < 100; i++) {"
-      "    var expected = i;"
-      "    var key = i;"
-      "    if (i == 50) {"
-      "       key = 'foobar';"
-      "       expected = undefined;"
-      "    }"
-      "    var v = obj[key];"
-      "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
-      "  }"
-      "  'PASSED'"
-      "} catch(e) {"
-      "  e"
-      "}";
-  ExpectString(code, "PASSED");
+TEST(StackTraceInExtension) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  v8::RegisterExtension(
+      new Extension("stacktracetest", kStackTraceFromExtensionSource));
+  const char* extension_names[] = {"stacktracetest"};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  Context::Scope lock(context);
+  CompileRun(
+      "function user() { bar(); }"
+      "var error;"
+      "try{ user(); } catch (e) { error = e; }");
+  CHECK_EQ(-1, CompileRun("error.stack.indexOf('foo')")->Int32Value());
+  CHECK_EQ(-1, CompileRun("error.stack.indexOf('bar')")->Int32Value());
+  CHECK_NE(-1, CompileRun("error.stack.indexOf('user')")->Int32Value());
 }
 
 
-THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
-
-  LocalContext context;
-  Local<v8::Object> obj = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), obj);
-
-  const char* code =
-      "var original = obj;"
-      "try {"
-      "  for (var i = 0; i < 100; i++) {"
-      "    var expected = i;"
-      "    if (i == 50) {"
-      "       obj = {50: 'foobar'};"
-      "       expected = 'foobar';"
-      "    }"
-      "    var v = obj[i];"
-      "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
-      "    if (i == 50) obj = original;"
-      "  }"
-      "  'PASSED'"
-      "} catch(e) {"
-      "  e"
-      "}";
-  ExpectString(code, "PASSED");
+TEST(NullExtensions) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  v8::RegisterExtension(new Extension("nulltest", NULL));
+  const char* extension_names[] = {"nulltest"};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = CompileRun("1+3");
+  CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
 }
 
 
-THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+static const char* kEmbeddedExtensionSource =
+    "function Ret54321(){return 54321;}~~@@$"
+    "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
+static const int kEmbeddedExtensionSourceValidLen = 34;
 
-  LocalContext context;
-  Local<v8::Object> obj = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), obj);
 
-  const char* code =
-      "var original = obj;"
-      "try {"
-      "  for (var i = 0; i < 100; i++) {"
-      "    var expected = i;"
-      "    if (i == 5) {"
-      "       obj = 239;"
-      "       expected = undefined;"
-      "    }"
-      "    var v = obj[i];"
-      "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
-      "    if (i == 5) obj = original;"
-      "  }"
-      "  'PASSED'"
-      "} catch(e) {"
-      "  e"
-      "}";
-  ExpectString(code, "PASSED");
+TEST(ExtensionMissingSourceLength) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  v8::RegisterExtension(
+      new Extension("srclentest_fail", kEmbeddedExtensionSource));
+  const char* extension_names[] = {"srclentest_fail"};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  CHECK(0 == *context);
 }
 
 
-THREADED_TEST(IndexedInterceptorOnProto) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
-
-  LocalContext context;
-  Local<v8::Object> obj = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), obj);
-
-  const char* code =
-      "var o = {__proto__: obj};"
-      "try {"
-      "  for (var i = 0; i < 100; i++) {"
-      "    var v = o[i];"
-      "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
-      "  }"
-      "  'PASSED'"
-      "} catch(e) {"
-      "  e"
-      "}";
-  ExpectString(code, "PASSED");
+TEST(ExtensionWithSourceLength) {
+  for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
+       source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
+    v8::HandleScope handle_scope(CcTest::isolate());
+    i::ScopedVector<char> extension_name(32);
+    i::SNPrintF(extension_name, "ext #%d", source_len);
+    v8::RegisterExtension(new Extension(
+        extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
+    const char* extension_names[1] = {extension_name.start()};
+    v8::ExtensionConfiguration extensions(1, extension_names);
+    v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+    if (source_len == kEmbeddedExtensionSourceValidLen) {
+      Context::Scope lock(context);
+      v8::Handle<Value> result = CompileRun("Ret54321()");
+      CHECK(v8::Integer::New(CcTest::isolate(), 54321)->Equals(result));
+    } else {
+      // Anything but exactly the right length should fail to compile.
+      CHECK(0 == *context);
+    }
+  }
 }
 
 
-THREADED_TEST(MultiContexts) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(isolate,
-                                                        DummyCallHandler));
+static const char* kEvalExtensionSource1 =
+    "function UseEval1() {"
+    "  var x = 42;"
+    "  return eval('x');"
+    "}";
 
-  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());
+static const char* kEvalExtensionSource2 =
+    "(function() {"
+    "  var x = 42;"
+    "  function e() {"
+    "    return eval('x');"
+    "  }"
+    "  this.UseEval2 = e;"
+    "})()";
 
-  // 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());
+TEST(UseEvalFromExtension) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  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(CcTest::isolate(), &extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = CompileRun("UseEval1()");
+  CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
+  result = CompileRun("UseEval2()");
+  CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
 }
 
 
-THREADED_TEST(FunctionPrototypeAcrossContexts) {
-  // Make sure that functions created by cloning boilerplates cannot
-  // communicate through their __proto__ field.
+static const char* kWithExtensionSource1 =
+    "function UseWith1() {"
+    "  var x = 42;"
+    "  with({x:87}) { return x; }"
+    "}";
 
-  v8::HandleScope scope(CcTest::isolate());
 
-  LocalContext env0;
-  v8::Handle<v8::Object> global0 =
-      env0->Global();
-  v8::Handle<v8::Object> object0 =
-      global0->Get(v8_str("Object")).As<v8::Object>();
-  v8::Handle<v8::Object> tostring0 =
-      object0->Get(v8_str("toString")).As<v8::Object>();
-  v8::Handle<v8::Object> proto0 =
-      tostring0->Get(v8_str("__proto__")).As<v8::Object>();
-  proto0->Set(v8_str("custom"), v8_num(1234));
+static const char* kWithExtensionSource2 =
+    "(function() {"
+    "  var x = 42;"
+    "  function e() {"
+    "    with ({x:87}) { return x; }"
+    "  }"
+    "  this.UseWith2 = e;"
+    "})()";
 
-  LocalContext env1;
-  v8::Handle<v8::Object> global1 =
-      env1->Global();
-  v8::Handle<v8::Object> object1 =
-      global1->Get(v8_str("Object")).As<v8::Object>();
-  v8::Handle<v8::Object> tostring1 =
-      object1->Get(v8_str("toString")).As<v8::Object>();
-  v8::Handle<v8::Object> proto1 =
-      tostring1->Get(v8_str("__proto__")).As<v8::Object>();
-  CHECK(!proto1->Has(v8_str("custom")));
+
+TEST(UseWithFromExtension) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  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(CcTest::isolate(), &extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = CompileRun("UseWith1()");
+  CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
+  result = CompileRun("UseWith2()");
+  CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
 }
 
 
-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.
+TEST(AutoExtensions) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  Extension* extension = new Extension("autotest", kSimpleExtensionSource);
+  extension->set_auto_enable(true);
+  v8::RegisterExtension(extension);
+  v8::Handle<Context> context = Context::New(CcTest::isolate());
+  Context::Scope lock(context);
+  v8::Handle<Value> result = CompileRun("Foo()");
+  CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
+}
 
-  v8::HandleScope scope(CcTest::isolate());
 
-  Local<String> source = v8_str("Object.prototype.obj = 1234;"
-                                "Array.prototype.arr = 4567;"
-                                "8901");
+static const char* kSyntaxErrorInExtensionSource = "[";
 
-  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());
+// Test that a syntax error in an extension does not cause a fatal
+// error but results in an empty context.
+TEST(SyntaxErrorExtensions) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  v8::RegisterExtension(
+      new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
+  const char* extension_names[] = {"syntaxerror"};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  CHECK(context.IsEmpty());
 }
 
 
-THREADED_TEST(UndetectableObject) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-
-  Local<v8::FunctionTemplate> desc =
-      v8::FunctionTemplate::New(env->GetIsolate());
-  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
+static const char* kExceptionInExtensionSource = "throw 42";
 
-  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);
+// Test that an exception when installing an extension does not cause
+// a fatal error but results in an empty context.
+TEST(ExceptionExtensions) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  v8::RegisterExtension(
+      new Extension("exception", kExceptionInExtensionSource));
+  const char* extension_names[] = {"exception"};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  CHECK(context.IsEmpty());
+}
 
-  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);
+static const char* kNativeCallInExtensionSource =
+    "function call_runtime_last_index_of(x) {"
+    "  return %StringLastIndexOf(x, 'bob', 10);"
+    "}";
 
-  ExpectBoolean("undetectable==null", true);
-  ExpectBoolean("null==undetectable", true);
-  ExpectBoolean("undetectable==undefined", true);
-  ExpectBoolean("undefined==undetectable", true);
-  ExpectBoolean("undetectable==undetectable", true);
 
+static const char* kNativeCallTest =
+    "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
 
-  ExpectBoolean("undetectable===null", false);
-  ExpectBoolean("null===undetectable", false);
-  ExpectBoolean("undetectable===undefined", false);
-  ExpectBoolean("undefined===undetectable", false);
-  ExpectBoolean("undetectable===undetectable", true);
+// Test that a native runtime calls are supported in extensions.
+TEST(NativeCallInExtensions) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  v8::RegisterExtension(
+      new Extension("nativecall", kNativeCallInExtensionSource));
+  const char* extension_names[] = {"nativecall"};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = CompileRun(kNativeCallTest);
+  CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 3)));
 }
 
 
-THREADED_TEST(VoidLiteral) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
+class NativeFunctionExtension : public Extension {
+ public:
+  NativeFunctionExtension(const char* name, const char* source,
+                          v8::FunctionCallback fun = &Echo)
+      : Extension(name, source), function_(fun) {}
 
-  Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
-  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+      v8::Isolate* isolate, v8::Handle<v8::String> name) {
+    return v8::FunctionTemplate::New(isolate, function_);
+  }
 
-  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
-  env->Global()->Set(v8_str("undetectable"), obj);
+  static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
+    if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
+  }
 
-  ExpectBoolean("undefined == void 0", true);
-  ExpectBoolean("undetectable == void 0", true);
-  ExpectBoolean("null == void 0", true);
-  ExpectBoolean("undefined === void 0", true);
-  ExpectBoolean("undetectable === void 0", false);
-  ExpectBoolean("null === void 0", false);
+ private:
+  v8::FunctionCallback function_;
+};
 
-  ExpectBoolean("void 0 == undefined", true);
-  ExpectBoolean("void 0 == undetectable", true);
-  ExpectBoolean("void 0 == null", true);
-  ExpectBoolean("void 0 === undefined", true);
-  ExpectBoolean("void 0 === undetectable", false);
-  ExpectBoolean("void 0 === null", false);
 
-  ExpectString("(function() {"
-               "  try {"
-               "    return x === void 0;"
-               "  } catch(e) {"
-               "    return e.toString();"
-               "  }"
-               "})()",
-               "ReferenceError: x is not defined");
-  ExpectString("(function() {"
-               "  try {"
-               "    return void 0 === x;"
-               "  } catch(e) {"
-               "    return e.toString();"
-               "  }"
-               "})()",
-               "ReferenceError: x is not defined");
+TEST(NativeFunctionDeclaration) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  const char* name = "nativedecl";
+  v8::RegisterExtension(
+      new NativeFunctionExtension(name, "native function foo();"));
+  const char* extension_names[] = {name};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = CompileRun("foo(42);");
+  CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
 }
 
 
-THREADED_TEST(ExtensibleOnUndetectable) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
+TEST(NativeFunctionDeclarationError) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  const char* name = "nativedeclerr";
+  // Syntax error in extension code.
+  v8::RegisterExtension(
+      new NativeFunctionExtension(name, "native\nfunction foo();"));
+  const char* extension_names[] = {name};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  CHECK(context.IsEmpty());
+}
 
-  Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
-  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
-
-  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
-  env->Global()->Set(v8_str("undetectable"), obj);
 
-  Local<String> source = v8_str("undetectable.x = 42;"
-                                "undetectable.x");
-
-  Local<Script> script = Script::Compile(source);
-
-  CHECK_EQ(v8::Integer::New(isolate, 42), script->Run());
-
-  ExpectBoolean("Object.isExtensible(undetectable)", true);
+TEST(NativeFunctionDeclarationErrorEscape) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  const char* name = "nativedeclerresc";
+  // Syntax error in extension code - escape code in "native" means that
+  // it's not treated as a keyword.
+  v8::RegisterExtension(
+      new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
+  const char* extension_names[] = {name};
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
+  CHECK(context.IsEmpty());
+}
 
-  source = v8_str("Object.preventExtensions(undetectable);");
-  script = Script::Compile(source);
-  script->Run();
-  ExpectBoolean("Object.isExtensible(undetectable)", false);
 
-  source = v8_str("undetectable.y = 2000;");
-  script = Script::Compile(source);
-  script->Run();
-  ExpectBoolean("undetectable.y == undefined", true);
+static void CheckDependencies(const char* name, const char* expected) {
+  v8::HandleScope handle_scope(CcTest::isolate());
+  v8::ExtensionConfiguration config(1, &name);
+  LocalContext context(&config);
+  CHECK(String::NewFromUtf8(CcTest::isolate(), expected)
+            ->Equals(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(CcTest::isolate());
+  static const char* exts[2] = {"C", "E"};
+  v8::ExtensionConfiguration config(2, exts);
+  LocalContext context(&config);
+  CHECK(v8_str("undefinedACBDE")
+            ->Equals(context->Global()->Get(v8_str("loaded"))));
+}
 
-THREADED_TEST(UndetectableString) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
 
-  Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
-                                          String::kUndetectableString);
-  env->Global()->Set(v8_str("undetectable"), obj);
+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();"
+    "}";
 
-  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);
+static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
+  if (args.IsConstructCall()) {
+    args.This()->Set(v8_str("data"), args.Data());
+    args.GetReturnValue().SetNull();
+    return;
+  }
+  args.GetReturnValue().Set(args.Data());
+}
 
-  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);
+class FunctionExtension : public Extension {
+ public:
+  FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+      v8::Isolate* isolate, v8::Handle<String> name);
+};
 
 
-  ExpectBoolean("undetectable===null", false);
-  ExpectBoolean("null===undetectable", false);
-  ExpectBoolean("undetectable===undefined", false);
-  ExpectBoolean("undefined===undetectable", false);
-  ExpectBoolean("undetectable===undetectable", true);
+static int lookup_count = 0;
+v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
+    v8::Isolate* isolate, v8::Handle<String> name) {
+  lookup_count++;
+  if (name->Equals(v8_str("A"))) {
+    return v8::FunctionTemplate::New(isolate, CallFun,
+                                     v8::Integer::New(isolate, 8));
+  } else if (name->Equals(v8_str("B"))) {
+    return v8::FunctionTemplate::New(isolate, CallFun,
+                                     v8::Integer::New(isolate, 7));
+  } else if (name->Equals(v8_str("C"))) {
+    return v8::FunctionTemplate::New(isolate, CallFun,
+                                     v8::Integer::New(isolate, 6));
+  } else {
+    return v8::Handle<v8::FunctionTemplate>();
+  }
 }
 
 
-TEST(UndetectableOptimized) {
-  i::FLAG_allow_natives_syntax = true;
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-
-  Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
-                                          String::kUndetectableString);
-  env->Global()->Set(v8_str("undetectable"), obj);
-  env->Global()->Set(v8_str("detectable"), v8_str("bar"));
-
-  ExpectString(
-      "function testBranch() {"
-      "  if (!%_IsUndetectableObject(undetectable)) throw 1;"
-      "  if (%_IsUndetectableObject(detectable)) throw 2;"
-      "}\n"
-      "function testBool() {"
-      "  var b1 = !%_IsUndetectableObject(undetectable);"
-      "  var b2 = %_IsUndetectableObject(detectable);"
-      "  if (b1) throw 3;"
-      "  if (b2) throw 4;"
-      "  return b1 == b2;"
-      "}\n"
-      "%OptimizeFunctionOnNextCall(testBranch);"
-      "%OptimizeFunctionOnNextCall(testBool);"
-      "for (var i = 0; i < 10; i++) {"
-      "  testBranch();"
-      "  testBool();"
-      "}\n"
-      "\"PASS\"",
-      "PASS");
+THREADED_TEST(FunctionLookup) {
+  v8::RegisterExtension(new FunctionExtension());
+  v8::HandleScope handle_scope(CcTest::isolate());
+  static const char* exts[1] = {"functiontest"};
+  v8::ExtensionConfiguration config(1, exts);
+  LocalContext context(&config);
+  CHECK_EQ(3, lookup_count);
+  CHECK(v8::Integer::New(CcTest::isolate(), 8)->Equals(CompileRun("Foo(0)")));
+  CHECK(v8::Integer::New(CcTest::isolate(), 7)->Equals(CompileRun("Foo(1)")));
+  CHECK(v8::Integer::New(CcTest::isolate(), 6)->Equals(CompileRun("Foo(2)")));
 }
 
 
-template <typename T> static void USE(T) { }
+THREADED_TEST(NativeFunctionConstructCall) {
+  v8::RegisterExtension(new FunctionExtension());
+  v8::HandleScope handle_scope(CcTest::isolate());
+  static const char* exts[1] = {"functiontest"};
+  v8::ExtensionConfiguration config(1, exts);
+  LocalContext context(&config);
+  for (int i = 0; i < 10; i++) {
+    // Run a few times to ensure that allocation of objects doesn't
+    // change behavior of a constructor function.
+    CHECK(v8::Integer::New(CcTest::isolate(), 8)
+              ->Equals(CompileRun("(new A()).data")));
+    CHECK(v8::Integer::New(CcTest::isolate(), 7)
+              ->Equals(CompileRun("(new B()).data")));
+    CHECK(v8::Integer::New(CcTest::isolate(), 6)
+              ->Equals(CompileRun("(new C()).data")));
+  }
+}
 
 
-// The point of this test is type checking. We run it only so compilers
-// don't complain about an unused function.
-TEST(PersistentHandles) {
-  LocalContext env;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<String> str = v8_str("foo");
-  v8::Persistent<String> p_str(isolate, str);
-  p_str.Reset();
-  Local<Script> scr = Script::Compile(v8_str(""));
-  v8::Persistent<Script> p_scr(isolate, scr);
-  p_scr.Reset();
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
-  p_templ.Reset();
+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;
+  }
 }
 
 
-static void HandleLogDelegator(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
+// 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(CcTest::isolate(), &config);
+  CHECK(context.IsEmpty());
+  CHECK(last_location);
 }
 
 
-THREADED_TEST(GlobalObjectTemplate) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope handle_scope(isolate);
-  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
-  global_template->Set(v8_str("JSNI_Log"),
-                       v8::FunctionTemplate::New(isolate, HandleLogDelegator));
-  v8::Local<Context> context = Context::New(isolate, 0, global_template);
-  Context::Scope context_scope(context);
-  Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
+static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
+                                             v8::Handle<Value> data) {
+  CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
+  CHECK(v8::Undefined(CcTest::isolate())
+            ->Equals(message->GetScriptOrigin().ResourceName()));
+  message->GetLineNumber();
+  message->GetSourceLine();
 }
 
 
-static const char* kSimpleExtensionSource =
-  "function Foo() {"
-  "  return 4;"
-  "}";
+THREADED_TEST(ErrorWithMissingScriptInfo) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
+  CompileRun("throw Error()");
+  v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
+}
 
 
-TEST(SimpleExtensions) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
-  const char* extension_names[] = { "simpletest" };
-  v8::ExtensionConfiguration extensions(1, extension_names);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  Context::Scope lock(context);
-  v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
-  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
-}
+struct FlagAndPersistent {
+  bool flag;
+  v8::Global<v8::Object> handle;
+};
 
 
-TEST(NullExtensions) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  v8::RegisterExtension(new Extension("nulltest", NULL));
-  const char* extension_names[] = { "nulltest" };
-  v8::ExtensionConfiguration extensions(1, extension_names);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  Context::Scope lock(context);
-  v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
-  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
+static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
+  data.GetParameter()->flag = true;
+  data.GetParameter()->handle.Reset();
 }
 
 
-static const char* kEmbeddedExtensionSource =
-    "function Ret54321(){return 54321;}~~@@$"
-    "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
-static const int kEmbeddedExtensionSourceValidLen = 34;
-
+static void IndependentWeakHandle(bool global_gc, bool interlinked) {
+  v8::Isolate* iso = CcTest::isolate();
+  v8::HandleScope scope(iso);
+  v8::Handle<Context> context = Context::New(iso);
+  Context::Scope context_scope(context);
 
-TEST(ExtensionMissingSourceLength) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  v8::RegisterExtension(new Extension("srclentest_fail",
-                                      kEmbeddedExtensionSource));
-  const char* extension_names[] = { "srclentest_fail" };
-  v8::ExtensionConfiguration extensions(1, extension_names);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  CHECK_EQ(0, *context);
-}
+  FlagAndPersistent object_a, object_b;
 
+  intptr_t big_heap_size;
 
-TEST(ExtensionWithSourceLength) {
-  for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
-       source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
-    v8::HandleScope handle_scope(CcTest::isolate());
-    i::ScopedVector<char> extension_name(32);
-    i::OS::SNPrintF(extension_name, "ext #%d", source_len);
-    v8::RegisterExtension(new Extension(extension_name.start(),
-                                        kEmbeddedExtensionSource, 0, 0,
-                                        source_len));
-    const char* extension_names[1] = { extension_name.start() };
-    v8::ExtensionConfiguration extensions(1, extension_names);
-    v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-    if (source_len == kEmbeddedExtensionSourceValidLen) {
-      Context::Scope lock(context);
-      v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
-      CHECK_EQ(v8::Integer::New(CcTest::isolate(), 54321), result);
+  {
+    v8::HandleScope handle_scope(iso);
+    Local<Object> a(v8::Object::New(iso));
+    Local<Object> b(v8::Object::New(iso));
+    object_a.handle.Reset(iso, a);
+    object_b.handle.Reset(iso, b);
+    if (interlinked) {
+      a->Set(v8_str("x"), b);
+      b->Set(v8_str("x"), a);
+    }
+    if (global_gc) {
+      CcTest::heap()->CollectAllGarbage();
     } else {
-      // Anything but exactly the right length should fail to compile.
-      CHECK_EQ(0, *context);
+      CcTest::heap()->CollectGarbage(i::NEW_SPACE);
     }
+    // We are relying on this creating a big flag array and reserving the space
+    // up front.
+    v8::Handle<Value> big_array = CompileRun("new Array(50000)");
+    a->Set(v8_str("y"), big_array);
+    big_heap_size = CcTest::heap()->SizeOfObjects();
+  }
+
+  object_a.flag = false;
+  object_b.flag = false;
+  object_a.handle.SetWeak(&object_a, &SetFlag,
+                          v8::WeakCallbackType::kParameter);
+  object_b.handle.SetWeak(&object_b, &SetFlag,
+                          v8::WeakCallbackType::kParameter);
+  CHECK(!object_b.handle.IsIndependent());
+  object_a.handle.MarkIndependent();
+  object_b.handle.MarkIndependent();
+  CHECK(object_b.handle.IsIndependent());
+  if (global_gc) {
+    CcTest::heap()->CollectAllGarbage();
+  } else {
+    CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   }
+  // A single GC should be enough to reclaim the memory, since we are using
+  // phantom handles.
+  CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 200000);
+  CHECK(object_a.flag);
+  CHECK(object_b.flag);
 }
 
 
-static const char* kEvalExtensionSource1 =
-  "function UseEval1() {"
-  "  var x = 42;"
-  "  return eval('x');"
-  "}";
+TEST(IndependentWeakHandle) {
+  IndependentWeakHandle(false, false);
+  IndependentWeakHandle(false, true);
+  IndependentWeakHandle(true, false);
+  IndependentWeakHandle(true, true);
+}
 
 
-static const char* kEvalExtensionSource2 =
-  "(function() {"
-  "  var x = 42;"
-  "  function e() {"
-  "    return eval('x');"
-  "  }"
-  "  this.UseEval2 = e;"
-  "})()";
+class Trivial {
+ public:
+  explicit Trivial(int x) : x_(x) {}
 
+  int x() { return x_; }
+  void set_x(int x) { x_ = x; }
 
-TEST(UseEvalFromExtension) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  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(CcTest::isolate(), &extensions);
-  Context::Scope lock(context);
-  v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
-  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
-  result = Script::Compile(v8_str("UseEval2()"))->Run();
-  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
-}
+ private:
+  int x_;
+};
 
 
-static const char* kWithExtensionSource1 =
-  "function UseWith1() {"
-  "  var x = 42;"
-  "  with({x:87}) { return x; }"
-  "}";
+class Trivial2 {
+ public:
+  Trivial2(int x, int y) : y_(y), x_(x) {}
 
+  int x() { return x_; }
+  void set_x(int x) { x_ = x; }
 
+  int y() { return y_; }
+  void set_y(int y) { y_ = y; }
 
-static const char* kWithExtensionSource2 =
-  "(function() {"
-  "  var x = 42;"
-  "  function e() {"
-  "    with ({x:87}) { return x; }"
-  "  }"
-  "  this.UseWith2 = e;"
-  "})()";
+ private:
+  int y_;
+  int x_;
+};
 
 
-TEST(UseWithFromExtension) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  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(CcTest::isolate(), &extensions);
-  Context::Scope lock(context);
-  v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
-  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
-  result = Script::Compile(v8_str("UseWith2()"))->Run();
-  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
+void CheckInternalFields(
+    const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
+  v8::Persistent<v8::Object>* handle = data.GetParameter();
+  handle->Reset();
+  Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField1());
+  Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField2());
+  CHECK_EQ(42, t1->x());
+  CHECK_EQ(103, t2->x());
+  t1->set_x(1729);
+  t2->set_x(33550336);
 }
 
 
-TEST(AutoExtensions) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  Extension* extension = new Extension("autotest", kSimpleExtensionSource);
-  extension->set_auto_enable(true);
-  v8::RegisterExtension(extension);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate());
-  Context::Scope lock(context);
-  v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
-  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
-}
-
-
-static const char* kSyntaxErrorInExtensionSource =
-    "[";
-
-
-// Test that a syntax error in an extension does not cause a fatal
-// error but results in an empty context.
-TEST(SyntaxErrorExtensions) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  v8::RegisterExtension(new Extension("syntaxerror",
-                                      kSyntaxErrorInExtensionSource));
-  const char* extension_names[] = { "syntaxerror" };
-  v8::ExtensionConfiguration extensions(1, extension_names);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  CHECK(context.IsEmpty());
-}
-
-
-static const char* kExceptionInExtensionSource =
-    "throw 42";
-
-
-// Test that an exception when installing an extension does not cause
-// a fatal error but results in an empty context.
-TEST(ExceptionExtensions) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  v8::RegisterExtension(new Extension("exception",
-                                      kExceptionInExtensionSource));
-  const char* extension_names[] = { "exception" };
-  v8::ExtensionConfiguration extensions(1, extension_names);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  CHECK(context.IsEmpty());
-}
-
-
-static const char* kNativeCallInExtensionSource =
-    "function call_runtime_last_index_of(x) {"
-    "  return %StringLastIndexOf(x, 'bob', 10);"
-    "}";
-
-
-static const char* kNativeCallTest =
-    "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
-
-// Test that a native runtime calls are supported in extensions.
-TEST(NativeCallInExtensions) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  v8::RegisterExtension(new Extension("nativecall",
-                                      kNativeCallInExtensionSource));
-  const char* extension_names[] = { "nativecall" };
-  v8::ExtensionConfiguration extensions(1, extension_names);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  Context::Scope lock(context);
-  v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
-  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 3));
-}
-
-
-class NativeFunctionExtension : public Extension {
- public:
-  NativeFunctionExtension(const char* name,
-                          const char* source,
-                          v8::FunctionCallback fun = &Echo)
-      : Extension(name, source),
-        function_(fun) { }
-
-  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
-      v8::Isolate* isolate,
-      v8::Handle<v8::String> name) {
-    return v8::FunctionTemplate::New(isolate, function_);
-  }
-
-  static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
-    if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
-  }
- private:
-  v8::FunctionCallback function_;
-};
-
-
-TEST(NativeFunctionDeclaration) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  const char* name = "nativedecl";
-  v8::RegisterExtension(new NativeFunctionExtension(name,
-                                                    "native function foo();"));
-  const char* extension_names[] = { name };
-  v8::ExtensionConfiguration extensions(1, extension_names);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  Context::Scope lock(context);
-  v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
-  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
-}
-
-
-TEST(NativeFunctionDeclarationError) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  const char* name = "nativedeclerr";
-  // Syntax error in extension code.
-  v8::RegisterExtension(new NativeFunctionExtension(name,
-                                                    "native\nfunction foo();"));
-  const char* extension_names[] = { name };
-  v8::ExtensionConfiguration extensions(1, extension_names);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  CHECK(context.IsEmpty());
-}
-
-
-TEST(NativeFunctionDeclarationErrorEscape) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  const char* name = "nativedeclerresc";
-  // Syntax error in extension code - escape code in "native" means that
-  // it's not treated as a keyword.
-  v8::RegisterExtension(new NativeFunctionExtension(
-      name,
-      "nativ\\u0065 function foo();"));
-  const char* extension_names[] = { name };
-  v8::ExtensionConfiguration extensions(1, extension_names);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  CHECK(context.IsEmpty());
-}
-
-
-static void CheckDependencies(const char* name, const char* expected) {
-  v8::HandleScope handle_scope(CcTest::isolate());
-  v8::ExtensionConfiguration config(1, &name);
-  LocalContext context(&config);
-  CHECK_EQ(String::NewFromUtf8(CcTest::isolate(), 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(CcTest::isolate());
-  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();"
-  "}";
-
+void InternalFieldCallback(bool global_gc) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
 
-static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-  if (args.IsConstructCall()) {
-    args.This()->Set(v8_str("data"), args.Data());
-    args.GetReturnValue().SetNull();
-    return;
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
+  Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
+  Trivial* t1;
+  Trivial2* t2;
+  instance_templ->SetInternalFieldCount(2);
+  {
+    v8::HandleScope scope(isolate);
+    Local<v8::Object> obj = templ->GetFunction()->NewInstance();
+    v8::Persistent<v8::Object> handle(isolate, obj);
+    CHECK_EQ(2, obj->InternalFieldCount());
+    CHECK(obj->GetInternalField(0)->IsUndefined());
+    t1 = new Trivial(42);
+    t2 = new Trivial2(103, 9);
+
+    obj->SetAlignedPointerInInternalField(0, t1);
+    t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
+    CHECK_EQ(42, t1->x());
+
+    obj->SetAlignedPointerInInternalField(1, t2);
+    t2 =
+        reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
+    CHECK_EQ(103, t2->x());
+
+    handle.SetWeak<v8::Persistent<v8::Object>>(
+        &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
+    if (!global_gc) {
+      handle.MarkIndependent();
+    }
   }
-  args.GetReturnValue().Set(args.Data());
-}
-
-
-class FunctionExtension : public Extension {
- public:
-  FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
-  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
-      v8::Isolate* isolate,
-      v8::Handle<String> name);
-};
-
-
-static int lookup_count = 0;
-v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
-    v8::Isolate* isolate, v8::Handle<String> name) {
-  lookup_count++;
-  if (name->Equals(v8_str("A"))) {
-    return v8::FunctionTemplate::New(
-        isolate, CallFun, v8::Integer::New(isolate, 8));
-  } else if (name->Equals(v8_str("B"))) {
-    return v8::FunctionTemplate::New(
-        isolate, CallFun, v8::Integer::New(isolate, 7));
-  } else if (name->Equals(v8_str("C"))) {
-    return v8::FunctionTemplate::New(
-        isolate, CallFun, v8::Integer::New(isolate, 6));
+  if (global_gc) {
+    CcTest::heap()->CollectAllGarbage();
   } else {
-    return v8::Handle<v8::FunctionTemplate>();
-  }
-}
-
-
-THREADED_TEST(FunctionLookup) {
-  v8::RegisterExtension(new FunctionExtension());
-  v8::HandleScope handle_scope(CcTest::isolate());
-  static const char* exts[1] = { "functiontest" };
-  v8::ExtensionConfiguration config(1, exts);
-  LocalContext context(&config);
-  CHECK_EQ(3, lookup_count);
-  CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
-           Script::Compile(v8_str("Foo(0)"))->Run());
-  CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
-           Script::Compile(v8_str("Foo(1)"))->Run());
-  CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
-           Script::Compile(v8_str("Foo(2)"))->Run());
-}
-
-
-THREADED_TEST(NativeFunctionConstructCall) {
-  v8::RegisterExtension(new FunctionExtension());
-  v8::HandleScope handle_scope(CcTest::isolate());
-  static const char* exts[1] = { "functiontest" };
-  v8::ExtensionConfiguration config(1, exts);
-  LocalContext context(&config);
-  for (int i = 0; i < 10; i++) {
-    // Run a few times to ensure that allocation of objects doesn't
-    // change behavior of a constructor function.
-    CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
-             Script::Compile(v8_str("(new A()).data"))->Run());
-    CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
-             Script::Compile(v8_str("(new B()).data"))->Run());
-    CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
-             Script::Compile(v8_str("(new C()).data"))->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;
+    CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   }
-}
-
-
-// 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(CcTest::isolate(), &config);
-  CHECK(context.IsEmpty());
-  CHECK_NE(last_location, NULL);
-}
 
+  CHECK_EQ(1729, t1->x());
+  CHECK_EQ(33550336, t2->x());
 
-static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
-                                             v8::Handle<Value> data) {
-  CHECK(message->GetScriptResourceName()->IsUndefined());
-  CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName());
-  message->GetLineNumber();
-  message->GetSourceLine();
+  delete t1;
+  delete t2;
 }
 
 
-THREADED_TEST(ErrorWithMissingScriptInfo) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
-  Script::Compile(v8_str("throw Error()"))->Run();
-  v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
+THREADED_TEST(InternalFieldCallback) {
+  InternalFieldCallback(false);
+  InternalFieldCallback(true);
 }
 
 
-struct FlagAndPersistent {
-  bool flag;
-  v8::Persistent<v8::Object> handle;
-};
-
-
-static void DisposeAndSetFlag(
-    const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
+static void ResetUseValueAndSetFlag(
+    const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
+  // Blink will reset the handle, and then use the other handle, so they
+  // can't use the same backing slot.
   data.GetParameter()->handle.Reset();
   data.GetParameter()->flag = true;
 }
 
 
-THREADED_TEST(IndependentWeakHandle) {
+static void ResetWeakHandle(bool global_gc) {
   v8::Isolate* iso = CcTest::isolate();
   v8::HandleScope scope(iso);
   v8::Handle<Context> context = Context::New(iso);
@@ -7087,49 +6708,77 @@ THREADED_TEST(IndependentWeakHandle) {
 
   {
     v8::HandleScope handle_scope(iso);
-    object_a.handle.Reset(iso, v8::Object::New(iso));
-    object_b.handle.Reset(iso, v8::Object::New(iso));
+    Local<Object> a(v8::Object::New(iso));
+    Local<Object> b(v8::Object::New(iso));
+    object_a.handle.Reset(iso, a);
+    object_b.handle.Reset(iso, b);
+    if (global_gc) {
+      CcTest::heap()->CollectAllGarbage(
+          TestHeap::Heap::kAbortIncrementalMarkingMask);
+    } else {
+      CcTest::heap()->CollectGarbage(i::NEW_SPACE);
+    }
   }
 
   object_a.flag = false;
   object_b.flag = false;
-  object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag);
-  object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag);
-  CHECK(!object_b.handle.IsIndependent());
-  object_a.handle.MarkIndependent();
-  object_b.handle.MarkIndependent();
-  CHECK(object_b.handle.IsIndependent());
-  CcTest::heap()->PerformScavenge();
+  object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
+                          v8::WeakCallbackType::kParameter);
+  object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
+                          v8::WeakCallbackType::kParameter);
+  if (!global_gc) {
+    object_a.handle.MarkIndependent();
+    object_b.handle.MarkIndependent();
+    CHECK(object_b.handle.IsIndependent());
+  }
+  if (global_gc) {
+    CcTest::heap()->CollectAllGarbage(
+        TestHeap::Heap::kAbortIncrementalMarkingMask);
+  } else {
+    CcTest::heap()->CollectGarbage(i::NEW_SPACE);
+  }
   CHECK(object_a.flag);
   CHECK(object_b.flag);
 }
 
 
-static void InvokeScavenge() {
-  CcTest::heap()->PerformScavenge();
+THREADED_TEST(ResetWeakHandle) {
+  ResetWeakHandle(false);
+  ResetWeakHandle(true);
 }
 
 
-static void InvokeMarkSweep() {
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-}
+static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
 
 
-static void ForceScavenge(
-    const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
-  data.GetParameter()->handle.Reset();
+static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
+
+
+static void ForceScavenge2(
+    const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   data.GetParameter()->flag = true;
   InvokeScavenge();
 }
 
-
-static void ForceMarkSweep(
-    const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
+static void ForceScavenge1(
+    const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   data.GetParameter()->handle.Reset();
+  data.SetSecondPassCallback(ForceScavenge2);
+}
+
+
+static void ForceMarkSweep2(
+    const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   data.GetParameter()->flag = true;
   InvokeMarkSweep();
 }
 
+static void ForceMarkSweep1(
+    const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
+  data.GetParameter()->handle.Reset();
+  data.SetSecondPassCallback(ForceMarkSweep2);
+}
+
 
 THREADED_TEST(GCFromWeakCallbacks) {
   v8::Isolate* isolate = CcTest::isolate();
@@ -7138,10 +6787,9 @@ THREADED_TEST(GCFromWeakCallbacks) {
   Context::Scope context_scope(context);
 
   static const int kNumberOfGCTypes = 2;
-  typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
-      Callback;
-  Callback gc_forcing_callback[kNumberOfGCTypes] =
-      {&ForceScavenge, &ForceMarkSweep};
+  typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
+  Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
+                                                    &ForceMarkSweep1};
 
   typedef void (*GCInvoker)();
   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
@@ -7154,7 +6802,8 @@ THREADED_TEST(GCFromWeakCallbacks) {
         object.handle.Reset(isolate, v8::Object::New(isolate));
       }
       object.flag = false;
-      object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
+      object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
+                            v8::WeakCallbackType::kParameter);
       object.handle.MarkIndependent();
       invoke_gc[outer_gc]();
       CHECK(object.flag);
@@ -7163,45 +6812,6 @@ THREADED_TEST(GCFromWeakCallbacks) {
 }
 
 
-static void RevivingCallback(
-    const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
-  data.GetParameter()->handle.ClearWeak();
-  data.GetParameter()->flag = true;
-}
-
-
-THREADED_TEST(IndependentHandleRevival) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<Context> context = Context::New(isolate);
-  Context::Scope context_scope(context);
-
-  FlagAndPersistent object;
-  {
-    v8::HandleScope handle_scope(isolate);
-    v8::Local<v8::Object> o = v8::Object::New(isolate);
-    object.handle.Reset(isolate, o);
-    o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
-    v8::Local<String> y_str = v8_str("y");
-    o->Set(y_str, y_str);
-  }
-  object.flag = false;
-  object.handle.SetWeak(&object, &RevivingCallback);
-  object.handle.MarkIndependent();
-  CcTest::heap()->PerformScavenge();
-  CHECK(object.flag);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
-  {
-    v8::HandleScope handle_scope(isolate);
-    v8::Local<v8::Object> o =
-        v8::Local<v8::Object>::New(isolate, object.handle);
-    v8::Local<String> y_str = v8_str("y");
-    CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x")));
-    CHECK(o->Get(y_str)->Equals(y_str));
-  }
-}
-
-
 v8::Handle<Function> args_fun;
 
 
@@ -7209,14 +6819,14 @@ static void ArgumentsTestCallback(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
   v8::Isolate* isolate = args.GetIsolate();
-  CHECK_EQ(args_fun, args.Callee());
+  CHECK(args_fun->Equals(args.Callee()));
   CHECK_EQ(3, args.Length());
-  CHECK_EQ(v8::Integer::New(isolate, 1), args[0]);
-  CHECK_EQ(v8::Integer::New(isolate, 2), args[1]);
-  CHECK_EQ(v8::Integer::New(isolate, 3), args[2]);
-  CHECK_EQ(v8::Undefined(isolate), args[3]);
+  CHECK(v8::Integer::New(isolate, 1)->Equals(args[0]));
+  CHECK(v8::Integer::New(isolate, 2)->Equals(args[1]));
+  CHECK(v8::Integer::New(isolate, 3)->Equals(args[2]));
+  CHECK(v8::Undefined(isolate)->Equals(args[3]));
   v8::HandleScope scope(args.GetIsolate());
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CcTest::heap()->CollectAllGarbage();
 }
 
 
@@ -7232,160 +6842,8 @@ THREADED_TEST(Arguments) {
 }
 
 
-static void NoBlockGetterX(Local<String> name,
-                           const v8::PropertyCallbackInfo<v8::Value>&) {
-}
-
-
-static void NoBlockGetterI(uint32_t index,
-                           const v8::PropertyCallbackInfo<v8::Value>&) {
-}
-
-
-static void PDeleter(Local<String> name,
-                     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
-  if (!name->Equals(v8_str("foo"))) {
-    return;  // not intercepted
-  }
-
-  info.GetReturnValue().Set(false);  // intercepted, don't delete the property
-}
-
-
-static void IDeleter(uint32_t index,
-                     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
-  if (index != 2) {
-    return;  // not intercepted
-  }
-
-  info.GetReturnValue().Set(false);  // intercepted, don't delete the property
-}
-
-
-THREADED_TEST(Deleter) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
-  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 void GetK(Local<String> name,
-                 const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (name->Equals(v8_str("foo")) ||
-      name->Equals(v8_str("bar")) ||
-      name->Equals(v8_str("baz"))) {
-    info.GetReturnValue().SetUndefined();
-  }
-}
-
-
-static void IndexedGetK(uint32_t index,
-                        const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
-}
-
-
-static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
-  ApiTestFuzzer::Fuzz();
-  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
-  result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"));
-  result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"));
-  result->Set(v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"));
-  info.GetReturnValue().Set(result);
-}
-
-
-static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
-  ApiTestFuzzer::Fuzz();
-  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
-  result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("0"));
-  result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("1"));
-  info.GetReturnValue().Set(result);
-}
-
-
-THREADED_TEST(Enumerators) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
-  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(isolate, 0)));
-  CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(isolate, 1)));
-  CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(isolate, 2)));
-  CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(isolate, 3)));
-  // Indexed interceptor properties in the order they are returned
-  // from the enumerator interceptor.
-  CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(isolate, 4)));
-  CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(isolate, 5)));
-  // Named properties in insertion order.
-  CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(isolate, 6)));
-  CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(isolate, 7)));
-  CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(isolate, 8)));
-  CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(isolate, 9)));
-  CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(isolate, 10)));
-  CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(isolate, 11)));
-  CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(isolate, 12)));
-  CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(isolate, 13)));
-  // Named interceptor properties.
-  CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(isolate, 14)));
-  CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(isolate, 15)));
-  CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(isolate, 16)));
-}
-
-
-int p_getter_count;
-int p_getter_count2;
+static int p_getter_count;
+static int p_getter_count2;
 
 
 static void PGetter(Local<String> name,
@@ -7394,15 +6852,15 @@ static void PGetter(Local<String> name,
   p_getter_count++;
   v8::Handle<v8::Object> global =
       info.GetIsolate()->GetCurrentContext()->Global();
-  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
+  CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
   if (name->Equals(v8_str("p1"))) {
-    CHECK_EQ(info.This(), global->Get(v8_str("o1")));
+    CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
   } else if (name->Equals(v8_str("p2"))) {
-    CHECK_EQ(info.This(), global->Get(v8_str("o2")));
+    CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
   } else if (name->Equals(v8_str("p3"))) {
-    CHECK_EQ(info.This(), global->Get(v8_str("o3")));
+    CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
   } else if (name->Equals(v8_str("p4"))) {
-    CHECK_EQ(info.This(), global->Get(v8_str("o4")));
+    CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
   }
 }
 
@@ -7423,21 +6881,21 @@ static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
 }
 
 
-static void PGetter2(Local<String> name,
+static void PGetter2(Local<Name> name,
                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   ApiTestFuzzer::Fuzz();
   p_getter_count2++;
   v8::Handle<v8::Object> global =
       info.GetIsolate()->GetCurrentContext()->Global();
-  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
+  CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
   if (name->Equals(v8_str("p1"))) {
-    CHECK_EQ(info.This(), global->Get(v8_str("o1")));
+    CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
   } else if (name->Equals(v8_str("p2"))) {
-    CHECK_EQ(info.This(), global->Get(v8_str("o2")));
+    CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
   } else if (name->Equals(v8_str("p3"))) {
-    CHECK_EQ(info.This(), global->Get(v8_str("o3")));
+    CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
   } else if (name->Equals(v8_str("p4"))) {
-    CHECK_EQ(info.This(), global->Get(v8_str("o4")));
+    CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
   }
 }
 
@@ -7460,7 +6918,7 @@ THREADED_TEST(PreInterceptorHolders) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
-  obj->SetNamedPropertyHandler(PGetter2);
+  obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
   p_getter_count2 = 0;
   RunHolderTest(obj);
   CHECK_EQ(40, p_getter_count2);
@@ -7477,11 +6935,11 @@ THREADED_TEST(ObjectInstantiation) {
   for (int i = 0; i < 100; i++) {
     v8::HandleScope inner_scope(CcTest::isolate());
     v8::Handle<v8::Object> obj = templ->NewInstance();
-    CHECK_NE(obj, context->Global()->Get(v8_str("o")));
+    CHECK(!obj->Equals(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(isolate), value);
+        CompileRun("o.__proto__ === o2.__proto__");
+    CHECK(v8::True(isolate)->Equals(value));
     context->Global()->Set(v8_str("o"), obj);
   }
 }
@@ -7512,7 +6970,7 @@ int GetUtf8Length(Handle<String> str) {
   int len = str->Utf8Length();
   if (len < 0) {
     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
-    i::FlattenString(istr);
+    i::String::Flatten(istr);
     len = str->Utf8Length();
   }
   return len;
@@ -7828,7 +7286,7 @@ THREADED_TEST(StringWrite) {
 
 
 static void Utf16Helper(
-    LocalContext& context,
+    LocalContext& context,  // NOLINT
     const char* name,
     const char* lengths_name,
     int len) {
@@ -7847,84 +7305,6 @@ static void Utf16Helper(
 }
 
 
-static uint16_t StringGet(Handle<String> str, int index) {
-  i::Handle<i::String> istring =
-      v8::Utils::OpenHandle(String::Cast(*str));
-  return istring->Get(index);
-}
-
-
-static void WriteUtf8Helper(
-    LocalContext& context,
-    const char* name,
-    const char* lengths_name,
-    int len) {
-  Local<v8::Array> b =
-      Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
-  Local<v8::Array> alens =
-      Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
-  char buffer[1000];
-  char buffer2[1000];
-  for (int i = 0; i < len; i++) {
-    Local<v8::String> string =
-      Local<v8::String>::Cast(b->Get(i));
-    Local<v8::Number> expected_len =
-      Local<v8::Number>::Cast(alens->Get(i));
-    int utf8_length = static_cast<int>(expected_len->Value());
-    for (int j = utf8_length + 1; j >= 0; j--) {
-      memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
-      memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
-      int nchars;
-      int utf8_written =
-          string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
-      int utf8_written2 =
-          string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
-      CHECK_GE(utf8_length + 1, utf8_written);
-      CHECK_GE(utf8_length, utf8_written2);
-      for (int k = 0; k < utf8_written2; k++) {
-        CHECK_EQ(buffer[k], buffer2[k]);
-      }
-      CHECK(nchars * 3 >= utf8_written - 1);
-      CHECK(nchars <= utf8_written);
-      if (j == utf8_length + 1) {
-        CHECK_EQ(utf8_written2, utf8_length);
-        CHECK_EQ(utf8_written2 + 1, utf8_written);
-      }
-      CHECK_EQ(buffer[utf8_written], 42);
-      if (j > utf8_length) {
-        if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
-        if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
-        Handle<String> roundtrip = v8_str(buffer);
-        CHECK(roundtrip->Equals(string));
-      } else {
-        if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
-      }
-      if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
-      if (nchars >= 2) {
-        uint16_t trail = StringGet(string, nchars - 1);
-        uint16_t lead = StringGet(string, nchars - 2);
-        if (((lead & 0xfc00) == 0xd800) &&
-            ((trail & 0xfc00) == 0xdc00)) {
-          unsigned char u1 = buffer2[utf8_written2 - 4];
-          unsigned char u2 = buffer2[utf8_written2 - 3];
-          unsigned char u3 = buffer2[utf8_written2 - 2];
-          unsigned char u4 = buffer2[utf8_written2 - 1];
-          CHECK_EQ((u1 & 0xf8), 0xf0);
-          CHECK_EQ((u2 & 0xc0), 0x80);
-          CHECK_EQ((u3 & 0xc0), 0x80);
-          CHECK_EQ((u4 & 0xc0), 0x80);
-          uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
-          CHECK_EQ((u4 & 0x3f), (c & 0x3f));
-          CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
-          CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
-          CHECK_EQ((u1 & 0x3), c >> 18);
-        }
-      }
-    }
-  }
-}
-
-
 THREADED_TEST(Utf16) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
@@ -7971,9 +7351,6 @@ THREADED_TEST(Utf16) {
       "}");
   Utf16Helper(context, "a", "alens", 9);
   Utf16Helper(context, "a2", "a2lens", 81);
-  WriteUtf8Helper(context, "b", "alens", 9);
-  WriteUtf8Helper(context, "b2", "a2lens", 81);
-  WriteUtf8Helper(context, "c2", "a2lens", 81);
 }
 
 
@@ -7983,15 +7360,6 @@ static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
   return *is1 == *is2;
 }
 
-static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
-                             const char* b) {
-  Handle<String> symbol1 =
-      v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
-  Handle<String> symbol2 =
-      v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
-  CHECK(SameSymbol(symbol1, symbol2));
-}
-
 
 THREADED_TEST(Utf16Symbol) {
   LocalContext context;
@@ -8003,18 +7371,6 @@ THREADED_TEST(Utf16Symbol) {
       context->GetIsolate(), "abc", v8::String::kInternalizedString);
   CHECK(SameSymbol(symbol1, symbol2));
 
-  SameSymbolHelper(context->GetIsolate(),
-                   "\360\220\220\205",  // 4 byte encoding.
-                   "\355\240\201\355\260\205");  // 2 3-byte surrogates.
-  SameSymbolHelper(context->GetIsolate(),
-                   "\355\240\201\355\260\206",  // 2 3-byte surrogates.
-                   "\360\220\220\206");  // 4 byte encoding.
-  SameSymbolHelper(context->GetIsolate(),
-                   "x\360\220\220\205",  // 4 byte encoding.
-                   "x\355\240\201\355\260\205");  // 2 3-byte surrogates.
-  SameSymbolHelper(context->GetIsolate(),
-                   "x\355\240\201\355\260\206",  // 2 3-byte surrogates.
-                   "x\360\220\220\206");  // 4 byte encoding.
   CompileRun(
       "var sym0 = 'benedictus';"
       "var sym0b = 'S\303\270ren';"
@@ -8062,6 +7418,57 @@ THREADED_TEST(Utf16Symbol) {
 }
 
 
+THREADED_TEST(Utf16MissingTrailing) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+
+  // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
+  int size = 1024 * 64;
+  uint8_t* buffer = new uint8_t[size];
+  for (int i = 0; i < size; i += 4) {
+    buffer[i] = 0xf0;
+    buffer[i + 1] = 0x9d;
+    buffer[i + 2] = 0x80;
+    buffer[i + 3] = 0x9e;
+  }
+
+  // Now invoke the decoder without last 3 bytes
+  v8::Local<v8::String> str =
+      v8::String::NewFromUtf8(
+          context->GetIsolate(), reinterpret_cast<char*>(buffer),
+          v8::NewStringType::kNormal, size - 3).ToLocalChecked();
+  USE(str);
+  delete[] buffer;
+}
+
+
+THREADED_TEST(Utf16Trailing3Byte) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+
+  // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
+  int size = 1024 * 63;
+  uint8_t* buffer = new uint8_t[size];
+  for (int i = 0; i < size; i += 3) {
+    buffer[i] = 0xe2;
+    buffer[i + 1] = 0x80;
+    buffer[i + 2] = 0xa6;
+  }
+
+  // Now invoke the decoder without last 3 bytes
+  v8::Local<v8::String> str =
+      v8::String::NewFromUtf8(
+          context->GetIsolate(), reinterpret_cast<char*>(buffer),
+          v8::NewStringType::kNormal, size).ToLocalChecked();
+
+  v8::String::Value value(str);
+  CHECK_EQ(value.length(), size / 3);
+  CHECK_EQ((*value)[value.length() - 1], 0x2026);
+
+  delete[] buffer;
+}
+
+
 THREADED_TEST(ToArrayIndex) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
@@ -8077,10 +7484,10 @@ THREADED_TEST(ToArrayIndex) {
   str = v8_str("-42");
   index = str->ToArrayIndex();
   CHECK(index.IsEmpty());
-  str = v8_str("4294967295");
+  str = v8_str("4294967294");
   index = str->ToArrayIndex();
   CHECK(!index.IsEmpty());
-  CHECK_EQ(4294967295.0, index->Uint32Value());
+  CHECK_EQ(4294967294.0, index->Uint32Value());
   v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
   index = num->ToArrayIndex();
   CHECK(!index.IsEmpty());
@@ -8118,6 +7525,101 @@ THREADED_TEST(ErrorConstruction) {
 }
 
 
+static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  v8::Handle<String> foo = v8_str("foo");
+  v8::Handle<String> message = v8_str("message");
+  v8::Handle<Value> error = v8::Exception::Error(foo);
+  CHECK(error->IsObject());
+  CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
+  info.GetIsolate()->ThrowException(error);
+  info.GetReturnValue().SetUndefined();
+}
+
+
+THREADED_TEST(ExceptionCreateMessage) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::Handle<String> foo_str = v8_str("foo");
+  v8::Handle<String> message_str = v8_str("message");
+
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+
+  Local<v8::FunctionTemplate> fun =
+      v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
+  v8::Local<v8::Object> global = context->Global();
+  global->Set(v8_str("throwV8Exception"), fun->GetFunction());
+
+  TryCatch try_catch(context->GetIsolate());
+  CompileRun(
+      "function f1() {\n"
+      "  throwV8Exception();\n"
+      "};\n"
+      "f1();");
+  CHECK(try_catch.HasCaught());
+
+  v8::Handle<v8::Value> error = try_catch.Exception();
+  CHECK(error->IsObject());
+  CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
+
+  v8::Handle<v8::Message> message = v8::Exception::CreateMessage(error);
+  CHECK(!message.IsEmpty());
+  CHECK_EQ(2, message->GetLineNumber());
+  CHECK_EQ(2, message->GetStartColumn());
+
+  v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace();
+  CHECK(!stackTrace.IsEmpty());
+  CHECK_EQ(2, stackTrace->GetFrameCount());
+
+  stackTrace = v8::Exception::GetStackTrace(error);
+  CHECK(!stackTrace.IsEmpty());
+  CHECK_EQ(2, stackTrace->GetFrameCount());
+
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+
+  // Now check message location when SetCaptureStackTraceForUncaughtExceptions
+  // is false.
+  try_catch.Reset();
+
+  CompileRun(
+      "function f2() {\n"
+      "  return throwV8Exception();\n"
+      "};\n"
+      "f2();");
+  CHECK(try_catch.HasCaught());
+
+  error = try_catch.Exception();
+  CHECK(error->IsObject());
+  CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
+
+  message = v8::Exception::CreateMessage(error);
+  CHECK(!message.IsEmpty());
+  CHECK_EQ(2, message->GetLineNumber());
+  CHECK_EQ(9, message->GetStartColumn());
+
+  // Should be empty stack trace.
+  stackTrace = message->GetStackTrace();
+  CHECK(stackTrace.IsEmpty());
+  CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
+}
+
+
+THREADED_TEST(ExceptionCreateMessageLength) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+
+  // Test that the message is not truncated.
+  TryCatch try_catch(context->GetIsolate());
+  CompileRun(
+      "var message = 'm';"
+      "while (message.length < 1000) message += message;"
+      "throw message;");
+  CHECK(try_catch.HasCaught());
+
+  CHECK_LT(1000, try_catch.Message()->Get()->Length());
+}
+
+
 static void YGetter(Local<String> name,
                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   ApiTestFuzzer::Fuzz();
@@ -8128,10 +7630,9 @@ static void YGetter(Local<String> name,
 static void YSetter(Local<String> name,
                     Local<Value> value,
                     const v8::PropertyCallbackInfo<void>& info) {
-  if (info.This()->Has(name)) {
-    info.This()->Delete(name);
-  }
-  info.This()->Set(name, value);
+  Local<Object> this_obj = Local<Object>::Cast(info.This());
+  if (this_obj->Has(name)) this_obj->Delete(name);
+  this_obj->Set(name, value);
 }
 
 
@@ -8145,7 +7646,7 @@ THREADED_TEST(DeleteAccessor) {
   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());
+  CHECK_EQ(12u, result->Uint32Value());
 }
 
 
@@ -8175,34 +7676,6 @@ THREADED_TEST(TypeSwitch) {
 }
 
 
-// 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 void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
@@ -8241,13 +7714,14 @@ TEST(ApiUncaughtException) {
   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();
+  CompileRun(
+      "function trouble_callee() {"
+      "  var x = null;"
+      "  return x.foo;"
+      "};"
+      "function trouble_caller() {"
+      "  trouble();"
+      "};");
   Local<Value> trouble = global->Get(v8_str("trouble"));
   CHECK(trouble->IsFunction());
   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
@@ -8259,16 +7733,43 @@ TEST(ApiUncaughtException) {
   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
 }
 
+
+TEST(ApiUncaughtExceptionInObjectObserve) {
+  v8::internal::FLAG_stack_size = 150;
+  report_count = 0;
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
+  CompileRun(
+      "var obj = {};"
+      "var observe_count = 0;"
+      "function observer1() { ++observe_count; };"
+      "function observer2() { ++observe_count; };"
+      "function observer_throws() { throw new Error(); };"
+      "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
+      "Object.observe(obj, observer_throws.bind());"
+      "Object.observe(obj, observer1);"
+      "Object.observe(obj, stack_overflow);"
+      "Object.observe(obj, observer2);"
+      "Object.observe(obj, observer_throws.bind());"
+      "obj.foo = 'bar';");
+  CHECK_EQ(3, report_count);
+  ExpectInt32("observe_count", 2);
+  v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
+}
+
+
 static const char* script_resource_name = "ExceptionInNativeScript.js";
 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
                                                 v8::Handle<Value>) {
-  v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
+  v8::Handle<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
   CHECK(!name_val.IsEmpty() && name_val->IsString());
-  v8::String::Utf8Value name(message->GetScriptResourceName());
-  CHECK_EQ(script_resource_name, *name);
+  v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
+  CHECK_EQ(0, strcmp(script_resource_name, *name));
   CHECK_EQ(3, message->GetLineNumber());
   v8::String::Utf8Value source_line(message->GetSourceLine());
-  CHECK_EQ("  new o.foo();", *source_line);
+  CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
 }
 
 
@@ -8283,13 +7784,12 @@ TEST(ExceptionInNativeScript) {
   v8::Local<v8::Object> global = env->Global();
   global->Set(v8_str("trouble"), fun->GetFunction());
 
-  Script::Compile(
-      v8_str(
-          "function trouble() {\n"
-          "  var o = {};\n"
-          "  new o.foo();\n"
-          "};"),
-      v8::String::NewFromUtf8(isolate, script_resource_name))->Run();
+  CompileRunWithOrigin(
+      "function trouble() {\n"
+      "  var o = {};\n"
+      "  new o.foo();\n"
+      "};",
+      script_resource_name);
   Local<Value> trouble = global->Get(v8_str("trouble"));
   CHECK(trouble->IsFunction());
   Function::Cast(*trouble)->Call(global, 0, NULL);
@@ -8300,9 +7800,9 @@ TEST(ExceptionInNativeScript) {
 TEST(CompilationErrorUsingTryCatchHandler) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
-  v8::TryCatch try_catch;
-  Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
-  CHECK_NE(NULL, *try_catch.Exception());
+  v8::TryCatch try_catch(env->GetIsolate());
+  v8_compile("This doesn't &*&@#$&*^ compile.");
+  CHECK(*try_catch.Exception());
   CHECK(try_catch.HasCaught());
 }
 
@@ -8310,20 +7810,66 @@ TEST(CompilationErrorUsingTryCatchHandler) {
 TEST(TryCatchFinallyUsingTryCatchHandler) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
-  v8::TryCatch try_catch;
-  Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
+  v8::TryCatch try_catch(env->GetIsolate());
+  CompileRun("try { throw ''; } catch (e) {}");
   CHECK(!try_catch.HasCaught());
-  Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
+  CompileRun("try { throw ''; } finally {}");
   CHECK(try_catch.HasCaught());
   try_catch.Reset();
-  Script::Compile(v8_str("(function() {"
-                         "try { throw ''; } finally { return; }"
-                         "})()"))->Run();
+  CompileRun(
+      "(function() {"
+      "try { throw ''; } finally { return; }"
+      "})()");
   CHECK(!try_catch.HasCaught());
-  Script::Compile(v8_str("(function()"
-                         "  { try { throw ''; } finally { throw 0; }"
-                         "})()"))->Run();
+  CompileRun(
+      "(function()"
+      "  { try { throw ''; } finally { throw 0; }"
+      "})()");
+  CHECK(try_catch.HasCaught());
+}
+
+
+void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::HandleScope scope(args.GetIsolate());
+  CompileRun(args[0]->ToString(args.GetIsolate()));
+}
+
+
+TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->Set(v8_str("CEvaluate"),
+             v8::FunctionTemplate::New(isolate, CEvaluate));
+  LocalContext context(0, templ);
+  v8::TryCatch try_catch(isolate);
+  CompileRun("try {"
+             "  CEvaluate('throw 1;');"
+             "} finally {"
+             "}");
+  CHECK(try_catch.HasCaught());
+  CHECK(!try_catch.Message().IsEmpty());
+  String::Utf8Value exception_value(try_catch.Exception());
+  CHECK_EQ(0, strcmp(*exception_value, "1"));
+  try_catch.Reset();
+  CompileRun("try {"
+             "  CEvaluate('throw 1;');"
+             "} finally {"
+             "  throw 2;"
+             "}");
   CHECK(try_catch.HasCaught());
+  CHECK(!try_catch.Message().IsEmpty());
+  String::Utf8Value finally_exception_value(try_catch.Exception());
+  CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
+}
+
+
+// For use within the TestSecurityHandler() test.
+static bool g_security_callback_result = false;
+static bool SecurityTestCallback(Local<v8::Object> global, Local<Value> name,
+                                 v8::AccessType type, Local<Value> data) {
+  printf("a\n");
+  return g_security_callback_result;
 }
 
 
@@ -8333,8 +7879,7 @@ TEST(SecurityHandler) {
   v8::HandleScope scope0(isolate);
   v8::Handle<v8::ObjectTemplate> global_template =
       v8::ObjectTemplate::New(isolate);
-  global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
-                                           IndexedSecurityTestCallback);
+  global_template->SetAccessCheckCallbacks(SecurityTestCallback, NULL);
   // Create an environment
   v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
   context0->Enter();
@@ -8361,6 +7906,7 @@ TEST(SecurityHandler) {
   v8::Handle<Script> script1 =
     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
   script1->Run();
+  g_security_callback_result = true;
   // This read will pass the security check.
   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
   CHECK_EQ(111, foo1->Int32Value());
@@ -8369,7 +7915,7 @@ TEST(SecurityHandler) {
   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(isolate);
     LocalContext context2;
     v8::Handle<v8::Object> global2 = context2->Global();
@@ -8400,12 +7946,12 @@ THREADED_TEST(SecurityChecks) {
   env1->SetSecurityToken(foo);
 
   // Create a function in env1.
-  Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
+  CompileRun("spy=function(){return spy;}");
   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();
+  CompileRun("spy2=function(){return new this.Array();}");
   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
   CHECK(spy2->IsFunction());
 
@@ -8423,7 +7969,7 @@ THREADED_TEST(SecurityChecks) {
     Context::Scope scope_env2(env2);
 
     // Call cross_domain_call, it should throw an exception
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(env1->GetIsolate());
     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
     CHECK(try_catch.HasCaught());
   }
@@ -8453,10 +7999,8 @@ THREADED_TEST(SecurityChecksForPrototypeChain) {
   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());
+    CHECK(access_other0->Run().IsEmpty());
+    CHECK(access_other1->Run().IsEmpty());
   }
 
   // Create an object that has 'other' in its prototype chain and make
@@ -8468,10 +8012,8 @@ THREADED_TEST(SecurityChecksForPrototypeChain) {
   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());
+    CHECK(access_f0->Run().IsEmpty());
+    CHECK(access_f1->Run().IsEmpty());
   }
 
   // Now it gets hairy: Set the prototype for the other global object
@@ -8490,14 +8032,45 @@ THREADED_TEST(SecurityChecksForPrototypeChain) {
   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());
+    CHECK(access_f2->Run().IsEmpty());
+    CHECK(access_f3->Run().IsEmpty());
   }
 }
 
 
+static bool security_check_with_gc_called;
+
+static bool SecurityTestCallbackWithGC(Local<v8::Object> global,
+                                       Local<v8::Value> name,
+                                       v8::AccessType type, Local<Value> data) {
+  CcTest::heap()->CollectAllGarbage();
+  security_check_with_gc_called = true;
+  return true;
+}
+
+
+TEST(SecurityTestGCAllowed) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<v8::ObjectTemplate> object_template =
+      v8::ObjectTemplate::New(isolate);
+  object_template->SetAccessCheckCallbacks(SecurityTestCallbackWithGC, NULL);
+
+  v8::Handle<Context> context = Context::New(isolate);
+  v8::Context::Scope context_scope(context);
+
+  context->Global()->Set(v8_str("obj"), object_template->NewInstance());
+
+  security_check_with_gc_called = false;
+  CompileRun("obj[0] = new String(1002);");
+  CHECK(security_check_with_gc_called);
+
+  security_check_with_gc_called = false;
+  CHECK(CompileRun("obj[0]")->ToString(isolate)->Equals(v8_str("1002")));
+  CHECK(security_check_with_gc_called);
+}
+
+
 THREADED_TEST(CrossDomainDelete) {
   LocalContext env1;
   v8::HandleScope handle_scope(env1->GetIsolate());
@@ -8518,8 +8091,8 @@ THREADED_TEST(CrossDomainDelete) {
   {
     Context::Scope scope_env2(env2);
     Local<Value> result =
-        Script::Compile(v8_str("delete env1.prop"))->Run();
-    CHECK(result->IsFalse());
+        CompileRun("delete env1.prop");
+    CHECK(result.IsEmpty());
   }
 
   // Check that env1.prop still exists.
@@ -8548,7 +8121,7 @@ THREADED_TEST(CrossDomainIsPropertyEnumerable) {
   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
   {
     Context::Scope scope_env2(env2);
-    Local<Value> result = Script::Compile(test)->Run();
+    Local<Value> result = CompileRun(test);
     CHECK(result->IsTrue());
   }
 
@@ -8556,8 +8129,8 @@ THREADED_TEST(CrossDomainIsPropertyEnumerable) {
   env2->SetSecurityToken(bar);
   {
     Context::Scope scope_env2(env2);
-    Local<Value> result = Script::Compile(test)->Run();
-    CHECK(result->IsFalse());
+    Local<Value> result = CompileRun(test);
+    CHECK(result.IsEmpty());
   }
 }
 
@@ -8584,11 +8157,18 @@ THREADED_TEST(CrossDomainForIn) {
   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;})()");
+    Local<Value> result = CompileRun(
+        "(function() {"
+        "  var obj = { '__proto__': env1 };"
+        "  try {"
+        "    for (var p in obj) {"
+        "      if (p == 'prop') return false;"
+        "    }"
+        "    return false;"
+        "  } catch (e) {"
+        "    return true;"
+        "  }"
+        "})()");
     CHECK(result->IsTrue());
   }
 }
@@ -8630,7 +8210,7 @@ TEST(ContextDetachGlobal) {
   env3->Enter();
 
   Local<v8::Object> global3 = env3->Global();
-  CHECK_EQ(global2, global3);
+  CHECK(global2->Equals(global3));
   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
   global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
@@ -8641,7 +8221,7 @@ TEST(ContextDetachGlobal) {
   {
     Local<Value> get_prop = global1->Get(v8_str("getProp"));
     CHECK(get_prop->IsFunction());
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(env1->GetIsolate());
     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
     CHECK(!try_catch.HasCaught());
     CHECK_EQ(1, r->Int32Value());
@@ -8650,7 +8230,7 @@ TEST(ContextDetachGlobal) {
   // Check that env3 is not accessible from env1
   {
     Local<Value> r = global3->Get(v8_str("prop2"));
-    CHECK(r->IsUndefined());
+    CHECK(r.IsEmpty());
   }
 }
 
@@ -8689,14 +8269,14 @@ TEST(DetachGlobal) {
   // Check that the global has been detached. No other.p property can
   // be found.
   result = CompileRun("other.p");
-  CHECK(result->IsUndefined());
+  CHECK(result.IsEmpty());
 
   // Reuse global2 for env3.
   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
                                           0,
                                           v8::Handle<v8::ObjectTemplate>(),
                                           global2);
-  CHECK_EQ(global2, env3->Global());
+  CHECK(global2->Equals(env3->Global()));
 
   // Start by using the same security token for env3 as for env1 and env2.
   env3->SetSecurityToken(foo);
@@ -8719,7 +8299,7 @@ TEST(DetachGlobal) {
   // the global object for env3 which has a different security token,
   // so access should be blocked.
   result = CompileRun("other.p");
-  CHECK(result->IsUndefined());
+  CHECK(result.IsEmpty());
 }
 
 
@@ -8765,18 +8345,17 @@ TEST(DetachedAccesses) {
   }
 
   Local<Object> env2_global = env2->Global();
-  env2_global->TurnOnAccessCheck();
   env2->DetachGlobal();
 
   Local<Value> result;
   result = CompileRun("bound_x()");
-  CHECK_EQ(v8_str("env2_x"), result);
+  CHECK(v8_str("env2_x")->Equals(result));
   result = CompileRun("get_x()");
-  CHECK(result->IsUndefined());
+  CHECK(result.IsEmpty());
   result = CompileRun("get_x_w()");
-  CHECK(result->IsUndefined());
+  CHECK(result.IsEmpty());
   result = CompileRun("this_x()");
-  CHECK_EQ(v8_str("env2_x"), result);
+  CHECK(v8_str("env2_x")->Equals(result));
 
   // Reattach env2's proxy
   env2 = Context::New(env1->GetIsolate(),
@@ -8798,12 +8377,12 @@ TEST(DetachedAccesses) {
         "}"
         "results");
     Local<v8::Array> results = Local<v8::Array>::Cast(result);
-    CHECK_EQ(16, results->Length());
+    CHECK_EQ(16u, results->Length());
     for (int i = 0; i < 16; i += 4) {
-      CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
-      CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
-      CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
-      CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
+      CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
+      CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
+      CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
+      CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
     }
   }
 
@@ -8817,12 +8396,12 @@ TEST(DetachedAccesses) {
       "}"
       "results");
   Local<v8::Array> results = Local<v8::Array>::Cast(result);
-  CHECK_EQ(16, results->Length());
+  CHECK_EQ(16u, results->Length());
   for (int i = 0; i < 16; i += 4) {
-    CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
-    CHECK_EQ(v8_str("env3_x"), results->Get(i + 1));
-    CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
-    CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
+    CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
+    CHECK(v8_str("env3_x")->Equals(results->Get(i + 1)));
+    CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
+    CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
   }
 
   result = CompileRun(
@@ -8835,48 +8414,31 @@ TEST(DetachedAccesses) {
       "}"
       "results");
   results = Local<v8::Array>::Cast(result);
-  CHECK_EQ(16, results->Length());
+  CHECK_EQ(16u, results->Length());
   for (int i = 0; i < 16; i += 4) {
-    CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
-    CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
-    CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
-    CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
+    CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
+    CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
+    CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
+    CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
   }
 }
 
 
-static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
-static bool NamedAccessBlocker(Local<v8::Object> global,
-                               Local<Value> name,
-                               v8::AccessType type,
-                               Local<Value> data) {
+static bool allowed_access = false;
+static bool AccessBlocker(Local<v8::Object> global, Local<Value> name,
+                          v8::AccessType type, Local<Value> data) {
   return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
-      allowed_access_type[type];
+         allowed_access;
 }
 
 
-static bool IndexedAccessBlocker(Local<v8::Object> global,
-                                 uint32_t key,
-                                 v8::AccessType type,
-                                 Local<Value> data) {
-  return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
-      allowed_access_type[type];
-}
-
-
-static int g_echo_value_1 = -1;
-static int g_echo_value_2 = -1;
+static int g_echo_value = -1;
 
 
 static void EchoGetter(
     Local<String> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(v8_num(g_echo_value_1));
-}
-
-
-static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(v8_num(g_echo_value_2));
+  info.GetReturnValue().Set(v8_num(g_echo_value));
 }
 
 
@@ -8884,14 +8446,7 @@ static void EchoSetter(Local<String> name,
                        Local<Value> value,
                        const v8::PropertyCallbackInfo<void>&) {
   if (value->IsNumber())
-    g_echo_value_1 = value->Int32Value();
-}
-
-
-static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  v8::Handle<v8::Value> value = info[0];
-  if (value->IsNumber())
-    g_echo_value_2 = value->Int32Value();
+    g_echo_value = value->Int32Value();
 }
 
 
@@ -8921,8 +8476,7 @@ TEST(AccessControl) {
   v8::Handle<v8::ObjectTemplate> global_template =
       v8::ObjectTemplate::New(isolate);
 
-  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
-                                           IndexedAccessBlocker);
+  global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
 
   // Add an accessor accessible by cross-domain JS code.
   global_template->SetAccessor(
@@ -8932,13 +8486,6 @@ TEST(AccessControl) {
       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
 
 
-  global_template->SetAccessorProperty(
-      v8_str("accessible_js_prop"),
-      v8::FunctionTemplate::New(isolate, EchoGetter),
-      v8::FunctionTemplate::New(isolate, EchoSetter),
-      v8::None,
-      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,
@@ -8990,89 +8537,32 @@ TEST(AccessControl) {
   // Access blocked property.
   CompileRun("other.blocked_prop = 1");
 
-  ExpectUndefined("other.blocked_prop");
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
-  ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
-
-  // Enable ACCESS_HAS
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  ExpectUndefined("other.blocked_prop");
-  // ... and now we can get the descriptor...
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
-  // ... and enumerate the property.
-  ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
-  allowed_access_type[v8::ACCESS_HAS] = false;
+  CHECK(CompileRun("other.blocked_prop").IsEmpty());
+  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
+            .IsEmpty());
+  CHECK(
+      CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
 
   // Access blocked element.
-  CompileRun("other[239] = 1");
-
-  ExpectUndefined("other[239]");
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
-  ExpectFalse("propertyIsEnumerable.call(other, '239')");
-
-  // Enable ACCESS_HAS
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  ExpectUndefined("other[239]");
-  // ... and now we can get the descriptor...
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
-  // ... and enumerate the property.
+  CHECK(CompileRun("other[239] = 1").IsEmpty());
+
+  CHECK(CompileRun("other[239]").IsEmpty());
+  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
+  CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
+
+  allowed_access = true;
+  // Now we can enumerate the property.
   ExpectTrue("propertyIsEnumerable.call(other, '239')");
-  allowed_access_type[v8::ACCESS_HAS] = false;
+  allowed_access = false;
 
   // Access a property with JS accessor.
-  CompileRun("other.js_accessor_p = 2");
+  CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
 
-  ExpectUndefined("other.js_accessor_p");
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
+  CHECK(CompileRun("other.js_accessor_p").IsEmpty());
+  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
+            .IsEmpty());
 
-  // Enable ACCESS_HAS.
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  ExpectUndefined("other.js_accessor_p");
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
-  allowed_access_type[v8::ACCESS_HAS] = false;
-
-  // Enable both ACCESS_HAS and ACCESS_GET.
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  allowed_access_type[v8::ACCESS_GET] = true;
-
-  ExpectString("other.js_accessor_p", "getter");
-  ExpectObject(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
-
-  allowed_access_type[v8::ACCESS_GET] = false;
-  allowed_access_type[v8::ACCESS_HAS] = false;
-
-  // Enable both ACCESS_HAS and ACCESS_SET.
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  allowed_access_type[v8::ACCESS_SET] = true;
-
-  ExpectUndefined("other.js_accessor_p");
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
-  ExpectObject(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
-
-  allowed_access_type[v8::ACCESS_SET] = false;
-  allowed_access_type[v8::ACCESS_HAS] = false;
-
-  // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  allowed_access_type[v8::ACCESS_GET] = true;
-  allowed_access_type[v8::ACCESS_SET] = true;
+  allowed_access = true;
 
   ExpectString("other.js_accessor_p", "getter");
   ExpectObject(
@@ -9082,61 +8572,22 @@ TEST(AccessControl) {
   ExpectUndefined(
       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
 
-  allowed_access_type[v8::ACCESS_SET] = false;
-  allowed_access_type[v8::ACCESS_GET] = false;
-  allowed_access_type[v8::ACCESS_HAS] = false;
+  allowed_access = false;
 
   // Access an element with JS accessor.
-  CompileRun("other[42] = 2");
-
-  ExpectUndefined("other[42]");
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
-
-  // Enable ACCESS_HAS.
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  ExpectUndefined("other[42]");
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
-  allowed_access_type[v8::ACCESS_HAS] = false;
-
-  // Enable both ACCESS_HAS and ACCESS_GET.
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  allowed_access_type[v8::ACCESS_GET] = true;
-
-  ExpectString("other[42]", "el_getter");
-  ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
-
-  allowed_access_type[v8::ACCESS_GET] = false;
-  allowed_access_type[v8::ACCESS_HAS] = false;
-
-  // Enable both ACCESS_HAS and ACCESS_SET.
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  allowed_access_type[v8::ACCESS_SET] = true;
-
-  ExpectUndefined("other[42]");
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
-  ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
-  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
+  CHECK(CompileRun("other[42] = 2").IsEmpty());
 
-  allowed_access_type[v8::ACCESS_SET] = false;
-  allowed_access_type[v8::ACCESS_HAS] = false;
+  CHECK(CompileRun("other[42]").IsEmpty());
+  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
 
-  // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
-  allowed_access_type[v8::ACCESS_HAS] = true;
-  allowed_access_type[v8::ACCESS_GET] = true;
-  allowed_access_type[v8::ACCESS_SET] = true;
+  allowed_access = true;
 
   ExpectString("other[42]", "el_getter");
   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
 
-  allowed_access_type[v8::ACCESS_SET] = false;
-  allowed_access_type[v8::ACCESS_GET] = false;
-  allowed_access_type[v8::ACCESS_HAS] = false;
+  allowed_access = false;
 
   v8::Handle<Value> value;
 
@@ -9144,50 +8595,38 @@ TEST(AccessControl) {
   value = CompileRun("other.accessible_prop = 3");
   CHECK(value->IsNumber());
   CHECK_EQ(3, value->Int32Value());
-  CHECK_EQ(3, g_echo_value_1);
-
-  // Access accessible js property
-  value = CompileRun("other.accessible_js_prop = 3");
-  CHECK(value->IsNumber());
-  CHECK_EQ(3, value->Int32Value());
-  CHECK_EQ(3, g_echo_value_2);
+  CHECK_EQ(3, g_echo_value);
 
   value = CompileRun("other.accessible_prop");
   CHECK(value->IsNumber());
   CHECK_EQ(3, value->Int32Value());
 
-  value = CompileRun("other.accessible_js_prop");
-  CHECK(value->IsNumber());
-  CHECK_EQ(3, value->Int32Value());
-
   value = CompileRun(
       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   CHECK(value->IsNumber());
   CHECK_EQ(3, value->Int32Value());
 
-  value = CompileRun(
-      "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
-  CHECK(value->IsNumber());
-  CHECK_EQ(3, value->Int32Value());
-
   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   CHECK(value->IsTrue());
 
-  value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
-  CHECK(value->IsTrue());
-
   // Enumeration doesn't enumerate accessors from inaccessible objects in
   // the prototype chain even if the accessors are in themselves accessible.
-  value =
-      CompileRun("(function(){var obj = {'__proto__':other};"
-                 "for (var p in obj)"
-                 "   if (p == 'accessible_prop' ||"
-                 "       p == 'accessible_js_prop' ||"
-                 "       p == 'blocked_js_prop' ||"
-                 "       p == 'blocked_js_prop') {"
-                 "     return false;"
-                 "   }"
-                 "return true;})()");
+  value = CompileRun(
+      "(function() {"
+      "  var obj = { '__proto__': other };"
+      "  try {"
+      "    for (var p in obj) {"
+      "      if (p == 'accessible_prop' ||"
+      "          p == 'blocked_js_prop' ||"
+      "          p == 'blocked_js_prop') {"
+      "        return false;"
+      "      }"
+      "    }"
+      "    return false;"
+      "  } catch (e) {"
+      "    return true;"
+      "  }"
+      "})()");
   CHECK(value->IsTrue());
 
   context1->Exit();
@@ -9201,8 +8640,7 @@ TEST(AccessControlES5) {
   v8::Handle<v8::ObjectTemplate> global_template =
       v8::ObjectTemplate::New(isolate);
 
-  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
-                                           IndexedAccessBlocker);
+  global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
 
   // Add accessible accessor.
   global_template->SetAccessor(
@@ -9230,16 +8668,15 @@ TEST(AccessControlES5) {
   global1->Set(v8_str("other"), global0);
 
   // Regression test for issue 1154.
-  ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
-
-  ExpectUndefined("other.blocked_prop");
+  CHECK(CompileRun("Object.keys(other)").IsEmpty());
+  CHECK(CompileRun("other.blocked_prop").IsEmpty());
 
   // Regression test for issue 1027.
   CompileRun("Object.defineProperty(\n"
              "  other, 'blocked_prop', {configurable: false})");
-  ExpectUndefined("other.blocked_prop");
-  ExpectUndefined(
-      "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
+  CHECK(CompileRun("other.blocked_prop").IsEmpty());
+  CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
+            .IsEmpty());
 
   // Regression test for issue 1171.
   ExpectTrue("Object.isExtensible(other)");
@@ -9257,28 +8694,18 @@ TEST(AccessControlES5) {
   // Make sure that we can set the accessible accessors value using normal
   // assignment.
   CompileRun("other.accessible_prop = 42");
-  CHECK_EQ(42, g_echo_value_1);
+  CHECK_EQ(42, g_echo_value);
 
   v8::Handle<Value> value;
-  // We follow Safari in ignoring assignments to host object accessors.
   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
   value = CompileRun("other.accessible_prop == 42");
   CHECK(value->IsTrue());
 }
 
 
-static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
-                                            Local<Value> name,
-                                            v8::AccessType type,
-                                            Local<Value> data) {
-  return false;
-}
-
-
-static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
-                                              uint32_t key,
-                                              v8::AccessType type,
-                                              Local<Value> data) {
+static bool AccessAlwaysBlocked(Local<v8::Object> global, Local<Value> name,
+                                v8::AccessType type, Local<Value> data) {
+  i::PrintF("Access blocked.\n");
   return false;
 }
 
@@ -9290,8 +8717,7 @@ THREADED_TEST(AccessControlGetOwnPropertyNames) {
       v8::ObjectTemplate::New(isolate);
 
   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
-  obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
-                                        GetOwnPropertyNamesIndexedBlocker);
+  obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
 
   // Create an environment
   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
@@ -9316,62 +8742,91 @@ THREADED_TEST(AccessControlGetOwnPropertyNames) {
   // proxy object.  Accessing the object that requires access checks
   // is blocked by the access checks on the object itself.
   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
-  CHECK(value->IsTrue());
+  CHECK(value.IsEmpty());
 
   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
-  CHECK(value->IsTrue());
+  CHECK(value.IsEmpty());
 
   context1->Exit();
   context0->Exit();
 }
 
 
-static void IndexedPropertyEnumerator(
-    const v8::PropertyCallbackInfo<v8::Array>& info) {
-  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
-  result->Set(0, v8::Integer::New(info.GetIsolate(), 7));
-  result->Set(1, v8::Object::New(info.GetIsolate()));
-  info.GetReturnValue().Set(result);
-}
+TEST(SuperAccessControl) {
+  i::FLAG_allow_natives_syntax = true;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<v8::ObjectTemplate> obj_template =
+      v8::ObjectTemplate::New(isolate);
+  obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
+  LocalContext env;
+  env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
 
+  {
+    v8::TryCatch try_catch(isolate);
+    CompileRun(
+        "var f = { m() { return super.hasOwnProperty; } }.m;"
+        "var m = %ToMethod(f, prohibited);"
+        "m();");
+    CHECK(try_catch.HasCaught());
+  }
 
-static void NamedPropertyEnumerator(
-    const v8::PropertyCallbackInfo<v8::Array>& info) {
-  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
-  result->Set(0, v8_str("x"));
-  result->Set(1, v8::Object::New(info.GetIsolate()));
-  info.GetReturnValue().Set(result);
+  {
+    v8::TryCatch try_catch(isolate);
+    CompileRun(
+        "var f = {m() { return super[42]; } }.m;"
+        "var m = %ToMethod(f, prohibited);"
+        "m();");
+    CHECK(try_catch.HasCaught());
+  }
+
+  {
+    v8::TryCatch try_catch(isolate);
+    CompileRun(
+        "var f = {m() { super.hasOwnProperty = function () {}; } }.m;"
+        "var m = %ToMethod(f, prohibited);"
+        "m();");
+    CHECK(try_catch.HasCaught());
+  }
+
+  {
+    v8::TryCatch try_catch(isolate);
+    CompileRun(
+        "Object.defineProperty(Object.prototype, 'x', { set : function(){}});"
+        "var f = {"
+        "  m() { "
+        "    'use strict';"
+        "    super.x = function () {};"
+        "  }"
+        "}.m;"
+        "var m = %ToMethod(f, prohibited);"
+        "m();");
+    CHECK(try_catch.HasCaught());
+  }
 }
 
 
-THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
+TEST(Regress470113) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope handle_scope(isolate);
   v8::Handle<v8::ObjectTemplate> obj_template =
       v8::ObjectTemplate::New(isolate);
+  obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
+  LocalContext env;
+  env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
 
-  obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
-  obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
-  obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
-                                          IndexedPropertyEnumerator);
-  obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
-                                        NamedPropertyEnumerator);
-
-  LocalContext context;
-  v8::Handle<v8::Object> global = context->Global();
-  global->Set(v8_str("object"), obj_template->NewInstance());
+  {
+    v8::TryCatch try_catch(isolate);
+    CompileRun(
+        "'use strict';\n"
+        "class C extends Object {\n"
+        "   m() { super.powned = 'Powned!'; }\n"
+        "}\n"
+        "let c = new C();\n"
+        "c.m.call(prohibited)");
 
-  v8::Handle<v8::Value> result =
-      CompileRun("Object.getOwnPropertyNames(object)");
-  CHECK(result->IsArray());
-  v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
-  CHECK_EQ(3, result_array->Length());
-  CHECK(result_array->Get(0)->IsString());
-  CHECK(result_array->Get(1)->IsString());
-  CHECK(result_array->Get(2)->IsString());
-  CHECK_EQ(v8_str("7"), result_array->Get(0));
-  CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
-  CHECK_EQ(v8_str("x"), result_array->Get(2));
+    CHECK(try_catch.HasCaught());
+  }
 }
 
 
@@ -9427,38 +8882,25 @@ THREADED_TEST(CrossDomainAccessors) {
   CHECK_EQ(10, value->Int32Value());
 
   value = v8_compile("other.unreachable")->Run();
-  CHECK(value->IsUndefined());
+  CHECK(value.IsEmpty());
 
   context1->Exit();
   context0->Exit();
 }
 
 
-static int named_access_count = 0;
-static int indexed_access_count = 0;
+static int 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++;
+static bool AccessCounter(Local<v8::Object> global, Local<Value> name,
+                          v8::AccessType type, Local<Value> data) {
+  access_count++;
   return true;
 }
 
 
 // This one is too easily disturbed by other tests.
 TEST(AccessControlIC) {
-  named_access_count = 0;
-  indexed_access_count = 0;
+  access_count = 0;
 
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope handle_scope(isolate);
@@ -9471,8 +8913,7 @@ TEST(AccessControlIC) {
   // called for cross-domain access.
   v8::Handle<v8::ObjectTemplate> object_template =
       v8::ObjectTemplate::New(isolate);
-  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
-                                           IndexedAccessCounter);
+  object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
   Local<v8::Object> object = object_template->NewInstance();
 
   v8::HandleScope scope1(isolate);
@@ -9496,7 +8937,7 @@ TEST(AccessControlIC) {
   value = CompileRun("testProp(obj)");
   CHECK(value->IsNumber());
   CHECK_EQ(1, value->Int32Value());
-  CHECK_EQ(21, named_access_count);
+  CHECK_EQ(21, access_count);
 
   // Check that the named access-control function is called every time.
   CompileRun("var p = 'prop';"
@@ -9510,16 +8951,18 @@ TEST(AccessControlIC) {
   value = CompileRun("testKeyed(obj)");
   CHECK(value->IsNumber());
   CHECK_EQ(1, value->Int32Value());
-  CHECK_EQ(42, named_access_count);
+  CHECK_EQ(42, 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_EQ(63, access_count);
 
   // Check that the indexed access-control function is called every time.
+  access_count = 0;
+
   CompileRun("function testIndexed(obj) {"
              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
              "  for (var j = 0; j < 10; j++) obj[0];"
@@ -9528,15 +8971,16 @@ TEST(AccessControlIC) {
   value = CompileRun("testIndexed(obj)");
   CHECK(value->IsNumber());
   CHECK_EQ(1, value->Int32Value());
-  CHECK_EQ(21, indexed_access_count);
+  CHECK_EQ(21, 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_EQ(42, access_count);
 
+  access_count = 0;
   // Check that the named access check is called when invoking
   // functions on an object that requires access checks.
   CompileRun("obj.f = function() {}");
@@ -9544,7 +8988,8 @@ TEST(AccessControlIC) {
              "  for (var i = 0; i < 10; i++) obj.f();"
              "}");
   CompileRun("testCallNormal(obj)");
-  CHECK_EQ(74, named_access_count);
+  printf("%i\n", access_count);
+  CHECK_EQ(11, access_count);
 
   // Force obj into slow case.
   value = CompileRun("delete obj.prop");
@@ -9555,195 +9000,21 @@ TEST(AccessControlIC) {
   value = CompileRun("testProp(obj);");
   CHECK(value->IsNumber());
   CHECK_EQ(1, value->Int32Value());
-  CHECK_EQ(96, named_access_count);
+  CHECK_EQ(33, 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();
-}
-
-
-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 = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
-  CHECK_EQ(4, len);
-
-  uint16_t buf2[100];
-
-  memset(buf, 0x1, sizeof(buf));
-  len = name.As<String>()->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::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope handle_scope(isolate);
-
-  // Create an environment.
-  v8::Local<Context> context0 = Context::New(isolate);
-  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(isolate);
-  object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
-                                           IndexedAccessFlatten);
-  Local<v8::Object> object = object_template->NewInstance();
-
-  v8::HandleScope scope1(isolate);
-
-  // Create another environment.
-  v8::Local<Context> context1 = Context::New(isolate);
-  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();
-}
-
-
-static void AccessControlNamedGetter(
-    Local<String>,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(42);
-}
-
-
-static void AccessControlNamedSetter(
-    Local<String>,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(value);
-}
-
-
-static void AccessControlIndexedGetter(
-      uint32_t index,
-      const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(v8_num(42));
-}
-
-
-static void AccessControlIndexedSetter(
-    uint32_t,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(value);
-}
-
-
-THREADED_TEST(AccessControlInterceptorIC) {
-  named_access_count = 0;
-  indexed_access_count = 0;
-
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope handle_scope(isolate);
-
-  // Create an environment.
-  v8::Local<Context> context0 = Context::New(isolate);
-  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(isolate);
-  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(isolate);
-
-  // Create another environment.
-  v8::Local<Context> context1 = Context::New(isolate);
-  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);
+  CHECK_EQ(43, access_count);
 
   context1->Exit();
   context0->Exit();
 }
 
 
-THREADED_TEST(Version) {
-  v8::V8::GetVersion();
-}
+THREADED_TEST(Version) { v8::V8::GetVersion(); }
 
 
 static void InstanceFunctionCallback(
@@ -9768,17 +9039,16 @@ THREADED_TEST(InstanceProperties) {
   Local<Value> o = t->GetFunction()->NewInstance();
 
   context->Global()->Set(v8_str("i"), o);
-  Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
+  Local<Value> value = CompileRun("i.x");
   CHECK_EQ(42, value->Int32Value());
 
-  value = Script::Compile(v8_str("i.f()"))->Run();
+  value = CompileRun("i.f()");
   CHECK_EQ(12, value->Int32Value());
 }
 
 
 static void GlobalObjectInstancePropertiesGet(
-    Local<String> key,
-    const v8::PropertyCallbackInfo<v8::Value>&) {
+    Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
   ApiTestFuzzer::Fuzz();
 }
 
@@ -9790,8 +9060,8 @@ THREADED_TEST(GlobalObjectInstanceProperties) {
   Local<Value> global_object;
 
   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
-  t->InstanceTemplate()->SetNamedPropertyHandler(
-      GlobalObjectInstancePropertiesGet);
+  t->InstanceTemplate()->SetHandler(
+      v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   instance_template->Set(v8_str("x"), v8_num(42));
   instance_template->Set(v8_str("f"),
@@ -9820,22 +9090,22 @@ THREADED_TEST(GlobalObjectInstanceProperties) {
     // environment initialization.
     global_object = env->Global();
 
-    Local<Value> value = Script::Compile(v8_str("x"))->Run();
+    Local<Value> value = CompileRun("x");
     CHECK_EQ(42, value->Int32Value());
-    value = Script::Compile(v8_str("f()"))->Run();
+    value = CompileRun("f()");
     CHECK_EQ(12, value->Int32Value());
-    value = Script::Compile(v8_str(script))->Run();
+    value = CompileRun(script);
     CHECK_EQ(1, 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();
+    Local<Value> value = CompileRun("x");
     CHECK_EQ(42, value->Int32Value());
-    value = Script::Compile(v8_str("f()"))->Run();
+    value = CompileRun("f()");
     CHECK_EQ(12, value->Int32Value());
-    value = Script::Compile(v8_str(script))->Run();
+    value = CompileRun(script);
     CHECK_EQ(1, value->Int32Value());
   }
 }
@@ -9870,14 +9140,14 @@ THREADED_TEST(CallKnownGlobalReceiver) {
     // Hold on to the global object so it can be used again in another
     // environment initialization.
     global_object = env->Global();
-    foo = Script::Compile(v8_str(script))->Run();
+    foo = CompileRun(script);
   }
 
   {
     // Create new environment reusing the global object.
     LocalContext env(NULL, instance_template, global_object);
     env->Global()->Set(v8_str("foo"), foo);
-    Script::Compile(v8_str("foo()"))->Run();
+    CompileRun("foo()");
   }
 }
 
@@ -9915,9 +9185,8 @@ static void ShadowIndexedGet(uint32_t index,
 }
 
 
-static void ShadowNamedGet(Local<String> key,
-                           const v8::PropertyCallbackInfo<v8::Value>&) {
-}
+static void ShadowNamedGet(Local<Name> key,
+                           const v8::PropertyCallbackInfo<v8::Value>&) {}
 
 
 THREADED_TEST(ShadowObject) {
@@ -9929,8 +9198,10 @@ THREADED_TEST(ShadowObject) {
   LocalContext context(NULL, global_template);
 
   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
-  t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
-  t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
+  t->InstanceTemplate()->SetHandler(
+      v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
+  t->InstanceTemplate()->SetHandler(
+      v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   Local<ObjectTemplate> instance = t->InstanceTemplate();
 
@@ -9946,19 +9217,19 @@ THREADED_TEST(ShadowObject) {
   context->Global()->Set(v8_str("__proto__"), o);
 
   Local<Value> value =
-      Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
+      CompileRun("this.propertyIsEnumerable(0)");
   CHECK(value->IsBoolean());
   CHECK(!value->BooleanValue());
 
-  value = Script::Compile(v8_str("x"))->Run();
+  value = CompileRun("x");
   CHECK_EQ(12, value->Int32Value());
 
-  value = Script::Compile(v8_str("f()"))->Run();
+  value = CompileRun("f()");
   CHECK_EQ(42, value->Int32Value());
 
-  Script::Compile(v8_str("y = 43"))->Run();
+  CompileRun("y = 43");
   CHECK_EQ(1, shadow_y_setter_call_count);
-  value = Script::Compile(v8_str("y"))->Run();
+  value = CompileRun("y");
   CHECK_EQ(1, shadow_y_getter_call_count);
   CHECK_EQ(42, value->Int32Value());
 }
@@ -10066,7 +9337,7 @@ THREADED_TEST(HiddenPrototypeIdentityHash) {
   int hash = o->GetIdentityHash();
   USE(hash);
   o->Set(v8_str("foo"), v8_num(42));
-  ASSERT_EQ(hash, o->GetIdentityHash());
+  DCHECK_EQ(hash, o->GetIdentityHash());
 }
 
 
@@ -10111,25 +9382,25 @@ THREADED_TEST(SetPrototype) {
   // object.
   Local<Value> proto = o0->Get(v8_str("__proto__"));
   CHECK(proto->IsObject());
-  CHECK_EQ(proto.As<v8::Object>(), o3);
+  CHECK(proto.As<v8::Object>()->Equals(o3));
 
   // However, Object::GetPrototype ignores hidden prototype.
   Local<Value> proto0 = o0->GetPrototype();
   CHECK(proto0->IsObject());
-  CHECK_EQ(proto0.As<v8::Object>(), o1);
+  CHECK(proto0.As<v8::Object>()->Equals(o1));
 
   Local<Value> proto1 = o1->GetPrototype();
   CHECK(proto1->IsObject());
-  CHECK_EQ(proto1.As<v8::Object>(), o2);
+  CHECK(proto1.As<v8::Object>()->Equals(o2));
 
   Local<Value> proto2 = o2->GetPrototype();
   CHECK(proto2->IsObject());
-  CHECK_EQ(proto2.As<v8::Object>(), o3);
+  CHECK(proto2.As<v8::Object>()->Equals(o3));
 }
 
 
 // Getting property names of an object with a prototype chain that
-// triggers dictionary elements in GetLocalPropertyNames() shouldn't
+// triggers dictionary elements in GetOwnPropertyNames() shouldn't
 // crash the runtime.
 THREADED_TEST(Regress91517) {
   i::FLAG_allow_natives_syntax = true;
@@ -10154,7 +9425,7 @@ THREADED_TEST(Regress91517) {
   // Force dictionary-based properties.
   i::ScopedVector<char> name_buf(1024);
   for (int i = 1; i <= 1000; i++) {
-    i::OS::SNPrintF(name_buf, "sdf%d", i);
+    i::SNPrintF(name_buf, "sdf%d", i);
     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   }
 
@@ -10168,11 +9439,11 @@ THREADED_TEST(Regress91517) {
   CHECK(o3->SetPrototype(o2));
   CHECK(o2->SetPrototype(o1));
 
-  // Call the runtime version of GetLocalPropertyNames() on the natively
+  // Call the runtime version of GetOwnPropertyNames() on the natively
   // created object through JavaScript.
   context->Global()->Set(v8_str("obj"), o4);
   // PROPERTY_ATTRIBUTES_NONE = 0
-  CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
+  CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
 
   ExpectInt32("names.length", 1006);
   ExpectTrue("names.indexOf(\"baz\") >= 0");
@@ -10217,17 +9488,18 @@ THREADED_TEST(Regress269562) {
   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   CHECK(o2->SetPrototype(o1));
 
-  v8::Local<v8::Symbol> sym = v8::Symbol::New(context->GetIsolate(), "s1");
+  v8::Local<v8::Symbol> sym =
+      v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
   o1->Set(sym, v8_num(3));
-  o1->SetHiddenValue(v8_str("h1"),
-                     v8::Integer::New(context->GetIsolate(), 2013));
+  o1->SetHiddenValue(
+      v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
 
-  // Call the runtime version of GetLocalPropertyNames() on
+  // Call the runtime version of GetOwnPropertyNames() on
   // the natively created object through JavaScript.
   context->Global()->Set(v8_str("obj"), o2);
   context->Global()->Set(v8_str("sym"), sym);
   // PROPERTY_ATTRIBUTES_NONE = 0
-  CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
+  CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
 
   ExpectInt32("names.length", 7);
   ExpectTrue("names.indexOf(\"foo\") >= 0");
@@ -10285,10 +9557,10 @@ THREADED_TEST(SetPrototypeThrows) {
   CHECK(o0->SetPrototype(o1));
   // If setting the prototype leads to the cycle, SetPrototype should
   // return false and keep VM in sane state.
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
   CHECK(!o1->SetPrototype(o0));
   CHECK(!try_catch.HasCaught());
-  ASSERT(!CcTest::i_isolate()->has_pending_exception());
+  DCHECK(!CcTest::i_isolate()->has_pending_exception());
 
   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
 }
@@ -10305,7 +9577,7 @@ THREADED_TEST(FunctionRemovePrototype) {
   context->Global()->Set(v8_str("fun"), fun);
   CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
 
-  v8::TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
   CompileRun("new fun()");
   CHECK(try_catch.HasCaught());
 
@@ -10320,14 +9592,14 @@ THREADED_TEST(GetterSetterExceptions) {
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope handle_scope(isolate);
   CompileRun(
-    "function Foo() { };"
-    "function Throw() { throw 5; };"
-    "var x = { };"
-    "x.__defineSetter__('set', Throw);"
-    "x.__defineGetter__('get', Throw);");
+      "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;
+  v8::TryCatch try_catch(isolate);
   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
   x->Get(v8_str("get"));
   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
@@ -10388,11 +9660,12 @@ THREADED_TEST(ConstructorForObject) {
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope handle_scope(isolate);
 
-  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
+  {
+    Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
     Local<Object> instance = instance_template->NewInstance();
     context->Global()->Set(v8_str("obj"), instance);
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
     Local<Value> value;
     CHECK(!try_catch.HasCaught());
 
@@ -10402,7 +9675,7 @@ THREADED_TEST(ConstructorForObject) {
     CHECK(value->IsInt32());
     CHECK_EQ(28, value->Int32Value());
 
-    Local<Value> args1[] = { v8_num(28) };
+    Local<Value> args1[] = {v8_num(28)};
     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
     CHECK(value_obj1->IsObject());
     Local<Object> object1 = Local<Object>::Cast(value_obj1);
@@ -10412,22 +9685,22 @@ THREADED_TEST(ConstructorForObject) {
     CHECK_EQ(28, value->Int32Value());
 
     // Call the Object's constructor with a String.
-    value = CompileRun(
-        "(function() { var o = new obj('tipli'); return o.a; })()");
+    value =
+        CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
     CHECK(!try_catch.HasCaught());
     CHECK(value->IsString());
-    String::Utf8Value string_value1(value->ToString());
-    CHECK_EQ("tipli", *string_value1);
+    String::Utf8Value string_value1(value->ToString(isolate));
+    CHECK_EQ(0, strcmp("tipli", *string_value1));
 
-    Local<Value> args2[] = { v8_str("tipli") };
+    Local<Value> args2[] = {v8_str("tipli")};
     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
     CHECK(value_obj2->IsObject());
     Local<Object> object2 = Local<Object>::Cast(value_obj2);
     value = object2->Get(v8_str("a"));
     CHECK(!try_catch.HasCaught());
     CHECK(value->IsString());
-    String::Utf8Value string_value2(value->ToString());
-    CHECK_EQ("tipli", *string_value2);
+    String::Utf8Value string_value2(value->ToString(isolate));
+    CHECK_EQ(0, strcmp("tipli", *string_value2));
 
     // Call the Object's constructor with a Boolean.
     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
@@ -10435,7 +9708,7 @@ THREADED_TEST(ConstructorForObject) {
     CHECK(value->IsBoolean());
     CHECK_EQ(true, value->BooleanValue());
 
-    Handle<Value> args3[] = { v8::True(isolate) };
+    Handle<Value> args3[] = {v8::True(isolate)};
     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
     CHECK(value_obj3->IsObject());
     Local<Object> object3 = Local<Object>::Cast(value_obj3);
@@ -10445,7 +9718,7 @@ THREADED_TEST(ConstructorForObject) {
     CHECK_EQ(true, value->BooleanValue());
 
     // Call the Object's constructor with undefined.
-    Handle<Value> args4[] = { v8::Undefined(isolate) };
+    Handle<Value> args4[] = {v8::Undefined(isolate)};
     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
     CHECK(value_obj4->IsObject());
     Local<Object> object4 = Local<Object>::Cast(value_obj4);
@@ -10454,7 +9727,7 @@ THREADED_TEST(ConstructorForObject) {
     CHECK(value->IsUndefined());
 
     // Call the Object's constructor with null.
-    Handle<Value> args5[] = { v8::Null(isolate) };
+    Handle<Value> args5[] = {v8::Null(isolate)};
     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
     CHECK(value_obj5->IsObject());
     Local<Object> object5 = Local<Object>::Cast(value_obj5);
@@ -10464,57 +9737,61 @@ THREADED_TEST(ConstructorForObject) {
   }
 
   // Check exception handling when there is no constructor set for the Object.
-  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
+  {
+    Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
     Local<Object> instance = instance_template->NewInstance();
     context->Global()->Set(v8_str("obj2"), instance);
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
     Local<Value> value;
     CHECK(!try_catch.HasCaught());
 
     value = CompileRun("new obj2(28)");
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value1(try_catch.Exception());
-    CHECK_EQ("TypeError: object is not a function", *exception_value1);
+    CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
     try_catch.Reset();
 
-    Local<Value> args[] = { v8_num(29) };
+    Local<Value> args[] = {v8_num(29)};
     value = instance->CallAsConstructor(1, args);
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value2(try_catch.Exception());
-    CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
+    CHECK_EQ(
+        0, strcmp("TypeError: #<Object> is not a function", *exception_value2));
     try_catch.Reset();
   }
 
   // Check the case when constructor throws exception.
-  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
+  {
+    Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
     instance_template->SetCallAsFunctionHandler(ThrowValue);
     Local<Object> instance = instance_template->NewInstance();
     context->Global()->Set(v8_str("obj3"), instance);
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
     Local<Value> value;
     CHECK(!try_catch.HasCaught());
 
     value = CompileRun("new obj3(22)");
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value1(try_catch.Exception());
-    CHECK_EQ("22", *exception_value1);
+    CHECK_EQ(0, strcmp("22", *exception_value1));
     try_catch.Reset();
 
-    Local<Value> args[] = { v8_num(23) };
+    Local<Value> args[] = {v8_num(23)};
     value = instance->CallAsConstructor(1, args);
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value2(try_catch.Exception());
-    CHECK_EQ("23", *exception_value2);
+    CHECK_EQ(0, strcmp("23", *exception_value2));
     try_catch.Reset();
   }
 
   // Check whether constructor returns with an object or non-object.
-  { Local<FunctionTemplate> function_template =
+  {
+    Local<FunctionTemplate> function_template =
         FunctionTemplate::New(isolate, FakeConstructorCallback);
     Local<Function> function = function_template->GetFunction();
     Local<Object> instance1 = function;
     context->Global()->Set(v8_str("obj4"), instance1);
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
     Local<Value> value;
     CHECK(!try_catch.HasCaught());
 
@@ -10525,7 +9802,7 @@ THREADED_TEST(ConstructorForObject) {
     CHECK(!try_catch.HasCaught());
     CHECK(value->IsObject());
 
-    Local<Value> args1[] = { v8_num(28) };
+    Local<Value> args1[] = {v8_num(28)};
     value = instance1->CallAsConstructor(1, args1);
     CHECK(!try_catch.HasCaught());
     CHECK(value->IsObject());
@@ -10543,7 +9820,7 @@ THREADED_TEST(ConstructorForObject) {
     CHECK(!try_catch.HasCaught());
     CHECK(!value->IsObject());
 
-    Local<Value> args2[] = { v8_num(28) };
+    Local<Value> args2[] = {v8_num(28)};
     value = instance2->CallAsConstructor(1, args2);
     CHECK(!try_catch.HasCaught());
     CHECK(!value->IsObject());
@@ -10560,19 +9837,19 @@ THREADED_TEST(FunctionDescriptorException) {
   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('#<Fun>') == -1) return 3;"
-    "    return 0;"
-    "  }"
-    "  return 4;"
-    "}"
-    "test();");
+      "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('#<Fun>') == -1) return 3;"
+      "    return 0;"
+      "  }"
+      "  return 4;"
+      "}"
+      "test();");
   CHECK_EQ(0, value->Int32Value());
 }
 
@@ -10582,29 +9859,29 @@ THREADED_TEST(EvalAliasedDynamic) {
   v8::HandleScope scope(current->GetIsolate());
 
   // 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);"));
+  Local<Script> script = v8_compile(
+      "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'); }"
-                           "}"
-                           "result4 = f(this)"));
+  v8::TryCatch try_catch(current->GetIsolate());
+  script = v8_compile(
+      "function f(x) { "
+      "  var bar = 2;"
+      "  with (x) { return eval('bar'); }"
+      "}"
+      "result4 = f(this)");
   script->Run();
   CHECK(!try_catch.HasCaught());
   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
@@ -10626,8 +9903,7 @@ THREADED_TEST(CrossEval) {
   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')"));
+  Local<Script> script = v8_compile("other.eval('var foo = 1234')");
   script->Run();
   Local<Value> foo = other->Global()->Get(v8_str("foo"));
   CHECK_EQ(1234, foo->Int32Value());
@@ -10635,28 +9911,26 @@ THREADED_TEST(CrossEval) {
 
   // Check that writing to non-existing properties introduces them in
   // the other context.
-  script =
-      Script::Compile(v8_str("other.eval('na = 1234')"));
+  script = v8_compile("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');"));
+  v8::TryCatch try_catch(CcTest::isolate());
+  script = v8_compile("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');"
-                             "})();"));
+  script = v8_compile(
+      "(function() { "
+      "  var baz = 87;"
+      "  return other.eval('baz');"
+      "})();");
   result = script->Run();
   CHECK(try_catch.HasCaught());
   try_catch.Reset();
@@ -10664,38 +9938,35 @@ THREADED_TEST(CrossEval) {
   // 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')"));
+  script = v8_compile("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')"));
+  script = v8_compile("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')}"));
+  script = v8_compile("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')"));
+  script = v8_compile("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.
+// its global proxy works.
 THREADED_TEST(EvalInDetachedGlobal) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
@@ -10705,12 +9976,12 @@ THREADED_TEST(EvalInDetachedGlobal) {
 
   // Set up 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); }"
-                 "})()");
+  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
@@ -10721,10 +9992,9 @@ THREADED_TEST(EvalInDetachedGlobal) {
   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
   CHECK_EQ(42, x_value->Int32Value());
   context0->DetachGlobal();
-  v8::TryCatch catcher;
+  v8::TryCatch catcher(isolate);
   x_value = CompileRun("fun('x')");
-  CHECK(x_value.IsEmpty());
-  CHECK(catcher.HasCaught());
+  CHECK_EQ(42, x_value->Int32Value());
   context1->Exit();
 }
 
@@ -10742,8 +10012,7 @@ THREADED_TEST(CrossLazyLoad) {
   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<Script> script = v8_compile("other.eval('new Date(42)')");
   Local<Value> value = script->Run();
   CHECK_EQ(42.0, value->NumberValue());
 }
@@ -10775,12 +10044,13 @@ THREADED_TEST(CallAsFunction) {
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope scope(isolate);
 
-  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
+  {
+    Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
     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;
+    v8::TryCatch try_catch(isolate);
     Local<Value> value;
     CHECK(!try_catch.HasCaught());
 
@@ -10797,8 +10067,9 @@ THREADED_TEST(CallAsFunction) {
     CHECK(!try_catch.HasCaught());
     CHECK_EQ(45, value->Int32Value());
 
-    value = CompileRun("obj.call = Function.prototype.call;"
-                       "obj.call(null, 87)");
+    value = CompileRun(
+        "obj.call = Function.prototype.call;"
+        "obj.call(null, 87)");
     CHECK(!try_catch.HasCaught());
     CHECK_EQ(87, value->Int32Value());
 
@@ -10822,18 +10093,19 @@ THREADED_TEST(CallAsFunction) {
 
     // Check that the call-as-function handler can be called through
     // the API.
-    v8::Handle<Value> args[] = { v8_num(28) };
+    v8::Handle<Value> args[] = {v8_num(28)};
     value = instance->CallAsFunction(instance, 1, args);
     CHECK(!try_catch.HasCaught());
     CHECK_EQ(28, value->Int32Value());
   }
 
-  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
+  {
+    Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
     USE(instance_template);
     Local<v8::Object> instance = t->GetFunction()->NewInstance();
     context->Global()->Set(v8_str("obj2"), instance);
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
     Local<Value> value;
     CHECK(!try_catch.HasCaught());
 
@@ -10843,27 +10115,28 @@ THREADED_TEST(CallAsFunction) {
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value1(try_catch.Exception());
     // TODO(verwaest): Better message
-    CHECK_EQ("TypeError: object is not a function",
-             *exception_value1);
+    CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
     try_catch.Reset();
 
     // Call an object without call-as-function handler through the API
     value = CompileRun("obj2(28)");
-    v8::Handle<Value> args[] = { v8_num(28) };
+    v8::Handle<Value> args[] = {v8_num(28)};
     value = instance->CallAsFunction(instance, 1, args);
     CHECK(value.IsEmpty());
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value2(try_catch.Exception());
-    CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
+    CHECK_EQ(0, strcmp("TypeError: [object Object] is not a function",
+                       *exception_value2));
     try_catch.Reset();
   }
 
-  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
+  {
+    Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
     instance_template->SetCallAsFunctionHandler(ThrowValue);
     Local<v8::Object> instance = t->GetFunction()->NewInstance();
     context->Global()->Set(v8_str("obj3"), instance);
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
     Local<Value> value;
     CHECK(!try_catch.HasCaught());
 
@@ -10871,18 +10144,19 @@ THREADED_TEST(CallAsFunction) {
     value = CompileRun("obj3(22)");
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value1(try_catch.Exception());
-    CHECK_EQ("22", *exception_value1);
+    CHECK_EQ(0, strcmp("22", *exception_value1));
     try_catch.Reset();
 
-    v8::Handle<Value> args[] = { v8_num(23) };
+    v8::Handle<Value> args[] = {v8_num(23)};
     value = instance->CallAsFunction(instance, 1, args);
     CHECK(try_catch.HasCaught());
     String::Utf8Value exception_value2(try_catch.Exception());
-    CHECK_EQ("23", *exception_value2);
+    CHECK_EQ(0, strcmp("23", *exception_value2));
     try_catch.Reset();
   }
 
-  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
+  {
+    Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
     instance_template->SetCallAsFunctionHandler(ReturnThis);
     Local<v8::Object> instance = t->GetFunction()->NewInstance();
@@ -10890,43 +10164,37 @@ THREADED_TEST(CallAsFunction) {
     Local<v8::Value> a1 =
         instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
     CHECK(a1->StrictEquals(instance));
-    Local<v8::Value> a2 =
-        instance->CallAsFunction(v8::Null(isolate), 0, NULL);
+    Local<v8::Value> a2 = instance->CallAsFunction(v8::Null(isolate), 0, NULL);
     CHECK(a2->StrictEquals(instance));
-    Local<v8::Value> a3 =
-        instance->CallAsFunction(v8_num(42), 0, NULL);
+    Local<v8::Value> a3 = instance->CallAsFunction(v8_num(42), 0, NULL);
     CHECK(a3->StrictEquals(instance));
-    Local<v8::Value> a4 =
-        instance->CallAsFunction(v8_str("hello"), 0, NULL);
+    Local<v8::Value> a4 = instance->CallAsFunction(v8_str("hello"), 0, NULL);
     CHECK(a4->StrictEquals(instance));
-    Local<v8::Value> a5 =
-        instance->CallAsFunction(v8::True(isolate), 0, NULL);
+    Local<v8::Value> a5 = instance->CallAsFunction(v8::True(isolate), 0, NULL);
     CHECK(a5->StrictEquals(instance));
   }
 
-  { CompileRun(
-      "function ReturnThisSloppy() {"
-      "  return this;"
-      "}"
-      "function ReturnThisStrict() {"
-      "  'use strict';"
-      "  return this;"
-      "}");
-    Local<Function> ReturnThisSloppy =
-        Local<Function>::Cast(
-            context->Global()->Get(v8_str("ReturnThisSloppy")));
-    Local<Function> ReturnThisStrict =
-        Local<Function>::Cast(
-            context->Global()->Get(v8_str("ReturnThisStrict")));
-
+  {
+    CompileRun(
+        "function ReturnThisSloppy() {"
+        "  return this;"
+        "}"
+        "function ReturnThisStrict() {"
+        "  'use strict';"
+        "  return this;"
+        "}");
+    Local<Function> ReturnThisSloppy = Local<Function>::Cast(
+        context->Global()->Get(v8_str("ReturnThisSloppy")));
+    Local<Function> ReturnThisStrict = Local<Function>::Cast(
+        context->Global()->Get(v8_str("ReturnThisStrict")));
+
     Local<v8::Value> a1 =
         ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
     CHECK(a1->StrictEquals(context->Global()));
     Local<v8::Value> a2 =
         ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
     CHECK(a2->StrictEquals(context->Global()));
-    Local<v8::Value> a3 =
-        ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
+    Local<v8::Value> a3 = ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
     CHECK(a3->IsNumberObject());
     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
     Local<v8::Value> a4 =
@@ -10944,8 +10212,7 @@ THREADED_TEST(CallAsFunction) {
     Local<v8::Value> a7 =
         ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
     CHECK(a7->IsNull());
-    Local<v8::Value> a8 =
-        ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
+    Local<v8::Value> a8 = ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
     CHECK(a8->StrictEquals(v8_num(42)));
     Local<v8::Value> a9 =
         ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
@@ -10963,37 +10230,41 @@ THREADED_TEST(CallableObject) {
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope scope(isolate);
 
-  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
+  {
+    Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
     instance_template->SetCallAsFunctionHandler(call_as_function);
     Local<Object> instance = instance_template->NewInstance();
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
 
     CHECK(instance->IsCallable());
     CHECK(!try_catch.HasCaught());
   }
 
-  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
+  {
+    Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
     Local<Object> instance = instance_template->NewInstance();
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
 
     CHECK(!instance->IsCallable());
     CHECK(!try_catch.HasCaught());
   }
 
-  { Local<FunctionTemplate> function_template =
+  {
+    Local<FunctionTemplate> function_template =
         FunctionTemplate::New(isolate, call_as_function);
     Local<Function> function = function_template->GetFunction();
     Local<Object> instance = function;
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
 
     CHECK(instance->IsCallable());
     CHECK(!try_catch.HasCaught());
   }
 
-  { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
+  {
+    Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
     Local<Function> function = function_template->GetFunction();
     Local<Object> instance = function;
-    v8::TryCatch try_catch;
+    v8::TryCatch try_catch(isolate);
 
     CHECK(instance->IsCallable());
     CHECK(!try_catch.HasCaught());
@@ -11042,10971 +10313,11601 @@ THREADED_TEST(HandleIteration) {
 }
 
 
-static void InterceptorHasOwnPropertyGetter(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
+static void InterceptorCallICFastApi(
+    Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   ApiTestFuzzer::Fuzz();
+  CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
+  int* call_count =
+      reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
+  ++(*call_count);
+  if ((*call_count) % 20 == 0) {
+    CcTest::heap()->CollectAllGarbage();
+  }
 }
 
-
-THREADED_TEST(InterceptorHasOwnProperty) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
-  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 void FastApiCallback_TrivialSignature(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
+  CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
+  v8::Isolate* isolate = CcTest::isolate();
+  CHECK_EQ(isolate, args.GetIsolate());
+  CHECK(args.This()->Equals(args.Holder()));
+  CHECK(args.Data()->Equals(v8_str("method_data")));
+  args.GetReturnValue().Set(args[0]->Int32Value() + 1);
 }
 
-
-static void InterceptorHasOwnPropertyGetterGC(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
+static void FastApiCallback_SimpleSignature(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+  CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
+  v8::Isolate* isolate = CcTest::isolate();
+  CHECK_EQ(isolate, args.GetIsolate());
+  CHECK(args.This()->GetPrototype()->Equals(args.Holder()));
+  CHECK(args.Data()->Equals(v8_str("method_data")));
+  // Note, we're using HasRealNamedProperty instead of Has to avoid
+  // invoking the interceptor again.
+  CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
+  args.GetReturnValue().Set(args[0]->Int32Value() + 1);
 }
 
 
-THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
-  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.
+// Helper to maximize the odds of object moving.
+static void GenerateSomeGarbage() {
   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 garbage;"
+      "for (var i = 0; i < 1000; i++) {"
+      "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
       "}"
-      "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 void (*NamedPropertyGetter)(
-    Local<String> property,
-    const v8::PropertyCallbackInfo<v8::Value>& info);
-
-
-static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
-                                   const char* source,
-                                   int expected) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
-  LocalContext context;
-  context->Global()->Set(v8_str("o"), templ->NewInstance());
-  v8::Handle<Value> value = CompileRun(source);
-  CHECK_EQ(expected, value->Int32Value());
+      "garbage = undefined;");
 }
 
 
-static void InterceptorLoadICGetter(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  v8::Isolate* isolate = CcTest::isolate();
-  CHECK_EQ(isolate, info.GetIsolate());
-  CHECK_EQ(v8_str("data"), info.Data());
-  CHECK_EQ(v8_str("x"), name);
-  info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
+void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  static int count = 0;
+  if (count++ % 3 == 0) {
+    CcTest::heap()->CollectAllGarbage();
+        // This should move the stub
+    GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
+  }
 }
 
 
-// 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);
+THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::ObjectTemplate> nativeobject_templ =
+      v8::ObjectTemplate::New(isolate);
+  nativeobject_templ->Set(isolate, "callback",
+                          v8::FunctionTemplate::New(isolate,
+                                                    DirectApiCallback));
+  v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
+  context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
+  // call the api function multiple times to ensure direct call stub creation.
+  CompileRun(
+        "function f() {"
+        "  for (var i = 1; i <= 30; i++) {"
+        "    nativeobject.callback();"
+        "  }"
+        "}"
+        "f();");
 }
 
 
-// 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 void InterceptorLoadXICGetter(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  info.GetReturnValue().Set(
-      v8_str("x")->Equals(name) ?
-          v8::Handle<v8::Value>(v8::Integer::New(info.GetIsolate(), 42)) :
-          v8::Handle<v8::Value>());
+void ThrowingDirectApiCallback(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  args.GetIsolate()->ThrowException(v8_str("g"));
 }
 
 
-THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
-  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
-    "var result = 0;"
-    "o.y = 239;"
-    "for (var i = 0; i < 1000; i++) {"
-    "  result = o.y;"
-    "}",
-    239);
+THREADED_TEST(CallICFastApi_DirectCall_Throw) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::ObjectTemplate> nativeobject_templ =
+      v8::ObjectTemplate::New(isolate);
+  nativeobject_templ->Set(isolate, "callback",
+                          v8::FunctionTemplate::New(isolate,
+                                                    ThrowingDirectApiCallback));
+  v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
+  context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
+  // call the api function multiple times to ensure direct call stub creation.
+  v8::Handle<Value> result = CompileRun(
+      "var result = '';"
+      "function f() {"
+      "  for (var i = 1; i <= 5; i++) {"
+      "    try { nativeobject.callback(); } catch (e) { result += e; }"
+      "  }"
+      "}"
+      "f(); result;");
+  CHECK(v8_str("ggggg")->Equals(result));
 }
 
 
-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);
-}
+static int p_getter_count_3;
 
 
-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);
+static Handle<Value> DoDirectGetter() {
+  if (++p_getter_count_3 % 3 == 0) {
+    CcTest::heap()->CollectAllGarbage();
+    GenerateSomeGarbage();
+  }
+  return v8_str("Direct Getter Result");
 }
 
 
-THREADED_TEST(InterceptorLoadICUndefined) {
-  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
-    "var result = 0;"
-    "for (var i = 0; i < 1000; i++) {"
-    "  result = (o.y == undefined) ? 239 : 42;"
-    "}",
-    239);
+static void DirectGetterCallback(
+    Local<String> name,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
+  info.GetReturnValue().Set(DoDirectGetter());
 }
 
 
-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);
+template<typename Accessor>
+static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
+  obj->SetAccessor(v8_str("p1"), accessor);
+  context->Global()->Set(v8_str("o1"), obj->NewInstance());
+  p_getter_count_3 = 0;
+  v8::Handle<v8::Value> result = CompileRun(
+      "function f() {"
+      "  for (var i = 0; i < 30; i++) o1.p1;"
+      "  return o1.p1"
+      "}"
+      "f();");
+  CHECK(v8_str("Direct Getter Result")->Equals(result));
+  CHECK_EQ(31, p_getter_count_3);
 }
 
 
-// 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);
+THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
+  LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
 }
 
 
-static int interceptor_load_not_handled_calls = 0;
-static void InterceptorLoadNotHandled(
+void ThrowingDirectGetterCallback(
     Local<String> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ++interceptor_load_not_handled_calls;
-}
-
-
-// Test how post-interceptor lookups are done in the non-cacheable
-// case: the interceptor should not be invoked during this lookup.
-THREADED_TEST(InterceptorLoadICPostInterceptor) {
-  interceptor_load_not_handled_calls = 0;
-  CheckInterceptorLoadIC(InterceptorLoadNotHandled,
-    "receiver = new Object();"
-    "receiver.__proto__ = o;"
-    "proto = new Object();"
-    "/* Make proto a slow-case object. */"
-    "for (var i = 0; i < 1000; i++) {"
-    "  proto[\"xxxxxxxx\" + i] = [];"
-    "}"
-    "proto.x = 17;"
-    "o.__proto__ = proto;"
-    "var result = 0;"
-    "for (var i = 0; i < 1000; i++) {"
-    "  result += receiver.x;"
-    "}"
-    "result;",
-    17 * 1000);
-  CHECK_EQ(1000, interceptor_load_not_handled_calls);
-}
-
-
-// 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);
+  info.GetIsolate()->ThrowException(v8_str("g"));
 }
 
 
-static void SetOnThis(Local<String> name,
-                      Local<Value> value,
-                      const v8::PropertyCallbackInfo<void>& info) {
-  info.This()->ForceSet(name, value);
+THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
+  obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
+  context->Global()->Set(v8_str("o1"), obj->NewInstance());
+  v8::Handle<Value> result = CompileRun(
+      "var result = '';"
+      "for (var i = 0; i < 5; i++) {"
+      "    try { o1.p1; } catch (e) { result += e; }"
+      "}"
+      "result;");
+  CHECK(v8_str("ggggg")->Equals(result));
 }
 
 
-THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
+THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
+  int interceptor_call_count = 0;
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
-  templ->SetAccessor(v8_str("y"), Return239Callback);
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ =
+      v8::FunctionTemplate::New(isolate,
+                                FastApiCallback_TrivialSignature,
+                                v8_str("method_data"),
+                                v8::Handle<v8::Signature>());
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+  templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
+      v8::External::New(isolate, &interceptor_call_count)));
   LocalContext context;
-  context->Global()->Set(v8_str("o"), templ->NewInstance());
-
-  // Check the case when receiver and interceptor's holder
-  // are the same objects.
-  v8::Handle<Value> value = CompileRun(
-      "var result = 0;"
-      "for (var i = 0; i < 7; i++) {"
-      "  result = o.y;"
-      "}");
-  CHECK_EQ(239, value->Int32Value());
-
-  // Check the case when interceptor's holder is in proto chain
-  // of receiver.
-  value = CompileRun(
-      "r = { __proto__: o };"
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  CompileRun(
       "var result = 0;"
-      "for (var i = 0; i < 7; i++) {"
-      "  result = r.y;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = o.method(41);"
       "}");
-  CHECK_EQ(239, value->Int32Value());
+  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+  CHECK_EQ(100, interceptor_call_count);
 }
 
 
-THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
+THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
+  int interceptor_call_count = 0;
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
-  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
-  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
-  templ_p->SetAccessor(v8_str("y"), Return239Callback);
-
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
+      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
+      v8::Signature::New(isolate, fun_templ));
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  fun_templ->SetHiddenPrototype(true);
+  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+  templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
+      v8::External::New(isolate, &interceptor_call_count)));
   LocalContext context;
-  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
-  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
-
-  // Check the case when receiver and interceptor's holder
-  // are the same objects.
-  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());
-
-  // Check the case when interceptor's holder is in proto chain
-  // of receiver.
-  value = CompileRun(
-      "r = { __proto__: o };"
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  CompileRun(
+      "o.foo = 17;"
+      "var receiver = {};"
+      "receiver.__proto__ = o;"
       "var result = 0;"
-      "for (var i = 0; i < 7; i++) {"
-      "  result = r.x + r.y;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = receiver.method(41);"
       "}");
-  CHECK_EQ(239 + 42, value->Int32Value());
+  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+  CHECK_EQ(100, interceptor_call_count);
 }
 
 
-THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
+THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
+  int interceptor_call_count = 0;
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
-  templ->SetAccessor(v8_str("y"), Return239Callback);
-
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
+      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
+      v8::Signature::New(isolate, fun_templ));
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  fun_templ->SetHiddenPrototype(true);
+  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+  templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
+      v8::External::New(isolate, &interceptor_call_count)));
   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::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
-  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
-  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
-  templ_p->SetAccessor(v8_str("y"), Return239Callback);
-
-  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());
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  CompileRun(
+      "o.foo = 17;"
+      "var receiver = {};"
+      "receiver.__proto__ = o;"
+      "var result = 0;"
+      "var saved_result = 0;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = receiver.method(41);"
+      "  if (i == 50) {"
+      "    saved_result = result;"
+      "    receiver = {method: function(x) { return x - 1 }};"
+      "  }"
+      "}");
+  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
+  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+  CHECK_GE(interceptor_call_count, 50);
 }
 
 
-// Test the case when we stored callback into
-// a stub, but it got invalidated later on.
-THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
+THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
+  int interceptor_call_count = 0;
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
-  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
-  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
-  templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
-
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
+      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
+      v8::Signature::New(isolate, fun_templ));
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  fun_templ->SetHiddenPrototype(true);
+  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+  templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
+      v8::External::New(isolate, &interceptor_call_count)));
   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());
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  CompileRun(
+      "o.foo = 17;"
+      "var receiver = {};"
+      "receiver.__proto__ = o;"
+      "var result = 0;"
+      "var saved_result = 0;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = receiver.method(41);"
+      "  if (i == 50) {"
+      "    saved_result = result;"
+      "    o.method = function(x) { return x - 1 };"
+      "  }"
+      "}");
+  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
+  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+  CHECK_GE(interceptor_call_count, 50);
 }
 
 
-// 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) {
+THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
+  int interceptor_call_count = 0;
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
-  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
-  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
-  templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
-
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
+      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
+      v8::Signature::New(isolate, fun_templ));
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  fun_templ->SetHiddenPrototype(true);
+  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+  templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
+      v8::External::New(isolate, &interceptor_call_count)));
   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 void InterceptorLoadICGetter0(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  CHECK(v8_str("x")->Equals(name));
-  info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
-}
-
-
-THREADED_TEST(InterceptorReturningZero) {
-  CheckInterceptorLoadIC(InterceptorLoadICGetter0,
-     "o.x == undefined ? 1 : 0",
-     0);
-}
-
-
-static void InterceptorStoreICSetter(
-    Local<String> key,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CHECK(v8_str("x")->Equals(key));
-  CHECK_EQ(42, value->Int32Value());
-  info.GetReturnValue().Set(value);
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  v8::TryCatch try_catch(isolate);
+  CompileRun(
+      "o.foo = 17;"
+      "var receiver = {};"
+      "receiver.__proto__ = o;"
+      "var result = 0;"
+      "var saved_result = 0;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = receiver.method(41);"
+      "  if (i == 50) {"
+      "    saved_result = result;"
+      "    receiver = 333;"
+      "  }"
+      "}");
+  CHECK(try_catch.HasCaught());
+  // TODO(verwaest): Adjust message.
+  CHECK(v8_str("TypeError: receiver.method is not a function")
+            ->Equals(try_catch.Exception()->ToString(isolate)));
+  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+  CHECK_GE(interceptor_call_count, 50);
 }
 
 
-// This test should hit the store IC for the interceptor case.
-THREADED_TEST(InterceptorStoreIC) {
+THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
+  int interceptor_call_count = 0;
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
-                                 InterceptorStoreICSetter,
-                                 0, 0, 0, v8_str("data"));
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
+      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
+      v8::Signature::New(isolate, fun_templ));
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  fun_templ->SetHiddenPrototype(true);
+  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+  templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
+      v8::External::New(isolate, &interceptor_call_count)));
   LocalContext context;
-  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  v8::TryCatch try_catch(isolate);
   CompileRun(
-      "for (var i = 0; i < 1000; i++) {"
-      "  o.x = 42;"
+      "o.foo = 17;"
+      "var receiver = {};"
+      "receiver.__proto__ = o;"
+      "var result = 0;"
+      "var saved_result = 0;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = receiver.method(41);"
+      "  if (i == 50) {"
+      "    saved_result = result;"
+      "    receiver = {method: receiver.method};"
+      "  }"
       "}");
+  CHECK(try_catch.HasCaught());
+  CHECK(v8_str("TypeError: Illegal invocation")
+            ->Equals(try_catch.Exception()->ToString(isolate)));
+  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+  CHECK_GE(interceptor_call_count, 50);
 }
 
 
-THREADED_TEST(InterceptorStoreICWithNoSetter) {
+THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ =
+      v8::FunctionTemplate::New(isolate,
+                                FastApiCallback_TrivialSignature,
+                                v8_str("method_data"),
+                                v8::Handle<v8::Signature>());
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
+  USE(templ);
   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 void InterceptorCallICGetter(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  CHECK(v8_str("x")->Equals(name));
-  info.GetReturnValue().Set(call_ic_function);
-}
-
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  CompileRun(
+      "var result = 0;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = o.method(41);"
+      "}");
 
-// This test should hit the call IC for the interceptor case.
-THREADED_TEST(InterceptorCallIC) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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());
+  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
 }
 
 
-// This test checks that if interceptor doesn't provide
-// a value, we can fetch regular value.
-THREADED_TEST(InterceptorCallICSeesOthers) {
+THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(NoBlockGetterX);
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
+      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
+      v8::Signature::New(isolate, fun_templ));
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  fun_templ->SetHiddenPrototype(true);
+  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
+  CHECK(!templ.IsEmpty());
   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());
-}
-
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  CompileRun(
+      "o.foo = 17;"
+      "var receiver = {};"
+      "receiver.__proto__ = o;"
+      "var result = 0;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = receiver.method(41);"
+      "}");
 
-static v8::Handle<Value> call_ic_function4;
-static void InterceptorCallICGetter4(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  CHECK(v8_str("x")->Equals(name));
-  info.GetReturnValue().Set(call_ic_function4);
+  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
 }
 
 
-// This test checks that if interceptor provides a function,
-// even if we cached shadowed variant, interceptor's function
-// is invoked
-THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
+THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
+      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
+      v8::Signature::New(isolate, fun_templ));
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  fun_templ->SetHiddenPrototype(true);
+  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
+  CHECK(!templ.IsEmpty());
   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(
-    "Object.getPrototypeOf(o).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());
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  CompileRun(
+      "o.foo = 17;"
+      "var receiver = {};"
+      "receiver.__proto__ = o;"
+      "var result = 0;"
+      "var saved_result = 0;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = receiver.method(41);"
+      "  if (i == 50) {"
+      "    saved_result = result;"
+      "    receiver = {method: function(x) { return x - 1 }};"
+      "  }"
+      "}");
+  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
+  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
 }
 
 
-// Test the case when we stored cacheable lookup into
-// a stub, but it got invalidated later on
-THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
+THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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());
-}
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
+      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
+      v8::Signature::New(isolate, fun_templ));
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  fun_templ->SetHiddenPrototype(true);
+  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
+  CHECK(!templ.IsEmpty());
+  LocalContext context;
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  v8::TryCatch try_catch(isolate);
+  CompileRun(
+      "o.foo = 17;"
+      "var receiver = {};"
+      "receiver.__proto__ = o;"
+      "var result = 0;"
+      "var saved_result = 0;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = receiver.method(41);"
+      "  if (i == 50) {"
+      "    saved_result = result;"
+      "    receiver = 333;"
+      "  }"
+      "}");
+  CHECK(try_catch.HasCaught());
+  // TODO(verwaest): Adjust message.
+  CHECK(v8_str("TypeError: receiver.method is not a function")
+            ->Equals(try_catch.Exception()->ToString(isolate)));
+  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+}
 
 
-// This test checks that if interceptor doesn't provide a function,
-// cached constant function is used
-THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
+THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(NoBlockGetterX);
+  v8::Handle<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
+      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
+      v8::Signature::New(isolate, fun_templ));
+  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+  proto_templ->Set(v8_str("method"), method_templ);
+  fun_templ->SetHiddenPrototype(true);
+  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
+  CHECK(!templ.IsEmpty());
   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());
+  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+  GenerateSomeGarbage();
+  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  v8::TryCatch try_catch(isolate);
+  CompileRun(
+      "o.foo = 17;"
+      "var receiver = {};"
+      "receiver.__proto__ = o;"
+      "var result = 0;"
+      "var saved_result = 0;"
+      "for (var i = 0; i < 100; i++) {"
+      "  result = receiver.method(41);"
+      "  if (i == 50) {"
+      "    saved_result = result;"
+      "    receiver = Object.create(receiver);"
+      "  }"
+      "}");
+  CHECK(try_catch.HasCaught());
+  CHECK(v8_str("TypeError: Illegal invocation")
+            ->Equals(try_catch.Exception()->ToString(isolate)));
+  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
 }
 
 
-static v8::Handle<Value> call_ic_function5;
-static void InterceptorCallICGetter5(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
+static void ThrowingGetter(Local<String> name,
+                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   ApiTestFuzzer::Fuzz();
-  if (v8_str("x")->Equals(name))
-    info.GetReturnValue().Set(call_ic_function5);
+  info.GetIsolate()->ThrowException(Handle<Value>());
+  info.GetReturnValue().SetUndefined();
 }
 
 
-// This test checks that if interceptor provides a function,
-// even if we cached constant function, interceptor's function
-// is invoked
-THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
+THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   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());
-}
-
-
-static v8::Handle<Value> call_ic_function6;
-static void InterceptorCallICGetter6(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (v8_str("x")->Equals(name))
-    info.GetReturnValue().Set(call_ic_function6);
-}
+  HandleScope scope(context->GetIsolate());
 
+  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
+  Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
+  instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
 
-// Same test as above, except the code is wrapped in a function
-// to test the optimized compiler.
-THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
-  i::FLAG_allow_natives_syntax = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
-  LocalContext context;
-  context->Global()->Set(v8_str("o"), templ->NewInstance());
-  call_ic_function6 =
-      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;"
-    "function test() {"
-    "  var result = 0;"
-    "  for (var i = 0; i < 1000; i++) {"
-    "    result = o.x(42);"
-    "  }"
-    "  return result;"
-    "};"
-    "test();"
-    "test();"
-    "test();"
-    "%OptimizeFunctionOnNextCall(test);"
-    "test()");
-  CHECK_EQ(41, value->Int32Value());
-}
+  Local<Object> instance = templ->GetFunction()->NewInstance();
 
+  Local<Object> another = Object::New(context->GetIsolate());
+  another->SetPrototype(instance);
 
-// Test the case when we stored constant function into
-// a stub, but it got invalidated later on
-THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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());
-}
+  Local<Object> with_js_getter = CompileRun(
+      "o = {};\n"
+      "o.__defineGetter__('f', function() { throw undefined; });\n"
+      "o\n").As<Object>();
+  CHECK(!with_js_getter.IsEmpty());
 
+  TryCatch try_catch(context->GetIsolate());
 
-// 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::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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());
-}
+  Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  CHECK(result.IsEmpty());
 
+  Maybe<PropertyAttribute> attr =
+      instance->GetRealNamedPropertyAttributes(v8_str("f"));
+  CHECK(!try_catch.HasCaught());
+  CHECK(Just(None) == attr);
 
-// Test the case when actual function to call sits on global object.
-THREADED_TEST(InterceptorCallICCachedFromGlobal) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
-  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
+  result = another->GetRealNamedProperty(v8_str("f"));
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  CHECK(result.IsEmpty());
 
-  LocalContext context;
-  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
-
-  v8::Handle<Value> value = CompileRun(
-    "try {"
-    "  o.__proto__ = this;"
-    "  for (var i = 0; i < 10; i++) {"
-    "    var v = o.parseFloat('239');"
-    "    if (v != 239) throw v;"
-      // Now it should be ICed and keep a reference to parseFloat.
-    "  }"
-    "  var result = 0;"
-    "  for (var i = 0; i < 10; i++) {"
-    "    result += o.parseFloat('239');"
-    "  }"
-    "  result"
-    "} catch(e) {"
-    "  e"
-    "};");
-  CHECK_EQ(239 * 10, value->Int32Value());
-}
+  attr = another->GetRealNamedPropertyAttributes(v8_str("f"));
+  CHECK(!try_catch.HasCaught());
+  CHECK(Just(None) == attr);
 
-static void InterceptorCallICFastApi(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
-  int* call_count =
-      reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
-  ++(*call_count);
-  if ((*call_count) % 20 == 0) {
-    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  }
-}
+  result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  CHECK(result.IsEmpty());
 
-static void FastApiCallback_TrivialSignature(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-  CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
-  v8::Isolate* isolate = CcTest::isolate();
-  CHECK_EQ(isolate, args.GetIsolate());
-  CHECK_EQ(args.This(), args.Holder());
-  CHECK(args.Data()->Equals(v8_str("method_data")));
-  args.GetReturnValue().Set(args[0]->Int32Value() + 1);
+  attr = another->GetRealNamedPropertyAttributesInPrototypeChain(v8_str("f"));
+  CHECK(!try_catch.HasCaught());
+  CHECK(Just(None) == attr);
+
+  result = another->Get(v8_str("f"));
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  CHECK(result.IsEmpty());
+
+  result = with_js_getter->GetRealNamedProperty(v8_str("f"));
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  CHECK(result.IsEmpty());
+
+  attr = with_js_getter->GetRealNamedPropertyAttributes(v8_str("f"));
+  CHECK(!try_catch.HasCaught());
+  CHECK(Just(None) == attr);
+
+  result = with_js_getter->Get(v8_str("f"));
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  CHECK(result.IsEmpty());
 }
 
-static void FastApiCallback_SimpleSignature(
+
+static void ThrowingCallbackWithTryCatch(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-  CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
-  v8::Isolate* isolate = CcTest::isolate();
-  CHECK_EQ(isolate, args.GetIsolate());
-  CHECK_EQ(args.This()->GetPrototype(), args.Holder());
-  CHECK(args.Data()->Equals(v8_str("method_data")));
-  // Note, we're using HasRealNamedProperty instead of Has to avoid
-  // invoking the interceptor again.
-  CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
-  args.GetReturnValue().Set(args[0]->Int32Value() + 1);
+  TryCatch try_catch(args.GetIsolate());
+  // Verboseness is important: it triggers message delivery which can call into
+  // external code.
+  try_catch.SetVerbose(true);
+  CompileRun("throw 'from JS';");
+  CHECK(try_catch.HasCaught());
+  CHECK(!CcTest::i_isolate()->has_pending_exception());
+  CHECK(!CcTest::i_isolate()->has_scheduled_exception());
 }
 
 
-// Helper to maximize the odds of object moving.
-static void GenerateSomeGarbage() {
-  CompileRun(
-      "var garbage;"
-      "for (var i = 0; i < 1000; i++) {"
-      "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
-      "}"
-      "garbage = undefined;");
+static int call_depth;
+
+
+static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
+  TryCatch try_catch(CcTest::isolate());
 }
 
 
-void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  static int count = 0;
-  if (count++ % 3 == 0) {
-    CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
-        // This should move the stub
-    GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
-  }
+static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
+  if (--call_depth) CompileRun("throw 'ThrowInJS';");
 }
 
 
-THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> nativeobject_templ =
-      v8::ObjectTemplate::New(isolate);
-  nativeobject_templ->Set(isolate, "callback",
-                          v8::FunctionTemplate::New(isolate,
-                                                    DirectApiCallback));
-  v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
-  context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
-  // call the api function multiple times to ensure direct call stub creation.
-  CompileRun(
-        "function f() {"
-        "  for (var i = 1; i <= 30; i++) {"
-        "    nativeobject.callback();"
-        "  }"
-        "}"
-        "f();");
+static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
+  if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
 }
 
 
-void ThrowingDirectApiCallback(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  args.GetIsolate()->ThrowException(v8_str("g"));
+static void WebKitLike(Handle<Message> message, Handle<Value> data) {
+  Handle<String> errorMessageString = message->Get();
+  CHECK(!errorMessageString.IsEmpty());
+  message->GetStackTrace();
+  message->GetScriptOrigin().ResourceName();
 }
 
 
-THREADED_TEST(CallICFastApi_DirectCall_Throw) {
+THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> nativeobject_templ =
-      v8::ObjectTemplate::New(isolate);
-  nativeobject_templ->Set(isolate, "callback",
-                          v8::FunctionTemplate::New(isolate,
-                                                    ThrowingDirectApiCallback));
-  v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
-  context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
-  // call the api function multiple times to ensure direct call stub creation.
-  v8::Handle<Value> result = CompileRun(
-      "var result = '';"
-      "function f() {"
-      "  for (var i = 1; i <= 5; i++) {"
-      "    try { nativeobject.callback(); } catch (e) { result += e; }"
-      "  }"
-      "}"
-      "f(); result;");
-  CHECK_EQ(v8_str("ggggg"), result);
-}
+  HandleScope scope(isolate);
 
+  Local<Function> func =
+      FunctionTemplate::New(isolate,
+                            ThrowingCallbackWithTryCatch)->GetFunction();
+  context->Global()->Set(v8_str("func"), func);
 
-static Handle<Value> DoDirectGetter() {
-  if (++p_getter_count % 3 == 0) {
-    CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
-    GenerateSomeGarbage();
+  MessageCallback callbacks[] =
+      { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
+  for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
+    MessageCallback callback = callbacks[i];
+    if (callback != NULL) {
+      V8::AddMessageListener(callback);
+    }
+    // Some small number to control number of times message handler should
+    // throw an exception.
+    call_depth = 5;
+    ExpectFalse(
+        "var thrown = false;\n"
+        "try { func(); } catch(e) { thrown = true; }\n"
+        "thrown\n");
+    if (callback != NULL) {
+      V8::RemoveMessageListeners(callback);
+    }
   }
-  return v8_str("Direct Getter Result");
 }
 
-static void DirectGetterCallback(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
-  info.GetReturnValue().Set(DoDirectGetter());
+
+static void ParentGetter(Local<String> name,
+                         const v8::PropertyCallbackInfo<v8::Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  info.GetReturnValue().Set(v8_num(1));
 }
 
 
-template<typename Accessor>
-static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
+static void ChildGetter(Local<String> name,
+                        const v8::PropertyCallbackInfo<v8::Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  info.GetReturnValue().Set(v8_num(42));
+}
+
+
+THREADED_TEST(Overriding) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
-  obj->SetAccessor(v8_str("p1"), accessor);
-  context->Global()->Set(v8_str("o1"), obj->NewInstance());
-  p_getter_count = 0;
-  v8::Handle<v8::Value> result = CompileRun(
-      "function f() {"
-      "  for (var i = 0; i < 30; i++) o1.p1;"
-      "  return o1.p1"
-      "}"
-      "f();");
-  CHECK_EQ(v8_str("Direct Getter Result"), result);
-  CHECK_EQ(31, p_getter_count);
-}
 
+  // Parent template.
+  Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
+  Local<ObjectTemplate> parent_instance_templ =
+      parent_templ->InstanceTemplate();
+  parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
 
-THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
-  LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
-}
+  // Template that inherits from the parent template.
+  Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
+  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);
 
-void ThrowingDirectGetterCallback(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetIsolate()->ThrowException(v8_str("g"));
+  // 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 that 'h' cannot be shadowed.
+  value = v8_compile("o.h = 3; o.h")->Run();
+  CHECK_EQ(1, value->Int32Value());
+
+  // Check that 'i' cannot be shadowed or changed.
+  value = v8_compile("o.i = 3; o.i")->Run();
+  CHECK_EQ(42, value->Int32Value());
 }
 
 
-THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
-  obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
-  context->Global()->Set(v8_str("o1"), obj->NewInstance());
-  v8::Handle<Value> result = CompileRun(
-      "var result = '';"
-      "for (var i = 0; i < 5; i++) {"
-      "    try { o1.p1; } catch (e) { result += e; }"
-      "}"
-      "result;");
-  CHECK_EQ(v8_str("ggggg"), result);
+static void IsConstructHandler(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
+  args.GetReturnValue().Set(args.IsConstructCall());
 }
 
 
-THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
-  int interceptor_call_count = 0;
+THREADED_TEST(IsConstructCall) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ =
-      v8::FunctionTemplate::New(isolate,
-                                FastApiCallback_TrivialSignature,
-                                v8_str("method_data"),
-                                v8::Handle<v8::Signature>());
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
-  templ->SetNamedPropertyHandler(
-      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
-      v8::External::New(isolate, &interceptor_call_count));
+
+  // Function template with call handler.
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
+  templ->SetCallHandler(IsConstructHandler);
+
   LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  CompileRun(
-      "var result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = o.method(41);"
-      "}");
-  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(100, interceptor_call_count);
+
+  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_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
-  int interceptor_call_count = 0;
+THREADED_TEST(ObjectProtoToString) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
-      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
-      v8::Signature::New(isolate, fun_templ));
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  fun_templ->SetHiddenPrototype(true);
-  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
-  templ->SetNamedPropertyHandler(
-      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
-      v8::External::New(isolate, &interceptor_call_count));
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
+  templ->SetClassName(v8_str("MyClass"));
+
   LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  CompileRun(
-      "o.foo = 17;"
-      "var receiver = {};"
-      "receiver.__proto__ = o;"
-      "var result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = receiver.method(41);"
-      "}");
-  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(100, interceptor_call_count);
+
+  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(isolate);
+  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 = object.As<v8::Object>()->ObjectProtoToString();
+  CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
 }
 
 
-THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
-  int interceptor_call_count = 0;
+TEST(ObjectProtoToStringES6) {
+  // TODO(dslomov, caitp): merge into ObjectProtoToString test once shipped.
+  i::FLAG_harmony_tostring = true;
+  LocalContext context;
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
-      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
-      v8::Signature::New(isolate, fun_templ));
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  fun_templ->SetHiddenPrototype(true);
-  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
-  templ->SetNamedPropertyHandler(
-      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
-      v8::External::New(isolate, &interceptor_call_count));
-  LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
+  templ->SetClassName(v8_str("MyClass"));
+
+  Local<String> customized_tostring = v8_str("customized toString");
+
+  // Replace Object.prototype.toString
   CompileRun(
-      "o.foo = 17;"
-      "var receiver = {};"
-      "receiver.__proto__ = o;"
-      "var result = 0;"
-      "var saved_result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = receiver.method(41);"
-      "  if (i == 50) {"
-      "    saved_result = result;"
-      "    receiver = {method: function(x) { return x - 1 }};"
-      "  }"
+      "Object.prototype.toString = function() {"
+      "  return 'customized toString';"
       "}");
-  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
-  CHECK_GE(interceptor_call_count, 50);
-}
 
+  // Normal ToString call should call replaced Object.prototype.toString
+  Local<v8::Object> instance = templ->GetFunction()->NewInstance();
+  Local<String> value = instance->ToString(isolate);
+  CHECK(value->IsString() && value->Equals(customized_tostring));
 
-THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
-  int interceptor_call_count = 0;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
-      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
-      v8::Signature::New(isolate, fun_templ));
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  fun_templ->SetHiddenPrototype(true);
-  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
-  templ->SetNamedPropertyHandler(
-      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
-      v8::External::New(isolate, &interceptor_call_count));
-  LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  CompileRun(
-      "o.foo = 17;"
-      "var receiver = {};"
-      "receiver.__proto__ = o;"
-      "var result = 0;"
-      "var saved_result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = receiver.method(41);"
-      "  if (i == 50) {"
-      "    saved_result = result;"
-      "    o.method = function(x) { return x - 1 };"
-      "  }"
-      "}");
-  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
-  CHECK_GE(interceptor_call_count, 50);
+  // 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 = CompileRun("new Object()");
+  value = object.As<v8::Object>()->ObjectProtoToString();
+  CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
+
+  // Check that ES6 semantics using @@toStringTag work
+  Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
+
+#define TEST_TOSTRINGTAG(type, tag, expected)                \
+  do {                                                       \
+    object = CompileRun("new " #type "()");                  \
+    object.As<v8::Object>()->Set(toStringTag, v8_str(#tag)); \
+    value = object.As<v8::Object>()->ObjectProtoToString();  \
+    CHECK(value->IsString() &&                               \
+          value->Equals(v8_str("[object " #expected "]")));  \
+  } while (0)
+
+  TEST_TOSTRINGTAG(Array, Object, Object);
+  TEST_TOSTRINGTAG(Object, Arguments, Arguments);
+  TEST_TOSTRINGTAG(Object, Array, Array);
+  TEST_TOSTRINGTAG(Object, Boolean, Boolean);
+  TEST_TOSTRINGTAG(Object, Date, Date);
+  TEST_TOSTRINGTAG(Object, Error, Error);
+  TEST_TOSTRINGTAG(Object, Function, Function);
+  TEST_TOSTRINGTAG(Object, Number, Number);
+  TEST_TOSTRINGTAG(Object, RegExp, RegExp);
+  TEST_TOSTRINGTAG(Object, String, String);
+  TEST_TOSTRINGTAG(Object, Foo, Foo);
+
+#undef TEST_TOSTRINGTAG
+
+  Local<v8::RegExp> valueRegExp = v8::RegExp::New(v8_str("^$"),
+                                                  v8::RegExp::kNone);
+  Local<Value> valueNumber = v8_num(123);
+  Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
+  Local<v8::Function> valueFunction =
+      CompileRun("(function fn() {})").As<v8::Function>();
+  Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
+  Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
+  Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
+
+#define TEST_TOSTRINGTAG(type, tagValue, expected)          \
+  do {                                                      \
+    object = CompileRun("new " #type "()");                 \
+    object.As<v8::Object>()->Set(toStringTag, tagValue);    \
+    value = object.As<v8::Object>()->ObjectProtoToString(); \
+    CHECK(value->IsString() &&                              \
+          value->Equals(v8_str("[object " #expected "]"))); \
+  } while (0)
+
+#define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
+  TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
+  TEST_TOSTRINGTAG(Object, tagValue, Object);               \
+  TEST_TOSTRINGTAG(Function, tagValue, Function);           \
+  TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
+  TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
+  TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
+
+  // Test non-String-valued @@toStringTag
+  TEST_TOSTRINGTAG_TYPES(valueRegExp);
+  TEST_TOSTRINGTAG_TYPES(valueNumber);
+  TEST_TOSTRINGTAG_TYPES(valueSymbol);
+  TEST_TOSTRINGTAG_TYPES(valueFunction);
+  TEST_TOSTRINGTAG_TYPES(valueObject);
+  TEST_TOSTRINGTAG_TYPES(valueNull);
+  TEST_TOSTRINGTAG_TYPES(valueUndef);
+
+#undef TEST_TOSTRINGTAG
+#undef TEST_TOSTRINGTAG_TYPES
+
+  // @@toStringTag getter throws
+  Local<Value> obj = v8::Object::New(isolate);
+  obj.As<v8::Object>()->SetAccessor(toStringTag, ThrowingSymbolAccessorGetter);
+  {
+    TryCatch try_catch(isolate);
+    value = obj.As<v8::Object>()->ObjectProtoToString();
+    CHECK(value.IsEmpty());
+    CHECK(try_catch.HasCaught());
+  }
+
+  // @@toStringTag getter does not throw
+  obj = v8::Object::New(isolate);
+  obj.As<v8::Object>()->SetAccessor(
+      toStringTag, SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"));
+  {
+    TryCatch try_catch(isolate);
+    value = obj.As<v8::Object>()->ObjectProtoToString();
+    CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
+    CHECK(!try_catch.HasCaught());
+  }
+
+  // JS @@toStringTag value
+  obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
+  {
+    TryCatch try_catch(isolate);
+    value = obj.As<v8::Object>()->ObjectProtoToString();
+    CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
+    CHECK(!try_catch.HasCaught());
+  }
+
+  // JS @@toStringTag getter throws
+  obj = CompileRun(
+      "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
+      "  get: function() { throw 'Test'; }"
+      "}); obj");
+  {
+    TryCatch try_catch(isolate);
+    value = obj.As<v8::Object>()->ObjectProtoToString();
+    CHECK(value.IsEmpty());
+    CHECK(try_catch.HasCaught());
+  }
+
+  // JS @@toStringTag getter does not throw
+  obj = CompileRun(
+      "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
+      "  get: function() { return 'Test'; }"
+      "}); obj");
+  {
+    TryCatch try_catch(isolate);
+    value = obj.As<v8::Object>()->ObjectProtoToString();
+    CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
+    CHECK(!try_catch.HasCaught());
+  }
 }
 
 
-THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
-  int interceptor_call_count = 0;
+THREADED_TEST(ObjectGetConstructorName) {
   v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
-      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
-      v8::Signature::New(isolate, fun_templ));
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  fun_templ->SetHiddenPrototype(true);
-  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
-  templ->SetNamedPropertyHandler(
-      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
-      v8::External::New(isolate, &interceptor_call_count));
   LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  v8::TryCatch try_catch;
-  CompileRun(
-      "o.foo = 17;"
-      "var receiver = {};"
-      "receiver.__proto__ = o;"
-      "var result = 0;"
-      "var saved_result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = receiver.method(41);"
-      "  if (i == 50) {"
-      "    saved_result = result;"
-      "    receiver = 333;"
-      "  }"
-      "}");
-  CHECK(try_catch.HasCaught());
-  // TODO(verwaest): Adjust message.
-  CHECK_EQ(v8_str("TypeError: undefined is not a function"),
-           try_catch.Exception()->ToString());
-  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
-  CHECK_GE(interceptor_call_count, 50);
+  v8::HandleScope scope(isolate);
+  v8_compile(
+      "function Parent() {};"
+      "function Child() {};"
+      "Child.prototype = new Parent();"
+      "var outer = { inner: function() { } };"
+      "var p = new Parent();"
+      "var c = new Child();"
+      "var x = new outer.inner();"
+      "var proto = Child.prototype;")->Run();
+
+  Local<v8::Value> p = context->Global()->Get(v8_str("p"));
+  CHECK(p->IsObject() &&
+        p->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Parent")));
+
+  Local<v8::Value> c = context->Global()->Get(v8_str("c"));
+  CHECK(c->IsObject() &&
+        c->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Child")));
+
+  Local<v8::Value> x = context->Global()->Get(v8_str("x"));
+  CHECK(x->IsObject() &&
+        x->ToObject(isolate)->GetConstructorName()->Equals(
+            v8_str("outer.inner")));
+
+  Local<v8::Value> child_prototype = context->Global()->Get(v8_str("proto"));
+  CHECK(child_prototype->IsObject() &&
+        child_prototype->ToObject(isolate)->GetConstructorName()->Equals(
+            v8_str("Parent")));
 }
 
 
-THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
-  int interceptor_call_count = 0;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
-      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
-      v8::Signature::New(isolate, fun_templ));
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  fun_templ->SetHiddenPrototype(true);
-  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
-  templ->SetNamedPropertyHandler(
-      InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
-      v8::External::New(isolate, &interceptor_call_count));
-  LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  v8::TryCatch try_catch;
-  CompileRun(
-      "o.foo = 17;"
-      "var receiver = {};"
-      "receiver.__proto__ = o;"
-      "var result = 0;"
-      "var saved_result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = receiver.method(41);"
-      "  if (i == 50) {"
-      "    saved_result = result;"
-      "    receiver = {method: receiver.method};"
-      "  }"
-      "}");
-  CHECK(try_catch.HasCaught());
-  CHECK_EQ(v8_str("TypeError: Illegal invocation"),
-           try_catch.Exception()->ToString());
-  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
-  CHECK_GE(interceptor_call_count, 50);
+bool ApiTestFuzzer::fuzzing_ = false;
+v8::base::Semaphore ApiTestFuzzer::all_tests_done_(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();
 }
 
 
-THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ =
-      v8::FunctionTemplate::New(isolate,
-                                FastApiCallback_TrivialSignature,
-                                v8_str("method_data"),
-                                v8::Handle<v8::Signature>());
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
-  USE(templ);
-  LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  CompileRun(
-      "var result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = o.method(41);"
-      "}");
+// 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();
+  const char* test_name = RegisterThreadedTest::nth(current_)->name();
+  if (test_position == current_) {
+    if (kLogThreading)
+      printf("Stay with %s\n", test_name);
+    return false;
+  }
+  if (kLogThreading) {
+    printf("Switch from %s to %s\n",
+           test_name,
+           RegisterThreadedTest::nth(test_position)->name());
+  }
+  current_ = test_position;
+  RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
+  return true;
+}
 
-  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+
+void ApiTestFuzzer::Run() {
+  // When it is our turn...
+  gate_.Wait();
+  {
+    // ... get the V8 lock and start running the test.
+    v8::Locker locker(CcTest::isolate());
+    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();
+  }
 }
 
 
-THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
-      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
-      v8::Signature::New(isolate, fun_templ));
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  fun_templ->SetHiddenPrototype(true);
-  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
-  CHECK(!templ.IsEmpty());
-  LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  CompileRun(
-      "o.foo = 17;"
-      "var receiver = {};"
-      "receiver.__proto__ = o;"
-      "var result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = receiver.method(41);"
-      "}");
+static unsigned linear_congruential_generator;
 
-  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+
+void ApiTestFuzzer::SetUp(PartOfTest part) {
+  linear_congruential_generator = i::FLAG_testing_prng_seed;
+  fuzzing_ = true;
+  int count = RegisterThreadedTest::count();
+  int start =  count * part / (LAST_PART + 1);
+  int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
+  active_tests_ = tests_being_run_ = end - start + 1;
+  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();
+  }
 }
 
 
-THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
-      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
-      v8::Signature::New(isolate, fun_templ));
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  fun_templ->SetHiddenPrototype(true);
-  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
-  CHECK(!templ.IsEmpty());
-  LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  CompileRun(
-      "o.foo = 17;"
-      "var receiver = {};"
-      "receiver.__proto__ = o;"
-      "var result = 0;"
-      "var saved_result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = receiver.method(41);"
-      "  if (i == 50) {"
-      "    saved_result = result;"
-      "    receiver = {method: function(x) { return x - 1 }};"
-      "  }"
-      "}");
-  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+static void CallTestNumber(int test_number) {
+  (RegisterThreadedTest::nth(test_number)->callback())();
 }
 
 
-THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
-      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
-      v8::Signature::New(isolate, fun_templ));
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  fun_templ->SetHiddenPrototype(true);
-  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
-  CHECK(!templ.IsEmpty());
-  LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  v8::TryCatch try_catch;
-  CompileRun(
-      "o.foo = 17;"
-      "var receiver = {};"
-      "receiver.__proto__ = o;"
-      "var result = 0;"
-      "var saved_result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = receiver.method(41);"
-      "  if (i == 50) {"
-      "    saved_result = result;"
-      "    receiver = 333;"
-      "  }"
-      "}");
-  CHECK(try_catch.HasCaught());
-  // TODO(verwaest): Adjust message.
-  CHECK_EQ(v8_str("TypeError: undefined is not a function"),
-           try_catch.Exception()->ToString());
-  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+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(CcTest::isolate());
+    // Wait till someone starts us again.
+    gate_.Wait();
+    // And we're off.
+  }
 }
 
 
-THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
-      isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
-      v8::Signature::New(isolate, fun_templ));
-  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
-  proto_templ->Set(v8_str("method"), method_templ);
-  fun_templ->SetHiddenPrototype(true);
-  v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
-  CHECK(!templ.IsEmpty());
-  LocalContext context;
-  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
-  GenerateSomeGarbage();
-  context->Global()->Set(v8_str("o"), fun->NewInstance());
-  v8::TryCatch try_catch;
-  CompileRun(
-      "o.foo = 17;"
-      "var receiver = {};"
-      "receiver.__proto__ = o;"
-      "var result = 0;"
-      "var saved_result = 0;"
-      "for (var i = 0; i < 100; i++) {"
-      "  result = receiver.method(41);"
-      "  if (i == 50) {"
-      "    saved_result = result;"
-      "    receiver = Object.create(receiver);"
-      "  }"
-      "}");
-  CHECK(try_catch.HasCaught());
-  CHECK_EQ(v8_str("TypeError: Illegal invocation"),
-           try_catch.Exception()->ToString());
-  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+void ApiTestFuzzer::TearDown() {
+  fuzzing_ = false;
+  for (int i = 0; i < RegisterThreadedTest::count(); i++) {
+    ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
+    if (fuzzer != NULL) fuzzer->Join();
+  }
 }
 
 
-v8::Handle<Value> keyed_call_ic_function;
-
-static void InterceptorKeyedCallICGetter(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (v8_str("x")->Equals(name)) {
-    info.GetReturnValue().Set(keyed_call_ic_function);
-  }
+// Lets not be needlessly self-referential.
+TEST(Threading1) {
+  ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
+  ApiTestFuzzer::RunAllTests();
+  ApiTestFuzzer::TearDown();
 }
 
 
-// Test the case when we stored cacheable lookup into
-// a stub, but the function name changed (to another cacheable function).
-THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(NoBlockGetterX);
-  LocalContext context;
-  context->Global()->Set(v8_str("o"), templ->NewInstance());
-  CompileRun(
-    "proto = new Object();"
-    "proto.y = function(x) { return x + 1; };"
-    "proto.z = function(x) { return x - 1; };"
-    "o.__proto__ = proto;"
-    "var result = 0;"
-    "var method = 'y';"
-    "for (var i = 0; i < 10; i++) {"
-    "  if (i == 5) { method = 'z'; };"
-    "  result += o[method](41);"
-    "}");
-  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
-}
-
-
-// Test the case when we stored cacheable lookup into
-// a stub, but the function name changed (and the new function is present
-// both before and after the interceptor in the prototype chain).
-THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
-  LocalContext context;
-  context->Global()->Set(v8_str("proto1"), templ->NewInstance());
-  keyed_call_ic_function =
-      v8_compile("function f(x) { return x - 1; }; f")->Run();
-  CompileRun(
-    "o = new Object();"
-    "proto2 = new Object();"
-    "o.y = function(x) { return x + 1; };"
-    "proto2.y = function(x) { return x + 2; };"
-    "o.__proto__ = proto1;"
-    "proto1.__proto__ = proto2;"
-    "var result = 0;"
-    "var method = 'x';"
-    "for (var i = 0; i < 10; i++) {"
-    "  if (i == 5) { method = 'y'; };"
-    "  result += o[method](41);"
-    "}");
-  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
-}
-
-
-// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
-// on the global object.
-THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(NoBlockGetterX);
-  LocalContext context;
-  context->Global()->Set(v8_str("o"), templ->NewInstance());
-  CompileRun(
-    "function inc(x) { return x + 1; };"
-    "inc(1);"
-    "function dec(x) { return x - 1; };"
-    "dec(1);"
-    "o.__proto__ = this;"
-    "this.__proto__.x = inc;"
-    "this.__proto__.y = dec;"
-    "var result = 0;"
-    "var method = 'x';"
-    "for (var i = 0; i < 10; i++) {"
-    "  if (i == 5) { method = 'y'; };"
-    "  result += o[method](41);"
-    "}");
-  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
-}
-
-
-// Test the case when actual function to call sits on global object.
-THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
-  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
-  LocalContext context;
-  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
+TEST(Threading2) {
+  ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
+  ApiTestFuzzer::RunAllTests();
+  ApiTestFuzzer::TearDown();
+}
 
-  CompileRun(
-    "function len(x) { return x.length; };"
-    "o.__proto__ = this;"
-    "var m = 'parseFloat';"
-    "var result = 0;"
-    "for (var i = 0; i < 10; i++) {"
-    "  if (i == 5) {"
-    "    m = 'len';"
-    "    saved_result = result;"
-    "  };"
-    "  result = o[m]('239');"
-    "}");
-  CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
-}
-
-
-// Test the map transition before the interceptor.
-THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
-  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
-  LocalContext context;
-  context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
 
-  CompileRun(
-    "var o = new Object();"
-    "o.__proto__ = proto;"
-    "o.method = function(x) { return x + 1; };"
-    "var m = 'method';"
-    "var result = 0;"
-    "for (var i = 0; i < 10; i++) {"
-    "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
-    "  result += o[m](41);"
-    "}");
-  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
+TEST(Threading3) {
+  ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
+  ApiTestFuzzer::RunAllTests();
+  ApiTestFuzzer::TearDown();
 }
 
 
-// Test the map transition after the interceptor.
-THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
-  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
-  LocalContext context;
-  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
+TEST(Threading4) {
+  ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
+  ApiTestFuzzer::RunAllTests();
+  ApiTestFuzzer::TearDown();
+}
 
-  CompileRun(
-    "var proto = new Object();"
-    "o.__proto__ = proto;"
-    "proto.method = function(x) { return x + 1; };"
-    "var m = 'method';"
-    "var result = 0;"
-    "for (var i = 0; i < 10; i++) {"
-    "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
-    "  result += o[m](41);"
-    "}");
-  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
+
+void ApiTestFuzzer::CallTest() {
+  v8::Isolate::Scope scope(CcTest::isolate());
+  if (kLogThreading)
+    printf("Start test %d\n", test_number_);
+  CallTestNumber(test_number_);
+  if (kLogThreading)
+    printf("End test %d\n", test_number_);
 }
 
 
-static int interceptor_call_count = 0;
+static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::Isolate* isolate = args.GetIsolate();
+  CHECK(v8::Locker::IsLocked(isolate));
+  ApiTestFuzzer::Fuzz();
+  v8::Unlocker unlocker(isolate);
+  const char* code = "throw 7;";
+  {
+    v8::Locker nested_locker(isolate);
+    v8::HandleScope scope(isolate);
+    v8::Handle<Value> exception;
+    {
+      v8::TryCatch try_catch(isolate);
+      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(isolate, try_catch.Exception());
+    }
+    args.GetIsolate()->ThrowException(exception);
+  }
+}
+
 
-static void InterceptorICRefErrorGetter(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
+static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   ApiTestFuzzer::Fuzz();
-  if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
-    info.GetReturnValue().Set(call_ic_function2);
+  v8::Unlocker unlocker(CcTest::isolate());
+  const char* code = "throw 7;";
+  {
+    v8::Locker nested_locker(CcTest::isolate());
+    v8::HandleScope scope(args.GetIsolate());
+    v8::Handle<Value> value = CompileRun(code);
+    CHECK(value.IsEmpty());
+    args.GetReturnValue().Set(v8_str("foo"));
   }
 }
 
 
-// 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) {
+// These are locking tests that don't need to be run again
+// as part of the locking aggregation tests.
+TEST(NestedLockers) {
   v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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());
+  v8::Locker locker(isolate);
+  CHECK(v8::Locker::IsLocked(isolate));
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  Local<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(isolate, 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());
 }
 
 
-static int interceptor_ic_exception_get_count = 0;
+// These are locking tests that don't need to be run again
+// as part of the locking aggregation tests.
+TEST(NestedLockersNoTryCatch) {
+  v8::Locker locker(CcTest::isolate());
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  Local<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(env->GetIsolate(), 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());
+}
+
 
-static void InterceptorICExceptionGetter(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
+THREADED_TEST(RecursiveLocking) {
+  v8::Locker locker(CcTest::isolate());
+  {
+    v8::Locker locker2(CcTest::isolate());
+    CHECK(v8::Locker::IsLocked(CcTest::isolate()));
+  }
+}
+
+
+static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
-  if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
-    info.GetReturnValue().Set(call_ic_function3);
+  v8::Unlocker unlocker(CcTest::isolate());
+}
+
+
+THREADED_TEST(LockUnlockLock) {
+  {
+    v8::Locker locker(CcTest::isolate());
+    v8::HandleScope scope(CcTest::isolate());
+    LocalContext env;
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(CcTest::isolate(), 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());
   }
-  if (interceptor_ic_exception_get_count == 20) {
-    info.GetIsolate()->ThrowException(v8_num(42));
-    return;
+  {
+    v8::Locker locker(CcTest::isolate());
+    v8::HandleScope scope(CcTest::isolate());
+    LocalContext env;
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(CcTest::isolate(), 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());
   }
 }
 
 
-// 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::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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 GetGlobalObjectsCount() {
+  int count = 0;
+  i::HeapIterator it(CcTest::heap());
+  for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
+    if (object->IsJSGlobalObject()) count++;
+  return count;
+}
+
+
+static void CheckSurvivingGlobalObjectsCount(int expected) {
+  // 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.
+  CcTest::heap()->CollectAllGarbage();
+  CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
+  int count = GetGlobalObjectsCount();
+#ifdef DEBUG
+  if (count != expected) CcTest::heap()->TracePathToGlobal();
+#endif
+  CHECK_EQ(expected, count);
 }
 
 
-static int interceptor_ic_exception_set_count = 0;
+TEST(DontLeakGlobalObjects) {
+  // Regression test for issues 1139850 and 1174891.
 
-static void InterceptorICExceptionSetter(
-      Local<String> key,
-      Local<Value> value,
-      const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  if (++interceptor_ic_exception_set_count > 20) {
-    info.GetIsolate()->ThrowException(v8_num(42));
-  }
-}
+  i::FLAG_expose_gc = true;
+  v8::V8::Initialize();
 
+  for (int i = 0; i < 5; i++) {
+    { v8::HandleScope scope(CcTest::isolate());
+      LocalContext context;
+    }
+    CcTest::isolate()->ContextDisposedNotification();
+    CheckSurvivingGlobalObjectsCount(0);
 
-// Test interceptor store IC where the interceptor throws an exception
-// once in a while.
-THREADED_TEST(InterceptorICSetterExceptions) {
-  interceptor_ic_exception_set_count = 0;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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());
-}
+    { v8::HandleScope scope(CcTest::isolate());
+      LocalContext context;
+      v8_compile("Date")->Run();
+    }
+    CcTest::isolate()->ContextDisposedNotification();
+    CheckSurvivingGlobalObjectsCount(0);
 
+    { v8::HandleScope scope(CcTest::isolate());
+      LocalContext context;
+      v8_compile("/aaa/")->Run();
+    }
+    CcTest::isolate()->ContextDisposedNotification();
+    CheckSurvivingGlobalObjectsCount(0);
 
-// Test that we ignore null interceptors.
-THREADED_TEST(NullNamedInterceptor) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(
-      static_cast<v8::NamedPropertyGetterCallback>(0));
-  LocalContext context;
-  templ->Set(CcTest::isolate(), "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());
+    { v8::HandleScope scope(CcTest::isolate());
+      const char* extension_list[] = { "v8/gc" };
+      v8::ExtensionConfiguration extensions(1, extension_list);
+      LocalContext context(&extensions);
+      v8_compile("gc();")->Run();
+    }
+    CcTest::isolate()->ContextDisposedNotification();
+    CheckSurvivingGlobalObjectsCount(0);
+  }
 }
 
 
-// Test that we ignore null interceptors.
-THREADED_TEST(NullIndexedInterceptor) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(
-      static_cast<v8::IndexedPropertyGetterCallback>(0));
+TEST(CopyablePersistent) {
   LocalContext context;
-  templ->Set(CcTest::isolate(), "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());
+  v8::Isolate* isolate = context->GetIsolate();
+  i::GlobalHandles* globals =
+      reinterpret_cast<i::Isolate*>(isolate)->global_handles();
+  int initial_handles = globals->global_handles_count();
+  typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
+      CopyableObject;
+  {
+    CopyableObject handle1;
+    {
+      v8::HandleScope scope(isolate);
+      handle1.Reset(isolate, v8::Object::New(isolate));
+    }
+    CHECK_EQ(initial_handles + 1, globals->global_handles_count());
+    CopyableObject  handle2;
+    handle2 = handle1;
+    CHECK(handle1 == handle2);
+    CHECK_EQ(initial_handles + 2, globals->global_handles_count());
+    CopyableObject handle3(handle2);
+    CHECK(handle1 == handle3);
+    CHECK_EQ(initial_handles + 3, globals->global_handles_count());
+  }
+  // Verify autodispose
+  CHECK_EQ(initial_handles, globals->global_handles_count());
 }
 
 
-THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
-  templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("obj"),
-                     templ->GetFunction()->NewInstance());
-  ExpectTrue("obj.x === 42");
-  ExpectTrue("!obj.propertyIsEnumerable('x')");
+static void WeakApiCallback(
+    const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
+  data.GetParameter()->Reset();
+  delete data.GetParameter();
 }
 
 
-static void ThrowingGetter(Local<String> name,
-                           const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  info.GetIsolate()->ThrowException(Handle<Value>());
-  info.GetReturnValue().SetUndefined();
+TEST(WeakCallbackApi) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  i::GlobalHandles* globals =
+      reinterpret_cast<i::Isolate*>(isolate)->global_handles();
+  int initial_handles = globals->global_handles_count();
+  {
+    v8::HandleScope scope(isolate);
+    v8::Local<v8::Object> obj = v8::Object::New(isolate);
+    obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
+    v8::Persistent<v8::Object>* handle =
+        new v8::Persistent<v8::Object>(isolate, obj);
+    handle->SetWeak<v8::Persistent<v8::Object>>(
+        handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
+  }
+  reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
+      i::Heap::kAbortIncrementalMarkingMask);
+  // Verify disposed.
+  CHECK_EQ(initial_handles, globals->global_handles_count());
 }
 
 
-THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
-  LocalContext context;
-  HandleScope scope(context->GetIsolate());
+v8::Persistent<v8::Object> some_object;
+v8::Persistent<v8::Object> bad_handle;
 
-  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
-  Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
-  instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
 
-  Local<Object> instance = templ->GetFunction()->NewInstance();
+void NewPersistentHandleCallback2(
+    const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
+  v8::HandleScope scope(data.GetIsolate());
+  bad_handle.Reset(data.GetIsolate(), some_object);
+}
 
-  Local<Object> another = Object::New(context->GetIsolate());
-  another->SetPrototype(instance);
 
-  Local<Object> with_js_getter = CompileRun(
-      "o = {};\n"
-      "o.__defineGetter__('f', function() { throw undefined; });\n"
-      "o\n").As<Object>();
-  CHECK(!with_js_getter.IsEmpty());
+void NewPersistentHandleCallback1(
+    const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
+  data.GetParameter()->Reset();
+  data.SetSecondPassCallback(NewPersistentHandleCallback2);
+}
 
-  TryCatch try_catch;
 
-  Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
-  CHECK(try_catch.HasCaught());
-  try_catch.Reset();
-  CHECK(result.IsEmpty());
+THREADED_TEST(NewPersistentHandleFromWeakCallback) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
 
-  result = another->GetRealNamedProperty(v8_str("f"));
-  CHECK(try_catch.HasCaught());
-  try_catch.Reset();
-  CHECK(result.IsEmpty());
+  v8::Persistent<v8::Object> handle1, handle2;
+  {
+    v8::HandleScope scope(isolate);
+    some_object.Reset(isolate, v8::Object::New(isolate));
+    handle1.Reset(isolate, v8::Object::New(isolate));
+    handle2.Reset(isolate, v8::Object::New(isolate));
+  }
+  // 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.SetWeak(&handle1, NewPersistentHandleCallback1,
+                  v8::WeakCallbackType::kParameter);
+  handle2.Reset();
+  CcTest::heap()->CollectAllGarbage();
+}
 
-  result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
-  CHECK(try_catch.HasCaught());
-  try_catch.Reset();
-  CHECK(result.IsEmpty());
 
-  result = another->Get(v8_str("f"));
-  CHECK(try_catch.HasCaught());
-  try_catch.Reset();
-  CHECK(result.IsEmpty());
+v8::Persistent<v8::Object> to_be_disposed;
 
-  result = with_js_getter->GetRealNamedProperty(v8_str("f"));
-  CHECK(try_catch.HasCaught());
-  try_catch.Reset();
-  CHECK(result.IsEmpty());
 
-  result = with_js_getter->Get(v8_str("f"));
-  CHECK(try_catch.HasCaught());
-  try_catch.Reset();
-  CHECK(result.IsEmpty());
+void DisposeAndForceGcCallback2(
+    const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
+  to_be_disposed.Reset();
+  CcTest::heap()->CollectAllGarbage();
 }
 
 
-static void ThrowingCallbackWithTryCatch(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  TryCatch try_catch;
-  // Verboseness is important: it triggers message delivery which can call into
-  // external code.
-  try_catch.SetVerbose(true);
-  CompileRun("throw 'from JS';");
-  CHECK(try_catch.HasCaught());
-  CHECK(!CcTest::i_isolate()->has_pending_exception());
-  CHECK(!CcTest::i_isolate()->has_scheduled_exception());
+void DisposeAndForceGcCallback1(
+    const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
+  data.GetParameter()->Reset();
+  data.SetSecondPassCallback(DisposeAndForceGcCallback2);
 }
 
 
-static int call_depth;
-
+THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
 
-static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
-  TryCatch try_catch;
+  v8::Persistent<v8::Object> handle1, handle2;
+  {
+    v8::HandleScope scope(isolate);
+    handle1.Reset(isolate, v8::Object::New(isolate));
+    handle2.Reset(isolate, v8::Object::New(isolate));
+  }
+  handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
+                  v8::WeakCallbackType::kParameter);
+  to_be_disposed.Reset(isolate, handle2);
+  CcTest::heap()->CollectAllGarbage();
 }
 
-
-static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
-  if (--call_depth) CompileRun("throw 'ThrowInJS';");
+void DisposingCallback(
+    const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
+  data.GetParameter()->Reset();
 }
 
-
-static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
-  if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
+void HandleCreatingCallback2(
+    const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
+  v8::HandleScope scope(data.GetIsolate());
+  v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
 }
 
 
-static void WebKitLike(Handle<Message> message, Handle<Value> data) {
-  Handle<String> errorMessageString = message->Get();
-  CHECK(!errorMessageString.IsEmpty());
-  message->GetStackTrace();
-  message->GetScriptResourceName();
+void HandleCreatingCallback1(
+    const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
+  data.GetParameter()->Reset();
+  data.SetSecondPassCallback(HandleCreatingCallback2);
 }
 
 
-THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
+THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
-  HandleScope scope(isolate);
 
-  Local<Function> func =
-      FunctionTemplate::New(isolate,
-                            ThrowingCallbackWithTryCatch)->GetFunction();
-  context->Global()->Set(v8_str("func"), func);
+  v8::Persistent<v8::Object> handle1, handle2, handle3;
+  {
+    v8::HandleScope scope(isolate);
+    handle3.Reset(isolate, v8::Object::New(isolate));
+    handle2.Reset(isolate, v8::Object::New(isolate));
+    handle1.Reset(isolate, v8::Object::New(isolate));
+  }
+  handle2.SetWeak(&handle2, DisposingCallback,
+                  v8::WeakCallbackType::kParameter);
+  handle3.SetWeak(&handle3, HandleCreatingCallback1,
+                  v8::WeakCallbackType::kParameter);
+  CcTest::heap()->CollectAllGarbage();
+}
 
-  MessageCallback callbacks[] =
-      { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
-  for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
-    MessageCallback callback = callbacks[i];
-    if (callback != NULL) {
-      V8::AddMessageListener(callback);
+
+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(CcTest::isolate());
+      LocalContext context;
+      CompileRun(source);
     }
-    // Some small number to control number of times message handler should
-    // throw an exception.
-    call_depth = 5;
-    ExpectFalse(
-        "var thrown = false;\n"
-        "try { func(); } catch(e) { thrown = true; }\n"
-        "thrown\n");
-    if (callback != NULL) {
-      V8::RemoveMessageListeners(callback);
+    { v8::HandleScope scope(CcTest::isolate());
+      LocalContext context;
+      CompileRun(source);
     }
   }
 }
 
 
-static void ParentGetter(Local<String> name,
-                         const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  info.GetReturnValue().Set(v8_num(1));
+static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
+  v8::EscapableHandleScope inner(env->GetIsolate());
+  env->Enter();
+  v8::Local<Value> three = v8_num(3);
+  v8::Local<Value> value = inner.Escape(three);
+  env->Exit();
+  return value;
+}
+
+
+THREADED_TEST(NestedHandleScopeAndContexts) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope outer(isolate);
+  v8::Local<Context> env = Context::New(isolate);
+  env->Enter();
+  v8::Handle<Value> value = NestedScope(env);
+  v8::Handle<String> str(value->ToString(isolate));
+  CHECK(!str.IsEmpty());
+  env->Exit();
 }
 
 
-static void ChildGetter(Local<String> name,
-                        const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-  info.GetReturnValue().Set(v8_num(42));
+static bool MatchPointers(void* key1, void* key2) {
+  return key1 == key2;
 }
 
 
-THREADED_TEST(Overriding) {
-  i::FLAG_es5_readonly = true;
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
+struct SymbolInfo {
+  size_t id;
+  size_t size;
+  std::string name;
+};
 
-  // Parent template.
-  Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
-  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(isolate);
-  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);
+class SetFunctionEntryHookTest {
+ public:
+  SetFunctionEntryHookTest() {
+    CHECK(instance_ == NULL);
+    instance_ = this;
+  }
+  ~SetFunctionEntryHookTest() {
+    CHECK(instance_ == this);
+    instance_ = NULL;
+  }
+  void Reset() {
+    symbols_.clear();
+    symbol_locations_.clear();
+    invocations_.clear();
+  }
+  void RunTest();
+  void OnJitEvent(const v8::JitCodeEvent* event);
+  static void JitEvent(const v8::JitCodeEvent* event) {
+    CHECK(instance_ != NULL);
+    instance_->OnJitEvent(event);
+  }
 
-  // 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);
+  void OnEntryHook(uintptr_t function,
+                   uintptr_t return_addr_location);
+  static void EntryHook(uintptr_t function,
+                        uintptr_t return_addr_location) {
+    CHECK(instance_ != NULL);
+    instance_->OnEntryHook(function, return_addr_location);
+  }
 
-  // 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);
+  static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
+    CHECK(instance_ != NULL);
+    args.GetReturnValue().Set(v8_num(42));
+  }
+  void RunLoopInNewEnv(v8::Isolate* isolate);
 
+  // Records addr as location of symbol.
+  void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
 
+  // Finds the symbol containing addr
+  SymbolInfo* FindSymbolForAddr(i::Address addr);
+  // Returns the number of invocations where the caller name contains
+  // \p caller_name and the function name contains \p function_name.
+  int CountInvocations(const char* caller_name,
+                       const char* function_name);
 
-  // Instantiate the child template.
-  Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
+  i::Handle<i::JSFunction> foo_func_;
+  i::Handle<i::JSFunction> bar_func_;
 
-  // 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());
+  typedef std::map<size_t, SymbolInfo> SymbolMap;
+  typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
+  typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
+  SymbolMap symbols_;
+  SymbolLocationMap symbol_locations_;
+  InvocationMap invocations_;
 
-  // Check that 'h' cannot be shadowed.
-  value = v8_compile("o.h = 3; o.h")->Run();
-  CHECK_EQ(1, value->Int32Value());
+  static SetFunctionEntryHookTest* instance_;
+};
+SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
 
-  // Check that 'i' cannot be shadowed or changed.
-  value = v8_compile("o.i = 3; o.i")->Run();
-  CHECK_EQ(42, value->Int32Value());
-}
 
+// Returns true if addr is in the range [start, start+len).
+static bool Overlaps(i::Address start, size_t len, i::Address addr) {
+  if (start <= addr && start + len > addr)
+    return true;
 
-static void IsConstructHandler(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-  args.GetReturnValue().Set(args.IsConstructCall());
+  return false;
 }
 
+void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
+                                              SymbolInfo* symbol) {
+  // Insert the symbol at the new location.
+  SymbolLocationMap::iterator it =
+      symbol_locations_.insert(std::make_pair(addr, symbol)).first;
+  // Now erase symbols to the left and right that overlap this one.
+  while (it != symbol_locations_.begin()) {
+    SymbolLocationMap::iterator left = it;
+    --left;
+    if (!Overlaps(left->first, left->second->size, addr))
+      break;
+    symbol_locations_.erase(left);
+  }
 
-THREADED_TEST(IsConstructCall) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-
-  // Function template with call handler.
-  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
-  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());
+  // Now erase symbols to the left and right that overlap this one.
+  while (true) {
+    SymbolLocationMap::iterator right = it;
+    ++right;
+    if (right == symbol_locations_.end())
+        break;
+    if (!Overlaps(addr, symbol->size, right->first))
+      break;
+    symbol_locations_.erase(right);
+  }
 }
 
 
-THREADED_TEST(ObjectProtoToString) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
-  templ->SetClassName(v8_str("MyClass"));
+void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
+  switch (event->type) {
+    case v8::JitCodeEvent::CODE_ADDED: {
+        CHECK(event->code_start != NULL);
+        CHECK_NE(0, static_cast<int>(event->code_len));
+        CHECK(event->name.str != NULL);
+        size_t symbol_id = symbols_.size();
 
-  LocalContext context;
+        // Record the new symbol.
+        SymbolInfo& info = symbols_[symbol_id];
+        info.id = symbol_id;
+        info.size = event->code_len;
+        info.name.assign(event->name.str, event->name.str + event->name.len);
 
-  Local<String> customized_tostring = v8_str("customized toString");
+        // And record it's location.
+        InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
+      }
+      break;
 
-  // Replace Object.prototype.toString
-  v8_compile("Object.prototype.toString = function() {"
-                  "  return 'customized toString';"
-                  "}")->Run();
+    case v8::JitCodeEvent::CODE_MOVED: {
+        // We would like to never see code move that we haven't seen before,
+        // but the code creation event does not happen until the line endings
+        // have been calculated (this is so that we can report the line in the
+        // script at which the function source is found, see
+        // Compiler::RecordFunctionCompilation) and the line endings
+        // calculations can cause a GC, which can move the newly created code
+        // before its existence can be logged.
+        SymbolLocationMap::iterator it(
+            symbol_locations_.find(
+                reinterpret_cast<i::Address>(event->code_start)));
+        if (it != symbol_locations_.end()) {
+          // Found a symbol at this location, move it.
+          SymbolInfo* info = it->second;
+          symbol_locations_.erase(it);
+          InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
+                         info);
+        }
+      }
+    default:
+      break;
+  }
+}
 
-  // 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));
+void SetFunctionEntryHookTest::OnEntryHook(
+    uintptr_t function, uintptr_t return_addr_location) {
+  // Get the function's code object.
+  i::Code* function_code = i::Code::GetCodeFromTargetAddress(
+      reinterpret_cast<i::Address>(function));
+  CHECK(function_code != NULL);
 
-  // ObjectProtoToString should not call replace toString function.
-  value = instance->ObjectProtoToString();
-  CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
+  // Then try and look up the caller's code object.
+  i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
 
-  // Check global
-  value = context->Global()->ObjectProtoToString();
-  CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
+  // Count the invocation.
+  SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
+  SymbolInfo* function_symbol =
+      FindSymbolForAddr(reinterpret_cast<i::Address>(function));
+  ++invocations_[std::make_pair(caller_symbol, function_symbol)];
 
-  // Check ordinary object
-  Local<Value> object = v8_compile("new Object()")->Run();
-  value = object.As<v8::Object>()->ObjectProtoToString();
-  CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
+  if (!bar_func_.is_null() && function_code == bar_func_->code()) {
+    // Check that we have a symbol for the "bar" function at the right location.
+    SymbolLocationMap::iterator it(
+        symbol_locations_.find(function_code->instruction_start()));
+    CHECK(it != symbol_locations_.end());
+  }
+
+  if (!foo_func_.is_null() && function_code == foo_func_->code()) {
+    // Check that we have a symbol for "foo" at the right location.
+    SymbolLocationMap::iterator it(
+        symbol_locations_.find(function_code->instruction_start()));
+    CHECK(it != symbol_locations_.end());
+  }
 }
 
 
-THREADED_TEST(ObjectGetConstructorName) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  v8_compile("function Parent() {};"
-             "function Child() {};"
-             "Child.prototype = new Parent();"
-             "var outer = { inner: function() { } };"
-             "var p = new Parent();"
-             "var c = new Child();"
-             "var x = new outer.inner();")->Run();
+SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
+  SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
+  // Do we have a direct hit on a symbol?
+  if (it != symbol_locations_.end()) {
+    if (it->first == addr)
+      return it->second;
+  }
 
-  Local<v8::Value> p = context->Global()->Get(v8_str("p"));
-  CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
-      v8_str("Parent")));
+  // If not a direct hit, it'll have to be the previous symbol.
+  if (it == symbol_locations_.begin())
+    return NULL;
 
-  Local<v8::Value> c = context->Global()->Get(v8_str("c"));
-  CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
-      v8_str("Child")));
+  --it;
+  size_t offs = addr - it->first;
+  if (offs < it->second->size)
+    return it->second;
 
-  Local<v8::Value> x = context->Global()->Get(v8_str("x"));
-  CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
-      v8_str("outer.inner")));
+  return NULL;
 }
 
 
-bool ApiTestFuzzer::fuzzing_ = false;
-i::Semaphore ApiTestFuzzer::all_tests_done_(0);
-int ApiTestFuzzer::active_tests_;
-int ApiTestFuzzer::tests_being_run_;
-int ApiTestFuzzer::current_;
-
+int SetFunctionEntryHookTest::CountInvocations(
+    const char* caller_name, const char* function_name) {
+  InvocationMap::iterator it(invocations_.begin());
+  int invocations = 0;
+  for (; it != invocations_.end(); ++it) {
+    SymbolInfo* caller = it->first.first;
+    SymbolInfo* function = it->first.second;
 
-// 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();
-}
+    // Filter out non-matching functions.
+    if (function_name != NULL) {
+      if (function->name.find(function_name) == std::string::npos)
+        continue;
+    }
 
+    // Filter out non-matching callers.
+    if (caller_name != NULL) {
+      if (caller == NULL)
+        continue;
+      if (caller->name.find(caller_name) == std::string::npos)
+        continue;
+    }
 
-// 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();
-  const char* test_name = RegisterThreadedTest::nth(current_)->name();
-  if (test_position == current_) {
-    if (kLogThreading)
-      printf("Stay with %s\n", test_name);
-    return false;
-  }
-  if (kLogThreading) {
-    printf("Switch from %s to %s\n",
-           test_name,
-           RegisterThreadedTest::nth(test_position)->name());
+    // It matches add the invocation count to the tally.
+    invocations += it->second;
   }
-  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(CcTest::isolate());
-    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();
-  }
+  return invocations;
 }
 
 
-static unsigned linear_congruential_generator;
+void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
+  v8::HandleScope outer(isolate);
+  v8::Local<Context> env = Context::New(isolate);
+  env->Enter();
 
+  Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
+  t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
+  env->Global()->Set(v8_str("obj"), t->NewInstance());
 
-void ApiTestFuzzer::SetUp(PartOfTest part) {
-  linear_congruential_generator = i::FLAG_testing_prng_seed;
-  fuzzing_ = true;
-  int count = RegisterThreadedTest::count();
-  int start =  count * part / (LAST_PART + 1);
-  int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
-  active_tests_ = tests_being_run_ = end - start + 1;
-  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();
-  }
-}
+  const char* script =
+      "function bar() {\n"
+      "  var sum = 0;\n"
+      "  for (i = 0; i < 100; ++i)\n"
+      "    sum = foo(i);\n"
+      "  return sum;\n"
+      "}\n"
+      "function foo(i) { return i * i; }\n"
+      "// Invoke on the runtime function.\n"
+      "obj.asdf()";
+  CompileRun(script);
+  bar_func_ = i::Handle<i::JSFunction>::cast(
+          v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
+  DCHECK(!bar_func_.is_null());
 
+  foo_func_ =
+      i::Handle<i::JSFunction>::cast(
+           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
+  DCHECK(!foo_func_.is_null());
 
-static void CallTestNumber(int test_number) {
-  (RegisterThreadedTest::nth(test_number)->callback())();
-}
+  v8::Handle<v8::Value> value = CompileRun("bar();");
+  CHECK(value->IsNumber());
+  CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
 
+  // Test the optimized codegen path.
+  value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
+                     "bar();");
+  CHECK(value->IsNumber());
+  CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
 
-void ApiTestFuzzer::RunAllTests() {
-  // Set off the first test.
-  current_ = -1;
-  NextThread();
-  // Wait till they are all done.
-  all_tests_done_.Wait();
+  env->Exit();
 }
 
 
-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 SetFunctionEntryHookTest::RunTest() {
+  // Work in a new isolate throughout.
+  v8::Isolate::CreateParams create_params;
+  create_params.entry_hook = EntryHook;
+  create_params.code_event_handler = JitEvent;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
 
+  {
+    v8::Isolate::Scope scope(isolate);
 
-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(CcTest::isolate());
-    // Wait till someone starts us again.
-    gate_.Wait();
-    // And we're off.
-  }
-}
+    RunLoopInNewEnv(isolate);
 
+    // Check the exepected invocation counts.
+    CHECK_EQ(2, CountInvocations(NULL, "bar"));
+    CHECK_EQ(200, CountInvocations("bar", "foo"));
+    CHECK_EQ(200, CountInvocations(NULL, "foo"));
 
-void ApiTestFuzzer::TearDown() {
-  fuzzing_ = false;
-  for (int i = 0; i < RegisterThreadedTest::count(); i++) {
-    ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
-    if (fuzzer != NULL) fuzzer->Join();
+    // Verify that we have an entry hook on some specific stubs.
+    CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
+    CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
+    CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
   }
-}
+  isolate->Dispose();
 
+  Reset();
 
-// Lets not be needlessly self-referential.
-TEST(Threading1) {
-  ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
-  ApiTestFuzzer::RunAllTests();
-  ApiTestFuzzer::TearDown();
-}
+  // Make sure a second isolate is unaffected by the previous entry hook.
+  create_params = v8::Isolate::CreateParams();
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  isolate = v8::Isolate::New(create_params);
+  {
+    v8::Isolate::Scope scope(isolate);
 
+    // Reset the entry count to zero and set the entry hook.
+    RunLoopInNewEnv(isolate);
 
-TEST(Threading2) {
-  ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
-  ApiTestFuzzer::RunAllTests();
-  ApiTestFuzzer::TearDown();
+    // We should record no invocations in this isolate.
+    CHECK_EQ(0, static_cast<int>(invocations_.size()));
+  }
+
+  isolate->Dispose();
 }
 
 
-TEST(Threading3) {
-  ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
-  ApiTestFuzzer::RunAllTests();
-  ApiTestFuzzer::TearDown();
+TEST(SetFunctionEntryHook) {
+  // FunctionEntryHook does not work well with experimental natives.
+  // Experimental natives are compiled during snapshot deserialization.
+  // This test breaks because InstallGetter (function from snapshot that
+  // only gets called from experimental natives) is compiled with entry hooks.
+  i::FLAG_allow_natives_syntax = true;
+  i::FLAG_use_inlining = false;
+
+  SetFunctionEntryHookTest test;
+  test.RunTest();
 }
 
 
-TEST(Threading4) {
-  ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
-  ApiTestFuzzer::RunAllTests();
-  ApiTestFuzzer::TearDown();
-}
+static i::HashMap* code_map = NULL;
+static i::HashMap* jitcode_line_info = NULL;
+static int saw_bar = 0;
+static int move_events = 0;
 
 
-void ApiTestFuzzer::CallTest() {
-  v8::Isolate::Scope scope(CcTest::isolate());
-  if (kLogThreading)
-    printf("Start test %d\n", test_number_);
-  CallTestNumber(test_number_);
-  if (kLogThreading)
-    printf("End test %d\n", test_number_);
-}
+static bool FunctionNameIs(const char* expected,
+                           const v8::JitCodeEvent* event) {
+  // Log lines for functions are of the general form:
+  // "LazyCompile:<type><function_name>", where the type is one of
+  // "*", "~" or "".
+  static const char kPreamble[] = "LazyCompile:";
+  static size_t kPreambleLen = sizeof(kPreamble) - 1;
+
+  if (event->name.len < sizeof(kPreamble) - 1 ||
+      strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
+    return false;
+  }
 
+  const char* tail = event->name.str + kPreambleLen;
+  size_t tail_len = event->name.len - kPreambleLen;
+  size_t expected_len = strlen(expected);
+  if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
+    --tail_len;
+    ++tail;
+  }
 
-static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::Isolate* isolate = args.GetIsolate();
-  CHECK(v8::Locker::IsLocked(isolate));
-  ApiTestFuzzer::Fuzz();
-  v8::Unlocker unlocker(isolate);
-  const char* code = "throw 7;";
-  {
-    v8::Locker nested_locker(isolate);
-    v8::HandleScope scope(isolate);
-    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(isolate, try_catch.Exception());
-    }
-    args.GetIsolate()->ThrowException(exception);
+  // Check for tails like 'bar :1'.
+  if (tail_len > expected_len + 2 &&
+      tail[expected_len] == ' ' &&
+      tail[expected_len + 1] == ':' &&
+      tail[expected_len + 2] &&
+      !strncmp(tail, expected, expected_len)) {
+    return true;
   }
-}
 
+  if (tail_len != expected_len)
+    return false;
 
-static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  CHECK(v8::Locker::IsLocked(CcTest::isolate()));
-  ApiTestFuzzer::Fuzz();
-  v8::Unlocker unlocker(CcTest::isolate());
-  const char* code = "throw 7;";
-  {
-    v8::Locker nested_locker(CcTest::isolate());
-    v8::HandleScope scope(args.GetIsolate());
-    v8::Handle<Value> value = CompileRun(code);
-    CHECK(value.IsEmpty());
-    args.GetReturnValue().Set(v8_str("foo"));
-  }
+  return strncmp(tail, expected, expected_len) == 0;
 }
 
 
-// These are locking tests that don't need to be run again
-// as part of the locking aggregation tests.
-TEST(NestedLockers) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::Locker locker(isolate);
-  CHECK(v8::Locker::IsLocked(isolate));
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  Local<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(isolate, 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());
-}
+static void event_handler(const v8::JitCodeEvent* event) {
+  CHECK(event != NULL);
+  CHECK(code_map != NULL);
+  CHECK(jitcode_line_info != NULL);
 
+  class DummyJitCodeLineInfo {
+  };
 
-// These are locking tests that don't need to be run again
-// as part of the locking aggregation tests.
-TEST(NestedLockersNoTryCatch) {
-  v8::Locker locker(CcTest::isolate());
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  Local<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(env->GetIsolate(), 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());
-}
+  switch (event->type) {
+    case v8::JitCodeEvent::CODE_ADDED: {
+        CHECK(event->code_start != NULL);
+        CHECK_NE(0, static_cast<int>(event->code_len));
+        CHECK(event->name.str != NULL);
+        i::HashMap::Entry* entry = code_map->LookupOrInsert(
+            event->code_start, i::ComputePointerHash(event->code_start));
+        entry->value = reinterpret_cast<void*>(event->code_len);
 
+        if (FunctionNameIs("bar", event)) {
+          ++saw_bar;
+        }
+      }
+      break;
 
-THREADED_TEST(RecursiveLocking) {
-  v8::Locker locker(CcTest::isolate());
-  {
-    v8::Locker locker2(CcTest::isolate());
-    CHECK(v8::Locker::IsLocked(CcTest::isolate()));
-  }
-}
+    case v8::JitCodeEvent::CODE_MOVED: {
+        uint32_t hash = i::ComputePointerHash(event->code_start);
+        // We would like to never see code move that we haven't seen before,
+        // but the code creation event does not happen until the line endings
+        // have been calculated (this is so that we can report the line in the
+        // script at which the function source is found, see
+        // Compiler::RecordFunctionCompilation) and the line endings
+        // calculations can cause a GC, which can move the newly created code
+        // before its existence can be logged.
+        i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
+        if (entry != NULL) {
+          ++move_events;
 
+          CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
+          code_map->Remove(event->code_start, hash);
 
-static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-  v8::Unlocker unlocker(CcTest::isolate());
-}
+          entry = code_map->LookupOrInsert(
+              event->new_code_start,
+              i::ComputePointerHash(event->new_code_start));
+          entry->value = reinterpret_cast<void*>(event->code_len);
+        }
+      }
+      break;
 
+    case v8::JitCodeEvent::CODE_REMOVED:
+      // Object/code removal events are currently not dispatched from the GC.
+      CHECK(false);
+      break;
 
-THREADED_TEST(LockUnlockLock) {
-  {
-    v8::Locker locker(CcTest::isolate());
-    v8::HandleScope scope(CcTest::isolate());
-    LocalContext env;
-    Local<v8::FunctionTemplate> fun_templ =
-        v8::FunctionTemplate::New(CcTest::isolate(), 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(CcTest::isolate());
-    v8::HandleScope scope(CcTest::isolate());
-    LocalContext env;
-    Local<v8::FunctionTemplate> fun_templ =
-        v8::FunctionTemplate::New(CcTest::isolate(), 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());
+    // For CODE_START_LINE_INFO_RECORDING event, we will create one
+    // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
+    // record it in jitcode_line_info.
+    case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
+        DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
+        v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
+        temp_event->user_data = line_info;
+        i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
+            line_info, i::ComputePointerHash(line_info));
+        entry->value = reinterpret_cast<void*>(line_info);
+      }
+      break;
+    // For these two events, we will check whether the event->user_data
+    // data structure is created before during CODE_START_LINE_INFO_RECORDING
+    // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
+    case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
+        CHECK(event->user_data != NULL);
+        uint32_t hash = i::ComputePointerHash(event->user_data);
+        i::HashMap::Entry* entry =
+            jitcode_line_info->Lookup(event->user_data, hash);
+        CHECK(entry != NULL);
+        delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
+      }
+      break;
+
+    case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
+        CHECK(event->user_data != NULL);
+        uint32_t hash = i::ComputePointerHash(event->user_data);
+        i::HashMap::Entry* entry =
+            jitcode_line_info->Lookup(event->user_data, hash);
+        CHECK(entry != NULL);
+      }
+      break;
+
+    default:
+      // Impossible event.
+      CHECK(false);
+      break;
   }
 }
 
 
-static int GetGlobalObjectsCount() {
-  CcTest::heap()->EnsureHeapIsIterable();
-  int count = 0;
-  i::HeapIterator it(CcTest::heap());
-  for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
-    if (object->IsJSGlobalObject()) count++;
-  return count;
-}
+UNINITIALIZED_TEST(SetJitCodeEventHandler) {
+  i::FLAG_stress_compaction = true;
+  i::FLAG_incremental_marking = false;
+  if (i::FLAG_never_compact) return;
+  const char* script =
+      "function bar() {"
+      "  var sum = 0;"
+      "  for (i = 0; i < 10; ++i)"
+      "    sum = foo(i);"
+      "  return sum;"
+      "}"
+      "function foo(i) { return i; };"
+      "bar();";
 
+  // Run this test in a new isolate to make sure we don't
+  // have remnants of state from other code.
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  isolate->Enter();
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::Heap* heap = i_isolate->heap();
 
-static void CheckSurvivingGlobalObjectsCount(int expected) {
-  // 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.
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
-  int count = GetGlobalObjectsCount();
-#ifdef DEBUG
-  if (count != expected) CcTest::heap()->TracePathToGlobal();
-#endif
-  CHECK_EQ(expected, count);
-}
+  // Start with a clean slate.
+  heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
 
+  {
+    v8::HandleScope scope(isolate);
+    i::HashMap code(MatchPointers);
+    code_map = &code;
 
-TEST(DontLeakGlobalObjects) {
-  // Regression test for issues 1139850 and 1174891.
+    i::HashMap lineinfo(MatchPointers);
+    jitcode_line_info = &lineinfo;
 
-  i::FLAG_expose_gc = true;
-  v8::V8::Initialize();
+    saw_bar = 0;
+    move_events = 0;
 
-  for (int i = 0; i < 5; i++) {
-    { v8::HandleScope scope(CcTest::isolate());
-      LocalContext context;
-    }
-    v8::V8::ContextDisposedNotification();
-    CheckSurvivingGlobalObjectsCount(0);
+    isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
+
+    // Generate new code objects sparsely distributed across several
+    // different fragmented code-space pages.
+    const int kIterations = 10;
+    for (int i = 0; i < kIterations; ++i) {
+      LocalContext env(isolate);
+      i::AlwaysAllocateScope always_allocate(i_isolate);
+      SimulateFullSpace(heap->code_space());
+      CompileRun(script);
 
-    { v8::HandleScope scope(CcTest::isolate());
-      LocalContext context;
-      v8_compile("Date")->Run();
-    }
-    v8::V8::ContextDisposedNotification();
-    CheckSurvivingGlobalObjectsCount(0);
+      // Keep a strong reference to the code object in the handle scope.
+      i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
+          v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
+      i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
+          v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
 
-    { v8::HandleScope scope(CcTest::isolate());
-      LocalContext context;
-      v8_compile("/aaa/")->Run();
+      // Clear the compilation cache to get more wastage.
+      reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
     }
-    v8::V8::ContextDisposedNotification();
-    CheckSurvivingGlobalObjectsCount(0);
 
-    { v8::HandleScope scope(CcTest::isolate());
-      const char* extension_list[] = { "v8/gc" };
-      v8::ExtensionConfiguration extensions(1, extension_list);
-      LocalContext context(&extensions);
-      v8_compile("gc();")->Run();
-    }
-    v8::V8::ContextDisposedNotification();
-    CheckSurvivingGlobalObjectsCount(0);
-  }
-}
+    // Force code movement.
+    heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
 
+    isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
 
-TEST(CopyablePersistent) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  i::GlobalHandles* globals =
-      reinterpret_cast<i::Isolate*>(isolate)->global_handles();
-  int initial_handles = globals->global_handles_count();
-  typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
-      CopyableObject;
-  {
-    CopyableObject handle1;
-    {
-      v8::HandleScope scope(isolate);
-      handle1.Reset(isolate, v8::Object::New(isolate));
-    }
-    CHECK_EQ(initial_handles + 1, globals->global_handles_count());
-    CopyableObject  handle2;
-    handle2 = handle1;
-    CHECK(handle1 == handle2);
-    CHECK_EQ(initial_handles + 2, globals->global_handles_count());
-    CopyableObject handle3(handle2);
-    CHECK(handle1 == handle3);
-    CHECK_EQ(initial_handles + 3, globals->global_handles_count());
-  }
-  // Verify autodispose
-  CHECK_EQ(initial_handles, globals->global_handles_count());
-}
+    CHECK_LE(kIterations, saw_bar);
+    CHECK_LT(0, move_events);
 
+    code_map = NULL;
+    jitcode_line_info = NULL;
+  }
 
-static void WeakApiCallback(
-    const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
-  Local<Value> value = data.GetValue()->Get(v8_str("key"));
-  CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
-  data.GetParameter()->Reset();
-  delete data.GetParameter();
-}
+  isolate->Exit();
+  isolate->Dispose();
 
+  // Do this in a new isolate.
+  isolate = v8::Isolate::New(create_params);
+  isolate->Enter();
 
-TEST(WeakCallbackApi) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  i::GlobalHandles* globals =
-      reinterpret_cast<i::Isolate*>(isolate)->global_handles();
-  int initial_handles = globals->global_handles_count();
+  // Verify that we get callbacks for existing code objects when we
+  // request enumeration of existing code.
   {
     v8::HandleScope scope(isolate);
-    v8::Local<v8::Object> obj = v8::Object::New(isolate);
-    obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
-    v8::Persistent<v8::Object>* handle =
-        new v8::Persistent<v8::Object>(isolate, obj);
-    handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
-                                                             WeakApiCallback);
-  }
-  reinterpret_cast<i::Isolate*>(isolate)->heap()->
-      CollectAllGarbage(i::Heap::kNoGCFlags);
-  // Verify disposed.
-  CHECK_EQ(initial_handles, globals->global_handles_count());
-}
-
+    LocalContext env(isolate);
+    CompileRun(script);
 
-v8::Persistent<v8::Object> some_object;
-v8::Persistent<v8::Object> bad_handle;
+    // Now get code through initial iteration.
+    i::HashMap code(MatchPointers);
+    code_map = &code;
 
-void NewPersistentHandleCallback(
-    const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
-  v8::HandleScope scope(data.GetIsolate());
-  bad_handle.Reset(data.GetIsolate(), some_object);
-  data.GetParameter()->Reset();
-}
+    i::HashMap lineinfo(MatchPointers);
+    jitcode_line_info = &lineinfo;
 
+    isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
+                                    event_handler);
+    isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
 
-THREADED_TEST(NewPersistentHandleFromWeakCallback) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
+    jitcode_line_info = NULL;
+    // We expect that we got some events. Note that if we could get code removal
+    // notifications, we could compare two collections, one created by listening
+    // from the time of creation of an isolate, and the other by subscribing
+    // with EnumExisting.
+    CHECK_LT(0u, code.occupancy());
 
-  v8::Persistent<v8::Object> handle1, handle2;
-  {
-    v8::HandleScope scope(isolate);
-    some_object.Reset(isolate, v8::Object::New(isolate));
-    handle1.Reset(isolate, v8::Object::New(isolate));
-    handle2.Reset(isolate, v8::Object::New(isolate));
+    code_map = NULL;
   }
-  // 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.SetWeak(&handle1, NewPersistentHandleCallback);
-  handle2.Reset();
-  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
-}
 
+  isolate->Exit();
+  isolate->Dispose();
+}
 
-v8::Persistent<v8::Object> to_be_disposed;
 
-void DisposeAndForceGcCallback(
-    const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
-  to_be_disposed.Reset();
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  data.GetParameter()->Reset();
+THREADED_TEST(ExternalAllocatedMemory) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope outer(isolate);
+  v8::Local<Context> env(Context::New(isolate));
+  CHECK(!env.IsEmpty());
+  const int64_t kSize = 1024*1024;
+  int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
+  CHECK_EQ(baseline + kSize,
+           isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
+  CHECK_EQ(baseline,
+           isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
+  const int64_t kTriggerGCSize =
+      v8::internal::Internals::kExternalAllocationLimit + 1;
+  CHECK_EQ(baseline + kTriggerGCSize,
+           isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
+  CHECK_EQ(baseline,
+           isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
 }
 
 
-THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
+// 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) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
-
-  v8::Persistent<v8::Object> handle1, handle2;
-  {
-    v8::HandleScope scope(isolate);
-    handle1.Reset(isolate, v8::Object::New(isolate));
-    handle2.Reset(isolate, v8::Object::New(isolate));
+  v8::HandleScope outer(isolate);
+  static v8::Persistent<v8::ObjectTemplate> templ;
+  if (templ.IsEmpty()) {
+    v8::EscapableHandleScope inner(isolate);
+    v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
+    local->SetInternalFieldCount(1);
+    templ.Reset(isolate, inner.Escape(local));
   }
-  handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
-  to_be_disposed.Reset(isolate, handle2);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+  v8::Handle<v8::Object> result =
+      v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
+  CHECK_EQ(1, result->InternalFieldCount());
 }
 
-void DisposingCallback(
-    const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
-  data.GetParameter()->Reset();
+
+// If part of the threaded tests, this test makes ThreadingTest fail
+// on mac.
+TEST(CatchStackOverflow) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::TryCatch try_catch(context->GetIsolate());
+  v8::Handle<v8::Value> result = CompileRun(
+    "function f() {"
+    "  return f();"
+    "}"
+    ""
+    "f();");
+  CHECK(result.IsEmpty());
 }
 
-void HandleCreatingCallback(
-    const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
-  v8::HandleScope scope(data.GetIsolate());
-  v8::Persistent<v8::Object>(data.GetIsolate(),
-                             v8::Object::New(data.GetIsolate()));
-  data.GetParameter()->Reset();
+
+static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
+                                    const char* resource_name,
+                                    int line_offset) {
+  v8::HandleScope scope(CcTest::isolate());
+  v8::TryCatch try_catch(CcTest::isolate());
+  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::Utf8Value line(message->GetSourceLine());
+  CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
+  v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
+  CHECK_EQ(0, strcmp(resource_name, *name));
 }
 
 
-THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
+THREADED_TEST(TryCatchSourceInfo) {
   LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(context->GetIsolate());
+  v8::Local<v8::String> source = v8_str(
+      "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");
 
-  v8::Persistent<v8::Object> handle1, handle2, handle3;
-  {
-    v8::HandleScope scope(isolate);
-    handle3.Reset(isolate, v8::Object::New(isolate));
-    handle2.Reset(isolate, v8::Object::New(isolate));
-    handle1.Reset(isolate, v8::Object::New(isolate));
-  }
-  handle2.SetWeak(&handle2, DisposingCallback);
-  handle3.SetWeak(&handle3, HandleCreatingCallback);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
-}
+  const char* resource_name;
+  v8::Handle<v8::Script> script;
+  resource_name = "test.js";
+  script = CompileWithOrigin(source, resource_name);
+  CheckTryCatchSourceInfo(script, resource_name, 0);
 
+  resource_name = "test1.js";
+  v8::ScriptOrigin origin1(
+      v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
+  script = v8::Script::Compile(source, &origin1);
+  CheckTryCatchSourceInfo(script, resource_name, 0);
 
-THREADED_TEST(CheckForCrossContextObjectLiterals) {
-  v8::V8::Initialize();
+  resource_name = "test2.js";
+  v8::ScriptOrigin origin2(
+      v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
+      v8::Integer::New(context->GetIsolate(), 7));
+  script = v8::Script::Compile(source, &origin2);
+  CheckTryCatchSourceInfo(script, resource_name, 7);
+}
 
-  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(CcTest::isolate());
-      LocalContext context;
-      CompileRun(source);
-    }
-    { v8::HandleScope scope(CcTest::isolate());
-      LocalContext context;
-      CompileRun(source);
-    }
-  }
+THREADED_TEST(TryCatchSourceInfoForEOSError) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::TryCatch try_catch(context->GetIsolate());
+  v8::Script::Compile(v8_str("!\n"));
+  CHECK(try_catch.HasCaught());
+  v8::Handle<v8::Message> message = try_catch.Message();
+  CHECK_EQ(1, message->GetLineNumber());
+  CHECK_EQ(0, message->GetStartColumn());
 }
 
 
-static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
-  v8::EscapableHandleScope inner(env->GetIsolate());
-  env->Enter();
-  v8::Local<Value> three = v8_num(3);
-  v8::Local<Value> value = inner.Escape(three);
-  env->Exit();
-  return value;
+THREADED_TEST(CompilationCache) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::Handle<v8::String> source0 =
+      v8::String::NewFromUtf8(context->GetIsolate(), "1234");
+  v8::Handle<v8::String> source1 =
+      v8::String::NewFromUtf8(context->GetIsolate(), "1234");
+  v8::Handle<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
+  v8::Handle<v8::Script> script1 = CompileWithOrigin(source1, "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());
 }
 
 
-THREADED_TEST(NestedHandleScopeAndContexts) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope outer(isolate);
-  v8::Local<Context> env = Context::New(isolate);
-  env->Enter();
-  v8::Handle<Value> value = NestedScope(env);
-  v8::Handle<String> str(value->ToString());
-  CHECK(!str.IsEmpty());
-  env->Exit();
+static void FunctionNameCallback(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
+  args.GetReturnValue().Set(v8_num(42));
 }
 
 
-static bool MatchPointers(void* key1, void* key2) {
-  return key1 == key2;
+THREADED_TEST(CallbackFunctionName) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
+  t->Set(v8_str("asdf"),
+         v8::FunctionTemplate::New(isolate, FunctionNameCallback));
+  context->Global()->Set(v8_str("obj"), t->NewInstance());
+  v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
+  CHECK(value->IsString());
+  v8::String::Utf8Value name(value);
+  CHECK_EQ(0, strcmp("asdf", *name));
 }
 
 
-struct SymbolInfo {
-  size_t id;
-  size_t size;
-  std::string name;
-};
+THREADED_TEST(DateAccess) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::Handle<v8::Value> date =
+      v8::Date::New(context->GetIsolate(), 1224744689038.0);
+  CHECK(date->IsDate());
+  CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
+}
 
 
-class SetFunctionEntryHookTest {
- public:
-  SetFunctionEntryHookTest() {
-    CHECK(instance_ == NULL);
-    instance_ = this;
-  }
-  ~SetFunctionEntryHookTest() {
-    CHECK(instance_ == this);
-    instance_ = NULL;
-  }
-  void Reset() {
-    symbols_.clear();
-    symbol_locations_.clear();
-    invocations_.clear();
-  }
-  void RunTest();
-  void OnJitEvent(const v8::JitCodeEvent* event);
-  static void JitEvent(const v8::JitCodeEvent* event) {
-    CHECK(instance_ != NULL);
-    instance_->OnJitEvent(event);
+void CheckProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
+                     unsigned elmc, const char* elmv[]) {
+  v8::Handle<v8::Object> obj = val.As<v8::Object>();
+  v8::Handle<v8::Array> props = obj->GetPropertyNames();
+  CHECK_EQ(elmc, props->Length());
+  for (unsigned i = 0; i < elmc; i++) {
+    v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
+    CHECK_EQ(0, strcmp(elmv[i], *elm));
   }
+}
 
-  void OnEntryHook(uintptr_t function,
-                   uintptr_t return_addr_location);
-  static void EntryHook(uintptr_t function,
-                        uintptr_t return_addr_location) {
-    CHECK(instance_ != NULL);
-    instance_->OnEntryHook(function, return_addr_location);
-  }
 
-  static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
-    CHECK(instance_ != NULL);
-    args.GetReturnValue().Set(v8_num(42));
+void CheckOwnProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
+                        unsigned elmc, const char* elmv[]) {
+  v8::Handle<v8::Object> obj = val.As<v8::Object>();
+  v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
+  CHECK_EQ(elmc, props->Length());
+  for (unsigned i = 0; i < elmc; i++) {
+    v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
+    CHECK_EQ(0, strcmp(elmv[i], *elm));
   }
-  void RunLoopInNewEnv(v8::Isolate* isolate);
-
-  // Records addr as location of symbol.
-  void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
-
-  // Finds the symbol containing addr
-  SymbolInfo* FindSymbolForAddr(i::Address addr);
-  // Returns the number of invocations where the caller name contains
-  // \p caller_name and the function name contains \p function_name.
-  int CountInvocations(const char* caller_name,
-                       const char* function_name);
-
-  i::Handle<i::JSFunction> foo_func_;
-  i::Handle<i::JSFunction> bar_func_;
-
-  typedef std::map<size_t, SymbolInfo> SymbolMap;
-  typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
-  typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
-  SymbolMap symbols_;
-  SymbolLocationMap symbol_locations_;
-  InvocationMap invocations_;
-
-  static SetFunctionEntryHookTest* instance_;
-};
-SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
-
-
-// Returns true if addr is in the range [start, start+len).
-static bool Overlaps(i::Address start, size_t len, i::Address addr) {
-  if (start <= addr && start + len > addr)
-    return true;
-
-  return false;
 }
 
-void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
-                                              SymbolInfo* symbol) {
-  // Insert the symbol at the new location.
-  SymbolLocationMap::iterator it =
-      symbol_locations_.insert(std::make_pair(addr, symbol)).first;
-  // Now erase symbols to the left and right that overlap this one.
-  while (it != symbol_locations_.begin()) {
-    SymbolLocationMap::iterator left = it;
-    --left;
-    if (!Overlaps(left->first, left->second->size, addr))
-      break;
-    symbol_locations_.erase(left);
-  }
 
-  // Now erase symbols to the left and right that overlap this one.
-  while (true) {
-    SymbolLocationMap::iterator right = it;
-    ++right;
-    if (right == symbol_locations_.end())
-        break;
-    if (!Overlaps(addr, symbol->size, right->first))
-      break;
-    symbol_locations_.erase(right);
-  }
+THREADED_TEST(PropertyEnumeration) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::Value> obj = CompileRun(
+      "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;");
+  v8::Handle<v8::Array> elms = obj.As<v8::Array>();
+  CHECK_EQ(4u, elms->Length());
+  int elmc0 = 0;
+  const char** elmv0 = NULL;
+  CheckProperties(
+      isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
+  CheckOwnProperties(
+      isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
+  int elmc1 = 2;
+  const char* elmv1[] = {"a", "b"};
+  CheckProperties(
+      isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
+  CheckOwnProperties(
+      isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
+  int elmc2 = 3;
+  const char* elmv2[] = {"0", "1", "2"};
+  CheckProperties(
+      isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
+  CheckOwnProperties(
+      isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
+  int elmc3 = 4;
+  const char* elmv3[] = {"w", "z", "x", "y"};
+  CheckProperties(
+      isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
+  int elmc4 = 2;
+  const char* elmv4[] = {"w", "z"};
+  CheckOwnProperties(
+      isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
 }
 
 
-void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
-  switch (event->type) {
-    case v8::JitCodeEvent::CODE_ADDED: {
-        CHECK(event->code_start != NULL);
-        CHECK_NE(0, static_cast<int>(event->code_len));
-        CHECK(event->name.str != NULL);
-        size_t symbol_id = symbols_.size();
+THREADED_TEST(PropertyEnumeration2) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::Value> obj = CompileRun(
+      "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;");
+  v8::Handle<v8::Array> elms = obj.As<v8::Array>();
+  CHECK_EQ(4u, elms->Length());
+  int elmc0 = 0;
+  const char** elmv0 = NULL;
+  CheckProperties(isolate,
+                  elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
 
-        // Record the new symbol.
-        SymbolInfo& info = symbols_[symbol_id];
-        info.id = symbol_id;
-        info.size = event->code_len;
-        info.name.assign(event->name.str, event->name.str + event->name.len);
+  v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
+  v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
+  CHECK_EQ(0u, props->Length());
+  for (uint32_t i = 0; i < props->Length(); i++) {
+    printf("p[%u]\n", i);
+  }
+}
 
-        // And record it's location.
-        InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
-      }
-      break;
 
-    case v8::JitCodeEvent::CODE_MOVED: {
-        // We would like to never see code move that we haven't seen before,
-        // but the code creation event does not happen until the line endings
-        // have been calculated (this is so that we can report the line in the
-        // script at which the function source is found, see
-        // Compiler::RecordFunctionCompilation) and the line endings
-        // calculations can cause a GC, which can move the newly created code
-        // before its existence can be logged.
-        SymbolLocationMap::iterator it(
-            symbol_locations_.find(
-                reinterpret_cast<i::Address>(event->code_start)));
-        if (it != symbol_locations_.end()) {
-          // Found a symbol at this location, move it.
-          SymbolInfo* info = it->second;
-          symbol_locations_.erase(it);
-          InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
-                         info);
-        }
+THREADED_TEST(AccessChecksReenabledCorrectly) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
+  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(isolate, k));
       }
-    default:
-      break;
+    }
   }
-}
-
-void SetFunctionEntryHookTest::OnEntryHook(
-    uintptr_t function, uintptr_t return_addr_location) {
-  // Get the function's code object.
-  i::Code* function_code = i::Code::GetCodeFromTargetAddress(
-      reinterpret_cast<i::Address>(function));
-  CHECK(function_code != NULL);
 
-  // Then try and look up the caller's code object.
-  i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
+  Local<v8::Object> instance_1 = templ->NewInstance();
+  context->Global()->Set(v8_str("obj_1"), instance_1);
 
-  // Count the invocation.
-  SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
-  SymbolInfo* function_symbol =
-      FindSymbolForAddr(reinterpret_cast<i::Address>(function));
-  ++invocations_[std::make_pair(caller_symbol, function_symbol)];
+  Local<Value> value_1 = CompileRun("obj_1.a");
+  CHECK(value_1.IsEmpty());
 
-  if (!bar_func_.is_null() && function_code == bar_func_->code()) {
-    // Check that we have a symbol for the "bar" function at the right location.
-    SymbolLocationMap::iterator it(
-        symbol_locations_.find(function_code->instruction_start()));
-    CHECK(it != symbol_locations_.end());
-  }
+  Local<v8::Object> instance_2 = templ->NewInstance();
+  context->Global()->Set(v8_str("obj_2"), instance_2);
 
-  if (!foo_func_.is_null() && function_code == foo_func_->code()) {
-    // Check that we have a symbol for "foo" at the right location.
-    SymbolLocationMap::iterator it(
-        symbol_locations_.find(function_code->instruction_start()));
-    CHECK(it != symbol_locations_.end());
-  }
+  Local<Value> value_2 = CompileRun("obj_2.a");
+  CHECK(value_2.IsEmpty());
 }
 
 
-SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
-  SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
-  // Do we have a direct hit on a symbol?
-  if (it != symbol_locations_.end()) {
-    if (it->first == addr)
-      return it->second;
-  }
+// Tests that ScriptData can be serialized and deserialized.
+TEST(PreCompileSerialization) {
+  v8::V8::Initialize();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  HandleScope handle_scope(isolate);
 
-  // If not a direct hit, it'll have to be the previous symbol.
-  if (it == symbol_locations_.begin())
-    return NULL;
+  i::FLAG_min_preparse_length = 0;
+  const char* script = "function foo(a) { return a+1; }";
+  v8::ScriptCompiler::Source source(v8_str(script));
+  v8::ScriptCompiler::Compile(isolate, &source,
+                              v8::ScriptCompiler::kProduceParserCache);
+  // Serialize.
+  const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
+  i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
+  i::MemCopy(serialized_data, cd->data, cd->length);
 
-  --it;
-  size_t offs = addr - it->first;
-  if (offs < it->second->size)
-    return it->second;
+  // Deserialize.
+  i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
 
-  return NULL;
+  // Verify that the original is the same as the deserialized.
+  CHECK_EQ(cd->length, deserialized->length());
+  CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
+
+  delete deserialized;
+  i::DeleteArray(serialized_data);
 }
 
 
-int SetFunctionEntryHookTest::CountInvocations(
-    const char* caller_name, const char* function_name) {
-  InvocationMap::iterator it(invocations_.begin());
-  int invocations = 0;
-  for (; it != invocations_.end(); ++it) {
-    SymbolInfo* caller = it->first.first;
-    SymbolInfo* function = it->first.second;
+// 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(CcTest::isolate());
+  // Test LoadIC.
+  for (int i = 0; i < 2; i++) {
+    LocalContext context;
+    context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
+    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(CcTest::isolate()));
+    context->Global()->Delete(v8_str("tmp"));
+    CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
+  }
+}
 
-    // Filter out non-matching functions.
-    if (function_name != NULL) {
-      if (function->name.find(function_name) == std::string::npos)
-        continue;
-    }
 
-    // Filter out non-matching callers.
-    if (caller_name != NULL) {
-      if (caller == NULL)
-        continue;
-      if (caller->name.find(caller_name) == std::string::npos)
-        continue;
-    }
+// Test that cross-context new calls use the context of the callee to
+// create the new JavaScript object.
+THREADED_TEST(CrossContextNew) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Local<Context> context0 = Context::New(isolate);
+  v8::Local<Context> context1 = Context::New(isolate);
 
-    // It matches add the invocation count to the tally.
-    invocations += it->second;
-  }
+  // Allow cross-domain access.
+  Local<String> token = v8_str("<security token>");
+  context0->SetSecurityToken(token);
+  context1->SetSecurityToken(token);
 
-  return invocations;
-}
+  // 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();
+}
 
-void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
-  v8::HandleScope outer(isolate);
-  v8::Local<Context> env = Context::New(isolate);
-  env->Enter();
 
-  Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
-  t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
-  env->Global()->Set(v8_str("obj"), t->NewInstance());
+// Verify that we can clone an object
+TEST(ObjectClone) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
 
-  const char* script =
-      "function bar() {\n"
-      "  var sum = 0;\n"
-      "  for (i = 0; i < 100; ++i)\n"
-      "    sum = foo(i);\n"
-      "  return sum;\n"
-      "}\n"
-      "function foo(i) { return i * i; }\n"
-      "// Invoke on the runtime function.\n"
-      "obj.asdf()";
-  CompileRun(script);
-  bar_func_ = i::Handle<i::JSFunction>::cast(
-          v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
-  ASSERT(!bar_func_.is_null());
+  const char* sample =
+    "var rv = {};"      \
+    "rv.alpha = 'hello';" \
+    "rv.beta = 123;"     \
+    "rv;";
 
-  foo_func_ =
-      i::Handle<i::JSFunction>::cast(
-           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
-  ASSERT(!foo_func_.is_null());
+  // Create an object, verify basics.
+  Local<Value> val = CompileRun(sample);
+  CHECK(val->IsObject());
+  Local<v8::Object> obj = val.As<v8::Object>();
+  obj->Set(v8_str("gamma"), v8_str("cloneme"));
 
-  v8::Handle<v8::Value> value = CompileRun("bar();");
-  CHECK(value->IsNumber());
-  CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
+  CHECK(v8_str("hello")->Equals(obj->Get(v8_str("alpha"))));
+  CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
+  CHECK(v8_str("cloneme")->Equals(obj->Get(v8_str("gamma"))));
 
-  // Test the optimized codegen path.
-  value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
-                     "bar();");
-  CHECK(value->IsNumber());
-  CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
+  // Clone it.
+  Local<v8::Object> clone = obj->Clone();
+  CHECK(v8_str("hello")->Equals(clone->Get(v8_str("alpha"))));
+  CHECK(v8::Integer::New(isolate, 123)->Equals(clone->Get(v8_str("beta"))));
+  CHECK(v8_str("cloneme")->Equals(clone->Get(v8_str("gamma"))));
 
-  env->Exit();
+  // Set a property on the clone, verify each object.
+  clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
+  CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
+  CHECK(v8::Integer::New(isolate, 456)->Equals(clone->Get(v8_str("beta"))));
 }
 
 
-void SetFunctionEntryHookTest::RunTest() {
-  // Work in a new isolate throughout.
-  v8::Isolate* isolate = v8::Isolate::New();
+class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
+ public:
+  explicit OneByteVectorResource(i::Vector<const char> vector)
+      : data_(vector) {}
+  virtual ~OneByteVectorResource() {}
+  virtual size_t length() const { return data_.length(); }
+  virtual const char* data() const { return data_.start(); }
+ private:
+  i::Vector<const char> data_;
+};
 
-  // Test setting the entry hook on the new isolate.
-  CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
 
-  // Replacing the hook, once set should fail.
-  CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
+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_;
+};
 
-  {
-    v8::Isolate::Scope scope(isolate);
 
-    v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
+static void MorphAString(i::String* string,
+                         OneByteVectorResource* one_byte_resource,
+                         UC16VectorResource* uc16_resource) {
+  CHECK(i::StringShape(string).IsExternal());
+  if (string->IsOneByteRepresentation()) {
+    // Check old map is not internalized or long.
+    CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
+    // Morph external string to be TwoByte string.
+    string->set_map(CcTest::heap()->external_string_map());
+    i::ExternalTwoByteString* morphed =
+         i::ExternalTwoByteString::cast(string);
+    morphed->set_resource(uc16_resource);
+  } else {
+    // Check old map is not internalized or long.
+    CHECK(string->map() == CcTest::heap()->external_string_map());
+    // Morph external string to be one-byte string.
+    string->set_map(CcTest::heap()->external_one_byte_string_map());
+    i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
+    morphed->set_resource(one_byte_resource);
+  }
+}
 
-    RunLoopInNewEnv(isolate);
 
-    // Check the exepected invocation counts.
-    CHECK_EQ(2, CountInvocations(NULL, "bar"));
-    CHECK_EQ(200, CountInvocations("bar", "foo"));
-    CHECK_EQ(200, CountInvocations(NULL, "foo"));
+// 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) {
+  char utf_buffer[129];
+  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);
+  {
+    LocalContext env;
+    i::Factory* factory = CcTest::i_isolate()->factory();
+    v8::HandleScope scope(env->GetIsolate());
+    OneByteVectorResource one_byte_resource(
+        i::Vector<const char>(c_string, i::StrLength(c_string)));
+    UC16VectorResource uc16_resource(
+        i::Vector<const uint16_t>(two_byte_string,
+                                  i::StrLength(c_string)));
 
-    // Verify that we have an entry hook on some specific stubs.
-    CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
-    CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
-    CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
-  }
-  isolate->Dispose();
+    Local<String> lhs(
+        v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
+                                        &one_byte_resource).ToHandleChecked()));
+    Local<String> rhs(
+        v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
+                                        &one_byte_resource).ToHandleChecked()));
 
-  Reset();
+    env->Global()->Set(v8_str("lhs"), lhs);
+    env->Global()->Set(v8_str("rhs"), rhs);
 
-  // Make sure a second isolate is unaffected by the previous entry hook.
-  isolate = v8::Isolate::New();
-  {
-    v8::Isolate::Scope scope(isolate);
+    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);");
 
-    // Reset the entry count to zero and set the entry hook.
-    RunLoopInNewEnv(isolate);
+    CHECK(lhs->IsOneByte());
+    CHECK(rhs->IsOneByte());
 
-    // We should record no invocations in this isolate.
-    CHECK_EQ(0, static_cast<int>(invocations_.size()));
-  }
-  // Since the isolate has been used, we shouldn't be able to set an entry
-  // hook anymore.
-  CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
+    MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
+                 &uc16_resource);
+    MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
+                 &uc16_resource);
 
-  isolate->Dispose();
+    // This should UTF-8 without flattening, since everything is ASCII.
+    Handle<String> cons = v8_compile("cons")->Run().As<String>();
+    CHECK_EQ(128, cons->Utf8Length());
+    int nchars = -1;
+    CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
+    CHECK_EQ(128, nchars);
+    CHECK_EQ(0, strcmp(
+        utf_buffer,
+        "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"));
+
+    // 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(String::NewFromUtf8(env->GetIsolate(), expected_cons)
+              ->Equals(env->Global()->Get(v8_str("cons"))));
+    CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice)
+              ->Equals(env->Global()->Get(v8_str("slice"))));
+    CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons)
+              ->Equals(env->Global()->Get(v8_str("slice_on_cons"))));
+  }
+  i::DeleteArray(two_byte_string);
 }
 
 
-TEST(SetFunctionEntryHook) {
-  // FunctionEntryHook does not work well with experimental natives.
-  // Experimental natives are compiled during snapshot deserialization.
-  // This test breaks because InstallGetter (function from snapshot that
-  // only gets called from experimental natives) is compiled with entry hooks.
-  i::FLAG_allow_natives_syntax = true;
-  i::FLAG_use_inlining = false;
+TEST(CompileExternalTwoByteSource) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
-  SetFunctionEntryHookTest test;
-  test.RunTest();
+  // This is a very short list of sources, which currently is to check for a
+  // regression caused by r2703.
+  const char* one_byte_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; one_byte_sources[i] != NULL; i++) {
+    uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
+    TestResource* uc16_resource = new TestResource(two_byte_string);
+    v8::Local<v8::String> source =
+        v8::String::NewExternal(context->GetIsolate(), uc16_resource);
+    v8::Script::Compile(source);
+  }
 }
 
 
-static i::HashMap* code_map = NULL;
-static i::HashMap* jitcode_line_info = NULL;
-static int saw_bar = 0;
-static int move_events = 0;
+#ifndef V8_INTERPRETED_REGEXP
 
+struct RegExpInterruptionData {
+  v8::base::Atomic32 loop_count;
+  UC16VectorResource* string_resource;
+  v8::Persistent<v8::String> string;
+} regexp_interruption_data;
 
-static bool FunctionNameIs(const char* expected,
-                           const v8::JitCodeEvent* event) {
-  // Log lines for functions are of the general form:
-  // "LazyCompile:<type><function_name>", where the type is one of
-  // "*", "~" or "".
-  static const char kPreamble[] = "LazyCompile:";
-  static size_t kPreambleLen = sizeof(kPreamble) - 1;
 
-  if (event->name.len < sizeof(kPreamble) - 1 ||
-      strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
-    return false;
-  }
+class RegExpInterruptionThread : public v8::base::Thread {
+ public:
+  explicit RegExpInterruptionThread(v8::Isolate* isolate)
+      : Thread(Options("TimeoutThread")), isolate_(isolate) {}
 
-  const char* tail = event->name.str + kPreambleLen;
-  size_t tail_len = event->name.len - kPreambleLen;
-  size_t expected_len = strlen(expected);
-  if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
-    --tail_len;
-    ++tail;
+  virtual void Run() {
+    for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
+         v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
+         v8::base::NoBarrier_AtomicIncrement(
+             &regexp_interruption_data.loop_count, 1)) {
+      // Wait a bit before requesting GC.
+      v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
+      reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
+    }
+    // Wait a bit before terminating.
+    v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
+    v8::V8::TerminateExecution(isolate_);
   }
 
-  // Check for tails like 'bar :1'.
-  if (tail_len > expected_len + 2 &&
-      tail[expected_len] == ' ' &&
-      tail[expected_len + 1] == ':' &&
-      tail[expected_len + 2] &&
-      !strncmp(tail, expected, expected_len)) {
-    return true;
-  }
+ private:
+  v8::Isolate* isolate_;
+};
 
-  if (tail_len != expected_len)
-    return false;
 
-  return strncmp(tail, expected, expected_len) == 0;
+void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
+  if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
+    return;
+  }
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::String> string = v8::Local<v8::String>::New(
+      CcTest::isolate(), regexp_interruption_data.string);
+  string->MakeExternal(regexp_interruption_data.string_resource);
 }
 
 
-static void event_handler(const v8::JitCodeEvent* event) {
-  CHECK(event != NULL);
-  CHECK(code_map != NULL);
-  CHECK(jitcode_line_info != NULL);
-
-  class DummyJitCodeLineInfo {
-  };
-
-  switch (event->type) {
-    case v8::JitCodeEvent::CODE_ADDED: {
-        CHECK(event->code_start != NULL);
-        CHECK_NE(0, static_cast<int>(event->code_len));
-        CHECK(event->name.str != NULL);
-        i::HashMap::Entry* entry =
-            code_map->Lookup(event->code_start,
-                             i::ComputePointerHash(event->code_start),
-                             true);
-        entry->value = reinterpret_cast<void*>(event->code_len);
-
-        if (FunctionNameIs("bar", event)) {
-          ++saw_bar;
-        }
-      }
-      break;
+// Test that RegExp execution can be interrupted.  Specifically, we test
+// * interrupting with GC
+// * turn the subject string from one-byte internal to two-byte external string
+// * force termination
+TEST(RegExpInterruption) {
+  v8::HandleScope scope(CcTest::isolate());
+  LocalContext env;
 
-    case v8::JitCodeEvent::CODE_MOVED: {
-        uint32_t hash = i::ComputePointerHash(event->code_start);
-        // We would like to never see code move that we haven't seen before,
-        // but the code creation event does not happen until the line endings
-        // have been calculated (this is so that we can report the line in the
-        // script at which the function source is found, see
-        // Compiler::RecordFunctionCompilation) and the line endings
-        // calculations can cause a GC, which can move the newly created code
-        // before its existence can be logged.
-        i::HashMap::Entry* entry =
-            code_map->Lookup(event->code_start, hash, false);
-        if (entry != NULL) {
-          ++move_events;
+  RegExpInterruptionThread timeout_thread(CcTest::isolate());
 
-          CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
-          code_map->Remove(event->code_start, hash);
+  v8::V8::AddGCPrologueCallback(RunBeforeGC);
+  static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+  i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
+  v8::Local<v8::String> string = v8_str(one_byte_content);
 
-          entry = code_map->Lookup(event->new_code_start,
-                                   i::ComputePointerHash(event->new_code_start),
-                                   true);
-          CHECK(entry != NULL);
-          entry->value = reinterpret_cast<void*>(event->code_len);
-        }
-      }
-      break;
+  CcTest::global()->Set(v8_str("a"), string);
+  regexp_interruption_data.string.Reset(CcTest::isolate(), string);
+  regexp_interruption_data.string_resource = new UC16VectorResource(
+      i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
 
-    case v8::JitCodeEvent::CODE_REMOVED:
-      // Object/code removal events are currently not dispatched from the GC.
-      CHECK(false);
-      break;
+  v8::TryCatch try_catch(CcTest::isolate());
+  timeout_thread.Start();
 
-    // For CODE_START_LINE_INFO_RECORDING event, we will create one
-    // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
-    // record it in jitcode_line_info.
-    case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
-        DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
-        v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
-        temp_event->user_data = line_info;
-        i::HashMap::Entry* entry =
-            jitcode_line_info->Lookup(line_info,
-                                      i::ComputePointerHash(line_info),
-                                      true);
-        entry->value = reinterpret_cast<void*>(line_info);
-      }
-      break;
-    // For these two events, we will check whether the event->user_data
-    // data structure is created before during CODE_START_LINE_INFO_RECORDING
-    // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
-    case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
-        CHECK(event->user_data != NULL);
-        uint32_t hash = i::ComputePointerHash(event->user_data);
-        i::HashMap::Entry* entry =
-            jitcode_line_info->Lookup(event->user_data, hash, false);
-        CHECK(entry != NULL);
-        delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
-      }
-      break;
+  CompileRun("/((a*)*)*b/.exec(a)");
+  CHECK(try_catch.HasTerminated());
 
-    case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
-        CHECK(event->user_data != NULL);
-        uint32_t hash = i::ComputePointerHash(event->user_data);
-        i::HashMap::Entry* entry =
-            jitcode_line_info->Lookup(event->user_data, hash, false);
-        CHECK(entry != NULL);
-      }
-      break;
+  timeout_thread.Join();
 
-    default:
-      // Impossible event.
-      CHECK(false);
-      break;
-  }
+  regexp_interruption_data.string.Reset();
+  i::DeleteArray(uc16_content);
 }
 
+#endif  // V8_INTERPRETED_REGEXP
 
-UNINITIALIZED_TEST(SetJitCodeEventHandler) {
-  i::FLAG_stress_compaction = true;
-  i::FLAG_incremental_marking = false;
-  const char* script =
-    "function bar() {"
-    "  var sum = 0;"
-    "  for (i = 0; i < 100; ++i)"
-    "    sum = foo(i);"
-    "  return sum;"
-    "}"
-    "function foo(i) { return i * i; };"
-    "bar();";
-
-  // Run this test in a new isolate to make sure we don't
-  // have remnants of state from other code.
-  v8::Isolate* isolate = v8::Isolate::New();
-  isolate->Enter();
-  i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
 
-  {
-    v8::HandleScope scope(isolate);
-    i::HashMap code(MatchPointers);
-    code_map = &code;
+// Test that we cannot set a property on the global object if there
+// is a read-only property in the prototype chain.
+TEST(ReadOnlyPropertyInGlobalProto) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+  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->ForceSet(v8_str("x"), v8::Integer::New(isolate, 0),
+                         v8::ReadOnly);
+  global_proto->ForceSet(v8_str("y"), v8::Integer::New(isolate, 0),
+                         v8::ReadOnly);
+  // Check without 'eval' or 'with'.
+  v8::Handle<v8::Value> res =
+      CompileRun("function f() { x = 42; return x; }; f()");
+  CHECK(v8::Integer::New(isolate, 0)->Equals(res));
+  // Check with 'eval'.
+  res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
+  CHECK(v8::Integer::New(isolate, 0)->Equals(res));
+  // Check with 'with'.
+  res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
+  CHECK(v8::Integer::New(isolate, 0)->Equals(res));
+}
 
-    i::HashMap lineinfo(MatchPointers);
-    jitcode_line_info = &lineinfo;
+static int force_set_set_count = 0;
+static int force_set_get_count = 0;
+bool pass_on_get = false;
 
-    saw_bar = 0;
-    move_events = 0;
+static void ForceSetGetter(v8::Local<v8::String> name,
+                           const v8::PropertyCallbackInfo<v8::Value>& info) {
+  force_set_get_count++;
+  if (pass_on_get) {
+    return;
+  }
+  info.GetReturnValue().Set(3);
+}
 
-    V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
+static void ForceSetSetter(v8::Local<v8::String> name,
+                           v8::Local<v8::Value> value,
+                           const v8::PropertyCallbackInfo<void>& info) {
+  force_set_set_count++;
+}
 
-    // Generate new code objects sparsely distributed across several
-    // different fragmented code-space pages.
-    const int kIterations = 10;
-    for (int i = 0; i < kIterations; ++i) {
-      LocalContext env(isolate);
-      i::AlwaysAllocateScope always_allocate;
-      SimulateFullSpace(heap->code_space());
-      CompileRun(script);
+static void ForceSetInterceptGetter(
+    v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  CHECK(name->IsString());
+  ForceSetGetter(Local<String>::Cast(name), info);
+}
 
-      // Keep a strong reference to the code object in the handle scope.
-      i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
-          v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
-      i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
-          v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
+static void ForceSetInterceptSetter(
+    v8::Local<v8::Name> name, v8::Local<v8::Value> value,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  force_set_set_count++;
+  info.GetReturnValue().SetUndefined();
+}
 
-      // Clear the compilation cache to get more wastage.
-      reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
-    }
 
-    // Force code movement.
-    heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
+TEST(ForceSet) {
+  force_set_get_count = 0;
+  force_set_set_count = 0;
+  pass_on_get = false;
 
-    V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+  v8::Handle<v8::String> access_property =
+      v8::String::NewFromUtf8(isolate, "a");
+  templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
+  LocalContext context(NULL, templ);
+  v8::Handle<v8::Object> global = context->Global();
 
-    CHECK_LE(kIterations, saw_bar);
-    CHECK_LT(0, move_events);
+  // Ordinary properties
+  v8::Handle<v8::String> simple_property =
+      v8::String::NewFromUtf8(isolate, "p");
+  global->ForceSet(simple_property, v8::Int32::New(isolate, 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(isolate, 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(isolate, 6));
+  CHECK_EQ(6, global->Get(simple_property)->Int32Value());
 
-    code_map = NULL;
-    jitcode_line_info = NULL;
-  }
+  // 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(isolate, 7));
+  CHECK_EQ(3, global->Get(access_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(2, force_set_get_count);
+  // ForceSet doesn't call the accessors for now.
+  // TODO(verwaest): Update once blink doesn't rely on ForceSet to delete api
+  // accessors.
+  global->ForceSet(access_property, v8::Int32::New(isolate, 8));
+  CHECK_EQ(8, global->Get(access_property)->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(2, force_set_get_count);
+}
 
-  isolate->Exit();
-  isolate->Dispose();
 
-  // Do this in a new isolate.
-  isolate = v8::Isolate::New();
-  isolate->Enter();
+TEST(ForceSetWithInterceptor) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+  templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      ForceSetInterceptGetter, ForceSetInterceptSetter));
+  pass_on_get = true;
+  LocalContext context(NULL, templ);
+  v8::Handle<v8::Object> global = context->Global();
 
-  // Verify that we get callbacks for existing code objects when we
-  // request enumeration of existing code.
-  {
-    v8::HandleScope scope(isolate);
-    LocalContext env(isolate);
-    CompileRun(script);
+  force_set_get_count = 0;
+  force_set_set_count = 0;
+  pass_on_get = false;
 
-    // Now get code through initial iteration.
-    i::HashMap code(MatchPointers);
-    code_map = &code;
+  v8::Handle<v8::String> some_property =
+      v8::String::NewFromUtf8(isolate, "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(isolate, 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(isolate, 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::NewFromUtf8(isolate, "b"))
+                  ->Int32Value());
+  CHECK_EQ(1, force_set_set_count);
+  CHECK_EQ(6, force_set_get_count);
+}
 
-    i::HashMap lineinfo(MatchPointers);
-    jitcode_line_info = &lineinfo;
 
-    V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
-    V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
+TEST(CreateDataProperty) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
 
-    jitcode_line_info = NULL;
-    // We expect that we got some events. Note that if we could get code removal
-    // notifications, we could compare two collections, one created by listening
-    // from the time of creation of an isolate, and the other by subscribing
-    // with EnumExisting.
-    CHECK_LT(0, code.occupancy());
+  CompileRun(
+      "var a = {};"
+      "var b = [];"
+      "Object.defineProperty(a, 'foo', {value: 23});"
+      "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
 
-    code_map = NULL;
+  v8::Local<v8::Object> obj =
+      v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
+  v8::Local<v8::Array> arr =
+      v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
+  {
+    // Can't change a non-configurable properties.
+    v8::TryCatch try_catch(isolate);
+    CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
+                                   v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
+                                  v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    v8::Local<v8::Value> val =
+        obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   }
 
-  isolate->Exit();
-  isolate->Dispose();
-}
+  {
+    // Set a regular property.
+    v8::TryCatch try_catch(isolate);
+    CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
+                                  v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    v8::Local<v8::Value> val =
+        obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+  }
 
+  {
+    // Set an indexed property.
+    v8::TryCatch try_catch(isolate);
+    CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
+                                  v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+  }
 
-THREADED_TEST(ExternalAllocatedMemory) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope outer(isolate);
-  v8::Local<Context> env(Context::New(isolate));
-  CHECK(!env.IsEmpty());
-  const int64_t kSize = 1024*1024;
-  int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
-  CHECK_EQ(baseline + kSize,
-           isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
-  CHECK_EQ(baseline,
-           isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
-}
+  {
+    // Special cases for arrays.
+    v8::TryCatch try_catch(isolate);
+    CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
+                                   v8::Integer::New(isolate, 1)).FromJust());
+    CHECK(!try_catch.HasCaught());
+  }
+  {
+    // Special cases for arrays: index exceeds the array's length
+    v8::TryCatch try_catch(isolate);
+    CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
+              .FromJust());
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(2U, arr->Length());
+    v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
+
+    // Set an existing entry.
+    CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
+              .FromJust());
+    CHECK(!try_catch.HasCaught());
+    val = arr->Get(env.local(), 0).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+  }
 
+  CompileRun("Object.freeze(a);");
+  {
+    // Can't change non-extensible objects.
+    v8::TryCatch try_catch(isolate);
+    CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
+                                   v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+  }
 
-// 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) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope outer(isolate);
-  static v8::Persistent<v8::ObjectTemplate> templ;
-  if (templ.IsEmpty()) {
-    v8::EscapableHandleScope inner(isolate);
-    v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
-    local->SetInternalFieldCount(1);
-    templ.Reset(isolate, inner.Escape(local));
+  v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+  templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
+  v8::Local<v8::Object> access_checked =
+      templ->NewInstance(env.local()).ToLocalChecked();
+  {
+    v8::TryCatch try_catch(isolate);
+    CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
+                                             v8::Integer::New(isolate, 42))
+              .IsNothing());
+    CHECK(try_catch.HasCaught());
   }
-  v8::Handle<v8::Object> result =
-      v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
-  CHECK_EQ(1, result->InternalFieldCount());
 }
 
 
-// If part of the threaded tests, this test makes ThreadingTest fail
-// on mac.
-TEST(CatchStackOverflow) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  v8::TryCatch try_catch;
-  v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::NewFromUtf8(
-    context->GetIsolate(),
-    "function f() {"
-    "  return f();"
-    "}"
-    ""
-    "f();"));
-  v8::Handle<v8::Value> result = script->Run();
-  CHECK(result.IsEmpty());
-}
+TEST(DefineOwnProperty) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
 
+  CompileRun(
+      "var a = {};"
+      "var b = [];"
+      "Object.defineProperty(a, 'foo', {value: 23});"
+      "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
 
-static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
-                                    const char* resource_name,
-                                    int line_offset) {
-  v8::HandleScope scope(CcTest::isolate());
-  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::Utf8Value line(message->GetSourceLine());
-  CHECK_EQ("  throw 'nirk';", *line);
-  v8::String::Utf8Value name(message->GetScriptResourceName());
-  CHECK_EQ(resource_name, *name);
-}
+  v8::Local<v8::Object> obj =
+      v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
+  v8::Local<v8::Array> arr =
+      v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
+  {
+    // Can't change a non-configurable properties.
+    v8::TryCatch try_catch(isolate);
+    CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
+                                  v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
+                                 v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    v8::Local<v8::Value> val =
+        obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+  }
 
+  {
+    // Set a regular property.
+    v8::TryCatch try_catch(isolate);
+    CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
+                                 v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    v8::Local<v8::Value> val =
+        obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+  }
 
-THREADED_TEST(TryCatchSourceInfo) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  v8::Handle<v8::String> source = v8::String::NewFromUtf8(
-      context->GetIsolate(),
-      "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");
+  {
+    // Set an indexed property.
+    v8::TryCatch try_catch(isolate);
+    CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
+                                 v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+  }
 
-  const char* resource_name;
-  v8::Handle<v8::Script> script;
-  resource_name = "test.js";
-  script = v8::Script::Compile(
-      source, v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
-  CheckTryCatchSourceInfo(script, resource_name, 0);
+  {
+    // Special cases for arrays.
+    v8::TryCatch try_catch(isolate);
+    CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
+                                  v8::Integer::New(isolate, 1)).FromJust());
+    CHECK(!try_catch.HasCaught());
+  }
+  {
+    // Special cases for arrays: index exceeds the array's length
+    v8::TryCatch try_catch(isolate);
+    CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
+                                 v8::Integer::New(isolate, 23)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(2U, arr->Length());
+    v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
+
+    // Set an existing entry.
+    CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
+                                 v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+    val = arr->Get(env.local(), 0).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+  }
 
-  resource_name = "test1.js";
-  v8::ScriptOrigin origin1(
-      v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
-  script = v8::Script::Compile(source, &origin1);
-  CheckTryCatchSourceInfo(script, resource_name, 0);
+  {
+    // Set a non-writable property.
+    v8::TryCatch try_catch(isolate);
+    CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
+                                 v8::Integer::New(isolate, 42),
+                                 v8::ReadOnly).FromJust());
+    CHECK(!try_catch.HasCaught());
+    v8::Local<v8::Value> val =
+        obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
+    CHECK(val->IsNumber());
+    CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+    CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
+                                    env.local(), v8_str("lala")).FromJust());
+    CHECK(!try_catch.HasCaught());
+  }
 
-  resource_name = "test2.js";
-  v8::ScriptOrigin origin2(
-      v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
-      v8::Integer::New(context->GetIsolate(), 7));
-  script = v8::Script::Compile(source, &origin2);
-  CheckTryCatchSourceInfo(script, resource_name, 7);
+  CompileRun("Object.freeze(a);");
+  {
+    // Can't change non-extensible objects.
+    v8::TryCatch try_catch(isolate);
+    CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
+                                  v8::Integer::New(isolate, 42)).FromJust());
+    CHECK(!try_catch.HasCaught());
+  }
+
+  v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+  templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
+  v8::Local<v8::Object> access_checked =
+      templ->NewInstance(env.local()).ToLocalChecked();
+  {
+    v8::TryCatch try_catch(isolate);
+    CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
+                                            v8::Integer::New(isolate, 42))
+              .IsNothing());
+    CHECK(try_catch.HasCaught());
+  }
 }
 
 
-THREADED_TEST(CompilationCache) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  v8::Handle<v8::String> source0 =
-      v8::String::NewFromUtf8(context->GetIsolate(), "1234");
-  v8::Handle<v8::String> source1 =
-      v8::String::NewFromUtf8(context->GetIsolate(), "1234");
-  v8::Handle<v8::Script> script0 = v8::Script::Compile(
-      source0, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
-  v8::Handle<v8::Script> script1 = v8::Script::Compile(
-      source1, v8::String::NewFromUtf8(context->GetIsolate(), "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::Local<Context> calling_context0;
+static v8::Local<Context> calling_context1;
+static v8::Local<Context> calling_context2;
 
 
-static void FunctionNameCallback(
+// 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 void GetCallingContextCallback(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
-  args.GetReturnValue().Set(v8_num(42));
+  CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
+  CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
+  CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
+  args.GetReturnValue().Set(42);
 }
 
 
-THREADED_TEST(CallbackFunctionName) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
-  t->Set(v8_str("asdf"),
-         v8::FunctionTemplate::New(isolate, FunctionNameCallback));
-  context->Global()->Set(v8_str("obj"), t->NewInstance());
-  v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
-  CHECK(value->IsString());
-  v8::String::Utf8Value name(value);
-  CHECK_EQ("asdf", *name);
+THREADED_TEST(GetCurrentContextWhenNotInContext) {
+  i::Isolate* isolate = CcTest::i_isolate();
+  CHECK(isolate != NULL);
+  CHECK(isolate->context() == NULL);
+  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
+  v8::HandleScope scope(v8_isolate);
+  // The following should not crash, but return an empty handle.
+  v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
+  CHECK(current.IsEmpty());
 }
 
 
-THREADED_TEST(DateAccess) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  v8::Handle<v8::Value> date =
-      v8::Date::New(context->GetIsolate(), 1224744689038.0);
-  CHECK(date->IsDate());
-  CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
-}
+THREADED_TEST(GetCallingContext) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
 
+  Local<Context> calling_context0(Context::New(isolate));
+  Local<Context> calling_context1(Context::New(isolate));
+  Local<Context> calling_context2(Context::New(isolate));
+  ::calling_context0 = calling_context0;
+  ::calling_context1 = calling_context1;
+  ::calling_context2 = calling_context2;
 
-void CheckProperties(v8::Isolate* isolate,
-                     v8::Handle<v8::Value> val,
-                     int elmc,
-                     const char* elmv[]) {
-  v8::Handle<v8::Object> obj = val.As<v8::Object>();
-  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(isolate, i)));
-    CHECK_EQ(elmv[i], *elm);
-  }
-}
+  // 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(isolate, GetCallingContextCallback);
+  calling_context0->Global()->Set(v8_str("callback"),
+                                  callback_templ->GetFunction());
+  calling_context0->Exit();
 
-void CheckOwnProperties(v8::Isolate* isolate,
-                        v8::Handle<v8::Value> val,
-                        int elmc,
-                        const char* elmv[]) {
-  v8::Handle<v8::Object> obj = val.As<v8::Object>();
-  v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
-  CHECK_EQ(elmc, props->Length());
-  for (int i = 0; i < elmc; i++) {
-    v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
-    CHECK_EQ(elmv[i], *elm);
-  }
+  // Expose context0 in context1 and set up 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();
+  ::calling_context0.Clear();
+  ::calling_context1.Clear();
+  ::calling_context2.Clear();
 }
 
 
-THREADED_TEST(PropertyEnumeration) {
+// Check that a variable declaration with no explicit initialization
+// value does shadow an existing property in the prototype chain.
+THREADED_TEST(InitGlobalVarInProtoChain) {
   LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
-      context->GetIsolate(),
-      "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 = obj.As<v8::Array>();
-  CHECK_EQ(4, elms->Length());
-  int elmc0 = 0;
-  const char** elmv0 = NULL;
-  CheckProperties(
-      isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
-  CheckOwnProperties(
-      isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
-  int elmc1 = 2;
-  const char* elmv1[] = {"a", "b"};
-  CheckProperties(
-      isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
-  CheckOwnProperties(
-      isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
-  int elmc2 = 3;
-  const char* elmv2[] = {"0", "1", "2"};
-  CheckProperties(
-      isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
-  CheckOwnProperties(
-      isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
-  int elmc3 = 4;
-  const char* elmv3[] = {"w", "z", "x", "y"};
-  CheckProperties(
-      isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
-  int elmc4 = 2;
-  const char* elmv4[] = {"w", "z"};
-  CheckOwnProperties(
-      isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
+  v8::HandleScope scope(context->GetIsolate());
+  // Introduce a variable in the prototype chain.
+  CompileRun("__proto__.x = 42");
+  v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
+  CHECK(!result->IsUndefined());
+  CHECK_EQ(43, result->Int32Value());
 }
 
 
-THREADED_TEST(PropertyEnumeration2) {
+// 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) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope scope(isolate);
-  v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
-      context->GetIsolate(),
-      "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 = obj.As<v8::Array>();
-  CHECK_EQ(4, elms->Length());
-  int elmc0 = 0;
-  const char** elmv0 = NULL;
-  CheckProperties(isolate,
-                  elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
-
-  v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
-  v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
-  CHECK_EQ(0, props->Length());
-  for (uint32_t i = 0; i < props->Length(); i++) {
-    printf("p[%d]\n", i);
-  }
-}
-
-static bool NamedSetAccessBlocker(Local<v8::Object> obj,
-                                  Local<Value> name,
-                                  v8::AccessType type,
-                                  Local<Value> data) {
-  return type != v8::ACCESS_SET;
+  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
+  v8::Handle<v8::FunctionTemplate> func_templ =
+      v8::FunctionTemplate::New(isolate);
+  v8::Handle<v8::String> foo_string =
+      v8::String::NewFromUtf8(isolate, "foo");
+  obj->Set(foo_string, func_templ->GetFunction());
+  v8::Handle<v8::Object> obj_clone = obj->Clone();
+  obj_clone->Set(foo_string,
+                 v8::String::NewFromUtf8(isolate, "Hello"));
+  CHECK(!obj->Get(foo_string)->IsUndefined());
 }
 
 
-static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
-                                    uint32_t key,
-                                    v8::AccessType type,
-                                    Local<Value> data) {
-  return type != v8::ACCESS_SET;
+static void CheckElementValue(i::Isolate* isolate,
+                              int expected,
+                              i::Handle<i::Object> obj,
+                              int offset) {
+  i::Object* element =
+      *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
+  CHECK_EQ(expected, i::Smi::cast(element)->value());
 }
 
 
-THREADED_TEST(DisableAccessChecksWhileConfiguring) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
-                                 IndexedSetAccessBlocker);
-  templ->Set(v8_str("x"), v8::True(isolate));
-  Local<v8::Object> instance = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), instance);
-  Local<Value> value = CompileRun("obj.x");
-  CHECK(value->BooleanValue());
-}
+template <class ExternalArrayClass, class ElementType>
+static void ObjectWithExternalArrayTestHelper(Handle<Context> context,
+                                              v8::Handle<Object> obj,
+                                              int element_count,
+                                              i::ExternalArrayType array_type,
+                                              int64_t low, int64_t high) {
+  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
+  i::Isolate* isolate = jsobj->GetIsolate();
+  obj->Set(v8_str("field"),
+           v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
+  context->Global()->Set(v8_str("ext_array"), obj);
+  v8::Handle<v8::Value> result = CompileRun("ext_array.field");
+  CHECK_EQ(1503, result->Int32Value());
+  result = CompileRun("ext_array[1]");
+  CHECK_EQ(1, result->Int32Value());
+
+  // Check assigned smis
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  ext_array[i] = i;"
+                      "}"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += ext_array[i];"
+                      "}"
+                      "sum;");
 
+  CHECK_EQ(28, result->Int32Value());
+  // Check pass through of assigned smis
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += ext_array[i] = ext_array[i] = -i;"
+                      "}"
+                      "sum;");
+  CHECK_EQ(-28, result->Int32Value());
 
-static bool NamedGetAccessBlocker(Local<v8::Object> obj,
-                                  Local<Value> name,
-                                  v8::AccessType type,
-                                  Local<Value> data) {
-  return false;
-}
 
+  // Check assigned smis in reverse order
+  result = CompileRun("for (var i = 8; --i >= 0; ) {"
+                      "  ext_array[i] = i;"
+                      "}"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += ext_array[i];"
+                      "}"
+                      "sum;");
+  CHECK_EQ(28, result->Int32Value());
 
-static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
-                                    uint32_t key,
-                                    v8::AccessType type,
-                                    Local<Value> data) {
-  return false;
-}
+  // Check pass through of assigned HeapNumbers
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 16; i+=2) {"
+                      "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
+                      "}"
+                      "sum;");
+  CHECK_EQ(-28, result->Int32Value());
 
+  // Check assigned HeapNumbers
+  result = CompileRun("for (var i = 0; i < 16; i+=2) {"
+                      "  ext_array[i] = (i * 0.5);"
+                      "}"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 16; i+=2) {"
+                      "  sum += ext_array[i];"
+                      "}"
+                      "sum;");
+  CHECK_EQ(28, result->Int32Value());
 
+  // Check assigned HeapNumbers in reverse order
+  result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
+                      "  ext_array[i] = (i * 0.5);"
+                      "}"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 16; i+=2) {"
+                      "  sum += ext_array[i];"
+                      "}"
+                      "sum;");
+  CHECK_EQ(28, result->Int32Value());
 
-THREADED_TEST(AccessChecksReenabledCorrectly) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  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(isolate, k));
-      }
-    }
-  }
+  i::ScopedVector<char> test_buf(1024);
 
-  Local<v8::Object> instance_1 = templ->NewInstance();
-  context->Global()->Set(v8_str("obj_1"), instance_1);
+  // Check legal boundary conditions.
+  // The repeated loads and stores ensure the ICs are exercised.
+  const char* boundary_program =
+      "var res = 0;"
+      "for (var i = 0; i < 16; i++) {"
+      "  ext_array[i] = %lld;"
+      "  if (i > 8) {"
+      "    res = ext_array[i];"
+      "  }"
+      "}"
+      "res;";
+  i::SNPrintF(test_buf,
+              boundary_program,
+              low);
+  result = CompileRun(test_buf.start());
+  CHECK_EQ(low, result->IntegerValue());
 
-  Local<Value> value_1 = CompileRun("obj_1.a");
-  CHECK(value_1->IsUndefined());
+  i::SNPrintF(test_buf,
+              boundary_program,
+              high);
+  result = CompileRun(test_buf.start());
+  CHECK_EQ(high, result->IntegerValue());
 
-  Local<v8::Object> instance_2 = templ->NewInstance();
-  context->Global()->Set(v8_str("obj_2"), instance_2);
+  // Check misprediction of type in IC.
+  result = CompileRun("var tmp_array = ext_array;"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  tmp_array[i] = i;"
+                      "  sum += tmp_array[i];"
+                      "  if (i == 4) {"
+                      "    tmp_array = {};"
+                      "  }"
+                      "}"
+                      "sum;");
+  // Force GC to trigger verification.
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(28, result->Int32Value());
 
-  Local<Value> value_2 = CompileRun("obj_2.a");
-  CHECK(value_2->IsUndefined());
-}
+  // Make sure out-of-range loads do not throw.
+  i::SNPrintF(test_buf,
+              "var caught_exception = false;"
+              "try {"
+              "  ext_array[%d];"
+              "} catch (e) {"
+              "  caught_exception = true;"
+              "}"
+              "caught_exception;",
+              element_count);
+  result = CompileRun(test_buf.start());
+  CHECK_EQ(false, result->BooleanValue());
 
+  // Make sure out-of-range stores do not throw.
+  i::SNPrintF(test_buf,
+              "var caught_exception = false;"
+              "try {"
+              "  ext_array[%d] = 1;"
+              "} catch (e) {"
+              "  caught_exception = true;"
+              "}"
+              "caught_exception;",
+              element_count);
+  result = CompileRun(test_buf.start());
+  CHECK_EQ(false, result->BooleanValue());
 
-// This tests that access check information remains on the global
-// object template when creating contexts.
-THREADED_TEST(AccessControlRepeatedContextCreation) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope handle_scope(isolate);
-  v8::Handle<v8::ObjectTemplate> global_template =
-      v8::ObjectTemplate::New(isolate);
-  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::Local<Context> context0(Context::New(isolate, NULL, global_template));
-  CHECK(!context0.IsEmpty());
-  CHECK(!constructor->access_check_info()->IsUndefined());
-}
+  // Check other boundary conditions, values and operations.
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  ext_array[7] = undefined;"
+                      "}"
+                      "ext_array[7];");
+  CHECK_EQ(0, result->Int32Value());
+  if (array_type == i::kExternalFloat64Array ||
+      array_type == i::kExternalFloat32Array) {
+    CHECK(std::isnan(
+        i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
+  } else {
+    CheckElementValue(isolate, 0, jsobj, 7);
+  }
 
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  ext_array[6] = '2.3';"
+                      "}"
+                      "ext_array[6];");
+  CHECK_EQ(2, result->Int32Value());
+  CHECK_EQ(2,
+           static_cast<int>(
+               i::Object::GetElement(
+                   isolate, jsobj, 6).ToHandleChecked()->Number()));
 
-THREADED_TEST(TurnOnAccessCheck) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope handle_scope(isolate);
+  if (array_type != i::kExternalFloat32Array &&
+      array_type != i::kExternalFloat64Array) {
+    // Though the specification doesn't state it, be explicit about
+    // converting NaNs and +/-Infinity to zero.
+    result = CompileRun("for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = 5;"
+                        "}"
+                        "for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = NaN;"
+                        "}"
+                        "ext_array[5];");
+    CHECK_EQ(0, result->Int32Value());
+    CheckElementValue(isolate, 0, jsobj, 5);
 
-  // Create an environment with access check to the global object disabled by
-  // default.
-  v8::Handle<v8::ObjectTemplate> global_template =
-      v8::ObjectTemplate::New(isolate);
-  global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
-                                           IndexedGetAccessBlocker,
-                                           v8::Handle<v8::Value>(),
-                                           false);
-  v8::Local<Context> context = Context::New(isolate, NULL, global_template);
-  Context::Scope context_scope(context);
+    result = CompileRun("for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = 5;"
+                        "}"
+                        "for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = Infinity;"
+                        "}"
+                        "ext_array[5];");
+    int expected_value =
+        (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
+    CHECK_EQ(expected_value, result->Int32Value());
+    CheckElementValue(isolate, expected_value, jsobj, 5);
 
-  // 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();
+    result = CompileRun("for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = 5;"
+                        "}"
+                        "for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = -Infinity;"
+                        "}"
+                        "ext_array[5];");
+    CHECK_EQ(0, result->Int32Value());
+    CheckElementValue(isolate, 0, jsobj, 5);
 
-  // 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)));
+    // Check truncation behavior of integral arrays.
+    const char* unsigned_data =
+        "var source_data = [0.6, 10.6];"
+        "var expected_results = [0, 10];";
+    const char* signed_data =
+        "var source_data = [0.6, 10.6, -0.6, -10.6];"
+        "var expected_results = [0, 10, 0, -10];";
+    const char* pixel_data =
+        "var source_data = [0.6, 10.6];"
+        "var expected_results = [1, 11];";
+    bool is_unsigned = (array_type == i::kExternalUint8Array ||
+                        array_type == i::kExternalUint16Array ||
+                        array_type == i::kExternalUint32Array);
+    bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
+
+    i::SNPrintF(test_buf,
+                "%s"
+                "var all_passed = true;"
+                "for (var i = 0; i < source_data.length; i++) {"
+                "  for (var j = 0; j < 8; j++) {"
+                "    ext_array[j] = source_data[i];"
+                "  }"
+                "  all_passed = all_passed &&"
+                "               (ext_array[5] == expected_results[i]);"
+                "}"
+                "all_passed;",
+                (is_unsigned ?
+                     unsigned_data :
+                     (is_pixel_data ? pixel_data : signed_data)));
+    result = CompileRun(test_buf.start());
+    CHECK_EQ(true, result->BooleanValue());
   }
 
-  // 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)));
+  i::Handle<ExternalArrayClass> array(
+      ExternalArrayClass::cast(jsobj->elements()));
+  for (int i = 0; i < element_count; i++) {
+    array->set(i, static_cast<ElementType>(i));
   }
 
-  // Detach the global and turn on access check.
-  Local<Object> hidden_global = Local<Object>::Cast(
-      context->Global()->GetPrototype());
-  context->DetachGlobal();
-  hidden_global->TurnOnAccessCheck();
+  // Test complex assignments
+  result = CompileRun("function ee_op_test_complex_func(sum) {"
+                      " for (var i = 0; i < 40; ++i) {"
+                      "   sum += (ext_array[i] += 1);"
+                      "   sum += (ext_array[i] -= 1);"
+                      " } "
+                      " return sum;"
+                      "}"
+                      "sum=0;"
+                      "for (var i=0;i<10000;++i) {"
+                      "  sum=ee_op_test_complex_func(sum);"
+                      "}"
+                      "sum;");
+  CHECK_EQ(16000000, result->Int32Value());
 
-  // Failing access check to property get results in undefined.
-  CHECK(f1->Call(global, 0, NULL)->IsUndefined());
-  CHECK(f2->Call(global, 0, NULL)->IsUndefined());
+  // Test count operations
+  result = CompileRun("function ee_op_test_count_func(sum) {"
+                      " for (var i = 0; i < 40; ++i) {"
+                      "   sum += (++ext_array[i]);"
+                      "   sum += (--ext_array[i]);"
+                      " } "
+                      " return sum;"
+                      "}"
+                      "sum=0;"
+                      "for (var i=0;i<10000;++i) {"
+                      "  sum=ee_op_test_count_func(sum);"
+                      "}"
+                      "sum;");
+  CHECK_EQ(16000000, result->Int32Value());
 
-  // Failing access check to function call results in exception.
-  CHECK(g1->Call(global, 0, NULL).IsEmpty());
-  CHECK(g2->Call(global, 0, NULL).IsEmpty());
+  result = CompileRun("ext_array[3] = 33;"
+                      "delete ext_array[3];"
+                      "ext_array[3];");
+  CHECK_EQ(33, result->Int32Value());
 
-  // No failing access check when just returning a constant.
-  CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
-}
+  result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
+                      "ext_array[2] = 12; ext_array[3] = 13;"
+                      "ext_array.__defineGetter__('2',"
+                      "function() { return 120; });"
+                      "ext_array[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());
 
-static const char* kPropertyA = "a";
-static const char* kPropertyH = "h";
+  result = CompileRun("ext_array[1] = 23;"
+                      "ext_array.__proto__ = [];"
+                      "js_array.__proto__ = ext_array;"
+                      "js_array.concat(ext_array);");
+  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
+  CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
 
-static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
-                                       Local<Value> name,
-                                       v8::AccessType type,
-                                       Local<Value> data) {
-  if (!name->IsString()) return false;
-  i::Handle<i::String> name_handle =
-      v8::Utils::OpenHandle(String::Cast(*name));
-  return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
-      && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
+  result = CompileRun("ext_array[1] = 23;");
+  CHECK_EQ(23, result->Int32Value());
 }
 
 
-THREADED_TEST(TurnOnAccessCheckAndRecompile) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope handle_scope(isolate);
-
-  // Create an environment with access check to the global object disabled by
-  // default. When the registered access checker will block access to properties
-  // a and h.
-  v8::Handle<v8::ObjectTemplate> global_template =
-     v8::ObjectTemplate::New(isolate);
-  global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
-                                           IndexedGetAccessBlocker,
-                                           v8::Handle<v8::Value>(),
-                                           false);
-  v8::Local<Context> context = Context::New(isolate, 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));
-  static const char* source = "function f1() {return a;}"
-                              "function f2() {return a;}"
-                              "function g1() {return h();}"
-                              "function g2() {return h();}"
-                              "function h() {return 1;}";
-
-  CompileRun(source);
-  Local<Function> f1;
-  Local<Function> f2;
-  Local<Function> g1;
-  Local<Function> g2;
-  Local<Function> h;
-  f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
-  f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
-  g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
-  g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
-  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)));
+template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
+          class ElementType>
+static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
+                                      ElementType low, ElementType high) {
+  i::FLAG_allow_natives_syntax = true;
+  LocalContext context;
+  i::Isolate* isolate = CcTest::i_isolate();
+  i::Factory* factory = isolate->factory();
+  v8::HandleScope scope(context->GetIsolate());
+  const int kElementCount = 260;
+  i::Handle<i::JSTypedArray> jsobj =
+      factory->NewJSTypedArray(elements_kind, kElementCount);
+  i::Handle<FixedTypedArrayClass> fixed_array(
+      FixedTypedArrayClass::cast(jsobj->elements()));
+  CHECK_EQ(FixedTypedArrayClass::kInstanceType,
+           fixed_array->map()->instance_type());
+  CHECK_EQ(kElementCount, fixed_array->length());
+  CcTest::heap()->CollectAllGarbage();
+  for (int i = 0; i < kElementCount; i++) {
+    fixed_array->set(i, static_cast<ElementType>(i));
   }
-
-  // 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)));
+  // Force GC to trigger verification.
+  CcTest::heap()->CollectAllGarbage();
+  for (int i = 0; i < kElementCount; i++) {
+    CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
+             static_cast<int64_t>(fixed_array->get_scalar(i)));
   }
+  v8::Handle<v8::Object> obj = v8::Utils::ToLocal(jsobj);
 
-  // Detach the global and turn on access check now blocking access to property
-  // a and function h.
-  Local<Object> hidden_global = Local<Object>::Cast(
-      context->Global()->GetPrototype());
-  context->DetachGlobal();
-  hidden_global->TurnOnAccessCheck();
+  ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
+      context.local(), obj, kElementCount, array_type,
+      static_cast<int64_t>(low),
+      static_cast<int64_t>(high));
+}
 
-  // 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());
+THREADED_TEST(FixedUint8Array) {
+  FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
+      i::kExternalUint8Array, 0x0, 0xFF);
+}
 
-  // No failing access check when just returning a constant.
-  CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
 
-  // Now compile the source again. And get the newly compiled functions, except
-  // for h for which access is blocked.
-  CompileRun(source);
-  f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
-  f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
-  g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
-  g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
-  CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());
+THREADED_TEST(FixedUint8ClampedArray) {
+  FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
+                            i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
+      i::kExternalUint8ClampedArray, 0x0, 0xFF);
+}
 
-  // 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());
+THREADED_TEST(FixedInt8Array) {
+  FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
+      i::kExternalInt8Array, -0x80, 0x7F);
 }
 
 
-// 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();
-  v8::Isolate* isolate = CcTest::isolate();
-  HandleScope handle_scope(isolate);
-  const char* script = "function foo(a) { return a+1; }";
-  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
-      isolate, script, v8::String::kNormalString, i::StrLength(script)));
-  CHECK_NE(sd->Length(), 0);
-  CHECK_NE(sd->Data(), NULL);
-  CHECK(!sd->HasError());
-  delete sd;
+THREADED_TEST(FixedUint16Array) {
+  FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
+      i::kExternalUint16Array, 0x0, 0xFFFF);
 }
 
 
-TEST(PreCompileWithError) {
-  v8::V8::Initialize();
-  v8::Isolate* isolate = CcTest::isolate();
-  HandleScope handle_scope(isolate);
-  const char* script = "function foo(a) { return 1 * * 2; }";
-  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
-      isolate, script, v8::String::kNormalString, i::StrLength(script)));
-  CHECK(sd->HasError());
-  delete sd;
+THREADED_TEST(FixedInt16Array) {
+  FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
+      i::kExternalInt16Array, -0x8000, 0x7FFF);
 }
 
 
-TEST(Regress31661) {
-  v8::V8::Initialize();
-  v8::Isolate* isolate = CcTest::isolate();
-  HandleScope handle_scope(isolate);
-  const char* script = " The Definintive Guide";
-  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
-      isolate, script, v8::String::kNormalString, i::StrLength(script)));
-  CHECK(sd->HasError());
-  delete sd;
+THREADED_TEST(FixedUint32Array) {
+  FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
+      i::kExternalUint32Array, 0x0, UINT_MAX);
 }
 
 
-// Tests that ScriptData can be serialized and deserialized.
-TEST(PreCompileSerialization) {
-  v8::V8::Initialize();
-  v8::Isolate* isolate = CcTest::isolate();
-  HandleScope handle_scope(isolate);
-  const char* script = "function foo(a) { return a+1; }";
-  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
-      isolate, script, v8::String::kNormalString, i::StrLength(script)));
+THREADED_TEST(FixedInt32Array) {
+  FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
+      i::kExternalInt32Array, INT_MIN, INT_MAX);
+}
 
-  // Serialize.
-  int serialized_data_length = sd->Length();
-  char* serialized_data = i::NewArray<char>(serialized_data_length);
-  i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
 
-  // Deserialize.
-  v8::ScriptData* deserialized_sd =
-      v8::ScriptData::New(serialized_data, serialized_data_length);
+THREADED_TEST(FixedFloat32Array) {
+  FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
+      i::kExternalFloat32Array, -500, 500);
+}
 
-  // Verify that the original is the same as the deserialized.
-  CHECK_EQ(sd->Length(), deserialized_sd->Length());
-  CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
-  CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
 
-  delete sd;
-  delete deserialized_sd;
-  i::DeleteArray(serialized_data);
+THREADED_TEST(FixedFloat64Array) {
+  FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
+      i::kExternalFloat64Array, -500, 500);
 }
 
 
-// Attempts to deserialize bad data.
-TEST(PreCompileDeserializationError) {
-  v8::V8::Initialize();
-  const char* data = "DONT CARE";
-  int invalid_size = 3;
-  v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
+template <typename ElementType, typename TypedArray, class ExternalArrayClass,
+          class ArrayBufferType>
+void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
+                          int64_t high) {
+  const int kElementCount = 50;
 
-  CHECK_EQ(0, sd->Length());
+  i::ScopedVector<ElementType> backing_store(kElementCount+2);
 
-  delete sd;
-}
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
 
+  Local<ArrayBufferType> ab =
+      ArrayBufferType::New(isolate, backing_store.start(),
+                           (kElementCount + 2) * sizeof(ElementType));
+  Local<TypedArray> ta =
+      TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
+  CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
+  CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
+  CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
+  CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
+  CHECK(ab->Equals(ta->Buffer()));
 
-// Attempts to deserialize bad data.
-TEST(PreCompileInvalidPreparseDataError) {
-  v8::V8::Initialize();
-  v8::Isolate* isolate = CcTest::isolate();
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+  ElementType* data = backing_store.start() + 2;
+  for (int i = 0; i < kElementCount; i++) {
+    data[i] = static_cast<ElementType>(i);
+  }
 
-  const char* script = "function foo(){ return 5;}\n"
-      "function bar(){ return 6 + 7;}  foo();";
-  v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
-      isolate, script, v8::String::kNormalString, i::StrLength(script)));
-  CHECK(!sd->HasError());
-  // ScriptDataImpl private implementation details
-  const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
-  const int kFunctionEntrySize = i::FunctionEntry::kSize;
-  const int kFunctionEntryStartOffset = 0;
-  const int kFunctionEntryEndOffset = 1;
-  unsigned* sd_data =
-      reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
-
-  // Overwrite function bar's end position with 0.
-  sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
-  v8::TryCatch try_catch;
-
-  Local<String> source = String::NewFromUtf8(isolate, script);
-  Local<Script> compiled_script = Script::New(source, NULL, sd);
-  CHECK(try_catch.HasCaught());
-  String::Utf8Value exception_value(try_catch.Message()->Get());
-  CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
-           *exception_value);
+  ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
+      env.local(), ta, kElementCount, array_type, low, high);
+}
 
-  try_catch.Reset();
-  delete sd;
-
-  // Overwrite function bar's start position with 200.  The function entry
-  // will not be found when searching for it by position and we should fall
-  // back on eager compilation.
-  sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
-      isolate, script, v8::String::kNormalString, i::StrLength(script)));
-  sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
-  sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
-      200;
-  compiled_script = Script::New(source, NULL, sd);
-  CHECK(!try_catch.HasCaught());
 
-  delete sd;
+THREADED_TEST(Uint8Array) {
+  TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array,
+                       v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
 }
 
 
-// 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(CcTest::isolate());
-  // Test LoadIC.
-  for (int i = 0; i < 2; i++) {
-    LocalContext context;
-    context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
-    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(CcTest::isolate()));
-    context->Global()->Delete(v8_str("tmp"));
-    CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
-  }
+THREADED_TEST(Int8Array) {
+  TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array,
+                       v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
 }
 
 
-// Test that cross-context new calls use the context of the callee to
-// create the new JavaScript object.
-THREADED_TEST(CrossContextNew) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> context0 = Context::New(isolate);
-  v8::Local<Context> context1 = Context::New(isolate);
-
-  // Allow cross-domain access.
-  Local<String> token = v8_str("<security token>");
-  context0->SetSecurityToken(token);
-  context1->SetSecurityToken(token);
+THREADED_TEST(Uint16Array) {
+  TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array,
+                       v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
+}
 
-  // 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();
+THREADED_TEST(Int16Array) {
+  TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array,
+                       v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
+                                        0x7FFF);
 }
 
 
-// Verify that we can clone an object
-TEST(ObjectClone) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-
-  const char* sample =
-    "var rv = {};"      \
-    "rv.alpha = 'hello';" \
-    "rv.beta = 123;"     \
-    "rv;";
+THREADED_TEST(Uint32Array) {
+  TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array,
+                       v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
+}
 
-  // Create an object, verify basics.
-  Local<Value> val = CompileRun(sample);
-  CHECK(val->IsObject());
-  Local<v8::Object> obj = val.As<v8::Object>();
-  obj->Set(v8_str("gamma"), v8_str("cloneme"));
 
-  CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
-  CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
-  CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
+THREADED_TEST(Int32Array) {
+  TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array,
+                       v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
+                                        INT_MAX);
+}
 
-  // Clone it.
-  Local<v8::Object> clone = obj->Clone();
-  CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
-  CHECK_EQ(v8::Integer::New(isolate, 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(isolate, 456));
-  CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
-  CHECK_EQ(v8::Integer::New(isolate, 456), clone->Get(v8_str("beta")));
+THREADED_TEST(Float32Array) {
+  TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array,
+                       v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
 }
 
 
-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_;
-};
+THREADED_TEST(Float64Array) {
+  TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array,
+                       v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
+}
 
 
-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_;
-};
+THREADED_TEST(Uint8ClampedArray) {
+  TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
+                       i::ExternalUint8ClampedArray, v8::ArrayBuffer>(
+      i::kExternalUint8ClampedArray, 0, 0xFF);
+}
 
 
-static void MorphAString(i::String* string,
-                         AsciiVectorResource* ascii_resource,
-                         UC16VectorResource* uc16_resource) {
-  CHECK(i::StringShape(string).IsExternal());
-  if (string->IsOneByteRepresentation()) {
-    // Check old map is not internalized or long.
-    CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
-    // Morph external string to be TwoByte string.
-    string->set_map(CcTest::heap()->external_string_map());
-    i::ExternalTwoByteString* morphed =
-         i::ExternalTwoByteString::cast(string);
-    morphed->set_resource(uc16_resource);
-  } else {
-    // Check old map is not internalized or long.
-    CHECK(string->map() == CcTest::heap()->external_string_map());
-    // Morph external string to be ASCII string.
-    string->set_map(CcTest::heap()->external_ascii_string_map());
-    i::ExternalAsciiString* morphed =
-         i::ExternalAsciiString::cast(string);
-    morphed->set_resource(ascii_resource);
-  }
-}
+THREADED_TEST(DataView) {
+  const int kSize = 50;
 
+  i::ScopedVector<uint8_t> backing_store(kSize+2);
 
-// 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) {
-  char utf_buffer[129];
-  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);
-  {
-    LocalContext env;
-    i::Factory* factory = CcTest::i_isolate()->factory();
-    v8::HandleScope scope(env->GetIsolate());
-    AsciiVectorResource ascii_resource(
-        i::Vector<const char>(c_string, i::StrLength(c_string)));
-    UC16VectorResource uc16_resource(
-        i::Vector<const uint16_t>(two_byte_string,
-                                  i::StrLength(c_string)));
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
 
-    Local<String> lhs(v8::Utils::ToLocal(
-        factory->NewExternalStringFromAscii(&ascii_resource)));
-    Local<String> rhs(v8::Utils::ToLocal(
-        factory->NewExternalStringFromAscii(&ascii_resource)));
+  Local<v8::ArrayBuffer> ab =
+      v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
+  Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
+  CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
+  CHECK_EQ(2u, dv->ByteOffset());
+  CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
+  CHECK(ab->Equals(dv->Buffer()));
+}
 
-    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);");
+THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
 
-    CHECK(lhs->IsOneByte());
-    CHECK(rhs->IsOneByte());
+  // Make sure the pointer looks like a heap object
+  uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
 
-    MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
-    MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
+  // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
+  Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
 
-    // This should UTF-8 without flattening, since everything is ASCII.
-    Handle<String> cons = v8_compile("cons")->Run().As<String>();
-    CHECK_EQ(128, cons->Utf8Length());
-    int nchars = -1;
-    CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
-    CHECK_EQ(128, nchars);
-    CHECK_EQ(0, strcmp(
-        utf_buffer,
-        "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"));
+  // Should not crash
+  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
+  CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
+  CcTest::heap()->CollectAllGarbage();
+  CcTest::heap()->CollectAllGarbage();
 
-    // 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::NewFromUtf8(env->GetIsolate(), expected_cons),
-             env->Global()->Get(v8_str("cons")));
-    CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
-             env->Global()->Get(v8_str("slice")));
-    CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
-             env->Global()->Get(v8_str("slice_on_cons")));
-  }
-  i::DeleteArray(two_byte_string);
+  // Should not move the pointer
+  CHECK_EQ(ab->GetContents().Data(), store_ptr);
 }
 
 
-TEST(CompileExternalTwoByteSource) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+THREADED_TEST(SharedUint8Array) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array,
+                       v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
+}
 
-  // 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]);
-    TestResource* uc16_resource = new TestResource(two_byte_string);
-    v8::Local<v8::String> source =
-        v8::String::NewExternal(context->GetIsolate(), uc16_resource);
-    v8::Script::Compile(source);
-  }
+THREADED_TEST(SharedInt8Array) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array,
+                       v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
+                                              0x7F);
 }
 
 
-#ifndef V8_INTERPRETED_REGEXP
+THREADED_TEST(SharedUint16Array) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array,
+                       v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
+                                              0xFFFF);
+}
 
-struct RegExpInterruptionData {
-  int loop_count;
-  UC16VectorResource* string_resource;
-  v8::Persistent<v8::String> string;
-} regexp_interruption_data;
 
+THREADED_TEST(SharedInt16Array) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array,
+                       v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
+                                              0x7FFF);
+}
 
-class RegExpInterruptionThread : public i::Thread {
- public:
-  explicit RegExpInterruptionThread(v8::Isolate* isolate)
-      : Thread("TimeoutThread"), isolate_(isolate) {}
 
-  virtual void Run() {
-    for (regexp_interruption_data.loop_count = 0;
-         regexp_interruption_data.loop_count < 7;
-         regexp_interruption_data.loop_count++) {
-      i::OS::Sleep(50);  // Wait a bit before requesting GC.
-      reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
-    }
-    i::OS::Sleep(50);  // Wait a bit before terminating.
-    v8::V8::TerminateExecution(isolate_);
-  }
+THREADED_TEST(SharedUint32Array) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array,
+                       v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
+                                              UINT_MAX);
+}
 
- private:
-  v8::Isolate* isolate_;
-};
+
+THREADED_TEST(SharedInt32Array) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array,
+                       v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
+                                              INT_MAX);
+}
 
 
-void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
-  if (regexp_interruption_data.loop_count != 2) return;
-  v8::HandleScope scope(CcTest::isolate());
-  v8::Local<v8::String> string = v8::Local<v8::String>::New(
-      CcTest::isolate(), regexp_interruption_data.string);
-  string->MakeExternal(regexp_interruption_data.string_resource);
+THREADED_TEST(SharedFloat32Array) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array,
+                       v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
+                                              500);
 }
 
 
-// Test that RegExp execution can be interrupted.  Specifically, we test
-// * interrupting with GC
-// * turn the subject string from one-byte internal to two-byte external string
-// * force termination
-TEST(RegExpInterruption) {
-  v8::HandleScope scope(CcTest::isolate());
-  LocalContext env;
+THREADED_TEST(SharedFloat64Array) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array,
+                       v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
+                                              500);
+}
 
-  RegExpInterruptionThread timeout_thread(CcTest::isolate());
 
-  v8::V8::AddGCPrologueCallback(RunBeforeGC);
-  static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-  i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
-  v8::Local<v8::String> string = v8_str(ascii_content);
+THREADED_TEST(SharedUint8ClampedArray) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
+                       i::ExternalUint8ClampedArray, v8::SharedArrayBuffer>(
+      i::kExternalUint8ClampedArray, 0, 0xFF);
+}
 
-  CcTest::global()->Set(v8_str("a"), string);
-  regexp_interruption_data.string.Reset(CcTest::isolate(), string);
-  regexp_interruption_data.string_resource = new UC16VectorResource(
-      i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
 
-  v8::TryCatch try_catch;
-  timeout_thread.Start();
+THREADED_TEST(SharedDataView) {
+  i::FLAG_harmony_sharedarraybuffer = true;
+  const int kSize = 50;
 
-  CompileRun("/((a*)*)*b/.exec(a)");
-  CHECK(try_catch.HasTerminated());
+  i::ScopedVector<uint8_t> backing_store(kSize + 2);
 
-  timeout_thread.Join();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
 
-  regexp_interruption_data.string.Reset();
-  i::DeleteArray(uc16_content);
+  Local<v8::SharedArrayBuffer> ab =
+      v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
+  Local<v8::DataView> dv =
+      v8::DataView::New(ab, 2, kSize);
+  CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
+  CHECK_EQ(2u, dv->ByteOffset());
+  CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
+  CHECK(ab->Equals(dv->Buffer()));
 }
 
-#endif  // V8_INTERPRETED_REGEXP
 
+#define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
+  THREADED_TEST(Is##View) {                                                   \
+    LocalContext env;                                                         \
+    v8::Isolate* isolate = env->GetIsolate();                                 \
+    v8::HandleScope handle_scope(isolate);                                    \
+                                                                              \
+    Handle<Value> result = CompileRun(                                        \
+        "var ab = new ArrayBuffer(128);"                                      \
+        "new " #View "(ab)");                                                 \
+    CHECK(result->IsArrayBufferView());                                       \
+    CHECK(result->Is##View());                                                \
+    CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
+  }
 
-// Test that we cannot set a property on the global object if there
-// is a read-only property in the prototype chain.
-TEST(ReadOnlyPropertyInGlobalProto) {
-  i::FLAG_es5_readonly = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
-  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(isolate, 0), v8::ReadOnly);
-  global_proto->Set(v8_str("y"), v8::Integer::New(isolate, 0), v8::ReadOnly);
-  // Check without 'eval' or 'with'.
-  v8::Handle<v8::Value> res =
-      CompileRun("function f() { x = 42; return x; }; f()");
-  CHECK_EQ(v8::Integer::New(isolate, 0), res);
-  // Check with 'eval'.
-  res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
-  CHECK_EQ(v8::Integer::New(isolate, 0), res);
-  // Check with 'with'.
-  res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
-  CHECK_EQ(v8::Integer::New(isolate, 0), res);
+IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
+IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
+IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
+IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
+IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
+IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
+IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
+IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
+IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
+IS_ARRAY_BUFFER_VIEW_TEST(DataView)
+
+#undef IS_ARRAY_BUFFER_VIEW_TEST
+
+
+
+THREADED_TEST(ScriptContextDependence) {
+  LocalContext c1;
+  v8::HandleScope scope(c1->GetIsolate());
+  const char *source = "foo";
+  v8::Handle<v8::Script> dep = v8_compile(source);
+  v8::ScriptCompiler::Source script_source(v8::String::NewFromUtf8(
+      c1->GetIsolate(), source));
+  v8::Handle<v8::UnboundScript> indep =
+      v8::ScriptCompiler::CompileUnbound(c1->GetIsolate(), &script_source);
+  c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
+                    v8::Integer::New(c1->GetIsolate(), 100));
+  CHECK_EQ(dep->Run()->Int32Value(), 100);
+  CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 100);
+  LocalContext c2;
+  c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
+                    v8::Integer::New(c2->GetIsolate(), 101));
+  CHECK_EQ(dep->Run()->Int32Value(), 100);
+  CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 101);
 }
 
-static int force_set_set_count = 0;
-static int force_set_get_count = 0;
-bool pass_on_get = false;
 
-static void ForceSetGetter(v8::Local<v8::String> name,
-                           const v8::PropertyCallbackInfo<v8::Value>& info) {
-  force_set_get_count++;
-  if (pass_on_get) {
-    return;
+THREADED_TEST(StackTrace) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::TryCatch try_catch(context->GetIsolate());
+  const char *source = "function foo() { FAIL.FAIL; }; foo();";
+  v8::Handle<v8::String> src =
+      v8::String::NewFromUtf8(context->GetIsolate(), source);
+  v8::Handle<v8::String> origin =
+      v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
+  v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
+  v8::ScriptCompiler::CompileUnbound(context->GetIsolate(), &script_source)
+      ->BindToCurrentContext()
+      ->Run();
+  CHECK(try_catch.HasCaught());
+  v8::String::Utf8Value stack(try_catch.StackTrace());
+  CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
+}
+
+
+// Checks that a StackFrame has certain expected values.
+void checkStackFrame(const char* expected_script_name,
+    const char* expected_func_name, int expected_line_number,
+    int expected_column, bool is_eval, bool is_constructor,
+    v8::Handle<v8::StackFrame> frame) {
+  v8::HandleScope scope(CcTest::isolate());
+  v8::String::Utf8Value func_name(frame->GetFunctionName());
+  v8::String::Utf8Value script_name(frame->GetScriptName());
+  if (*script_name == NULL) {
+    // The situation where there is no associated script, like for evals.
+    CHECK(expected_script_name == NULL);
+  } else {
+    CHECK(strstr(*script_name, expected_script_name) != NULL);
   }
-  info.GetReturnValue().Set(3);
+  CHECK(strstr(*func_name, expected_func_name) != NULL);
+  CHECK_EQ(expected_line_number, frame->GetLineNumber());
+  CHECK_EQ(expected_column, frame->GetColumn());
+  CHECK_EQ(is_eval, frame->IsEval());
+  CHECK_EQ(is_constructor, frame->IsConstructor());
 }
 
-static void ForceSetSetter(v8::Local<v8::String> name,
-                           v8::Local<v8::Value> value,
-                           const v8::PropertyCallbackInfo<void>& info) {
-  force_set_set_count++;
+
+void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::HandleScope scope(args.GetIsolate());
+  const char* origin = "capture-stack-trace-test";
+  const int kOverviewTest = 1;
+  const int kDetailedTest = 2;
+
+  DCHECK(args.Length() == 1);
+
+  int testGroup = args[0]->Int32Value();
+  if (testGroup == kOverviewTest) {
+    v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
+        args.GetIsolate(), 10, v8::StackTrace::kOverview);
+    CHECK_EQ(4, stackTrace->GetFrameCount());
+    checkStackFrame(origin, "bar", 2, 10, false, false,
+                    stackTrace->GetFrame(0));
+    checkStackFrame(origin, "foo", 6, 3, false, false,
+                    stackTrace->GetFrame(1));
+    // This is the source string inside the eval which has the call to foo.
+    checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
+    // The last frame is an anonymous function which has the initial eval call.
+    checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
+
+    CHECK(stackTrace->AsArray()->IsArray());
+  } else if (testGroup == kDetailedTest) {
+    v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
+        args.GetIsolate(), 10, v8::StackTrace::kDetailed);
+    CHECK_EQ(4, stackTrace->GetFrameCount());
+    checkStackFrame(origin, "bat", 4, 22, false, false,
+                    stackTrace->GetFrame(0));
+    checkStackFrame(origin, "baz", 8, 3, false, true,
+                    stackTrace->GetFrame(1));
+    bool is_eval = true;
+    // This is the source string inside the eval which has the call to baz.
+    checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
+    // The last frame is an anonymous function which has the initial eval call.
+    checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
+
+    CHECK(stackTrace->AsArray()->IsArray());
+  }
 }
 
-static void ForceSetInterceptSetter(
-    v8::Local<v8::String> name,
-    v8::Local<v8::Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  force_set_set_count++;
-  info.GetReturnValue().SetUndefined();
+
+// Tests the C++ StackTrace API.
+// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
+// THREADED_TEST(CaptureStackTrace) {
+TEST(CaptureStackTrace) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::String> origin =
+      v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->Set(v8_str("AnalyzeStackInNativeCode"),
+             v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
+  LocalContext context(0, templ);
+
+  // Test getting OVERVIEW information. Should ignore information that is not
+  // script name, function name, line number, and column offset.
+  const char *overview_source =
+    "function bar() {\n"
+    "  var y; AnalyzeStackInNativeCode(1);\n"
+    "}\n"
+    "function foo() {\n"
+    "\n"
+    "  bar();\n"
+    "}\n"
+    "var x;eval('new foo();');";
+  v8::Handle<v8::String> overview_src =
+      v8::String::NewFromUtf8(isolate, overview_source);
+  v8::ScriptCompiler::Source script_source(overview_src,
+                                           v8::ScriptOrigin(origin));
+  v8::Handle<Value> overview_result(
+      v8::ScriptCompiler::CompileUnbound(isolate, &script_source)
+          ->BindToCurrentContext()
+          ->Run());
+  CHECK(!overview_result.IsEmpty());
+  CHECK(overview_result->IsObject());
+
+  // Test getting DETAILED information.
+  const char *detailed_source =
+    "function bat() {AnalyzeStackInNativeCode(2);\n"
+    "}\n"
+    "\n"
+    "function baz() {\n"
+    "  bat();\n"
+    "}\n"
+    "eval('new baz();');";
+  v8::Handle<v8::String> detailed_src =
+      v8::String::NewFromUtf8(isolate, detailed_source);
+  // Make the script using a non-zero line and column offset.
+  v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
+  v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
+  v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
+  v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
+  v8::Handle<v8::UnboundScript> detailed_script(
+      v8::ScriptCompiler::CompileUnbound(isolate, &script_source2));
+  v8::Handle<Value> detailed_result(
+      detailed_script->BindToCurrentContext()->Run());
+  CHECK(!detailed_result.IsEmpty());
+  CHECK(detailed_result->IsObject());
 }
 
 
-TEST(ForceSet) {
-  force_set_get_count = 0;
-  force_set_set_count = 0;
-  pass_on_get = false;
+static void StackTraceForUncaughtExceptionListener(
+    v8::Handle<v8::Message> message,
+    v8::Handle<Value>) {
+  report_count++;
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK_EQ(2, stack_trace->GetFrameCount());
+  checkStackFrame("origin", "foo", 2, 3, false, false,
+                  stack_trace->GetFrame(0));
+  checkStackFrame("origin", "bar", 5, 3, false, false,
+                  stack_trace->GetFrame(1));
+}
 
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
-  v8::Handle<v8::String> access_property =
-      v8::String::NewFromUtf8(isolate, "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::NewFromUtf8(isolate, "p");
-  global->Set(simple_property, v8::Int32::New(isolate, 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(isolate, 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(isolate, 6));
-  CHECK_EQ(6, global->Get(simple_property)->Int32Value());
+TEST(CaptureStackTraceForUncaughtException) {
+  report_count = 0;
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
 
-  // 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(isolate, 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(isolate, 8));
-  CHECK_EQ(8, global->Get(access_property)->Int32Value());
-  CHECK_EQ(1, force_set_set_count);
-  CHECK_EQ(2, force_set_get_count);
+  CompileRunWithOrigin(
+      "function foo() {\n"
+      "  throw 1;\n"
+      "};\n"
+      "function bar() {\n"
+      "  foo();\n"
+      "};",
+      "origin");
+  v8::Local<v8::Object> global = env->Global();
+  Local<Value> trouble = global->Get(v8_str("bar"));
+  CHECK(trouble->IsFunction());
+  Function::Cast(*trouble)->Call(global, 0, NULL);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
+  CHECK_EQ(1, report_count);
 }
 
 
-TEST(ForceSetWithInterceptor) {
-  force_set_get_count = 0;
-  force_set_set_count = 0;
-  pass_on_get = false;
+TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
+  report_count = 0;
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
 
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
-  LocalContext context(NULL, templ);
-  v8::Handle<v8::Object> global = context->Global();
+  // Create an Error object first.
+  CompileRunWithOrigin(
+      "function foo() {\n"
+      "e=new Error('err');\n"
+      "};\n"
+      "function bar() {\n"
+      "  foo();\n"
+      "};\n"
+      "var e;",
+      "origin");
+  v8::Local<v8::Object> global = env->Global();
+  Local<Value> trouble = global->Get(v8_str("bar"));
+  CHECK(trouble->IsFunction());
+  Function::Cast(*trouble)->Call(global, 0, NULL);
 
-  v8::Handle<v8::String> some_property =
-      v8::String::NewFromUtf8(isolate, "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(isolate, 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(isolate, 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::NewFromUtf8(isolate, "b"))
-                  ->Int32Value());
-  CHECK_EQ(1, force_set_set_count);
-  CHECK_EQ(6, force_set_get_count);
+  // Enable capturing detailed stack trace late, and throw the exception.
+  // The detailed stack trace should be extracted from the simple stack.
+  v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRunWithOrigin("throw e", "origin");
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
+  CHECK_EQ(1, report_count);
 }
 
 
-THREADED_TEST(ForceDelete) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
-  LocalContext context(NULL, templ);
-  v8::Handle<v8::Object> global = context->Global();
+TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
+                                                    1024,
+                                                    v8::StackTrace::kDetailed);
 
-  // Ordinary properties
-  v8::Handle<v8::String> simple_property =
-      v8::String::NewFromUtf8(isolate, "p");
-  global->Set(simple_property, v8::Int32::New(isolate, 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());
+  CompileRun(
+      "var setters = ['column', 'lineNumber', 'scriptName',\n"
+      "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
+      "    'isConstructor'];\n"
+      "for (var i = 0; i < setters.length; i++) {\n"
+      "  var prop = setters[i];\n"
+      "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
+      "}\n");
+  CompileRun("throw 'exception';");
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
 }
 
 
-static int force_delete_interceptor_count = 0;
-static bool pass_on_delete = false;
-
-
-static void ForceDeleteDeleter(
-    v8::Local<v8::String> name,
-    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
-  force_delete_interceptor_count++;
-  if (pass_on_delete) return;
-  info.GetReturnValue().Set(true);
+static void StackTraceFunctionNameListener(v8::Handle<v8::Message> message,
+                                           v8::Handle<Value>) {
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK_EQ(5, stack_trace->GetFrameCount());
+  checkStackFrame("origin", "foo:0", 4, 7, false, false,
+                  stack_trace->GetFrame(0));
+  checkStackFrame("origin", "foo:1", 5, 27, false, false,
+                  stack_trace->GetFrame(1));
+  checkStackFrame("origin", "foo", 5, 27, false, false,
+                  stack_trace->GetFrame(2));
+  checkStackFrame("origin", "foo", 5, 27, false, false,
+                  stack_trace->GetFrame(3));
+  checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
 }
 
 
-THREADED_TEST(ForceDeleteWithInterceptor) {
-  force_delete_interceptor_count = 0;
-  pass_on_delete = false;
-
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
-  LocalContext context(NULL, templ);
-  v8::Handle<v8::Object> global = context->Global();
+TEST(GetStackTraceContainsFunctionsWithFunctionName) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
 
-  v8::Handle<v8::String> some_property =
-      v8::String::NewFromUtf8(isolate, "a");
-  global->Set(some_property, v8::Integer::New(isolate, 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);
+  CompileRunWithOrigin(
+      "function gen(name, counter) {\n"
+      "  var f = function foo() {\n"
+      "    if (counter === 0)\n"
+      "      throw 1;\n"
+      "    gen(name, counter - 1)();\n"
+      "  };\n"
+      "  if (counter == 3) {\n"
+      "    Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
+      "  } else {\n"
+      "    Object.defineProperty(f, 'name', {writable:true});\n"
+      "    if (counter == 2)\n"
+      "      f.name = 42;\n"
+      "    else\n"
+      "      f.name = name + ':' + counter;\n"
+      "  }\n"
+      "  return f;\n"
+      "};",
+      "origin");
+
+  v8::V8::AddMessageListener(StackTraceFunctionNameListener);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRunWithOrigin("gen('foo', 3)();", "origin");
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(StackTraceFunctionNameListener);
 }
 
 
-// Make sure that forcing a delete invalidates any IC stubs, so we
-// don't read the hole value.
-THREADED_TEST(ForceDeleteIC) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  // 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());
-}
-
-
-TEST(InlinedFunctionAcrossContexts) {
-  i::FLAG_allow_natives_syntax = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope outer_scope(isolate);
-  v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
-  v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
-  ctx1->Enter();
-
-  {
-    v8::HandleScope inner_scope(CcTest::isolate());
-    CompileRun("var G = 42; function foo() { return G; }");
-    v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
-    ctx2->Enter();
-    ctx2->Global()->Set(v8_str("o"), foo);
-    v8::Local<v8::Value> res = CompileRun(
-        "function f() { return o(); }"
-        "for (var i = 0; i < 10; ++i) f();"
-        "%OptimizeFunctionOnNextCall(f);"
-        "f();");
-    CHECK_EQ(42, res->Int32Value());
-    ctx2->Exit();
-    v8::Handle<v8::String> G_property =
-        v8::String::NewFromUtf8(CcTest::isolate(), "G");
-    CHECK(ctx1->Global()->ForceDelete(G_property));
-    ctx2->Enter();
-    ExpectString(
-        "(function() {"
-        "  try {"
-        "    return f();"
-        "  } catch(e) {"
-        "    return e.toString();"
-        "  }"
-        " })()",
-        "ReferenceError: G is not defined");
-    ctx2->Exit();
-    ctx1->Exit();
+static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
+                                     v8::Handle<v8::Value> data) {
+  // Use the frame where JavaScript is called from.
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK(!stack_trace.IsEmpty());
+  int frame_count = stack_trace->GetFrameCount();
+  CHECK_EQ(3, frame_count);
+  int line_number[] = {1, 2, 5};
+  for (int i = 0; i < frame_count; i++) {
+    CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   }
 }
 
 
-static v8::Local<Context> calling_context0;
-static v8::Local<Context> calling_context1;
-static v8::Local<Context> calling_context2;
+// Test that we only return the stack trace at the site where the exception
+// is first thrown (not where it is rethrown).
+TEST(RethrowStackTrace) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  // We make sure that
+  // - the stack trace of the ReferenceError in g() is reported.
+  // - the stack trace is not overwritten when e1 is rethrown by t().
+  // - the stack trace of e2 does not overwrite that of e1.
+  const char* source =
+      "function g() { error; }          \n"
+      "function f() { g(); }            \n"
+      "function t(e) { throw e; }       \n"
+      "try {                            \n"
+      "  f();                           \n"
+      "} catch (e1) {                   \n"
+      "  try {                          \n"
+      "    error;                       \n"
+      "  } catch (e2) {                 \n"
+      "    t(e1);                       \n"
+      "  }                              \n"
+      "}                                \n";
+  v8::V8::AddMessageListener(RethrowStackTraceHandler);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRun(source);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
+}
 
 
-// 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 void GetCallingContextCallback(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ApiTestFuzzer::Fuzz();
-  CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
-  CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
-  CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
-  args.GetReturnValue().Set(42);
+static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
+                                              v8::Handle<v8::Value> data) {
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK(!stack_trace.IsEmpty());
+  int frame_count = stack_trace->GetFrameCount();
+  CHECK_EQ(2, frame_count);
+  int line_number[] = {3, 7};
+  for (int i = 0; i < frame_count; i++) {
+    CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
+  }
 }
 
 
-THREADED_TEST(GetCurrentContextWhenNotInContext) {
-  i::Isolate* isolate = CcTest::i_isolate();
-  CHECK(isolate != NULL);
-  CHECK(isolate->context() == NULL);
-  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
-  v8::HandleScope scope(v8_isolate);
-  // The following should not crash, but return an empty handle.
-  v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
-  CHECK(current.IsEmpty());
+// Test that we do not recognize identity for primitive exceptions.
+TEST(RethrowPrimitiveStackTrace) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  // We do not capture stack trace for non Error objects on creation time.
+  // Instead, we capture the stack trace on last throw.
+  const char* source =
+      "function g() { throw 404; }      \n"
+      "function f() { g(); }            \n"
+      "function t(e) { throw e; }       \n"
+      "try {                            \n"
+      "  f();                           \n"
+      "} catch (e1) {                   \n"
+      "  t(e1)                          \n"
+      "}                                \n";
+  v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRun(source);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
 }
 
 
-THREADED_TEST(GetCallingContext) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-
-  Local<Context> calling_context0(Context::New(isolate));
-  Local<Context> calling_context1(Context::New(isolate));
-  Local<Context> calling_context2(Context::New(isolate));
-  ::calling_context0 = calling_context0;
-  ::calling_context1 = calling_context1;
-  ::calling_context2 = calling_context2;
+static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
+                                              v8::Handle<v8::Value> data) {
+  // Use the frame where JavaScript is called from.
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK(!stack_trace.IsEmpty());
+  CHECK_EQ(1, stack_trace->GetFrameCount());
+  CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
+}
 
-  // 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(isolate, GetCallingContextCallback);
-  calling_context0->Global()->Set(v8_str("callback"),
-                                  callback_templ->GetFunction());
-  calling_context0->Exit();
+// Test that the stack trace is captured when the error object is created and
+// not where it is thrown.
+TEST(RethrowExistingStackTrace) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  const char* source =
+      "var e = new Error();           \n"
+      "throw e;                       \n";
+  v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRun(source);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
+}
 
-  // Expose context0 in context1 and set up 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();
-  ::calling_context0.Clear();
-  ::calling_context1.Clear();
-  ::calling_context2.Clear();
+static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
+                                               v8::Handle<v8::Value> data) {
+  // Use the frame where JavaScript is called from.
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK(!stack_trace.IsEmpty());
+  CHECK_EQ(1, stack_trace->GetFrameCount());
+  CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
 }
 
 
-// Check that a variable declaration with no explicit initialization
-// value does shadow an existing property in the prototype chain.
-THREADED_TEST(InitGlobalVarInProtoChain) {
-  i::FLAG_es52_globals = true;
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  // Introduce a variable in the prototype chain.
-  CompileRun("__proto__.x = 42");
-  v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
-  CHECK(!result->IsUndefined());
-  CHECK_EQ(43, result->Int32Value());
+// Test that the stack trace is captured where the bogus Error object is thrown.
+TEST(RethrowBogusErrorStackTrace) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  const char* source =
+      "var e = {__proto__: new Error()} \n"
+      "throw e;                         \n";
+  v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRun(source);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
 }
 
 
-// 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) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
-  v8::Handle<v8::FunctionTemplate> func_templ =
-      v8::FunctionTemplate::New(isolate);
-  v8::Handle<v8::String> foo_string =
-      v8::String::NewFromUtf8(isolate, "foo");
-  obj->Set(foo_string, func_templ->GetFunction());
-  v8::Handle<v8::Object> obj_clone = obj->Clone();
-  obj_clone->Set(foo_string,
-                 v8::String::NewFromUtf8(isolate, "Hello"));
-  CHECK(!obj->Get(foo_string)->IsUndefined());
+v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
+int promise_reject_counter = 0;
+int promise_revoke_counter = 0;
+int promise_reject_msg_line_number = -1;
+int promise_reject_msg_column_number = -1;
+int promise_reject_line_number = -1;
+int promise_reject_column_number = -1;
+int promise_reject_frame_count = -1;
+
+void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
+  if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
+    promise_reject_counter++;
+    CcTest::global()->Set(v8_str("rejected"), reject_message.GetPromise());
+    CcTest::global()->Set(v8_str("value"), reject_message.GetValue());
+    v8::Handle<v8::Message> message =
+        v8::Exception::CreateMessage(reject_message.GetValue());
+    v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+
+    promise_reject_msg_line_number = message->GetLineNumber();
+    promise_reject_msg_column_number = message->GetStartColumn() + 1;
+
+    if (!stack_trace.IsEmpty()) {
+      promise_reject_frame_count = stack_trace->GetFrameCount();
+      if (promise_reject_frame_count > 0) {
+        CHECK(stack_trace->GetFrame(0)->GetScriptName()->Equals(v8_str("pro")));
+        promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
+        promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
+      } else {
+        promise_reject_line_number = -1;
+        promise_reject_column_number = -1;
+      }
+    }
+  } else {
+    promise_revoke_counter++;
+    CcTest::global()->Set(v8_str("revoked"), reject_message.GetPromise());
+    CHECK(reject_message.GetValue().IsEmpty());
+  }
 }
 
 
-static void CheckElementValue(i::Isolate* isolate,
-                              int expected,
-                              i::Handle<i::Object> obj,
-                              int offset) {
-  i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
-  CHECK_EQ(expected, i::Smi::cast(element)->value());
+v8::Handle<v8::Promise> GetPromise(const char* name) {
+  return v8::Handle<v8::Promise>::Cast(CcTest::global()->Get(v8_str(name)));
 }
 
 
-THREADED_TEST(PixelArray) {
-  LocalContext context;
-  i::Isolate* isolate = CcTest::i_isolate();
-  i::Factory* factory = isolate->factory();
-  v8::HandleScope scope(context->GetIsolate());
-  const int kElementCount = 260;
-  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
-  i::Handle<i::ExternalUint8ClampedArray> pixels =
-      i::Handle<i::ExternalUint8ClampedArray>::cast(
-          factory->NewExternalArray(kElementCount,
-                                    v8::kExternalUint8ClampedArray,
-                                    pixel_data));
-  // Force GC to trigger verification.
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  for (int i = 0; i < kElementCount; i++) {
-    pixels->set(i, i % 256);
-  }
-  // Force GC to trigger verification.
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  for (int i = 0; i < kElementCount; i++) {
-    CHECK_EQ(i % 256, pixels->get_scalar(i));
-    CHECK_EQ(i % 256, pixel_data[i]);
-  }
-
-  v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
-  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);
-  CheckElementValue(isolate, 1, jsobj, 1);
-  obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 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());
+v8::Handle<v8::Value> RejectValue() {
+  return CcTest::global()->Get(v8_str("value"));
+}
 
-  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());
+void ResetPromiseStates() {
+  promise_reject_counter = 0;
+  promise_revoke_counter = 0;
+  promise_reject_msg_line_number = -1;
+  promise_reject_msg_column_number = -1;
+  promise_reject_line_number = -1;
+  promise_reject_column_number = -1;
+  promise_reject_frame_count = -1;
+  CcTest::global()->Set(v8_str("rejected"), v8_str(""));
+  CcTest::global()->Set(v8_str("value"), v8_str(""));
+  CcTest::global()->Set(v8_str("revoked"), v8_str(""));
+}
 
-  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());
+TEST(PromiseRejectCallback) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
 
-  result = CompileRun("var sum = 0;"
-                      "for (var i = 0; i < 8; i++) {"
-                      "  sum += pixels[i] = pixels[i] = i;"
-                      "}"
-                      "sum;");
-  CHECK_EQ(28, result->Int32Value());
+  isolate->SetPromiseRejectCallback(PromiseRejectCallback);
 
-  result = CompileRun("var sum = 0;"
-                      "for (var i = 0; i < 8; i++) {"
-                      "  sum += pixels[i];"
-                      "}"
-                      "sum;");
-  CHECK_EQ(28, result->Int32Value());
+  ResetPromiseStates();
 
-  i::Handle<i::Smi> value(i::Smi::FromInt(2),
-                          reinterpret_cast<i::Isolate*>(context->GetIsolate()));
-  i::Handle<i::Object> no_failure;
-  no_failure =
-      i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
-  ASSERT(!no_failure.is_null());
-  i::USE(no_failure);
-  CheckElementValue(isolate, 2, jsobj, 1);
-  *value.location() = i::Smi::FromInt(256);
-  no_failure =
-      i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
-  ASSERT(!no_failure.is_null());
-  i::USE(no_failure);
-  CheckElementValue(isolate, 255, jsobj, 1);
-  *value.location() = i::Smi::FromInt(-1);
-  no_failure =
-      i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
-  ASSERT(!no_failure.is_null());
-  i::USE(no_failure);
-  CheckElementValue(isolate, 0, jsobj, 1);
+  // Create promise p0.
+  CompileRun(
+      "var reject;            \n"
+      "var p0 = new Promise(  \n"
+      "  function(res, rej) { \n"
+      "    reject = rej;      \n"
+      "  }                    \n"
+      ");                     \n");
+  CHECK(!GetPromise("p0")->HasHandler());
+  CHECK_EQ(0, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+
+  // Add resolve handler (and default reject handler) to p0.
+  CompileRun("var p1 = p0.then(function(){});");
+  CHECK(GetPromise("p0")->HasHandler());
+  CHECK(!GetPromise("p1")->HasHandler());
+  CHECK_EQ(0, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+
+  // Reject p0.
+  CompileRun("reject('ppp');");
+  CHECK(GetPromise("p0")->HasHandler());
+  CHECK(!GetPromise("p1")->HasHandler());
+  CHECK_EQ(1, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+  CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
+  CHECK(GetPromise("rejected")->Equals(GetPromise("p1")));
+  CHECK(RejectValue()->Equals(v8_str("ppp")));
+
+  // Reject p0 again. Callback is not triggered again.
+  CompileRun("reject();");
+  CHECK(GetPromise("p0")->HasHandler());
+  CHECK(!GetPromise("p1")->HasHandler());
+  CHECK_EQ(1, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+
+  // Add resolve handler to p1.
+  CompileRun("var p2 = p1.then(function(){});");
+  CHECK(GetPromise("p0")->HasHandler());
+  CHECK(GetPromise("p1")->HasHandler());
+  CHECK(!GetPromise("p2")->HasHandler());
+  CHECK_EQ(2, promise_reject_counter);
+  CHECK_EQ(1, promise_revoke_counter);
+  CHECK(GetPromise("rejected")->Equals(GetPromise("p2")));
+  CHECK(RejectValue()->Equals(v8_str("ppp")));
+  CHECK(GetPromise("revoked")->Equals(GetPromise("p1")));
+
+  ResetPromiseStates();
+
+  // Create promise q0.
+  CompileRun(
+      "var q0 = new Promise(  \n"
+      "  function(res, rej) { \n"
+      "    reject = rej;      \n"
+      "  }                    \n"
+      ");                     \n");
+  CHECK(!GetPromise("q0")->HasHandler());
+  CHECK_EQ(0, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+
+  // Add reject handler to q0.
+  CompileRun("var q1 = q0.catch(function() {});");
+  CHECK(GetPromise("q0")->HasHandler());
+  CHECK(!GetPromise("q1")->HasHandler());
+  CHECK_EQ(0, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+
+  // Reject q0.
+  CompileRun("reject('qq')");
+  CHECK(GetPromise("q0")->HasHandler());
+  CHECK(!GetPromise("q1")->HasHandler());
+  CHECK_EQ(0, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+
+  // Add a new reject handler, which rejects by returning Promise.reject().
+  // The returned promise q_ triggers a reject callback at first, only to
+  // revoke it when returning it causes q2 to be rejected.
+  CompileRun(
+      "var q_;"
+      "var q2 = q0.catch(               \n"
+      "   function() {                  \n"
+      "     q_ = Promise.reject('qqq'); \n"
+      "     return q_;                  \n"
+      "   }                             \n"
+      ");                               \n");
+  CHECK(GetPromise("q0")->HasHandler());
+  CHECK(!GetPromise("q1")->HasHandler());
+  CHECK(!GetPromise("q2")->HasHandler());
+  CHECK(GetPromise("q_")->HasHandler());
+  CHECK_EQ(2, promise_reject_counter);
+  CHECK_EQ(1, promise_revoke_counter);
+  CHECK(GetPromise("rejected")->Equals(GetPromise("q2")));
+  CHECK(GetPromise("revoked")->Equals(GetPromise("q_")));
+  CHECK(RejectValue()->Equals(v8_str("qqq")));
+
+  // Add a reject handler to the resolved q1, which rejects by throwing.
+  CompileRun(
+      "var q3 = q1.then(  \n"
+      "   function() {    \n"
+      "     throw 'qqqq'; \n"
+      "   }               \n"
+      ");                 \n");
+  CHECK(GetPromise("q0")->HasHandler());
+  CHECK(GetPromise("q1")->HasHandler());
+  CHECK(!GetPromise("q2")->HasHandler());
+  CHECK(!GetPromise("q3")->HasHandler());
+  CHECK_EQ(3, promise_reject_counter);
+  CHECK_EQ(1, promise_revoke_counter);
+  CHECK(GetPromise("rejected")->Equals(GetPromise("q3")));
+  CHECK(RejectValue()->Equals(v8_str("qqqq")));
+
+  ResetPromiseStates();
+
+  // Create promise r0, which has three handlers, two of which handle rejects.
+  CompileRun(
+      "var r0 = new Promise(             \n"
+      "  function(res, rej) {            \n"
+      "    reject = rej;                 \n"
+      "  }                               \n"
+      ");                                \n"
+      "var r1 = r0.catch(function() {}); \n"
+      "var r2 = r0.then(function() {});  \n"
+      "var r3 = r0.then(function() {},   \n"
+      "                 function() {});  \n");
+  CHECK(GetPromise("r0")->HasHandler());
+  CHECK(!GetPromise("r1")->HasHandler());
+  CHECK(!GetPromise("r2")->HasHandler());
+  CHECK(!GetPromise("r3")->HasHandler());
+  CHECK_EQ(0, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+
+  // Reject r0.
+  CompileRun("reject('rrr')");
+  CHECK(GetPromise("r0")->HasHandler());
+  CHECK(!GetPromise("r1")->HasHandler());
+  CHECK(!GetPromise("r2")->HasHandler());
+  CHECK(!GetPromise("r3")->HasHandler());
+  CHECK_EQ(1, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+  CHECK(GetPromise("rejected")->Equals(GetPromise("r2")));
+  CHECK(RejectValue()->Equals(v8_str("rrr")));
+
+  // Add reject handler to r2.
+  CompileRun("var r4 = r2.catch(function() {});");
+  CHECK(GetPromise("r0")->HasHandler());
+  CHECK(!GetPromise("r1")->HasHandler());
+  CHECK(GetPromise("r2")->HasHandler());
+  CHECK(!GetPromise("r3")->HasHandler());
+  CHECK(!GetPromise("r4")->HasHandler());
+  CHECK_EQ(1, promise_reject_counter);
+  CHECK_EQ(1, promise_revoke_counter);
+  CHECK(GetPromise("revoked")->Equals(GetPromise("r2")));
+  CHECK(RejectValue()->Equals(v8_str("rrr")));
+
+  // Add reject handlers to r4.
+  CompileRun("var r5 = r4.then(function() {}, function() {});");
+  CHECK(GetPromise("r0")->HasHandler());
+  CHECK(!GetPromise("r1")->HasHandler());
+  CHECK(GetPromise("r2")->HasHandler());
+  CHECK(!GetPromise("r3")->HasHandler());
+  CHECK(GetPromise("r4")->HasHandler());
+  CHECK(!GetPromise("r5")->HasHandler());
+  CHECK_EQ(1, promise_reject_counter);
+  CHECK_EQ(1, promise_revoke_counter);
+
+  ResetPromiseStates();
+
+  // Create promise s0, which has three handlers, none of which handle rejects.
+  CompileRun(
+      "var s0 = new Promise(            \n"
+      "  function(res, rej) {           \n"
+      "    reject = rej;                \n"
+      "  }                              \n"
+      ");                               \n"
+      "var s1 = s0.then(function() {}); \n"
+      "var s2 = s0.then(function() {}); \n"
+      "var s3 = s0.then(function() {}); \n");
+  CHECK(GetPromise("s0")->HasHandler());
+  CHECK(!GetPromise("s1")->HasHandler());
+  CHECK(!GetPromise("s2")->HasHandler());
+  CHECK(!GetPromise("s3")->HasHandler());
+  CHECK_EQ(0, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+
+  // Reject s0.
+  CompileRun("reject('sss')");
+  CHECK(GetPromise("s0")->HasHandler());
+  CHECK(!GetPromise("s1")->HasHandler());
+  CHECK(!GetPromise("s2")->HasHandler());
+  CHECK(!GetPromise("s3")->HasHandler());
+  CHECK_EQ(3, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+  CHECK(RejectValue()->Equals(v8_str("sss")));
+
+  // Test stack frames.
+  V8::SetCaptureStackTraceForUncaughtExceptions(true);
+
+  ResetPromiseStates();
+
+  // Create promise t0, which is rejected in the constructor with an error.
+  CompileRunWithOrigin(
+      "var t0 = new Promise(  \n"
+      "  function(res, rej) { \n"
+      "    reference_error;   \n"
+      "  }                    \n"
+      ");                     \n",
+      "pro", 0, 0);
+  CHECK(!GetPromise("t0")->HasHandler());
+  CHECK_EQ(1, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+  CHECK_EQ(2, promise_reject_frame_count);
+  CHECK_EQ(3, promise_reject_line_number);
+  CHECK_EQ(5, promise_reject_column_number);
+  CHECK_EQ(3, promise_reject_msg_line_number);
+  CHECK_EQ(5, promise_reject_msg_column_number);
+
+  ResetPromiseStates();
+
+  // Create promise u0 and chain u1 to it, which is rejected via throw.
+  CompileRunWithOrigin(
+      "var u0 = Promise.resolve();        \n"
+      "var u1 = u0.then(                  \n"
+      "           function() {            \n"
+      "             (function() {         \n"
+      "                throw new Error(); \n"
+      "              })();                \n"
+      "           }                       \n"
+      "         );                        \n",
+      "pro", 0, 0);
+  CHECK(GetPromise("u0")->HasHandler());
+  CHECK(!GetPromise("u1")->HasHandler());
+  CHECK_EQ(1, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+  CHECK_EQ(2, promise_reject_frame_count);
+  CHECK_EQ(5, promise_reject_line_number);
+  CHECK_EQ(23, promise_reject_column_number);
+  CHECK_EQ(5, promise_reject_msg_line_number);
+  CHECK_EQ(23, promise_reject_msg_column_number);
+
+  // Throw in u3, which handles u1's rejection.
+  CompileRunWithOrigin(
+      "function f() {                \n"
+      "  return (function() {        \n"
+      "    return new Error();       \n"
+      "  })();                       \n"
+      "}                             \n"
+      "var u2 = Promise.reject(f()); \n"
+      "var u3 = u1.catch(            \n"
+      "           function() {       \n"
+      "             return u2;       \n"
+      "           }                  \n"
+      "         );                   \n",
+      "pro", 0, 0);
+  CHECK(GetPromise("u0")->HasHandler());
+  CHECK(GetPromise("u1")->HasHandler());
+  CHECK(GetPromise("u2")->HasHandler());
+  CHECK(!GetPromise("u3")->HasHandler());
+  CHECK_EQ(3, promise_reject_counter);
+  CHECK_EQ(2, promise_revoke_counter);
+  CHECK_EQ(3, promise_reject_frame_count);
+  CHECK_EQ(3, promise_reject_line_number);
+  CHECK_EQ(12, promise_reject_column_number);
+  CHECK_EQ(3, promise_reject_msg_line_number);
+  CHECK_EQ(12, promise_reject_msg_column_number);
+
+  ResetPromiseStates();
+
+  // Create promise rejected promise v0, which is incorrectly handled by v1
+  // via chaining cycle.
+  CompileRunWithOrigin(
+      "var v0 = Promise.reject(); \n"
+      "var v1 = v0.catch(         \n"
+      "           function() {    \n"
+      "             return v1;    \n"
+      "           }               \n"
+      "         );                \n",
+      "pro", 0, 0);
+  CHECK(GetPromise("v0")->HasHandler());
+  CHECK(!GetPromise("v1")->HasHandler());
+  CHECK_EQ(2, promise_reject_counter);
+  CHECK_EQ(1, promise_revoke_counter);
+  CHECK_EQ(0, promise_reject_frame_count);
+  CHECK_EQ(-1, promise_reject_line_number);
+  CHECK_EQ(-1, promise_reject_column_number);
+
+  ResetPromiseStates();
+
+  // Create promise t1, which rejects by throwing syntax error from eval.
+  CompileRunWithOrigin(
+      "var t1 = new Promise(   \n"
+      "  function(res, rej) {  \n"
+      "    var content = '\\n\\\n"
+      "      }';               \n"
+      "    eval(content);      \n"
+      "  }                     \n"
+      ");                      \n",
+      "pro", 0, 0);
+  CHECK(!GetPromise("t1")->HasHandler());
+  CHECK_EQ(1, promise_reject_counter);
+  CHECK_EQ(0, promise_revoke_counter);
+  CHECK_EQ(2, promise_reject_frame_count);
+  CHECK_EQ(5, promise_reject_line_number);
+  CHECK_EQ(10, promise_reject_column_number);
+  CHECK_EQ(2, promise_reject_msg_line_number);
+  CHECK_EQ(7, promise_reject_msg_column_number);
+}
 
-  result = CompileRun("for (var i = 0; i < 8; i++) {"
-                      "  pixels[i] = (i * 65) - 109;"
-                      "}"
-                      "pixels[1] + pixels[6];");
-  CHECK_EQ(255, result->Int32Value());
-  CheckElementValue(isolate, 0, jsobj, 0);
-  CheckElementValue(isolate, 0, jsobj, 1);
-  CheckElementValue(isolate, 21, jsobj, 2);
-  CheckElementValue(isolate, 86, jsobj, 3);
-  CheckElementValue(isolate, 151, jsobj, 4);
-  CheckElementValue(isolate, 216, jsobj, 5);
-  CheckElementValue(isolate, 255, jsobj, 6);
-  CheckElementValue(isolate, 255, jsobj, 7);
-  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());
-  CheckElementValue(isolate, 0, jsobj, 0);
-  CheckElementValue(isolate, 1, jsobj, 1);
-  CheckElementValue(isolate, 2, jsobj, 2);
-  CheckElementValue(isolate, 3, jsobj, 3);
-  CheckElementValue(isolate, 4, jsobj, 4);
-  CheckElementValue(isolate, 6, jsobj, 5);
-  CheckElementValue(isolate, 7, jsobj, 6);
-  CheckElementValue(isolate, 8, jsobj, 7);
+void AnalyzeStackOfEvalWithSourceURL(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::HandleScope scope(args.GetIsolate());
+  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
+      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
+  CHECK_EQ(5, stackTrace->GetFrameCount());
+  v8::Handle<v8::String> url = v8_str("eval_url");
+  for (int i = 0; i < 3; i++) {
+    v8::Handle<v8::String> name =
+        stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
+    CHECK(!name.IsEmpty());
+    CHECK(url->Equals(name));
+  }
+}
 
-  result = CompileRun("for (var i = 0; i < 8; i++) {"
-                      "  pixels[7] = undefined;"
-                      "}"
-                      "pixels[7];");
-  CHECK_EQ(0, result->Int32Value());
-  CheckElementValue(isolate, 0, jsobj, 7);
 
-  result = CompileRun("for (var i = 0; i < 8; i++) {"
-                      "  pixels[6] = '2.3';"
-                      "}"
-                      "pixels[6];");
-  CHECK_EQ(2, result->Int32Value());
-  CheckElementValue(isolate, 2, jsobj, 6);
+TEST(SourceURLInStackTrace) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
+             v8::FunctionTemplate::New(isolate,
+                                       AnalyzeStackOfEvalWithSourceURL));
+  LocalContext context(0, templ);
 
-  result = CompileRun("for (var i = 0; i < 8; i++) {"
-                      "  pixels[5] = NaN;"
-                      "}"
-                      "pixels[5];");
-  CHECK_EQ(0, result->Int32Value());
-  CheckElementValue(isolate, 0, jsobj, 5);
+  const char *source =
+    "function outer() {\n"
+    "function bar() {\n"
+    "  AnalyzeStackOfEvalWithSourceURL();\n"
+    "}\n"
+    "function foo() {\n"
+    "\n"
+    "  bar();\n"
+    "}\n"
+    "foo();\n"
+    "}\n"
+    "eval('(' + outer +')()%s');";
 
-  result = CompileRun("for (var i = 0; i < 8; i++) {"
-                      "  pixels[8] = Infinity;"
-                      "}"
-                      "pixels[8];");
-  CHECK_EQ(255, result->Int32Value());
-  CheckElementValue(isolate, 255, jsobj, 8);
+  i::ScopedVector<char> code(1024);
+  i::SNPrintF(code, source, "//# sourceURL=eval_url");
+  CHECK(CompileRun(code.start())->IsUndefined());
+  i::SNPrintF(code, source, "//@ sourceURL=eval_url");
+  CHECK(CompileRun(code.start())->IsUndefined());
+}
 
-  result = CompileRun("for (var i = 0; i < 8; i++) {"
-                      "  pixels[9] = -Infinity;"
-                      "}"
-                      "pixels[9];");
-  CHECK_EQ(0, result->Int32Value());
-  CheckElementValue(isolate, 0, jsobj, 9);
 
-  result = CompileRun("pixels[3] = 33;"
-                      "delete pixels[3];"
-                      "pixels[3];");
-  CHECK_EQ(33, result->Int32Value());
+static int scriptIdInStack[2];
 
-  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());
+void AnalyzeScriptIdInStack(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::HandleScope scope(args.GetIsolate());
+  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
+      args.GetIsolate(), 10, v8::StackTrace::kScriptId);
+  CHECK_EQ(2, stackTrace->GetFrameCount());
+  for (int i = 0; i < 2; i++) {
+    scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
+  }
+}
 
-  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());
+TEST(ScriptIdInStackTrace) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->Set(v8_str("AnalyzeScriptIdInStack"),
+             v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
+  LocalContext context(0, templ);
 
-  result = CompileRun("pixels[1] = 23;");
-  CHECK_EQ(23, result->Int32Value());
+  v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
+    isolate,
+    "function foo() {\n"
+    "  AnalyzeScriptIdInStack();"
+    "}\n"
+    "foo();\n");
+  v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
+  script->Run();
+  for (int i = 0; i < 2; i++) {
+    CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
+    CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
+  }
+}
 
-  // Test for index greater than 255.  Regression test for:
-  // http://code.google.com/p/chromium/issues/detail?id=26337.
-  result = CompileRun("pixels[256] = 255;");
-  CHECK_EQ(255, result->Int32Value());
-  result = CompileRun("var i = 0;"
-                      "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
-                      "i");
-  CHECK_EQ(255, result->Int32Value());
-
-  // Make sure that pixel array ICs recognize when a non-pixel array
-  // is passed to it.
-  result = CompileRun("function pa_load(p) {"
-                      "  var sum = 0;"
-                      "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
-                      "  return sum;"
-                      "}"
-                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
-                      "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
-                      "just_ints = new Object();"
-                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
-                      "for (var i = 0; i < 10; ++i) {"
-                      "  result = pa_load(just_ints);"
-                      "}"
-                      "result");
-  CHECK_EQ(32640, result->Int32Value());
-
-  // Make sure that pixel array ICs recognize out-of-bound accesses.
-  result = CompileRun("function pa_load(p, start) {"
-                      "  var sum = 0;"
-                      "  for (var j = start; j < 256; j++) { sum += p[j]; }"
-                      "  return sum;"
-                      "}"
-                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
-                      "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
-                      "for (var i = 0; i < 10; ++i) {"
-                      "  result = pa_load(pixels,-10);"
-                      "}"
-                      "result");
-  CHECK_EQ(0, result->Int32Value());
 
-  // Make sure that generic ICs properly handles a pixel array.
-  result = CompileRun("function pa_load(p) {"
-                      "  var sum = 0;"
-                      "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
-                      "  return sum;"
-                      "}"
-                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
-                      "just_ints = new Object();"
-                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
-                      "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
-                      "for (var i = 0; i < 10; ++i) {"
-                      "  result = pa_load(pixels);"
-                      "}"
-                      "result");
-  CHECK_EQ(32640, result->Int32Value());
-
-  // Make sure that generic load ICs recognize out-of-bound accesses in
-  // pixel arrays.
-  result = CompileRun("function pa_load(p, start) {"
-                      "  var sum = 0;"
-                      "  for (var j = start; j < 256; j++) { sum += p[j]; }"
-                      "  return sum;"
-                      "}"
-                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
-                      "just_ints = new Object();"
-                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
-                      "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
-                      "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
-                      "for (var i = 0; i < 10; ++i) {"
-                      "  result = pa_load(pixels,-10);"
-                      "}"
-                      "result");
-  CHECK_EQ(0, result->Int32Value());
+void AnalyzeStackOfInlineScriptWithSourceURL(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::HandleScope scope(args.GetIsolate());
+  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
+      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
+  CHECK_EQ(4, stackTrace->GetFrameCount());
+  v8::Handle<v8::String> url = v8_str("source_url");
+  for (int i = 0; i < 3; i++) {
+    v8::Handle<v8::String> name =
+        stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
+    CHECK(!name.IsEmpty());
+    CHECK(url->Equals(name));
+  }
+}
 
-  // Make sure that generic ICs properly handles other types than pixel
-  // arrays (that the inlined fast pixel array test leaves the right information
-  // in the right registers).
-  result = CompileRun("function pa_load(p) {"
-                      "  var sum = 0;"
-                      "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
-                      "  return sum;"
-                      "}"
-                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
-                      "just_ints = new Object();"
-                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
-                      "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
-                      "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
-                      "sparse_array = new Object();"
-                      "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
-                      "sparse_array[1000000] = 3;"
-                      "for (var i = 0; i < 10; ++i) {"
-                      "  result = pa_load(sparse_array);"
-                      "}"
-                      "result");
-  CHECK_EQ(32640, result->Int32Value());
 
-  // Make sure that pixel array store ICs clamp values correctly.
-  result = CompileRun("function pa_store(p) {"
-                      "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
-                      "}"
-                      "pa_store(pixels);"
-                      "var sum = 0;"
-                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
-                      "sum");
-  CHECK_EQ(48896, result->Int32Value());
-
-  // Make sure that pixel array stores correctly handle accesses outside
-  // of the pixel array..
-  result = CompileRun("function pa_store(p,start) {"
-                      "  for (var j = 0; j < 256; j++) {"
-                      "    p[j+start] = j * 2;"
-                      "  }"
-                      "}"
-                      "pa_store(pixels,0);"
-                      "pa_store(pixels,-128);"
-                      "var sum = 0;"
-                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
-                      "sum");
-  CHECK_EQ(65280, result->Int32Value());
-
-  // Make sure that the generic store stub correctly handle accesses outside
-  // of the pixel array..
-  result = CompileRun("function pa_store(p,start) {"
-                      "  for (var j = 0; j < 256; j++) {"
-                      "    p[j+start] = j * 2;"
-                      "  }"
-                      "}"
-                      "pa_store(pixels,0);"
-                      "just_ints = new Object();"
-                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
-                      "pa_store(just_ints, 0);"
-                      "pa_store(pixels,-128);"
-                      "var sum = 0;"
-                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
-                      "sum");
-  CHECK_EQ(65280, result->Int32Value());
-
-  // Make sure that the generic keyed store stub clamps pixel array values
-  // correctly.
-  result = CompileRun("function pa_store(p) {"
-                      "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
-                      "}"
-                      "pa_store(pixels);"
-                      "just_ints = new Object();"
-                      "pa_store(just_ints);"
-                      "pa_store(pixels);"
-                      "var sum = 0;"
-                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
-                      "sum");
-  CHECK_EQ(48896, result->Int32Value());
-
-  // Make sure that pixel array loads are optimized by crankshaft.
-  result = CompileRun("function pa_load(p) {"
-                      "  var sum = 0;"
-                      "  for (var i=0; i<256; ++i) {"
-                      "    sum += p[i];"
-                      "  }"
-                      "  return sum; "
-                      "}"
-                      "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
-                      "for (var i = 0; i < 5000; ++i) {"
-                      "  result = pa_load(pixels);"
-                      "}"
-                      "result");
-  CHECK_EQ(32640, result->Int32Value());
+TEST(InlineScriptWithSourceURLInStackTrace) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
+             v8::FunctionTemplate::New(
+                 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
+  LocalContext context(0, templ);
 
-  // Make sure that pixel array stores are optimized by crankshaft.
-  result = CompileRun("function pa_init(p) {"
-                      "for (var i = 0; i < 256; ++i) { p[i] = i; }"
-                      "}"
-                      "function pa_load(p) {"
-                      "  var sum = 0;"
-                      "  for (var i=0; i<256; ++i) {"
-                      "    sum += p[i];"
-                      "  }"
-                      "  return sum; "
-                      "}"
-                      "for (var i = 0; i < 5000; ++i) {"
-                      "  pa_init(pixels);"
-                      "}"
-                      "result = pa_load(pixels);"
-                      "result");
-  CHECK_EQ(32640, result->Int32Value());
+  const char *source =
+    "function outer() {\n"
+    "function bar() {\n"
+    "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
+    "}\n"
+    "function foo() {\n"
+    "\n"
+    "  bar();\n"
+    "}\n"
+    "foo();\n"
+    "}\n"
+    "outer()\n%s";
 
-  free(pixel_data);
+  i::ScopedVector<char> code(1024);
+  i::SNPrintF(code, source, "//# sourceURL=source_url");
+  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
+  i::SNPrintF(code, source, "//@ sourceURL=source_url");
+  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
 }
 
 
-THREADED_TEST(PixelArrayInfo) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  for (int size = 0; size < 100; size += 10) {
-    uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
-    v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
-    obj->SetIndexedPropertiesToPixelData(pixel_data, size);
-    CHECK(obj->HasIndexedPropertiesInPixelData());
-    CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
-    CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
-    free(pixel_data);
+void AnalyzeStackOfDynamicScriptWithSourceURL(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::HandleScope scope(args.GetIsolate());
+  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
+      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
+  CHECK_EQ(4, stackTrace->GetFrameCount());
+  v8::Handle<v8::String> url = v8_str("source_url");
+  for (int i = 0; i < 3; i++) {
+    v8::Handle<v8::String> name =
+        stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
+    CHECK(!name.IsEmpty());
+    CHECK(url->Equals(name));
   }
 }
 
 
-static void NotHandledIndexedPropertyGetter(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
-}
+TEST(DynamicWithSourceURLInStackTrace) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
+             v8::FunctionTemplate::New(
+                 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
+  LocalContext context(0, templ);
 
+  const char *source =
+    "function outer() {\n"
+    "function bar() {\n"
+    "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
+    "}\n"
+    "function foo() {\n"
+    "\n"
+    "  bar();\n"
+    "}\n"
+    "foo();\n"
+    "}\n"
+    "outer()\n%s";
 
-static void NotHandledIndexedPropertySetter(
-    uint32_t index,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
+  i::ScopedVector<char> code(1024);
+  i::SNPrintF(code, source, "//# sourceURL=source_url");
+  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
+  i::SNPrintF(code, source, "//@ sourceURL=source_url");
+  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
 }
 
 
-THREADED_TEST(PixelArrayWithInterceptor) {
+TEST(DynamicWithSourceURLInStackTraceString) {
   LocalContext context;
-  i::Factory* factory = CcTest::i_isolate()->factory();
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  const int kElementCount = 260;
-  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
-  i::Handle<i::ExternalUint8ClampedArray> pixels =
-      i::Handle<i::ExternalUint8ClampedArray>::cast(
-          factory->NewExternalArray(kElementCount,
-                                    v8::kExternalUint8ClampedArray,
-                                    pixel_data));
-  for (int i = 0; i < kElementCount; i++) {
-    pixels->set(i, i % 256);
-  }
-  v8::Handle<v8::ObjectTemplate> templ =
-      v8::ObjectTemplate::New(context->GetIsolate());
-  templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
-                                   NotHandledIndexedPropertySetter);
-  v8::Handle<v8::Object> obj = templ->NewInstance();
-  obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
-  context->Global()->Set(v8_str("pixels"), obj);
-  v8::Handle<v8::Value> 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("pixels.hasOwnProperty('1')");
-  CHECK(result->BooleanValue());
-  free(pixel_data);
-}
+  v8::HandleScope scope(context->GetIsolate());
 
+  const char *source =
+    "function outer() {\n"
+    "  function foo() {\n"
+    "    FAIL.FAIL;\n"
+    "  }\n"
+    "  foo();\n"
+    "}\n"
+    "outer()\n%s";
 
-static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
-  switch (array_type) {
-    case v8::kExternalInt8Array:
-    case v8::kExternalUint8Array:
-    case v8::kExternalUint8ClampedArray:
-      return 1;
-      break;
-    case v8::kExternalInt16Array:
-    case v8::kExternalUint16Array:
-      return 2;
-      break;
-    case v8::kExternalInt32Array:
-    case v8::kExternalUint32Array:
-    case v8::kExternalFloat32Array:
-      return 4;
-      break;
-    case v8::kExternalFloat64Array:
-      return 8;
-      break;
-    default:
-      UNREACHABLE();
-      return -1;
-  }
-  UNREACHABLE();
-  return -1;
+  i::ScopedVector<char> code(1024);
+  i::SNPrintF(code, source, "//# sourceURL=source_url");
+  v8::TryCatch try_catch(context->GetIsolate());
+  CompileRunWithOrigin(code.start(), "", 0, 0);
+  CHECK(try_catch.HasCaught());
+  v8::String::Utf8Value stack(try_catch.StackTrace());
+  CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
 }
 
 
-template <class ExternalArrayClass, class ElementType>
-static void ObjectWithExternalArrayTestHelper(
-    Handle<Context> context,
-    v8::Handle<Object> obj,
-    int element_count,
-    v8::ExternalArrayType array_type,
-    int64_t low, int64_t high) {
-  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
-  i::Isolate* isolate = jsobj->GetIsolate();
-  obj->Set(v8_str("field"),
-           v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
-  context->Global()->Set(v8_str("ext_array"), obj);
-  v8::Handle<v8::Value> result = CompileRun("ext_array.field");
-  CHECK_EQ(1503, result->Int32Value());
-  result = CompileRun("ext_array[1]");
-  CHECK_EQ(1, result->Int32Value());
+TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
-  // Check assigned smis
-  result = CompileRun("for (var i = 0; i < 8; i++) {"
-                      "  ext_array[i] = i;"
-                      "}"
-                      "var sum = 0;"
-                      "for (var i = 0; i < 8; i++) {"
-                      "  sum += ext_array[i];"
-                      "}"
-                      "sum;");
+  const char *source =
+    "function outer() {\n"
+    "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
+    "  //# sourceURL=source_url\";\n"
+    "  eval(scriptContents);\n"
+    "  foo(); }\n"
+    "outer();\n"
+    "//# sourceURL=outer_url";
+
+  v8::TryCatch try_catch(context->GetIsolate());
+  CompileRun(source);
+  CHECK(try_catch.HasCaught());
 
-  CHECK_EQ(28, result->Int32Value());
-  // Check pass through of assigned smis
-  result = CompileRun("var sum = 0;"
-                      "for (var i = 0; i < 8; i++) {"
-                      "  sum += ext_array[i] = ext_array[i] = -i;"
-                      "}"
-                      "sum;");
-  CHECK_EQ(-28, result->Int32Value());
+  Local<v8::Message> message = try_catch.Message();
+  Handle<Value> sourceURL =
+    message->GetScriptOrigin().ResourceName();
+  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
+}
 
 
-  // Check assigned smis in reverse order
-  result = CompileRun("for (var i = 8; --i >= 0; ) {"
-                      "  ext_array[i] = i;"
-                      "}"
-                      "var sum = 0;"
-                      "for (var i = 0; i < 8; i++) {"
-                      "  sum += ext_array[i];"
-                      "}"
-                      "sum;");
-  CHECK_EQ(28, result->Int32Value());
+TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
-  // Check pass through of assigned HeapNumbers
-  result = CompileRun("var sum = 0;"
-                      "for (var i = 0; i < 16; i+=2) {"
-                      "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
-                      "}"
-                      "sum;");
-  CHECK_EQ(-28, result->Int32Value());
+  const char *source =
+    "function outer() {\n"
+    "  var scriptContents = \"function boo(){ boo(); }\\\n"
+    "  //# sourceURL=source_url\";\n"
+    "  eval(scriptContents);\n"
+    "  boo(); }\n"
+    "outer();\n"
+    "//# sourceURL=outer_url";
+
+  v8::TryCatch try_catch(context->GetIsolate());
+  CompileRun(source);
+  CHECK(try_catch.HasCaught());
 
-  // Check assigned HeapNumbers
-  result = CompileRun("for (var i = 0; i < 16; i+=2) {"
-                      "  ext_array[i] = (i * 0.5);"
-                      "}"
-                      "var sum = 0;"
-                      "for (var i = 0; i < 16; i+=2) {"
-                      "  sum += ext_array[i];"
-                      "}"
-                      "sum;");
-  CHECK_EQ(28, result->Int32Value());
+  Local<v8::Message> message = try_catch.Message();
+  Handle<Value> sourceURL =
+    message->GetScriptOrigin().ResourceName();
+  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
+}
 
-  // Check assigned HeapNumbers in reverse order
-  result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
-                      "  ext_array[i] = (i * 0.5);"
-                      "}"
-                      "var sum = 0;"
-                      "for (var i = 0; i < 16; i+=2) {"
-                      "  sum += ext_array[i];"
-                      "}"
-                      "sum;");
-  CHECK_EQ(28, result->Int32Value());
 
-  i::ScopedVector<char> test_buf(1024);
+static void CreateGarbageInOldSpace() {
+  i::Factory* factory = CcTest::i_isolate()->factory();
+  v8::HandleScope scope(CcTest::isolate());
+  i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
+  for (int i = 0; i < 1000; i++) {
+    factory->NewFixedArray(1000, i::TENURED);
+  }
+}
+
+
+// Test that idle notification can be handled and eventually collects garbage.
+TEST(TestIdleNotification) {
+  if (!i::FLAG_incremental_marking) return;
+  const intptr_t MB = 1024 * 1024;
+  const double IdlePauseInSeconds = 1.0;
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
+  CreateGarbageInOldSpace();
+  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
+  CHECK_GT(size_with_garbage, initial_size + MB);
+  bool finished = false;
+  for (int i = 0; i < 200 && !finished; i++) {
+    if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
+      CcTest::heap()->StartIdleIncrementalMarking();
+    }
+    finished = env->GetIsolate()->IdleNotificationDeadline(
+        (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
+         static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
+        IdlePauseInSeconds);
+    if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
+      CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
+    }
+  }
+  intptr_t final_size = CcTest::heap()->SizeOfObjects();
+  CHECK(finished);
+  CHECK_LT(final_size, initial_size + 1);
+}
+
 
-  // Check legal boundary conditions.
-  // The repeated loads and stores ensure the ICs are exercised.
-  const char* boundary_program =
-      "var res = 0;"
-      "for (var i = 0; i < 16; i++) {"
-      "  ext_array[i] = %lld;"
-      "  if (i > 8) {"
-      "    res = ext_array[i];"
-      "  }"
-      "}"
-      "res;";
-  i::OS::SNPrintF(test_buf,
-                  boundary_program,
-                  low);
-  result = CompileRun(test_buf.start());
-  CHECK_EQ(low, result->IntegerValue());
+TEST(Regress2333) {
+  LocalContext env;
+  for (int i = 0; i < 3; i++) {
+    CcTest::heap()->CollectGarbage(i::NEW_SPACE);
+  }
+}
 
-  i::OS::SNPrintF(test_buf,
-                  boundary_program,
-                  high);
-  result = CompileRun(test_buf.start());
-  CHECK_EQ(high, result->IntegerValue());
+static uint32_t* stack_limit;
 
-  // Check misprediction of type in IC.
-  result = CompileRun("var tmp_array = ext_array;"
-                      "var sum = 0;"
-                      "for (var i = 0; i < 8; i++) {"
-                      "  tmp_array[i] = i;"
-                      "  sum += tmp_array[i];"
-                      "  if (i == 4) {"
-                      "    tmp_array = {};"
-                      "  }"
-                      "}"
-                      "sum;");
-  // Force GC to trigger verification.
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CHECK_EQ(28, result->Int32Value());
+static void GetStackLimitCallback(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  stack_limit = reinterpret_cast<uint32_t*>(
+      CcTest::i_isolate()->stack_guard()->real_climit());
+}
 
-  // Make sure out-of-range loads do not throw.
-  i::OS::SNPrintF(test_buf,
-                  "var caught_exception = false;"
-                  "try {"
-                  "  ext_array[%d];"
-                  "} catch (e) {"
-                  "  caught_exception = true;"
-                  "}"
-                  "caught_exception;",
-                  element_count);
-  result = CompileRun(test_buf.start());
-  CHECK_EQ(false, result->BooleanValue());
 
-  // Make sure out-of-range stores do not throw.
-  i::OS::SNPrintF(test_buf,
-                  "var caught_exception = false;"
-                  "try {"
-                  "  ext_array[%d] = 1;"
-                  "} catch (e) {"
-                  "  caught_exception = true;"
-                  "}"
-                  "caught_exception;",
-                  element_count);
-  result = CompileRun(test_buf.start());
-  CHECK_EQ(false, result->BooleanValue());
+// 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;
+}
 
-  // Check other boundary conditions, values and operations.
-  result = CompileRun("for (var i = 0; i < 8; i++) {"
-                      "  ext_array[7] = undefined;"
-                      "}"
-                      "ext_array[7];");
-  CHECK_EQ(0, result->Int32Value());
-  if (array_type == v8::kExternalFloat64Array ||
-      array_type == v8::kExternalFloat32Array) {
-    CHECK_EQ(static_cast<int>(i::OS::nan_value()),
-             static_cast<int>(
-                 jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
-  } else {
-    CheckElementValue(isolate, 0, jsobj, 7);
-  }
 
-  result = CompileRun("for (var i = 0; i < 8; i++) {"
-                      "  ext_array[6] = '2.3';"
-                      "}"
-                      "ext_array[6];");
-  CHECK_EQ(2, result->Int32Value());
-  CHECK_EQ(2,
-           static_cast<int>(
-               jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
+// We need at least 165kB for an x64 debug build with clang and ASAN.
+static const int stack_breathing_room = 256 * i::KB;
 
-  if (array_type != v8::kExternalFloat32Array &&
-      array_type != v8::kExternalFloat64Array) {
-    // Though the specification doesn't state it, be explicit about
-    // converting NaNs and +/-Infinity to zero.
-    result = CompileRun("for (var i = 0; i < 8; i++) {"
-                        "  ext_array[i] = 5;"
-                        "}"
-                        "for (var i = 0; i < 8; i++) {"
-                        "  ext_array[i] = NaN;"
-                        "}"
-                        "ext_array[5];");
-    CHECK_EQ(0, result->Int32Value());
-    CheckElementValue(isolate, 0, jsobj, 5);
 
-    result = CompileRun("for (var i = 0; i < 8; i++) {"
-                        "  ext_array[i] = 5;"
-                        "}"
-                        "for (var i = 0; i < 8; i++) {"
-                        "  ext_array[i] = Infinity;"
-                        "}"
-                        "ext_array[5];");
-    int expected_value =
-        (array_type == v8::kExternalUint8ClampedArray) ? 255 : 0;
-    CHECK_EQ(expected_value, result->Int32Value());
-    CheckElementValue(isolate, expected_value, jsobj, 5);
+TEST(SetStackLimit) {
+  uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
 
-    result = CompileRun("for (var i = 0; i < 8; i++) {"
-                        "  ext_array[i] = 5;"
-                        "}"
-                        "for (var i = 0; i < 8; i++) {"
-                        "  ext_array[i] = -Infinity;"
-                        "}"
-                        "ext_array[5];");
-    CHECK_EQ(0, result->Int32Value());
-    CheckElementValue(isolate, 0, jsobj, 5);
+  // Set stack limit.
+  CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
 
-    // Check truncation behavior of integral arrays.
-    const char* unsigned_data =
-        "var source_data = [0.6, 10.6];"
-        "var expected_results = [0, 10];";
-    const char* signed_data =
-        "var source_data = [0.6, 10.6, -0.6, -10.6];"
-        "var expected_results = [0, 10, 0, -10];";
-    const char* pixel_data =
-        "var source_data = [0.6, 10.6];"
-        "var expected_results = [1, 11];";
-    bool is_unsigned =
-        (array_type == v8::kExternalUint8Array ||
-         array_type == v8::kExternalUint16Array ||
-         array_type == v8::kExternalUint32Array);
-    bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
-
-    i::OS::SNPrintF(test_buf,
-                    "%s"
-                    "var all_passed = true;"
-                    "for (var i = 0; i < source_data.length; i++) {"
-                    "  for (var j = 0; j < 8; j++) {"
-                    "    ext_array[j] = source_data[i];"
-                    "  }"
-                    "  all_passed = all_passed &&"
-                    "               (ext_array[5] == expected_results[i]);"
-                    "}"
-                    "all_passed;",
-                    (is_unsigned ?
-                         unsigned_data :
-                         (is_pixel_data ? pixel_data : signed_data)));
-    result = CompileRun(test_buf.start());
-    CHECK_EQ(true, result->BooleanValue());
-  }
+  // Execute a script.
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  Local<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
+  Local<Function> fun = fun_templ->GetFunction();
+  env->Global()->Set(v8_str("get_stack_limit"), fun);
+  CompileRun("get_stack_limit();");
 
-  i::Handle<ExternalArrayClass> array(
-      ExternalArrayClass::cast(jsobj->elements()));
-  for (int i = 0; i < element_count; i++) {
-    array->set(i, static_cast<ElementType>(i));
-  }
+  CHECK(stack_limit == set_limit);
+}
 
-  // Test complex assignments
-  result = CompileRun("function ee_op_test_complex_func(sum) {"
-                      " for (var i = 0; i < 40; ++i) {"
-                      "   sum += (ext_array[i] += 1);"
-                      "   sum += (ext_array[i] -= 1);"
-                      " } "
-                      " return sum;"
-                      "}"
-                      "sum=0;"
-                      "for (var i=0;i<10000;++i) {"
-                      "  sum=ee_op_test_complex_func(sum);"
-                      "}"
-                      "sum;");
-  CHECK_EQ(16000000, result->Int32Value());
 
-  // Test count operations
-  result = CompileRun("function ee_op_test_count_func(sum) {"
-                      " for (var i = 0; i < 40; ++i) {"
-                      "   sum += (++ext_array[i]);"
-                      "   sum += (--ext_array[i]);"
-                      " } "
-                      " return sum;"
-                      "}"
-                      "sum=0;"
-                      "for (var i=0;i<10000;++i) {"
-                      "  sum=ee_op_test_count_func(sum);"
-                      "}"
-                      "sum;");
-  CHECK_EQ(16000000, result->Int32Value());
+TEST(SetStackLimitInThread) {
+  uint32_t* set_limit;
+  {
+    v8::Locker locker(CcTest::isolate());
+    set_limit = ComputeStackLimit(stack_breathing_room);
 
-  result = CompileRun("ext_array[3] = 33;"
-                      "delete ext_array[3];"
-                      "ext_array[3];");
-  CHECK_EQ(33, result->Int32Value());
+    // Set stack limit.
+    CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
 
-  result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
-                      "ext_array[2] = 12; ext_array[3] = 13;"
-                      "ext_array.__defineGetter__('2',"
-                      "function() { return 120; });"
-                      "ext_array[2];");
-  CHECK_EQ(12, result->Int32Value());
+    // Execute a script.
+    v8::HandleScope scope(CcTest::isolate());
+    LocalContext env;
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("get_stack_limit"), fun);
+    CompileRun("get_stack_limit();");
 
-  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());
+    CHECK(stack_limit == set_limit);
+  }
+  {
+    v8::Locker locker(CcTest::isolate());
+    CHECK(stack_limit == set_limit);
+  }
+}
 
-  result = CompileRun("ext_array[1] = 23;"
-                      "ext_array.__proto__ = [];"
-                      "js_array.__proto__ = ext_array;"
-                      "js_array.concat(ext_array);");
-  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("ext_array[1] = 23;");
-  CHECK_EQ(23, result->Int32Value());
+THREADED_TEST(GetHeapStatistics) {
+  LocalContext c1;
+  v8::HandleScope scope(c1->GetIsolate());
+  v8::HeapStatistics heap_statistics;
+  CHECK_EQ(0u, heap_statistics.total_heap_size());
+  CHECK_EQ(0u, heap_statistics.used_heap_size());
+  c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
+  CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
+  CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
 }
 
 
-template <class FixedTypedArrayClass,
-          i::ElementsKind elements_kind,
-          class ElementType>
-static void FixedTypedArrayTestHelper(
-    v8::ExternalArrayType array_type,
-    ElementType low,
-    ElementType high) {
-  i::FLAG_allow_natives_syntax = true;
-  LocalContext context;
-  i::Isolate* isolate = CcTest::i_isolate();
-  i::Factory* factory = isolate->factory();
-  v8::HandleScope scope(context->GetIsolate());
-  const int kElementCount = 260;
-  i::Handle<FixedTypedArrayClass> fixed_array =
-    i::Handle<FixedTypedArrayClass>::cast(
-        factory->NewFixedTypedArray(kElementCount, array_type));
-  CHECK_EQ(FixedTypedArrayClass::kInstanceType,
-           fixed_array->map()->instance_type());
-  CHECK_EQ(kElementCount, fixed_array->length());
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  for (int i = 0; i < kElementCount; i++) {
-    fixed_array->set(i, static_cast<ElementType>(i));
+class VisitorImpl : public v8::ExternalResourceVisitor {
+ public:
+  explicit VisitorImpl(TestResource** resource) {
+    for (int i = 0; i < 4; i++) {
+      resource_[i] = resource[i];
+      found_resource_[i] = false;
+    }
+  }
+  virtual ~VisitorImpl() {}
+  virtual void VisitExternalString(v8::Handle<v8::String> string) {
+    if (!string->IsExternal()) {
+      CHECK(string->IsExternalOneByte());
+      return;
+    }
+    v8::String::ExternalStringResource* resource =
+        string->GetExternalStringResource();
+    CHECK(resource);
+    for (int i = 0; i < 4; i++) {
+      if (resource_[i] == resource) {
+        CHECK(!found_resource_[i]);
+        found_resource_[i] = true;
+      }
+    }
   }
-  // Force GC to trigger verification.
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  for (int i = 0; i < kElementCount; i++) {
-    CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
-             static_cast<int64_t>(fixed_array->get_scalar(i)));
+  void CheckVisitedResources() {
+    for (int i = 0; i < 4; i++) {
+      CHECK(found_resource_[i]);
+    }
   }
-  v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
-  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
-  i::Handle<i::Map> fixed_array_map =
-      isolate->factory()->GetElementsTransitionMap(jsobj, elements_kind);
-  jsobj->set_map(*fixed_array_map);
-  jsobj->set_elements(*fixed_array);
 
-  ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
-      context.local(), obj, kElementCount, array_type,
-      static_cast<int64_t>(low),
-      static_cast<int64_t>(high));
-}
+ private:
+  v8::String::ExternalStringResource* resource_[4];
+  bool found_resource_[4];
+};
 
 
-THREADED_TEST(FixedUint8Array) {
-  FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
-    v8::kExternalUint8Array,
-    0x0, 0xFF);
-}
+TEST(ExternalizeOldSpaceTwoByteCons) {
+  v8::Isolate* isolate = CcTest::isolate();
+  LocalContext env;
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::String> cons =
+      CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
+  CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
+  CcTest::heap()->CollectAllAvailableGarbage();
+  CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
 
+  TestResource* resource = new TestResource(
+      AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
+  cons->MakeExternal(resource);
 
-THREADED_TEST(FixedUint8ClampedArray) {
-  FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
-                            i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
-    v8::kExternalUint8ClampedArray,
-    0x0, 0xFF);
+  CHECK(cons->IsExternal());
+  CHECK_EQ(resource, cons->GetExternalStringResource());
+  String::Encoding encoding;
+  CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
+  CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
 }
 
 
-THREADED_TEST(FixedInt8Array) {
-  FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
-    v8::kExternalInt8Array,
-    -0x80, 0x7F);
-}
+TEST(ExternalizeOldSpaceOneByteCons) {
+  v8::Isolate* isolate = CcTest::isolate();
+  LocalContext env;
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::String> cons =
+      CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
+  CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
+  CcTest::heap()->CollectAllAvailableGarbage();
+  CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
 
+  TestOneByteResource* resource =
+      new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
+  cons->MakeExternal(resource);
 
-THREADED_TEST(FixedUint16Array) {
-  FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
-    v8::kExternalUint16Array,
-    0x0, 0xFFFF);
+  CHECK(cons->IsExternalOneByte());
+  CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
+  String::Encoding encoding;
+  CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
+  CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
 }
 
 
-THREADED_TEST(FixedInt16Array) {
-  FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
-    v8::kExternalInt16Array,
-    -0x8000, 0x7FFF);
-}
+TEST(VisitExternalStrings) {
+  v8::Isolate* isolate = CcTest::isolate();
+  LocalContext env;
+  v8::HandleScope scope(isolate);
+  const char* string = "Some string";
+  uint16_t* two_byte_string = AsciiToTwoByteString(string);
+  TestResource* resource[4];
+  resource[0] = new TestResource(two_byte_string);
+  v8::Local<v8::String> string0 =
+      v8::String::NewExternal(env->GetIsolate(), resource[0]);
+  resource[1] = new TestResource(two_byte_string, NULL, false);
+  v8::Local<v8::String> string1 =
+      v8::String::NewExternal(env->GetIsolate(), resource[1]);
 
+  // Externalized symbol.
+  resource[2] = new TestResource(two_byte_string, NULL, false);
+  v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
+      env->GetIsolate(), string, v8::String::kInternalizedString);
+  CHECK(string2->MakeExternal(resource[2]));
 
-THREADED_TEST(FixedUint32Array) {
-  FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
-    v8::kExternalUint32Array,
-    0x0, UINT_MAX);
-}
+  // Symbolized External.
+  resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
+  v8::Local<v8::String> string3 =
+      v8::String::NewExternal(env->GetIsolate(), resource[3]);
+  CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
+  // Turn into a symbol.
+  i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
+  CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
+      string3_i).is_null());
+  CHECK(string3_i->IsInternalizedString());
 
+  // We need to add usages for string* to avoid warnings in GCC 4.7
+  CHECK(string0->IsExternal());
+  CHECK(string1->IsExternal());
+  CHECK(string2->IsExternal());
+  CHECK(string3->IsExternal());
 
-THREADED_TEST(FixedInt32Array) {
-  FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
-    v8::kExternalInt32Array,
-    INT_MIN, INT_MAX);
+  VisitorImpl visitor(resource);
+  v8::V8::VisitExternalResources(&visitor);
+  visitor.CheckVisitedResources();
 }
 
 
-THREADED_TEST(FixedFloat32Array) {
-  FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
-    v8::kExternalFloat32Array,
-    -500, 500);
-}
-
+TEST(ExternalStringCollectedAtTearDown) {
+  int destroyed = 0;
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  { v8::Isolate::Scope isolate_scope(isolate);
+    v8::HandleScope handle_scope(isolate);
+    const char* s = "One string to test them all, one string to find them.";
+    TestOneByteResource* inscription =
+        new TestOneByteResource(i::StrDup(s), &destroyed);
+    v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
+    // Ring is still alive.  Orcs are roaming freely across our lands.
+    CHECK_EQ(0, destroyed);
+    USE(ring);
+  }
 
-THREADED_TEST(FixedFloat64Array) {
-  FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
-    v8::kExternalFloat64Array,
-    -500, 500);
+  isolate->Dispose();
+  // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
+  CHECK_EQ(1, destroyed);
 }
 
 
-template <class ExternalArrayClass, class ElementType>
-static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
-                                    int64_t low,
-                                    int64_t high) {
-  LocalContext context;
-  i::Isolate* isolate = CcTest::i_isolate();
-  i::Factory* factory = isolate->factory();
-  v8::HandleScope scope(context->GetIsolate());
-  const int kElementCount = 40;
-  int element_size = ExternalArrayElementSize(array_type);
-  ElementType* array_data =
-      static_cast<ElementType*>(malloc(kElementCount * element_size));
-  i::Handle<ExternalArrayClass> array =
-      i::Handle<ExternalArrayClass>::cast(
-          factory->NewExternalArray(kElementCount, array_type, array_data));
-  // Force GC to trigger verification.
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  for (int i = 0; i < kElementCount; i++) {
-    array->set(i, static_cast<ElementType>(i));
-  }
-  // Force GC to trigger verification.
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  for (int i = 0; i < kElementCount; i++) {
-    CHECK_EQ(static_cast<int64_t>(i),
-             static_cast<int64_t>(array->get_scalar(i)));
-    CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
+TEST(ExternalInternalizedStringCollectedAtTearDown) {
+  int destroyed = 0;
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  { v8::Isolate::Scope isolate_scope(isolate);
+    LocalContext env(isolate);
+    v8::HandleScope handle_scope(isolate);
+    CompileRun("var ring = 'One string to test them all';");
+    const char* s = "One string to test them all";
+    TestOneByteResource* inscription =
+        new TestOneByteResource(i::StrDup(s), &destroyed);
+    v8::Local<v8::String> ring = CompileRun("ring")->ToString(isolate);
+    CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
+    ring->MakeExternal(inscription);
+    // Ring is still alive.  Orcs are roaming freely across our lands.
+    CHECK_EQ(0, destroyed);
+    USE(ring);
   }
 
-  v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
-  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
-  // Set the elements to be the external array.
-  obj->SetIndexedPropertiesToExternalArrayData(array_data,
-                                               array_type,
-                                               kElementCount);
-  CHECK_EQ(1,
-           static_cast<int>(
-               jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
-
-  ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
-      context.local(), obj, kElementCount, array_type, low, high);
+  isolate->Dispose();
+  // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
+  CHECK_EQ(1, destroyed);
+}
 
-  v8::Handle<v8::Value> result;
 
-  // Test more complex manipulations which cause eax to contain values
-  // that won't be completely overwritten by loads from the arrays.
-  // This catches bugs in the instructions used for the KeyedLoadIC
-  // for byte and word types.
-  {
-    const int kXSize = 300;
-    const int kYSize = 300;
-    const int kLargeElementCount = kXSize * kYSize * 4;
-    ElementType* large_array_data =
-        static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
-    v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
-    // Set the elements to be the external array.
-    large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
-                                                       array_type,
-                                                       kLargeElementCount);
-    context->Global()->Set(v8_str("large_array"), large_obj);
-    // Initialize contents of a few rows.
-    for (int x = 0; x < 300; x++) {
-      int row = 0;
-      int offset = row * 300 * 4;
-      large_array_data[offset + 4 * x + 0] = (ElementType) 127;
-      large_array_data[offset + 4 * x + 1] = (ElementType) 0;
-      large_array_data[offset + 4 * x + 2] = (ElementType) 0;
-      large_array_data[offset + 4 * x + 3] = (ElementType) 127;
-      row = 150;
-      offset = row * 300 * 4;
-      large_array_data[offset + 4 * x + 0] = (ElementType) 127;
-      large_array_data[offset + 4 * x + 1] = (ElementType) 0;
-      large_array_data[offset + 4 * x + 2] = (ElementType) 0;
-      large_array_data[offset + 4 * x + 3] = (ElementType) 127;
-      row = 298;
-      offset = row * 300 * 4;
-      large_array_data[offset + 4 * x + 0] = (ElementType) 127;
-      large_array_data[offset + 4 * x + 1] = (ElementType) 0;
-      large_array_data[offset + 4 * x + 2] = (ElementType) 0;
-      large_array_data[offset + 4 * x + 3] = (ElementType) 127;
-    }
-    // The goal of the code below is to make "offset" large enough
-    // that the computation of the index (which goes into eax) has
-    // high bits set which will not be overwritten by a byte or short
-    // load.
-    result = CompileRun("var failed = false;"
-                        "var offset = 0;"
-                        "for (var i = 0; i < 300; i++) {"
-                        "  if (large_array[4 * i] != 127 ||"
-                        "      large_array[4 * i + 1] != 0 ||"
-                        "      large_array[4 * i + 2] != 0 ||"
-                        "      large_array[4 * i + 3] != 127) {"
-                        "    failed = true;"
-                        "  }"
-                        "}"
-                        "offset = 150 * 300 * 4;"
-                        "for (var i = 0; i < 300; i++) {"
-                        "  if (large_array[offset + 4 * i] != 127 ||"
-                        "      large_array[offset + 4 * i + 1] != 0 ||"
-                        "      large_array[offset + 4 * i + 2] != 0 ||"
-                        "      large_array[offset + 4 * i + 3] != 127) {"
-                        "    failed = true;"
-                        "  }"
-                        "}"
-                        "offset = 298 * 300 * 4;"
-                        "for (var i = 0; i < 300; i++) {"
-                        "  if (large_array[offset + 4 * i] != 127 ||"
-                        "      large_array[offset + 4 * i + 1] != 0 ||"
-                        "      large_array[offset + 4 * i + 2] != 0 ||"
-                        "      large_array[offset + 4 * i + 3] != 127) {"
-                        "    failed = true;"
-                        "  }"
-                        "}"
-                        "!failed;");
-    CHECK_EQ(true, result->BooleanValue());
-    free(large_array_data);
+TEST(ExternalInternalizedStringCollectedAtGC) {
+  int destroyed = 0;
+  { LocalContext env;
+    v8::HandleScope handle_scope(env->GetIsolate());
+    CompileRun("var ring = 'One string to test them all';");
+    const char* s = "One string to test them all";
+    TestOneByteResource* inscription =
+        new TestOneByteResource(i::StrDup(s), &destroyed);
+    v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
+    CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
+    ring->MakeExternal(inscription);
+    // Ring is still alive.  Orcs are roaming freely across our lands.
+    CHECK_EQ(0, destroyed);
+    USE(ring);
   }
 
-  // The "" property descriptor is overloaded to store information about
-  // the external array. Ensure that setting and accessing the "" property
-  // works (it should overwrite the information cached about the external
-  // array in the DescriptorArray) in various situations.
-  result = CompileRun("ext_array[''] = 23; ext_array['']");
-  CHECK_EQ(23, result->Int32Value());
-
-  // Property "" set after the external array is associated with the object.
-  {
-    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
-    obj2->Set(v8_str("ee_test_field"),
-              v8::Int32::New(context->GetIsolate(), 256));
-    obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
-    // Set the elements to be the external array.
-    obj2->SetIndexedPropertiesToExternalArrayData(array_data,
-                                                  array_type,
-                                                  kElementCount);
-    context->Global()->Set(v8_str("ext_array"), obj2);
-    result = CompileRun("ext_array['']");
-    CHECK_EQ(1503, result->Int32Value());
-  }
-
-  // Property "" set after the external array is associated with the object.
-  {
-    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
-    obj2->Set(v8_str("ee_test_field_2"),
-              v8::Int32::New(context->GetIsolate(), 256));
-    // Set the elements to be the external array.
-    obj2->SetIndexedPropertiesToExternalArrayData(array_data,
-                                                  array_type,
-                                                  kElementCount);
-    obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
-    context->Global()->Set(v8_str("ext_array"), obj2);
-    result = CompileRun("ext_array['']");
-    CHECK_EQ(1503, result->Int32Value());
-  }
-
-  // Should reuse the map from previous test.
-  {
-    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
-    obj2->Set(v8_str("ee_test_field_2"),
-              v8::Int32::New(context->GetIsolate(), 256));
-    // Set the elements to be the external array. Should re-use the map
-    // from previous test.
-    obj2->SetIndexedPropertiesToExternalArrayData(array_data,
-                                                  array_type,
-                                                  kElementCount);
-    context->Global()->Set(v8_str("ext_array"), obj2);
-    result = CompileRun("ext_array['']");
-  }
-
-  // Property "" is a constant function that shouldn't not be interfered with
-  // when an external array is set.
-  {
-    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
-    // Start
-    obj2->Set(v8_str("ee_test_field3"),
-              v8::Int32::New(context->GetIsolate(), 256));
-
-    // Add a constant function to an object.
-    context->Global()->Set(v8_str("ext_array"), obj2);
-    result = CompileRun("ext_array[''] = function() {return 1503;};"
-                        "ext_array['']();");
-
-    // Add an external array transition to the same map that
-    // has the constant transition.
-    v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
-    obj3->Set(v8_str("ee_test_field3"),
-              v8::Int32::New(context->GetIsolate(), 256));
-    obj3->SetIndexedPropertiesToExternalArrayData(array_data,
-                                                  array_type,
-                                                  kElementCount);
-    context->Global()->Set(v8_str("ext_array"), obj3);
-  }
-
-  // If a external array transition is in the map, it should get clobbered
-  // by a constant function.
-  {
-    // Add an external array transition.
-    v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
-    obj3->Set(v8_str("ee_test_field4"),
-              v8::Int32::New(context->GetIsolate(), 256));
-    obj3->SetIndexedPropertiesToExternalArrayData(array_data,
-                                                  array_type,
-                                                  kElementCount);
-
-    // Add a constant function to the same map that just got an external array
-    // transition.
-    v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
-    obj2->Set(v8_str("ee_test_field4"),
-              v8::Int32::New(context->GetIsolate(), 256));
-    context->Global()->Set(v8_str("ext_array"), obj2);
-    result = CompileRun("ext_array[''] = function() {return 1503;};"
-                        "ext_array['']();");
-  }
+  // Garbage collector deals swift blows to evil.
+  CcTest::i_isolate()->compilation_cache()->Clear();
+  CcTest::heap()->CollectAllAvailableGarbage();
 
-  free(array_data);
+  // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
+  CHECK_EQ(1, destroyed);
 }
 
 
-THREADED_TEST(ExternalInt8Array) {
-  ExternalArrayTestHelper<i::ExternalInt8Array, int8_t>(
-      v8::kExternalInt8Array,
-      -128,
-      127);
+static double DoubleFromBits(uint64_t value) {
+  double target;
+  i::MemCopy(&target, &value, sizeof(target));
+  return target;
 }
 
 
-THREADED_TEST(ExternalUint8Array) {
-  ExternalArrayTestHelper<i::ExternalUint8Array, uint8_t>(
-      v8::kExternalUint8Array,
-      0,
-      255);
+static uint64_t DoubleToBits(double value) {
+  uint64_t target;
+  i::MemCopy(&target, &value, sizeof(target));
+  return target;
 }
 
 
-THREADED_TEST(ExternalUint8ClampedArray) {
-  ExternalArrayTestHelper<i::ExternalUint8ClampedArray, uint8_t>(
-      v8::kExternalUint8ClampedArray,
-      0,
-      255);
+static double DoubleToDateTime(double input) {
+  double date_limit = 864e13;
+  if (std::isnan(input) || input < -date_limit || input > date_limit) {
+    return std::numeric_limits<double>::quiet_NaN();
+  }
+  return (input < 0) ? -(std::floor(-input)) : std::floor(input);
 }
 
 
-THREADED_TEST(ExternalInt16Array) {
-  ExternalArrayTestHelper<i::ExternalInt16Array, int16_t>(
-      v8::kExternalInt16Array,
-      -32768,
-      32767);
+// We don't have a consistent way to write 64-bit constants syntactically, so we
+// split them into two 32-bit constants and combine them programmatically.
+static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
+  return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
 }
 
 
-THREADED_TEST(ExternalUint16Array) {
-  ExternalArrayTestHelper<i::ExternalUint16Array, uint16_t>(
-      v8::kExternalUint16Array,
-      0,
-      65535);
-}
-
+THREADED_TEST(QuietSignalingNaNs) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::TryCatch try_catch(isolate);
 
-THREADED_TEST(ExternalInt32Array) {
-  ExternalArrayTestHelper<i::ExternalInt32Array, int32_t>(
-      v8::kExternalInt32Array,
-      INT_MIN,   // -2147483648
-      INT_MAX);  //  2147483647
-}
+  // Special double values.
+  double snan = DoubleFromBits(0x7ff00000, 0x00000001);
+  double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
+  double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
+  double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
+  double min_normal = DoubleFromBits(0x00100000, 0x00000000);
+  double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
+  double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
 
+  // Date values are capped at +/-100000000 days (times 864e5 ms per day)
+  // on either side of the epoch.
+  double date_limit = 864e13;
 
-THREADED_TEST(ExternalUint32Array) {
-  ExternalArrayTestHelper<i::ExternalUint32Array, uint32_t>(
-      v8::kExternalUint32Array,
+  double test_values[] = {
+      snan,
+      qnan,
+      infinity,
+      max_normal,
+      date_limit + 1,
+      date_limit,
+      min_normal,
+      max_denormal,
+      min_denormal,
       0,
-      UINT_MAX);  // 4294967295
-}
-
-
-THREADED_TEST(ExternalFloat32Array) {
-  ExternalArrayTestHelper<i::ExternalFloat32Array, float>(
-      v8::kExternalFloat32Array,
-      -500,
-      500);
-}
-
-
-THREADED_TEST(ExternalFloat64Array) {
-  ExternalArrayTestHelper<i::ExternalFloat64Array, double>(
-      v8::kExternalFloat64Array,
-      -500,
-      500);
-}
-
+      -0,
+      -min_denormal,
+      -max_denormal,
+      -min_normal,
+      -date_limit,
+      -date_limit - 1,
+      -max_normal,
+      -infinity,
+      -qnan,
+      -snan
+  };
+  int num_test_values = 20;
 
-THREADED_TEST(ExternalArrays) {
-  TestExternalInt8Array();
-  TestExternalUint8Array();
-  TestExternalInt16Array();
-  TestExternalUint16Array();
-  TestExternalInt32Array();
-  TestExternalUint32Array();
-  TestExternalFloat32Array();
-}
+  for (int i = 0; i < num_test_values; i++) {
+    double test_value = test_values[i];
 
+    // Check that Number::New preserves non-NaNs and quiets SNaNs.
+    v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
+    double stored_number = number->NumberValue();
+    if (!std::isnan(test_value)) {
+      CHECK_EQ(test_value, stored_number);
+    } else {
+      uint64_t stored_bits = DoubleToBits(stored_number);
+      // Check if quiet nan (bits 51..62 all set).
+#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
+    !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
+      // Most significant fraction bit for quiet nan is set to 0
+      // on MIPS architecture. Allowed by IEEE-754.
+      CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
+#else
+      CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
+#endif
+    }
 
-void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  for (int size = 0; size < 100; size += 10) {
-    int element_size = ExternalArrayElementSize(array_type);
-    void* external_data = malloc(size * element_size);
-    v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
-    obj->SetIndexedPropertiesToExternalArrayData(
-        external_data, array_type, size);
-    CHECK(obj->HasIndexedPropertiesInExternalArrayData());
-    CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
-    CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
-    CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
-    free(external_data);
+    // Check that Date::New preserves non-NaNs in the date range and
+    // quiets SNaNs.
+    v8::Handle<v8::Value> date =
+        v8::Date::New(isolate, test_value);
+    double expected_stored_date = DoubleToDateTime(test_value);
+    double stored_date = date->NumberValue();
+    if (!std::isnan(expected_stored_date)) {
+      CHECK_EQ(expected_stored_date, stored_date);
+    } else {
+      uint64_t stored_bits = DoubleToBits(stored_date);
+      // Check if quiet nan (bits 51..62 all set).
+#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
+    !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
+      // Most significant fraction bit for quiet nan is set to 0
+      // on MIPS architecture. Allowed by IEEE-754.
+      CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
+#else
+      CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
+#endif
+    }
   }
 }
 
 
-THREADED_TEST(ExternalArrayInfo) {
-  ExternalArrayInfoTestHelper(v8::kExternalInt8Array);
-  ExternalArrayInfoTestHelper(v8::kExternalUint8Array);
-  ExternalArrayInfoTestHelper(v8::kExternalInt16Array);
-  ExternalArrayInfoTestHelper(v8::kExternalUint16Array);
-  ExternalArrayInfoTestHelper(v8::kExternalInt32Array);
-  ExternalArrayInfoTestHelper(v8::kExternalUint32Array);
-  ExternalArrayInfoTestHelper(v8::kExternalFloat32Array);
-  ExternalArrayInfoTestHelper(v8::kExternalFloat64Array);
-  ExternalArrayInfoTestHelper(v8::kExternalUint8ClampedArray);
+static void SpaghettiIncident(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::HandleScope scope(args.GetIsolate());
+  v8::TryCatch tc(args.GetIsolate());
+  v8::Handle<v8::String> str(args[0]->ToString(args.GetIsolate()));
+  USE(str);
+  if (tc.HasCaught())
+    tc.ReThrow();
 }
 
 
-void ExtArrayLimitsHelper(v8::Isolate* isolate,
-                          v8::ExternalArrayType array_type,
-                          int size) {
-  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
-  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
-  last_location = last_message = NULL;
-  obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
-  CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
-  CHECK_NE(NULL, last_location);
-  CHECK_NE(NULL, last_message);
+// Test that an exception can be propagated down through a spaghetti
+// stack using ReThrow.
+THREADED_TEST(SpaghettiStackReThrow) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  LocalContext context;
+  context->Global()->Set(
+      v8::String::NewFromUtf8(isolate, "s"),
+      v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
+  v8::TryCatch try_catch(isolate);
+  CompileRun(
+      "var i = 0;"
+      "var o = {"
+      "  toString: function () {"
+      "    if (i == 10) {"
+      "      throw 'Hey!';"
+      "    } else {"
+      "      i++;"
+      "      return s(o);"
+      "    }"
+      "  }"
+      "};"
+      "s(o);");
+  CHECK(try_catch.HasCaught());
+  v8::String::Utf8Value value(try_catch.Exception());
+  CHECK_EQ(0, strcmp(*value, "Hey!"));
 }
 
 
-TEST(ExternalArrayLimits) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
+TEST(Regress528) {
+  v8::V8::Initialize();
+  v8::Isolate* isolate = CcTest::isolate();
+  i::FLAG_retain_maps_for_n_gc = 0;
   v8::HandleScope scope(isolate);
-  ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0x40000000);
-  ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0xffffffff);
-  ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0x40000000);
-  ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0xffffffff);
-  ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0x40000000);
-  ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0xffffffff);
-  ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0x40000000);
-  ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0xffffffff);
-  ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0x40000000);
-  ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0xffffffff);
-  ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0x40000000);
-  ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0xffffffff);
-  ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0x40000000);
-  ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0xffffffff);
-  ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0x40000000);
-  ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0xffffffff);
-  ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0x40000000);
-  ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0xffffffff);
-}
-
-
-template <typename ElementType, typename TypedArray,
-          class ExternalArrayClass>
-void TypedArrayTestHelper(v8::ExternalArrayType array_type,
-                          int64_t low, int64_t high) {
-  const int kElementCount = 50;
-
-  i::ScopedVector<ElementType> backing_store(kElementCount+2);
+  v8::Local<Context> other_context;
+  int gc_count;
 
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope handle_scope(isolate);
+  // Create a context used to keep the code from aging in the compilation
+  // cache.
+  other_context = Context::New(isolate);
 
-  Local<v8::ArrayBuffer> ab =
-      v8::ArrayBuffer::New(isolate, backing_store.start(),
-                           (kElementCount + 2) * sizeof(ElementType));
-  Local<TypedArray> ta =
-      TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
-  CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
-  CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
-  CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
-  CHECK_EQ(kElementCount*sizeof(ElementType),
-           static_cast<int>(ta->ByteLength()));
-  CHECK_EQ(ab, ta->Buffer());
+  // Context-dependent context data creates reference from the compilation
+  // cache to the global object.
+  const char* source_simple = "1";
+  {
+    v8::HandleScope scope(isolate);
+    v8::Local<Context> context = Context::New(isolate);
 
-  ElementType* data = backing_store.start() + 2;
-  for (int i = 0; i < kElementCount; i++) {
-    data[i] = static_cast<ElementType>(i);
+    context->Enter();
+    Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
+    context->SetEmbedderData(0, obj);
+    CompileRun(source_simple);
+    context->Exit();
   }
+  isolate->ContextDisposedNotification();
+  for (gc_count = 1; gc_count < 10; gc_count++) {
+    other_context->Enter();
+    CompileRun(source_simple);
+    other_context->Exit();
+    CcTest::heap()->CollectAllGarbage();
+    if (GetGlobalObjectsCount() == 1) break;
+  }
+  CHECK_GE(2, gc_count);
+  CHECK_EQ(1, GetGlobalObjectsCount());
 
-  ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
-      env.local(), ta, kElementCount, array_type, low, high);
-}
-
-
-THREADED_TEST(Uint8Array) {
-  TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>(
-      v8::kExternalUint8Array, 0, 0xFF);
-}
-
-
-THREADED_TEST(Int8Array) {
-  TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>(
-      v8::kExternalInt8Array, -0x80, 0x7F);
-}
+  // Eval in a function creates reference from the compilation cache to the
+  // global object.
+  const char* source_eval = "function f(){eval('1')}; f()";
+  {
+    v8::HandleScope scope(isolate);
+    v8::Local<Context> context = Context::New(isolate);
 
+    context->Enter();
+    CompileRun(source_eval);
+    context->Exit();
+  }
+  isolate->ContextDisposedNotification();
+  for (gc_count = 1; gc_count < 10; gc_count++) {
+    other_context->Enter();
+    CompileRun(source_eval);
+    other_context->Exit();
+    CcTest::heap()->CollectAllGarbage();
+    if (GetGlobalObjectsCount() == 1) break;
+  }
+  CHECK_GE(2, gc_count);
+  CHECK_EQ(1, GetGlobalObjectsCount());
 
-THREADED_TEST(Uint16Array) {
-  TypedArrayTestHelper<uint16_t,
-                       v8::Uint16Array,
-                       i::ExternalUint16Array>(
-      v8::kExternalUint16Array, 0, 0xFFFF);
-}
+  // Looking up the line number for an exception creates reference from the
+  // compilation cache to the global object.
+  const char* source_exception = "function f(){throw 1;} f()";
+  {
+    v8::HandleScope scope(isolate);
+    v8::Local<Context> context = Context::New(isolate);
 
+    context->Enter();
+    v8::TryCatch try_catch(isolate);
+    CompileRun(source_exception);
+    CHECK(try_catch.HasCaught());
+    v8::Handle<v8::Message> message = try_catch.Message();
+    CHECK(!message.IsEmpty());
+    CHECK_EQ(1, message->GetLineNumber());
+    context->Exit();
+  }
+  isolate->ContextDisposedNotification();
+  for (gc_count = 1; gc_count < 10; gc_count++) {
+    other_context->Enter();
+    CompileRun(source_exception);
+    other_context->Exit();
+    CcTest::heap()->CollectAllGarbage();
+    if (GetGlobalObjectsCount() == 1) break;
+  }
+  CHECK_GE(2, gc_count);
+  CHECK_EQ(1, GetGlobalObjectsCount());
 
-THREADED_TEST(Int16Array) {
-  TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>(
-      v8::kExternalInt16Array, -0x8000, 0x7FFF);
+  isolate->ContextDisposedNotification();
 }
 
 
-THREADED_TEST(Uint32Array) {
-  TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>(
-      v8::kExternalUint32Array, 0, UINT_MAX);
-}
-
+THREADED_TEST(ScriptOrigin) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::ScriptOrigin origin = v8::ScriptOrigin(
+      v8::String::NewFromUtf8(env->GetIsolate(), "test"),
+      v8::Integer::New(env->GetIsolate(), 1),
+      v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
+      v8::Handle<v8::Integer>(), v8::True(env->GetIsolate()),
+      v8::String::NewFromUtf8(env->GetIsolate(), "http://sourceMapUrl"),
+      v8::True(env->GetIsolate()));
+  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
+      env->GetIsolate(), "function f() {}\n\nfunction g() {}");
+  v8::Script::Compile(script, &origin)->Run();
+  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
+  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
 
-THREADED_TEST(Int32Array) {
-  TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>(
-      v8::kExternalInt32Array, INT_MIN, INT_MAX);
-}
+  v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
+  CHECK_EQ(0, strcmp("test",
+                     *v8::String::Utf8Value(script_origin_f.ResourceName())));
+  CHECK_EQ(1, script_origin_f.ResourceLineOffset()->Int32Value());
+  CHECK(script_origin_f.Options().IsSharedCrossOrigin());
+  CHECK(script_origin_f.Options().IsEmbedderDebugScript());
+  CHECK(script_origin_f.Options().IsOpaque());
+  printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
 
+  CHECK_EQ(0, strcmp("http://sourceMapUrl",
+                     *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
 
-THREADED_TEST(Float32Array) {
-  TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>(
-      v8::kExternalFloat32Array, -500, 500);
+  v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
+  CHECK_EQ(0, strcmp("test",
+                     *v8::String::Utf8Value(script_origin_g.ResourceName())));
+  CHECK_EQ(1, script_origin_g.ResourceLineOffset()->Int32Value());
+  CHECK(script_origin_g.Options().IsSharedCrossOrigin());
+  CHECK(script_origin_g.Options().IsEmbedderDebugScript());
+  CHECK(script_origin_g.Options().IsOpaque());
+  CHECK_EQ(0, strcmp("http://sourceMapUrl",
+                     *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
 }
 
 
-THREADED_TEST(Float64Array) {
-  TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>(
-      v8::kExternalFloat64Array, -500, 500);
+THREADED_TEST(FunctionGetInferredName) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
+  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
+      env->GetIsolate(),
+      "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
+  v8::Script::Compile(script, &origin)->Run();
+  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
+  CHECK_EQ(0,
+           strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
 }
 
 
-THREADED_TEST(Uint8ClampedArray) {
-  TypedArrayTestHelper<uint8_t,
-                       v8::Uint8ClampedArray, i::ExternalUint8ClampedArray>(
-      v8::kExternalUint8ClampedArray, 0, 0xFF);
+THREADED_TEST(FunctionGetDisplayName) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  const char* code = "var error = false;"
+                     "function a() { this.x = 1; };"
+                     "a.displayName = 'display_a';"
+                     "var b = (function() {"
+                     "  var f = function() { this.x = 2; };"
+                     "  f.displayName = 'display_b';"
+                     "  return f;"
+                     "})();"
+                     "var c = function() {};"
+                     "c.__defineGetter__('displayName', function() {"
+                     "  error = true;"
+                     "  throw new Error();"
+                     "});"
+                     "function d() {};"
+                     "d.__defineGetter__('displayName', function() {"
+                     "  error = true;"
+                     "  return 'wrong_display_name';"
+                     "});"
+                     "function e() {};"
+                     "e.displayName = 'wrong_display_name';"
+                     "e.__defineSetter__('displayName', function() {"
+                     "  error = true;"
+                     "  throw new Error();"
+                     "});"
+                     "function f() {};"
+                     "f.displayName = { 'foo': 6, toString: function() {"
+                     "  error = true;"
+                     "  return 'wrong_display_name';"
+                     "}};"
+                     "var g = function() {"
+                     "  arguments.callee.displayName = 'set_in_runtime';"
+                     "}; g();"
+                     ;
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
+  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
+      ->Run();
+  v8::Local<v8::Value> error =
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
+  v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
+  v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
+  v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
+  v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
+  v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
+  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
+  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
+  CHECK_EQ(false, error->BooleanValue());
+  CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
+  CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
+  CHECK(c->GetDisplayName()->IsUndefined());
+  CHECK(d->GetDisplayName()->IsUndefined());
+  CHECK(e->GetDisplayName()->IsUndefined());
+  CHECK(f->GetDisplayName()->IsUndefined());
+  CHECK_EQ(
+      0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
 }
 
 
-THREADED_TEST(DataView) {
-  const int kSize = 50;
-
-  i::ScopedVector<uint8_t> backing_store(kSize+2);
-
+THREADED_TEST(ScriptLineNumber) {
   LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope handle_scope(isolate);
-
-  Local<v8::ArrayBuffer> ab =
-      v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
-  Local<v8::DataView> dv =
-      v8::DataView::New(ab, 2, kSize);
-  CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
-  CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
-  CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
-  CHECK_EQ(ab, dv->Buffer());
+  v8::HandleScope scope(env->GetIsolate());
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
+  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
+      env->GetIsolate(), "function f() {}\n\nfunction g() {}");
+  v8::Script::Compile(script, &origin)->Run();
+  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
+  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
+  CHECK_EQ(0, f->GetScriptLineNumber());
+  CHECK_EQ(2, g->GetScriptLineNumber());
 }
 
 
-#define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
-  THREADED_TEST(Is##View) {                                                   \
-    LocalContext env;                                                         \
-    v8::Isolate* isolate = env->GetIsolate();                                 \
-    v8::HandleScope handle_scope(isolate);                                    \
-                                                                              \
-    Handle<Value> result = CompileRun(                                        \
-        "var ab = new ArrayBuffer(128);"                                      \
-        "new " #View "(ab)");                                                 \
-    CHECK(result->IsArrayBufferView());                                       \
-    CHECK(result->Is##View());                                                \
-    CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
-  }
-
-IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
-IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
-IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
-IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
-IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
-IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
-IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
-IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
-IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
-IS_ARRAY_BUFFER_VIEW_TEST(DataView)
-
-#undef IS_ARRAY_BUFFER_VIEW_TEST
-
-
-
-THREADED_TEST(ScriptContextDependence) {
-  LocalContext c1;
-  v8::HandleScope scope(c1->GetIsolate());
-  const char *source = "foo";
-  v8::Handle<v8::Script> dep =
-      v8::Script::Compile(v8::String::NewFromUtf8(c1->GetIsolate(), source));
-  v8::Handle<v8::Script> indep =
-      v8::Script::New(v8::String::NewFromUtf8(c1->GetIsolate(), source));
-  c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
-                    v8::Integer::New(c1->GetIsolate(), 100));
-  CHECK_EQ(dep->Run()->Int32Value(), 100);
-  CHECK_EQ(indep->Run()->Int32Value(), 100);
-  LocalContext c2;
-  c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
-                    v8::Integer::New(c2->GetIsolate(), 101));
-  CHECK_EQ(dep->Run()->Int32Value(), 100);
-  CHECK_EQ(indep->Run()->Int32Value(), 101);
+THREADED_TEST(ScriptColumnNumber) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
+                       v8::Integer::New(isolate, 3),
+                       v8::Integer::New(isolate, 2));
+  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
+      isolate, "function foo() {}\n\n     function bar() {}");
+  v8::Script::Compile(script, &origin)->Run();
+  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
+  v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
+  CHECK_EQ(14, foo->GetScriptColumnNumber());
+  CHECK_EQ(17, bar->GetScriptColumnNumber());
 }
 
 
-THREADED_TEST(StackTrace) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  v8::TryCatch try_catch;
-  const char *source = "function foo() { FAIL.FAIL; }; foo();";
-  v8::Handle<v8::String> src =
-      v8::String::NewFromUtf8(context->GetIsolate(), source);
-  v8::Handle<v8::String> origin =
-      v8::String::NewFromUtf8(context->GetIsolate(), "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);
+THREADED_TEST(FunctionIsBuiltin) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::Function> f;
+  f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
+  CHECK(f->IsBuiltin());
+  f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
+  CHECK(f->IsBuiltin());
+  f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
+  CHECK(f->IsBuiltin());
+  f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
+  CHECK(f->IsBuiltin());
+  f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
+  CHECK(!f->IsBuiltin());
 }
 
 
-// Checks that a StackFrame has certain expected values.
-void checkStackFrame(const char* expected_script_name,
-    const char* expected_func_name, int expected_line_number,
-    int expected_column, bool is_eval, bool is_constructor,
-    v8::Handle<v8::StackFrame> frame) {
-  v8::HandleScope scope(CcTest::isolate());
-  v8::String::Utf8Value func_name(frame->GetFunctionName());
-  v8::String::Utf8Value script_name(frame->GetScriptName());
-  if (*script_name == NULL) {
-    // The situation where there is no associated script, like for evals.
-    CHECK(expected_script_name == NULL);
-  } else {
-    CHECK(strstr(*script_name, expected_script_name) != NULL);
-  }
-  CHECK(strstr(*func_name, expected_func_name) != NULL);
-  CHECK_EQ(expected_line_number, frame->GetLineNumber());
-  CHECK_EQ(expected_column, frame->GetColumn());
-  CHECK_EQ(is_eval, frame->IsEval());
-  CHECK_EQ(is_constructor, frame->IsConstructor());
+THREADED_TEST(FunctionGetScriptId) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
+                       v8::Integer::New(isolate, 3),
+                       v8::Integer::New(isolate, 2));
+  v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
+      isolate, "function foo() {}\n\n     function bar() {}");
+  v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
+  script->Run();
+  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
+  v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
+  CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
+  CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
 }
 
 
-void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::HandleScope scope(args.GetIsolate());
-  const char* origin = "capture-stack-trace-test";
-  const int kOverviewTest = 1;
-  const int kDetailedTest = 2;
-
-  ASSERT(args.Length() == 1);
-
-  int testGroup = args[0]->Int32Value();
-  if (testGroup == kOverviewTest) {
-    v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
-        args.GetIsolate(), 10, v8::StackTrace::kOverview);
-    CHECK_EQ(4, stackTrace->GetFrameCount());
-    checkStackFrame(origin, "bar", 2, 10, false, false,
-                    stackTrace->GetFrame(0));
-    checkStackFrame(origin, "foo", 6, 3, false, false,
-                    stackTrace->GetFrame(1));
-    // This is the source string inside the eval which has the call to foo.
-    checkStackFrame(NULL, "", 1, 5, false, false,
-                    stackTrace->GetFrame(2));
-    // The last frame is an anonymous function which has the initial eval call.
-    checkStackFrame(origin, "", 8, 7, false, false,
-                    stackTrace->GetFrame(3));
-
-    CHECK(stackTrace->AsArray()->IsArray());
-  } else if (testGroup == kDetailedTest) {
-    v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
-        args.GetIsolate(), 10, v8::StackTrace::kDetailed);
-    CHECK_EQ(4, stackTrace->GetFrameCount());
-    checkStackFrame(origin, "bat", 4, 22, false, false,
-                    stackTrace->GetFrame(0));
-    checkStackFrame(origin, "baz", 8, 3, false, true,
-                    stackTrace->GetFrame(1));
-#ifdef ENABLE_DEBUGGER_SUPPORT
-    bool is_eval = true;
-#else  // ENABLE_DEBUGGER_SUPPORT
-    bool is_eval = false;
-#endif  // ENABLE_DEBUGGER_SUPPORT
-
-    // This is the source string inside the eval which has the call to baz.
-    checkStackFrame(NULL, "", 1, 5, is_eval, false,
-                    stackTrace->GetFrame(2));
-    // The last frame is an anonymous function which has the initial eval call.
-    checkStackFrame(origin, "", 10, 1, false, false,
-                    stackTrace->GetFrame(3));
-
-    CHECK(stackTrace->AsArray()->IsArray());
-  }
+THREADED_TEST(FunctionGetBoundFunction) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
+      env->GetIsolate(), "test"));
+  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
+      env->GetIsolate(),
+      "var a = new Object();\n"
+      "a.x = 1;\n"
+      "function f () { return this.x };\n"
+      "var g = f.bind(a);\n"
+      "var b = g();");
+  v8::Script::Compile(script, &origin)->Run();
+  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
+  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
+  CHECK(g->GetBoundFunction()->IsFunction());
+  Local<v8::Function> original_function = Local<v8::Function>::Cast(
+      g->GetBoundFunction());
+  CHECK(f->GetName()->Equals(original_function->GetName()));
+  CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
+  CHECK_EQ(f->GetScriptColumnNumber(),
+           original_function->GetScriptColumnNumber());
 }
 
 
-// Tests the C++ StackTrace API.
-// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
-// THREADED_TEST(CaptureStackTrace) {
-TEST(CaptureStackTrace) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Handle<v8::String> origin =
-      v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->Set(v8_str("AnalyzeStackInNativeCode"),
-             v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
-  LocalContext context(0, templ);
+static void GetterWhichReturns42(
+    Local<String> name,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
+  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
+  info.GetReturnValue().Set(v8_num(42));
+}
 
-  // Test getting OVERVIEW information. Should ignore information that is not
-  // script name, function name, line number, and column offset.
-  const char *overview_source =
-    "function bar() {\n"
-    "  var y; AnalyzeStackInNativeCode(1);\n"
-    "}\n"
-    "function foo() {\n"
-    "\n"
-    "  bar();\n"
-    "}\n"
-    "var x;eval('new foo();');";
-  v8::Handle<v8::String> overview_src =
-      v8::String::NewFromUtf8(isolate, overview_source);
-  v8::Handle<Value> overview_result(
-      v8::Script::New(overview_src, origin)->Run());
-  CHECK(!overview_result.IsEmpty());
-  CHECK(overview_result->IsObject());
 
-  // Test getting DETAILED information.
-  const char *detailed_source =
-    "function bat() {AnalyzeStackInNativeCode(2);\n"
-    "}\n"
-    "\n"
-    "function baz() {\n"
-    "  bat();\n"
-    "}\n"
-    "eval('new baz();');";
-  v8::Handle<v8::String> detailed_src =
-      v8::String::NewFromUtf8(isolate, detailed_source);
-  // Make the script using a non-zero line and column offset.
-  v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
-  v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
-  v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
-  v8::Handle<v8::Script> detailed_script(
-      v8::Script::New(detailed_src, &detailed_origin));
-  v8::Handle<Value> detailed_result(detailed_script->Run());
-  CHECK(!detailed_result.IsEmpty());
-  CHECK(detailed_result->IsObject());
+static void SetterWhichSetsYOnThisTo23(
+    Local<String> name,
+    Local<Value> value,
+    const v8::PropertyCallbackInfo<void>& info) {
+  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
+  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
+  Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
 }
 
 
-static void StackTraceForUncaughtExceptionListener(
-    v8::Handle<v8::Message> message,
-    v8::Handle<Value>) {
-  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
-  CHECK_EQ(2, stack_trace->GetFrameCount());
-  checkStackFrame("origin", "foo", 2, 3, false, false,
-                  stack_trace->GetFrame(0));
-  checkStackFrame("origin", "bar", 5, 3, false, false,
-                  stack_trace->GetFrame(1));
+void FooGetInterceptor(Local<Name> name,
+                       const v8::PropertyCallbackInfo<v8::Value>& info) {
+  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
+  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
+  if (!name->Equals(v8_str("foo"))) return;
+  info.GetReturnValue().Set(v8_num(42));
 }
 
 
-TEST(CaptureStackTraceForUncaughtException) {
-  report_count = 0;
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
-
-  Script::Compile(v8_str("function foo() {\n"
-                         "  throw 1;\n"
-                         "};\n"
-                         "function bar() {\n"
-                         "  foo();\n"
-                         "};"),
-                  v8_str("origin"))->Run();
-  v8::Local<v8::Object> global = env->Global();
-  Local<Value> trouble = global->Get(v8_str("bar"));
-  CHECK(trouble->IsFunction());
-  Function::Cast(*trouble)->Call(global, 0, NULL);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
-  v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
+void FooSetInterceptor(Local<Name> name, Local<Value> value,
+                       const v8::PropertyCallbackInfo<v8::Value>& info) {
+  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
+  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
+  if (!name->Equals(v8_str("foo"))) return;
+  Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
+  info.GetReturnValue().Set(v8_num(23));
 }
 
 
-TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
-                                                    1024,
-                                                    v8::StackTrace::kDetailed);
-
-  CompileRun(
-      "var setters = ['column', 'lineNumber', 'scriptName',\n"
-      "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
-      "    'isConstructor'];\n"
-      "for (var i = 0; i < setters.length; i++) {\n"
-      "  var prop = setters[i];\n"
-      "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
-      "}\n");
-  CompileRun("throw 'exception';");
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
-}
+TEST(SetterOnConstructorPrototype) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
+                     SetterWhichSetsYOnThisTo23);
+  LocalContext context;
+  context->Global()->Set(v8_str("P"), templ->NewInstance());
+  CompileRun("function C1() {"
+             "  this.x = 23;"
+             "};"
+             "C1.prototype = P;"
+             "function C2() {"
+             "  this.x = 23"
+             "};"
+             "C2.prototype = { };"
+             "C2.prototype.__proto__ = P;");
 
+  v8::Local<v8::Script> script;
+  script = v8_compile("new C1();");
+  for (int i = 0; i < 10; i++) {
+    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
+    CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
+    CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
+  }
 
-static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
-                                     v8::Handle<v8::Value> data) {
-  // Use the frame where JavaScript is called from.
-  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
-  CHECK(!stack_trace.IsEmpty());
-  int frame_count = stack_trace->GetFrameCount();
-  CHECK_EQ(3, frame_count);
-  int line_number[] = {1, 2, 5};
-  for (int i = 0; i < frame_count; i++) {
-    CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
+script = v8_compile("new C2();");
+  for (int i = 0; i < 10; i++) {
+    v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
+    CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
+    CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
   }
 }
 
 
-// Test that we only return the stack trace at the site where the exception
-// is first thrown (not where it is rethrown).
-TEST(RethrowStackTrace) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  // We make sure that
-  // - the stack trace of the ReferenceError in g() is reported.
-  // - the stack trace is not overwritten when e1 is rethrown by t().
-  // - the stack trace of e2 does not overwrite that of e1.
-  const char* source =
-      "function g() { error; }          \n"
-      "function f() { g(); }            \n"
-      "function t(e) { throw e; }       \n"
-      "try {                            \n"
-      "  f();                           \n"
-      "} catch (e1) {                   \n"
-      "  try {                          \n"
-      "    error;                       \n"
-      "  } catch (e2) {                 \n"
-      "    t(e1);                       \n"
-      "  }                              \n"
-      "}                                \n";
-  v8::V8::AddMessageListener(RethrowStackTraceHandler);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
-  CompileRun(source);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
-  v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
+static void NamedPropertyGetterWhichReturns42(
+    Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(v8_num(42));
 }
 
 
-static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
-                                              v8::Handle<v8::Value> data) {
-  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
-  CHECK(!stack_trace.IsEmpty());
-  int frame_count = stack_trace->GetFrameCount();
-  CHECK_EQ(2, frame_count);
-  int line_number[] = {3, 7};
-  for (int i = 0; i < frame_count; i++) {
-    CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
+static void NamedPropertySetterWhichSetsYOnThisTo23(
+    Local<Name> name, Local<Value> value,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  if (name->Equals(v8_str("x"))) {
+    Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
   }
 }
 
 
-// Test that we do not recognize identity for primitive exceptions.
-TEST(RethrowPrimitiveStackTrace) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  // We do not capture stack trace for non Error objects on creation time.
-  // Instead, we capture the stack trace on last throw.
-  const char* source =
-      "function g() { throw 404; }      \n"
-      "function f() { g(); }            \n"
-      "function t(e) { throw e; }       \n"
-      "try {                            \n"
-      "  f();                           \n"
-      "} catch (e1) {                   \n"
-      "  t(e1)                          \n"
-      "}                                \n";
-  v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
-  CompileRun(source);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
-  v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
-}
+THREADED_TEST(InterceptorOnConstructorPrototype) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      NamedPropertyGetterWhichReturns42,
+      NamedPropertySetterWhichSetsYOnThisTo23));
+  LocalContext context;
+  context->Global()->Set(v8_str("P"), templ->NewInstance());
+  CompileRun("function C1() {"
+             "  this.x = 23;"
+             "};"
+             "C1.prototype = P;"
+             "function C2() {"
+             "  this.x = 23"
+             "};"
+             "C2.prototype = { };"
+             "C2.prototype.__proto__ = P;");
 
+  v8::Local<v8::Script> script;
+  script = v8_compile("new C1();");
+  for (int i = 0; i < 10; i++) {
+    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
+    CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
+    CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
+  }
 
-static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
-                                              v8::Handle<v8::Value> data) {
-  // Use the frame where JavaScript is called from.
-  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
-  CHECK(!stack_trace.IsEmpty());
-  CHECK_EQ(1, stack_trace->GetFrameCount());
-  CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
+  script = v8_compile("new C2();");
+  for (int i = 0; i < 10; i++) {
+    v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
+    CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
+    CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
+  }
 }
 
 
-// Test that the stack trace is captured when the error object is created and
-// not where it is thrown.
-TEST(RethrowExistingStackTrace) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  const char* source =
-      "var e = new Error();           \n"
-      "throw e;                       \n";
-  v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+TEST(Regress618) {
+  const char* source = "function C1() {"
+                       "  this.x = 23;"
+                       "};"
+                       "C1.prototype = P;";
+
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::Script> script;
+
+  // Use a simple object as prototype.
+  v8::Local<v8::Object> prototype = v8::Object::New(isolate);
+  prototype->Set(v8_str("y"), v8_num(42));
+  context->Global()->Set(v8_str("P"), prototype);
+
+  // This compile will add the code to the compilation cache.
   CompileRun(source);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
-  v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
-}
 
+  script = v8_compile("new C1();");
+  // Allow enough iterations for the inobject slack tracking logic
+  // to finalize instance size and install the fast construct stub.
+  for (int i = 0; i < 256; i++) {
+    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
+    CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
+    CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
+  }
 
-static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
-                                               v8::Handle<v8::Value> data) {
-  // Use the frame where JavaScript is called from.
-  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
-  CHECK(!stack_trace.IsEmpty());
-  CHECK_EQ(1, stack_trace->GetFrameCount());
-  CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
+  // Use an API object with accessors as prototype.
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
+                     SetterWhichSetsYOnThisTo23);
+  context->Global()->Set(v8_str("P"), templ->NewInstance());
+
+  // This compile will get the code from the compilation cache.
+  CompileRun(source);
+
+  script = v8_compile("new C1();");
+  for (int i = 0; i < 10; i++) {
+    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
+    CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
+    CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
+  }
 }
 
+v8::Isolate* gc_callbacks_isolate = NULL;
+int prologue_call_count = 0;
+int epilogue_call_count = 0;
+int prologue_call_count_second = 0;
+int epilogue_call_count_second = 0;
+int prologue_call_count_alloc = 0;
+int epilogue_call_count_alloc = 0;
 
-// Test that the stack trace is captured where the bogus Error object is thrown.
-TEST(RethrowBogusErrorStackTrace) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  const char* source =
-      "var e = {__proto__: new Error()} \n"
-      "throw e;                         \n";
-  v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
-  CompileRun(source);
-  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
-  v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
+void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  ++prologue_call_count;
 }
 
 
-void AnalyzeStackOfEvalWithSourceURL(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::HandleScope scope(args.GetIsolate());
-  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
-      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
-  CHECK_EQ(5, stackTrace->GetFrameCount());
-  v8::Handle<v8::String> url = v8_str("eval_url");
-  for (int i = 0; i < 3; i++) {
-    v8::Handle<v8::String> name =
-        stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
-    CHECK(!name.IsEmpty());
-    CHECK_EQ(url, name);
-  }
+void PrologueCallback(v8::Isolate* isolate,
+                      v8::GCType,
+                      v8::GCCallbackFlags flags) {
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  CHECK_EQ(gc_callbacks_isolate, isolate);
+  ++prologue_call_count;
 }
 
 
-TEST(SourceURLInStackTrace) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
-             v8::FunctionTemplate::New(isolate,
-                                       AnalyzeStackOfEvalWithSourceURL));
-  LocalContext context(0, templ);
+void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  ++epilogue_call_count;
+}
 
-  const char *source =
-    "function outer() {\n"
-    "function bar() {\n"
-    "  AnalyzeStackOfEvalWithSourceURL();\n"
-    "}\n"
-    "function foo() {\n"
-    "\n"
-    "  bar();\n"
-    "}\n"
-    "foo();\n"
-    "}\n"
-    "eval('(' + outer +')()%s');";
 
-  i::ScopedVector<char> code(1024);
-  i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
-  CHECK(CompileRun(code.start())->IsUndefined());
-  i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
-  CHECK(CompileRun(code.start())->IsUndefined());
+void EpilogueCallback(v8::Isolate* isolate,
+                      v8::GCType,
+                      v8::GCCallbackFlags flags) {
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  CHECK_EQ(gc_callbacks_isolate, isolate);
+  ++epilogue_call_count;
 }
 
 
-static int scriptIdInStack[2];
-
-void AnalyzeScriptIdInStack(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::HandleScope scope(args.GetIsolate());
-  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
-      args.GetIsolate(), 10, v8::StackTrace::kScriptId);
-  CHECK_EQ(2, stackTrace->GetFrameCount());
-  for (int i = 0; i < 2; i++) {
-    scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
-  }
+void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  ++prologue_call_count_second;
 }
 
 
-TEST(ScriptIdInStackTrace) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->Set(v8_str("AnalyzeScriptIdInStack"),
-             v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
-  LocalContext context(0, templ);
+void PrologueCallbackSecond(v8::Isolate* isolate,
+                            v8::GCType,
+                            v8::GCCallbackFlags flags) {
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  CHECK_EQ(gc_callbacks_isolate, isolate);
+  ++prologue_call_count_second;
+}
 
-  v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
-    isolate,
-    "function foo() {\n"
-    "  AnalyzeScriptIdInStack();"
-    "}\n"
-    "foo();\n");
-  v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"));
-  v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
-  script->Run();
-  for (int i = 0; i < 2; i++) {
-    CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
-    CHECK_EQ(scriptIdInStack[i], script->GetId());
-  }
+
+void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  ++epilogue_call_count_second;
 }
 
 
-void AnalyzeStackOfInlineScriptWithSourceURL(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::HandleScope scope(args.GetIsolate());
-  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
-      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
-  CHECK_EQ(4, stackTrace->GetFrameCount());
-  v8::Handle<v8::String> url = v8_str("url");
-  for (int i = 0; i < 3; i++) {
-    v8::Handle<v8::String> name =
-        stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
-    CHECK(!name.IsEmpty());
-    CHECK_EQ(url, name);
-  }
+void EpilogueCallbackSecond(v8::Isolate* isolate,
+                            v8::GCType,
+                            v8::GCCallbackFlags flags) {
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  CHECK_EQ(gc_callbacks_isolate, isolate);
+  ++epilogue_call_count_second;
 }
 
 
-TEST(InlineScriptWithSourceURLInStackTrace) {
-  v8::Isolate* isolate = CcTest::isolate();
+void PrologueCallbackAlloc(v8::Isolate* isolate,
+                           v8::GCType,
+                           v8::GCCallbackFlags flags) {
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
-             v8::FunctionTemplate::New(
-                 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
-  LocalContext context(0, templ);
 
-  const char *source =
-    "function outer() {\n"
-    "function bar() {\n"
-    "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
-    "}\n"
-    "function foo() {\n"
-    "\n"
-    "  bar();\n"
-    "}\n"
-    "foo();\n"
-    "}\n"
-    "outer()\n%s";
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  CHECK_EQ(gc_callbacks_isolate, isolate);
+  ++prologue_call_count_alloc;
 
-  i::ScopedVector<char> code(1024);
-  i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
-  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
-  i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
-  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
-}
+  // Simulate full heap to see if we will reenter this callback
+  SimulateFullSpace(CcTest::heap()->new_space());
 
+  Local<Object> obj = Object::New(isolate);
+  CHECK(!obj.IsEmpty());
 
-void AnalyzeStackOfDynamicScriptWithSourceURL(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::HandleScope scope(args.GetIsolate());
-  v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
-      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
-  CHECK_EQ(4, stackTrace->GetFrameCount());
-  v8::Handle<v8::String> url = v8_str("source_url");
-  for (int i = 0; i < 3; i++) {
-    v8::Handle<v8::String> name =
-        stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
-    CHECK(!name.IsEmpty());
-    CHECK_EQ(url, name);
-  }
+  CcTest::heap()->CollectAllGarbage(
+      i::Heap::kAbortIncrementalMarkingMask);
 }
 
 
-TEST(DynamicWithSourceURLInStackTrace) {
-  v8::Isolate* isolate = CcTest::isolate();
+void EpilogueCallbackAlloc(v8::Isolate* isolate,
+                           v8::GCType,
+                           v8::GCCallbackFlags flags) {
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
-             v8::FunctionTemplate::New(
-                 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
-  LocalContext context(0, templ);
 
-  const char *source =
-    "function outer() {\n"
-    "function bar() {\n"
-    "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
-    "}\n"
-    "function foo() {\n"
-    "\n"
-    "  bar();\n"
-    "}\n"
-    "foo();\n"
-    "}\n"
-    "outer()\n%s";
+  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
+  CHECK_EQ(gc_callbacks_isolate, isolate);
+  ++epilogue_call_count_alloc;
 
-  i::ScopedVector<char> code(1024);
-  i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
-  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
-  i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
-  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
-}
+  // Simulate full heap to see if we will reenter this callback
+  SimulateFullSpace(CcTest::heap()->new_space());
 
+  Local<Object> obj = Object::New(isolate);
+  CHECK(!obj.IsEmpty());
 
-static void CreateGarbageInOldSpace() {
-  i::Factory* factory = CcTest::i_isolate()->factory();
-  v8::HandleScope scope(CcTest::isolate());
-  i::AlwaysAllocateScope always_allocate;
-  for (int i = 0; i < 1000; i++) {
-    factory->NewFixedArray(1000, i::TENURED);
-  }
+  CcTest::heap()->CollectAllGarbage(
+      i::Heap::kAbortIncrementalMarkingMask);
 }
 
 
-// Test that idle notification can be handled and eventually returns true.
-TEST(IdleNotification) {
-  const intptr_t MB = 1024 * 1024;
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
-  CreateGarbageInOldSpace();
-  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
-  CHECK_GT(size_with_garbage, initial_size + MB);
-  bool finished = false;
-  for (int i = 0; i < 200 && !finished; i++) {
-    finished = v8::V8::IdleNotification();
-  }
-  intptr_t final_size = CcTest::heap()->SizeOfObjects();
-  CHECK(finished);
-  CHECK_LT(final_size, initial_size + 1);
+TEST(GCCallbacksOld) {
+  LocalContext context;
+
+  v8::V8::AddGCPrologueCallback(PrologueCallback);
+  v8::V8::AddGCEpilogueCallback(EpilogueCallback);
+  CHECK_EQ(0, prologue_call_count);
+  CHECK_EQ(0, epilogue_call_count);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(1, prologue_call_count);
+  CHECK_EQ(1, epilogue_call_count);
+  v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
+  v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(2, prologue_call_count);
+  CHECK_EQ(2, epilogue_call_count);
+  CHECK_EQ(1, prologue_call_count_second);
+  CHECK_EQ(1, epilogue_call_count_second);
+  v8::V8::RemoveGCPrologueCallback(PrologueCallback);
+  v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(2, prologue_call_count);
+  CHECK_EQ(2, epilogue_call_count);
+  CHECK_EQ(2, prologue_call_count_second);
+  CHECK_EQ(2, epilogue_call_count_second);
+  v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
+  v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(2, prologue_call_count);
+  CHECK_EQ(2, epilogue_call_count);
+  CHECK_EQ(2, prologue_call_count_second);
+  CHECK_EQ(2, epilogue_call_count_second);
 }
 
 
-// Test that idle notification can be handled and eventually collects garbage.
-TEST(IdleNotificationWithSmallHint) {
-  const intptr_t MB = 1024 * 1024;
-  const int IdlePauseInMs = 900;
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
-  CreateGarbageInOldSpace();
-  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
-  CHECK_GT(size_with_garbage, initial_size + MB);
-  bool finished = false;
-  for (int i = 0; i < 200 && !finished; i++) {
-    finished = v8::V8::IdleNotification(IdlePauseInMs);
-  }
-  intptr_t final_size = CcTest::heap()->SizeOfObjects();
-  CHECK(finished);
-  CHECK_LT(final_size, initial_size + 1);
+TEST(GCCallbacks) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  gc_callbacks_isolate = isolate;
+  isolate->AddGCPrologueCallback(PrologueCallback);
+  isolate->AddGCEpilogueCallback(EpilogueCallback);
+  CHECK_EQ(0, prologue_call_count);
+  CHECK_EQ(0, epilogue_call_count);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(1, prologue_call_count);
+  CHECK_EQ(1, epilogue_call_count);
+  isolate->AddGCPrologueCallback(PrologueCallbackSecond);
+  isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(2, prologue_call_count);
+  CHECK_EQ(2, epilogue_call_count);
+  CHECK_EQ(1, prologue_call_count_second);
+  CHECK_EQ(1, epilogue_call_count_second);
+  isolate->RemoveGCPrologueCallback(PrologueCallback);
+  isolate->RemoveGCEpilogueCallback(EpilogueCallback);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(2, prologue_call_count);
+  CHECK_EQ(2, epilogue_call_count);
+  CHECK_EQ(2, prologue_call_count_second);
+  CHECK_EQ(2, epilogue_call_count_second);
+  isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
+  isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
+  CcTest::heap()->CollectAllGarbage();
+  CHECK_EQ(2, prologue_call_count);
+  CHECK_EQ(2, epilogue_call_count);
+  CHECK_EQ(2, prologue_call_count_second);
+  CHECK_EQ(2, epilogue_call_count_second);
+
+  CHECK_EQ(0, prologue_call_count_alloc);
+  CHECK_EQ(0, epilogue_call_count_alloc);
+  isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
+  isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
+  CcTest::heap()->CollectAllGarbage(
+      i::Heap::kAbortIncrementalMarkingMask);
+  CHECK_EQ(1, prologue_call_count_alloc);
+  CHECK_EQ(1, epilogue_call_count_alloc);
+  isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
+  isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
 }
 
 
-// Test that idle notification can be handled and eventually collects garbage.
-TEST(IdleNotificationWithLargeHint) {
-  const intptr_t MB = 1024 * 1024;
-  const int IdlePauseInMs = 900;
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
-  CreateGarbageInOldSpace();
-  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
-  CHECK_GT(size_with_garbage, initial_size + MB);
-  bool finished = false;
-  for (int i = 0; i < 200 && !finished; i++) {
-    finished = v8::V8::IdleNotification(IdlePauseInMs);
-  }
-  intptr_t final_size = CcTest::heap()->SizeOfObjects();
-  CHECK(finished);
-  CHECK_LT(final_size, initial_size + 1);
-}
+THREADED_TEST(AddToJSFunctionResultCache) {
+  i::FLAG_stress_compaction = false;
+  i::FLAG_allow_natives_syntax = true;
+  v8::HandleScope scope(CcTest::isolate());
 
+  LocalContext context;
 
-TEST(Regress2107) {
-  const intptr_t MB = 1024 * 1024;
-  const int kShortIdlePauseInMs = 100;
-  const int kLongIdlePauseInMs = 1000;
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(env->GetIsolate());
-  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
-  // Send idle notification to start a round of incremental GCs.
-  v8::V8::IdleNotification(kShortIdlePauseInMs);
-  // Emulate 7 page reloads.
-  for (int i = 0; i < 7; i++) {
-    {
-      v8::HandleScope inner_scope(env->GetIsolate());
-      v8::Local<v8::Context> ctx = v8::Context::New(isolate);
-      ctx->Enter();
-      CreateGarbageInOldSpace();
-      ctx->Exit();
-    }
-    v8::V8::ContextDisposedNotification();
-    v8::V8::IdleNotification(kLongIdlePauseInMs);
-  }
-  // Create garbage and check that idle notification still collects it.
-  CreateGarbageInOldSpace();
-  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
-  CHECK_GT(size_with_garbage, initial_size + MB);
-  bool finished = false;
-  for (int i = 0; i < 200 && !finished; i++) {
-    finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
-  }
-  intptr_t final_size = CcTest::heap()->SizeOfObjects();
-  CHECK_LT(final_size, initial_size + 1);
+  const char* code =
+      "(function() {"
+      "  var key0 = 'a';"
+      "  var key1 = 'b';"
+      "  var r0 = %_GetFromCache(0, key0);"
+      "  var r1 = %_GetFromCache(0, key1);"
+      "  var r0_ = %_GetFromCache(0, key0);"
+      "  if (r0 !== r0_)"
+      "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
+      "  var r1_ = %_GetFromCache(0, key1);"
+      "  if (r1 !== r1_)"
+      "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
+      "  return 'PASSED';"
+      "})()";
+  CcTest::heap()->ClearJSFunctionResultCaches();
+  ExpectString(code, "PASSED");
 }
 
 
-TEST(Regress2333) {
-  LocalContext env;
-  for (int i = 0; i < 3; i++) {
-    CcTest::heap()->PerformScavenge();
-  }
+THREADED_TEST(FillJSFunctionResultCache) {
+  i::FLAG_allow_natives_syntax = true;
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+
+  const char* code =
+      "(function() {"
+      "  var k = 'a';"
+      "  var r = %_GetFromCache(0, k);"
+      "  for (var i = 0; i < 16; i++) {"
+      "    %_GetFromCache(0, 'a' + i);"
+      "  };"
+      "  if (r === %_GetFromCache(0, k))"
+      "    return 'FAILED: k0CacheSize is too small';"
+      "  return 'PASSED';"
+      "})()";
+  CcTest::heap()->ClearJSFunctionResultCaches();
+  ExpectString(code, "PASSED");
 }
 
-static uint32_t* stack_limit;
 
-static void GetStackLimitCallback(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  stack_limit = reinterpret_cast<uint32_t*>(
-      CcTest::i_isolate()->stack_guard()->real_climit());
+THREADED_TEST(RoundRobinGetFromCache) {
+  i::FLAG_allow_natives_syntax = true;
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+
+  const char* code =
+      "(function() {"
+      "  var keys = [];"
+      "  for (var i = 0; i < 16; i++) keys.push(i);"
+      "  var values = [];"
+      "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
+      "  for (var i = 0; i < 16; i++) {"
+      "    var v = %_GetFromCache(0, keys[i]);"
+      "    if (v.toString() !== values[i].toString())"
+      "      return 'Wrong value for ' + "
+      "          keys[i] + ': ' + v + ' vs. ' + values[i];"
+      "  };"
+      "  return 'PASSED';"
+      "})()";
+  CcTest::heap()->ClearJSFunctionResultCaches();
+  ExpectString(code, "PASSED");
 }
 
 
-// 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;
-}
+THREADED_TEST(ReverseGetFromCache) {
+  i::FLAG_allow_natives_syntax = true;
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
+  const char* code =
+      "(function() {"
+      "  var keys = [];"
+      "  for (var i = 0; i < 16; i++) keys.push(i);"
+      "  var values = [];"
+      "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
+      "  for (var i = 15; i >= 16; i--) {"
+      "    var v = %_GetFromCache(0, keys[i]);"
+      "    if (v !== values[i])"
+      "      return 'Wrong value for ' + "
+      "          keys[i] + ': ' + v + ' vs. ' + values[i];"
+      "  };"
+      "  return 'PASSED';"
+      "})()";
+  CcTest::heap()->ClearJSFunctionResultCaches();
+  ExpectString(code, "PASSED");
+}
 
-// We need at least 165kB for an x64 debug build with clang and ASAN.
-static const int stack_breathing_room = 256 * i::KB;
 
+THREADED_TEST(TestEviction) {
+  i::FLAG_allow_natives_syntax = true;
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
-TEST(SetResourceConstraints) {
-  uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
+  const char* code =
+      "(function() {"
+      "  for (var i = 0; i < 2*16; i++) {"
+      "    %_GetFromCache(0, 'a' + i);"
+      "  };"
+      "  return 'PASSED';"
+      "})()";
+  CcTest::heap()->ClearJSFunctionResultCaches();
+  ExpectString(code, "PASSED");
+}
 
-  // Set stack limit.
-  v8::ResourceConstraints constraints;
-  constraints.set_stack_limit(set_limit);
-  CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
 
-  // Execute a script.
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  Local<v8::FunctionTemplate> fun_templ =
-      v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
-  Local<Function> fun = fun_templ->GetFunction();
-  env->Global()->Set(v8_str("get_stack_limit"), fun);
-  CompileRun("get_stack_limit();");
+THREADED_TEST(TwoByteStringInOneByteCons) {
+  // See Chromium issue 47824.
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
-  CHECK(stack_limit == set_limit);
-}
+  const char* init_code =
+      "var str1 = 'abelspendabel';"
+      "var str2 = str1 + str1 + str1;"
+      "str2;";
+  Local<Value> result = CompileRun(init_code);
 
+  Local<Value> indexof = CompileRun("str2.indexOf('els')");
+  Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
 
-TEST(SetResourceConstraintsInThread) {
-  uint32_t* set_limit;
-  {
-    v8::Locker locker(CcTest::isolate());
-    set_limit = ComputeStackLimit(stack_breathing_room);
+  CHECK(result->IsString());
+  i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
+  int length = string->length();
+  CHECK(string->IsOneByteRepresentation());
 
-    // Set stack limit.
-    v8::ResourceConstraints constraints;
-    constraints.set_stack_limit(set_limit);
-    CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
+  i::Handle<i::String> flat_string = i::String::Flatten(string);
 
-    // Execute a script.
-    v8::HandleScope scope(CcTest::isolate());
-    LocalContext env;
-    Local<v8::FunctionTemplate> fun_templ =
-        v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
-    Local<Function> fun = fun_templ->GetFunction();
-    env->Global()->Set(v8_str("get_stack_limit"), fun);
-    CompileRun("get_stack_limit();");
+  CHECK(string->IsOneByteRepresentation());
+  CHECK(flat_string->IsOneByteRepresentation());
 
-    CHECK(stack_limit == set_limit);
-  }
-  {
-    v8::Locker locker(CcTest::isolate());
-    CHECK(stack_limit == set_limit);
-  }
-}
+  // Create external resource.
+  uint16_t* uc16_buffer = new uint16_t[length + 1];
 
+  i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
+  uc16_buffer[length] = 0;
 
-THREADED_TEST(GetHeapStatistics) {
-  LocalContext c1;
-  v8::HandleScope scope(c1->GetIsolate());
-  v8::HeapStatistics heap_statistics;
-  CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
-  CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
-  c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
-  CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
-  CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
-}
+  TestResource resource(uc16_buffer);
 
+  flat_string->MakeExternal(&resource);
 
-class VisitorImpl : public v8::ExternalResourceVisitor {
- public:
-  explicit VisitorImpl(TestResource** resource) {
-    for (int i = 0; i < 4; i++) {
-      resource_[i] = resource[i];
-      found_resource_[i] = false;
-    }
-  }
-  virtual ~VisitorImpl() {}
-  virtual void VisitExternalString(v8::Handle<v8::String> string) {
-    if (!string->IsExternal()) {
-      CHECK(string->IsExternalAscii());
-      return;
-    }
-    v8::String::ExternalStringResource* resource =
-        string->GetExternalStringResource();
-    CHECK(resource);
-    for (int i = 0; i < 4; i++) {
-      if (resource_[i] == resource) {
-        CHECK(!found_resource_[i]);
-        found_resource_[i] = true;
-      }
-    }
-  }
-  void CheckVisitedResources() {
-    for (int i = 0; i < 4; i++) {
-      CHECK(found_resource_[i]);
-    }
+  CHECK(flat_string->IsTwoByteRepresentation());
+
+  // If the cons string has been short-circuited, skip the following checks.
+  if (!string.is_identical_to(flat_string)) {
+    // At this point, we should have a Cons string which is flat and one-byte,
+    // with a first half that is a two-byte string (although it only contains
+    // one-byte characters). This is a valid sequence of steps, and it can
+    // happen in real pages.
+    CHECK(string->IsOneByteRepresentation());
+    i::ConsString* cons = i::ConsString::cast(*string);
+    CHECK_EQ(0, cons->second()->length());
+    CHECK(cons->first()->IsTwoByteRepresentation());
   }
 
- private:
-  v8::String::ExternalStringResource* resource_[4];
-  bool found_resource_[4];
-};
+  // Check that some string operations work.
 
+  // Atom RegExp.
+  Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
+  CHECK_EQ(6, reresult->Int32Value());
 
-TEST(ExternalizeOldSpaceTwoByteCons) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::Local<v8::String> cons =
-      CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
-  CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
-  CcTest::heap()->CollectAllAvailableGarbage();
-  CHECK(CcTest::heap()->old_pointer_space()->Contains(
-            *v8::Utils::OpenHandle(*cons)));
+  // Nonatom RegExp.
+  reresult = CompileRun("str2.match(/abe./g).length;");
+  CHECK_EQ(6, reresult->Int32Value());
 
-  TestResource* resource = new TestResource(
-      AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
-  cons->MakeExternal(resource);
+  reresult = CompileRun("str2.search(/bel/g);");
+  CHECK_EQ(1, reresult->Int32Value());
 
-  CHECK(cons->IsExternal());
-  CHECK_EQ(resource, cons->GetExternalStringResource());
-  String::Encoding encoding;
-  CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
-  CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
-}
+  reresult = CompileRun("str2.search(/be./g);");
+  CHECK_EQ(1, reresult->Int32Value());
 
+  ExpectTrue("/bel/g.test(str2);");
 
-TEST(ExternalizeOldSpaceOneByteCons) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::Local<v8::String> cons =
-      CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
-  CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
-  CcTest::heap()->CollectAllAvailableGarbage();
-  CHECK(CcTest::heap()->old_pointer_space()->Contains(
-            *v8::Utils::OpenHandle(*cons)));
+  ExpectTrue("/be./g.test(str2);");
 
-  TestAsciiResource* resource =
-      new TestAsciiResource(i::StrDup("Romeo Montague Juliet Capulet"));
-  cons->MakeExternal(resource);
+  reresult = CompileRun("/bel/g.exec(str2);");
+  CHECK(!reresult->IsNull());
 
-  CHECK(cons->IsExternalAscii());
-  CHECK_EQ(resource, cons->GetExternalAsciiStringResource());
-  String::Encoding encoding;
-  CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
-  CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
-}
+  reresult = CompileRun("/be./g.exec(str2);");
+  CHECK(!reresult->IsNull());
 
+  ExpectString("str2.substring(2, 10);", "elspenda");
 
-TEST(VisitExternalStrings) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  const char* string = "Some string";
-  uint16_t* two_byte_string = AsciiToTwoByteString(string);
-  TestResource* resource[4];
-  resource[0] = new TestResource(two_byte_string);
-  v8::Local<v8::String> string0 =
-      v8::String::NewExternal(env->GetIsolate(), resource[0]);
-  resource[1] = new TestResource(two_byte_string, NULL, false);
-  v8::Local<v8::String> string1 =
-      v8::String::NewExternal(env->GetIsolate(), resource[1]);
+  ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
 
-  // Externalized symbol.
-  resource[2] = new TestResource(two_byte_string, NULL, false);
-  v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
-      env->GetIsolate(), string, v8::String::kInternalizedString);
-  CHECK(string2->MakeExternal(resource[2]));
+  ExpectString("str2.charAt(2);", "e");
 
-  // Symbolized External.
-  resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
-  v8::Local<v8::String> string3 =
-      v8::String::NewExternal(env->GetIsolate(), resource[3]);
-  CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
-  // Turn into a symbol.
-  i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
-  CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
-  CHECK(string3_i->IsInternalizedString());
+  ExpectObject("str2.indexOf('els');", indexof);
 
-  // We need to add usages for string* to avoid warnings in GCC 4.7
-  CHECK(string0->IsExternal());
-  CHECK(string1->IsExternal());
-  CHECK(string2->IsExternal());
-  CHECK(string3->IsExternal());
+  ExpectObject("str2.lastIndexOf('dab');", lastindexof);
 
-  VisitorImpl visitor(resource);
-  v8::V8::VisitExternalResources(&visitor);
-  visitor.CheckVisitedResources();
+  reresult = CompileRun("str2.charCodeAt(2);");
+  CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
 }
 
 
-TEST(ExternalStringCollectedAtTearDown) {
-  int destroyed = 0;
-  v8::Isolate* isolate = v8::Isolate::New();
-  { v8::Isolate::Scope isolate_scope(isolate);
-    v8::HandleScope handle_scope(isolate);
-    const char* s = "One string to test them all, one string to find them.";
-    TestAsciiResource* inscription =
-        new TestAsciiResource(i::StrDup(s), &destroyed);
-    v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
-    // Ring is still alive.  Orcs are roaming freely across our lands.
-    CHECK_EQ(0, destroyed);
-    USE(ring);
+TEST(ContainsOnlyOneByte) {
+  v8::V8::Initialize();
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  // Make a buffer long enough that it won't automatically be converted.
+  const int length = 512;
+  // Ensure word aligned assignment.
+  const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
+  i::SmartArrayPointer<uintptr_t>
+  aligned_contents(new uintptr_t[aligned_length]);
+  uint16_t* string_contents =
+      reinterpret_cast<uint16_t*>(aligned_contents.get());
+  // Set to contain only one byte.
+  for (int i = 0; i < length-1; i++) {
+    string_contents[i] = 0x41;
+  }
+  string_contents[length-1] = 0;
+  // Simple case.
+  Handle<String> string =
+      String::NewExternal(isolate,
+                          new TestResource(string_contents, NULL, false));
+  CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
+  // Counter example.
+  string = String::NewFromTwoByte(isolate, string_contents);
+  CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
+  // Test left right and balanced cons strings.
+  Handle<String> base = String::NewFromUtf8(isolate, "a");
+  Handle<String> left = base;
+  Handle<String> right = base;
+  for (int i = 0; i < 1000; i++) {
+    left = String::Concat(base, left);
+    right = String::Concat(right, base);
+  }
+  Handle<String> balanced = String::Concat(left, base);
+  balanced = String::Concat(balanced, right);
+  Handle<String> cons_strings[] = {left, balanced, right};
+  Handle<String> two_byte =
+      String::NewExternal(isolate,
+                          new TestResource(string_contents, NULL, false));
+  USE(two_byte); USE(cons_strings);
+  for (size_t i = 0; i < arraysize(cons_strings); i++) {
+    // Base assumptions.
+    string = cons_strings[i];
+    CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
+    // Test left and right concatentation.
+    string = String::Concat(two_byte, cons_strings[i]);
+    CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
+    string = String::Concat(cons_strings[i], two_byte);
+    CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
+  }
+  // Set bits in different positions
+  // for strings of different lengths and alignments.
+  for (int alignment = 0; alignment < 7; alignment++) {
+    for (int size = 2; alignment + size < length; size *= 2) {
+      int zero_offset = size + alignment;
+      string_contents[zero_offset] = 0;
+      for (int i = 0; i < size; i++) {
+        int shift = 8 + (i % 7);
+        string_contents[alignment + i] = 1 << shift;
+        string = String::NewExternal(
+            isolate,
+            new TestResource(string_contents + alignment, NULL, false));
+        CHECK_EQ(size, string->Length());
+        CHECK(!string->ContainsOnlyOneByte());
+        string_contents[alignment + i] = 0x41;
+      }
+      string_contents[zero_offset] = 0x41;
+    }
   }
+}
 
-  isolate->Dispose();
-  // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
-  CHECK_EQ(1, destroyed);
+
+// Failed access check callback that performs a GC on each invocation.
+void FailedAccessCheckCallbackGC(Local<v8::Object> target,
+                                 v8::AccessType type,
+                                 Local<v8::Value> data) {
+  CcTest::heap()->CollectAllGarbage();
+  CcTest::isolate()->ThrowException(
+      v8::Exception::Error(v8_str("cross context")));
 }
 
 
-TEST(ExternalInternalizedStringCollectedAtTearDown) {
-  int destroyed = 0;
-  v8::Isolate* isolate = v8::Isolate::New();
-  { v8::Isolate::Scope isolate_scope(isolate);
-    LocalContext env(isolate);
-    v8::HandleScope handle_scope(isolate);
-    CompileRun("var ring = 'One string to test them all';");
-    const char* s = "One string to test them all";
-    TestAsciiResource* inscription =
-        new TestAsciiResource(i::StrDup(s), &destroyed);
-    v8::Local<v8::String> ring = CompileRun("ring")->ToString();
-    CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
-    ring->MakeExternal(inscription);
-    // Ring is still alive.  Orcs are roaming freely across our lands.
-    CHECK_EQ(0, destroyed);
-    USE(ring);
-  }
+TEST(GCInFailedAccessCheckCallback) {
+  // Install a failed access check callback that performs a GC on each
+  // invocation. Then force the callback to be called from va
 
-  isolate->Dispose();
-  // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
-  CHECK_EQ(1, destroyed);
-}
+  v8::V8::Initialize();
+  v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
 
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
 
-TEST(ExternalInternalizedStringCollectedAtGC) {
-  int destroyed = 0;
-  { LocalContext env;
-    v8::HandleScope handle_scope(env->GetIsolate());
-    CompileRun("var ring = 'One string to test them all';");
-    const char* s = "One string to test them all";
-    TestAsciiResource* inscription =
-        new TestAsciiResource(i::StrDup(s), &destroyed);
-    v8::Local<v8::String> ring = CompileRun("ring")->ToString();
-    CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
-    ring->MakeExternal(inscription);
-    // Ring is still alive.  Orcs are roaming freely across our lands.
-    CHECK_EQ(0, destroyed);
-    USE(ring);
-  }
+  // Create an ObjectTemplate for global objects and install access
+  // check callbacks that will block access.
+  v8::Handle<v8::ObjectTemplate> global_template =
+      v8::ObjectTemplate::New(isolate);
+  global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL,
+                                           v8::Handle<v8::Value>());
 
-  // Garbage collector deals swift blows to evil.
-  CcTest::i_isolate()->compilation_cache()->Clear();
-  CcTest::heap()->CollectAllAvailableGarbage();
+  // Create a context and set an x property on it's global object.
+  LocalContext context0(NULL, global_template);
+  context0->Global()->Set(v8_str("x"), v8_num(42));
+  v8::Handle<v8::Object> global0 = context0->Global();
+
+  // Create a context with a different security token so that the
+  // failed access check callback will be called on each access.
+  LocalContext context1(NULL, global_template);
+  context1->Global()->Set(v8_str("other"), global0);
+
+  v8::TryCatch try_catch(isolate);
+
+  // Get property with failed access check.
+  CHECK(CompileRun("other.x").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Get element with failed access check.
+  CHECK(CompileRun("other[0]").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Set property with failed access check.
+  CHECK(CompileRun("other.x = new Object()").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Set element with failed access check.
+  CHECK(CompileRun("other[0] = new Object()").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Get property attribute with failed access check.
+  CHECK(CompileRun("\'x\' in other").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
 
-  // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
-  CHECK_EQ(1, destroyed);
-}
+  // Get property attribute for element with failed access check.
+  CHECK(CompileRun("0 in other").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
 
+  // Delete property.
+  CHECK(CompileRun("delete other.x").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
 
-static double DoubleFromBits(uint64_t value) {
-  double target;
-  i::OS::MemCopy(&target, &value, sizeof(target));
-  return target;
-}
+  // Delete element.
+  CHECK_EQ(false, global0->Delete(0));
 
+  // DefineAccessor.
+  CHECK_EQ(false,
+           global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
 
-static uint64_t DoubleToBits(double value) {
-  uint64_t target;
-  i::OS::MemCopy(&target, &value, sizeof(target));
-  return target;
-}
+  // Define JavaScript accessor.
+  CHECK(CompileRun(
+            "Object.prototype.__defineGetter__.call("
+            "    other, \'x\', function() { return 42; })").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
 
+  // LookupAccessor.
+  CHECK(CompileRun(
+            "Object.prototype.__lookupGetter__.call("
+            "    other, \'x\')").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
 
-static double DoubleToDateTime(double input) {
-  double date_limit = 864e13;
-  if (std::isnan(input) || input < -date_limit || input > date_limit) {
-    return i::OS::nan_value();
-  }
-  return (input < 0) ? -(std::floor(-input)) : std::floor(input);
-}
+  // HasOwnElement.
+  CHECK(CompileRun(
+            "Object.prototype.hasOwnProperty.call("
+            "other, \'0\')").IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
 
+  CHECK_EQ(false, global0->HasRealIndexedProperty(0));
+  CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
+  CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
 
-// We don't have a consistent way to write 64-bit constants syntactically, so we
-// split them into two 32-bit constants and combine them programmatically.
-static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
-  return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
+  // Reset the failed access check callback so it does not influence
+  // the other tests.
+  v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
 }
 
 
-THREADED_TEST(QuietSignalingNaNs) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::TryCatch try_catch;
+TEST(IsolateNewDispose) {
+  v8::Isolate* current_isolate = CcTest::isolate();
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  CHECK(isolate != NULL);
+  CHECK(current_isolate != isolate);
+  CHECK(current_isolate == CcTest::isolate());
 
-  // Special double values.
-  double snan = DoubleFromBits(0x7ff00000, 0x00000001);
-  double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
-  double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
-  double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
-  double min_normal = DoubleFromBits(0x00100000, 0x00000000);
-  double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
-  double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
+  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+  last_location = last_message = NULL;
+  isolate->Dispose();
+  CHECK(!last_location);
+  CHECK(!last_message);
+}
 
-  // Date values are capped at +/-100000000 days (times 864e5 ms per day)
-  // on either side of the epoch.
-  double date_limit = 864e13;
 
-  double test_values[] = {
-      snan,
-      qnan,
-      infinity,
-      max_normal,
-      date_limit + 1,
-      date_limit,
-      min_normal,
-      max_denormal,
-      min_denormal,
-      0,
-      -0,
-      -min_denormal,
-      -max_denormal,
-      -min_normal,
-      -date_limit,
-      -date_limit - 1,
-      -max_normal,
-      -infinity,
-      -qnan,
-      -snan
-  };
-  int num_test_values = 20;
+UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  {
+    v8::Isolate::Scope i_scope(isolate);
+    v8::HandleScope scope(isolate);
+    LocalContext context(isolate);
+    // Run something in this isolate.
+    ExpectTrue("true");
+    v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+    last_location = last_message = NULL;
+    // Still entered, should fail.
+    isolate->Dispose();
+    CHECK(last_location);
+    CHECK(last_message);
+  }
+  isolate->Dispose();
+}
 
-  for (int i = 0; i < num_test_values; i++) {
-    double test_value = test_values[i];
 
-    // Check that Number::New preserves non-NaNs and quiets SNaNs.
-    v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
-    double stored_number = number->NumberValue();
-    if (!std::isnan(test_value)) {
-      CHECK_EQ(test_value, stored_number);
-    } else {
-      uint64_t stored_bits = DoubleToBits(stored_number);
-      // Check if quiet nan (bits 51..62 all set).
-#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
-      // Most significant fraction bit for quiet nan is set to 0
-      // on MIPS architecture. Allowed by IEEE-754.
-      CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
-#else
-      CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
-#endif
-    }
+static void BreakArrayGuarantees(const char* script) {
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate1 = v8::Isolate::New(create_params);
+  isolate1->Enter();
+  v8::Persistent<v8::Context> context1;
+  {
+    v8::HandleScope scope(isolate1);
+    context1.Reset(isolate1, Context::New(isolate1));
+  }
 
-    // Check that Date::New preserves non-NaNs in the date range and
-    // quiets SNaNs.
-    v8::Handle<v8::Value> date =
-        v8::Date::New(isolate, test_value);
-    double expected_stored_date = DoubleToDateTime(test_value);
-    double stored_date = date->NumberValue();
-    if (!std::isnan(expected_stored_date)) {
-      CHECK_EQ(expected_stored_date, stored_date);
-    } else {
-      uint64_t stored_bits = DoubleToBits(stored_date);
-      // Check if quiet nan (bits 51..62 all set).
-#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
-      // Most significant fraction bit for quiet nan is set to 0
-      // on MIPS architecture. Allowed by IEEE-754.
-      CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
-#else
-      CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
-#endif
-    }
+  {
+    v8::HandleScope scope(isolate1);
+    v8::Local<v8::Context> context =
+        v8::Local<v8::Context>::New(isolate1, context1);
+    v8::Context::Scope context_scope(context);
+    v8::internal::Isolate* i_isolate =
+        reinterpret_cast<v8::internal::Isolate*>(isolate1);
+    CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
+    // Run something in new isolate.
+    CompileRun(script);
+    CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
   }
+  isolate1->Exit();
+  isolate1->Dispose();
 }
 
 
-static void SpaghettiIncident(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::HandleScope scope(args.GetIsolate());
-  v8::TryCatch tc;
-  v8::Handle<v8::String> str(args[0]->ToString());
-  USE(str);
-  if (tc.HasCaught())
-    tc.ReThrow();
+TEST(VerifyArrayPrototypeGuarantees) {
+  // Break fast array hole handling by element changes.
+  BreakArrayGuarantees("[].__proto__[1] = 3;");
+  BreakArrayGuarantees("Object.prototype[3] = 'three';");
+  BreakArrayGuarantees("Array.prototype.push(1);");
+  BreakArrayGuarantees("Array.prototype.unshift(1);");
+  // Break fast array hole handling by changing length.
+  BreakArrayGuarantees("Array.prototype.length = 30;");
+  // Break fast array hole handling by prototype structure changes.
+  BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
+  // By sending elements to dictionary mode.
+  BreakArrayGuarantees("Object.freeze(Array.prototype);");
+  BreakArrayGuarantees("Object.freeze(Object.prototype);");
+  BreakArrayGuarantees(
+      "Object.defineProperty(Array.prototype, 0, {"
+      "  get: function() { return 3; }});");
+  BreakArrayGuarantees(
+      "Object.defineProperty(Object.prototype, 0, {"
+      "  get: function() { return 3; }});");
 }
 
 
-// Test that an exception can be propagated down through a spaghetti
-// stack using ReThrow.
-THREADED_TEST(SpaghettiStackReThrow) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  LocalContext context;
-  context->Global()->Set(
-      v8::String::NewFromUtf8(isolate, "s"),
-      v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
-  v8::TryCatch try_catch;
-  CompileRun(
-      "var i = 0;"
-      "var o = {"
-      "  toString: function () {"
-      "    if (i == 10) {"
-      "      throw 'Hey!';"
-      "    } else {"
-      "      i++;"
-      "      return s(o);"
-      "    }"
-      "  }"
-      "};"
-      "s(o);");
-  CHECK(try_catch.HasCaught());
-  v8::String::Utf8Value value(try_catch.Exception());
-  CHECK_EQ(0, strcmp(*value, "Hey!"));
-}
-
+TEST(RunTwoIsolatesOnSingleThread) {
+  // Run isolate 1.
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate1 = v8::Isolate::New(create_params);
+  isolate1->Enter();
+  v8::Persistent<v8::Context> context1;
+  {
+    v8::HandleScope scope(isolate1);
+    context1.Reset(isolate1, Context::New(isolate1));
+  }
 
-TEST(Regress528) {
-  v8::V8::Initialize();
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> other_context;
-  int gc_count;
+  {
+    v8::HandleScope scope(isolate1);
+    v8::Local<v8::Context> context =
+        v8::Local<v8::Context>::New(isolate1, context1);
+    v8::Context::Scope context_scope(context);
+    // Run something in new isolate.
+    CompileRun("var foo = 'isolate 1';");
+    ExpectString("function f() { return foo; }; f()", "isolate 1");
+  }
 
-  // Create a context used to keep the code from aging in the compilation
-  // cache.
-  other_context = Context::New(isolate);
+  // Run isolate 2.
+  v8::Isolate* isolate2 = v8::Isolate::New(create_params);
+  v8::Persistent<v8::Context> context2;
 
-  // Context-dependent context data creates reference from the compilation
-  // cache to the global object.
-  const char* source_simple = "1";
   {
-    v8::HandleScope scope(isolate);
-    v8::Local<Context> context = Context::New(isolate);
+    v8::Isolate::Scope iscope(isolate2);
+    v8::HandleScope scope(isolate2);
+    context2.Reset(isolate2, Context::New(isolate2));
+    v8::Local<v8::Context> context =
+        v8::Local<v8::Context>::New(isolate2, context2);
+    v8::Context::Scope context_scope(context);
 
-    context->Enter();
-    Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
-    context->SetEmbedderData(0, obj);
-    CompileRun(source_simple);
-    context->Exit();
-  }
-  v8::V8::ContextDisposedNotification();
-  for (gc_count = 1; gc_count < 10; gc_count++) {
-    other_context->Enter();
-    CompileRun(source_simple);
-    other_context->Exit();
-    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-    if (GetGlobalObjectsCount() == 1) break;
+    // Run something in new isolate.
+    CompileRun("var foo = 'isolate 2';");
+    ExpectString("function f() { return foo; }; f()", "isolate 2");
+  }
+
+  {
+    v8::HandleScope scope(isolate1);
+    v8::Local<v8::Context> context =
+        v8::Local<v8::Context>::New(isolate1, context1);
+    v8::Context::Scope context_scope(context);
+    // Now again in isolate 1
+    ExpectString("function f() { return foo; }; f()", "isolate 1");
   }
-  CHECK_GE(2, gc_count);
-  CHECK_EQ(1, GetGlobalObjectsCount());
 
-  // Eval in a function creates reference from the compilation cache to the
-  // global object.
-  const char* source_eval = "function f(){eval('1')}; f()";
+  isolate1->Exit();
+
+  // Run some stuff in default isolate.
+  v8::Persistent<v8::Context> context_default;
   {
+    v8::Isolate* isolate = CcTest::isolate();
+    v8::Isolate::Scope iscope(isolate);
     v8::HandleScope scope(isolate);
-    v8::Local<Context> context = Context::New(isolate);
+    context_default.Reset(isolate, Context::New(isolate));
+  }
 
-    context->Enter();
-    CompileRun(source_eval);
-    context->Exit();
+  {
+    v8::HandleScope scope(CcTest::isolate());
+    v8::Local<v8::Context> context =
+        v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
+    v8::Context::Scope context_scope(context);
+    // Variables in other isolates should be not available, verify there
+    // is an exception.
+    ExpectTrue("function f() {"
+               "  try {"
+               "    foo;"
+               "    return false;"
+               "  } catch(e) {"
+               "    return true;"
+               "  }"
+               "};"
+               "var isDefaultIsolate = true;"
+               "f()");
   }
-  v8::V8::ContextDisposedNotification();
-  for (gc_count = 1; gc_count < 10; gc_count++) {
-    other_context->Enter();
-    CompileRun(source_eval);
-    other_context->Exit();
-    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-    if (GetGlobalObjectsCount() == 1) break;
+
+  isolate1->Enter();
+
+  {
+    v8::Isolate::Scope iscope(isolate2);
+    v8::HandleScope scope(isolate2);
+    v8::Local<v8::Context> context =
+        v8::Local<v8::Context>::New(isolate2, context2);
+    v8::Context::Scope context_scope(context);
+    ExpectString("function f() { return foo; }; f()", "isolate 2");
   }
-  CHECK_GE(2, gc_count);
-  CHECK_EQ(1, GetGlobalObjectsCount());
 
-  // Looking up the line number for an exception creates reference from the
-  // compilation cache to the global object.
-  const char* source_exception = "function f(){throw 1;} f()";
   {
-    v8::HandleScope scope(isolate);
-    v8::Local<Context> context = Context::New(isolate);
+    v8::HandleScope scope(v8::Isolate::GetCurrent());
+    v8::Local<v8::Context> context =
+        v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
+    v8::Context::Scope context_scope(context);
+    ExpectString("function f() { return foo; }; f()", "isolate 1");
+  }
 
-    context->Enter();
-    v8::TryCatch try_catch;
-    CompileRun(source_exception);
-    CHECK(try_catch.HasCaught());
-    v8::Handle<v8::Message> message = try_catch.Message();
-    CHECK(!message.IsEmpty());
-    CHECK_EQ(1, message->GetLineNumber());
-    context->Exit();
+  {
+    v8::Isolate::Scope iscope(isolate2);
+    context2.Reset();
   }
-  v8::V8::ContextDisposedNotification();
-  for (gc_count = 1; gc_count < 10; gc_count++) {
-    other_context->Enter();
-    CompileRun(source_exception);
-    other_context->Exit();
-    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-    if (GetGlobalObjectsCount() == 1) break;
+
+  context1.Reset();
+  isolate1->Exit();
+
+  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+  last_location = last_message = NULL;
+
+  isolate1->Dispose();
+  CHECK(!last_location);
+  CHECK(!last_message);
+
+  isolate2->Dispose();
+  CHECK(!last_location);
+  CHECK(!last_message);
+
+  // Check that default isolate still runs.
+  {
+    v8::HandleScope scope(CcTest::isolate());
+    v8::Local<v8::Context> context =
+        v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
+    v8::Context::Scope context_scope(context);
+    ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   }
-  CHECK_GE(2, gc_count);
-  CHECK_EQ(1, GetGlobalObjectsCount());
+}
 
-  v8::V8::ContextDisposedNotification();
+
+static int CalcFibonacci(v8::Isolate* isolate, int limit) {
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::HandleScope scope(isolate);
+  LocalContext context(isolate);
+  i::ScopedVector<char> code(1024);
+  i::SNPrintF(code, "function fib(n) {"
+                    "  if (n <= 2) return 1;"
+                    "  return fib(n-1) + fib(n-2);"
+                    "}"
+                    "fib(%d)", limit);
+  Local<Value> value = CompileRun(code.start());
+  CHECK(value->IsNumber());
+  return static_cast<int>(value->NumberValue());
 }
 
+class IsolateThread : public v8::base::Thread {
+ public:
+  explicit IsolateThread(int fib_limit)
+      : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
 
-THREADED_TEST(ScriptOrigin) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
-  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
-      env->GetIsolate(), "function f() {}\n\nfunction g() {}");
-  v8::Script::Compile(script, &origin)->Run();
-  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
-  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
+  void Run() {
+    v8::Isolate::CreateParams create_params;
+    create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+    v8::Isolate* isolate = v8::Isolate::New(create_params);
+    result_ = CalcFibonacci(isolate, fib_limit_);
+    isolate->Dispose();
+  }
 
-  v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
-  CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
-  CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
+  int result() { return result_; }
 
-  v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
-  CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
-  CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
+ private:
+  int fib_limit_;
+  int result_;
+};
+
+
+TEST(MultipleIsolatesOnIndividualThreads) {
+  IsolateThread thread1(21);
+  IsolateThread thread2(12);
+
+  // Compute some fibonacci numbers on 3 threads in 3 isolates.
+  thread1.Start();
+  thread2.Start();
+
+  int result1 = CalcFibonacci(CcTest::isolate(), 21);
+  int result2 = CalcFibonacci(CcTest::isolate(), 12);
+
+  thread1.Join();
+  thread2.Join();
+
+  // Compare results. The actual fibonacci numbers for 12 and 21 are taken
+  // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
+  CHECK_EQ(result1, 10946);
+  CHECK_EQ(result2, 144);
+  CHECK_EQ(result1, thread1.result());
+  CHECK_EQ(result2, thread2.result());
 }
 
 
-THREADED_TEST(FunctionGetInferredName) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
-  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
-      env->GetIsolate(),
-      "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
-  v8::Script::Compile(script, &origin)->Run();
-  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
-  CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
+TEST(IsolateDifferentContexts) {
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  Local<v8::Context> context;
+  {
+    v8::Isolate::Scope isolate_scope(isolate);
+    v8::HandleScope handle_scope(isolate);
+    context = v8::Context::New(isolate);
+    v8::Context::Scope context_scope(context);
+    Local<Value> v = CompileRun("2");
+    CHECK(v->IsNumber());
+    CHECK_EQ(2, static_cast<int>(v->NumberValue()));
+  }
+  {
+    v8::Isolate::Scope isolate_scope(isolate);
+    v8::HandleScope handle_scope(isolate);
+    context = v8::Context::New(isolate);
+    v8::Context::Scope context_scope(context);
+    Local<Value> v = CompileRun("22");
+    CHECK(v->IsNumber());
+    CHECK_EQ(22, static_cast<int>(v->NumberValue()));
+  }
+  isolate->Dispose();
 }
 
+class InitDefaultIsolateThread : public v8::base::Thread {
+ public:
+  enum TestCase {
+    SetResourceConstraints,
+    SetFatalHandler,
+    SetCounterFunction,
+    SetCreateHistogramFunction,
+    SetAddHistogramSampleFunction
+  };
 
-THREADED_TEST(FunctionGetDisplayName) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  const char* code = "var error = false;"
-                     "function a() { this.x = 1; };"
-                     "a.displayName = 'display_a';"
-                     "var b = (function() {"
-                     "  var f = function() { this.x = 2; };"
-                     "  f.displayName = 'display_b';"
-                     "  return f;"
-                     "})();"
-                     "var c = function() {};"
-                     "c.__defineGetter__('displayName', function() {"
-                     "  error = true;"
-                     "  throw new Error();"
-                     "});"
-                     "function d() {};"
-                     "d.__defineGetter__('displayName', function() {"
-                     "  error = true;"
-                     "  return 'wrong_display_name';"
-                     "});"
-                     "function e() {};"
-                     "e.displayName = 'wrong_display_name';"
-                     "e.__defineSetter__('displayName', function() {"
-                     "  error = true;"
-                     "  throw new Error();"
-                     "});"
-                     "function f() {};"
-                     "f.displayName = { 'foo': 6, toString: function() {"
-                     "  error = true;"
-                     "  return 'wrong_display_name';"
-                     "}};"
-                     "var g = function() {"
-                     "  arguments.callee.displayName = 'set_in_runtime';"
-                     "}; g();"
-                     ;
-  v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
-  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
-      ->Run();
-  v8::Local<v8::Value> error =
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
-  v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
-  v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
-  v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
-  v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
-  v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
-  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
-  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
-  CHECK_EQ(false, error->BooleanValue());
-  CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
-  CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
-  CHECK(c->GetDisplayName()->IsUndefined());
-  CHECK(d->GetDisplayName()->IsUndefined());
-  CHECK(e->GetDisplayName()->IsUndefined());
-  CHECK(f->GetDisplayName()->IsUndefined());
-  CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
+  explicit InitDefaultIsolateThread(TestCase testCase)
+      : Thread(Options("InitDefaultIsolateThread")),
+        testCase_(testCase),
+        result_(false) {}
+
+  void Run() {
+    v8::Isolate::CreateParams create_params;
+    create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+    switch (testCase_) {
+      case SetResourceConstraints: {
+        create_params.constraints.set_max_semi_space_size(1);
+        create_params.constraints.set_max_old_space_size(4);
+        break;
+      }
+      default:
+        break;
+    }
+    v8::Isolate* isolate = v8::Isolate::New(create_params);
+    isolate->Enter();
+    switch (testCase_) {
+      case SetResourceConstraints:
+        // Already handled in pre-Isolate-creation block.
+        break;
+
+      case SetFatalHandler:
+        v8::V8::SetFatalErrorHandler(NULL);
+        break;
+
+      case SetCounterFunction:
+        CcTest::isolate()->SetCounterFunction(NULL);
+        break;
+
+      case SetCreateHistogramFunction:
+        CcTest::isolate()->SetCreateHistogramFunction(NULL);
+        break;
+
+      case SetAddHistogramSampleFunction:
+        CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
+        break;
+    }
+    isolate->Exit();
+    isolate->Dispose();
+    result_ = true;
+  }
+
+  bool result() { return result_; }
+
+ private:
+  TestCase testCase_;
+  bool result_;
+};
+
+
+static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
+  InitDefaultIsolateThread thread(testCase);
+  thread.Start();
+  thread.Join();
+  CHECK_EQ(thread.result(), true);
 }
 
 
-THREADED_TEST(ScriptLineNumber) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
-  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
-      env->GetIsolate(), "function f() {}\n\nfunction g() {}");
-  v8::Script::Compile(script, &origin)->Run();
-  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
-  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
-  CHECK_EQ(0, f->GetScriptLineNumber());
-  CHECK_EQ(2, g->GetScriptLineNumber());
+TEST(InitializeDefaultIsolateOnSecondaryThread1) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
 }
 
 
-THREADED_TEST(ScriptColumnNumber) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
-                       v8::Integer::New(isolate, 3),
-                       v8::Integer::New(isolate, 2));
-  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
-      isolate, "function foo() {}\n\n     function bar() {}");
-  v8::Script::Compile(script, &origin)->Run();
-  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
-  v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
-  CHECK_EQ(14, foo->GetScriptColumnNumber());
-  CHECK_EQ(17, bar->GetScriptColumnNumber());
+TEST(InitializeDefaultIsolateOnSecondaryThread2) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
 }
 
 
-THREADED_TEST(FunctionIsBuiltin) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<v8::Function> f;
-  f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
-  CHECK(f->IsBuiltin());
-  f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
-  CHECK(f->IsBuiltin());
-  f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
-  CHECK(f->IsBuiltin());
-  f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
-  CHECK(f->IsBuiltin());
-  f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
-  CHECK(!f->IsBuiltin());
+TEST(InitializeDefaultIsolateOnSecondaryThread3) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
 }
 
 
-THREADED_TEST(FunctionGetScriptId) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::ScriptOrigin origin =
-      v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
-                       v8::Integer::New(isolate, 3),
-                       v8::Integer::New(isolate, 2));
-  v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
-      isolate, "function foo() {}\n\n     function bar() {}");
-  v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
-  script->Run();
-  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
-  v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
-  CHECK_EQ(script->GetId(), foo->ScriptId());
-  CHECK_EQ(script->GetId(), bar->ScriptId());
+TEST(InitializeDefaultIsolateOnSecondaryThread4) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
 }
 
 
-THREADED_TEST(FunctionGetBoundFunction) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
-      env->GetIsolate(), "test"));
-  v8::Handle<v8::String> script = v8::String::NewFromUtf8(
-      env->GetIsolate(),
-      "var a = new Object();\n"
-      "a.x = 1;\n"
-      "function f () { return this.x };\n"
-      "var g = f.bind(a);\n"
-      "var b = g();");
-  v8::Script::Compile(script, &origin)->Run();
-  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
-  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
-      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
-  CHECK(g->GetBoundFunction()->IsFunction());
-  Local<v8::Function> original_function = Local<v8::Function>::Cast(
-      g->GetBoundFunction());
-  CHECK_EQ(f->GetName(), original_function->GetName());
-  CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
-  CHECK_EQ(f->GetScriptColumnNumber(),
-           original_function->GetScriptColumnNumber());
+TEST(InitializeDefaultIsolateOnSecondaryThread5) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
 }
 
 
-static void GetterWhichReturns42(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
-  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
-  info.GetReturnValue().Set(v8_num(42));
+TEST(StringCheckMultipleContexts) {
+  const char* code =
+      "(function() { return \"a\".charAt(0); })()";
+
+  {
+    // Run the code twice in the first context to initialize the call IC.
+    LocalContext context1;
+    v8::HandleScope scope(context1->GetIsolate());
+    ExpectString(code, "a");
+    ExpectString(code, "a");
+  }
+
+  {
+    // Change the String.prototype in the second context and check
+    // that the right function gets called.
+    LocalContext context2;
+    v8::HandleScope scope(context2->GetIsolate());
+    CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
+    ExpectString(code, "not a");
+  }
+}
+
+
+TEST(NumberCheckMultipleContexts) {
+  const char* code =
+      "(function() { return (42).toString(); })()";
+
+  {
+    // Run the code twice in the first context to initialize the call IC.
+    LocalContext context1;
+    v8::HandleScope scope(context1->GetIsolate());
+    ExpectString(code, "42");
+    ExpectString(code, "42");
+  }
+
+  {
+    // Change the Number.prototype in the second context and check
+    // that the right function gets called.
+    LocalContext context2;
+    v8::HandleScope scope(context2->GetIsolate());
+    CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
+    ExpectString(code, "not 42");
+  }
+}
+
+
+TEST(BooleanCheckMultipleContexts) {
+  const char* code =
+      "(function() { return true.toString(); })()";
+
+  {
+    // Run the code twice in the first context to initialize the call IC.
+    LocalContext context1;
+    v8::HandleScope scope(context1->GetIsolate());
+    ExpectString(code, "true");
+    ExpectString(code, "true");
+  }
+
+  {
+    // Change the Boolean.prototype in the second context and check
+    // that the right function gets called.
+    LocalContext context2;
+    v8::HandleScope scope(context2->GetIsolate());
+    CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
+    ExpectString(code, "");
+  }
+}
+
+
+TEST(DontDeleteCellLoadIC) {
+  const char* function_code =
+      "function readCell() { while (true) { return cell; } }";
+
+  {
+    // Run the code twice in the first context to initialize the load
+    // IC for a don't delete cell.
+    LocalContext context1;
+    v8::HandleScope scope(context1->GetIsolate());
+    CompileRun("var cell = \"first\";");
+    ExpectBoolean("delete cell", false);
+    CompileRun(function_code);
+    ExpectString("readCell()", "first");
+    ExpectString("readCell()", "first");
+  }
+
+  {
+    // Use a deletable cell in the second context.
+    LocalContext context2;
+    v8::HandleScope scope(context2->GetIsolate());
+    CompileRun("cell = \"second\";");
+    CompileRun(function_code);
+    ExpectString("readCell()", "second");
+    ExpectBoolean("delete cell", true);
+    ExpectString("(function() {"
+                 "  try {"
+                 "    return readCell();"
+                 "  } catch(e) {"
+                 "    return e.toString();"
+                 "  }"
+                 "})()",
+                 "ReferenceError: cell is not defined");
+    CompileRun("cell = \"new_second\";");
+    CcTest::heap()->CollectAllGarbage();
+    ExpectString("readCell()", "new_second");
+    ExpectString("readCell()", "new_second");
+  }
 }
 
 
-static void SetterWhichSetsYOnThisTo23(
-    Local<String> name,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<void>& info) {
-  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
-  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
-  info.This()->Set(v8_str("y"), v8_num(23));
-}
+class Visitor42 : public v8::PersistentHandleVisitor {
+ public:
+  explicit Visitor42(v8::Persistent<v8::Object>* object)
+      : counter_(0), object_(object) { }
+
+  virtual void VisitPersistentHandle(Persistent<Value>* value,
+                                     uint16_t class_id) {
+    if (class_id != 42) return;
+    CHECK_EQ(42, value->WrapperClassId());
+    v8::Isolate* isolate = CcTest::isolate();
+    v8::HandleScope handle_scope(isolate);
+    v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
+    v8::Handle<v8::Value> object =
+        v8::Local<v8::Object>::New(isolate, *object_);
+    CHECK(handle->IsObject());
+    CHECK(Handle<Object>::Cast(handle)->Equals(object));
+    ++counter_;
+  }
+
+  int counter_;
+  v8::Persistent<v8::Object>* object_;
+};
 
 
-void FooGetInterceptor(Local<String> name,
-                       const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
-  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
-  if (!name->Equals(v8_str("foo"))) return;
-  info.GetReturnValue().Set(v8_num(42));
-}
+TEST(PersistentHandleVisitor) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
+  CHECK_EQ(0, object.WrapperClassId());
+  object.SetWrapperClassId(42);
+  CHECK_EQ(42, object.WrapperClassId());
 
+  Visitor42 visitor(&object);
+  v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
+  CHECK_EQ(1, visitor.counter_);
 
-void FooSetInterceptor(Local<String> name,
-                       Local<Value> value,
-                       const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
-  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
-  if (!name->Equals(v8_str("foo"))) return;
-  info.This()->Set(v8_str("y"), v8_num(23));
-  info.GetReturnValue().Set(v8_num(23));
+  object.Reset();
 }
 
 
-TEST(SetterOnConstructorPrototype) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetAccessor(v8_str("x"),
-                     GetterWhichReturns42,
-                     SetterWhichSetsYOnThisTo23);
+TEST(WrapperClassId) {
   LocalContext context;
-  context->Global()->Set(v8_str("P"), templ->NewInstance());
-  CompileRun("function C1() {"
-             "  this.x = 23;"
-             "};"
-             "C1.prototype = P;"
-             "function C2() {"
-             "  this.x = 23"
-             "};"
-             "C2.prototype = { };"
-             "C2.prototype.__proto__ = P;");
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
+  CHECK_EQ(0, object.WrapperClassId());
+  object.SetWrapperClassId(65535);
+  CHECK_EQ(65535, object.WrapperClassId());
+  object.Reset();
+}
 
-  v8::Local<v8::Script> script;
-  script = v8::Script::Compile(v8_str("new C1();"));
-  for (int i = 0; i < 10; i++) {
-    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
-    CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
-    CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
-  }
 
-  script = v8::Script::Compile(v8_str("new C2();"));
-  for (int i = 0; i < 10; i++) {
-    v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
-    CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
-    CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
-  }
-}
+TEST(PersistentHandleInNewSpaceVisitor) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
+  CHECK_EQ(0, object1.WrapperClassId());
+  object1.SetWrapperClassId(42);
+  CHECK_EQ(42, object1.WrapperClassId());
 
+  CcTest::heap()->CollectAllGarbage();
+  CcTest::heap()->CollectAllGarbage();
 
-static void NamedPropertyGetterWhichReturns42(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(v8_num(42));
-}
+  v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
+  CHECK_EQ(0, object2.WrapperClassId());
+  object2.SetWrapperClassId(42);
+  CHECK_EQ(42, object2.WrapperClassId());
 
+  Visitor42 visitor(&object2);
+  v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
+  CHECK_EQ(1, visitor.counter_);
 
-static void NamedPropertySetterWhichSetsYOnThisTo23(
-    Local<String> name,
-    Local<Value> value,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  if (name->Equals(v8_str("x"))) {
-    info.This()->Set(v8_str("y"), v8_num(23));
-  }
+  object1.Reset();
+  object2.Reset();
 }
 
 
-THREADED_TEST(InterceptorOnConstructorPrototype) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
-                                 NamedPropertySetterWhichSetsYOnThisTo23);
+TEST(RegExp) {
   LocalContext context;
-  context->Global()->Set(v8_str("P"), templ->NewInstance());
-  CompileRun("function C1() {"
-             "  this.x = 23;"
-             "};"
-             "C1.prototype = P;"
-             "function C2() {"
-             "  this.x = 23"
-             "};"
-             "C2.prototype = { };"
-             "C2.prototype.__proto__ = P;");
+  v8::HandleScope scope(context->GetIsolate());
 
-  v8::Local<v8::Script> script;
-  script = v8::Script::Compile(v8_str("new C1();"));
-  for (int i = 0; i < 10; i++) {
-    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
-    CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
-    CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
-  }
+  v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
+  CHECK(re->IsRegExp());
+  CHECK(re->GetSource()->Equals(v8_str("foo")));
+  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
 
-  script = v8::Script::Compile(v8_str("new C2();"));
-  for (int i = 0; i < 10; i++) {
-    v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
-    CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
-    CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
-  }
-}
+  re = v8::RegExp::New(v8_str("bar"),
+                       static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
+                                                      v8::RegExp::kGlobal));
+  CHECK(re->IsRegExp());
+  CHECK(re->GetSource()->Equals(v8_str("bar")));
+  CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
+           static_cast<int>(re->GetFlags()));
 
+  re = v8::RegExp::New(v8_str("baz"),
+                       static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
+                                                      v8::RegExp::kMultiline));
+  CHECK(re->IsRegExp());
+  CHECK(re->GetSource()->Equals(v8_str("baz")));
+  CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
+           static_cast<int>(re->GetFlags()));
 
-TEST(Regress618) {
-  const char* source = "function C1() {"
-                       "  this.x = 23;"
-                       "};"
-                       "C1.prototype = P;";
+  re = CompileRun("/quux/").As<v8::RegExp>();
+  CHECK(re->IsRegExp());
+  CHECK(re->GetSource()->Equals(v8_str("quux")));
+  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
 
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<v8::Script> script;
+  re = CompileRun("/quux/gm").As<v8::RegExp>();
+  CHECK(re->IsRegExp());
+  CHECK(re->GetSource()->Equals(v8_str("quux")));
+  CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
+           static_cast<int>(re->GetFlags()));
 
-  // Use a simple object as prototype.
-  v8::Local<v8::Object> prototype = v8::Object::New(isolate);
-  prototype->Set(v8_str("y"), v8_num(42));
-  context->Global()->Set(v8_str("P"), prototype);
+  // Override the RegExp constructor and check the API constructor
+  // still works.
+  CompileRun("RegExp = function() {}");
 
-  // This compile will add the code to the compilation cache.
-  CompileRun(source);
+  re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
+  CHECK(re->IsRegExp());
+  CHECK(re->GetSource()->Equals(v8_str("foobar")));
+  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
 
-  script = v8::Script::Compile(v8_str("new C1();"));
-  // Allow enough iterations for the inobject slack tracking logic
-  // to finalize instance size and install the fast construct stub.
-  for (int i = 0; i < 256; i++) {
-    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
-    CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
-    CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
-  }
+  re = v8::RegExp::New(v8_str("foobarbaz"),
+                       static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
+                                                      v8::RegExp::kMultiline));
+  CHECK(re->IsRegExp());
+  CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
+  CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
+           static_cast<int>(re->GetFlags()));
 
-  // Use an API object with accessors as prototype.
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetAccessor(v8_str("x"),
-                     GetterWhichReturns42,
-                     SetterWhichSetsYOnThisTo23);
-  context->Global()->Set(v8_str("P"), templ->NewInstance());
+  context->Global()->Set(v8_str("re"), re);
+  ExpectTrue("re.test('FoobarbaZ')");
 
-  // This compile will get the code from the compilation cache.
-  CompileRun(source);
+  // RegExps are objects on which you can set properties.
+  re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
+  v8::Handle<v8::Value> value(CompileRun("re.property"));
+  CHECK_EQ(32, value->Int32Value());
 
-  script = v8::Script::Compile(v8_str("new C1();"));
-  for (int i = 0; i < 10; i++) {
-    v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
-    CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
-    CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
-  }
+  v8::TryCatch try_catch(context->GetIsolate());
+  re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
+  CHECK(re.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  context->Global()->Set(v8_str("ex"), try_catch.Exception());
+  ExpectTrue("ex instanceof SyntaxError");
 }
 
-v8::Isolate* gc_callbacks_isolate = NULL;
-int prologue_call_count = 0;
-int epilogue_call_count = 0;
-int prologue_call_count_second = 0;
-int epilogue_call_count_second = 0;
 
-void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
-  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
-  ++prologue_call_count;
-}
+THREADED_TEST(Equals) {
+  LocalContext localContext;
+  v8::HandleScope handleScope(localContext->GetIsolate());
 
+  v8::Handle<v8::Object> globalProxy = localContext->Global();
+  v8::Handle<Value> global = globalProxy->GetPrototype();
 
-void PrologueCallback(v8::Isolate* isolate,
-                      v8::GCType,
-                      v8::GCCallbackFlags flags) {
-  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
-  CHECK_EQ(gc_callbacks_isolate, isolate);
-  ++prologue_call_count;
+  CHECK(global->StrictEquals(global));
+  CHECK(!global->StrictEquals(globalProxy));
+  CHECK(!globalProxy->StrictEquals(global));
+  CHECK(globalProxy->StrictEquals(globalProxy));
+
+  CHECK(global->Equals(global));
+  CHECK(!global->Equals(globalProxy));
+  CHECK(!globalProxy->Equals(global));
+  CHECK(globalProxy->Equals(globalProxy));
 }
 
 
-void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
-  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
-  ++epilogue_call_count;
+static void Getter(v8::Local<v8::Name> property,
+                   const v8::PropertyCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(v8_str("42!"));
 }
 
 
-void EpilogueCallback(v8::Isolate* isolate,
-                      v8::GCType,
-                      v8::GCCallbackFlags flags) {
-  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
-  CHECK_EQ(gc_callbacks_isolate, isolate);
-  ++epilogue_call_count;
+static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
+  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
+  result->Set(0, v8_str("universalAnswer"));
+  info.GetReturnValue().Set(result);
 }
 
 
-void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
-  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
-  ++prologue_call_count_second;
+TEST(NamedEnumeratorAndForIn) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Context::Scope context_scope(context.local());
+
+  v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
+  tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
+                                                         NULL, Enumerator));
+  context->Global()->Set(v8_str("o"), tmpl->NewInstance());
+  v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
+        "var result = []; for (var k in o) result.push(k); result"));
+  CHECK_EQ(1u, result->Length());
+  CHECK(v8_str("universalAnswer")->Equals(result->Get(0)));
 }
 
 
-void PrologueCallbackSecond(v8::Isolate* isolate,
-                            v8::GCType,
-                            v8::GCCallbackFlags flags) {
-  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
-  CHECK_EQ(gc_callbacks_isolate, isolate);
-  ++prologue_call_count_second;
+TEST(DefinePropertyPostDetach) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::Handle<v8::Object> proxy = context->Global();
+  v8::Handle<v8::Function> define_property =
+      CompileRun("(function() {"
+                 "  Object.defineProperty("
+                 "    this,"
+                 "    1,"
+                 "    { configurable: true, enumerable: true, value: 3 });"
+                 "})").As<Function>();
+  context->DetachGlobal();
+  define_property->Call(proxy, 0, NULL);
 }
 
 
-void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
-  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
-  ++epilogue_call_count_second;
+static void InstallContextId(v8::Handle<Context> context, int id) {
+  Context::Scope scope(context);
+  CompileRun("Object.prototype").As<Object>()->
+      Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
 }
 
 
-void EpilogueCallbackSecond(v8::Isolate* isolate,
-                            v8::GCType,
-                            v8::GCCallbackFlags flags) {
-  CHECK_EQ(flags, v8::kNoGCCallbackFlags);
-  CHECK_EQ(gc_callbacks_isolate, isolate);
-  ++epilogue_call_count_second;
+static void CheckContextId(v8::Handle<Object> object, int expected) {
+  CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
 }
 
 
-TEST(GCCallbacksOld) {
-  LocalContext context;
+THREADED_TEST(CreationContext) {
+  v8::Isolate* isolate = CcTest::isolate();
+  HandleScope handle_scope(isolate);
+  Handle<Context> context1 = Context::New(isolate);
+  InstallContextId(context1, 1);
+  Handle<Context> context2 = Context::New(isolate);
+  InstallContextId(context2, 2);
+  Handle<Context> context3 = Context::New(isolate);
+  InstallContextId(context3, 3);
 
-  v8::V8::AddGCPrologueCallback(PrologueCallback);
-  v8::V8::AddGCEpilogueCallback(EpilogueCallback);
-  CHECK_EQ(0, prologue_call_count);
-  CHECK_EQ(0, epilogue_call_count);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CHECK_EQ(1, prologue_call_count);
-  CHECK_EQ(1, epilogue_call_count);
-  v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
-  v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CHECK_EQ(2, prologue_call_count);
-  CHECK_EQ(2, epilogue_call_count);
-  CHECK_EQ(1, prologue_call_count_second);
-  CHECK_EQ(1, epilogue_call_count_second);
-  v8::V8::RemoveGCPrologueCallback(PrologueCallback);
-  v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CHECK_EQ(2, prologue_call_count);
-  CHECK_EQ(2, epilogue_call_count);
-  CHECK_EQ(2, prologue_call_count_second);
-  CHECK_EQ(2, epilogue_call_count_second);
-  v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
-  v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CHECK_EQ(2, prologue_call_count);
-  CHECK_EQ(2, epilogue_call_count);
-  CHECK_EQ(2, prologue_call_count_second);
-  CHECK_EQ(2, epilogue_call_count_second);
-}
+  Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
 
+  Local<Object> object1;
+  Local<Function> func1;
+  {
+    Context::Scope scope(context1);
+    object1 = Object::New(isolate);
+    func1 = tmpl->GetFunction();
+  }
 
-TEST(GCCallbacks) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  gc_callbacks_isolate = isolate;
-  isolate->AddGCPrologueCallback(PrologueCallback);
-  isolate->AddGCEpilogueCallback(EpilogueCallback);
-  CHECK_EQ(0, prologue_call_count);
-  CHECK_EQ(0, epilogue_call_count);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CHECK_EQ(1, prologue_call_count);
-  CHECK_EQ(1, epilogue_call_count);
-  isolate->AddGCPrologueCallback(PrologueCallbackSecond);
-  isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CHECK_EQ(2, prologue_call_count);
-  CHECK_EQ(2, epilogue_call_count);
-  CHECK_EQ(1, prologue_call_count_second);
-  CHECK_EQ(1, epilogue_call_count_second);
-  isolate->RemoveGCPrologueCallback(PrologueCallback);
-  isolate->RemoveGCEpilogueCallback(EpilogueCallback);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CHECK_EQ(2, prologue_call_count);
-  CHECK_EQ(2, epilogue_call_count);
-  CHECK_EQ(2, prologue_call_count_second);
-  CHECK_EQ(2, epilogue_call_count_second);
-  isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
-  isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-  CHECK_EQ(2, prologue_call_count);
-  CHECK_EQ(2, epilogue_call_count);
-  CHECK_EQ(2, prologue_call_count_second);
-  CHECK_EQ(2, epilogue_call_count_second);
-}
+  Local<Object> object2;
+  Local<Function> func2;
+  {
+    Context::Scope scope(context2);
+    object2 = Object::New(isolate);
+    func2 = tmpl->GetFunction();
+  }
 
+  Local<Object> instance1;
+  Local<Object> instance2;
 
-THREADED_TEST(AddToJSFunctionResultCache) {
-  i::FLAG_stress_compaction = false;
-  i::FLAG_allow_natives_syntax = true;
-  v8::HandleScope scope(CcTest::isolate());
+  {
+    Context::Scope scope(context3);
+    instance1 = func1->NewInstance();
+    instance2 = func2->NewInstance();
+  }
 
-  LocalContext context;
+  {
+    Handle<Context> other_context = Context::New(isolate);
+    Context::Scope scope(other_context);
+    CHECK(object1->CreationContext() == context1);
+    CheckContextId(object1, 1);
+    CHECK(func1->CreationContext() == context1);
+    CheckContextId(func1, 1);
+    CHECK(instance1->CreationContext() == context1);
+    CheckContextId(instance1, 1);
+    CHECK(object2->CreationContext() == context2);
+    CheckContextId(object2, 2);
+    CHECK(func2->CreationContext() == context2);
+    CheckContextId(func2, 2);
+    CHECK(instance2->CreationContext() == context2);
+    CheckContextId(instance2, 2);
+  }
 
-  const char* code =
-      "(function() {"
-      "  var key0 = 'a';"
-      "  var key1 = 'b';"
-      "  var r0 = %_GetFromCache(0, key0);"
-      "  var r1 = %_GetFromCache(0, key1);"
-      "  var r0_ = %_GetFromCache(0, key0);"
-      "  if (r0 !== r0_)"
-      "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
-      "  var r1_ = %_GetFromCache(0, key1);"
-      "  if (r1 !== r1_)"
-      "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
-      "  return 'PASSED';"
-      "})()";
-  CcTest::heap()->ClearJSFunctionResultCaches();
-  ExpectString(code, "PASSED");
+  {
+    Context::Scope scope(context1);
+    CHECK(object1->CreationContext() == context1);
+    CheckContextId(object1, 1);
+    CHECK(func1->CreationContext() == context1);
+    CheckContextId(func1, 1);
+    CHECK(instance1->CreationContext() == context1);
+    CheckContextId(instance1, 1);
+    CHECK(object2->CreationContext() == context2);
+    CheckContextId(object2, 2);
+    CHECK(func2->CreationContext() == context2);
+    CheckContextId(func2, 2);
+    CHECK(instance2->CreationContext() == context2);
+    CheckContextId(instance2, 2);
+  }
+
+  {
+    Context::Scope scope(context2);
+    CHECK(object1->CreationContext() == context1);
+    CheckContextId(object1, 1);
+    CHECK(func1->CreationContext() == context1);
+    CheckContextId(func1, 1);
+    CHECK(instance1->CreationContext() == context1);
+    CheckContextId(instance1, 1);
+    CHECK(object2->CreationContext() == context2);
+    CheckContextId(object2, 2);
+    CHECK(func2->CreationContext() == context2);
+    CheckContextId(func2, 2);
+    CHECK(instance2->CreationContext() == context2);
+    CheckContextId(instance2, 2);
+  }
 }
 
 
-THREADED_TEST(FillJSFunctionResultCache) {
-  i::FLAG_allow_natives_syntax = true;
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+THREADED_TEST(CreationContextOfJsFunction) {
+  HandleScope handle_scope(CcTest::isolate());
+  Handle<Context> context = Context::New(CcTest::isolate());
+  InstallContextId(context, 1);
 
-  const char* code =
-      "(function() {"
-      "  var k = 'a';"
-      "  var r = %_GetFromCache(0, k);"
-      "  for (var i = 0; i < 16; i++) {"
-      "    %_GetFromCache(0, 'a' + i);"
-      "  };"
-      "  if (r === %_GetFromCache(0, k))"
-      "    return 'FAILED: k0CacheSize is too small';"
-      "  return 'PASSED';"
-      "})()";
-  CcTest::heap()->ClearJSFunctionResultCaches();
-  ExpectString(code, "PASSED");
-}
+  Local<Object> function;
+  {
+    Context::Scope scope(context);
+    function = CompileRun("function foo() {}; foo").As<Object>();
+  }
 
+  Handle<Context> other_context = Context::New(CcTest::isolate());
+  Context::Scope scope(other_context);
+  CHECK(function->CreationContext() == context);
+  CheckContextId(function, 1);
+}
 
-THREADED_TEST(RoundRobinGetFromCache) {
-  i::FLAG_allow_natives_syntax = true;
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
 
-  const char* code =
-      "(function() {"
-      "  var keys = [];"
-      "  for (var i = 0; i < 16; i++) keys.push(i);"
-      "  var values = [];"
-      "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
-      "  for (var i = 0; i < 16; i++) {"
-      "    var v = %_GetFromCache(0, keys[i]);"
-      "    if (v.toString() !== values[i].toString())"
-      "      return 'Wrong value for ' + "
-      "          keys[i] + ': ' + v + ' vs. ' + values[i];"
-      "  };"
-      "  return 'PASSED';"
-      "})()";
-  CcTest::heap()->ClearJSFunctionResultCaches();
-  ExpectString(code, "PASSED");
+void HasOwnPropertyIndexedPropertyGetter(
+    uint32_t index,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
 }
 
 
-THREADED_TEST(ReverseGetFromCache) {
-  i::FLAG_allow_natives_syntax = true;
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+void HasOwnPropertyNamedPropertyGetter(
+    Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
+}
 
-  const char* code =
-      "(function() {"
-      "  var keys = [];"
-      "  for (var i = 0; i < 16; i++) keys.push(i);"
-      "  var values = [];"
-      "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
-      "  for (var i = 15; i >= 16; i--) {"
-      "    var v = %_GetFromCache(0, keys[i]);"
-      "    if (v !== values[i])"
-      "      return 'Wrong value for ' + "
-      "          keys[i] + ': ' + v + ' vs. ' + values[i];"
-      "  };"
-      "  return 'PASSED';"
-      "})()";
-  CcTest::heap()->ClearJSFunctionResultCaches();
-  ExpectString(code, "PASSED");
+
+void HasOwnPropertyIndexedPropertyQuery(
+    uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
+  if (index == 42) info.GetReturnValue().Set(1);
 }
 
 
-THREADED_TEST(TestEviction) {
-  i::FLAG_allow_natives_syntax = true;
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+void HasOwnPropertyNamedPropertyQuery(
+    Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
+  if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
+}
 
-  const char* code =
-      "(function() {"
-      "  for (var i = 0; i < 2*16; i++) {"
-      "    %_GetFromCache(0, 'a' + i);"
-      "  };"
-      "  return 'PASSED';"
-      "})()";
-  CcTest::heap()->ClearJSFunctionResultCaches();
-  ExpectString(code, "PASSED");
+
+void HasOwnPropertyNamedPropertyQuery2(
+    Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
+  if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
 }
 
 
-THREADED_TEST(TwoByteStringInAsciiCons) {
-  // See Chromium issue 47824.
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+void HasOwnPropertyAccessorGetter(
+    Local<String> property,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(v8_str("yes"));
+}
 
-  const char* init_code =
-      "var str1 = 'abelspendabel';"
-      "var str2 = str1 + str1 + str1;"
-      "str2;";
-  Local<Value> result = CompileRun(init_code);
 
-  Local<Value> indexof = CompileRun("str2.indexOf('els')");
-  Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
+TEST(HasOwnProperty) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  { // Check normal properties and defined getters.
+    Handle<Value> value = CompileRun(
+        "function Foo() {"
+        "    this.foo = 11;"
+        "    this.__defineGetter__('baz', function() { return 1; });"
+        "};"
+        "function Bar() { "
+        "    this.bar = 13;"
+        "    this.__defineGetter__('bla', function() { return 2; });"
+        "};"
+        "Bar.prototype = new Foo();"
+        "new Bar();");
+    CHECK(value->IsObject());
+    Handle<Object> object = value->ToObject(isolate);
+    CHECK(object->Has(v8_str("foo")));
+    CHECK(!object->HasOwnProperty(v8_str("foo")));
+    CHECK(object->HasOwnProperty(v8_str("bar")));
+    CHECK(object->Has(v8_str("baz")));
+    CHECK(!object->HasOwnProperty(v8_str("baz")));
+    CHECK(object->HasOwnProperty(v8_str("bla")));
+  }
+  { // Check named getter interceptors.
+    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+    templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+        HasOwnPropertyNamedPropertyGetter));
+    Handle<Object> instance = templ->NewInstance();
+    CHECK(!instance->HasOwnProperty(v8_str("42")));
+    CHECK(instance->HasOwnProperty(v8_str("foo")));
+    CHECK(!instance->HasOwnProperty(v8_str("bar")));
+  }
+  { // Check indexed getter interceptors.
+    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+    templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
+        HasOwnPropertyIndexedPropertyGetter));
+    Handle<Object> instance = templ->NewInstance();
+    CHECK(instance->HasOwnProperty(v8_str("42")));
+    CHECK(!instance->HasOwnProperty(v8_str("43")));
+    CHECK(!instance->HasOwnProperty(v8_str("foo")));
+  }
+  { // Check named query interceptors.
+    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+    templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+        0, 0, HasOwnPropertyNamedPropertyQuery));
+    Handle<Object> instance = templ->NewInstance();
+    CHECK(instance->HasOwnProperty(v8_str("foo")));
+    CHECK(!instance->HasOwnProperty(v8_str("bar")));
+  }
+  { // Check indexed query interceptors.
+    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+    templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
+        0, 0, HasOwnPropertyIndexedPropertyQuery));
+    Handle<Object> instance = templ->NewInstance();
+    CHECK(instance->HasOwnProperty(v8_str("42")));
+    CHECK(!instance->HasOwnProperty(v8_str("41")));
+  }
+  { // Check callbacks.
+    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+    templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
+    Handle<Object> instance = templ->NewInstance();
+    CHECK(instance->HasOwnProperty(v8_str("foo")));
+    CHECK(!instance->HasOwnProperty(v8_str("bar")));
+  }
+  { // Check that query wins on disagreement.
+    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+    templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
+        HasOwnPropertyNamedPropertyGetter, 0,
+        HasOwnPropertyNamedPropertyQuery2));
+    Handle<Object> instance = templ->NewInstance();
+    CHECK(!instance->HasOwnProperty(v8_str("foo")));
+    CHECK(instance->HasOwnProperty(v8_str("bar")));
+  }
+}
 
-  CHECK(result->IsString());
-  i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
-  int length = string->length();
-  CHECK(string->IsOneByteRepresentation());
 
-  FlattenString(string);
-  i::Handle<i::String> flat_string = FlattenGetString(string);
+TEST(IndexedInterceptorWithStringProto) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
+      NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
+  LocalContext context;
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
+  // These should be intercepted.
+  CHECK(CompileRun("42 in obj")->BooleanValue());
+  CHECK(CompileRun("'42' in obj")->BooleanValue());
+  // These should fall through to the String prototype.
+  CHECK(CompileRun("0 in obj")->BooleanValue());
+  CHECK(CompileRun("'0' in obj")->BooleanValue());
+  // And these should both fail.
+  CHECK(!CompileRun("32 in obj")->BooleanValue());
+  CHECK(!CompileRun("'32' in obj")->BooleanValue());
+}
 
-  CHECK(string->IsOneByteRepresentation());
-  CHECK(flat_string->IsOneByteRepresentation());
 
-  // Create external resource.
-  uint16_t* uc16_buffer = new uint16_t[length + 1];
+void CheckCodeGenerationAllowed() {
+  Handle<Value> result = CompileRun("eval('42')");
+  CHECK_EQ(42, result->Int32Value());
+  result = CompileRun("(function(e) { return e('42'); })(eval)");
+  CHECK_EQ(42, result->Int32Value());
+  result = CompileRun("var f = new Function('return 42'); f()");
+  CHECK_EQ(42, result->Int32Value());
+}
 
-  i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
-  uc16_buffer[length] = 0;
 
-  TestResource resource(uc16_buffer);
+void CheckCodeGenerationDisallowed() {
+  TryCatch try_catch(CcTest::isolate());
 
-  flat_string->MakeExternal(&resource);
+  Handle<Value> result = CompileRun("eval('42')");
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
 
-  CHECK(flat_string->IsTwoByteRepresentation());
+  result = CompileRun("(function(e) { return e('42'); })(eval)");
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
 
-  // If the cons string has been short-circuited, skip the following checks.
-  if (!string.is_identical_to(flat_string)) {
-    // At this point, we should have a Cons string which is flat and ASCII,
-    // with a first half that is a two-byte string (although it only contains
-    // ASCII characters). This is a valid sequence of steps, and it can happen
-    // in real pages.
-    CHECK(string->IsOneByteRepresentation());
-    i::ConsString* cons = i::ConsString::cast(*string);
-    CHECK_EQ(0, cons->second()->length());
-    CHECK(cons->first()->IsTwoByteRepresentation());
-  }
+  result = CompileRun("var f = new Function('return 42'); f()");
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+}
 
-  // Check that some string operations work.
 
-  // Atom RegExp.
-  Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
-  CHECK_EQ(6, reresult->Int32Value());
+bool CodeGenerationAllowed(Local<Context> context) {
+  ApiTestFuzzer::Fuzz();
+  return true;
+}
 
-  // Nonatom RegExp.
-  reresult = CompileRun("str2.match(/abe./g).length;");
-  CHECK_EQ(6, reresult->Int32Value());
 
-  reresult = CompileRun("str2.search(/bel/g);");
-  CHECK_EQ(1, reresult->Int32Value());
+bool CodeGenerationDisallowed(Local<Context> context) {
+  ApiTestFuzzer::Fuzz();
+  return false;
+}
 
-  reresult = CompileRun("str2.search(/be./g);");
-  CHECK_EQ(1, reresult->Int32Value());
 
-  ExpectTrue("/bel/g.test(str2);");
+THREADED_TEST(AllowCodeGenFromStrings) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
-  ExpectTrue("/be./g.test(str2);");
+  // eval and the Function constructor allowed by default.
+  CHECK(context->IsCodeGenerationFromStringsAllowed());
+  CheckCodeGenerationAllowed();
 
-  reresult = CompileRun("/bel/g.exec(str2);");
-  CHECK(!reresult->IsNull());
+  // Disallow eval and the Function constructor.
+  context->AllowCodeGenerationFromStrings(false);
+  CHECK(!context->IsCodeGenerationFromStringsAllowed());
+  CheckCodeGenerationDisallowed();
 
-  reresult = CompileRun("/be./g.exec(str2);");
-  CHECK(!reresult->IsNull());
+  // Allow again.
+  context->AllowCodeGenerationFromStrings(true);
+  CheckCodeGenerationAllowed();
 
-  ExpectString("str2.substring(2, 10);", "elspenda");
+  // Disallow but setting a global callback that will allow the calls.
+  context->AllowCodeGenerationFromStrings(false);
+  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
+  CHECK(!context->IsCodeGenerationFromStringsAllowed());
+  CheckCodeGenerationAllowed();
 
-  ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
+  // Set a callback that disallows the code generation.
+  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
+  CHECK(!context->IsCodeGenerationFromStringsAllowed());
+  CheckCodeGenerationDisallowed();
+}
 
-  ExpectString("str2.charAt(2);", "e");
 
-  ExpectObject("str2.indexOf('els');", indexof);
+TEST(SetErrorMessageForCodeGenFromStrings) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  TryCatch try_catch(context->GetIsolate());
+
+  Handle<String> message = v8_str("Message") ;
+  Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
+  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
+  context->AllowCodeGenerationFromStrings(false);
+  context->SetErrorMessageForCodeGenerationFromStrings(message);
+  Handle<Value> result = CompileRun("eval('42')");
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  Handle<String> actual_message = try_catch.Message()->Get();
+  CHECK(expected_message->Equals(actual_message));
+}
+
+
+static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
+}
 
-  ExpectObject("str2.lastIndexOf('dab');", lastindexof);
 
-  reresult = CompileRun("str2.charCodeAt(2);");
-  CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
+THREADED_TEST(CallAPIFunctionOnNonObject) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Handle<FunctionTemplate> templ =
+      v8::FunctionTemplate::New(isolate, NonObjectThis);
+  Handle<Function> function = templ->GetFunction();
+  context->Global()->Set(v8_str("f"), function);
+  TryCatch try_catch(isolate);
+  CompileRun("f.call(2)");
 }
 
 
-TEST(ContainsOnlyOneByte) {
-  v8::V8::Initialize();
+// Regression test for issue 1470.
+THREADED_TEST(ReadOnlyIndexedProperties) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  // Make a buffer long enough that it won't automatically be converted.
-  const int length = 512;
-  // Ensure word aligned assignment.
-  const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
-  i::SmartArrayPointer<uintptr_t>
-  aligned_contents(new uintptr_t[aligned_length]);
-  uint16_t* string_contents =
-      reinterpret_cast<uint16_t*>(aligned_contents.get());
-  // Set to contain only one byte.
-  for (int i = 0; i < length-1; i++) {
-    string_contents[i] = 0x41;
-  }
-  string_contents[length-1] = 0;
-  // Simple case.
-  Handle<String> string =
-      String::NewExternal(isolate,
-                          new TestResource(string_contents, NULL, false));
-  CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
-  // Counter example.
-  string = String::NewFromTwoByte(isolate, string_contents);
-  CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
-  // Test left right and balanced cons strings.
-  Handle<String> base = String::NewFromUtf8(isolate, "a");
-  Handle<String> left = base;
-  Handle<String> right = base;
-  for (int i = 0; i < 1000; i++) {
-    left = String::Concat(base, left);
-    right = String::Concat(right, base);
-  }
-  Handle<String> balanced = String::Concat(left, base);
-  balanced = String::Concat(balanced, right);
-  Handle<String> cons_strings[] = {left, balanced, right};
-  Handle<String> two_byte =
-      String::NewExternal(isolate,
-                          new TestResource(string_contents, NULL, false));
-  USE(two_byte); USE(cons_strings);
-  for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
-    // Base assumptions.
-    string = cons_strings[i];
-    CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
-    // Test left and right concatentation.
-    string = String::Concat(two_byte, cons_strings[i]);
-    CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
-    string = String::Concat(cons_strings[i], two_byte);
-    CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
-  }
-  // Set bits in different positions
-  // for strings of different lengths and alignments.
-  for (int alignment = 0; alignment < 7; alignment++) {
-    for (int size = 2; alignment + size < length; size *= 2) {
-      int zero_offset = size + alignment;
-      string_contents[zero_offset] = 0;
-      for (int i = 0; i < size; i++) {
-        int shift = 8 + (i % 7);
-        string_contents[alignment + i] = 1 << shift;
-        string = String::NewExternal(
-            isolate,
-            new TestResource(string_contents + alignment, NULL, false));
-        CHECK_EQ(size, string->Length());
-        CHECK(!string->ContainsOnlyOneByte());
-        string_contents[alignment + i] = 0x41;
-      }
-      string_contents[zero_offset] = 0x41;
-    }
-  }
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+
+  LocalContext context;
+  Local<v8::Object> obj = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), obj);
+  obj->ForceSet(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
+  obj->Set(v8_str("1"), v8_str("foobar"));
+  CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("1"))));
+  obj->ForceSet(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
+  obj->Set(v8_num(2), v8_str("foobar"));
+  CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_num(2))));
+
+  // Test non-smi case.
+  obj->ForceSet(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
+  obj->Set(v8_str("2000000000"), v8_str("foobar"));
+  CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("2000000000"))));
 }
 
 
-// Failed access check callback that performs a GC on each invocation.
-void FailedAccessCheckCallbackGC(Local<v8::Object> target,
-                                 v8::AccessType type,
-                                 Local<v8::Value> data) {
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+static int CountLiveMapsInMapCache(i::Context* context) {
+  i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
+  int length = map_cache->length();
+  int count = 0;
+  for (int i = 0; i < length; i++) {
+    i::Object* value = map_cache->get(i);
+    if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
+  }
+  return count;
 }
 
 
-TEST(GCInFailedAccessCheckCallback) {
-  // Install a failed access check callback that performs a GC on each
-  // invocation. Then force the callback to be called from va
+THREADED_TEST(Regress1516) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
-  v8::V8::Initialize();
-  v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
+  // Object with 20 properties is not a common case, so it should be removed
+  // from the cache after GC.
+  { v8::HandleScope temp_scope(context->GetIsolate());
+    CompileRun(
+        "({"
+        "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
+        "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
+        "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
+        "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
+        "})");
+  }
 
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
+  int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
+  CHECK_LE(1, elements);
 
-  // Create an ObjectTemplate for global objects and install access
-  // check callbacks that will block access.
-  v8::Handle<v8::ObjectTemplate> global_template =
-      v8::ObjectTemplate::New(isolate);
-  global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
-                                           IndexedGetAccessBlocker,
-                                           v8::Handle<v8::Value>(),
-                                           false);
+  CcTest::heap()->CollectAllGarbage();
 
-  // Create a context and set an x property on it's global object.
-  LocalContext context0(NULL, global_template);
-  context0->Global()->Set(v8_str("x"), v8_num(42));
-  v8::Handle<v8::Object> global0 = context0->Global();
+  CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
+}
 
-  // Create a context with a different security token so that the
-  // failed access check callback will be called on each access.
-  LocalContext context1(NULL, global_template);
-  context1->Global()->Set(v8_str("other"), global0);
 
-  // Get property with failed access check.
-  ExpectUndefined("other.x");
+THREADED_TEST(Regress93759) {
+  v8::Isolate* isolate = CcTest::isolate();
+  HandleScope scope(isolate);
 
-  // Get element with failed access check.
-  ExpectUndefined("other[0]");
+  // Template for object with security check.
+  Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
+  no_proto_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
 
-  // Set property with failed access check.
-  v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
-  CHECK(result->IsObject());
+  // Templates for objects with hidden prototypes and possibly security check.
+  Local<FunctionTemplate> hidden_proto_template =
+      v8::FunctionTemplate::New(isolate);
+  hidden_proto_template->SetHiddenPrototype(true);
 
-  // Set element with failed access check.
-  result = CompileRun("other[0] = new Object()");
-  CHECK(result->IsObject());
+  Local<FunctionTemplate> protected_hidden_proto_template =
+      v8::FunctionTemplate::New(isolate);
+  protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
+      AccessAlwaysBlocked, NULL);
+  protected_hidden_proto_template->SetHiddenPrototype(true);
 
-  // Get property attribute with failed access check.
-  ExpectFalse("\'x\' in other");
+  // Context for "foreign" objects used in test.
+  Local<Context> context = v8::Context::New(isolate);
+  context->Enter();
 
-  // Get property attribute for element with failed access check.
-  ExpectFalse("0 in other");
+  // Plain object, no security check.
+  Local<Object> simple_object = Object::New(isolate);
 
-  // Delete property.
-  ExpectFalse("delete other.x");
+  // Object with explicit security check.
+  Local<Object> protected_object = no_proto_template->NewInstance();
 
-  // Delete element.
-  CHECK_EQ(false, global0->Delete(0));
+  // JSGlobalProxy object, always have security check.
+  Local<Object> proxy_object = context->Global();
 
-  // DefineAccessor.
-  CHECK_EQ(false,
-           global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
+  // Global object, the  prototype of proxy_object. No security checks.
+  Local<Object> global_object = proxy_object->GetPrototype()->ToObject(isolate);
 
-  // Define JavaScript accessor.
-  ExpectUndefined("Object.prototype.__defineGetter__.call("
-                  "    other, \'x\', function() { return 42; })");
+  // Hidden prototype without security check.
+  Local<Object> hidden_prototype =
+      hidden_proto_template->GetFunction()->NewInstance();
+  Local<Object> object_with_hidden =
+    Object::New(isolate);
+  object_with_hidden->SetPrototype(hidden_prototype);
 
-  // LookupAccessor.
-  ExpectUndefined("Object.prototype.__lookupGetter__.call("
-                  "    other, \'x\')");
+  // Hidden prototype with security check on the hidden prototype.
+  Local<Object> protected_hidden_prototype =
+      protected_hidden_proto_template->GetFunction()->NewInstance();
+  Local<Object> object_with_protected_hidden =
+    Object::New(isolate);
+  object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
 
-  // HasLocalElement.
-  ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
+  context->Exit();
 
-  CHECK_EQ(false, global0->HasRealIndexedProperty(0));
-  CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
-  CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
+  // Template for object for second context. Values to test are put on it as
+  // properties.
+  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
+  global_template->Set(v8_str("simple"), simple_object);
+  global_template->Set(v8_str("protected"), protected_object);
+  global_template->Set(v8_str("global"), global_object);
+  global_template->Set(v8_str("proxy"), proxy_object);
+  global_template->Set(v8_str("hidden"), object_with_hidden);
+  global_template->Set(v8_str("phidden"), object_with_protected_hidden);
 
-  // Reset the failed access check callback so it does not influence
-  // the other tests.
-  v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
-}
+  LocalContext context2(NULL, global_template);
 
+  Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
+  CHECK(result1->Equals(simple_object->GetPrototype()));
 
-TEST(IsolateNewDispose) {
-  v8::Isolate* current_isolate = CcTest::isolate();
-  v8::Isolate* isolate = v8::Isolate::New();
-  CHECK(isolate != NULL);
-  CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
-  CHECK(current_isolate != isolate);
-  CHECK(current_isolate == CcTest::isolate());
+  Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
+  CHECK(result2.IsEmpty());
 
-  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
-  last_location = last_message = NULL;
-  isolate->Dispose();
-  CHECK_EQ(last_location, NULL);
-  CHECK_EQ(last_message, NULL);
-}
+  Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
+  CHECK(result3->Equals(global_object->GetPrototype()));
 
+  Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
+  CHECK(result4.IsEmpty());
 
-UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
-  v8::Isolate* isolate = v8::Isolate::New();
-  {
-    v8::Isolate::Scope i_scope(isolate);
-    v8::HandleScope scope(isolate);
-    LocalContext context(isolate);
-    // Run something in this isolate.
-    ExpectTrue("true");
-    v8::V8::SetFatalErrorHandler(StoringErrorCallback);
-    last_location = last_message = NULL;
-    // Still entered, should fail.
-    isolate->Dispose();
-    CHECK_NE(last_location, NULL);
-    CHECK_NE(last_message, NULL);
-  }
-  isolate->Dispose();
-}
+  Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
+  CHECK(result5->Equals(
+      object_with_hidden->GetPrototype()->ToObject(isolate)->GetPrototype()));
 
+  Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
+  CHECK(result6.IsEmpty());
+}
 
-TEST(RunTwoIsolatesOnSingleThread) {
-  // Run isolate 1.
-  v8::Isolate* isolate1 = v8::Isolate::New();
-  isolate1->Enter();
-  v8::Persistent<v8::Context> context1;
-  {
-    v8::HandleScope scope(isolate1);
-    context1.Reset(isolate1, Context::New(isolate1));
-  }
 
-  {
-    v8::HandleScope scope(isolate1);
-    v8::Local<v8::Context> context =
-        v8::Local<v8::Context>::New(isolate1, context1);
-    v8::Context::Scope context_scope(context);
-    // Run something in new isolate.
-    CompileRun("var foo = 'isolate 1';");
-    ExpectString("function f() { return foo; }; f()", "isolate 1");
-  }
+static void TestReceiver(Local<Value> expected_result,
+                         Local<Value> expected_receiver,
+                         const char* code) {
+  Local<Value> result = CompileRun(code);
+  CHECK(result->IsObject());
+  CHECK(expected_receiver->Equals(result.As<v8::Object>()->Get(1)));
+  CHECK(expected_result->Equals(result.As<v8::Object>()->Get(0)));
+}
 
-  // Run isolate 2.
-  v8::Isolate* isolate2 = v8::Isolate::New();
-  v8::Persistent<v8::Context> context2;
 
-  {
-    v8::Isolate::Scope iscope(isolate2);
-    v8::HandleScope scope(isolate2);
-    context2.Reset(isolate2, Context::New(isolate2));
-    v8::Local<v8::Context> context =
-        v8::Local<v8::Context>::New(isolate2, context2);
-    v8::Context::Scope context_scope(context);
+THREADED_TEST(ForeignFunctionReceiver) {
+  v8::Isolate* isolate = CcTest::isolate();
+  HandleScope scope(isolate);
 
-    // Run something in new isolate.
-    CompileRun("var foo = 'isolate 2';");
-    ExpectString("function f() { return foo; }; f()", "isolate 2");
-  }
+  // Create two contexts with different "id" properties ('i' and 'o').
+  // Call a function both from its own context and from a the foreign
+  // context, and see what "this" is bound to (returning both "this"
+  // and "this.id" for comparison).
 
-  {
-    v8::HandleScope scope(isolate1);
-    v8::Local<v8::Context> context =
-        v8::Local<v8::Context>::New(isolate1, context1);
-    v8::Context::Scope context_scope(context);
-    // Now again in isolate 1
-    ExpectString("function f() { return foo; }; f()", "isolate 1");
-  }
+  Local<Context> foreign_context = v8::Context::New(isolate);
+  foreign_context->Enter();
+  Local<Value> foreign_function =
+    CompileRun("function func() { return { 0: this.id, "
+               "                           1: this, "
+               "                           toString: function() { "
+               "                               return this[0];"
+               "                           }"
+               "                         };"
+               "}"
+               "var id = 'i';"
+               "func;");
+  CHECK(foreign_function->IsFunction());
+  foreign_context->Exit();
 
-  isolate1->Exit();
+  LocalContext context;
 
-  // Run some stuff in default isolate.
-  v8::Persistent<v8::Context> context_default;
-  {
-    v8::Isolate* isolate = CcTest::isolate();
-    v8::Isolate::Scope iscope(isolate);
-    v8::HandleScope scope(isolate);
-    context_default.Reset(isolate, Context::New(isolate));
-  }
+  Local<String> password = v8_str("Password");
+  // Don't get hit by security checks when accessing foreign_context's
+  // global receiver (aka. global proxy).
+  context->SetSecurityToken(password);
+  foreign_context->SetSecurityToken(password);
 
-  {
-    v8::HandleScope scope(CcTest::isolate());
-    v8::Local<v8::Context> context =
-        v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
-    v8::Context::Scope context_scope(context);
-    // Variables in other isolates should be not available, verify there
-    // is an exception.
-    ExpectTrue("function f() {"
-               "  try {"
-               "    foo;"
-               "    return false;"
-               "  } catch(e) {"
-               "    return true;"
-               "  }"
-               "};"
-               "var isDefaultIsolate = true;"
-               "f()");
-  }
+  Local<String> i = v8_str("i");
+  Local<String> o = v8_str("o");
+  Local<String> id = v8_str("id");
 
-  isolate1->Enter();
+  CompileRun("function ownfunc() { return { 0: this.id, "
+             "                              1: this, "
+             "                              toString: function() { "
+             "                                  return this[0];"
+             "                              }"
+             "                             };"
+             "}"
+             "var id = 'o';"
+             "ownfunc");
+  context->Global()->Set(v8_str("func"), foreign_function);
 
-  {
-    v8::Isolate::Scope iscope(isolate2);
-    v8::HandleScope scope(isolate2);
-    v8::Local<v8::Context> context =
-        v8::Local<v8::Context>::New(isolate2, context2);
-    v8::Context::Scope context_scope(context);
-    ExpectString("function f() { return foo; }; f()", "isolate 2");
-  }
+  // Sanity check the contexts.
+  CHECK(i->Equals(foreign_context->Global()->Get(id)));
+  CHECK(o->Equals(context->Global()->Get(id)));
 
-  {
-    v8::HandleScope scope(v8::Isolate::GetCurrent());
-    v8::Local<v8::Context> context =
-        v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
-    v8::Context::Scope context_scope(context);
-    ExpectString("function f() { return foo; }; f()", "isolate 1");
-  }
+  // Checking local function's receiver.
+  // Calling function using its call/apply methods.
+  TestReceiver(o, context->Global(), "ownfunc.call()");
+  TestReceiver(o, context->Global(), "ownfunc.apply()");
+  // Making calls through built-in functions.
+  TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
+  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
+  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
+  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
+  // Calling with environment record as base.
+  TestReceiver(o, context->Global(), "ownfunc()");
+  // Calling with no base.
+  TestReceiver(o, context->Global(), "(1,ownfunc)()");
 
-  {
-    v8::Isolate::Scope iscope(isolate2);
-    context2.Reset();
-  }
+  // Checking foreign function return value.
+  // Calling function using its call/apply methods.
+  TestReceiver(i, foreign_context->Global(), "func.call()");
+  TestReceiver(i, foreign_context->Global(), "func.apply()");
+  // Calling function using another context's call/apply methods.
+  TestReceiver(i, foreign_context->Global(),
+               "Function.prototype.call.call(func)");
+  TestReceiver(i, foreign_context->Global(),
+               "Function.prototype.call.apply(func)");
+  TestReceiver(i, foreign_context->Global(),
+               "Function.prototype.apply.call(func)");
+  TestReceiver(i, foreign_context->Global(),
+               "Function.prototype.apply.apply(func)");
+  // Making calls through built-in functions.
+  TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
+  // ToString(func()) is func()[0], i.e., the returned this.id.
+  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
+  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
+  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
 
-  context1.Reset();
-  isolate1->Exit();
+  // Calling with environment record as base.
+  TestReceiver(i, foreign_context->Global(), "func()");
+  // Calling with no base.
+  TestReceiver(i, foreign_context->Global(), "(1,func)()");
+}
 
-  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
-  last_location = last_message = NULL;
 
-  isolate1->Dispose();
-  CHECK_EQ(last_location, NULL);
-  CHECK_EQ(last_message, NULL);
+uint8_t callback_fired = 0;
 
-  isolate2->Dispose();
-  CHECK_EQ(last_location, NULL);
-  CHECK_EQ(last_message, NULL);
 
-  // Check that default isolate still runs.
-  {
-    v8::HandleScope scope(CcTest::isolate());
-    v8::Local<v8::Context> context =
-        v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
-    v8::Context::Scope context_scope(context);
-    ExpectTrue("function f() { return isDefaultIsolate; }; f()");
-  }
+void CallCompletedCallback1() {
+  v8::base::OS::Print("Firing callback 1.\n");
+  callback_fired ^= 1;  // Toggle first bit.
 }
 
 
-static int CalcFibonacci(v8::Isolate* isolate, int limit) {
-  v8::Isolate::Scope isolate_scope(isolate);
-  v8::HandleScope scope(isolate);
-  LocalContext context(isolate);
-  i::ScopedVector<char> code(1024);
-  i::OS::SNPrintF(code, "function fib(n) {"
-                        "  if (n <= 2) return 1;"
-                        "  return fib(n-1) + fib(n-2);"
-                        "}"
-                        "fib(%d)", limit);
-  Local<Value> value = CompileRun(code.start());
-  CHECK(value->IsNumber());
-  return static_cast<int>(value->NumberValue());
+void CallCompletedCallback2() {
+  v8::base::OS::Print("Firing callback 2.\n");
+  callback_fired ^= 2;  // Toggle second bit.
 }
 
-class IsolateThread : public v8::internal::Thread {
- public:
-  IsolateThread(v8::Isolate* isolate, int fib_limit)
-      : Thread("IsolateThread"),
-        isolate_(isolate),
-        fib_limit_(fib_limit),
-        result_(0) { }
 
-  void Run() {
-    result_ = CalcFibonacci(isolate_, fib_limit_);
+void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  int32_t level = args[0]->Int32Value();
+  if (level < 3) {
+    level++;
+    v8::base::OS::Print("Entering recursion level %d.\n", level);
+    char script[64];
+    i::Vector<char> script_vector(script, sizeof(script));
+    i::SNPrintF(script_vector, "recursion(%d)", level);
+    CompileRun(script_vector.start());
+    v8::base::OS::Print("Leaving recursion level %d.\n", level);
+    CHECK_EQ(0, callback_fired);
+  } else {
+    v8::base::OS::Print("Recursion ends.\n");
+    CHECK_EQ(0, callback_fired);
   }
+}
 
-  int result() { return result_; }
 
- private:
-  v8::Isolate* isolate_;
-  int fib_limit_;
-  int result_;
-};
+TEST(CallCompletedCallback) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::Handle<v8::FunctionTemplate> recursive_runtime =
+      v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
+  env->Global()->Set(v8_str("recursion"),
+                     recursive_runtime->GetFunction());
+  // Adding the same callback a second time has no effect.
+  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
+  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
+  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
+  v8::base::OS::Print("--- Script (1) ---\n");
+  Local<Script> script = v8::Script::Compile(
+      v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
+  script->Run();
+  CHECK_EQ(3, callback_fired);
 
+  v8::base::OS::Print("\n--- Script (2) ---\n");
+  callback_fired = 0;
+  env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
+  script->Run();
+  CHECK_EQ(2, callback_fired);
 
-TEST(MultipleIsolatesOnIndividualThreads) {
-  v8::Isolate* isolate1 = v8::Isolate::New();
-  v8::Isolate* isolate2 = v8::Isolate::New();
+  v8::base::OS::Print("\n--- Function ---\n");
+  callback_fired = 0;
+  Local<Function> recursive_function =
+      Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
+  v8::Handle<Value> args[] = { v8_num(0) };
+  recursive_function->Call(env->Global(), 1, args);
+  CHECK_EQ(2, callback_fired);
+}
 
-  IsolateThread thread1(isolate1, 21);
-  IsolateThread thread2(isolate2, 12);
 
-  // Compute some fibonacci numbers on 3 threads in 3 isolates.
-  thread1.Start();
-  thread2.Start();
+void CallCompletedCallbackNoException() {
+  v8::HandleScope scope(CcTest::isolate());
+  CompileRun("1+1;");
+}
 
-  int result1 = CalcFibonacci(CcTest::isolate(), 21);
-  int result2 = CalcFibonacci(CcTest::isolate(), 12);
 
-  thread1.Join();
-  thread2.Join();
+void CallCompletedCallbackException() {
+  v8::HandleScope scope(CcTest::isolate());
+  CompileRun("throw 'second exception';");
+}
 
-  // Compare results. The actual fibonacci numbers for 12 and 21 are taken
-  // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
-  CHECK_EQ(result1, 10946);
-  CHECK_EQ(result2, 144);
-  CHECK_EQ(result1, thread1.result());
-  CHECK_EQ(result2, thread2.result());
 
-  isolate1->Dispose();
-  isolate2->Dispose();
+TEST(CallCompletedCallbackOneException) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
+  CompileRun("throw 'exception';");
 }
 
-
-TEST(IsolateDifferentContexts) {
-  v8::Isolate* isolate = v8::Isolate::New();
-  Local<v8::Context> context;
-  {
-    v8::Isolate::Scope isolate_scope(isolate);
-    v8::HandleScope handle_scope(isolate);
-    context = v8::Context::New(isolate);
-    v8::Context::Scope context_scope(context);
-    Local<Value> v = CompileRun("2");
-    CHECK(v->IsNumber());
-    CHECK_EQ(2, static_cast<int>(v->NumberValue()));
-  }
-  {
-    v8::Isolate::Scope isolate_scope(isolate);
-    v8::HandleScope handle_scope(isolate);
-    context = v8::Context::New(isolate);
-    v8::Context::Scope context_scope(context);
-    Local<Value> v = CompileRun("22");
-    CHECK(v->IsNumber());
-    CHECK_EQ(22, static_cast<int>(v->NumberValue()));
-  }
-  isolate->Dispose();
+
+TEST(CallCompletedCallbackTwoExceptions) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
+  CompileRun("throw 'first exception';");
 }
 
-class InitDefaultIsolateThread : public v8::internal::Thread {
- public:
-  enum TestCase {
-    IgnoreOOM,
-    SetResourceConstraints,
-    SetFatalHandler,
-    SetCounterFunction,
-    SetCreateHistogramFunction,
-    SetAddHistogramSampleFunction
-  };
 
-  explicit InitDefaultIsolateThread(TestCase testCase)
-      : Thread("InitDefaultIsolateThread"),
-        testCase_(testCase),
-        result_(false) { }
+static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
+  v8::HandleScope scope(info.GetIsolate());
+  CompileRun("ext1Calls++;");
+}
 
-  void Run() {
-    v8::Isolate* isolate = v8::Isolate::New();
-    isolate->Enter();
-    switch (testCase_) {
-    case IgnoreOOM:
-      v8::V8::IgnoreOutOfMemoryException();
-      break;
 
-    case SetResourceConstraints: {
-      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(CcTest::isolate(), &constraints);
-      break;
-    }
+static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
+  v8::HandleScope scope(info.GetIsolate());
+  CompileRun("ext2Calls++;");
+}
 
-    case SetFatalHandler:
-      v8::V8::SetFatalErrorHandler(NULL);
-      break;
 
-    case SetCounterFunction:
-      v8::V8::SetCounterFunction(NULL);
-      break;
+void* g_passed_to_three = NULL;
 
-    case SetCreateHistogramFunction:
-      v8::V8::SetCreateHistogramFunction(NULL);
-      break;
 
-    case SetAddHistogramSampleFunction:
-      v8::V8::SetAddHistogramSampleFunction(NULL);
-      break;
-    }
-    isolate->Exit();
-    isolate->Dispose();
-    result_ = true;
-  }
+static void MicrotaskThree(void* data) {
+  g_passed_to_three = data;
+}
 
-  bool result() { return result_; }
 
- private:
-  TestCase testCase_;
-  bool result_;
-};
+TEST(EnqueueMicrotask) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  CompileRun(
+      "var ext1Calls = 0;"
+      "var ext2Calls = 0;");
+  CompileRun("1+1;");
+  CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
 
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskOne));
+  CompileRun("1+1;");
+  CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
 
-static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
-  InitDefaultIsolateThread thread(testCase);
-  thread.Start();
-  thread.Join();
-  CHECK_EQ(thread.result(), true);
-}
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskOne));
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskTwo));
+  CompileRun("1+1;");
+  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
 
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskTwo));
+  CompileRun("1+1;");
+  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
 
-TEST(InitializeDefaultIsolateOnSecondaryThread1) {
-  InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
+  CompileRun("1+1;");
+  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
+
+  g_passed_to_three = NULL;
+  env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
+  CompileRun("1+1;");
+  CHECK(!g_passed_to_three);
+  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
+
+  int dummy;
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskOne));
+  env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskTwo));
+  CompileRun("1+1;");
+  CHECK_EQ(&dummy, g_passed_to_three);
+  CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
+  g_passed_to_three = NULL;
 }
 
 
-TEST(InitializeDefaultIsolateOnSecondaryThread2) {
-  InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
+static void MicrotaskExceptionOne(
+    const v8::FunctionCallbackInfo<Value>& info) {
+  v8::HandleScope scope(info.GetIsolate());
+  CompileRun("exception1Calls++;");
+  info.GetIsolate()->ThrowException(
+      v8::Exception::Error(v8_str("first")));
 }
 
 
-TEST(InitializeDefaultIsolateOnSecondaryThread3) {
-  InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
+static void MicrotaskExceptionTwo(
+    const v8::FunctionCallbackInfo<Value>& info) {
+  v8::HandleScope scope(info.GetIsolate());
+  CompileRun("exception2Calls++;");
+  info.GetIsolate()->ThrowException(
+      v8::Exception::Error(v8_str("second")));
 }
 
 
-TEST(InitializeDefaultIsolateOnSecondaryThread4) {
-  InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
+TEST(RunMicrotasksIgnoresThrownExceptions) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  CompileRun(
+      "var exception1Calls = 0;"
+      "var exception2Calls = 0;");
+  isolate->EnqueueMicrotask(
+      Function::New(isolate, MicrotaskExceptionOne));
+  isolate->EnqueueMicrotask(
+      Function::New(isolate, MicrotaskExceptionTwo));
+  TryCatch try_catch(isolate);
+  CompileRun("1+1;");
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value());
+  CHECK_EQ(1, CompileRun("exception2Calls")->Int32Value());
 }
 
 
-TEST(InitializeDefaultIsolateOnSecondaryThread5) {
-  InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
-}
+TEST(SetAutorunMicrotasks) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  CompileRun(
+      "var ext1Calls = 0;"
+      "var ext2Calls = 0;");
+  CompileRun("1+1;");
+  CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
 
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskOne));
+  CompileRun("1+1;");
+  CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
+
+  env->GetIsolate()->SetAutorunMicrotasks(false);
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskOne));
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskTwo));
+  CompileRun("1+1;");
+  CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
 
-TEST(InitializeDefaultIsolateOnSecondaryThread6) {
-  InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
-}
+  env->GetIsolate()->RunMicrotasks();
+  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
 
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskTwo));
+  CompileRun("1+1;");
+  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
 
-TEST(StringCheckMultipleContexts) {
-  const char* code =
-      "(function() { return \"a\".charAt(0); })()";
+  env->GetIsolate()->RunMicrotasks();
+  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
 
-  {
-    // Run the code twice in the first context to initialize the call IC.
-    LocalContext context1;
-    v8::HandleScope scope(context1->GetIsolate());
-    ExpectString(code, "a");
-    ExpectString(code, "a");
-  }
+  env->GetIsolate()->SetAutorunMicrotasks(true);
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskTwo));
+  CompileRun("1+1;");
+  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
 
+  env->GetIsolate()->EnqueueMicrotask(
+      Function::New(env->GetIsolate(), MicrotaskTwo));
   {
-    // Change the String.prototype in the second context and check
-    // that the right function gets called.
-    LocalContext context2;
-    v8::HandleScope scope(context2->GetIsolate());
-    CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
-    ExpectString(code, "not a");
+    v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
+    CompileRun("1+1;");
+    CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+    CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
   }
-}
 
+  CompileRun("1+1;");
+  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+  CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value());
+}
 
-TEST(NumberCheckMultipleContexts) {
-  const char* code =
-      "(function() { return (42).toString(); })()";
 
+TEST(RunMicrotasksWithoutEnteringContext) {
+  v8::Isolate* isolate = CcTest::isolate();
+  HandleScope handle_scope(isolate);
+  isolate->SetAutorunMicrotasks(false);
+  Handle<Context> context = Context::New(isolate);
   {
-    // Run the code twice in the first context to initialize the call IC.
-    LocalContext context1;
-    v8::HandleScope scope(context1->GetIsolate());
-    ExpectString(code, "42");
-    ExpectString(code, "42");
+    Context::Scope context_scope(context);
+    CompileRun("var ext1Calls = 0;");
+    isolate->EnqueueMicrotask(Function::New(isolate, MicrotaskOne));
   }
-
+  isolate->RunMicrotasks();
   {
-    // Change the Number.prototype in the second context and check
-    // that the right function gets called.
-    LocalContext context2;
-    v8::HandleScope scope(context2->GetIsolate());
-    CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
-    ExpectString(code, "not 42");
+    Context::Scope context_scope(context);
+    CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
   }
+  isolate->SetAutorunMicrotasks(true);
 }
 
 
-TEST(BooleanCheckMultipleContexts) {
-  const char* code =
-      "(function() { return true.toString(); })()";
+static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
+  v8::DebugEvent event = event_details.GetEvent();
+  if (event != v8::Break) return;
+  Handle<Object> exec_state = event_details.GetExecutionState();
+  Handle<Value> break_id = exec_state->Get(v8_str("break_id"));
+  CompileRun("function f(id) { new FrameDetails(id, 0); }");
+  Handle<Function> fun =
+      Handle<Function>::Cast(CcTest::global()->Get(v8_str("f")));
+  fun->Call(CcTest::global(), 1, &break_id);
+}
 
-  {
-    // Run the code twice in the first context to initialize the call IC.
-    LocalContext context1;
-    v8::HandleScope scope(context1->GetIsolate());
-    ExpectString(code, "true");
-    ExpectString(code, "true");
-  }
 
+TEST(Regress385349) {
+  i::FLAG_allow_natives_syntax = true;
+  v8::Isolate* isolate = CcTest::isolate();
+  HandleScope handle_scope(isolate);
+  isolate->SetAutorunMicrotasks(false);
+  Handle<Context> context = Context::New(isolate);
+  v8::Debug::SetDebugEventListener(DebugEventInObserver);
   {
-    // Change the Boolean.prototype in the second context and check
-    // that the right function gets called.
-    LocalContext context2;
-    v8::HandleScope scope(context2->GetIsolate());
-    CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
-    ExpectString(code, "");
+    Context::Scope context_scope(context);
+    CompileRun("var obj = {};"
+               "Object.observe(obj, function(changes) { debugger; });"
+               "obj.a = 0;");
   }
+  isolate->RunMicrotasks();
+  isolate->SetAutorunMicrotasks(true);
+  v8::Debug::SetDebugEventListener(NULL);
 }
 
 
-TEST(DontDeleteCellLoadIC) {
-  const char* function_code =
-      "function readCell() { while (true) { return cell; } }";
+#ifdef ENABLE_DISASSEMBLER
+static int probes_counter = 0;
+static int misses_counter = 0;
+static int updates_counter = 0;
 
-  {
-    // Run the code twice in the first context to initialize the load
-    // IC for a don't delete cell.
-    LocalContext context1;
-    v8::HandleScope scope(context1->GetIsolate());
-    CompileRun("var cell = \"first\";");
-    ExpectBoolean("delete cell", false);
-    CompileRun(function_code);
-    ExpectString("readCell()", "first");
-    ExpectString("readCell()", "first");
+
+static int* LookupCounter(const char* name) {
+  if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
+    return &probes_counter;
+  } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
+    return &misses_counter;
+  } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
+    return &updates_counter;
   }
+  return NULL;
+}
 
-  {
-    // Use a deletable cell in the second context.
-    LocalContext context2;
-    v8::HandleScope scope(context2->GetIsolate());
-    CompileRun("cell = \"second\";");
-    CompileRun(function_code);
-    ExpectString("readCell()", "second");
-    ExpectBoolean("delete cell", true);
-    ExpectString("(function() {"
-                 "  try {"
-                 "    return readCell();"
-                 "  } catch(e) {"
-                 "    return e.toString();"
-                 "  }"
-                 "})()",
-                 "ReferenceError: cell is not defined");
-    CompileRun("cell = \"new_second\";");
-    CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-    ExpectString("readCell()", "new_second");
-    ExpectString("readCell()", "new_second");
+
+static const char* kMegamorphicTestProgram =
+    "function ClassA() { };"
+    "function ClassB() { };"
+    "ClassA.prototype.foo = function() { };"
+    "ClassB.prototype.foo = function() { };"
+    "function fooify(obj) { obj.foo(); };"
+    "var a = new ClassA();"
+    "var b = new ClassB();"
+    "for (var i = 0; i < 10000; i++) {"
+    "  fooify(a);"
+    "  fooify(b);"
+    "}";
+#endif
+
+
+static void StubCacheHelper(bool primary) {
+#ifdef ENABLE_DISASSEMBLER
+  i::FLAG_native_code_counters = true;
+  if (primary) {
+    i::FLAG_test_primary_stub_cache = true;
+  } else {
+    i::FLAG_test_secondary_stub_cache = true;
   }
+  i::FLAG_crankshaft = false;
+  LocalContext env;
+  env->GetIsolate()->SetCounterFunction(LookupCounter);
+  v8::HandleScope scope(env->GetIsolate());
+  int initial_probes = probes_counter;
+  int initial_misses = misses_counter;
+  int initial_updates = updates_counter;
+  CompileRun(kMegamorphicTestProgram);
+  int probes = probes_counter - initial_probes;
+  int misses = misses_counter - initial_misses;
+  int updates = updates_counter - initial_updates;
+  CHECK_LT(updates, 10);
+  CHECK_LT(misses, 10);
+  // TODO(verwaest): Update this test to overflow the degree of polymorphism
+  // before megamorphism. The number of probes will only work once we teach the
+  // serializer to embed references to counters in the stubs, given that the
+  // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
+  CHECK_GE(probes, 0);
+#endif
 }
 
 
-TEST(DontDeleteCellLoadICForceDelete) {
-  const char* function_code =
-      "function readCell() { while (true) { return cell; } }";
+TEST(SecondaryStubCache) {
+  StubCacheHelper(true);
+}
 
-  // Run the code twice to initialize the load IC for a don't delete
-  // cell.
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  CompileRun("var cell = \"value\";");
-  ExpectBoolean("delete cell", false);
-  CompileRun(function_code);
-  ExpectString("readCell()", "value");
-  ExpectString("readCell()", "value");
-
-  // Delete the cell using the API and check the inlined code works
-  // correctly.
-  CHECK(context->Global()->ForceDelete(v8_str("cell")));
-  ExpectString("(function() {"
-               "  try {"
-               "    return readCell();"
-               "  } catch(e) {"
-               "    return e.toString();"
-               "  }"
-               "})()",
-               "ReferenceError: cell is not defined");
+
+TEST(PrimaryStubCache) {
+  StubCacheHelper(false);
+}
+
+
+#ifdef DEBUG
+static int cow_arrays_created_runtime = 0;
+
+
+static int* LookupCounterCOWArrays(const char* name) {
+  if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
+    return &cow_arrays_created_runtime;
+  }
+  return NULL;
+}
+#endif
+
+
+TEST(CheckCOWArraysCreatedRuntimeCounter) {
+#ifdef DEBUG
+  i::FLAG_native_code_counters = true;
+  LocalContext env;
+  env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
+  v8::HandleScope scope(env->GetIsolate());
+  int initial_cow_arrays = cow_arrays_created_runtime;
+  CompileRun("var o = [1, 2, 3];");
+  CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
+  CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
+  CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
+  CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
+  CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
+#endif
 }
 
 
-TEST(DontDeleteCellLoadICAPI) {
-  const char* function_code =
-      "function readCell() { while (true) { return cell; } }";
-
-  // Run the code twice to initialize the load IC for a don't delete
-  // cell created using the API.
+TEST(StaticGetters) {
   LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
-  ExpectBoolean("delete cell", false);
-  CompileRun(function_code);
-  ExpectString("readCell()", "value");
-  ExpectString("readCell()", "value");
-
-  // Delete the cell using the API and check the inlined code works
-  // correctly.
-  CHECK(context->Global()->ForceDelete(v8_str("cell")));
-  ExpectString("(function() {"
-               "  try {"
-               "    return readCell();"
-               "  } catch(e) {"
-               "    return e.toString();"
-               "  }"
-               "})()",
-               "ReferenceError: cell is not defined");
+  i::Factory* factory = CcTest::i_isolate()->factory();
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  i::Handle<i::Object> undefined_value = factory->undefined_value();
+  CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
+  i::Handle<i::Object> null_value = factory->null_value();
+  CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
+  i::Handle<i::Object> true_value = factory->true_value();
+  CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
+  i::Handle<i::Object> false_value = factory->false_value();
+  CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
 }
 
 
-class Visitor42 : public v8::PersistentHandleVisitor {
- public:
-  explicit Visitor42(v8::Persistent<v8::Object>* object)
-      : counter_(0), object_(object) { }
-
-  virtual void VisitPersistentHandle(Persistent<Value>* value,
-                                     uint16_t class_id) {
-    if (class_id != 42) return;
-    CHECK_EQ(42, value->WrapperClassId());
-    v8::Isolate* isolate = CcTest::isolate();
-    v8::HandleScope handle_scope(isolate);
-    v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
-    v8::Handle<v8::Value> object =
-        v8::Local<v8::Object>::New(isolate, *object_);
-    CHECK(handle->IsObject());
-    CHECK_EQ(Handle<Object>::Cast(handle), object);
-    ++counter_;
+UNINITIALIZED_TEST(IsolateEmbedderData) {
+  CcTest::DisableAutomaticDispose();
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  isolate->Enter();
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
+    CHECK(!isolate->GetData(slot));
+    CHECK(!i_isolate->GetData(slot));
   }
-
-  int counter_;
-  v8::Persistent<v8::Object>* object_;
-};
+  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
+    void* data = reinterpret_cast<void*>(0xacce55ed + slot);
+    isolate->SetData(slot, data);
+  }
+  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
+    void* data = reinterpret_cast<void*>(0xacce55ed + slot);
+    CHECK_EQ(data, isolate->GetData(slot));
+    CHECK_EQ(data, i_isolate->GetData(slot));
+  }
+  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
+    void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
+    isolate->SetData(slot, data);
+  }
+  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
+    void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
+    CHECK_EQ(data, isolate->GetData(slot));
+    CHECK_EQ(data, i_isolate->GetData(slot));
+  }
+  isolate->Exit();
+  isolate->Dispose();
+}
 
 
-TEST(PersistentHandleVisitor) {
+TEST(StringEmpty) {
   LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
+  i::Factory* factory = CcTest::i_isolate()->factory();
+  v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
-  CHECK_EQ(0, object.WrapperClassId());
-  object.SetWrapperClassId(42);
-  CHECK_EQ(42, object.WrapperClassId());
+  i::Handle<i::Object> empty_string = factory->empty_string();
+  CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
+}
 
-  Visitor42 visitor(&object);
-  v8::V8::VisitHandlesWithClassIds(&visitor);
-  CHECK_EQ(1, visitor.counter_);
 
-  object.Reset();
+static int instance_checked_getter_count = 0;
+static void InstanceCheckedGetter(
+    Local<String> name,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  CHECK(name->Equals(v8_str("foo")));
+  instance_checked_getter_count++;
+  info.GetReturnValue().Set(v8_num(11));
 }
 
 
-TEST(WrapperClassId) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
-  CHECK_EQ(0, object.WrapperClassId());
-  object.SetWrapperClassId(65535);
-  CHECK_EQ(65535, object.WrapperClassId());
-  object.Reset();
+static int instance_checked_setter_count = 0;
+static void InstanceCheckedSetter(Local<String> name,
+                      Local<Value> value,
+                      const v8::PropertyCallbackInfo<void>& info) {
+  CHECK(name->Equals(v8_str("foo")));
+  CHECK(value->Equals(v8_num(23)));
+  instance_checked_setter_count++;
 }
 
 
-TEST(PersistentHandleInNewSpaceVisitor) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
-  CHECK_EQ(0, object1.WrapperClassId());
-  object1.SetWrapperClassId(42);
-  CHECK_EQ(42, object1.WrapperClassId());
+static void CheckInstanceCheckedResult(int getters, int setters,
+                                       bool expects_callbacks,
+                                       TryCatch* try_catch) {
+  if (expects_callbacks) {
+    CHECK(!try_catch->HasCaught());
+    CHECK_EQ(getters, instance_checked_getter_count);
+    CHECK_EQ(setters, instance_checked_setter_count);
+  } else {
+    CHECK(try_catch->HasCaught());
+    CHECK_EQ(0, instance_checked_getter_count);
+    CHECK_EQ(0, instance_checked_setter_count);
+  }
+  try_catch->Reset();
+}
 
-  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
 
-  v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
-  CHECK_EQ(0, object2.WrapperClassId());
-  object2.SetWrapperClassId(42);
-  CHECK_EQ(42, object2.WrapperClassId());
+static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
+  instance_checked_getter_count = 0;
+  instance_checked_setter_count = 0;
+  TryCatch try_catch(CcTest::isolate());
 
-  Visitor42 visitor(&object2);
-  v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
-  CHECK_EQ(1, visitor.counter_);
+  // Test path through generic runtime code.
+  CompileRun("obj.foo");
+  CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
+  CompileRun("obj.foo = 23");
+  CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
 
-  object1.Reset();
-  object2.Reset();
+  // Test path through generated LoadIC and StoredIC.
+  CompileRun("function test_get(o) { o.foo; }"
+             "test_get(obj);");
+  CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
+  CompileRun("test_get(obj);");
+  CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
+  CompileRun("test_get(obj);");
+  CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
+  CompileRun("function test_set(o) { o.foo = 23; }"
+             "test_set(obj);");
+  CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
+  CompileRun("test_set(obj);");
+  CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
+  CompileRun("test_set(obj);");
+  CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
+
+  // Test path through optimized code.
+  CompileRun("%OptimizeFunctionOnNextCall(test_get);"
+             "test_get(obj);");
+  CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
+  CompileRun("%OptimizeFunctionOnNextCall(test_set);"
+             "test_set(obj);");
+  CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
+
+  // Cleanup so that closures start out fresh in next check.
+  CompileRun("%DeoptimizeFunction(test_get);"
+             "%ClearFunctionTypeFeedback(test_get);"
+             "%DeoptimizeFunction(test_set);"
+             "%ClearFunctionTypeFeedback(test_set);");
 }
 
 
-TEST(RegExp) {
+THREADED_TEST(InstanceCheckOnInstanceAccessor) {
+  v8::internal::FLAG_allow_natives_syntax = true;
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
 
-  v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
-  CHECK(re->IsRegExp());
-  CHECK(re->GetSource()->Equals(v8_str("foo")));
-  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
+  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
+  Local<ObjectTemplate> inst = templ->InstanceTemplate();
+  inst->SetAccessor(v8_str("foo"),
+                    InstanceCheckedGetter, InstanceCheckedSetter,
+                    Handle<Value>(),
+                    v8::DEFAULT,
+                    v8::None,
+                    v8::AccessorSignature::New(context->GetIsolate(), templ));
+  context->Global()->Set(v8_str("f"), templ->GetFunction());
 
-  re = v8::RegExp::New(v8_str("bar"),
-                       static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
-                                                      v8::RegExp::kGlobal));
-  CHECK(re->IsRegExp());
-  CHECK(re->GetSource()->Equals(v8_str("bar")));
-  CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
-           static_cast<int>(re->GetFlags()));
+  printf("Testing positive ...\n");
+  CompileRun("var obj = new f();");
+  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
+  CheckInstanceCheckedAccessors(true);
 
-  re = v8::RegExp::New(v8_str("baz"),
-                       static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
-                                                      v8::RegExp::kMultiline));
-  CHECK(re->IsRegExp());
-  CHECK(re->GetSource()->Equals(v8_str("baz")));
-  CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
-           static_cast<int>(re->GetFlags()));
+  printf("Testing negative ...\n");
+  CompileRun("var obj = {};"
+             "obj.__proto__ = new f();");
+  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
+  CheckInstanceCheckedAccessors(false);
+}
 
-  re = CompileRun("/quux/").As<v8::RegExp>();
-  CHECK(re->IsRegExp());
-  CHECK(re->GetSource()->Equals(v8_str("quux")));
-  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
 
-  re = CompileRun("/quux/gm").As<v8::RegExp>();
-  CHECK(re->IsRegExp());
-  CHECK(re->GetSource()->Equals(v8_str("quux")));
-  CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
-           static_cast<int>(re->GetFlags()));
+static void EmptyInterceptorGetter(
+    Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
 
-  // Override the RegExp constructor and check the API constructor
-  // still works.
-  CompileRun("RegExp = function() {}");
 
-  re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
-  CHECK(re->IsRegExp());
-  CHECK(re->GetSource()->Equals(v8_str("foobar")));
-  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
+static void EmptyInterceptorSetter(
+    Local<String> name, Local<Value> value,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {}
 
-  re = v8::RegExp::New(v8_str("foobarbaz"),
-                       static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
-                                                      v8::RegExp::kMultiline));
-  CHECK(re->IsRegExp());
-  CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
-  CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
-           static_cast<int>(re->GetFlags()));
 
-  context->Global()->Set(v8_str("re"), re);
-  ExpectTrue("re.test('FoobarbaZ')");
+THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
+  v8::internal::FLAG_allow_natives_syntax = true;
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+
+  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
+  Local<ObjectTemplate> inst = templ->InstanceTemplate();
+  templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
+                                                     EmptyInterceptorSetter);
+  inst->SetAccessor(v8_str("foo"),
+                    InstanceCheckedGetter, InstanceCheckedSetter,
+                    Handle<Value>(),
+                    v8::DEFAULT,
+                    v8::None,
+                    v8::AccessorSignature::New(context->GetIsolate(), templ));
+  context->Global()->Set(v8_str("f"), templ->GetFunction());
 
-  // RegExps are objects on which you can set properties.
-  re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
-  v8::Handle<v8::Value> value(CompileRun("re.property"));
-  CHECK_EQ(32, value->Int32Value());
+  printf("Testing positive ...\n");
+  CompileRun("var obj = new f();");
+  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
+  CheckInstanceCheckedAccessors(true);
 
-  v8::TryCatch try_catch;
-  re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
-  CHECK(re.IsEmpty());
-  CHECK(try_catch.HasCaught());
-  context->Global()->Set(v8_str("ex"), try_catch.Exception());
-  ExpectTrue("ex instanceof SyntaxError");
+  printf("Testing negative ...\n");
+  CompileRun("var obj = {};"
+             "obj.__proto__ = new f();");
+  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
+  CheckInstanceCheckedAccessors(false);
 }
 
 
-THREADED_TEST(Equals) {
-  LocalContext localContext;
-  v8::HandleScope handleScope(localContext->GetIsolate());
-
-  v8::Handle<v8::Object> globalProxy = localContext->Global();
-  v8::Handle<Value> global = globalProxy->GetPrototype();
+THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
+  v8::internal::FLAG_allow_natives_syntax = true;
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
-  CHECK(global->StrictEquals(global));
-  CHECK(!global->StrictEquals(globalProxy));
-  CHECK(!globalProxy->StrictEquals(global));
-  CHECK(globalProxy->StrictEquals(globalProxy));
+  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
+  Local<ObjectTemplate> proto = templ->PrototypeTemplate();
+  proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
+                     InstanceCheckedSetter, Handle<Value>(), v8::DEFAULT,
+                     v8::None,
+                     v8::AccessorSignature::New(context->GetIsolate(), templ));
+  context->Global()->Set(v8_str("f"), templ->GetFunction());
 
-  CHECK(global->Equals(global));
-  CHECK(!global->Equals(globalProxy));
-  CHECK(!globalProxy->Equals(global));
-  CHECK(globalProxy->Equals(globalProxy));
-}
+  printf("Testing positive ...\n");
+  CompileRun("var obj = new f();");
+  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
+  CheckInstanceCheckedAccessors(true);
 
+  printf("Testing negative ...\n");
+  CompileRun("var obj = {};"
+             "obj.__proto__ = new f();");
+  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
+  CheckInstanceCheckedAccessors(false);
 
-static void Getter(v8::Local<v8::String> property,
-                   const v8::PropertyCallbackInfo<v8::Value>& info ) {
-  info.GetReturnValue().Set(v8_str("42!"));
+  printf("Testing positive with modified prototype chain ...\n");
+  CompileRun("var obj = new f();"
+             "var pro = {};"
+             "pro.__proto__ = obj.__proto__;"
+             "obj.__proto__ = pro;");
+  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
+  CheckInstanceCheckedAccessors(true);
 }
 
 
-static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
-  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
-  result->Set(0, v8_str("universalAnswer"));
-  info.GetReturnValue().Set(result);
+TEST(TryFinallyMessage) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  {
+    // Test that the original error message is not lost if there is a
+    // recursive call into Javascript is done in the finally block, e.g. to
+    // initialize an IC. (crbug.com/129171)
+    TryCatch try_catch(context->GetIsolate());
+    const char* trigger_ic =
+        "try {                      \n"
+        "  throw new Error('test'); \n"
+        "} finally {                \n"
+        "  var x = 0;               \n"
+        "  x++;                     \n"  // Trigger an IC initialization here.
+        "}                          \n";
+    CompileRun(trigger_ic);
+    CHECK(try_catch.HasCaught());
+    Local<Message> message = try_catch.Message();
+    CHECK(!message.IsEmpty());
+    CHECK_EQ(2, message->GetLineNumber());
+  }
+
+  {
+    // Test that the original exception message is indeed overwritten if
+    // a new error is thrown in the finally block.
+    TryCatch try_catch(context->GetIsolate());
+    const char* throw_again =
+        "try {                       \n"
+        "  throw new Error('test');  \n"
+        "} finally {                 \n"
+        "  var x = 0;                \n"
+        "  x++;                      \n"
+        "  throw new Error('again'); \n"  // This is the new uncaught error.
+        "}                           \n";
+    CompileRun(throw_again);
+    CHECK(try_catch.HasCaught());
+    Local<Message> message = try_catch.Message();
+    CHECK(!message.IsEmpty());
+    CHECK_EQ(6, message->GetLineNumber());
+  }
 }
 
 
-TEST(NamedEnumeratorAndForIn) {
+static void Helper137002(bool do_store,
+                         bool polymorphic,
+                         bool remove_accessor,
+                         bool interceptor) {
   LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope handle_scope(isolate);
-  v8::Context::Scope context_scope(context.local());
+  Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
+  if (interceptor) {
+    templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
+                                                            FooSetInterceptor));
+  } else {
+    templ->SetAccessor(v8_str("foo"),
+                       GetterWhichReturns42,
+                       SetterWhichSetsYOnThisTo23);
+  }
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
 
-  v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
-  tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
-  context->Global()->Set(v8_str("o"), tmpl->NewInstance());
-  v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
-        "var result = []; for (var k in o) result.push(k); result"));
-  CHECK_EQ(1, result->Length());
-  CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
+  // Turn monomorphic on slow object with native accessor, then turn
+  // polymorphic, finally optimize to create negative lookup and fail.
+  CompileRun(do_store ?
+             "function f(x) { x.foo = void 0; }" :
+             "function f(x) { return x.foo; }");
+  CompileRun("obj.y = void 0;");
+  if (!interceptor) {
+    CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
+  }
+  CompileRun("obj.__proto__ = null;"
+             "f(obj); f(obj); f(obj);");
+  if (polymorphic) {
+    CompileRun("f({});");
+  }
+  CompileRun("obj.y = void 0;"
+             "%OptimizeFunctionOnNextCall(f);");
+  if (remove_accessor) {
+    CompileRun("delete obj.foo;");
+  }
+  CompileRun("var result = f(obj);");
+  if (do_store) {
+    CompileRun("result = obj.y;");
+  }
+  if (remove_accessor && !interceptor) {
+    CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
+  } else {
+    CHECK_EQ(do_store ? 23 : 42,
+             context->Global()->Get(v8_str("result"))->Int32Value());
+  }
 }
 
 
-TEST(DefinePropertyPostDetach) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  v8::Handle<v8::Object> proxy = context->Global();
-  v8::Handle<v8::Function> define_property =
-      CompileRun("(function() {"
-                 "  Object.defineProperty("
-                 "    this,"
-                 "    1,"
-                 "    { configurable: true, enumerable: true, value: 3 });"
-                 "})").As<Function>();
-  context->DetachGlobal();
-  define_property->Call(proxy, 0, NULL);
+THREADED_TEST(Regress137002a) {
+  i::FLAG_allow_natives_syntax = true;
+  i::FLAG_compilation_cache = false;
+  v8::HandleScope scope(CcTest::isolate());
+  for (int i = 0; i < 16; i++) {
+    Helper137002(i & 8, i & 4, i & 2, i & 1);
+  }
 }
 
 
-static void InstallContextId(v8::Handle<Context> context, int id) {
-  Context::Scope scope(context);
-  CompileRun("Object.prototype").As<Object>()->
-      Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
-}
+THREADED_TEST(Regress137002b) {
+  i::FLAG_allow_natives_syntax = true;
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->SetAccessor(v8_str("foo"),
+                     GetterWhichReturns42,
+                     SetterWhichSetsYOnThisTo23);
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
 
+  // Turn monomorphic on slow object with native accessor, then just
+  // delete the property and fail.
+  CompileRun("function load(x) { return x.foo; }"
+             "function store(x) { x.foo = void 0; }"
+             "function keyed_load(x, key) { return x[key]; }"
+             // Second version of function has a different source (add void 0)
+             // so that it does not share code with the first version.  This
+             // ensures that the ICs are monomorphic.
+             "function load2(x) { void 0; return x.foo; }"
+             "function store2(x) { void 0; x.foo = void 0; }"
+             "function keyed_load2(x, key) { void 0; return x[key]; }"
 
-static void CheckContextId(v8::Handle<Object> object, int expected) {
-  CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
-}
+             "obj.y = void 0;"
+             "obj.__proto__ = null;"
+             "var subobj = {};"
+             "subobj.y = void 0;"
+             "subobj.__proto__ = obj;"
+             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
 
+             // Make the ICs monomorphic.
+             "load(obj); load(obj);"
+             "load2(subobj); load2(subobj);"
+             "store(obj); store(obj);"
+             "store2(subobj); store2(subobj);"
+             "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
+             "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
 
-THREADED_TEST(CreationContext) {
-  v8::Isolate* isolate = CcTest::isolate();
-  HandleScope handle_scope(isolate);
-  Handle<Context> context1 = Context::New(isolate);
-  InstallContextId(context1, 1);
-  Handle<Context> context2 = Context::New(isolate);
-  InstallContextId(context2, 2);
-  Handle<Context> context3 = Context::New(isolate);
-  InstallContextId(context3, 3);
+             // Actually test the shiny new ICs and better not crash. This
+             // serves as a regression test for issue 142088 as well.
+             "load(obj);"
+             "load2(subobj);"
+             "store(obj);"
+             "store2(subobj);"
+             "keyed_load(obj, 'foo');"
+             "keyed_load2(subobj, 'foo');"
 
-  Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
+             // Delete the accessor.  It better not be called any more now.
+             "delete obj.foo;"
+             "obj.y = void 0;"
+             "subobj.y = void 0;"
 
-  Local<Object> object1;
-  Local<Function> func1;
-  {
-    Context::Scope scope(context1);
-    object1 = Object::New(isolate);
-    func1 = tmpl->GetFunction();
-  }
+             "var load_result = load(obj);"
+             "var load_result2 = load2(subobj);"
+             "var keyed_load_result = keyed_load(obj, 'foo');"
+             "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
+             "store(obj);"
+             "store2(subobj);"
+             "var y_from_obj = obj.y;"
+             "var y_from_subobj = subobj.y;");
+  CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
+}
 
-  Local<Object> object2;
-  Local<Function> func2;
-  {
-    Context::Scope scope(context2);
-    object2 = Object::New(isolate);
-    func2 = tmpl->GetFunction();
-  }
 
-  Local<Object> instance1;
-  Local<Object> instance2;
+THREADED_TEST(Regress142088) {
+  i::FLAG_allow_natives_syntax = true;
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->SetAccessor(v8_str("foo"),
+                     GetterWhichReturns42,
+                     SetterWhichSetsYOnThisTo23);
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
 
-  {
-    Context::Scope scope(context3);
-    instance1 = func1->NewInstance();
-    instance2 = func2->NewInstance();
-  }
+  CompileRun("function load(x) { return x.foo; }"
+             "var o = Object.create(obj);"
+             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
+             "load(o); load(o); load(o); load(o);");
+}
 
-  CHECK(object1->CreationContext() == context1);
-  CheckContextId(object1, 1);
-  CHECK(func1->CreationContext() == context1);
-  CheckContextId(func1, 1);
-  CHECK(instance1->CreationContext() == context1);
-  CheckContextId(instance1, 1);
-  CHECK(object2->CreationContext() == context2);
-  CheckContextId(object2, 2);
-  CHECK(func2->CreationContext() == context2);
-  CheckContextId(func2, 2);
-  CHECK(instance2->CreationContext() == context2);
-  CheckContextId(instance2, 2);
 
-  {
-    Context::Scope scope(context1);
-    CHECK(object1->CreationContext() == context1);
-    CheckContextId(object1, 1);
-    CHECK(func1->CreationContext() == context1);
-    CheckContextId(func1, 1);
-    CHECK(instance1->CreationContext() == context1);
-    CheckContextId(instance1, 1);
-    CHECK(object2->CreationContext() == context2);
-    CheckContextId(object2, 2);
-    CHECK(func2->CreationContext() == context2);
-    CheckContextId(func2, 2);
-    CHECK(instance2->CreationContext() == context2);
-    CheckContextId(instance2, 2);
-  }
+THREADED_TEST(Regress137496) {
+  i::FLAG_expose_gc = true;
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
 
-  {
-    Context::Scope scope(context2);
-    CHECK(object1->CreationContext() == context1);
-    CheckContextId(object1, 1);
-    CHECK(func1->CreationContext() == context1);
-    CheckContextId(func1, 1);
-    CHECK(instance1->CreationContext() == context1);
-    CheckContextId(instance1, 1);
-    CHECK(object2->CreationContext() == context2);
-    CheckContextId(object2, 2);
-    CHECK(func2->CreationContext() == context2);
-    CheckContextId(func2, 2);
-    CHECK(instance2->CreationContext() == context2);
-    CheckContextId(instance2, 2);
-  }
+  // Compile a try-finally clause where the finally block causes a GC
+  // while there still is a message pending for external reporting.
+  TryCatch try_catch(context->GetIsolate());
+  try_catch.SetVerbose(true);
+  CompileRun("try { throw new Error(); } finally { gc(); }");
+  CHECK(try_catch.HasCaught());
 }
 
 
-THREADED_TEST(CreationContextOfJsFunction) {
-  HandleScope handle_scope(CcTest::isolate());
-  Handle<Context> context = Context::New(CcTest::isolate());
-  InstallContextId(context, 1);
-
-  Local<Object> function;
-  {
-    Context::Scope scope(context);
-    function = CompileRun("function foo() {}; foo").As<Object>();
-  }
-
-  CHECK(function->CreationContext() == context);
-  CheckContextId(function, 1);
+THREADED_TEST(Regress157124) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  Local<Object> obj = templ->NewInstance();
+  obj->GetIdentityHash();
+  obj->DeleteHiddenValue(v8_str("Bug"));
 }
 
 
-void HasOwnPropertyIndexedPropertyGetter(
-    uint32_t index,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
+THREADED_TEST(Regress2535) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  Local<Value> set_value = CompileRun("new Set();");
+  Local<Object> set_object(Local<Object>::Cast(set_value));
+  CHECK_EQ(0, set_object->InternalFieldCount());
+  Local<Value> map_value = CompileRun("new Map();");
+  Local<Object> map_object(Local<Object>::Cast(map_value));
+  CHECK_EQ(0, map_object->InternalFieldCount());
 }
 
 
-void HasOwnPropertyNamedPropertyGetter(
-    Local<String> property,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
+THREADED_TEST(Regress2746) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<Object> obj = Object::New(isolate);
+  Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
+  obj->SetHiddenValue(key, v8::Undefined(isolate));
+  Local<Value> value = obj->GetHiddenValue(key);
+  CHECK(!value.IsEmpty());
+  CHECK(value->IsUndefined());
 }
 
 
-void HasOwnPropertyIndexedPropertyQuery(
-    uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
-  if (index == 42) info.GetReturnValue().Set(1);
+THREADED_TEST(Regress260106) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
+                                                        DummyCallHandler);
+  CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
+  Local<Function> function = templ->GetFunction();
+  CHECK(!function.IsEmpty());
+  CHECK(function->IsFunction());
 }
 
 
-void HasOwnPropertyNamedPropertyQuery(
-    Local<String> property,
-    const v8::PropertyCallbackInfo<v8::Integer>& info) {
-  if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
+THREADED_TEST(JSONParseObject) {
+  LocalContext context;
+  HandleScope scope(context->GetIsolate());
+  Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
+  Handle<Object> global = context->Global();
+  global->Set(v8_str("obj"), obj);
+  ExpectString("JSON.stringify(obj)", "{\"x\":42}");
 }
 
 
-void HasOwnPropertyNamedPropertyQuery2(
-    Local<String> property,
-    const v8::PropertyCallbackInfo<v8::Integer>& info) {
-  if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
+THREADED_TEST(JSONParseNumber) {
+  LocalContext context;
+  HandleScope scope(context->GetIsolate());
+  Local<Value> obj = v8::JSON::Parse(v8_str("42"));
+  Handle<Object> global = context->Global();
+  global->Set(v8_str("obj"), obj);
+  ExpectString("JSON.stringify(obj)", "42");
 }
 
 
-void HasOwnPropertyAccessorGetter(
-    Local<String> property,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(v8_str("yes"));
-}
+#if V8_OS_POSIX && !V8_OS_NACL
+class ThreadInterruptTest {
+ public:
+  ThreadInterruptTest() : sem_(0), sem_value_(0) { }
+  ~ThreadInterruptTest() {}
 
+  void RunTest() {
+    InterruptThread i_thread(this);
+    i_thread.Start();
 
-TEST(HasOwnProperty) {
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-  { // Check normal properties and defined getters.
-    Handle<Value> value = CompileRun(
-        "function Foo() {"
-        "    this.foo = 11;"
-        "    this.__defineGetter__('baz', function() { return 1; });"
-        "};"
-        "function Bar() { "
-        "    this.bar = 13;"
-        "    this.__defineGetter__('bla', function() { return 2; });"
-        "};"
-        "Bar.prototype = new Foo();"
-        "new Bar();");
-    CHECK(value->IsObject());
-    Handle<Object> object = value->ToObject();
-    CHECK(object->Has(v8_str("foo")));
-    CHECK(!object->HasOwnProperty(v8_str("foo")));
-    CHECK(object->HasOwnProperty(v8_str("bar")));
-    CHECK(object->Has(v8_str("baz")));
-    CHECK(!object->HasOwnProperty(v8_str("baz")));
-    CHECK(object->HasOwnProperty(v8_str("bla")));
-  }
-  { // Check named getter interceptors.
-    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-    templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
-    Handle<Object> instance = templ->NewInstance();
-    CHECK(!instance->HasOwnProperty(v8_str("42")));
-    CHECK(instance->HasOwnProperty(v8_str("foo")));
-    CHECK(!instance->HasOwnProperty(v8_str("bar")));
-  }
-  { // Check indexed getter interceptors.
-    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-    templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
-    Handle<Object> instance = templ->NewInstance();
-    CHECK(instance->HasOwnProperty(v8_str("42")));
-    CHECK(!instance->HasOwnProperty(v8_str("43")));
-    CHECK(!instance->HasOwnProperty(v8_str("foo")));
-  }
-  { // Check named query interceptors.
-    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-    templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
-    Handle<Object> instance = templ->NewInstance();
-    CHECK(instance->HasOwnProperty(v8_str("foo")));
-    CHECK(!instance->HasOwnProperty(v8_str("bar")));
-  }
-  { // Check indexed query interceptors.
-    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-    templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
-    Handle<Object> instance = templ->NewInstance();
-    CHECK(instance->HasOwnProperty(v8_str("42")));
-    CHECK(!instance->HasOwnProperty(v8_str("41")));
-  }
-  { // Check callbacks.
-    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-    templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
-    Handle<Object> instance = templ->NewInstance();
-    CHECK(instance->HasOwnProperty(v8_str("foo")));
-    CHECK(!instance->HasOwnProperty(v8_str("bar")));
-  }
-  { // Check that query wins on disagreement.
-    Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-    templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
-                                   0,
-                                   HasOwnPropertyNamedPropertyQuery2);
-    Handle<Object> instance = templ->NewInstance();
-    CHECK(!instance->HasOwnProperty(v8_str("foo")));
-    CHECK(instance->HasOwnProperty(v8_str("bar")));
+    sem_.Wait();
+    CHECK_EQ(kExpectedValue, sem_value_);
   }
-}
 
+ private:
+  static const int kExpectedValue = 1;
 
-TEST(IndexedInterceptorWithStringProto) {
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetIndexedPropertyHandler(NULL,
-                                   NULL,
-                                   HasOwnPropertyIndexedPropertyQuery);
-  LocalContext context;
-  context->Global()->Set(v8_str("obj"), templ->NewInstance());
-  CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
-  // These should be intercepted.
-  CHECK(CompileRun("42 in obj")->BooleanValue());
-  CHECK(CompileRun("'42' in obj")->BooleanValue());
-  // These should fall through to the String prototype.
-  CHECK(CompileRun("0 in obj")->BooleanValue());
-  CHECK(CompileRun("'0' in obj")->BooleanValue());
-  // And these should both fail.
-  CHECK(!CompileRun("32 in obj")->BooleanValue());
-  CHECK(!CompileRun("'32' in obj")->BooleanValue());
-}
+  class InterruptThread : public v8::base::Thread {
+   public:
+    explicit InterruptThread(ThreadInterruptTest* test)
+        : Thread(Options("InterruptThread")), test_(test) {}
+
+    virtual void Run() {
+      struct sigaction action;
+
+      // Ensure that we'll enter waiting condition
+      v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
+
+      // Setup signal handler
+      memset(&action, 0, sizeof(action));
+      action.sa_handler = SignalHandler;
+      sigaction(SIGCHLD, &action, NULL);
 
+      // Send signal
+      kill(getpid(), SIGCHLD);
 
-void CheckCodeGenerationAllowed() {
-  Handle<Value> result = CompileRun("eval('42')");
-  CHECK_EQ(42, result->Int32Value());
-  result = CompileRun("(function(e) { return e('42'); })(eval)");
-  CHECK_EQ(42, result->Int32Value());
-  result = CompileRun("var f = new Function('return 42'); f()");
-  CHECK_EQ(42, result->Int32Value());
-}
+      // Ensure that if wait has returned because of error
+      v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
 
+      // Set value and signal semaphore
+      test_->sem_value_ = 1;
+      test_->sem_.Signal();
+    }
 
-void CheckCodeGenerationDisallowed() {
-  TryCatch try_catch;
+    static void SignalHandler(int signal) {
+    }
 
-  Handle<Value> result = CompileRun("eval('42')");
-  CHECK(result.IsEmpty());
-  CHECK(try_catch.HasCaught());
-  try_catch.Reset();
+   private:
+     ThreadInterruptTest* test_;
+  };
 
-  result = CompileRun("(function(e) { return e('42'); })(eval)");
-  CHECK(result.IsEmpty());
-  CHECK(try_catch.HasCaught());
-  try_catch.Reset();
+  v8::base::Semaphore sem_;
+  volatile int sem_value_;
+};
 
-  result = CompileRun("var f = new Function('return 42'); f()");
-  CHECK(result.IsEmpty());
-  CHECK(try_catch.HasCaught());
+
+THREADED_TEST(SemaphoreInterruption) {
+  ThreadInterruptTest().RunTest();
 }
 
 
-bool CodeGenerationAllowed(Local<Context> context) {
-  ApiTestFuzzer::Fuzz();
-  return true;
-}
+#endif  // V8_OS_POSIX
 
 
-bool CodeGenerationDisallowed(Local<Context> context) {
-  ApiTestFuzzer::Fuzz();
-  return false;
+void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  CHECK(false);
 }
 
 
-THREADED_TEST(AllowCodeGenFromStrings) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+TEST(JSONStringifyAccessCheck) {
+  v8::V8::Initialize();
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
 
-  // eval and the Function constructor allowed by default.
-  CHECK(context->IsCodeGenerationFromStringsAllowed());
-  CheckCodeGenerationAllowed();
+  // Create an ObjectTemplate for global objects and install access
+  // check callbacks that will block access.
+  v8::Handle<v8::ObjectTemplate> global_template =
+      v8::ObjectTemplate::New(isolate);
+  global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
 
-  // Disallow eval and the Function constructor.
-  context->AllowCodeGenerationFromStrings(false);
-  CHECK(!context->IsCodeGenerationFromStringsAllowed());
-  CheckCodeGenerationDisallowed();
+  // Create a context and set an x property on it's global object.
+  LocalContext context0(NULL, global_template);
+  v8::Handle<v8::Object> global0 = context0->Global();
+  global0->Set(v8_str("x"), v8_num(42));
+  ExpectString("JSON.stringify(this)", "{\"x\":42}");
 
-  // Allow again.
-  context->AllowCodeGenerationFromStrings(true);
-  CheckCodeGenerationAllowed();
+  for (int i = 0; i < 2; i++) {
+    if (i == 1) {
+      // Install a toJSON function on the second run.
+      v8::Handle<v8::FunctionTemplate> toJSON =
+          v8::FunctionTemplate::New(isolate, UnreachableCallback);
 
-  // Disallow but setting a global callback that will allow the calls.
-  context->AllowCodeGenerationFromStrings(false);
-  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
-  CHECK(!context->IsCodeGenerationFromStringsAllowed());
-  CheckCodeGenerationAllowed();
+      global0->Set(v8_str("toJSON"), toJSON->GetFunction());
+    }
+    // Create a context with a different security token so that the
+    // failed access check callback will be called on each access.
+    LocalContext context1(NULL, global_template);
+    context1->Global()->Set(v8_str("other"), global0);
 
-  // Set a callback that disallows the code generation.
-  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
-  CHECK(!context->IsCodeGenerationFromStringsAllowed());
-  CheckCodeGenerationDisallowed();
+    CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
+    CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
+    CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
+  }
 }
 
 
-TEST(SetErrorMessageForCodeGenFromStrings) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  TryCatch try_catch;
+bool access_check_fail_thrown = false;
+bool catch_callback_called = false;
 
-  Handle<String> message = v8_str("Message") ;
-  Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
-  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
-  context->AllowCodeGenerationFromStrings(false);
-  context->SetErrorMessageForCodeGenerationFromStrings(message);
-  Handle<Value> result = CompileRun("eval('42')");
-  CHECK(result.IsEmpty());
-  CHECK(try_catch.HasCaught());
-  Handle<String> actual_message = try_catch.Message()->Get();
-  CHECK(expected_message->Equals(actual_message));
+
+// Failed access check callback that performs a GC on each invocation.
+void FailedAccessCheckThrows(Local<v8::Object> target,
+                             v8::AccessType type,
+                             Local<v8::Value> data) {
+  access_check_fail_thrown = true;
+  i::PrintF("Access check failed. Error thrown.\n");
+  CcTest::isolate()->ThrowException(
+      v8::Exception::Error(v8_str("cross context")));
 }
 
 
-static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
+void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  for (int i = 0; i < args.Length(); i++) {
+    i::PrintF("%s\n", *String::Utf8Value(args[i]));
+  }
+  catch_callback_called = true;
 }
 
 
-THREADED_TEST(CallAPIFunctionOnNonObject) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  Handle<FunctionTemplate> templ =
-      v8::FunctionTemplate::New(isolate, NonObjectThis);
-  Handle<Function> function = templ->GetFunction();
-  context->Global()->Set(v8_str("f"), function);
-  TryCatch try_catch;
-  CompileRun("f.call(2)");
+void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  args[0]->ToObject(args.GetIsolate())->HasOwnProperty(
+      args[1]->ToString(args.GetIsolate()));
 }
 
 
-// Regression test for issue 1470.
-THREADED_TEST(ReadOnlyIndexedProperties) {
+void CheckCorrectThrow(const char* script) {
+  // Test that the script, when wrapped into a try-catch, triggers the catch
+  // clause due to failed access check throwing an exception.
+  // The subsequent try-catch should run without any exception.
+  access_check_fail_thrown = false;
+  catch_callback_called = false;
+  i::ScopedVector<char> source(1024);
+  i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
+  CompileRun(source.start());
+  CHECK(access_check_fail_thrown);
+  CHECK(catch_callback_called);
+
+  access_check_fail_thrown = false;
+  catch_callback_called = false;
+  CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
+  CHECK(!access_check_fail_thrown);
+  CHECK(!catch_callback_called);
+}
+
+
+TEST(AccessCheckThrows) {
+  i::FLAG_allow_natives_syntax = true;
+  i::FLAG_turbo_try_catch = true;
+  v8::V8::Initialize();
+  v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
 
-  LocalContext context;
-  Local<v8::Object> obj = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), obj);
-  obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
-  obj->Set(v8_str("1"), v8_str("foobar"));
-  CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
-  obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
-  obj->Set(v8_num(2), v8_str("foobar"));
-  CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
+  // Create an ObjectTemplate for global objects and install access
+  // check callbacks that will block access.
+  v8::Handle<v8::ObjectTemplate> global_template =
+      v8::ObjectTemplate::New(isolate);
+  global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
 
-  // Test non-smi case.
-  obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
-  obj->Set(v8_str("2000000000"), v8_str("foobar"));
-  CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
-}
+  // Create a context and set an x property on it's global object.
+  LocalContext context0(NULL, global_template);
+  v8::Handle<v8::Object> global0 = context0->Global();
 
+  // Create a context with a different security token so that the
+  // failed access check callback will be called on each access.
+  LocalContext context1(NULL, global_template);
+  context1->Global()->Set(v8_str("other"), global0);
 
-THREADED_TEST(Regress1516) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+  v8::Handle<v8::FunctionTemplate> catcher_fun =
+      v8::FunctionTemplate::New(isolate, CatcherCallback);
+  context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
 
-  { v8::HandleScope temp_scope(context->GetIsolate());
-    CompileRun("({'a': 0})");
-  }
+  v8::Handle<v8::FunctionTemplate> has_own_property_fun =
+      v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
+  context1->Global()->Set(v8_str("has_own_property"),
+                          has_own_property_fun->GetFunction());
 
-  int elements;
-  { i::MapCache* map_cache =
-        i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
-    elements = map_cache->NumberOfElements();
-    CHECK_LE(1, elements);
+  {
+    v8::TryCatch try_catch(isolate);
+    access_check_fail_thrown = false;
+    CompileRun("other.x;");
+    CHECK(access_check_fail_thrown);
+    CHECK(try_catch.HasCaught());
   }
 
-  CcTest::heap()->CollectAllGarbage(
-      i::Heap::kAbortIncrementalMarkingMask);
-  { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
-    if (raw_map_cache != CcTest::heap()->undefined_value()) {
-      i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
-      CHECK_GT(elements, map_cache->NumberOfElements());
-    }
-  }
+  CheckCorrectThrow("other.x");
+  CheckCorrectThrow("other[1]");
+  CheckCorrectThrow("JSON.stringify(other)");
+  CheckCorrectThrow("has_own_property(other, 'x')");
+  CheckCorrectThrow("%GetProperty(other, 'x')");
+  CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
+  CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
+  CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
+  CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
+  CheckCorrectThrow("%HasOwnProperty(other, 'x')");
+  CheckCorrectThrow("%HasProperty(other, 'x')");
+  CheckCorrectThrow("%HasElement(other, 1)");
+  CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
+  CheckCorrectThrow("%GetPropertyNames(other)");
+  // PROPERTY_ATTRIBUTES_NONE = 0
+  CheckCorrectThrow("%GetOwnPropertyNames(other, 0)");
+  CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
+                        "other, 'x', null, null, 1)");
+
+  // Reset the failed access check callback so it does not influence
+  // the other tests.
+  v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
 }
 
 
-static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
-                                                Local<Value> name,
-                                                v8::AccessType type,
-                                                Local<Value> data) {
-  // Only block read access to __proto__.
-  if (type == v8::ACCESS_GET &&
-      name->IsString() &&
-      name->ToString()->Length() == 9 &&
-      name->ToString()->Utf8Length() == 9) {
-    char buffer[10];
-    CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
-    return strncmp(buffer, "__proto__", 9) != 0;
+class RequestInterruptTestBase {
+ public:
+  RequestInterruptTestBase()
+      : env_(),
+        isolate_(env_->GetIsolate()),
+        sem_(0),
+        warmup_(20000),
+        should_continue_(true) {
   }
 
-  return true;
-}
+  virtual ~RequestInterruptTestBase() { }
 
+  virtual void StartInterruptThread() = 0;
 
-THREADED_TEST(Regress93759) {
-  v8::Isolate* isolate = CcTest::isolate();
-  HandleScope scope(isolate);
+  virtual void TestBody() = 0;
 
-  // Template for object with security check.
-  Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
-  // We don't do indexing, so any callback can be used for that.
-  no_proto_template->SetAccessCheckCallbacks(
-      BlockProtoNamedSecurityTestCallback,
-      IndexedSecurityTestCallback);
+  void RunTest() {
+    StartInterruptThread();
 
-  // Templates for objects with hidden prototypes and possibly security check.
-  Local<FunctionTemplate> hidden_proto_template =
-      v8::FunctionTemplate::New(isolate);
-  hidden_proto_template->SetHiddenPrototype(true);
+    v8::HandleScope handle_scope(isolate_);
+
+    TestBody();
+
+    // Verify we arrived here because interruptor was called
+    // not due to a bug causing us to exit the loop too early.
+    CHECK(!should_continue());
+  }
+
+  void WakeUpInterruptor() {
+    sem_.Signal();
+  }
+
+  bool should_continue() const { return should_continue_; }
+
+  bool ShouldContinue() {
+    if (warmup_ > 0) {
+      if (--warmup_ == 0) {
+        WakeUpInterruptor();
+      }
+    }
 
-  Local<FunctionTemplate> protected_hidden_proto_template =
-      v8::FunctionTemplate::New(isolate);
-  protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
-      BlockProtoNamedSecurityTestCallback,
-      IndexedSecurityTestCallback);
-  protected_hidden_proto_template->SetHiddenPrototype(true);
+    return should_continue_;
+  }
 
-  // Context for "foreign" objects used in test.
-  Local<Context> context = v8::Context::New(isolate);
-  context->Enter();
+  static void ShouldContinueCallback(
+      const v8::FunctionCallbackInfo<Value>& info) {
+    RequestInterruptTestBase* test =
+        reinterpret_cast<RequestInterruptTestBase*>(
+            info.Data().As<v8::External>()->Value());
+    info.GetReturnValue().Set(test->ShouldContinue());
+  }
 
-  // Plain object, no security check.
-  Local<Object> simple_object = Object::New(isolate);
+  LocalContext env_;
+  v8::Isolate* isolate_;
+  v8::base::Semaphore sem_;
+  int warmup_;
+  bool should_continue_;
+};
 
-  // Object with explicit security check.
-  Local<Object> protected_object =
-      no_proto_template->NewInstance();
 
-  // JSGlobalProxy object, always have security check.
-  Local<Object> proxy_object =
-      context->Global();
+class RequestInterruptTestBaseWithSimpleInterrupt
+    : public RequestInterruptTestBase {
+ public:
+  RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
 
-  // Global object, the  prototype of proxy_object. No security checks.
-  Local<Object> global_object =
-      proxy_object->GetPrototype()->ToObject();
+  virtual void StartInterruptThread() {
+    i_thread.Start();
+  }
 
-  // Hidden prototype without security check.
-  Local<Object> hidden_prototype =
-      hidden_proto_template->GetFunction()->NewInstance();
-  Local<Object> object_with_hidden =
-    Object::New(isolate);
-  object_with_hidden->SetPrototype(hidden_prototype);
+ private:
+  class InterruptThread : public v8::base::Thread {
+   public:
+    explicit InterruptThread(RequestInterruptTestBase* test)
+        : Thread(Options("RequestInterruptTest")), test_(test) {}
 
-  // Hidden prototype with security check on the hidden prototype.
-  Local<Object> protected_hidden_prototype =
-      protected_hidden_proto_template->GetFunction()->NewInstance();
-  Local<Object> object_with_protected_hidden =
-    Object::New(isolate);
-  object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
+    virtual void Run() {
+      test_->sem_.Wait();
+      test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
+    }
 
-  context->Exit();
+    static void OnInterrupt(v8::Isolate* isolate, void* data) {
+      reinterpret_cast<RequestInterruptTestBase*>(data)->
+          should_continue_ = false;
+    }
 
-  // Template for object for second context. Values to test are put on it as
-  // properties.
-  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
-  global_template->Set(v8_str("simple"), simple_object);
-  global_template->Set(v8_str("protected"), protected_object);
-  global_template->Set(v8_str("global"), global_object);
-  global_template->Set(v8_str("proxy"), proxy_object);
-  global_template->Set(v8_str("hidden"), object_with_hidden);
-  global_template->Set(v8_str("phidden"), object_with_protected_hidden);
+   private:
+     RequestInterruptTestBase* test_;
+  };
 
-  LocalContext context2(NULL, global_template);
+  InterruptThread i_thread;
+};
 
-  Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
-  CHECK(result1->Equals(simple_object->GetPrototype()));
 
-  Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
-  CHECK(result2->Equals(Undefined(isolate)));
+class RequestInterruptTestWithFunctionCall
+    : public RequestInterruptTestBaseWithSimpleInterrupt {
+ public:
+  virtual void TestBody() {
+    Local<Function> func = Function::New(
+        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
+    env_->Global()->Set(v8_str("ShouldContinue"), func);
 
-  Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
-  CHECK(result3->Equals(global_object->GetPrototype()));
+    CompileRun("while (ShouldContinue()) { }");
+  }
+};
 
-  Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
-  CHECK(result4->Equals(Undefined(isolate)));
 
-  Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
-  CHECK(result5->Equals(
-      object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
+class RequestInterruptTestWithMethodCall
+    : public RequestInterruptTestBaseWithSimpleInterrupt {
+ public:
+  virtual void TestBody() {
+    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
+    v8::Local<v8::Template> proto = t->PrototypeTemplate();
+    proto->Set(v8_str("shouldContinue"), Function::New(
+        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
+    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
 
-  Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
-  CHECK(result6->Equals(Undefined(isolate)));
-}
+    CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
+  }
+};
 
 
-THREADED_TEST(Regress125988) {
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
-  AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
-  CompileRun("var a = new Object();"
-             "var b = new Intercept();"
-             "var c = new Object();"
-             "c.__proto__ = b;"
-             "b.__proto__ = a;"
-             "a.x = 23;"
-             "for (var i = 0; i < 3; i++) c.x;");
-  ExpectBoolean("c.hasOwnProperty('x')", false);
-  ExpectInt32("c.x", 23);
-  CompileRun("a.y = 42;"
-             "for (var i = 0; i < 3; i++) c.x;");
-  ExpectBoolean("c.hasOwnProperty('x')", false);
-  ExpectInt32("c.x", 23);
-  ExpectBoolean("c.hasOwnProperty('y')", false);
-  ExpectInt32("c.y", 42);
-}
+class RequestInterruptTestWithAccessor
+    : public RequestInterruptTestBaseWithSimpleInterrupt {
+ public:
+  virtual void TestBody() {
+    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
+    v8::Local<v8::Template> proto = t->PrototypeTemplate();
+    proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
+        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
+    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
 
+    CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
+  }
+};
 
-static void TestReceiver(Local<Value> expected_result,
-                         Local<Value> expected_receiver,
-                         const char* code) {
-  Local<Value> result = CompileRun(code);
-  CHECK(result->IsObject());
-  CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
-  CHECK(expected_result->Equals(result->ToObject()->Get(0)));
-}
 
+class RequestInterruptTestWithNativeAccessor
+    : public RequestInterruptTestBaseWithSimpleInterrupt {
+ public:
+  virtual void TestBody() {
+    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
+    t->InstanceTemplate()->SetNativeDataProperty(
+        v8_str("shouldContinue"),
+        &ShouldContinueNativeGetter,
+        NULL,
+        v8::External::New(isolate_, this));
+    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
 
-THREADED_TEST(ForeignFunctionReceiver) {
-  v8::Isolate* isolate = CcTest::isolate();
-  HandleScope scope(isolate);
+    CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
+  }
 
-  // Create two contexts with different "id" properties ('i' and 'o').
-  // Call a function both from its own context and from a the foreign
-  // context, and see what "this" is bound to (returning both "this"
-  // and "this.id" for comparison).
+ private:
+  static void ShouldContinueNativeGetter(
+      Local<String> property,
+      const v8::PropertyCallbackInfo<v8::Value>& info) {
+    RequestInterruptTestBase* test =
+        reinterpret_cast<RequestInterruptTestBase*>(
+            info.Data().As<v8::External>()->Value());
+    info.GetReturnValue().Set(test->ShouldContinue());
+  }
+};
 
-  Local<Context> foreign_context = v8::Context::New(isolate);
-  foreign_context->Enter();
-  Local<Value> foreign_function =
-    CompileRun("function func() { return { 0: this.id, "
-               "                           1: this, "
-               "                           toString: function() { "
-               "                               return this[0];"
-               "                           }"
-               "                         };"
-               "}"
-               "var id = 'i';"
-               "func;");
-  CHECK(foreign_function->IsFunction());
-  foreign_context->Exit();
 
-  LocalContext context;
+class RequestInterruptTestWithMethodCallAndInterceptor
+    : public RequestInterruptTestBaseWithSimpleInterrupt {
+ public:
+  virtual void TestBody() {
+    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
+    v8::Local<v8::Template> proto = t->PrototypeTemplate();
+    proto->Set(v8_str("shouldContinue"), Function::New(
+        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
+    v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
+    instance_template->SetHandler(
+        v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
 
-  Local<String> password = v8_str("Password");
-  // Don't get hit by security checks when accessing foreign_context's
-  // global receiver (aka. global proxy).
-  context->SetSecurityToken(password);
-  foreign_context->SetSecurityToken(password);
+    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
 
-  Local<String> i = v8_str("i");
-  Local<String> o = v8_str("o");
-  Local<String> id = v8_str("id");
+    CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
+  }
 
-  CompileRun("function ownfunc() { return { 0: this.id, "
-             "                              1: this, "
-             "                              toString: function() { "
-             "                                  return this[0];"
-             "                              }"
-             "                             };"
-             "}"
-             "var id = 'o';"
-             "ownfunc");
-  context->Global()->Set(v8_str("func"), foreign_function);
+ private:
+  static void EmptyInterceptor(
+      Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
+};
 
-  // Sanity check the contexts.
-  CHECK(i->Equals(foreign_context->Global()->Get(id)));
-  CHECK(o->Equals(context->Global()->Get(id)));
 
-  // Checking local function's receiver.
-  // Calling function using its call/apply methods.
-  TestReceiver(o, context->Global(), "ownfunc.call()");
-  TestReceiver(o, context->Global(), "ownfunc.apply()");
-  // Making calls through built-in functions.
-  TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
-  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
-  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
-  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
-  // Calling with environment record as base.
-  TestReceiver(o, context->Global(), "ownfunc()");
-  // Calling with no base.
-  TestReceiver(o, context->Global(), "(1,ownfunc)()");
+class RequestInterruptTestWithMathAbs
+    : public RequestInterruptTestBaseWithSimpleInterrupt {
+ public:
+  virtual void TestBody() {
+    env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
+        isolate_,
+        WakeUpInterruptorCallback,
+        v8::External::New(isolate_, this)));
 
-  // Checking foreign function return value.
-  // Calling function using its call/apply methods.
-  TestReceiver(i, foreign_context->Global(), "func.call()");
-  TestReceiver(i, foreign_context->Global(), "func.apply()");
-  // Calling function using another context's call/apply methods.
-  TestReceiver(i, foreign_context->Global(),
-               "Function.prototype.call.call(func)");
-  TestReceiver(i, foreign_context->Global(),
-               "Function.prototype.call.apply(func)");
-  TestReceiver(i, foreign_context->Global(),
-               "Function.prototype.apply.call(func)");
-  TestReceiver(i, foreign_context->Global(),
-               "Function.prototype.apply.apply(func)");
-  // Making calls through built-in functions.
-  TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
-  // ToString(func()) is func()[0], i.e., the returned this.id.
-  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
-  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
-  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
+    env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
+        isolate_,
+        ShouldContinueCallback,
+        v8::External::New(isolate_, this)));
 
-  // Calling with environment record as base.
-  TestReceiver(i, foreign_context->Global(), "func()");
-  // Calling with no base.
-  TestReceiver(i, foreign_context->Global(), "(1,func)()");
-}
+    i::FLAG_allow_natives_syntax = true;
+    CompileRun("function loopish(o) {"
+               "  var pre = 10;"
+               "  while (o.abs(1) > 0) {"
+               "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
+               "    if (pre > 0) {"
+               "      if (--pre === 0) WakeUpInterruptor(o === Math);"
+               "    }"
+               "  }"
+               "}"
+               "var i = 50;"
+               "var obj = {abs: function () { return i-- }, x: null};"
+               "delete obj.x;"
+               "loopish(obj);"
+               "%OptimizeFunctionOnNextCall(loopish);"
+               "loopish(Math);");
 
+    i::FLAG_allow_natives_syntax = false;
+  }
 
-uint8_t callback_fired = 0;
+ private:
+  static void WakeUpInterruptorCallback(
+      const v8::FunctionCallbackInfo<Value>& info) {
+    if (!info[0]->BooleanValue()) return;
 
+    RequestInterruptTestBase* test =
+        reinterpret_cast<RequestInterruptTestBase*>(
+            info.Data().As<v8::External>()->Value());
+    test->WakeUpInterruptor();
+  }
 
-void CallCompletedCallback1() {
-  i::OS::Print("Firing callback 1.\n");
-  callback_fired ^= 1;  // Toggle first bit.
-}
+  static void ShouldContinueCallback(
+      const v8::FunctionCallbackInfo<Value>& info) {
+    RequestInterruptTestBase* test =
+        reinterpret_cast<RequestInterruptTestBase*>(
+            info.Data().As<v8::External>()->Value());
+    info.GetReturnValue().Set(test->should_continue());
+  }
+};
 
 
-void CallCompletedCallback2() {
-  i::OS::Print("Firing callback 2.\n");
-  callback_fired ^= 2;  // Toggle second bit.
+TEST(RequestInterruptTestWithFunctionCall) {
+  RequestInterruptTestWithFunctionCall().RunTest();
 }
 
 
-void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  int32_t level = args[0]->Int32Value();
-  if (level < 3) {
-    level++;
-    i::OS::Print("Entering recursion level %d.\n", level);
-    char script[64];
-    i::Vector<char> script_vector(script, sizeof(script));
-    i::OS::SNPrintF(script_vector, "recursion(%d)", level);
-    CompileRun(script_vector.start());
-    i::OS::Print("Leaving recursion level %d.\n", level);
-    CHECK_EQ(0, callback_fired);
-  } else {
-    i::OS::Print("Recursion ends.\n");
-    CHECK_EQ(0, callback_fired);
-  }
+TEST(RequestInterruptTestWithMethodCall) {
+  RequestInterruptTestWithMethodCall().RunTest();
 }
 
 
-TEST(CallCompletedCallback) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::Handle<v8::FunctionTemplate> recursive_runtime =
-      v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
-  env->Global()->Set(v8_str("recursion"),
-                     recursive_runtime->GetFunction());
-  // Adding the same callback a second time has no effect.
-  v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
-  v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
-  v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
-  i::OS::Print("--- Script (1) ---\n");
-  Local<Script> script = v8::Script::Compile(
-      v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
-  script->Run();
-  CHECK_EQ(3, callback_fired);
+TEST(RequestInterruptTestWithAccessor) {
+  RequestInterruptTestWithAccessor().RunTest();
+}
 
-  i::OS::Print("\n--- Script (2) ---\n");
-  callback_fired = 0;
-  v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
-  script->Run();
-  CHECK_EQ(2, callback_fired);
 
-  i::OS::Print("\n--- Function ---\n");
-  callback_fired = 0;
-  Local<Function> recursive_function =
-      Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
-  v8::Handle<Value> args[] = { v8_num(0) };
-  recursive_function->Call(env->Global(), 1, args);
-  CHECK_EQ(2, callback_fired);
+TEST(RequestInterruptTestWithNativeAccessor) {
+  RequestInterruptTestWithNativeAccessor().RunTest();
 }
 
 
-void CallCompletedCallbackNoException() {
-  v8::HandleScope scope(CcTest::isolate());
-  CompileRun("1+1;");
+TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
+  RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
 }
 
 
-void CallCompletedCallbackException() {
-  v8::HandleScope scope(CcTest::isolate());
-  CompileRun("throw 'second exception';");
+TEST(RequestInterruptTestWithMathAbs) {
+  RequestInterruptTestWithMathAbs().RunTest();
 }
 
 
-TEST(CallCompletedCallbackOneException) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
-  CompileRun("throw 'exception';");
-}
+class RequestMultipleInterrupts : public RequestInterruptTestBase {
+ public:
+  RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
 
+  virtual void StartInterruptThread() {
+    i_thread.Start();
+  }
 
-TEST(CallCompletedCallbackTwoExceptions) {
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
-  CompileRun("throw 'first exception';");
-}
+  virtual void TestBody() {
+    Local<Function> func = Function::New(
+        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
+    env_->Global()->Set(v8_str("ShouldContinue"), func);
 
+    CompileRun("while (ShouldContinue()) { }");
+  }
 
-static int probes_counter = 0;
-static int misses_counter = 0;
-static int updates_counter = 0;
+ private:
+  class InterruptThread : public v8::base::Thread {
+   public:
+    enum { NUM_INTERRUPTS = 10 };
+    explicit InterruptThread(RequestMultipleInterrupts* test)
+        : Thread(Options("RequestInterruptTest")), test_(test) {}
 
+    virtual void Run() {
+      test_->sem_.Wait();
+      for (int i = 0; i < NUM_INTERRUPTS; i++) {
+        test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
+      }
+    }
 
-static int* LookupCounter(const char* name) {
-  if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
-    return &probes_counter;
-  } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
-    return &misses_counter;
-  } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
-    return &updates_counter;
-  }
-  return NULL;
-}
+    static void OnInterrupt(v8::Isolate* isolate, void* data) {
+      RequestMultipleInterrupts* test =
+          reinterpret_cast<RequestMultipleInterrupts*>(data);
+      test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
+    }
 
+   private:
+    RequestMultipleInterrupts* test_;
+  };
 
-static const char* kMegamorphicTestProgram =
-    "function ClassA() { };"
-    "function ClassB() { };"
-    "ClassA.prototype.foo = function() { };"
-    "ClassB.prototype.foo = function() { };"
-    "function fooify(obj) { obj.foo(); };"
-    "var a = new ClassA();"
-    "var b = new ClassB();"
-    "for (var i = 0; i < 10000; i++) {"
-    "  fooify(a);"
-    "  fooify(b);"
-    "}";
+  InterruptThread i_thread;
+  int counter_;
+};
 
 
-static void StubCacheHelper(bool primary) {
-  V8::SetCounterFunction(LookupCounter);
-  USE(kMegamorphicTestProgram);
-#ifdef DEBUG
-  i::FLAG_native_code_counters = true;
-  if (primary) {
-    i::FLAG_test_primary_stub_cache = true;
-  } else {
-    i::FLAG_test_secondary_stub_cache = true;
-  }
-  i::FLAG_crankshaft = false;
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  int initial_probes = probes_counter;
-  int initial_misses = misses_counter;
-  int initial_updates = updates_counter;
-  CompileRun(kMegamorphicTestProgram);
-  int probes = probes_counter - initial_probes;
-  int misses = misses_counter - initial_misses;
-  int updates = updates_counter - initial_updates;
-  CHECK_LT(updates, 10);
-  CHECK_LT(misses, 10);
-  // TODO(verwaest): Update this test to overflow the degree of polymorphism
-  // before megamorphism. The number of probes will only work once we teach the
-  // serializer to embed references to counters in the stubs, given that the
-  // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
-  CHECK_GE(probes, 0);
-#endif
-}
+TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
 
 
-TEST(SecondaryStubCache) {
-  StubCacheHelper(true);
-}
+static bool interrupt_was_called = false;
 
 
-TEST(PrimaryStubCache) {
-  StubCacheHelper(false);
+void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
+  interrupt_was_called = true;
 }
 
 
-static int cow_arrays_created_runtime = 0;
-
+TEST(RequestInterruptSmallScripts) {
+  LocalContext env;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
 
-static int* LookupCounterCOWArrays(const char* name) {
-  if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
-    return &cow_arrays_created_runtime;
-  }
-  return NULL;
+  interrupt_was_called = false;
+  isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
+  CompileRun("(function(x){return x;})(1);");
+  CHECK(interrupt_was_called);
 }
 
 
-TEST(CheckCOWArraysCreatedRuntimeCounter) {
-  V8::SetCounterFunction(LookupCounterCOWArrays);
-#ifdef DEBUG
-  i::FLAG_native_code_counters = true;
-  LocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
-  int initial_cow_arrays = cow_arrays_created_runtime;
-  CompileRun("var o = [1, 2, 3];");
-  CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
-  CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
-  CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
-  CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
-  CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
-#endif
+static Local<Value> function_new_expected_env;
+static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
+  CHECK(function_new_expected_env->Equals(info.Data()));
+  info.GetReturnValue().Set(17);
 }
 
 
-TEST(StaticGetters) {
-  LocalContext context;
-  i::Factory* factory = CcTest::i_isolate()->factory();
-  v8::Isolate* isolate = CcTest::isolate();
+THREADED_TEST(FunctionNew) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
-  i::Handle<i::Object> undefined_value = factory->undefined_value();
-  CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
-  i::Handle<i::Object> null_value = factory->null_value();
-  CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
-  i::Handle<i::Object> true_value = factory->true_value();
-  CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
-  i::Handle<i::Object> false_value = factory->false_value();
-  CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
+  Local<Object> data = v8::Object::New(isolate);
+  function_new_expected_env = data;
+  Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
+  env->Global()->Set(v8_str("func"), func);
+  Local<Value> result = CompileRun("func();");
+  CHECK(v8::Integer::New(isolate, 17)->Equals(result));
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  // Verify function not cached
+  auto serial_number = handle(i::Smi::cast(v8::Utils::OpenHandle(*func)
+                                               ->shared()
+                                               ->get_api_func_data()
+                                               ->serial_number()),
+                              i_isolate);
+  auto cache = i_isolate->function_cache();
+  CHECK(cache->Lookup(serial_number)->IsTheHole());
+  // Verify that each Function::New creates a new function instance
+  Local<Object> data2 = v8::Object::New(isolate);
+  function_new_expected_env = data2;
+  Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
+  CHECK(!func2->IsNull());
+  CHECK(!func->Equals(func2));
+  env->Global()->Set(v8_str("func2"), func2);
+  Local<Value> result2 = CompileRun("func2();");
+  CHECK(v8::Integer::New(isolate, 17)->Equals(result2));
 }
 
 
-UNINITIALIZED_TEST(IsolateEmbedderData) {
-  CcTest::DisableAutomaticDispose();
-  v8::Isolate* isolate = v8::Isolate::New();
-  isolate->Enter();
-  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
-    CHECK_EQ(NULL, isolate->GetData(slot));
-    CHECK_EQ(NULL, i_isolate->GetData(slot));
-  }
-  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
-    void* data = reinterpret_cast<void*>(0xacce55ed + slot);
-    isolate->SetData(slot, data);
-  }
-  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
-    void* data = reinterpret_cast<void*>(0xacce55ed + slot);
-    CHECK_EQ(data, isolate->GetData(slot));
-    CHECK_EQ(data, i_isolate->GetData(slot));
-  }
-  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
-    void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
-    isolate->SetData(slot, data);
+TEST(EscapeableHandleScope) {
+  HandleScope outer_scope(CcTest::isolate());
+  LocalContext context;
+  const int runs = 10;
+  Local<String> values[runs];
+  for (int i = 0; i < runs; i++) {
+    v8::EscapableHandleScope inner_scope(CcTest::isolate());
+    Local<String> value;
+    if (i != 0) value = v8_str("escape value");
+    values[i] = inner_scope.Escape(value);
   }
-  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
-    void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
-    CHECK_EQ(data, isolate->GetData(slot));
-    CHECK_EQ(data, i_isolate->GetData(slot));
+  for (int i = 0; i < runs; i++) {
+    Local<String> expected;
+    if (i != 0) {
+      CHECK(v8_str("escape value")->Equals(values[i]));
+    } else {
+      CHECK(values[i].IsEmpty());
+    }
   }
-  isolate->Exit();
-  isolate->Dispose();
 }
 
 
-TEST(StringEmpty) {
-  LocalContext context;
-  i::Factory* factory = CcTest::i_isolate()->factory();
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  i::Handle<i::Object> empty_string = factory->empty_string();
-  CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
+static void SetterWhichExpectsThisAndHolderToDiffer(
+    Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
+  CHECK(info.Holder() != info.This());
 }
 
 
-static int instance_checked_getter_count = 0;
-static void InstanceCheckedGetter(
-    Local<String> name,
-    const v8::PropertyCallbackInfo<v8::Value>& info) {
-  CHECK_EQ(name, v8_str("foo"));
-  instance_checked_getter_count++;
-  info.GetReturnValue().Set(v8_num(11));
+TEST(Regress239669) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
+  templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
+  context->Global()->Set(v8_str("P"), templ->NewInstance());
+  CompileRun(
+      "function C1() {"
+      "  this.x = 23;"
+      "};"
+      "C1.prototype = P;"
+      "for (var i = 0; i < 4; i++ ) {"
+      "  new C1();"
+      "}");
 }
 
 
-static int instance_checked_setter_count = 0;
-static void InstanceCheckedSetter(Local<String> name,
-                      Local<Value> value,
-                      const v8::PropertyCallbackInfo<void>& info) {
-  CHECK_EQ(name, v8_str("foo"));
-  CHECK_EQ(value, v8_num(23));
-  instance_checked_setter_count++;
-}
-
+class ApiCallOptimizationChecker {
+ private:
+  static Local<Object> data;
+  static Local<Object> receiver;
+  static Local<Object> holder;
+  static Local<Object> callee;
+  static int count;
 
-static void CheckInstanceCheckedResult(int getters,
-                                       int setters,
-                                       bool expects_callbacks,
-                                       TryCatch* try_catch) {
-  if (expects_callbacks) {
-    CHECK(!try_catch->HasCaught());
-    CHECK_EQ(getters, instance_checked_getter_count);
-    CHECK_EQ(setters, instance_checked_setter_count);
-  } else {
-    CHECK(try_catch->HasCaught());
-    CHECK_EQ(0, instance_checked_getter_count);
-    CHECK_EQ(0, instance_checked_setter_count);
+  static void OptimizationCallback(
+      const v8::FunctionCallbackInfo<v8::Value>& info) {
+    CHECK(callee == info.Callee());
+    CHECK(data == info.Data());
+    CHECK(receiver == info.This());
+    if (info.Length() == 1) {
+      CHECK(v8_num(1)->Equals(info[0]));
+    }
+    CHECK(holder == info.Holder());
+    count++;
+    info.GetReturnValue().Set(v8_str("returned"));
   }
-  try_catch->Reset();
-}
 
+ public:
+  enum SignatureType {
+    kNoSignature,
+    kSignatureOnReceiver,
+    kSignatureOnPrototype
+  };
 
-static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
-  instance_checked_getter_count = 0;
-  instance_checked_setter_count = 0;
-  TryCatch try_catch;
+  void RunAll() {
+    SignatureType signature_types[] =
+      {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
+    for (unsigned i = 0; i < arraysize(signature_types); i++) {
+      SignatureType signature_type = signature_types[i];
+      for (int j = 0; j < 2; j++) {
+        bool global = j == 0;
+        int key = signature_type +
+            arraysize(signature_types) * (global ? 1 : 0);
+        Run(signature_type, global, key);
+      }
+    }
+  }
 
-  // Test path through generic runtime code.
-  CompileRun("obj.foo");
-  CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
-  CompileRun("obj.foo = 23");
-  CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
+  void Run(SignatureType signature_type, bool global, int key) {
+    v8::Isolate* isolate = CcTest::isolate();
+    v8::HandleScope scope(isolate);
+    // Build a template for signature checks.
+    Local<v8::ObjectTemplate> signature_template;
+    Local<v8::Signature> signature;
+    {
+      Local<v8::FunctionTemplate> parent_template =
+        FunctionTemplate::New(isolate);
+      parent_template->SetHiddenPrototype(true);
+      Local<v8::FunctionTemplate> function_template
+          = FunctionTemplate::New(isolate);
+      function_template->Inherit(parent_template);
+      switch (signature_type) {
+        case kNoSignature:
+          break;
+        case kSignatureOnReceiver:
+          signature = v8::Signature::New(isolate, function_template);
+          break;
+        case kSignatureOnPrototype:
+          signature = v8::Signature::New(isolate, parent_template);
+          break;
+      }
+      signature_template = function_template->InstanceTemplate();
+    }
+    // Global object must pass checks.
+    Local<v8::Context> context =
+        v8::Context::New(isolate, NULL, signature_template);
+    v8::Context::Scope context_scope(context);
+    // Install regular object that can pass signature checks.
+    Local<Object> function_receiver = signature_template->NewInstance();
+    context->Global()->Set(v8_str("function_receiver"), function_receiver);
+    // Get the holder objects.
+    Local<Object> inner_global =
+        Local<Object>::Cast(context->Global()->GetPrototype());
+    // Install functions on hidden prototype object if there is one.
+    data = Object::New(isolate);
+    Local<FunctionTemplate> function_template = FunctionTemplate::New(
+        isolate, OptimizationCallback, data, signature);
+    Local<Function> function = function_template->GetFunction();
+    Local<Object> global_holder = inner_global;
+    Local<Object> function_holder = function_receiver;
+    if (signature_type == kSignatureOnPrototype) {
+      function_holder = Local<Object>::Cast(function_holder->GetPrototype());
+      global_holder = Local<Object>::Cast(global_holder->GetPrototype());
+    }
+    global_holder->Set(v8_str("g_f"), function);
+    global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
+    function_holder->Set(v8_str("f"), function);
+    function_holder->SetAccessorProperty(v8_str("acc"), function, function);
+    // Initialize expected values.
+    callee = function;
+    count = 0;
+    if (global) {
+      receiver = context->Global();
+      holder = inner_global;
+    } else {
+      holder = function_receiver;
+      // If not using a signature, add something else to the prototype chain
+      // to test the case that holder != receiver
+      if (signature_type == kNoSignature) {
+        receiver = Local<Object>::Cast(CompileRun(
+            "var receiver_subclass = {};\n"
+            "receiver_subclass.__proto__ = function_receiver;\n"
+            "receiver_subclass"));
+      } else {
+        receiver = Local<Object>::Cast(CompileRun(
+          "var receiver_subclass = function_receiver;\n"
+          "receiver_subclass"));
+      }
+    }
+    // With no signature, the holder is not set.
+    if (signature_type == kNoSignature) holder = receiver;
+    // build wrap_function
+    i::ScopedVector<char> wrap_function(200);
+    if (global) {
+      i::SNPrintF(
+          wrap_function,
+          "function wrap_f_%d() { var f = g_f; return f(); }\n"
+          "function wrap_get_%d() { return this.g_acc; }\n"
+          "function wrap_set_%d() { return this.g_acc = 1; }\n",
+          key, key, key);
+    } else {
+      i::SNPrintF(
+          wrap_function,
+          "function wrap_f_%d() { return receiver_subclass.f(); }\n"
+          "function wrap_get_%d() { return receiver_subclass.acc; }\n"
+          "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
+          key, key, key);
+    }
+    // build source string
+    i::ScopedVector<char> source(1000);
+    i::SNPrintF(
+        source,
+        "%s\n"  // wrap functions
+        "function wrap_f() { return wrap_f_%d(); }\n"
+        "function wrap_get() { return wrap_get_%d(); }\n"
+        "function wrap_set() { return wrap_set_%d(); }\n"
+        "check = function(returned) {\n"
+        "  if (returned !== 'returned') { throw returned; }\n"
+        "}\n"
+        "\n"
+        "check(wrap_f());\n"
+        "check(wrap_f());\n"
+        "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
+        "check(wrap_f());\n"
+        "\n"
+        "check(wrap_get());\n"
+        "check(wrap_get());\n"
+        "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
+        "check(wrap_get());\n"
+        "\n"
+        "check = function(returned) {\n"
+        "  if (returned !== 1) { throw returned; }\n"
+        "}\n"
+        "check(wrap_set());\n"
+        "check(wrap_set());\n"
+        "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
+        "check(wrap_set());\n",
+        wrap_function.start(), key, key, key, key, key, key);
+    v8::TryCatch try_catch(isolate);
+    CompileRun(source.start());
+    DCHECK(!try_catch.HasCaught());
+    CHECK_EQ(9, count);
+  }
+};
 
-  // Test path through generated LoadIC and StoredIC.
-  CompileRun("function test_get(o) { o.foo; }"
-             "test_get(obj);");
-  CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
-  CompileRun("test_get(obj);");
-  CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
-  CompileRun("test_get(obj);");
-  CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
-  CompileRun("function test_set(o) { o.foo = 23; }"
-             "test_set(obj);");
-  CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
-  CompileRun("test_set(obj);");
-  CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
-  CompileRun("test_set(obj);");
-  CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
 
-  // Test path through optimized code.
-  CompileRun("%OptimizeFunctionOnNextCall(test_get);"
-             "test_get(obj);");
-  CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
-  CompileRun("%OptimizeFunctionOnNextCall(test_set);"
-             "test_set(obj);");
-  CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
+Local<Object> ApiCallOptimizationChecker::data;
+Local<Object> ApiCallOptimizationChecker::receiver;
+Local<Object> ApiCallOptimizationChecker::holder;
+Local<Object> ApiCallOptimizationChecker::callee;
+int ApiCallOptimizationChecker::count = 0;
 
-  // Cleanup so that closures start out fresh in next check.
-  CompileRun("%DeoptimizeFunction(test_get);"
-             "%ClearFunctionTypeFeedback(test_get);"
-             "%DeoptimizeFunction(test_set);"
-             "%ClearFunctionTypeFeedback(test_set);");
+
+TEST(FunctionCallOptimization) {
+  i::FLAG_allow_natives_syntax = true;
+  ApiCallOptimizationChecker checker;
+  checker.RunAll();
 }
 
 
-THREADED_TEST(InstanceCheckOnInstanceAccessor) {
-  v8::internal::FLAG_allow_natives_syntax = true;
+TEST(FunctionCallOptimizationMultipleArgs) {
+  i::FLAG_allow_natives_syntax = true;
   LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-
-  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
-  Local<ObjectTemplate> inst = templ->InstanceTemplate();
-  inst->SetAccessor(v8_str("foo"),
-                    InstanceCheckedGetter, InstanceCheckedSetter,
-                    Handle<Value>(),
-                    v8::DEFAULT,
-                    v8::None,
-                    v8::AccessorSignature::New(context->GetIsolate(), templ));
-  context->Global()->Set(v8_str("f"), templ->GetFunction());
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Handle<Object> global = context->Global();
+  Local<v8::Function> function = Function::New(isolate, Returns42);
+  global->Set(v8_str("x"), function);
+  CompileRun(
+      "function x_wrap() {\n"
+      "  for (var i = 0; i < 5; i++) {\n"
+      "    x(1,2,3);\n"
+      "  }\n"
+      "}\n"
+      "x_wrap();\n"
+      "%OptimizeFunctionOnNextCall(x_wrap);"
+      "x_wrap();\n");
+}
 
-  printf("Testing positive ...\n");
-  CompileRun("var obj = new f();");
-  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
-  CheckInstanceCheckedAccessors(true);
 
-  printf("Testing negative ...\n");
-  CompileRun("var obj = {};"
-             "obj.__proto__ = new f();");
-  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
-  CheckInstanceCheckedAccessors(false);
+static void ReturnsSymbolCallback(
+    const v8::FunctionCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
 }
 
 
-THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
-  v8::internal::FLAG_allow_natives_syntax = true;
+TEST(ApiCallbackCanReturnSymbols) {
+  i::FLAG_allow_natives_syntax = true;
   LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-
-  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
-  Local<ObjectTemplate> inst = templ->InstanceTemplate();
-  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
-  inst->SetAccessor(v8_str("foo"),
-                    InstanceCheckedGetter, InstanceCheckedSetter,
-                    Handle<Value>(),
-                    v8::DEFAULT,
-                    v8::None,
-                    v8::AccessorSignature::New(context->GetIsolate(), templ));
-  context->Global()->Set(v8_str("f"), templ->GetFunction());
-
-  printf("Testing positive ...\n");
-  CompileRun("var obj = new f();");
-  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
-  CheckInstanceCheckedAccessors(true);
-
-  printf("Testing negative ...\n");
-  CompileRun("var obj = {};"
-             "obj.__proto__ = new f();");
-  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
-  CheckInstanceCheckedAccessors(false);
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Handle<Object> global = context->Global();
+  Local<v8::Function> function = Function::New(isolate, ReturnsSymbolCallback);
+  global->Set(v8_str("x"), function);
+  CompileRun(
+      "function x_wrap() {\n"
+      "  for (var i = 0; i < 5; i++) {\n"
+      "    x();\n"
+      "  }\n"
+      "}\n"
+      "x_wrap();\n"
+      "%OptimizeFunctionOnNextCall(x_wrap);"
+      "x_wrap();\n");
 }
 
 
-THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
-  v8::internal::FLAG_allow_natives_syntax = true;
+TEST(EmptyApiCallback) {
   LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+  auto isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  auto global = context->Global();
+  auto function = FunctionTemplate::New(isolate)->GetFunction();
+  global->Set(v8_str("x"), function);
 
-  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
-  Local<ObjectTemplate> proto = templ->PrototypeTemplate();
-  proto->SetAccessor(v8_str("foo"),
-                     InstanceCheckedGetter, InstanceCheckedSetter,
-                     Handle<Value>(),
-                     v8::DEFAULT,
-                     v8::None,
-                     v8::AccessorSignature::New(context->GetIsolate(), templ));
-  context->Global()->Set(v8_str("f"), templ->GetFunction());
+  auto result = CompileRun("x()");
+  CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
 
-  printf("Testing positive ...\n");
-  CompileRun("var obj = new f();");
-  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
-  CheckInstanceCheckedAccessors(true);
+  result = CompileRun("x(1,2,3)");
+  CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
 
-  printf("Testing negative ...\n");
-  CompileRun("var obj = {};"
-             "obj.__proto__ = new f();");
-  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
-  CheckInstanceCheckedAccessors(false);
+  result = CompileRun("7 + x.call(3) + 11");
+  CHECK(result->IsInt32());
+  CHECK_EQ(21, result->Int32Value());
 
-  printf("Testing positive with modified prototype chain ...\n");
-  CompileRun("var obj = new f();"
-             "var pro = {};"
-             "pro.__proto__ = obj.__proto__;"
-             "obj.__proto__ = pro;");
-  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
-  CheckInstanceCheckedAccessors(true);
+  result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
+  CHECK(result->IsInt32());
+  CHECK_EQ(21, result->Int32Value());
+
+  result = CompileRun("var y = []; x.call(y)");
+  CHECK(result->IsArray());
+
+  result = CompileRun("x.call(y, 1, 2, 3, 4)");
+  CHECK(result->IsArray());
 }
 
 
-TEST(TryFinallyMessage) {
+TEST(SimpleSignatureCheck) {
   LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+  auto isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  auto global = context->Global();
+  auto sig_obj = FunctionTemplate::New(isolate);
+  auto sig = v8::Signature::New(isolate, sig_obj);
+  auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
+  global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
+  global->Set(v8_str("x"), x->GetFunction());
+  CompileRun("var s = new sig_obj();");
   {
-    // Test that the original error message is not lost if there is a
-    // recursive call into Javascript is done in the finally block, e.g. to
-    // initialize an IC. (crbug.com/129171)
-    TryCatch try_catch;
-    const char* trigger_ic =
-        "try {                      \n"
-        "  throw new Error('test'); \n"
-        "} finally {                \n"
-        "  var x = 0;               \n"
-        "  x++;                     \n"  // Trigger an IC initialization here.
-        "}                          \n";
-    CompileRun(trigger_ic);
+    TryCatch try_catch(isolate);
+    CompileRun("x()");
     CHECK(try_catch.HasCaught());
-    Local<Message> message = try_catch.Message();
-    CHECK(!message.IsEmpty());
-    CHECK_EQ(2, message->GetLineNumber());
   }
-
   {
-    // Test that the original exception message is indeed overwritten if
-    // a new error is thrown in the finally block.
-    TryCatch try_catch;
-    const char* throw_again =
-        "try {                       \n"
-        "  throw new Error('test');  \n"
-        "} finally {                 \n"
-        "  var x = 0;                \n"
-        "  x++;                      \n"
-        "  throw new Error('again'); \n"  // This is the new uncaught error.
-        "}                           \n";
-    CompileRun(throw_again);
-    CHECK(try_catch.HasCaught());
-    Local<Message> message = try_catch.Message();
-    CHECK(!message.IsEmpty());
-    CHECK_EQ(6, message->GetLineNumber());
+    TryCatch try_catch(isolate);
+    CompileRun("x.call(1)");
+    CHECK(try_catch.HasCaught());
+  }
+  {
+    TryCatch try_catch(isolate);
+    auto result = CompileRun("s.x = x; s.x()");
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(42, result->Int32Value());
+  }
+  {
+    TryCatch try_catch(isolate);
+    auto result = CompileRun("x.call(s)");
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(42, result->Int32Value());
   }
 }
 
 
-static void Helper137002(bool do_store,
-                         bool polymorphic,
-                         bool remove_accessor,
-                         bool interceptor) {
+TEST(ChainSignatureCheck) {
   LocalContext context;
-  Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
-  if (interceptor) {
-    templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
-  } else {
-    templ->SetAccessor(v8_str("foo"),
-                       GetterWhichReturns42,
-                       SetterWhichSetsYOnThisTo23);
+  auto isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  auto global = context->Global();
+  auto sig_obj = FunctionTemplate::New(isolate);
+  auto sig = v8::Signature::New(isolate, sig_obj);
+  for (int i = 0; i < 4; ++i) {
+    auto temp = FunctionTemplate::New(isolate);
+    temp->Inherit(sig_obj);
+    sig_obj = temp;
+  }
+  auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
+  global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
+  global->Set(v8_str("x"), x->GetFunction());
+  CompileRun("var s = new sig_obj();");
+  {
+    TryCatch try_catch(isolate);
+    CompileRun("x()");
+    CHECK(try_catch.HasCaught());
   }
-  context->Global()->Set(v8_str("obj"), templ->NewInstance());
-
-  // Turn monomorphic on slow object with native accessor, then turn
-  // polymorphic, finally optimize to create negative lookup and fail.
-  CompileRun(do_store ?
-             "function f(x) { x.foo = void 0; }" :
-             "function f(x) { return x.foo; }");
-  CompileRun("obj.y = void 0;");
-  if (!interceptor) {
-    CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
+  {
+    TryCatch try_catch(isolate);
+    CompileRun("x.call(1)");
+    CHECK(try_catch.HasCaught());
   }
-  CompileRun("obj.__proto__ = null;"
-             "f(obj); f(obj); f(obj);");
-  if (polymorphic) {
-    CompileRun("f({});");
+  {
+    TryCatch try_catch(isolate);
+    auto result = CompileRun("s.x = x; s.x()");
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(42, result->Int32Value());
   }
-  CompileRun("obj.y = void 0;"
-             "%OptimizeFunctionOnNextCall(f);");
-  if (remove_accessor) {
-    CompileRun("delete obj.foo;");
+  {
+    TryCatch try_catch(isolate);
+    auto result = CompileRun("x.call(s)");
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(42, result->Int32Value());
   }
-  CompileRun("var result = f(obj);");
-  if (do_store) {
-    CompileRun("result = obj.y;");
+}
+
+
+TEST(PrototypeSignatureCheck) {
+  LocalContext context;
+  auto isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  auto global = context->Global();
+  auto sig_obj = FunctionTemplate::New(isolate);
+  sig_obj->SetHiddenPrototype(true);
+  auto sig = v8::Signature::New(isolate, sig_obj);
+  auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
+  global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
+  global->Set(v8_str("x"), x->GetFunction());
+  CompileRun("s = {}; s.__proto__ = new sig_obj();");
+  {
+    TryCatch try_catch(isolate);
+    CompileRun("x()");
+    CHECK(try_catch.HasCaught());
   }
-  if (remove_accessor && !interceptor) {
-    CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
-  } else {
-    CHECK_EQ(do_store ? 23 : 42,
-             context->Global()->Get(v8_str("result"))->Int32Value());
+  {
+    TryCatch try_catch(isolate);
+    CompileRun("x.call(1)");
+    CHECK(try_catch.HasCaught());
+  }
+  {
+    TryCatch try_catch(isolate);
+    auto result = CompileRun("s.x = x; s.x()");
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(42, result->Int32Value());
+  }
+  {
+    TryCatch try_catch(isolate);
+    auto result = CompileRun("x.call(s)");
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(42, result->Int32Value());
   }
 }
 
 
-THREADED_TEST(Regress137002a) {
-  i::FLAG_allow_natives_syntax = true;
-  i::FLAG_compilation_cache = false;
-  v8::HandleScope scope(CcTest::isolate());
-  for (int i = 0; i < 16; i++) {
-    Helper137002(i & 8, i & 4, i & 2, i & 1);
-  }
+static const char* last_event_message;
+static int last_event_status;
+void StoringEventLoggerCallback(const char* message, int status) {
+    last_event_message = message;
+    last_event_status = status;
 }
 
 
-THREADED_TEST(Regress137002b) {
-  i::FLAG_allow_natives_syntax = true;
+TEST(EventLogging) {
+  v8::Isolate* isolate = CcTest::isolate();
+  isolate->SetEventLogger(StoringEventLoggerCallback);
+  v8::internal::HistogramTimer histogramTimer(
+      "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
+      reinterpret_cast<v8::internal::Isolate*>(isolate));
+  histogramTimer.Start();
+  CHECK_EQ(0, strcmp("V8.Test", last_event_message));
+  CHECK_EQ(0, last_event_status);
+  histogramTimer.Stop();
+  CHECK_EQ(0, strcmp("V8.Test", last_event_message));
+  CHECK_EQ(1, last_event_status);
+}
+
+
+TEST(Promises) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetAccessor(v8_str("foo"),
-                     GetterWhichReturns42,
-                     SetterWhichSetsYOnThisTo23);
-  context->Global()->Set(v8_str("obj"), templ->NewInstance());
-
-  // Turn monomorphic on slow object with native accessor, then just
-  // delete the property and fail.
-  CompileRun("function load(x) { return x.foo; }"
-             "function store(x) { x.foo = void 0; }"
-             "function keyed_load(x, key) { return x[key]; }"
-             // Second version of function has a different source (add void 0)
-             // so that it does not share code with the first version.  This
-             // ensures that the ICs are monomorphic.
-             "function load2(x) { void 0; return x.foo; }"
-             "function store2(x) { void 0; x.foo = void 0; }"
-             "function keyed_load2(x, key) { void 0; return x[key]; }"
+  Handle<Object> global = context->Global();
 
-             "obj.y = void 0;"
-             "obj.__proto__ = null;"
-             "var subobj = {};"
-             "subobj.y = void 0;"
-             "subobj.__proto__ = obj;"
-             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
+  // Creation.
+  Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
+  Handle<v8::Promise::Resolver> rr = v8::Promise::Resolver::New(isolate);
+  Handle<v8::Promise> p = pr->GetPromise();
+  Handle<v8::Promise> r = rr->GetPromise();
+  CHECK_EQ(isolate, p->GetIsolate());
+
+  // IsPromise predicate.
+  CHECK(p->IsPromise());
+  CHECK(r->IsPromise());
+  Handle<Value> o = v8::Object::New(isolate);
+  CHECK(!o->IsPromise());
+
+  // Resolution and rejection.
+  pr->Resolve(v8::Integer::New(isolate, 1));
+  CHECK(p->IsPromise());
+  rr->Reject(v8::Integer::New(isolate, 2));
+  CHECK(r->IsPromise());
+
+  // Chaining non-pending promises.
+  CompileRun(
+      "var x1 = 0;\n"
+      "var x2 = 0;\n"
+      "function f1(x) { x1 = x; return x+1 };\n"
+      "function f2(x) { x2 = x; return x+1 };\n");
+  Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
+  Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
+
+  p->Chain(f1);
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  isolate->RunMicrotasks();
+  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
+
+  p->Catch(f2);
+  isolate->RunMicrotasks();
+  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+
+  r->Catch(f2);
+  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+  isolate->RunMicrotasks();
+  CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
+
+  r->Chain(f1);
+  isolate->RunMicrotasks();
+  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
+
+  // Chaining pending promises.
+  CompileRun("x1 = x2 = 0;");
+  pr = v8::Promise::Resolver::New(isolate);
+  rr = v8::Promise::Resolver::New(isolate);
+
+  pr->GetPromise()->Chain(f1);
+  rr->GetPromise()->Catch(f2);
+  isolate->RunMicrotasks();
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+
+  pr->Resolve(v8::Integer::New(isolate, 1));
+  rr->Reject(v8::Integer::New(isolate, 2));
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+
+  isolate->RunMicrotasks();
+  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
+
+  // Multi-chaining.
+  CompileRun("x1 = x2 = 0;");
+  pr = v8::Promise::Resolver::New(isolate);
+  pr->GetPromise()->Chain(f1)->Chain(f2);
+  pr->Resolve(v8::Integer::New(isolate, 3));
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+  isolate->RunMicrotasks();
+  CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
+
+  CompileRun("x1 = x2 = 0;");
+  rr = v8::Promise::Resolver::New(isolate);
+  rr->GetPromise()->Catch(f1)->Chain(f2);
+  rr->Reject(v8::Integer::New(isolate, 3));
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+  isolate->RunMicrotasks();
+  CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
+}
+
+
+TEST(PromiseThen) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Handle<Object> global = context->Global();
 
-             // Make the ICs monomorphic.
-             "load(obj); load(obj);"
-             "load2(subobj); load2(subobj);"
-             "store(obj); store(obj);"
-             "store2(subobj); store2(subobj);"
-             "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
-             "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
+  // Creation.
+  Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
+  Handle<v8::Promise::Resolver> qr = v8::Promise::Resolver::New(isolate);
+  Handle<v8::Promise> p = pr->GetPromise();
+  Handle<v8::Promise> q = qr->GetPromise();
 
-             // Actually test the shiny new ICs and better not crash. This
-             // serves as a regression test for issue 142088 as well.
-             "load(obj);"
-             "load2(subobj);"
-             "store(obj);"
-             "store2(subobj);"
-             "keyed_load(obj, 'foo');"
-             "keyed_load2(subobj, 'foo');"
+  CHECK(p->IsPromise());
+  CHECK(q->IsPromise());
 
-             // Delete the accessor.  It better not be called any more now.
-             "delete obj.foo;"
-             "obj.y = void 0;"
-             "subobj.y = void 0;"
+  pr->Resolve(v8::Integer::New(isolate, 1));
+  qr->Resolve(p);
 
-             "var load_result = load(obj);"
-             "var load_result2 = load2(subobj);"
-             "var keyed_load_result = keyed_load(obj, 'foo');"
-             "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
-             "store(obj);"
-             "store2(subobj);"
-             "var y_from_obj = obj.y;"
-             "var y_from_subobj = subobj.y;");
-  CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
-  CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
-  CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
-  CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
-  CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
-  CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
+  // Chaining non-pending promises.
+  CompileRun(
+      "var x1 = 0;\n"
+      "var x2 = 0;\n"
+      "function f1(x) { x1 = x; return x+1 };\n"
+      "function f2(x) { x2 = x; return x+1 };\n");
+  Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
+  Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
+
+  // Chain
+  q->Chain(f1);
+  CHECK(global->Get(v8_str("x1"))->IsNumber());
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  isolate->RunMicrotasks();
+  CHECK(!global->Get(v8_str("x1"))->IsNumber());
+  CHECK(p->Equals(global->Get(v8_str("x1"))));
+
+  // Then
+  CompileRun("x1 = x2 = 0;");
+  q->Then(f1);
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  isolate->RunMicrotasks();
+  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
+
+  // Then
+  CompileRun("x1 = x2 = 0;");
+  pr = v8::Promise::Resolver::New(isolate);
+  qr = v8::Promise::Resolver::New(isolate);
+
+  qr->Resolve(pr);
+  qr->GetPromise()->Then(f1)->Then(f2);
+
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+  isolate->RunMicrotasks();
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+
+  pr->Resolve(v8::Integer::New(isolate, 3));
+
+  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
+  isolate->RunMicrotasks();
+  CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
+  CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
+}
+
+
+TEST(DisallowJavascriptExecutionScope) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Isolate::DisallowJavascriptExecutionScope no_js(
+      isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
+  CompileRun("2+2");
 }
 
 
-THREADED_TEST(Regress142088) {
-  i::FLAG_allow_natives_syntax = true;
+TEST(AllowJavascriptExecutionScope) {
   LocalContext context;
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetAccessor(v8_str("foo"),
-                     GetterWhichReturns42,
-                     SetterWhichSetsYOnThisTo23);
-  context->Global()->Set(v8_str("obj"), templ->NewInstance());
-
-  CompileRun("function load(x) { return x.foo; }"
-             "var o = Object.create(obj);"
-             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
-             "load(o); load(o); load(o); load(o);");
+  v8::Isolate::DisallowJavascriptExecutionScope no_js(
+      isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
+  v8::Isolate::DisallowJavascriptExecutionScope throw_js(
+      isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
+  { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
+    CompileRun("1+1");
+  }
 }
 
 
-THREADED_TEST(Regress137496) {
-  i::FLAG_expose_gc = true;
+TEST(ThrowOnJavascriptExecution) {
   LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-
-  // Compile a try-finally clause where the finally block causes a GC
-  // while there still is a message pending for external reporting.
-  TryCatch try_catch;
-  try_catch.SetVerbose(true);
-  CompileRun("try { throw new Error(); } finally { gc(); }");
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::TryCatch try_catch(isolate);
+  v8::Isolate::DisallowJavascriptExecutionScope throw_js(
+      isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
+  CompileRun("1+1");
   CHECK(try_catch.HasCaught());
 }
 
 
-THREADED_TEST(Regress149912) {
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
-  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
-  context->Global()->Set(v8_str("Bug"), templ->GetFunction());
-  CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
+TEST(Regress354123) {
+  LocalContext current;
+  v8::Isolate* isolate = current->GetIsolate();
+  v8::HandleScope scope(isolate);
+
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+  templ->SetAccessCheckCallbacks(AccessCounter, NULL);
+  current->Global()->Set(v8_str("friend"), templ->NewInstance());
+
+  // Test access using __proto__ from the prototype chain.
+  access_count = 0;
+  CompileRun("friend.__proto__ = {};");
+  CHECK_EQ(2, access_count);
+  CompileRun("friend.__proto__;");
+  CHECK_EQ(4, access_count);
+
+  // Test access using __proto__ as a hijacked function (A).
+  access_count = 0;
+  CompileRun("var p = Object.prototype;"
+             "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
+             "f.call(friend, {});");
+  CHECK_EQ(1, access_count);
+  CompileRun("var p = Object.prototype;"
+             "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
+             "f.call(friend);");
+  CHECK_EQ(2, access_count);
+
+  // Test access using __proto__ as a hijacked function (B).
+  access_count = 0;
+  CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
+             "f.call(friend, {});");
+  CHECK_EQ(1, access_count);
+  CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
+             "f.call(friend);");
+  CHECK_EQ(2, access_count);
+
+  // Test access using Object.setPrototypeOf reflective method.
+  access_count = 0;
+  CompileRun("Object.setPrototypeOf(friend, {});");
+  CHECK_EQ(1, access_count);
+  CompileRun("Object.getPrototypeOf(friend);");
+  CHECK_EQ(2, access_count);
 }
 
 
-THREADED_TEST(Regress157124) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
+TEST(CaptureStackTraceForStackOverflow) {
+  v8::internal::FLAG_stack_size = 150;
+  LocalContext current;
+  v8::Isolate* isolate = current->GetIsolate();
   v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  Local<Object> obj = templ->NewInstance();
-  obj->GetIdentityHash();
-  obj->DeleteHiddenValue(v8_str("Bug"));
+  V8::SetCaptureStackTraceForUncaughtExceptions(
+      true, 10, v8::StackTrace::kDetailed);
+  v8::TryCatch try_catch(isolate);
+  CompileRun("(function f(x) { f(x+1); })(0)");
+  CHECK(try_catch.HasCaught());
 }
 
 
-THREADED_TEST(Regress2535) {
-  i::FLAG_harmony_collections = true;
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  Local<Value> set_value = CompileRun("new Set();");
-  Local<Object> set_object(Local<Object>::Cast(set_value));
-  CHECK_EQ(0, set_object->InternalFieldCount());
-  Local<Value> map_value = CompileRun("new Map();");
-  Local<Object> map_object(Local<Object>::Cast(map_value));
-  CHECK_EQ(0, map_object->InternalFieldCount());
+TEST(ScriptNameAndLineNumber) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  const char* url = "http://www.foo.com/foo.js";
+  v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
+  v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
+  Local<Script> script = v8::ScriptCompiler::Compile(
+      isolate, &script_source);
+  Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
+  CHECK(!script_name.IsEmpty());
+  CHECK(script_name->IsString());
+  String::Utf8Value utf8_name(script_name);
+  CHECK_EQ(0, strcmp(url, *utf8_name));
+  int line_number = script->GetUnboundScript()->GetLineNumber(0);
+  CHECK_EQ(13, line_number);
+}
+
+void CheckMagicComments(Handle<Script> script, const char* expected_source_url,
+                        const char* expected_source_mapping_url) {
+  if (expected_source_url != NULL) {
+    v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
+    CHECK_EQ(0, strcmp(expected_source_url, *url));
+  } else {
+    CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
+  }
+  if (expected_source_mapping_url != NULL) {
+    v8::String::Utf8Value url(
+        script->GetUnboundScript()->GetSourceMappingURL());
+    CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
+  } else {
+    CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
+  }
 }
 
+void SourceURLHelper(const char* source, const char* expected_source_url,
+                     const char* expected_source_mapping_url) {
+  Local<Script> script = v8_compile(source);
+  CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
+}
 
-THREADED_TEST(Regress2746) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
+
+TEST(ScriptSourceURLAndSourceMappingURL) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
-  Local<Object> obj = Object::New(isolate);
-  Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
-  obj->SetHiddenValue(key, v8::Undefined(isolate));
-  Local<Value> value = obj->GetHiddenValue(key);
-  CHECK(!value.IsEmpty());
-  CHECK(value->IsUndefined());
-}
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL=bar1.js\n", "bar1.js", NULL);
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
+
+  // Both sourceURL and sourceMappingURL.
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL=bar3.js\n"
+                  "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
+
+  // Two source URLs; the first one is ignored.
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL=ignoreme.js\n"
+                  "//# sourceURL=bar5.js\n", "bar5.js", NULL);
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceMappingURL=ignoreme.js\n"
+                  "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
+
+  // SourceURL or sourceMappingURL in the middle of the script.
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL=bar7.js\n"
+                  "function baz() {}\n", "bar7.js", NULL);
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceMappingURL=bar8.js\n"
+                  "function baz() {}\n", NULL, "bar8.js");
+
+  // Too much whitespace.
+  SourceURLHelper("function foo() {}\n"
+                  "//#  sourceURL=bar9.js\n"
+                  "//#  sourceMappingURL=bar10.js\n", NULL, NULL);
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL =bar11.js\n"
+                  "//# sourceMappingURL =bar12.js\n", NULL, NULL);
+
+  // Disallowed characters in value.
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL=bar13 .js   \n"
+                  "//# sourceMappingURL=bar14 .js \n",
+                  NULL, NULL);
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL=bar15\t.js   \n"
+                  "//# sourceMappingURL=bar16\t.js \n",
+                  NULL, NULL);
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL=bar17'.js   \n"
+                  "//# sourceMappingURL=bar18'.js \n",
+                  NULL, NULL);
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL=bar19\".js   \n"
+                  "//# sourceMappingURL=bar20\".js \n",
+                  NULL, NULL);
+
+  // Not too much whitespace.
+  SourceURLHelper("function foo() {}\n"
+                  "//# sourceURL=  bar21.js   \n"
+                  "//# sourceMappingURL=  bar22.js \n", "bar21.js", "bar22.js");
+}
+
+
+TEST(GetOwnPropertyDescriptor) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  CompileRun(
+    "var x = { value : 13};"
+    "Object.defineProperty(x, 'p0', {value : 12});"
+    "Object.defineProperty(x, 'p1', {"
+    "  set : function(value) { this.value = value; },"
+    "  get : function() { return this.value; },"
+    "});");
+  Local<Object> x = Local<Object>::Cast(env->Global()->Get(v8_str("x")));
+  Local<Value> desc = x->GetOwnPropertyDescriptor(v8_str("no_prop"));
+  CHECK(desc->IsUndefined());
+  desc = x->GetOwnPropertyDescriptor(v8_str("p0"));
+  CHECK(v8_num(12)->Equals(Local<Object>::Cast(desc)->Get(v8_str("value"))));
+  desc = x->GetOwnPropertyDescriptor(v8_str("p1"));
+  Local<Function> set =
+    Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("set")));
+  Local<Function> get =
+    Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("get")));
+  CHECK(v8_num(13)->Equals(get->Call(x, 0, NULL)));
+  Handle<Value> args[] = { v8_num(14) };
+  set->Call(x, 1, args);
+  CHECK(v8_num(14)->Equals(get->Call(x, 0, NULL)));
+}
+
+
+TEST(Regress411877) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<v8::ObjectTemplate> object_template =
+      v8::ObjectTemplate::New(isolate);
+  object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
 
+  v8::Handle<Context> context = Context::New(isolate);
+  v8::Context::Scope context_scope(context);
 
-THREADED_TEST(Regress260106) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
-                                                        DummyCallHandler);
-  CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
-  Local<Function> function = templ->GetFunction();
-  CHECK(!function.IsEmpty());
-  CHECK(function->IsFunction());
+  context->Global()->Set(v8_str("o"), object_template->NewInstance());
+  CompileRun("Object.getOwnPropertyNames(o)");
 }
 
 
-THREADED_TEST(JSONParseObject) {
-  LocalContext context;
-  HandleScope scope(context->GetIsolate());
-  Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
-  Handle<Object> global = context->Global();
-  global->Set(v8_str("obj"), obj);
-  ExpectString("JSON.stringify(obj)", "{\"x\":42}");
-}
+TEST(GetHiddenPropertyTableAfterAccessCheck) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<v8::ObjectTemplate> object_template =
+      v8::ObjectTemplate::New(isolate);
+  object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
 
+  v8::Handle<Context> context = Context::New(isolate);
+  v8::Context::Scope context_scope(context);
 
-THREADED_TEST(JSONParseNumber) {
-  LocalContext context;
-  HandleScope scope(context->GetIsolate());
-  Local<Value> obj = v8::JSON::Parse(v8_str("42"));
-  Handle<Object> global = context->Global();
-  global->Set(v8_str("obj"), obj);
-  ExpectString("JSON.stringify(obj)", "42");
+  v8::Handle<v8::Object> obj = object_template->NewInstance();
+  obj->Set(v8_str("key"), v8_str("value"));
+  obj->Delete(v8_str("key"));
+
+  obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2"));
 }
 
 
-#if V8_OS_POSIX
-class ThreadInterruptTest {
- public:
-  ThreadInterruptTest() : sem_(0), sem_value_(0) { }
-  ~ThreadInterruptTest() {}
+TEST(Regress411793) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<v8::ObjectTemplate> object_template =
+      v8::ObjectTemplate::New(isolate);
+  object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
 
-  void RunTest() {
-    InterruptThread i_thread(this);
-    i_thread.Start();
+  v8::Handle<Context> context = Context::New(isolate);
+  v8::Context::Scope context_scope(context);
 
-    sem_.Wait();
-    CHECK_EQ(kExpectedValue, sem_value_);
+  context->Global()->Set(v8_str("o"), object_template->NewInstance());
+  CompileRun(
+      "Object.defineProperty(o, 'key', "
+      "    { get: function() {}, set: function() {} });");
+}
+
+class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
+ public:
+  explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
+
+  virtual size_t GetMoreData(const uint8_t** src) {
+    // Unlike in real use cases, this function will never block.
+    if (chunks_[index_] == NULL) {
+      return 0;
+    }
+    // Copy the data, since the caller takes ownership of it.
+    size_t len = strlen(chunks_[index_]);
+    // We don't need to zero-terminate since we return the length.
+    uint8_t* copy = new uint8_t[len];
+    memcpy(copy, chunks_[index_], len);
+    *src = copy;
+    ++index_;
+    return len;
+  }
+
+  // Helper for constructing a string from chunks (the compilation needs it
+  // too).
+  static char* FullSourceString(const char** chunks) {
+    size_t total_len = 0;
+    for (size_t i = 0; chunks[i] != NULL; ++i) {
+      total_len += strlen(chunks[i]);
+    }
+    char* full_string = new char[total_len + 1];
+    size_t offset = 0;
+    for (size_t i = 0; chunks[i] != NULL; ++i) {
+      size_t len = strlen(chunks[i]);
+      memcpy(full_string + offset, chunks[i], len);
+      offset += len;
+    }
+    full_string[total_len] = 0;
+    return full_string;
   }
 
  private:
-  static const int kExpectedValue = 1;
+  const char** chunks_;
+  unsigned index_;
+};
 
-  class InterruptThread : public i::Thread {
-   public:
-    explicit InterruptThread(ThreadInterruptTest* test)
-        : Thread("InterruptThread"), test_(test) {}
 
-    virtual void Run() {
-      struct sigaction action;
+// Helper function for running streaming tests.
+void RunStreamingTest(const char** chunks,
+                      v8::ScriptCompiler::StreamedSource::Encoding encoding =
+                          v8::ScriptCompiler::StreamedSource::ONE_BYTE,
+                      bool expected_success = true,
+                      const char* expected_source_url = NULL,
+                      const char* expected_source_mapping_url = NULL) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::TryCatch try_catch(isolate);
+
+  v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
+                                            encoding);
+  v8::ScriptCompiler::ScriptStreamingTask* task =
+      v8::ScriptCompiler::StartStreamingScript(isolate, &source);
+
+  // TestSourceStream::GetMoreData won't block, so it's OK to just run the
+  // task here in the main thread.
+  task->Run();
+  delete task;
+
+  // Possible errors are only produced while compiling.
+  CHECK_EQ(false, try_catch.HasCaught());
+
+  v8::ScriptOrigin origin(v8_str("http://foo.com"));
+  char* full_source = TestSourceStream::FullSourceString(chunks);
+  v8::Handle<Script> script = v8::ScriptCompiler::Compile(
+      isolate, &source, v8_str(full_source), origin);
+  if (expected_success) {
+    CHECK(!script.IsEmpty());
+    v8::Handle<Value> result(script->Run());
+    // All scripts are supposed to return the fixed value 13 when ran.
+    CHECK_EQ(13, result->Int32Value());
+    CheckMagicComments(script, expected_source_url,
+                       expected_source_mapping_url);
+  } else {
+    CHECK(script.IsEmpty());
+    CHECK(try_catch.HasCaught());
+  }
+  delete[] full_source;
+}
 
-      // Ensure that we'll enter waiting condition
-      i::OS::Sleep(100);
 
-      // Setup signal handler
-      memset(&action, 0, sizeof(action));
-      action.sa_handler = SignalHandler;
-      sigaction(SIGCHLD, &action, NULL);
+TEST(StreamingSimpleScript) {
+  // This script is unrealistically small, since no one chunk is enough to fill
+  // the backing buffer of Scanner, let alone overflow it.
+  const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
+                          NULL};
+  RunStreamingTest(chunks);
+}
 
-      // Send signal
-      kill(getpid(), SIGCHLD);
 
-      // Ensure that if wait has returned because of error
-      i::OS::Sleep(100);
+TEST(StreamingBiggerScript) {
+  const char* chunk1 =
+      "function foo() {\n"
+      "  // Make this chunk sufficiently long so that it will overflow the\n"
+      "  // backing buffer of the Scanner.\n"
+      "  var i = 0;\n"
+      "  var result = 0;\n"
+      "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
+      "  result = 0;\n"
+      "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
+      "  result = 0;\n"
+      "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
+      "  result = 0;\n"
+      "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
+      "  return result;\n"
+      "}\n";
+  const char* chunks[] = {chunk1, "foo(); ", NULL};
+  RunStreamingTest(chunks);
+}
 
-      // Set value and signal semaphore
-      test_->sem_value_ = 1;
-      test_->sem_.Signal();
-    }
 
-    static void SignalHandler(int signal) {
-    }
+TEST(StreamingScriptWithParseError) {
+  // Test that parse errors from streamed scripts are propagated correctly.
+  {
+    char chunk1[] =
+        "  // This will result in a parse error.\n"
+        "  var if else then foo";
+    char chunk2[] = "  13\n";
+    const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
 
-   private:
-     ThreadInterruptTest* test_;
-  };
+    RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
+                     false);
+  }
+  // Test that the next script succeeds normally.
+  {
+    char chunk1[] =
+        "  // This will be parsed successfully.\n"
+        "  function foo() { return ";
+    char chunk2[] = "  13; }\n";
+    const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+
+    RunStreamingTest(chunks);
+  }
+}
+
+
+TEST(StreamingUtf8Script) {
+  // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
+  // don't like it.
+  const char* chunk1 =
+      "function foo() {\n"
+      "  // This function will contain an UTF-8 character which is not in\n"
+      "  // ASCII.\n"
+      "  var foob\xec\x92\x81r = 13;\n"
+      "  return foob\xec\x92\x81r;\n"
+      "}\n";
+  const char* chunks[] = {chunk1, "foo(); ", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+}
+
+
+TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
+  // A sanity check to prove that the approach of splitting UTF-8
+  // characters is correct. Here is an UTF-8 character which will take three
+  // bytes.
+  const char* reference = "\xec\x92\x81";
+  CHECK(3u == strlen(reference));  // NOLINT - no CHECK_EQ for unsigned.
+
+  char chunk1[] =
+      "function foo() {\n"
+      "  // This function will contain an UTF-8 character which is not in\n"
+      "  // ASCII.\n"
+      "  var foob";
+  char chunk2[] =
+      "XXXr = 13;\n"
+      "  return foob\xec\x92\x81r;\n"
+      "}\n";
+  for (int i = 0; i < 3; ++i) {
+    chunk2[i] = reference[i];
+  }
+  const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+}
+
+
+TEST(StreamingUtf8ScriptWithSplitCharacters) {
+  // Stream data where a multi-byte UTF-8 character is split between two data
+  // chunks.
+  const char* reference = "\xec\x92\x81";
+  char chunk1[] =
+      "function foo() {\n"
+      "  // This function will contain an UTF-8 character which is not in\n"
+      "  // ASCII.\n"
+      "  var foobX";
+  char chunk2[] =
+      "XXr = 13;\n"
+      "  return foob\xec\x92\x81r;\n"
+      "}\n";
+  chunk1[strlen(chunk1) - 1] = reference[0];
+  chunk2[0] = reference[1];
+  chunk2[1] = reference[2];
+  const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+}
+
+
+TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
+  // Tests edge cases which should still be decoded correctly.
+
+  // Case 1: a chunk contains only bytes for a split character (and no other
+  // data). This kind of a chunk would be exceptionally small, but we should
+  // still decode it correctly.
+  const char* reference = "\xec\x92\x81";
+  // The small chunk is at the beginning of the split character
+  {
+    char chunk1[] =
+        "function foo() {\n"
+        "  // This function will contain an UTF-8 character which is not in\n"
+        "  // ASCII.\n"
+        "  var foob";
+    char chunk2[] = "XX";
+    char chunk3[] =
+        "Xr = 13;\n"
+        "  return foob\xec\x92\x81r;\n"
+        "}\n";
+    chunk2[0] = reference[0];
+    chunk2[1] = reference[1];
+    chunk3[0] = reference[2];
+    const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
+    RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+  }
+  // The small chunk is at the end of a character
+  {
+    char chunk1[] =
+        "function foo() {\n"
+        "  // This function will contain an UTF-8 character which is not in\n"
+        "  // ASCII.\n"
+        "  var foobX";
+    char chunk2[] = "XX";
+    char chunk3[] =
+        "r = 13;\n"
+        "  return foob\xec\x92\x81r;\n"
+        "}\n";
+    chunk1[strlen(chunk1) - 1] = reference[0];
+    chunk2[0] = reference[1];
+    chunk2[1] = reference[2];
+    const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
+    RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+  }
+  // Case 2: the script ends with a multi-byte character. Make sure that it's
+  // decoded correctly and not just ignored.
+  {
+    char chunk1[] =
+        "var foob\xec\x92\x81 = 13;\n"
+        "foob\xec\x92\x81";
+    const char* chunks[] = {chunk1, NULL};
+    RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+  }
+}
 
-  i::Semaphore sem_;
-  volatile int sem_value_;
-};
 
+TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
+  // Test cases where a UTF-8 character is split over several chunks. Those
+  // cases are not supported (the embedder should give the data in big enough
+  // chunks), but we shouldn't crash, just produce a parse error.
+  const char* reference = "\xec\x92\x81";
+  char chunk1[] =
+      "function foo() {\n"
+      "  // This function will contain an UTF-8 character which is not in\n"
+      "  // ASCII.\n"
+      "  var foobX";
+  char chunk2[] = "X";
+  char chunk3[] =
+      "Xr = 13;\n"
+      "  return foob\xec\x92\x81r;\n"
+      "}\n";
+  chunk1[strlen(chunk1) - 1] = reference[0];
+  chunk2[0] = reference[1];
+  chunk3[0] = reference[2];
+  const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
 
-THREADED_TEST(SemaphoreInterruption) {
-  ThreadInterruptTest().RunTest();
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
 }
 
 
-#endif  // V8_OS_POSIX
+TEST(StreamingProducesParserCache) {
+  i::FLAG_min_preparse_length = 0;
+  const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
+                          NULL};
 
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
 
-static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
-                                     Local<Value> name,
-                                     v8::AccessType type,
-                                     Local<Value> data) {
-  i::PrintF("Named access blocked.\n");
-  return false;
-}
+  v8::ScriptCompiler::StreamedSource source(
+      new TestSourceStream(chunks),
+      v8::ScriptCompiler::StreamedSource::ONE_BYTE);
+  v8::ScriptCompiler::ScriptStreamingTask* task =
+      v8::ScriptCompiler::StartStreamingScript(
+          isolate, &source, v8::ScriptCompiler::kProduceParserCache);
 
+  // TestSourceStream::GetMoreData won't block, so it's OK to just run the
+  // task here in the main thread.
+  task->Run();
+  delete task;
 
-static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
-                                     uint32_t key,
-                                     v8::AccessType type,
-                                     Local<Value> data) {
-  i::PrintF("Indexed access blocked.\n");
-  return false;
+  const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
+  CHECK(cached_data != NULL);
+  CHECK(cached_data->data != NULL);
+  CHECK(!cached_data->rejected);
+  CHECK_GT(cached_data->length, 0);
 }
 
 
-void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  CHECK(false);
-}
+TEST(StreamingWithDebuggingDoesNotProduceParserCache) {
+  // If the debugger is active, we should just not produce parser cache at
+  // all. This is a regeression test: We used to produce a parser cache without
+  // any data in it (just headers).
+  i::FLAG_min_preparse_length = 0;
+  const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
+                          NULL};
 
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
 
-TEST(JSONStringifyAccessCheck) {
-  v8::V8::Initialize();
-  v8::Isolate* isolate = CcTest::isolate();
+  // Make the debugger active by setting a breakpoint.
+  CompileRun("function break_here() { }");
+  i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(
+      v8::Utils::OpenHandle(*env->Global()->Get(v8_str("break_here"))));
+  EnableDebugger();
+  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
+  int position = 0;
+  debug->SetBreakPoint(func, i::Handle<i::Object>(v8::internal::Smi::FromInt(1),
+                                                  CcTest::i_isolate()),
+                       &position);
+
+  v8::ScriptCompiler::StreamedSource source(
+      new TestSourceStream(chunks),
+      v8::ScriptCompiler::StreamedSource::ONE_BYTE);
+  v8::ScriptCompiler::ScriptStreamingTask* task =
+      v8::ScriptCompiler::StartStreamingScript(
+          isolate, &source, v8::ScriptCompiler::kProduceParserCache);
+
+  // TestSourceStream::GetMoreData won't block, so it's OK to just run the
+  // task here in the main thread.
+  task->Run();
+  delete task;
+
+  // Check that we got no cached data.
+  CHECK(source.GetCachedData() == NULL);
+  DisableDebugger();
+}
+
+
+TEST(StreamingScriptWithInvalidUtf8) {
+  // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
+  // chunk don't produce a crash.
+  const char* reference = "\xec\x92\x81\x80\x80";
+  char chunk1[] =
+      "function foo() {\n"
+      "  // This function will contain an UTF-8 character which is not in\n"
+      "  // ASCII.\n"
+      "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
+  char chunk2[] =
+      "r = 13;\n"
+      "  return foob\xec\x92\x81\x80\x80r;\n"
+      "}\n";
+  for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
+
+  const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
+}
+
+
+TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
+  // Regression test: Stream data where there are several multi-byte UTF-8
+  // characters in a sequence and one of them is split between two data chunks.
+  const char* reference = "\xec\x92\x81";
+  char chunk1[] =
+      "function foo() {\n"
+      "  // This function will contain an UTF-8 character which is not in\n"
+      "  // ASCII.\n"
+      "  var foob\xec\x92\x81X";
+  char chunk2[] =
+      "XXr = 13;\n"
+      "  return foob\xec\x92\x81\xec\x92\x81r;\n"
+      "}\n";
+  chunk1[strlen(chunk1) - 1] = reference[0];
+  chunk2[0] = reference[1];
+  chunk2[1] = reference[2];
+  const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+}
+
+
+TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
+  // Another regression test, similar to the previous one. The difference is
+  // that the split character is not the last one in the sequence.
+  const char* reference = "\xec\x92\x81";
+  char chunk1[] =
+      "function foo() {\n"
+      "  // This function will contain an UTF-8 character which is not in\n"
+      "  // ASCII.\n"
+      "  var foobX";
+  char chunk2[] =
+      "XX\xec\x92\x81r = 13;\n"
+      "  return foob\xec\x92\x81\xec\x92\x81r;\n"
+      "}\n";
+  chunk1[strlen(chunk1) - 1] = reference[0];
+  chunk2[0] = reference[1];
+  chunk2[1] = reference[2];
+  const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
+}
+
+
+TEST(StreamingWithHarmonyScopes) {
+  // Don't use RunStreamingTest here so that both scripts get to use the same
+  // LocalContext and HandleScope.
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
 
-  // Create an ObjectTemplate for global objects and install access
-  // check callbacks that will block access.
-  v8::Handle<v8::ObjectTemplate> global_template =
-      v8::ObjectTemplate::New(isolate);
-  global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
-                                           IndexAccessAlwaysBlocked);
+  // First, run a script with a let variable.
+  CompileRun("\"use strict\"; let x = 1;");
+
+  // Then stream a script which (erroneously) tries to introduce the same
+  // variable again.
+  const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
+
+  v8::TryCatch try_catch(isolate);
+  v8::ScriptCompiler::StreamedSource source(
+      new TestSourceStream(chunks),
+      v8::ScriptCompiler::StreamedSource::ONE_BYTE);
+  v8::ScriptCompiler::ScriptStreamingTask* task =
+      v8::ScriptCompiler::StartStreamingScript(isolate, &source);
+  task->Run();
+  delete task;
+
+  // Parsing should succeed (the script will be parsed and compiled in a context
+  // independent way, so the error is not detected).
+  CHECK_EQ(false, try_catch.HasCaught());
+
+  v8::ScriptOrigin origin(v8_str("http://foo.com"));
+  char* full_source = TestSourceStream::FullSourceString(chunks);
+  v8::Handle<Script> script = v8::ScriptCompiler::Compile(
+      isolate, &source, v8_str(full_source), origin);
+  CHECK(!script.IsEmpty());
+  CHECK_EQ(false, try_catch.HasCaught());
+
+  // Running the script exposes the error.
+  v8::Handle<Value> result(script->Run());
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  delete[] full_source;
+}
 
-  // Create a context and set an x property on it's global object.
-  LocalContext context0(NULL, global_template);
-  v8::Handle<v8::Object> global0 = context0->Global();
-  global0->Set(v8_str("x"), v8_num(42));
-  ExpectString("JSON.stringify(this)", "{\"x\":42}");
 
-  for (int i = 0; i < 2; i++) {
-    if (i == 1) {
-      // Install a toJSON function on the second run.
-      v8::Handle<v8::FunctionTemplate> toJSON =
-          v8::FunctionTemplate::New(isolate, UnreachableCallback);
+TEST(CodeCache) {
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
 
-      global0->Set(v8_str("toJSON"), toJSON->GetFunction());
-    }
-    // Create a context with a different security token so that the
-    // failed access check callback will be called on each access.
-    LocalContext context1(NULL, global_template);
-    context1->Global()->Set(v8_str("other"), global0);
+  const char* source = "Math.sqrt(4)";
+  const char* origin = "code cache test";
+  v8::ScriptCompiler::CachedData* cache;
 
-    ExpectString("JSON.stringify(other)", "{}");
-    ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
-                 "{\"a\":{},\"b\":[\"c\"]}");
-    ExpectString("JSON.stringify([other, 'b', 'c'])",
-                 "[{},\"b\",\"c\"]");
+  v8::Isolate* isolate1 = v8::Isolate::New(create_params);
+  {
+    v8::Isolate::Scope iscope(isolate1);
+    v8::HandleScope scope(isolate1);
+    v8::Local<v8::Context> context = v8::Context::New(isolate1);
+    v8::Context::Scope cscope(context);
+    v8::Local<v8::String> source_string = v8_str(source);
+    v8::ScriptOrigin script_origin(v8_str(origin));
+    v8::ScriptCompiler::Source source(source_string, script_origin);
+    v8::ScriptCompiler::CompileOptions option =
+        v8::ScriptCompiler::kProduceCodeCache;
+    v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
+    int length = source.GetCachedData()->length;
+    uint8_t* cache_data = new uint8_t[length];
+    memcpy(cache_data, source.GetCachedData()->data, length);
+    cache = new v8::ScriptCompiler::CachedData(
+        cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
+  }
+  isolate1->Dispose();
 
-    v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
-    array->Set(0, v8_str("a"));
-    array->Set(1, v8_str("b"));
-    context1->Global()->Set(v8_str("array"), array);
-    ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
-    array->TurnOnAccessCheck();
-    ExpectString("JSON.stringify(array)", "[]");
-    ExpectString("JSON.stringify([array])", "[[]]");
-    ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
+  v8::Isolate* isolate2 = v8::Isolate::New(create_params);
+  {
+    v8::Isolate::Scope iscope(isolate2);
+    v8::HandleScope scope(isolate2);
+    v8::Local<v8::Context> context = v8::Context::New(isolate2);
+    v8::Context::Scope cscope(context);
+    v8::Local<v8::String> source_string = v8_str(source);
+    v8::ScriptOrigin script_origin(v8_str(origin));
+    v8::ScriptCompiler::Source source(source_string, script_origin, cache);
+    v8::ScriptCompiler::CompileOptions option =
+        v8::ScriptCompiler::kConsumeCodeCache;
+    v8::Local<v8::Script> script;
+    {
+      i::DisallowCompilation no_compile(
+          reinterpret_cast<i::Isolate*>(isolate2));
+      script = v8::ScriptCompiler::Compile(context, &source, option)
+                   .ToLocalChecked();
+    }
+    CHECK_EQ(2, script->Run()->ToInt32(isolate2)->Int32Value());
   }
+  isolate2->Dispose();
 }
 
 
-bool access_check_fail_thrown = false;
-bool catch_callback_called = false;
+void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
+  const char* garbage = "garbage garbage garbage garbage garbage garbage";
+  const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
+  int length = 16;
+  v8::ScriptCompiler::CachedData* cached_data =
+      new v8::ScriptCompiler::CachedData(data, length);
+  DCHECK(!cached_data->rejected);
+  v8::ScriptOrigin origin(v8_str("origin"));
+  v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
+  v8::Handle<v8::Script> script =
+      v8::ScriptCompiler::Compile(CcTest::isolate(), &source, option);
+  CHECK(cached_data->rejected);
+  CHECK_EQ(42, script->Run()->Int32Value());
+}
 
 
-// Failed access check callback that performs a GC on each invocation.
-void FailedAccessCheckThrows(Local<v8::Object> target,
-                             v8::AccessType type,
-                             Local<v8::Value> data) {
-  access_check_fail_thrown = true;
-  i::PrintF("Access check failed. Error thrown.\n");
-  CcTest::isolate()->ThrowException(
-      v8::Exception::Error(v8_str("cross context")));
+TEST(InvalidCacheData) {
+  v8::V8::Initialize();
+  v8::HandleScope scope(CcTest::isolate());
+  LocalContext context;
+  TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
+  TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
 }
 
 
-void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  for (int i = 0; i < args.Length(); i++) {
-    i::PrintF("%s\n", *String::Utf8Value(args[i]));
+TEST(ParserCacheRejectedGracefully) {
+  i::FLAG_min_preparse_length = 0;
+  v8::V8::Initialize();
+  v8::HandleScope scope(CcTest::isolate());
+  LocalContext context;
+  // Produce valid cached data.
+  v8::ScriptOrigin origin(v8_str("origin"));
+  v8::Local<v8::String> source_str = v8_str("function foo() {}");
+  v8::ScriptCompiler::Source source(source_str, origin);
+  v8::Handle<v8::Script> script = v8::ScriptCompiler::Compile(
+      CcTest::isolate(), &source, v8::ScriptCompiler::kProduceParserCache);
+  CHECK(!script.IsEmpty());
+  const v8::ScriptCompiler::CachedData* original_cached_data =
+      source.GetCachedData();
+  CHECK(original_cached_data != NULL);
+  CHECK(original_cached_data->data != NULL);
+  CHECK(!original_cached_data->rejected);
+  CHECK_GT(original_cached_data->length, 0);
+  // Recompiling the same script with it won't reject the data.
+  {
+    v8::ScriptCompiler::Source source_with_cached_data(
+        source_str, origin,
+        new v8::ScriptCompiler::CachedData(original_cached_data->data,
+                                           original_cached_data->length));
+    v8::Handle<v8::Script> script =
+        v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
+                                    v8::ScriptCompiler::kConsumeParserCache);
+    CHECK(!script.IsEmpty());
+    const v8::ScriptCompiler::CachedData* new_cached_data =
+        source_with_cached_data.GetCachedData();
+    CHECK(new_cached_data != NULL);
+    CHECK(!new_cached_data->rejected);
+  }
+  // Compile an incompatible script with the cached data. The new script doesn't
+  // have the same starting position for the function as the old one, so the old
+  // cached data will be incompatible with it and will be rejected.
+  {
+    v8::Local<v8::String> incompatible_source_str =
+        v8_str("   function foo() {}");
+    v8::ScriptCompiler::Source source_with_cached_data(
+        incompatible_source_str, origin,
+        new v8::ScriptCompiler::CachedData(original_cached_data->data,
+                                           original_cached_data->length));
+    v8::Handle<v8::Script> script =
+        v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
+                                    v8::ScriptCompiler::kConsumeParserCache);
+    CHECK(!script.IsEmpty());
+    const v8::ScriptCompiler::CachedData* new_cached_data =
+        source_with_cached_data.GetCachedData();
+    CHECK(new_cached_data != NULL);
+    CHECK(new_cached_data->rejected);
   }
-  catch_callback_called = true;
 }
 
 
-void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
+TEST(StringConcatOverflow) {
+  v8::V8::Initialize();
+  v8::HandleScope scope(CcTest::isolate());
+  RandomLengthOneByteResource* r =
+      new RandomLengthOneByteResource(i::String::kMaxLength);
+  v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), r);
+  CHECK(!str.IsEmpty());
+  v8::TryCatch try_catch(CcTest::isolate());
+  v8::Local<v8::String> result = v8::String::Concat(str, str);
+  CHECK(result.IsEmpty());
+  CHECK(!try_catch.HasCaught());
 }
 
 
-void CheckCorrectThrow(const char* script) {
-  // Test that the script, when wrapped into a try-catch, triggers the catch
-  // clause due to failed access check throwing an exception.
-  // The subsequent try-catch should run without any exception.
-  access_check_fail_thrown = false;
-  catch_callback_called = false;
-  i::ScopedVector<char> source(1024);
-  i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
-  CompileRun(source.start());
-  CHECK(access_check_fail_thrown);
-  CHECK(catch_callback_called);
+TEST(TurboAsmDisablesNeuter) {
+  v8::V8::Initialize();
+  v8::HandleScope scope(CcTest::isolate());
+  LocalContext context;
+#if V8_TURBOFAN_TARGET
+  bool should_be_neuterable = !i::FLAG_turbo_asm;
+#else
+  bool should_be_neuterable = true;
+#endif
+  const char* load =
+      "function Module(stdlib, foreign, heap) {"
+      "  'use asm';"
+      "  var MEM32 = new stdlib.Int32Array(heap);"
+      "  function load() { return MEM32[0]; }"
+      "  return { load: load };"
+      "}"
+      "var buffer = new ArrayBuffer(4);"
+      "Module(this, {}, buffer).load();"
+      "buffer";
+
+  i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
+  v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
+  CHECK_EQ(should_be_neuterable, result->IsNeuterable());
+
+  const char* store =
+      "function Module(stdlib, foreign, heap) {"
+      "  'use asm';"
+      "  var MEM32 = new stdlib.Int32Array(heap);"
+      "  function store() { MEM32[0] = 0; }"
+      "  return { store: store };"
+      "}"
+      "var buffer = new ArrayBuffer(4);"
+      "Module(this, {}, buffer).store();"
+      "buffer";
 
-  access_check_fail_thrown = false;
-  catch_callback_called = false;
-  CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
-  CHECK(!access_check_fail_thrown);
-  CHECK(!catch_callback_called);
+  i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
+  result = CompileRun(store).As<v8::ArrayBuffer>();
+  CHECK_EQ(should_be_neuterable, result->IsNeuterable());
 }
 
 
-TEST(AccessCheckThrows) {
+TEST(GetPrototypeAccessControl) {
   i::FLAG_allow_natives_syntax = true;
-  v8::V8::Initialize();
-  v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-
-  // Create an ObjectTemplate for global objects and install access
-  // check callbacks that will block access.
-  v8::Handle<v8::ObjectTemplate> global_template =
-      v8::ObjectTemplate::New(isolate);
-  global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
-                                           IndexAccessAlwaysBlocked);
-
-  // Create a context and set an x property on it's global object.
-  LocalContext context0(NULL, global_template);
-  context0->Global()->Set(v8_str("x"), v8_num(42));
-  v8::Handle<v8::Object> global0 = context0->Global();
-
-  // Create a context with a different security token so that the
-  // failed access check callback will be called on each access.
-  LocalContext context1(NULL, global_template);
-  context1->Global()->Set(v8_str("other"), global0);
-
-  v8::Handle<v8::FunctionTemplate> catcher_fun =
-      v8::FunctionTemplate::New(isolate, CatcherCallback);
-  context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
-
-  v8::Handle<v8::FunctionTemplate> has_own_property_fun =
-      v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
-  context1->Global()->Set(v8_str("has_own_property"),
-                          has_own_property_fun->GetFunction());
-
-  { v8::TryCatch try_catch;
-    access_check_fail_thrown = false;
-    CompileRun("other.x;");
-    CHECK(access_check_fail_thrown);
-    CHECK(try_catch.HasCaught());
-  }
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
 
-  CheckCorrectThrow("other.x");
-  CheckCorrectThrow("other[1]");
-  CheckCorrectThrow("JSON.stringify(other)");
-  CheckCorrectThrow("has_own_property(other, 'x')");
-  CheckCorrectThrow("%GetProperty(other, 'x')");
-  CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
-  CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
-  CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
-  CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
-  CheckCorrectThrow("%HasLocalProperty(other, 'x')");
-  CheckCorrectThrow("%HasProperty(other, 'x')");
-  CheckCorrectThrow("%HasElement(other, 1)");
-  CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
-  CheckCorrectThrow("%GetPropertyNames(other)");
-  // PROPERTY_ATTRIBUTES_NONE = 0
-  CheckCorrectThrow("%GetLocalPropertyNames(other, 0)");
-  CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
-                        "other, 'x', null, null, 1)");
+  v8::Handle<v8::ObjectTemplate> obj_template =
+      v8::ObjectTemplate::New(isolate);
+  obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
 
-  // Reset the failed access check callback so it does not influence
-  // the other tests.
-  v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
+  env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
+
+  {
+    v8::TryCatch try_catch(isolate);
+    CompileRun(
+        "function f() { %_GetPrototype(prohibited); }"
+        "%OptimizeFunctionOnNextCall(f);"
+        "f();");
+    CHECK(try_catch.HasCaught());
+  }
 }
 
 
-THREADED_TEST(Regress256330) {
+TEST(GetPrototypeHidden) {
   i::FLAG_allow_natives_syntax = true;
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
-  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
-  context->Global()->Set(v8_str("Bug"), templ->GetFunction());
-  CompileRun("\"use strict\"; var o = new Bug;"
-             "function f(o) { o.x = 10; };"
-             "f(o); f(o); f(o);"
-             "%OptimizeFunctionOnNextCall(f);"
-             "f(o);");
-  ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
+
+  Handle<FunctionTemplate> t = FunctionTemplate::New(isolate);
+  t->SetHiddenPrototype(true);
+  Handle<Object> proto = t->GetFunction()->NewInstance();
+  Handle<Object> object = Object::New(isolate);
+  Handle<Object> proto2 = Object::New(isolate);
+  object->SetPrototype(proto);
+  proto->SetPrototype(proto2);
+
+  env->Global()->Set(v8_str("object"), object);
+  env->Global()->Set(v8_str("proto"), proto);
+  env->Global()->Set(v8_str("proto2"), proto2);
+
+  v8::Handle<v8::Value> result = CompileRun("%_GetPrototype(object)");
+  CHECK(result->Equals(proto2));
+
+  result = CompileRun(
+      "function f() { return %_GetPrototype(object); }"
+      "%OptimizeFunctionOnNextCall(f);"
+      "f()");
+  CHECK(result->Equals(proto2));
 }
 
 
-THREADED_TEST(CrankshaftInterceptorSetter) {
-  i::FLAG_allow_natives_syntax = true;
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
-  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
-  CompileRun("var obj = new Obj;"
-             // Initialize fields to avoid transitions later.
-             "obj.age = 0;"
-             "obj.accessor_age = 42;"
-             "function setter(i) { this.accessor_age = i; };"
-             "function getter() { return this.accessor_age; };"
-             "function setAge(i) { obj.age = i; };"
-             "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
-             "setAge(1);"
-             "setAge(2);"
-             "setAge(3);"
-             "%OptimizeFunctionOnNextCall(setAge);"
-             "setAge(4);");
-  // All stores went through the interceptor.
-  ExpectInt32("obj.interceptor_age", 4);
-  ExpectInt32("obj.accessor_age", 42);
-}
-
-
-THREADED_TEST(CrankshaftInterceptorGetter) {
-  i::FLAG_allow_natives_syntax = true;
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
-  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
-  CompileRun("var obj = new Obj;"
-             // Initialize fields to avoid transitions later.
-             "obj.age = 1;"
-             "obj.accessor_age = 42;"
-             "function getter() { return this.accessor_age; };"
-             "function getAge() { return obj.interceptor_age; };"
-             "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
-             "getAge();"
-             "getAge();"
-             "getAge();"
-             "%OptimizeFunctionOnNextCall(getAge);");
-  // Access through interceptor.
-  ExpectInt32("getAge()", 1);
-}
-
-
-THREADED_TEST(CrankshaftInterceptorFieldRead) {
-  i::FLAG_allow_natives_syntax = true;
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
-  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
+TEST(ClassPrototypeCreationContext) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
   LocalContext env;
-  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
-  CompileRun("var obj = new Obj;"
-             "obj.__proto__.interceptor_age = 42;"
-             "obj.age = 100;"
-             "function getAge() { return obj.interceptor_age; };");
-  ExpectInt32("getAge();", 100);
-  ExpectInt32("getAge();", 100);
-  ExpectInt32("getAge();", 100);
-  CompileRun("%OptimizeFunctionOnNextCall(getAge);");
-  // Access through interceptor.
-  ExpectInt32("getAge();", 100);
+
+  Handle<Object> result = Handle<Object>::Cast(
+      CompileRun("'use strict'; class Example { }; Example.prototype"));
+  CHECK(env.local() == result->CreationContext());
 }
 
 
-THREADED_TEST(CrankshaftInterceptorFieldWrite) {
-  i::FLAG_allow_natives_syntax = true;
-  v8::HandleScope scope(CcTest::isolate());
-  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
-  AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
-  CompileRun("var obj = new Obj;"
-             "obj.age = 100000;"
-             "function setAge(i) { obj.age = i };"
-             "setAge(100);"
-             "setAge(101);"
-             "setAge(102);"
-             "%OptimizeFunctionOnNextCall(setAge);"
-             "setAge(103);");
-  ExpectInt32("obj.age", 100000);
-  ExpectInt32("obj.interceptor_age", 103);
+TEST(SimpleStreamingScriptWithSourceURL) {
+  const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
+                          "//# sourceURL=bar2.js\n", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
+                   "bar2.js");
 }
 
 
-class RequestInterruptTestBase {
- public:
-  RequestInterruptTestBase()
-      : env_(),
-        isolate_(env_->GetIsolate()),
-        sem_(0),
-        warmup_(20000),
-        should_continue_(true) {
+TEST(StreamingScriptWithSplitSourceURL) {
+  const char* chunks[] = {"function foo() { ret", "urn 13; } f",
+                          "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
+                   "bar2.js");
+}
+
+
+TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
+  const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
+                          " sourceMappingURL=bar2.js\n", "foo();", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
+                   "bar2.js");
+}
+
+
+TEST(NewStringRangeError) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  const int length = i::String::kMaxLength + 1;
+  const int buffer_size = length * sizeof(uint16_t);
+  void* buffer = malloc(buffer_size);
+  if (buffer == NULL) return;
+  memset(buffer, 'A', buffer_size);
+  {
+    v8::TryCatch try_catch(isolate);
+    char* data = reinterpret_cast<char*>(buffer);
+    CHECK(v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString,
+                                  length).IsEmpty());
+    CHECK(!try_catch.HasCaught());
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
+    CHECK(v8::String::NewFromOneByte(isolate, data, v8::String::kNormalString,
+                                     length).IsEmpty());
+    CHECK(!try_catch.HasCaught());
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
+    CHECK(v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString,
+                                     length).IsEmpty());
+    CHECK(!try_catch.HasCaught());
   }
+  free(buffer);
+}
 
-  virtual ~RequestInterruptTestBase() { }
 
-  virtual void TestBody() = 0;
+TEST(SealHandleScope) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
 
-  void RunTest() {
-    InterruptThread i_thread(this);
-    i_thread.Start();
+  v8::SealHandleScope seal(isolate);
 
-    v8::HandleScope handle_scope(isolate_);
+  // Should fail
+  v8::Local<v8::Object> obj = v8::Object::New(isolate);
 
-    TestBody();
+  USE(obj);
+}
 
-    isolate_->ClearInterrupt();
 
-    // Verify we arrived here because interruptor was called
-    // not due to a bug causing us to exit the loop too early.
-    CHECK(!should_continue());
-  }
+TEST(SealHandleScopeNested) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
 
-  void WakeUpInterruptor() {
-    sem_.Signal();
-  }
+  v8::SealHandleScope seal(isolate);
 
-  bool should_continue() const { return should_continue_; }
+  {
+    v8::HandleScope handle_scope(isolate);
 
-  bool ShouldContinue() {
-    if (warmup_ > 0) {
-      if (--warmup_ == 0) {
-        WakeUpInterruptor();
-      }
-    }
+    // Should work
+    v8::Local<v8::Object> obj = v8::Object::New(isolate);
 
-    return should_continue_;
+    USE(obj);
   }
+}
 
- protected:
-  static void ShouldContinueCallback(
-      const v8::FunctionCallbackInfo<Value>& info) {
-    RequestInterruptTestBase* test =
-        reinterpret_cast<RequestInterruptTestBase*>(
-            info.Data().As<v8::External>()->Value());
-    info.GetReturnValue().Set(test->ShouldContinue());
-  }
 
-  class InterruptThread : public i::Thread {
-   public:
-    explicit InterruptThread(RequestInterruptTestBase* test)
-        : Thread("RequestInterruptTest"), test_(test) {}
+static bool access_was_called = false;
 
-    virtual void Run() {
-      test_->sem_.Wait();
-      test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
-    }
 
-    static void OnInterrupt(v8::Isolate* isolate, void* data) {
-      reinterpret_cast<RequestInterruptTestBase*>(data)->
-          should_continue_ = false;
-    }
+static bool AccessAlwaysAllowedWithFlag(Local<v8::Object> global,
+                                        Local<Value> name, v8::AccessType type,
+                                        Local<Value> data) {
+  access_was_called = true;
+  return true;
+}
 
-   private:
-     RequestInterruptTestBase* test_;
-  };
 
-  LocalContext env_;
-  v8::Isolate* isolate_;
-  i::Semaphore sem_;
-  int warmup_;
-  bool should_continue_;
-};
+static bool AccessAlwaysBlockedWithFlag(Local<v8::Object> global,
+                                        Local<Value> name, v8::AccessType type,
+                                        Local<Value> data) {
+  access_was_called = true;
+  return false;
+}
 
 
-class RequestInterruptTestWithFunctionCall : public RequestInterruptTestBase {
- public:
-  virtual void TestBody() {
-    Local<Function> func = Function::New(
-        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
-    env_->Global()->Set(v8_str("ShouldContinue"), func);
+TEST(StrongModeAccessCheckAllowed) {
+  i::FLAG_strong_mode = true;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<Value> value;
+  access_was_called = false;
 
-    CompileRun("while (ShouldContinue()) { }");
-  }
-};
+  v8::Handle<v8::ObjectTemplate> obj_template =
+      v8::ObjectTemplate::New(isolate);
 
+  obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
+  obj_template->SetAccessCheckCallbacks(AccessAlwaysAllowedWithFlag, NULL);
 
-class RequestInterruptTestWithMethodCall : public RequestInterruptTestBase {
- public:
-  virtual void TestBody() {
-    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
-    v8::Local<v8::Template> proto = t->PrototypeTemplate();
-    proto->Set(v8_str("shouldContinue"), Function::New(
-        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
-    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
+  // Create an environment
+  v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
+  context0->Enter();
+  v8::Handle<v8::Object> global0 = context0->Global();
+  global0->Set(v8_str("object"), obj_template->NewInstance());
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.x");
+    CHECK(!try_catch.HasCaught());
+    CHECK(!access_was_called);
+    CHECK_EQ(42, value->Int32Value());
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.foo");
+    CHECK(try_catch.HasCaught());
+    CHECK(!access_was_called);
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object[10]");
+    CHECK(try_catch.HasCaught());
+    CHECK(!access_was_called);
+  }
 
-    CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
+  // Create an environment
+  v8::Local<Context> context1 = Context::New(isolate);
+  context1->Enter();
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("object"), obj_template->NewInstance());
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.x");
+    CHECK(!try_catch.HasCaught());
+    CHECK(access_was_called);
+    CHECK_EQ(42, value->Int32Value());
+  }
+  access_was_called = false;
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.foo");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
+  }
+  access_was_called = false;
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object[10]");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
   }
-};
 
+  context1->Exit();
+  context0->Exit();
+}
 
-class RequestInterruptTestWithAccessor : public RequestInterruptTestBase {
- public:
-  virtual void TestBody() {
-    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
-    v8::Local<v8::Template> proto = t->PrototypeTemplate();
-    proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
-        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
-    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
 
-    CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
-  }
-};
+TEST(StrongModeAccessCheckBlocked) {
+  i::FLAG_strong_mode = true;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<Value> value;
+  access_was_called = false;
 
+  v8::Handle<v8::ObjectTemplate> obj_template =
+      v8::ObjectTemplate::New(isolate);
 
-class RequestInterruptTestWithNativeAccessor : public RequestInterruptTestBase {
- public:
-  virtual void TestBody() {
-    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
-    t->InstanceTemplate()->SetNativeDataProperty(
-        v8_str("shouldContinue"),
-        &ShouldContinueNativeGetter,
-        NULL,
-        v8::External::New(isolate_, this));
-    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
+  obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
+  obj_template->SetAccessCheckCallbacks(AccessAlwaysBlockedWithFlag, NULL);
 
-    CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
+  // Create an environment
+  v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
+  context0->Enter();
+  v8::Handle<v8::Object> global0 = context0->Global();
+  global0->Set(v8_str("object"), obj_template->NewInstance());
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.x");
+    CHECK(!try_catch.HasCaught());
+    CHECK(!access_was_called);
+    CHECK_EQ(42, value->Int32Value());
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.foo");
+    CHECK(try_catch.HasCaught());
+    CHECK(!access_was_called);
+  }
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object[10]");
+    CHECK(try_catch.HasCaught());
+    CHECK(!access_was_called);
   }
 
- private:
-  static void ShouldContinueNativeGetter(
-      Local<String> property,
-      const v8::PropertyCallbackInfo<v8::Value>& info) {
-    RequestInterruptTestBase* test =
-        reinterpret_cast<RequestInterruptTestBase*>(
-            info.Data().As<v8::External>()->Value());
-    info.GetReturnValue().Set(test->ShouldContinue());
+  // Create an environment
+  v8::Local<Context> context1 = Context::New(isolate);
+  context1->Enter();
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("object"), obj_template->NewInstance());
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.x");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
+  }
+  access_was_called = false;
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object.foo");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
+  }
+  access_was_called = false;
+  {
+    v8::TryCatch try_catch(isolate);
+    value = CompileRun("'use strong'; object[10]");
+    CHECK(try_catch.HasCaught());
+    CHECK(access_was_called);
   }
-};
 
+  context1->Exit();
+  context0->Exit();
+}
 
-class RequestInterruptTestWithMethodCallAndInterceptor
-    : public RequestInterruptTestBase {
- public:
-  virtual void TestBody() {
-    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
-    v8::Local<v8::Template> proto = t->PrototypeTemplate();
-    proto->Set(v8_str("shouldContinue"), Function::New(
-        isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
-    v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
-    instance_template->SetNamedPropertyHandler(EmptyInterceptor);
 
-    env_->Global()->Set(v8_str("Klass"), t->GetFunction());
+TEST(StrongModeArityCallFromApi) {
+  i::FLAG_strong_mode = true;
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<Function> fun;
+  {
+    v8::TryCatch try_catch(isolate);
+    fun = Local<Function>::Cast(CompileRun(
+        "function f(x) { 'use strong'; }"
+        "f"));
 
-    CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
+    CHECK(!try_catch.HasCaught());
   }
 
- private:
-  static void EmptyInterceptor(
-      Local<String> property,
-      const v8::PropertyCallbackInfo<v8::Value>& info) {
+  {
+    v8::TryCatch try_catch(isolate);
+    fun->Call(v8::Undefined(isolate), 0, nullptr);
+    CHECK(try_catch.HasCaught());
   }
-};
 
+  {
+    v8::TryCatch try_catch(isolate);
+    v8::Handle<Value> args[] = {v8_num(42)};
+    fun->Call(v8::Undefined(isolate), arraysize(args), args);
+    CHECK(!try_catch.HasCaught());
+  }
 
-class RequestInterruptTestWithMathAbs : public RequestInterruptTestBase {
- public:
-  virtual void TestBody() {
-    env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
-        isolate_,
-        WakeUpInterruptorCallback,
-        v8::External::New(isolate_, this)));
+  {
+    v8::TryCatch try_catch(isolate);
+    v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
+    fun->Call(v8::Undefined(isolate), arraysize(args), args);
+    CHECK(!try_catch.HasCaught());
+  }
+}
 
-    env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
-        isolate_,
-        ShouldContinueCallback,
-        v8::External::New(isolate_, this)));
 
-    i::FLAG_allow_natives_syntax = true;
-    CompileRun("function loopish(o) {"
-               "  var pre = 10;"
-               "  while (o.abs(1) > 0) {"
-               "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
-               "    if (pre > 0) {"
-               "      if (--pre === 0) WakeUpInterruptor(o === Math);"
-               "    }"
-               "  }"
-               "}"
-               "var i = 50;"
-               "var obj = {abs: function () { return i-- }, x: null};"
-               "delete obj.x;"
-               "loopish(obj);"
-               "%OptimizeFunctionOnNextCall(loopish);"
-               "loopish(Math);");
+TEST(StrongModeArityCallFromApi2) {
+  i::FLAG_strong_mode = true;
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<Function> fun;
+  {
+    v8::TryCatch try_catch(isolate);
+    fun = Local<Function>::Cast(CompileRun(
+        "'use strong';"
+        "function f(x) {}"
+        "f"));
 
-    i::FLAG_allow_natives_syntax = false;
+    CHECK(!try_catch.HasCaught());
   }
 
- private:
-  static void WakeUpInterruptorCallback(
-      const v8::FunctionCallbackInfo<Value>& info) {
-    if (!info[0]->BooleanValue()) return;
+  {
+    v8::TryCatch try_catch(isolate);
+    fun->Call(v8::Undefined(isolate), 0, nullptr);
+    CHECK(try_catch.HasCaught());
+  }
 
-    RequestInterruptTestBase* test =
-        reinterpret_cast<RequestInterruptTestBase*>(
-            info.Data().As<v8::External>()->Value());
-    test->WakeUpInterruptor();
+  {
+    v8::TryCatch try_catch(isolate);
+    v8::Handle<Value> args[] = {v8_num(42)};
+    fun->Call(v8::Undefined(isolate), arraysize(args), args);
+    CHECK(!try_catch.HasCaught());
   }
 
-  static void ShouldContinueCallback(
-      const v8::FunctionCallbackInfo<Value>& info) {
-    RequestInterruptTestBase* test =
-        reinterpret_cast<RequestInterruptTestBase*>(
-            info.Data().As<v8::External>()->Value());
-    info.GetReturnValue().Set(test->should_continue());
+  {
+    v8::TryCatch try_catch(isolate);
+    v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
+    fun->Call(v8::Undefined(isolate), arraysize(args), args);
+    CHECK(!try_catch.HasCaught());
   }
-};
+}
 
 
-TEST(RequestInterruptTestWithFunctionCall) {
-  RequestInterruptTestWithFunctionCall().RunTest();
+TEST(StrongObjectDelete) {
+  i::FLAG_strong_mode = true;
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<Object> obj;
+  {
+    v8::TryCatch try_catch;
+    obj = Local<Object>::Cast(CompileRun(
+        "'use strong';"
+        "({});"));
+    CHECK(!try_catch.HasCaught());
+  }
+  obj->ForceSet(v8_str("foo"), v8_num(1), v8::None);
+  obj->ForceSet(v8_str("2"), v8_num(1), v8::None);
+  CHECK(obj->HasOwnProperty(v8_str("foo")));
+  CHECK(obj->HasOwnProperty(v8_str("2")));
+  CHECK(!obj->Delete(v8_str("foo")));
+  CHECK(!obj->Delete(2));
 }
 
 
-TEST(RequestInterruptTestWithMethodCall) {
-  RequestInterruptTestWithMethodCall().RunTest();
+static void ExtrasExportsTestRuntimeFunction(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  CHECK_EQ(3, args[0]->Int32Value());
+  args.GetReturnValue().Set(v8_num(7));
 }
 
 
-TEST(RequestInterruptTestWithAccessor) {
-  RequestInterruptTestWithAccessor().RunTest();
-}
+TEST(ExtrasExportsObject) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
 
+  // standalone.gypi ensures we include the test-extra.js file, which should
+  // export the tested functions.
+  v8::Local<v8::Object> exports = env->GetExtrasExportsObject();
 
-TEST(RequestInterruptTestWithNativeAccessor) {
-  RequestInterruptTestWithNativeAccessor().RunTest();
+  auto func =
+      exports->Get(v8_str("testExtraShouldReturnFive")).As<v8::Function>();
+  auto undefined = v8::Undefined(isolate);
+  auto result = func->Call(undefined, 0, {}).As<v8::Number>();
+  CHECK_EQ(5, result->Int32Value());
+
+  v8::Handle<v8::FunctionTemplate> runtimeFunction =
+      v8::FunctionTemplate::New(isolate, ExtrasExportsTestRuntimeFunction);
+  exports->Set(v8_str("runtime"), runtimeFunction->GetFunction());
+  func =
+      exports->Get(v8_str("testExtraShouldCallToRuntime")).As<v8::Function>();
+  result = func->Call(undefined, 0, {}).As<v8::Number>();
+  CHECK_EQ(7, result->Int32Value());
 }
 
 
-TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
-  RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
-}
+TEST(Map) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
 
+  v8::Local<v8::Map> map = v8::Map::New(isolate);
+  CHECK(map->IsObject());
+  CHECK(map->IsMap());
+  CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
+  CHECK_EQ(0U, map->Size());
 
-TEST(RequestInterruptTestWithMathAbs) {
-  RequestInterruptTestWithMathAbs().RunTest();
-}
+  v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
+  CHECK(val->IsMap());
+  map = v8::Local<v8::Map>::Cast(val);
+  CHECK_EQ(2U, map->Size());
 
+  v8::Local<v8::Array> contents = map->AsArray();
+  CHECK_EQ(4U, contents->Length());
+  CHECK_EQ(1, contents->Get(0).As<v8::Int32>()->Value());
+  CHECK_EQ(2, contents->Get(1).As<v8::Int32>()->Value());
+  CHECK_EQ(3, contents->Get(2).As<v8::Int32>()->Value());
+  CHECK_EQ(4, contents->Get(3).As<v8::Int32>()->Value());
 
-static Local<Value> function_new_expected_env;
-static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
-  CHECK_EQ(function_new_expected_env, info.Data());
-  info.GetReturnValue().Set(17);
+  map = v8::Map::FromArray(env.local(), contents).ToLocalChecked();
+  CHECK_EQ(2U, map->Size());
+
+  CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
+  CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
+
+  CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
+  CHECK(!map->Has(env.local(), map).FromJust());
+
+  CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
+                  .ToLocalChecked()
+                  ->Int32Value());
+  CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
+                  .ToLocalChecked()
+                  ->Int32Value());
+
+  CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
+            .ToLocalChecked()
+            ->IsUndefined());
+
+  CHECK(!map->Set(env.local(), map, map).IsEmpty());
+  CHECK_EQ(3U, map->Size());
+  CHECK(map->Has(env.local(), map).FromJust());
+
+  CHECK(map->Delete(env.local(), map).FromJust());
+  CHECK_EQ(2U, map->Size());
+  CHECK(!map->Has(env.local(), map).FromJust());
+  CHECK(!map->Delete(env.local(), map).FromJust());
+
+  map->Clear();
+  CHECK_EQ(0U, map->Size());
 }
 
 
-THREADED_TEST(FunctionNew) {
+TEST(MapFromArrayOddLength) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
   LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-  Local<Object> data = v8::Object::New(isolate);
-  function_new_expected_env = data;
-  Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
-  env->Global()->Set(v8_str("func"), func);
-  Local<Value> result = CompileRun("func();");
-  CHECK_EQ(v8::Integer::New(isolate, 17), result);
-  // Verify function not cached
-  int serial_number =
-      i::Smi::cast(v8::Utils::OpenHandle(*func)
-          ->shared()->get_api_func_data()->serial_number())->value();
-  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  i::Object* elm = i_isolate->native_context()->function_cache()
-      ->GetElementNoExceptionThrown(i_isolate, serial_number);
-  CHECK(elm->IsUndefined());
-  // Verify that each Function::New creates a new function instance
-  Local<Object> data2 = v8::Object::New(isolate);
-  function_new_expected_env = data2;
-  Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
-  CHECK(!func2->IsNull());
-  CHECK_NE(func, func2);
-  env->Global()->Set(v8_str("func2"), func2);
-  Local<Value> result2 = CompileRun("func2();");
-  CHECK_EQ(v8::Integer::New(isolate, 17), result2);
+  // Odd lengths result in a null MaybeLocal.
+  Local<v8::Array> contents = v8::Array::New(isolate, 41);
+  CHECK(v8::Map::FromArray(env.local(), contents).IsEmpty());
 }
 
 
-TEST(EscapeableHandleScope) {
-  HandleScope outer_scope(CcTest::isolate());
-  LocalContext context;
-  const int runs = 10;
-  Local<String> values[runs];
-  for (int i = 0; i < runs; i++) {
-    v8::EscapableHandleScope inner_scope(CcTest::isolate());
-    Local<String> value;
-    if (i != 0) value = v8_str("escape value");
-    values[i] = inner_scope.Escape(value);
-  }
-  for (int i = 0; i < runs; i++) {
-    Local<String> expected;
-    if (i != 0) {
-      CHECK_EQ(v8_str("escape value"), values[i]);
-    } else {
-      CHECK(values[i].IsEmpty());
-    }
-  }
-}
+TEST(Set) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
 
+  v8::Local<v8::Set> set = v8::Set::New(isolate);
+  CHECK(set->IsObject());
+  CHECK(set->IsSet());
+  CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
+  CHECK_EQ(0U, set->Size());
 
-static void SetterWhichExpectsThisAndHolderToDiffer(
-    Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
-  CHECK(info.Holder() != info.This());
-}
+  v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
+  CHECK(val->IsSet());
+  set = v8::Local<v8::Set>::Cast(val);
+  CHECK_EQ(2U, set->Size());
 
+  v8::Local<v8::Array> keys = set->AsArray();
+  CHECK_EQ(2U, keys->Length());
+  CHECK_EQ(1, keys->Get(0).As<v8::Int32>()->Value());
+  CHECK_EQ(2, keys->Get(1).As<v8::Int32>()->Value());
 
-TEST(Regress239669) {
-  LocalContext context;
-  v8::Isolate* isolate = context->GetIsolate();
-  v8::HandleScope scope(isolate);
-  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
-  templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
-  context->Global()->Set(v8_str("P"), templ->NewInstance());
-  CompileRun(
-      "function C1() {"
-      "  this.x = 23;"
-      "};"
-      "C1.prototype = P;"
-      "for (var i = 0; i < 4; i++ ) {"
-      "  new C1();"
-      "}");
+  set = v8::Set::FromArray(env.local(), keys).ToLocalChecked();
+  CHECK_EQ(2U, set->Size());
+
+  CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
+  CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
+
+  CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
+  CHECK(!set->Has(env.local(), set).FromJust());
+
+  CHECK(!set->Add(env.local(), set).IsEmpty());
+  CHECK_EQ(3U, set->Size());
+  CHECK(set->Has(env.local(), set).FromJust());
+
+  CHECK(set->Delete(env.local(), set).FromJust());
+  CHECK_EQ(2U, set->Size());
+  CHECK(!set->Has(env.local(), set).FromJust());
+  CHECK(!set->Delete(env.local(), set).FromJust());
+
+  set->Clear();
+  CHECK_EQ(0U, set->Size());
 }
 
 
-class ApiCallOptimizationChecker {
- private:
-  static Local<Object> data;
-  static Local<Object> receiver;
-  static Local<Object> holder;
-  static Local<Object> callee;
-  static int count;
+TEST(CompatibleReceiverCheckOnCachedICHandler) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
+  v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
+  auto returns_42 =
+      v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
+  parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
+  v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
+  child->Inherit(parent);
+  LocalContext env;
+  env->Global()->Set(v8_str("Child"), child->GetFunction());
 
-  static void OptimizationCallback(
-      const v8::FunctionCallbackInfo<v8::Value>& info) {
-    CHECK(callee == info.Callee());
-    CHECK(data == info.Data());
-    CHECK(receiver == info.This());
-    if (info.Length() == 1) {
-      CHECK_EQ(v8_num(1), info[0]);
-    }
-    CHECK(holder == info.Holder());
-    count++;
-  }
+  // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
+  CompileRun(
+      "var real = new Child();\n"
+      "for (var i = 0; i < 3; ++i) {\n"
+      "  real.age;\n"
+      "}\n");
 
-  // TODO(dcarney): move this to v8.h
-  static void SetAccessorProperty(Local<Object> object,
-                                  Local<String> name,
-                                  Local<Function> getter,
-                                  Local<Function> setter = Local<Function>()) {
-    i::Isolate* isolate = CcTest::i_isolate();
-    v8::AccessControl settings = v8::DEFAULT;
-    v8::PropertyAttribute attribute = v8::None;
-    i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter);
-    i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true);
-    if (setter_i.is_null()) setter_i = isolate->factory()->null_value();
-    i::JSObject::DefineAccessor(v8::Utils::OpenHandle(*object),
-                                v8::Utils::OpenHandle(*name),
-                                getter_i,
-                                setter_i,
-                                static_cast<PropertyAttributes>(attribute),
-                                settings);
-  }
-
-  public:
-    void Run(bool use_signature, bool global) {
-      v8::Isolate* isolate = CcTest::isolate();
-      v8::HandleScope scope(isolate);
-      // Build a template for signature checks.
-      Local<v8::ObjectTemplate> signature_template;
-      Local<v8::Signature> signature;
-      {
-        Local<v8::FunctionTemplate> parent_template =
-          FunctionTemplate::New(isolate);
-        parent_template->SetHiddenPrototype(true);
-        Local<v8::FunctionTemplate> function_template
-            = FunctionTemplate::New(isolate);
-        function_template->Inherit(parent_template);
-        if (use_signature) {
-          signature = v8::Signature::New(isolate, parent_template);
-        }
-        signature_template = function_template->InstanceTemplate();
-      }
-      // Global object must pass checks.
-      Local<v8::Context> context =
-          v8::Context::New(isolate, NULL, signature_template);
-      v8::Context::Scope context_scope(context);
-      // Install regular object that can pass signature checks.
-      Local<Object> function_receiver = signature_template->NewInstance();
-      context->Global()->Set(v8_str("function_receiver"), function_receiver);
-      // Get the holder objects.
-      Local<Object> inner_global =
-          Local<Object>::Cast(context->Global()->GetPrototype());
-      Local<Object> function_holder =
-          Local<Object>::Cast(function_receiver->GetPrototype());
-      // Install function on hidden prototype object.
-      data = Object::New(isolate);
-      Local<FunctionTemplate> function_template = FunctionTemplate::New(
-          isolate, OptimizationCallback, data, signature);
-      Local<Function> function = function_template->GetFunction();
-      Local<Object> global_holder = Local<Object>::Cast(
-          inner_global->GetPrototype());
-      global_holder->Set(v8_str("g_f"), function);
-      SetAccessorProperty(global_holder, v8_str("g_acc"), function, function);
-      function_holder->Set(v8_str("f"), function);
-      SetAccessorProperty(function_holder, v8_str("acc"), function, function);
-      // Initialize expected values.
-      callee = function;
-      count = 0;
-      if (global) {
-        receiver = context->Global();
-        holder = inner_global;
-      } else {
-        holder = function_receiver;
-        // If not using a signature, add something else to the prototype chain
-        // to test the case that holder != receiver
-        if (!use_signature) {
-          receiver = Local<Object>::Cast(CompileRun(
-              "var receiver_subclass = {};\n"
-              "receiver_subclass.__proto__ = function_receiver;\n"
-              "receiver_subclass"));
-        } else {
-          receiver = Local<Object>::Cast(CompileRun(
-            "var receiver_subclass = function_receiver;\n"
-            "receiver_subclass"));
-        }
-      }
-      // With no signature, the holder is not set.
-      if (!use_signature) holder = receiver;
-      // build wrap_function
-      int key = (use_signature ? 1 : 0) + 2 * (global ? 1 : 0);
-      i::ScopedVector<char> wrap_function(200);
-      if (global) {
-        i::OS::SNPrintF(
-            wrap_function,
-            "function wrap_f_%d() { var f = g_f; return f(); }\n"
-            "function wrap_get_%d() { return this.g_acc; }\n"
-            "function wrap_set_%d() { this.g_acc = 1; }\n",
-            key, key, key);
-      } else {
-        i::OS::SNPrintF(
-            wrap_function,
-            "function wrap_f_%d() { return receiver_subclass.f(); }\n"
-            "function wrap_get_%d() { return receiver_subclass.acc; }\n"
-            "function wrap_set_%d() { receiver_subclass.acc = 1; }\n",
-            key, key, key);
-      }
-      // build source string
-      i::ScopedVector<char> source(500);
-      i::OS::SNPrintF(
-          source,
-          "%s\n"  // wrap functions
-          "function wrap_f() { wrap_f_%d(); }\n"
-          "function wrap_get() { wrap_get_%d(); }\n"
-          "function wrap_set() { wrap_set_%d(); }\n"
-          "\n"
-          "wrap_f();\n"
-          "wrap_f();\n"
-          "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
-          "wrap_f();\n"
-          "\n"
-          "wrap_get();\n"
-          "wrap_get();\n"
-          "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
-          "wrap_get();\n"
-          "\n"
-          "wrap_set();\n"
-          "wrap_set();\n"
-          "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
-          "wrap_set();\n",
-          wrap_function.start(), key, key, key, key, key, key);
-      v8::TryCatch try_catch;
-      CompileRun(source.start());
-      ASSERT(!try_catch.HasCaught());
-      CHECK_EQ(9, count);
-    }
-};
+  // Check that the cached stub is never used.
+  ExpectInt32(
+      "var fake = Object.create(Child.prototype);\n"
+      "var result = 0;\n"
+      "function test(d) {\n"
+      "  if (d == 3) return;\n"
+      "  try {\n"
+      "    fake.age;\n"
+      "    result = 1;\n"
+      "  } catch (e) {\n"
+      "  }\n"
+      "  test(d+1);\n"
+      "}\n"
+      "test(0);\n"
+      "result;\n",
+      0);
+}
 
 
-Local<Object> ApiCallOptimizationChecker::data;
-Local<Object> ApiCallOptimizationChecker::receiver;
-Local<Object> ApiCallOptimizationChecker::holder;
-Local<Object> ApiCallOptimizationChecker::callee;
-int ApiCallOptimizationChecker::count = 0;
+static int nb_uncaught_exception_callback_calls = 0;
 
 
-TEST(TestFunctionCallOptimization) {
-  i::FLAG_allow_natives_syntax = true;
-  ApiCallOptimizationChecker checker;
-  checker.Run(true, true);
-  checker.Run(false, true);
-  checker.Run(true, false);
-  checker.Run(false, false);
+bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
+  ++nb_uncaught_exception_callback_calls;
+  return false;
 }
 
 
-TEST(Regress354123) {
-  LocalContext current;
-  v8::Isolate* isolate = current->GetIsolate();
-  v8::HandleScope scope(isolate);
+TEST(AbortOnUncaughtExceptionNoAbort) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<v8::ObjectTemplate> global_template =
+      v8::ObjectTemplate::New(isolate);
+  LocalContext env(NULL, global_template);
 
-  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
-  templ->SetAccessCheckCallbacks(NamedAccessCounter, IndexedAccessCounter);
-  current->Global()->Set(v8_str("friend"), templ->NewInstance());
+  i::FLAG_abort_on_uncaught_exception = true;
+  isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
 
-  // Test access using __proto__ from the prototype chain.
-  named_access_count = 0;
-  CompileRun("friend.__proto__ = {};");
-  CHECK_EQ(2, named_access_count);
-  CompileRun("friend.__proto__;");
-  CHECK_EQ(4, named_access_count);
+  CompileRun("function boom() { throw new Error(\"boom\") }");
 
-  // Test access using __proto__ as a hijacked function (A).
-  named_access_count = 0;
-  CompileRun("var p = Object.prototype;"
-             "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
-             "f.call(friend, {});");
-  CHECK_EQ(1, named_access_count);
-  CompileRun("var p = Object.prototype;"
-             "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
-             "f.call(friend);");
-  CHECK_EQ(2, named_access_count);
+  v8::Local<v8::Object> global_object = env->Global();
+  v8::Local<v8::Function> foo =
+      v8::Local<v8::Function>::Cast(global_object->Get(v8_str("boom")));
 
-  // Test access using __proto__ as a hijacked function (B).
-  named_access_count = 0;
-  CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
-             "f.call(friend, {});");
-  CHECK_EQ(1, named_access_count);
-  CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
-             "f.call(friend);");
-  CHECK_EQ(2, named_access_count);
+  foo->Call(global_object, 0, NULL);
 
-  // Test access using Object.setPrototypeOf reflective method.
-  named_access_count = 0;
-  CompileRun("Object.setPrototypeOf(friend, {});");
-  CHECK_EQ(1, named_access_count);
-  CompileRun("Object.getPrototypeOf(friend);");
-  CHECK_EQ(2, named_access_count);
+  CHECK_EQ(1, nb_uncaught_exception_callback_calls);
 }