Home | History | Annotate | Download | only in cctest
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <climits>
     29 #include <csignal>
     30 #include <map>
     31 #include <string>
     32 
     33 #include "src/v8.h"
     34 
     35 #if V8_OS_POSIX
     36 #include <unistd.h>  // NOLINT
     37 #endif
     38 
     39 #include "include/v8-util.h"
     40 #include "src/api.h"
     41 #include "src/arguments.h"
     42 #include "src/base/platform/platform.h"
     43 #include "src/compilation-cache.h"
     44 #include "src/cpu-profiler.h"
     45 #include "src/execution.h"
     46 #include "src/isolate.h"
     47 #include "src/objects.h"
     48 #include "src/parser.h"
     49 #include "src/snapshot.h"
     50 #include "src/unicode-inl.h"
     51 #include "src/utils.h"
     52 #include "src/vm-state.h"
     53 #include "test/cctest/cctest.h"
     54 
     55 static const bool kLogThreading = false;
     56 
     57 using ::v8::Boolean;
     58 using ::v8::BooleanObject;
     59 using ::v8::Context;
     60 using ::v8::Extension;
     61 using ::v8::Function;
     62 using ::v8::FunctionTemplate;
     63 using ::v8::Handle;
     64 using ::v8::HandleScope;
     65 using ::v8::Local;
     66 using ::v8::Name;
     67 using ::v8::Message;
     68 using ::v8::MessageCallback;
     69 using ::v8::Object;
     70 using ::v8::ObjectTemplate;
     71 using ::v8::Persistent;
     72 using ::v8::Script;
     73 using ::v8::StackTrace;
     74 using ::v8::String;
     75 using ::v8::Symbol;
     76 using ::v8::TryCatch;
     77 using ::v8::Undefined;
     78 using ::v8::UniqueId;
     79 using ::v8::V8;
     80 using ::v8::Value;
     81 
     82 
     83 #define THREADED_PROFILED_TEST(Name)                                 \
     84   static void Test##Name();                                          \
     85   TEST(Name##WithProfiler) {                                         \
     86     RunWithProfiler(&Test##Name);                                    \
     87   }                                                                  \
     88   THREADED_TEST(Name)
     89 
     90 
     91 void RunWithProfiler(void (*test)()) {
     92   LocalContext env;
     93   v8::HandleScope scope(env->GetIsolate());
     94   v8::Local<v8::String> profile_name =
     95       v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
     96   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
     97 
     98   cpu_profiler->StartProfiling(profile_name);
     99   (*test)();
    100   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
    101 }
    102 
    103 
    104 static int signature_callback_count;
    105 static Local<Value> signature_expected_receiver;
    106 static void IncrementingSignatureCallback(
    107     const v8::FunctionCallbackInfo<v8::Value>& args) {
    108   ApiTestFuzzer::Fuzz();
    109   signature_callback_count++;
    110   CHECK_EQ(signature_expected_receiver, args.Holder());
    111   CHECK_EQ(signature_expected_receiver, args.This());
    112   v8::Handle<v8::Array> result =
    113       v8::Array::New(args.GetIsolate(), args.Length());
    114   for (int i = 0; i < args.Length(); i++)
    115     result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
    116   args.GetReturnValue().Set(result);
    117 }
    118 
    119 
    120 static void SignatureCallback(
    121     const v8::FunctionCallbackInfo<v8::Value>& args) {
    122   ApiTestFuzzer::Fuzz();
    123   v8::Handle<v8::Array> result =
    124       v8::Array::New(args.GetIsolate(), args.Length());
    125   for (int i = 0; i < args.Length(); i++) {
    126     result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
    127   }
    128   args.GetReturnValue().Set(result);
    129 }
    130 
    131 
    132 // Tests that call v8::V8::Dispose() cannot be threaded.
    133 UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
    134   CHECK(v8::V8::Initialize());
    135   CHECK(v8::V8::Dispose());
    136 }
    137 
    138 
    139 // Tests that call v8::V8::Dispose() cannot be threaded.
    140 UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
    141   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    142   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
    143   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    144   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
    145   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    146 }
    147 
    148 
    149 THREADED_TEST(Handles) {
    150   v8::HandleScope scope(CcTest::isolate());
    151   Local<Context> local_env;
    152   {
    153     LocalContext env;
    154     local_env = env.local();
    155   }
    156 
    157   // Local context should still be live.
    158   CHECK(!local_env.IsEmpty());
    159   local_env->Enter();
    160 
    161   v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
    162   CHECK(!undef.IsEmpty());
    163   CHECK(undef->IsUndefined());
    164 
    165   const char* source = "1 + 2 + 3";
    166   Local<Script> script = v8_compile(source);
    167   CHECK_EQ(6, script->Run()->Int32Value());
    168 
    169   local_env->Exit();
    170 }
    171 
    172 
    173 THREADED_TEST(IsolateOfContext) {
    174   v8::HandleScope scope(CcTest::isolate());
    175   v8::Handle<Context> env = Context::New(CcTest::isolate());
    176 
    177   CHECK(!env->GetIsolate()->InContext());
    178   CHECK(env->GetIsolate() == CcTest::isolate());
    179   env->Enter();
    180   CHECK(env->GetIsolate()->InContext());
    181   CHECK(env->GetIsolate() == CcTest::isolate());
    182   env->Exit();
    183   CHECK(!env->GetIsolate()->InContext());
    184   CHECK(env->GetIsolate() == CcTest::isolate());
    185 }
    186 
    187 
    188 static void TestSignature(const char* loop_js, Local<Value> receiver) {
    189   i::ScopedVector<char> source(200);
    190   i::SNPrintF(source,
    191               "for (var i = 0; i < 10; i++) {"
    192               "  %s"
    193               "}",
    194               loop_js);
    195   signature_callback_count = 0;
    196   signature_expected_receiver = receiver;
    197   bool expected_to_throw = receiver.IsEmpty();
    198   v8::TryCatch try_catch;
    199   CompileRun(source.start());
    200   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
    201   if (!expected_to_throw) {
    202     CHECK_EQ(10, signature_callback_count);
    203   } else {
    204     CHECK_EQ(v8_str("TypeError: Illegal invocation"),
    205              try_catch.Exception()->ToString());
    206   }
    207 }
    208 
    209 
    210 THREADED_TEST(ReceiverSignature) {
    211   LocalContext env;
    212   v8::Isolate* isolate = env->GetIsolate();
    213   v8::HandleScope scope(isolate);
    214   // Setup templates.
    215   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
    216   v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
    217   v8::Handle<v8::FunctionTemplate> callback_sig =
    218       v8::FunctionTemplate::New(
    219           isolate, IncrementingSignatureCallback, Local<Value>(), sig);
    220   v8::Handle<v8::FunctionTemplate> callback =
    221       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
    222   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
    223   sub_fun->Inherit(fun);
    224   v8::Handle<v8::FunctionTemplate> unrel_fun =
    225       v8::FunctionTemplate::New(isolate);
    226   // Install properties.
    227   v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
    228   fun_proto->Set(v8_str("prop_sig"), callback_sig);
    229   fun_proto->Set(v8_str("prop"), callback);
    230   fun_proto->SetAccessorProperty(
    231       v8_str("accessor_sig"), callback_sig, callback_sig);
    232   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
    233   // Instantiate templates.
    234   Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
    235   Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
    236   // Setup global variables.
    237   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
    238   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
    239   env->Global()->Set(v8_str("fun_instance"), fun_instance);
    240   env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
    241   CompileRun(
    242       "var accessor_sig_key = 'accessor_sig';"
    243       "var accessor_key = 'accessor';"
    244       "var prop_sig_key = 'prop_sig';"
    245       "var prop_key = 'prop';"
    246       ""
    247       "function copy_props(obj) {"
    248       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
    249       "  var source = Fun.prototype;"
    250       "  for (var i in keys) {"
    251       "    var key = keys[i];"
    252       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
    253       "    Object.defineProperty(obj, key, desc);"
    254       "  }"
    255       "}"
    256       ""
    257       "var obj = {};"
    258       "copy_props(obj);"
    259       "var unrel = new UnrelFun();"
    260       "copy_props(unrel);");
    261   // Test with and without ICs
    262   const char* test_objects[] = {
    263       "fun_instance", "sub_fun_instance", "obj", "unrel" };
    264   unsigned bad_signature_start_offset = 2;
    265   for (unsigned i = 0; i < arraysize(test_objects); i++) {
    266     i::ScopedVector<char> source(200);
    267     i::SNPrintF(
    268         source, "var test_object = %s; test_object", test_objects[i]);
    269     Local<Value> test_object = CompileRun(source.start());
    270     TestSignature("test_object.prop();", test_object);
    271     TestSignature("test_object.accessor;", test_object);
    272     TestSignature("test_object[accessor_key];", test_object);
    273     TestSignature("test_object.accessor = 1;", test_object);
    274     TestSignature("test_object[accessor_key] = 1;", test_object);
    275     if (i >= bad_signature_start_offset) test_object = Local<Value>();
    276     TestSignature("test_object.prop_sig();", test_object);
    277     TestSignature("test_object.accessor_sig;", test_object);
    278     TestSignature("test_object[accessor_sig_key];", test_object);
    279     TestSignature("test_object.accessor_sig = 1;", test_object);
    280     TestSignature("test_object[accessor_sig_key] = 1;", test_object);
    281   }
    282 }
    283 
    284 
    285 THREADED_TEST(ArgumentSignature) {
    286   LocalContext env;
    287   v8::Isolate* isolate = env->GetIsolate();
    288   v8::HandleScope scope(isolate);
    289   v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New(isolate);
    290   cons->SetClassName(v8_str("Cons"));
    291   v8::Handle<v8::Signature> sig = v8::Signature::New(
    292       isolate, v8::Handle<v8::FunctionTemplate>(), 1, &cons);
    293   v8::Handle<v8::FunctionTemplate> fun =
    294       v8::FunctionTemplate::New(isolate,
    295                                 SignatureCallback,
    296                                 v8::Handle<Value>(),
    297                                 sig);
    298   env->Global()->Set(v8_str("Cons"), cons->GetFunction());
    299   env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
    300 
    301   v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
    302   CHECK(value1->IsTrue());
    303 
    304   v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
    305   CHECK(value2->IsTrue());
    306 
    307   v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
    308   CHECK(value3->IsTrue());
    309 
    310   v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New(isolate);
    311   cons1->SetClassName(v8_str("Cons1"));
    312   v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New(isolate);
    313   cons2->SetClassName(v8_str("Cons2"));
    314   v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New(isolate);
    315   cons3->SetClassName(v8_str("Cons3"));
    316 
    317   v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
    318   v8::Handle<v8::Signature> wsig = v8::Signature::New(
    319       isolate, v8::Handle<v8::FunctionTemplate>(), 3, args);
    320   v8::Handle<v8::FunctionTemplate> fun2 =
    321       v8::FunctionTemplate::New(isolate,
    322                                 SignatureCallback,
    323                                 v8::Handle<Value>(),
    324                                 wsig);
    325 
    326   env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
    327   env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
    328   env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
    329   env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
    330   v8::Handle<Value> value4 = CompileRun(
    331       "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
    332       "'[object Cons1],[object Cons2],[object Cons3]'");
    333   CHECK(value4->IsTrue());
    334 
    335   v8::Handle<Value> value5 = CompileRun(
    336       "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
    337   CHECK(value5->IsTrue());
    338 
    339   v8::Handle<Value> value6 = CompileRun(
    340       "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
    341   CHECK(value6->IsTrue());
    342 
    343   v8::Handle<Value> value7 = CompileRun(
    344       "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
    345       "'[object Cons1],[object Cons2],[object Cons3],d';");
    346   CHECK(value7->IsTrue());
    347 
    348   v8::Handle<Value> value8 = CompileRun(
    349       "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
    350   CHECK(value8->IsTrue());
    351 }
    352 
    353 
    354 THREADED_TEST(HulIgennem) {
    355   LocalContext env;
    356   v8::Isolate* isolate = env->GetIsolate();
    357   v8::HandleScope scope(isolate);
    358   v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
    359   Local<String> undef_str = undef->ToString();
    360   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
    361   undef_str->WriteUtf8(value);
    362   CHECK_EQ(0, strcmp(value, "undefined"));
    363   i::DeleteArray(value);
    364 }
    365 
    366 
    367 THREADED_TEST(Access) {
    368   LocalContext env;
    369   v8::Isolate* isolate = env->GetIsolate();
    370   v8::HandleScope scope(isolate);
    371   Local<v8::Object> obj = v8::Object::New(isolate);
    372   Local<Value> foo_before = obj->Get(v8_str("foo"));
    373   CHECK(foo_before->IsUndefined());
    374   Local<String> bar_str = v8_str("bar");
    375   obj->Set(v8_str("foo"), bar_str);
    376   Local<Value> foo_after = obj->Get(v8_str("foo"));
    377   CHECK(!foo_after->IsUndefined());
    378   CHECK(foo_after->IsString());
    379   CHECK_EQ(bar_str, foo_after);
    380 }
    381 
    382 
    383 THREADED_TEST(AccessElement) {
    384   LocalContext env;
    385   v8::HandleScope scope(env->GetIsolate());
    386   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    387   Local<Value> before = obj->Get(1);
    388   CHECK(before->IsUndefined());
    389   Local<String> bar_str = v8_str("bar");
    390   obj->Set(1, bar_str);
    391   Local<Value> after = obj->Get(1);
    392   CHECK(!after->IsUndefined());
    393   CHECK(after->IsString());
    394   CHECK_EQ(bar_str, after);
    395 
    396   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
    397   CHECK_EQ(v8_str("a"), value->Get(0));
    398   CHECK_EQ(v8_str("b"), value->Get(1));
    399 }
    400 
    401 
    402 THREADED_TEST(Script) {
    403   LocalContext env;
    404   v8::HandleScope scope(env->GetIsolate());
    405   const char* source = "1 + 2 + 3";
    406   Local<Script> script = v8_compile(source);
    407   CHECK_EQ(6, script->Run()->Int32Value());
    408 }
    409 
    410 
    411 class TestResource: public String::ExternalStringResource {
    412  public:
    413   explicit TestResource(uint16_t* data, int* counter = NULL,
    414                         bool owning_data = true)
    415       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
    416     while (data[length_]) ++length_;
    417   }
    418 
    419   ~TestResource() {
    420     if (owning_data_) i::DeleteArray(data_);
    421     if (counter_ != NULL) ++*counter_;
    422   }
    423 
    424   const uint16_t* data() const {
    425     return data_;
    426   }
    427 
    428   size_t length() const {
    429     return length_;
    430   }
    431 
    432  private:
    433   uint16_t* data_;
    434   size_t length_;
    435   int* counter_;
    436   bool owning_data_;
    437 };
    438 
    439 
    440 class TestOneByteResource : public String::ExternalOneByteStringResource {
    441  public:
    442   explicit TestOneByteResource(const char* data, int* counter = NULL,
    443                                size_t offset = 0)
    444       : orig_data_(data),
    445         data_(data + offset),
    446         length_(strlen(data) - offset),
    447         counter_(counter) {}
    448 
    449   ~TestOneByteResource() {
    450     i::DeleteArray(orig_data_);
    451     if (counter_ != NULL) ++*counter_;
    452   }
    453 
    454   const char* data() const {
    455     return data_;
    456   }
    457 
    458   size_t length() const {
    459     return length_;
    460   }
    461 
    462  private:
    463   const char* orig_data_;
    464   const char* data_;
    465   size_t length_;
    466   int* counter_;
    467 };
    468 
    469 
    470 THREADED_TEST(ScriptUsingStringResource) {
    471   int dispose_count = 0;
    472   const char* c_source = "1 + 2 * 3";
    473   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
    474   {
    475     LocalContext env;
    476     v8::HandleScope scope(env->GetIsolate());
    477     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
    478     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
    479     Local<Script> script = v8_compile(source);
    480     Local<Value> value = script->Run();
    481     CHECK(value->IsNumber());
    482     CHECK_EQ(7, value->Int32Value());
    483     CHECK(source->IsExternal());
    484     CHECK_EQ(resource,
    485              static_cast<TestResource*>(source->GetExternalStringResource()));
    486     String::Encoding encoding = String::UNKNOWN_ENCODING;
    487     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    488              source->GetExternalStringResourceBase(&encoding));
    489     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
    490     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    491     CHECK_EQ(0, dispose_count);
    492   }
    493   CcTest::i_isolate()->compilation_cache()->Clear();
    494   CcTest::heap()->CollectAllAvailableGarbage();
    495   CHECK_EQ(1, dispose_count);
    496 }
    497 
    498 
    499 THREADED_TEST(ScriptUsingOneByteStringResource) {
    500   int dispose_count = 0;
    501   const char* c_source = "1 + 2 * 3";
    502   {
    503     LocalContext env;
    504     v8::HandleScope scope(env->GetIsolate());
    505     TestOneByteResource* resource =
    506         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
    507     Local<String> source = String::NewExternal(env->GetIsolate(), resource);
    508     CHECK(source->IsExternalOneByte());
    509     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    510              source->GetExternalOneByteStringResource());
    511     String::Encoding encoding = String::UNKNOWN_ENCODING;
    512     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    513              source->GetExternalStringResourceBase(&encoding));
    514     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
    515     Local<Script> script = v8_compile(source);
    516     Local<Value> value = script->Run();
    517     CHECK(value->IsNumber());
    518     CHECK_EQ(7, value->Int32Value());
    519     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    520     CHECK_EQ(0, dispose_count);
    521   }
    522   CcTest::i_isolate()->compilation_cache()->Clear();
    523   CcTest::heap()->CollectAllAvailableGarbage();
    524   CHECK_EQ(1, dispose_count);
    525 }
    526 
    527 
    528 THREADED_TEST(ScriptMakingExternalString) {
    529   int dispose_count = 0;
    530   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
    531   {
    532     LocalContext env;
    533     v8::HandleScope scope(env->GetIsolate());
    534     Local<String> source =
    535         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
    536     // Trigger GCs so that the newly allocated string moves to old gen.
    537     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    538     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    539     CHECK_EQ(source->IsExternal(), false);
    540     CHECK_EQ(source->IsExternalOneByte(), false);
    541     String::Encoding encoding = String::UNKNOWN_ENCODING;
    542     CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
    543     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
    544     bool success = source->MakeExternal(new TestResource(two_byte_source,
    545                                                          &dispose_count));
    546     CHECK(success);
    547     Local<Script> script = v8_compile(source);
    548     Local<Value> value = script->Run();
    549     CHECK(value->IsNumber());
    550     CHECK_EQ(7, value->Int32Value());
    551     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    552     CHECK_EQ(0, dispose_count);
    553   }
    554   CcTest::i_isolate()->compilation_cache()->Clear();
    555   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
    556   CHECK_EQ(1, dispose_count);
    557 }
    558 
    559 
    560 THREADED_TEST(ScriptMakingExternalOneByteString) {
    561   int dispose_count = 0;
    562   const char* c_source = "1 + 2 * 3";
    563   {
    564     LocalContext env;
    565     v8::HandleScope scope(env->GetIsolate());
    566     Local<String> source = v8_str(c_source);
    567     // Trigger GCs so that the newly allocated string moves to old gen.
    568     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    569     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    570     bool success = source->MakeExternal(
    571         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
    572     CHECK(success);
    573     Local<Script> script = v8_compile(source);
    574     Local<Value> value = script->Run();
    575     CHECK(value->IsNumber());
    576     CHECK_EQ(7, value->Int32Value());
    577     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    578     CHECK_EQ(0, dispose_count);
    579   }
    580   CcTest::i_isolate()->compilation_cache()->Clear();
    581   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
    582   CHECK_EQ(1, dispose_count);
    583 }
    584 
    585 
    586 TEST(MakingExternalStringConditions) {
    587   LocalContext env;
    588   v8::HandleScope scope(env->GetIsolate());
    589 
    590   // Free some space in the new space so that we can check freshness.
    591   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    592   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    593 
    594   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
    595   Local<String> small_string =
    596       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
    597   i::DeleteArray(two_byte_string);
    598 
    599   // We should refuse to externalize newly created small string.
    600   CHECK(!small_string->CanMakeExternal());
    601   // Trigger GCs so that the newly allocated string moves to old gen.
    602   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    603   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    604   // Old space strings should be accepted.
    605   CHECK(small_string->CanMakeExternal());
    606 
    607   two_byte_string = AsciiToTwoByteString("small string 2");
    608   small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
    609   i::DeleteArray(two_byte_string);
    610 
    611   // We should refuse externalizing newly created small string.
    612   CHECK(!small_string->CanMakeExternal());
    613   for (int i = 0; i < 100; i++) {
    614     String::Value value(small_string);
    615   }
    616   // Frequently used strings should be accepted.
    617   CHECK(small_string->CanMakeExternal());
    618 
    619   const int buf_size = 10 * 1024;
    620   char* buf = i::NewArray<char>(buf_size);
    621   memset(buf, 'a', buf_size);
    622   buf[buf_size - 1] = '\0';
    623 
    624   two_byte_string = AsciiToTwoByteString(buf);
    625   Local<String> large_string =
    626       String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
    627   i::DeleteArray(buf);
    628   i::DeleteArray(two_byte_string);
    629   // Large strings should be immediately accepted.
    630   CHECK(large_string->CanMakeExternal());
    631 }
    632 
    633 
    634 TEST(MakingExternalOneByteStringConditions) {
    635   LocalContext env;
    636   v8::HandleScope scope(env->GetIsolate());
    637 
    638   // Free some space in the new space so that we can check freshness.
    639   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    640   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    641 
    642   Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
    643   // We should refuse to externalize newly created small string.
    644   CHECK(!small_string->CanMakeExternal());
    645   // Trigger GCs so that the newly allocated string moves to old gen.
    646   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    647   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    648   // Old space strings should be accepted.
    649   CHECK(small_string->CanMakeExternal());
    650 
    651   small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
    652   // We should refuse externalizing newly created small string.
    653   CHECK(!small_string->CanMakeExternal());
    654   for (int i = 0; i < 100; i++) {
    655     String::Value value(small_string);
    656   }
    657   // Frequently used strings should be accepted.
    658   CHECK(small_string->CanMakeExternal());
    659 
    660   const int buf_size = 10 * 1024;
    661   char* buf = i::NewArray<char>(buf_size);
    662   memset(buf, 'a', buf_size);
    663   buf[buf_size - 1] = '\0';
    664   Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
    665   i::DeleteArray(buf);
    666   // Large strings should be immediately accepted.
    667   CHECK(large_string->CanMakeExternal());
    668 }
    669 
    670 
    671 TEST(MakingExternalUnalignedOneByteString) {
    672   LocalContext env;
    673   v8::HandleScope scope(env->GetIsolate());
    674 
    675   CompileRun("function cons(a, b) { return a + b; }"
    676              "function slice(a) { return a.substring(1); }");
    677   // Create a cons string that will land in old pointer space.
    678   Local<String> cons = Local<String>::Cast(CompileRun(
    679       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
    680   // Create a sliced string that will land in old pointer space.
    681   Local<String> slice = Local<String>::Cast(CompileRun(
    682       "slice('abcdefghijklmnopqrstuvwxyz');"));
    683 
    684   // Trigger GCs so that the newly allocated string moves to old gen.
    685   SimulateFullSpace(CcTest::heap()->old_pointer_space());
    686   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    687   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    688 
    689   // Turn into external string with unaligned resource data.
    690   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
    691   bool success =
    692       cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
    693   CHECK(success);
    694   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
    695   success =
    696       slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
    697   CHECK(success);
    698 
    699   // Trigger GCs and force evacuation.
    700   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    701   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
    702 }
    703 
    704 
    705 THREADED_TEST(UsingExternalString) {
    706   i::Factory* factory = CcTest::i_isolate()->factory();
    707   {
    708     v8::HandleScope scope(CcTest::isolate());
    709     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    710     Local<String> string = String::NewExternal(
    711         CcTest::isolate(), new TestResource(two_byte_string));
    712     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    713     // Trigger GCs so that the newly allocated string moves to old gen.
    714     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    715     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    716     i::Handle<i::String> isymbol =
    717         factory->InternalizeString(istring);
    718     CHECK(isymbol->IsInternalizedString());
    719   }
    720   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    721   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    722 }
    723 
    724 
    725 THREADED_TEST(UsingExternalOneByteString) {
    726   i::Factory* factory = CcTest::i_isolate()->factory();
    727   {
    728     v8::HandleScope scope(CcTest::isolate());
    729     const char* one_byte_string = "test string";
    730     Local<String> string = String::NewExternal(
    731         CcTest::isolate(), new TestOneByteResource(i::StrDup(one_byte_string)));
    732     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    733     // Trigger GCs so that the newly allocated string moves to old gen.
    734     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    735     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    736     i::Handle<i::String> isymbol =
    737         factory->InternalizeString(istring);
    738     CHECK(isymbol->IsInternalizedString());
    739   }
    740   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    741   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    742 }
    743 
    744 
    745 THREADED_TEST(ScavengeExternalString) {
    746   i::FLAG_stress_compaction = false;
    747   i::FLAG_gc_global = false;
    748   int dispose_count = 0;
    749   bool in_new_space = false;
    750   {
    751     v8::HandleScope scope(CcTest::isolate());
    752     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    753     Local<String> string = String::NewExternal(
    754         CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
    755     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    756     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    757     in_new_space = CcTest::heap()->InNewSpace(*istring);
    758     CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
    759     CHECK_EQ(0, dispose_count);
    760   }
    761   CcTest::heap()->CollectGarbage(
    762       in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    763   CHECK_EQ(1, dispose_count);
    764 }
    765 
    766 
    767 THREADED_TEST(ScavengeExternalOneByteString) {
    768   i::FLAG_stress_compaction = false;
    769   i::FLAG_gc_global = false;
    770   int dispose_count = 0;
    771   bool in_new_space = false;
    772   {
    773     v8::HandleScope scope(CcTest::isolate());
    774     const char* one_byte_string = "test string";
    775     Local<String> string = String::NewExternal(
    776         CcTest::isolate(),
    777         new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count));
    778     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    779     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    780     in_new_space = CcTest::heap()->InNewSpace(*istring);
    781     CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
    782     CHECK_EQ(0, dispose_count);
    783   }
    784   CcTest::heap()->CollectGarbage(
    785       in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    786   CHECK_EQ(1, dispose_count);
    787 }
    788 
    789 
    790 class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
    791  public:
    792   // Only used by non-threaded tests, so it can use static fields.
    793   static int dispose_calls;
    794   static int dispose_count;
    795 
    796   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
    797       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
    798 
    799   void Dispose() {
    800     ++dispose_calls;
    801     if (dispose_) delete this;
    802   }
    803  private:
    804   bool dispose_;
    805 };
    806 
    807 
    808 int TestOneByteResourceWithDisposeControl::dispose_count = 0;
    809 int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
    810 
    811 
    812 TEST(ExternalStringWithDisposeHandling) {
    813   const char* c_source = "1 + 2 * 3";
    814 
    815   // Use a stack allocated external string resource allocated object.
    816   TestOneByteResourceWithDisposeControl::dispose_count = 0;
    817   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
    818   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
    819   {
    820     LocalContext env;
    821     v8::HandleScope scope(env->GetIsolate());
    822     Local<String> source =  String::NewExternal(env->GetIsolate(), &res_stack);
    823     Local<Script> script = v8_compile(source);
    824     Local<Value> value = script->Run();
    825     CHECK(value->IsNumber());
    826     CHECK_EQ(7, value->Int32Value());
    827     CcTest::heap()->CollectAllAvailableGarbage();
    828     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
    829   }
    830   CcTest::i_isolate()->compilation_cache()->Clear();
    831   CcTest::heap()->CollectAllAvailableGarbage();
    832   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
    833   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
    834 
    835   // Use a heap allocated external string resource allocated object.
    836   TestOneByteResourceWithDisposeControl::dispose_count = 0;
    837   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
    838   TestOneByteResource* res_heap =
    839       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
    840   {
    841     LocalContext env;
    842     v8::HandleScope scope(env->GetIsolate());
    843     Local<String> source =  String::NewExternal(env->GetIsolate(), res_heap);
    844     Local<Script> script = v8_compile(source);
    845     Local<Value> value = script->Run();
    846     CHECK(value->IsNumber());
    847     CHECK_EQ(7, value->Int32Value());
    848     CcTest::heap()->CollectAllAvailableGarbage();
    849     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
    850   }
    851   CcTest::i_isolate()->compilation_cache()->Clear();
    852   CcTest::heap()->CollectAllAvailableGarbage();
    853   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
    854   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
    855 }
    856 
    857 
    858 THREADED_TEST(StringConcat) {
    859   {
    860     LocalContext env;
    861     v8::HandleScope scope(env->GetIsolate());
    862     const char* one_byte_string_1 = "function a_times_t";
    863     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
    864     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
    865     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
    866     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    867     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    868     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
    869     Local<String> left = v8_str(one_byte_string_1);
    870 
    871     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
    872     Local<String> right =
    873         String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
    874     i::DeleteArray(two_byte_source);
    875 
    876     Local<String> source = String::Concat(left, right);
    877     right = String::NewExternal(
    878         env->GetIsolate(),
    879         new TestOneByteResource(i::StrDup(one_byte_extern_1)));
    880     source = String::Concat(source, right);
    881     right = String::NewExternal(
    882         env->GetIsolate(),
    883         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
    884     source = String::Concat(source, right);
    885     right = v8_str(one_byte_string_2);
    886     source = String::Concat(source, right);
    887 
    888     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
    889     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
    890     i::DeleteArray(two_byte_source);
    891 
    892     source = String::Concat(source, right);
    893     right = String::NewExternal(
    894         env->GetIsolate(),
    895         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
    896     source = String::Concat(source, right);
    897     Local<Script> script = v8_compile(source);
    898     Local<Value> value = script->Run();
    899     CHECK(value->IsNumber());
    900     CHECK_EQ(68, value->Int32Value());
    901   }
    902   CcTest::i_isolate()->compilation_cache()->Clear();
    903   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    904   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    905 }
    906 
    907 
    908 THREADED_TEST(GlobalProperties) {
    909   LocalContext env;
    910   v8::HandleScope scope(env->GetIsolate());
    911   v8::Handle<v8::Object> global = env->Global();
    912   global->Set(v8_str("pi"), v8_num(3.1415926));
    913   Local<Value> pi = global->Get(v8_str("pi"));
    914   CHECK_EQ(3.1415926, pi->NumberValue());
    915 }
    916 
    917 
    918 template<typename T>
    919 static void CheckReturnValue(const T& t, i::Address callback) {
    920   v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
    921   i::Object** o = *reinterpret_cast<i::Object***>(&rv);
    922   CHECK_EQ(CcTest::isolate(), t.GetIsolate());
    923   CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
    924   CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
    925   // Verify reset
    926   bool is_runtime = (*o)->IsTheHole();
    927   rv.Set(true);
    928   CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
    929   rv.Set(v8::Handle<v8::Object>());
    930   CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
    931   CHECK_EQ(is_runtime, (*o)->IsTheHole());
    932 
    933   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
    934   // If CPU profiler is active check that when API callback is invoked
    935   // VMState is set to EXTERNAL.
    936   if (isolate->cpu_profiler()->is_profiling()) {
    937     CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
    938     CHECK(isolate->external_callback_scope());
    939     CHECK_EQ(callback, isolate->external_callback_scope()->callback());
    940   }
    941 }
    942 
    943 
    944 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
    945                                  i::Address callback) {
    946   ApiTestFuzzer::Fuzz();
    947   CheckReturnValue(info, callback);
    948   info.GetReturnValue().Set(v8_str("bad value"));
    949   info.GetReturnValue().Set(v8_num(102));
    950 }
    951 
    952 
    953 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
    954   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
    955 }
    956 
    957 
    958 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
    959   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
    960 }
    961 
    962 static void construct_callback(
    963     const v8::FunctionCallbackInfo<Value>& info) {
    964   ApiTestFuzzer::Fuzz();
    965   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
    966   info.This()->Set(v8_str("x"), v8_num(1));
    967   info.This()->Set(v8_str("y"), v8_num(2));
    968   info.GetReturnValue().Set(v8_str("bad value"));
    969   info.GetReturnValue().Set(info.This());
    970 }
    971 
    972 
    973 static void Return239Callback(
    974     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
    975   ApiTestFuzzer::Fuzz();
    976   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
    977   info.GetReturnValue().Set(v8_str("bad value"));
    978   info.GetReturnValue().Set(v8_num(239));
    979 }
    980 
    981 
    982 template<typename Handler>
    983 static void TestFunctionTemplateInitializer(Handler handler,
    984                                             Handler handler_2) {
    985   // Test constructor calls.
    986   {
    987     LocalContext env;
    988     v8::Isolate* isolate = env->GetIsolate();
    989     v8::HandleScope scope(isolate);
    990 
    991     Local<v8::FunctionTemplate> fun_templ =
    992         v8::FunctionTemplate::New(isolate, handler);
    993     Local<Function> fun = fun_templ->GetFunction();
    994     env->Global()->Set(v8_str("obj"), fun);
    995     Local<Script> script = v8_compile("obj()");
    996     for (int i = 0; i < 30; i++) {
    997       CHECK_EQ(102, script->Run()->Int32Value());
    998     }
    999   }
   1000   // Use SetCallHandler to initialize a function template, should work like
   1001   // the previous one.
   1002   {
   1003     LocalContext env;
   1004     v8::Isolate* isolate = env->GetIsolate();
   1005     v8::HandleScope scope(isolate);
   1006 
   1007     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
   1008     fun_templ->SetCallHandler(handler_2);
   1009     Local<Function> fun = fun_templ->GetFunction();
   1010     env->Global()->Set(v8_str("obj"), fun);
   1011     Local<Script> script = v8_compile("obj()");
   1012     for (int i = 0; i < 30; i++) {
   1013       CHECK_EQ(102, script->Run()->Int32Value());
   1014     }
   1015   }
   1016 }
   1017 
   1018 
   1019 template<typename Constructor, typename Accessor>
   1020 static void TestFunctionTemplateAccessor(Constructor constructor,
   1021                                          Accessor accessor) {
   1022   LocalContext env;
   1023   v8::HandleScope scope(env->GetIsolate());
   1024 
   1025   Local<v8::FunctionTemplate> fun_templ =
   1026       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
   1027   fun_templ->SetClassName(v8_str("funky"));
   1028   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
   1029   Local<Function> fun = fun_templ->GetFunction();
   1030   env->Global()->Set(v8_str("obj"), fun);
   1031   Local<Value> result = v8_compile("(new obj()).toString()")->Run();
   1032   CHECK_EQ(v8_str("[object funky]"), result);
   1033   CompileRun("var obj_instance = new obj();");
   1034   Local<Script> script;
   1035   script = v8_compile("obj_instance.x");
   1036   for (int i = 0; i < 30; i++) {
   1037     CHECK_EQ(1, script->Run()->Int32Value());
   1038   }
   1039   script = v8_compile("obj_instance.m");
   1040   for (int i = 0; i < 30; i++) {
   1041     CHECK_EQ(239, script->Run()->Int32Value());
   1042   }
   1043 }
   1044 
   1045 
   1046 THREADED_PROFILED_TEST(FunctionTemplate) {
   1047   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
   1048   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
   1049 }
   1050 
   1051 
   1052 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   1053   ApiTestFuzzer::Fuzz();
   1054   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
   1055   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
   1056 }
   1057 
   1058 
   1059 template<typename Callback>
   1060 static void TestSimpleCallback(Callback callback) {
   1061   LocalContext env;
   1062   v8::Isolate* isolate = env->GetIsolate();
   1063   v8::HandleScope scope(isolate);
   1064 
   1065   v8::Handle<v8::ObjectTemplate> object_template =
   1066       v8::ObjectTemplate::New(isolate);
   1067   object_template->Set(isolate, "callback",
   1068                        v8::FunctionTemplate::New(isolate, callback));
   1069   v8::Local<v8::Object> object = object_template->NewInstance();
   1070   (*env)->Global()->Set(v8_str("callback_object"), object);
   1071   v8::Handle<v8::Script> script;
   1072   script = v8_compile("callback_object.callback(17)");
   1073   for (int i = 0; i < 30; i++) {
   1074     CHECK_EQ(51424, script->Run()->Int32Value());
   1075   }
   1076   script = v8_compile("callback_object.callback(17, 24)");
   1077   for (int i = 0; i < 30; i++) {
   1078     CHECK_EQ(51425, script->Run()->Int32Value());
   1079   }
   1080 }
   1081 
   1082 
   1083 THREADED_PROFILED_TEST(SimpleCallback) {
   1084   TestSimpleCallback(SimpleCallback);
   1085 }
   1086 
   1087 
   1088 template<typename T>
   1089 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
   1090 
   1091 // constant return values
   1092 static int32_t fast_return_value_int32 = 471;
   1093 static uint32_t fast_return_value_uint32 = 571;
   1094 static const double kFastReturnValueDouble = 2.7;
   1095 // variable return values
   1096 static bool fast_return_value_bool = false;
   1097 enum ReturnValueOddball {
   1098   kNullReturnValue,
   1099   kUndefinedReturnValue,
   1100   kEmptyStringReturnValue
   1101 };
   1102 static ReturnValueOddball fast_return_value_void;
   1103 static bool fast_return_value_object_is_empty = false;
   1104 
   1105 // Helper function to avoid compiler error: insufficient contextual information
   1106 // to determine type when applying FUNCTION_ADDR to a template function.
   1107 static i::Address address_of(v8::FunctionCallback callback) {
   1108   return FUNCTION_ADDR(callback);
   1109 }
   1110 
   1111 template<>
   1112 void FastReturnValueCallback<int32_t>(
   1113     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1114   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
   1115   info.GetReturnValue().Set(fast_return_value_int32);
   1116 }
   1117 
   1118 template<>
   1119 void FastReturnValueCallback<uint32_t>(
   1120     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1121   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
   1122   info.GetReturnValue().Set(fast_return_value_uint32);
   1123 }
   1124 
   1125 template<>
   1126 void FastReturnValueCallback<double>(
   1127     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1128   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
   1129   info.GetReturnValue().Set(kFastReturnValueDouble);
   1130 }
   1131 
   1132 template<>
   1133 void FastReturnValueCallback<bool>(
   1134     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1135   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
   1136   info.GetReturnValue().Set(fast_return_value_bool);
   1137 }
   1138 
   1139 template<>
   1140 void FastReturnValueCallback<void>(
   1141     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1142   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
   1143   switch (fast_return_value_void) {
   1144     case kNullReturnValue:
   1145       info.GetReturnValue().SetNull();
   1146       break;
   1147     case kUndefinedReturnValue:
   1148       info.GetReturnValue().SetUndefined();
   1149       break;
   1150     case kEmptyStringReturnValue:
   1151       info.GetReturnValue().SetEmptyString();
   1152       break;
   1153   }
   1154 }
   1155 
   1156 template<>
   1157 void FastReturnValueCallback<Object>(
   1158     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1159   v8::Handle<v8::Object> object;
   1160   if (!fast_return_value_object_is_empty) {
   1161     object = Object::New(info.GetIsolate());
   1162   }
   1163   info.GetReturnValue().Set(object);
   1164 }
   1165 
   1166 template<typename T>
   1167 Handle<Value> TestFastReturnValues() {
   1168   LocalContext env;
   1169   v8::Isolate* isolate = env->GetIsolate();
   1170   v8::EscapableHandleScope scope(isolate);
   1171   v8::Handle<v8::ObjectTemplate> object_template =
   1172       v8::ObjectTemplate::New(isolate);
   1173   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
   1174   object_template->Set(isolate, "callback",
   1175                        v8::FunctionTemplate::New(isolate, callback));
   1176   v8::Local<v8::Object> object = object_template->NewInstance();
   1177   (*env)->Global()->Set(v8_str("callback_object"), object);
   1178   return scope.Escape(CompileRun("callback_object.callback()"));
   1179 }
   1180 
   1181 
   1182 THREADED_PROFILED_TEST(FastReturnValues) {
   1183   LocalContext env;
   1184   v8::HandleScope scope(CcTest::isolate());
   1185   v8::Handle<v8::Value> value;
   1186   // check int32_t and uint32_t
   1187   int32_t int_values[] = {
   1188       0, 234, -723,
   1189       i::Smi::kMinValue, i::Smi::kMaxValue
   1190   };
   1191   for (size_t i = 0; i < arraysize(int_values); i++) {
   1192     for (int modifier = -1; modifier <= 1; modifier++) {
   1193       int int_value = int_values[i] + modifier;
   1194       // check int32_t
   1195       fast_return_value_int32 = int_value;
   1196       value = TestFastReturnValues<int32_t>();
   1197       CHECK(value->IsInt32());
   1198       CHECK(fast_return_value_int32 == value->Int32Value());
   1199       // check uint32_t
   1200       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
   1201       value = TestFastReturnValues<uint32_t>();
   1202       CHECK(value->IsUint32());
   1203       CHECK(fast_return_value_uint32 == value->Uint32Value());
   1204     }
   1205   }
   1206   // check double
   1207   value = TestFastReturnValues<double>();
   1208   CHECK(value->IsNumber());
   1209   CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
   1210   // check bool values
   1211   for (int i = 0; i < 2; i++) {
   1212     fast_return_value_bool = i == 0;
   1213     value = TestFastReturnValues<bool>();
   1214     CHECK(value->IsBoolean());
   1215     CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
   1216   }
   1217   // check oddballs
   1218   ReturnValueOddball oddballs[] = {
   1219       kNullReturnValue,
   1220       kUndefinedReturnValue,
   1221       kEmptyStringReturnValue
   1222   };
   1223   for (size_t i = 0; i < arraysize(oddballs); i++) {
   1224     fast_return_value_void = oddballs[i];
   1225     value = TestFastReturnValues<void>();
   1226     switch (fast_return_value_void) {
   1227       case kNullReturnValue:
   1228         CHECK(value->IsNull());
   1229         break;
   1230       case kUndefinedReturnValue:
   1231         CHECK(value->IsUndefined());
   1232         break;
   1233       case kEmptyStringReturnValue:
   1234         CHECK(value->IsString());
   1235         CHECK_EQ(0, v8::String::Cast(*value)->Length());
   1236         break;
   1237     }
   1238   }
   1239   // check handles
   1240   fast_return_value_object_is_empty = false;
   1241   value = TestFastReturnValues<Object>();
   1242   CHECK(value->IsObject());
   1243   fast_return_value_object_is_empty = true;
   1244   value = TestFastReturnValues<Object>();
   1245   CHECK(value->IsUndefined());
   1246 }
   1247 
   1248 
   1249 THREADED_TEST(FunctionTemplateSetLength) {
   1250   LocalContext env;
   1251   v8::Isolate* isolate = env->GetIsolate();
   1252   v8::HandleScope scope(isolate);
   1253   {
   1254     Local<v8::FunctionTemplate> fun_templ =
   1255         v8::FunctionTemplate::New(isolate,
   1256                                   handle_callback,
   1257                                   Handle<v8::Value>(),
   1258                                   Handle<v8::Signature>(),
   1259                                   23);
   1260     Local<Function> fun = fun_templ->GetFunction();
   1261     env->Global()->Set(v8_str("obj"), fun);
   1262     Local<Script> script = v8_compile("obj.length");
   1263     CHECK_EQ(23, script->Run()->Int32Value());
   1264   }
   1265   {
   1266     Local<v8::FunctionTemplate> fun_templ =
   1267         v8::FunctionTemplate::New(isolate, handle_callback);
   1268     fun_templ->SetLength(22);
   1269     Local<Function> fun = fun_templ->GetFunction();
   1270     env->Global()->Set(v8_str("obj"), fun);
   1271     Local<Script> script = v8_compile("obj.length");
   1272     CHECK_EQ(22, script->Run()->Int32Value());
   1273   }
   1274   {
   1275     // Without setting length it defaults to 0.
   1276     Local<v8::FunctionTemplate> fun_templ =
   1277         v8::FunctionTemplate::New(isolate, handle_callback);
   1278     Local<Function> fun = fun_templ->GetFunction();
   1279     env->Global()->Set(v8_str("obj"), fun);
   1280     Local<Script> script = v8_compile("obj.length");
   1281     CHECK_EQ(0, script->Run()->Int32Value());
   1282   }
   1283 }
   1284 
   1285 
   1286 static void* expected_ptr;
   1287 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1288   void* ptr = v8::External::Cast(*args.Data())->Value();
   1289   CHECK_EQ(expected_ptr, ptr);
   1290   args.GetReturnValue().Set(true);
   1291 }
   1292 
   1293 
   1294 static void TestExternalPointerWrapping() {
   1295   LocalContext env;
   1296   v8::Isolate* isolate = env->GetIsolate();
   1297   v8::HandleScope scope(isolate);
   1298 
   1299   v8::Handle<v8::Value> data =
   1300       v8::External::New(isolate, expected_ptr);
   1301 
   1302   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
   1303   obj->Set(v8_str("func"),
   1304            v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
   1305   env->Global()->Set(v8_str("obj"), obj);
   1306 
   1307   CHECK(CompileRun(
   1308         "function foo() {\n"
   1309         "  for (var i = 0; i < 13; i++) obj.func();\n"
   1310         "}\n"
   1311         "foo(), true")->BooleanValue());
   1312 }
   1313 
   1314 
   1315 THREADED_TEST(ExternalWrap) {
   1316   // Check heap allocated object.
   1317   int* ptr = new int;
   1318   expected_ptr = ptr;
   1319   TestExternalPointerWrapping();
   1320   delete ptr;
   1321 
   1322   // Check stack allocated object.
   1323   int foo;
   1324   expected_ptr = &foo;
   1325   TestExternalPointerWrapping();
   1326 
   1327   // Check not aligned addresses.
   1328   const int n = 100;
   1329   char* s = new char[n];
   1330   for (int i = 0; i < n; i++) {
   1331     expected_ptr = s + i;
   1332     TestExternalPointerWrapping();
   1333   }
   1334 
   1335   delete[] s;
   1336 
   1337   // Check several invalid addresses.
   1338   expected_ptr = reinterpret_cast<void*>(1);
   1339   TestExternalPointerWrapping();
   1340 
   1341   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
   1342   TestExternalPointerWrapping();
   1343 
   1344   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
   1345   TestExternalPointerWrapping();
   1346 
   1347 #if defined(V8_HOST_ARCH_X64)
   1348   // Check a value with a leading 1 bit in x64 Smi encoding.
   1349   expected_ptr = reinterpret_cast<void*>(0x400000000);
   1350   TestExternalPointerWrapping();
   1351 
   1352   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
   1353   TestExternalPointerWrapping();
   1354 
   1355   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
   1356   TestExternalPointerWrapping();
   1357 #endif
   1358 }
   1359 
   1360 
   1361 THREADED_TEST(FindInstanceInPrototypeChain) {
   1362   LocalContext env;
   1363   v8::Isolate* isolate = env->GetIsolate();
   1364   v8::HandleScope scope(isolate);
   1365 
   1366   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
   1367   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
   1368   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
   1369   derived->Inherit(base);
   1370 
   1371   Local<v8::Function> base_function = base->GetFunction();
   1372   Local<v8::Function> derived_function = derived->GetFunction();
   1373   Local<v8::Function> other_function = other->GetFunction();
   1374 
   1375   Local<v8::Object> base_instance = base_function->NewInstance();
   1376   Local<v8::Object> derived_instance = derived_function->NewInstance();
   1377   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
   1378   Local<v8::Object> other_instance = other_function->NewInstance();
   1379   derived_instance2->Set(v8_str("__proto__"), derived_instance);
   1380   other_instance->Set(v8_str("__proto__"), derived_instance2);
   1381 
   1382   // base_instance is only an instance of base.
   1383   CHECK_EQ(base_instance,
   1384            base_instance->FindInstanceInPrototypeChain(base));
   1385   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
   1386   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1387 
   1388   // derived_instance is an instance of base and derived.
   1389   CHECK_EQ(derived_instance,
   1390            derived_instance->FindInstanceInPrototypeChain(base));
   1391   CHECK_EQ(derived_instance,
   1392            derived_instance->FindInstanceInPrototypeChain(derived));
   1393   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1394 
   1395   // other_instance is an instance of other and its immediate
   1396   // prototype derived_instance2 is an instance of base and derived.
   1397   // Note, derived_instance is an instance of base and derived too,
   1398   // but it comes after derived_instance2 in the prototype chain of
   1399   // other_instance.
   1400   CHECK_EQ(derived_instance2,
   1401            other_instance->FindInstanceInPrototypeChain(base));
   1402   CHECK_EQ(derived_instance2,
   1403            other_instance->FindInstanceInPrototypeChain(derived));
   1404   CHECK_EQ(other_instance,
   1405            other_instance->FindInstanceInPrototypeChain(other));
   1406 }
   1407 
   1408 
   1409 THREADED_TEST(TinyInteger) {
   1410   LocalContext env;
   1411   v8::Isolate* isolate = env->GetIsolate();
   1412   v8::HandleScope scope(isolate);
   1413 
   1414   int32_t value = 239;
   1415   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
   1416   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1417 
   1418   value_obj = v8::Integer::New(isolate, value);
   1419   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1420 }
   1421 
   1422 
   1423 THREADED_TEST(BigSmiInteger) {
   1424   LocalContext env;
   1425   v8::HandleScope scope(env->GetIsolate());
   1426   v8::Isolate* isolate = CcTest::isolate();
   1427 
   1428   int32_t value = i::Smi::kMaxValue;
   1429   // We cannot add one to a Smi::kMaxValue without wrapping.
   1430   if (i::SmiValuesAre31Bits()) {
   1431     CHECK(i::Smi::IsValid(value));
   1432     CHECK(!i::Smi::IsValid(value + 1));
   1433 
   1434     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
   1435     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1436 
   1437     value_obj = v8::Integer::New(isolate, value);
   1438     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1439   }
   1440 }
   1441 
   1442 
   1443 THREADED_TEST(BigInteger) {
   1444   LocalContext env;
   1445   v8::HandleScope scope(env->GetIsolate());
   1446   v8::Isolate* isolate = CcTest::isolate();
   1447 
   1448   // We cannot add one to a Smi::kMaxValue without wrapping.
   1449   if (i::SmiValuesAre31Bits()) {
   1450     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
   1451     // The code will not be run in that case, due to the "if" guard.
   1452     int32_t value =
   1453         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
   1454     CHECK(value > i::Smi::kMaxValue);
   1455     CHECK(!i::Smi::IsValid(value));
   1456 
   1457     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
   1458     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1459 
   1460     value_obj = v8::Integer::New(isolate, value);
   1461     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1462   }
   1463 }
   1464 
   1465 
   1466 THREADED_TEST(TinyUnsignedInteger) {
   1467   LocalContext env;
   1468   v8::HandleScope scope(env->GetIsolate());
   1469   v8::Isolate* isolate = CcTest::isolate();
   1470 
   1471   uint32_t value = 239;
   1472 
   1473   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1474   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1475 
   1476   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1477   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1478 }
   1479 
   1480 
   1481 THREADED_TEST(BigUnsignedSmiInteger) {
   1482   LocalContext env;
   1483   v8::HandleScope scope(env->GetIsolate());
   1484   v8::Isolate* isolate = CcTest::isolate();
   1485 
   1486   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
   1487   CHECK(i::Smi::IsValid(value));
   1488   CHECK(!i::Smi::IsValid(value + 1));
   1489 
   1490   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1491   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1492 
   1493   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1494   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1495 }
   1496 
   1497 
   1498 THREADED_TEST(BigUnsignedInteger) {
   1499   LocalContext env;
   1500   v8::HandleScope scope(env->GetIsolate());
   1501   v8::Isolate* isolate = CcTest::isolate();
   1502 
   1503   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
   1504   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
   1505   CHECK(!i::Smi::IsValid(value));
   1506 
   1507   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1508   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1509 
   1510   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1511   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1512 }
   1513 
   1514 
   1515 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
   1516   LocalContext env;
   1517   v8::HandleScope scope(env->GetIsolate());
   1518   v8::Isolate* isolate = CcTest::isolate();
   1519 
   1520   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
   1521   uint32_t value = INT32_MAX_AS_UINT + 1;
   1522   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
   1523 
   1524   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1525   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1526 
   1527   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1528   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1529 }
   1530 
   1531 
   1532 THREADED_TEST(IsNativeError) {
   1533   LocalContext env;
   1534   v8::HandleScope scope(env->GetIsolate());
   1535   v8::Handle<Value> syntax_error = CompileRun(
   1536       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
   1537   CHECK(syntax_error->IsNativeError());
   1538   v8::Handle<Value> not_error = CompileRun("{a:42}");
   1539   CHECK(!not_error->IsNativeError());
   1540   v8::Handle<Value> not_object = CompileRun("42");
   1541   CHECK(!not_object->IsNativeError());
   1542 }
   1543 
   1544 
   1545 THREADED_TEST(ArgumentsObject) {
   1546   LocalContext env;
   1547   v8::HandleScope scope(env->GetIsolate());
   1548   v8::Handle<Value> arguments_object =
   1549       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
   1550   CHECK(arguments_object->IsArgumentsObject());
   1551   v8::Handle<Value> array = CompileRun("[1,2,3]");
   1552   CHECK(!array->IsArgumentsObject());
   1553   v8::Handle<Value> object = CompileRun("{a:42}");
   1554   CHECK(!object->IsArgumentsObject());
   1555 }
   1556 
   1557 
   1558 THREADED_TEST(IsMapOrSet) {
   1559   LocalContext env;
   1560   v8::HandleScope scope(env->GetIsolate());
   1561   v8::Handle<Value> map = CompileRun("new Map()");
   1562   v8::Handle<Value> set = CompileRun("new Set()");
   1563   v8::Handle<Value> weak_map = CompileRun("new WeakMap()");
   1564   v8::Handle<Value> weak_set = CompileRun("new WeakSet()");
   1565   CHECK(map->IsMap());
   1566   CHECK(set->IsSet());
   1567   CHECK(weak_map->IsWeakMap());
   1568   CHECK(weak_set->IsWeakSet());
   1569 
   1570   CHECK(!map->IsSet());
   1571   CHECK(!map->IsWeakMap());
   1572   CHECK(!map->IsWeakSet());
   1573 
   1574   CHECK(!set->IsMap());
   1575   CHECK(!set->IsWeakMap());
   1576   CHECK(!set->IsWeakSet());
   1577 
   1578   CHECK(!weak_map->IsMap());
   1579   CHECK(!weak_map->IsSet());
   1580   CHECK(!weak_map->IsWeakSet());
   1581 
   1582   CHECK(!weak_set->IsMap());
   1583   CHECK(!weak_set->IsSet());
   1584   CHECK(!weak_set->IsWeakMap());
   1585 
   1586   v8::Handle<Value> object = CompileRun("{a:42}");
   1587   CHECK(!object->IsMap());
   1588   CHECK(!object->IsSet());
   1589   CHECK(!object->IsWeakMap());
   1590   CHECK(!object->IsWeakSet());
   1591 }
   1592 
   1593 
   1594 THREADED_TEST(StringObject) {
   1595   LocalContext env;
   1596   v8::HandleScope scope(env->GetIsolate());
   1597   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
   1598   CHECK(boxed_string->IsStringObject());
   1599   v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
   1600   CHECK(!unboxed_string->IsStringObject());
   1601   v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
   1602   CHECK(!boxed_not_string->IsStringObject());
   1603   v8::Handle<Value> not_object = CompileRun("0");
   1604   CHECK(!not_object->IsStringObject());
   1605   v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
   1606   CHECK(!as_boxed.IsEmpty());
   1607   Local<v8::String> the_string = as_boxed->ValueOf();
   1608   CHECK(!the_string.IsEmpty());
   1609   ExpectObject("\"test\"", the_string);
   1610   v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
   1611   CHECK(new_boxed_string->IsStringObject());
   1612   as_boxed = new_boxed_string.As<v8::StringObject>();
   1613   the_string = as_boxed->ValueOf();
   1614   CHECK(!the_string.IsEmpty());
   1615   ExpectObject("\"test\"", the_string);
   1616 }
   1617 
   1618 
   1619 THREADED_TEST(NumberObject) {
   1620   LocalContext env;
   1621   v8::HandleScope scope(env->GetIsolate());
   1622   v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
   1623   CHECK(boxed_number->IsNumberObject());
   1624   v8::Handle<Value> unboxed_number = CompileRun("42");
   1625   CHECK(!unboxed_number->IsNumberObject());
   1626   v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
   1627   CHECK(!boxed_not_number->IsNumberObject());
   1628   v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
   1629   CHECK(!as_boxed.IsEmpty());
   1630   double the_number = as_boxed->ValueOf();
   1631   CHECK_EQ(42.0, the_number);
   1632   v8::Handle<v8::Value> new_boxed_number =
   1633       v8::NumberObject::New(env->GetIsolate(), 43);
   1634   CHECK(new_boxed_number->IsNumberObject());
   1635   as_boxed = new_boxed_number.As<v8::NumberObject>();
   1636   the_number = as_boxed->ValueOf();
   1637   CHECK_EQ(43.0, the_number);
   1638 }
   1639 
   1640 
   1641 THREADED_TEST(BooleanObject) {
   1642   LocalContext env;
   1643   v8::HandleScope scope(env->GetIsolate());
   1644   v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
   1645   CHECK(boxed_boolean->IsBooleanObject());
   1646   v8::Handle<Value> unboxed_boolean = CompileRun("true");
   1647   CHECK(!unboxed_boolean->IsBooleanObject());
   1648   v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
   1649   CHECK(!boxed_not_boolean->IsBooleanObject());
   1650   v8::Handle<v8::BooleanObject> as_boxed =
   1651       boxed_boolean.As<v8::BooleanObject>();
   1652   CHECK(!as_boxed.IsEmpty());
   1653   bool the_boolean = as_boxed->ValueOf();
   1654   CHECK_EQ(true, the_boolean);
   1655   v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
   1656   v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
   1657   CHECK(boxed_true->IsBooleanObject());
   1658   CHECK(boxed_false->IsBooleanObject());
   1659   as_boxed = boxed_true.As<v8::BooleanObject>();
   1660   CHECK_EQ(true, as_boxed->ValueOf());
   1661   as_boxed = boxed_false.As<v8::BooleanObject>();
   1662   CHECK_EQ(false, as_boxed->ValueOf());
   1663 }
   1664 
   1665 
   1666 THREADED_TEST(PrimitiveAndWrappedBooleans) {
   1667   LocalContext env;
   1668   v8::HandleScope scope(env->GetIsolate());
   1669 
   1670   Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
   1671   CHECK(primitive_false->IsBoolean());
   1672   CHECK(!primitive_false->IsBooleanObject());
   1673   CHECK(!primitive_false->BooleanValue());
   1674   CHECK(!primitive_false->IsTrue());
   1675   CHECK(primitive_false->IsFalse());
   1676 
   1677   Local<Value> false_value = BooleanObject::New(false);
   1678   CHECK(!false_value->IsBoolean());
   1679   CHECK(false_value->IsBooleanObject());
   1680   CHECK(false_value->BooleanValue());
   1681   CHECK(!false_value->IsTrue());
   1682   CHECK(!false_value->IsFalse());
   1683 
   1684   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
   1685   CHECK(!false_boolean_object->IsBoolean());
   1686   CHECK(false_boolean_object->IsBooleanObject());
   1687   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
   1688   // CHECK(false_boolean_object->BooleanValue());
   1689   CHECK(!false_boolean_object->ValueOf());
   1690   CHECK(!false_boolean_object->IsTrue());
   1691   CHECK(!false_boolean_object->IsFalse());
   1692 
   1693   Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
   1694   CHECK(primitive_true->IsBoolean());
   1695   CHECK(!primitive_true->IsBooleanObject());
   1696   CHECK(primitive_true->BooleanValue());
   1697   CHECK(primitive_true->IsTrue());
   1698   CHECK(!primitive_true->IsFalse());
   1699 
   1700   Local<Value> true_value = BooleanObject::New(true);
   1701   CHECK(!true_value->IsBoolean());
   1702   CHECK(true_value->IsBooleanObject());
   1703   CHECK(true_value->BooleanValue());
   1704   CHECK(!true_value->IsTrue());
   1705   CHECK(!true_value->IsFalse());
   1706 
   1707   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
   1708   CHECK(!true_boolean_object->IsBoolean());
   1709   CHECK(true_boolean_object->IsBooleanObject());
   1710   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
   1711   // CHECK(true_boolean_object->BooleanValue());
   1712   CHECK(true_boolean_object->ValueOf());
   1713   CHECK(!true_boolean_object->IsTrue());
   1714   CHECK(!true_boolean_object->IsFalse());
   1715 }
   1716 
   1717 
   1718 THREADED_TEST(Number) {
   1719   LocalContext env;
   1720   v8::HandleScope scope(env->GetIsolate());
   1721   double PI = 3.1415926;
   1722   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
   1723   CHECK_EQ(PI, pi_obj->NumberValue());
   1724 }
   1725 
   1726 
   1727 THREADED_TEST(ToNumber) {
   1728   LocalContext env;
   1729   v8::Isolate* isolate = CcTest::isolate();
   1730   v8::HandleScope scope(isolate);
   1731   Local<String> str = v8_str("3.1415926");
   1732   CHECK_EQ(3.1415926, str->NumberValue());
   1733   v8::Handle<v8::Boolean> t = v8::True(isolate);
   1734   CHECK_EQ(1.0, t->NumberValue());
   1735   v8::Handle<v8::Boolean> f = v8::False(isolate);
   1736   CHECK_EQ(0.0, f->NumberValue());
   1737 }
   1738 
   1739 
   1740 THREADED_TEST(Date) {
   1741   LocalContext env;
   1742   v8::HandleScope scope(env->GetIsolate());
   1743   double PI = 3.1415926;
   1744   Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
   1745   CHECK_EQ(3.0, date->NumberValue());
   1746   date.As<v8::Date>()->Set(v8_str("property"),
   1747                            v8::Integer::New(env->GetIsolate(), 42));
   1748   CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
   1749 }
   1750 
   1751 
   1752 THREADED_TEST(Boolean) {
   1753   LocalContext env;
   1754   v8::Isolate* isolate = env->GetIsolate();
   1755   v8::HandleScope scope(isolate);
   1756   v8::Handle<v8::Boolean> t = v8::True(isolate);
   1757   CHECK(t->Value());
   1758   v8::Handle<v8::Boolean> f = v8::False(isolate);
   1759   CHECK(!f->Value());
   1760   v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
   1761   CHECK(!u->BooleanValue());
   1762   v8::Handle<v8::Primitive> n = v8::Null(isolate);
   1763   CHECK(!n->BooleanValue());
   1764   v8::Handle<String> str1 = v8_str("");
   1765   CHECK(!str1->BooleanValue());
   1766   v8::Handle<String> str2 = v8_str("x");
   1767   CHECK(str2->BooleanValue());
   1768   CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
   1769   CHECK(v8::Number::New(isolate, -1)->BooleanValue());
   1770   CHECK(v8::Number::New(isolate, 1)->BooleanValue());
   1771   CHECK(v8::Number::New(isolate, 42)->BooleanValue());
   1772   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
   1773 }
   1774 
   1775 
   1776 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1777   ApiTestFuzzer::Fuzz();
   1778   args.GetReturnValue().Set(v8_num(13.4));
   1779 }
   1780 
   1781 
   1782 static void GetM(Local<String> name,
   1783                  const v8::PropertyCallbackInfo<v8::Value>& info) {
   1784   ApiTestFuzzer::Fuzz();
   1785   info.GetReturnValue().Set(v8_num(876));
   1786 }
   1787 
   1788 
   1789 THREADED_TEST(GlobalPrototype) {
   1790   v8::Isolate* isolate = CcTest::isolate();
   1791   v8::HandleScope scope(isolate);
   1792   v8::Handle<v8::FunctionTemplate> func_templ =
   1793       v8::FunctionTemplate::New(isolate);
   1794   func_templ->PrototypeTemplate()->Set(
   1795       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
   1796   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
   1797   templ->Set(isolate, "x", v8_num(200));
   1798   templ->SetAccessor(v8_str("m"), GetM);
   1799   LocalContext env(0, templ);
   1800   v8::Handle<Script> script(v8_compile("dummy()"));
   1801   v8::Handle<Value> result(script->Run());
   1802   CHECK_EQ(13.4, result->NumberValue());
   1803   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
   1804   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
   1805 }
   1806 
   1807 
   1808 THREADED_TEST(ObjectTemplate) {
   1809   v8::Isolate* isolate = CcTest::isolate();
   1810   v8::HandleScope scope(isolate);
   1811   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
   1812   templ1->Set(isolate, "x", v8_num(10));
   1813   templ1->Set(isolate, "y", v8_num(13));
   1814   LocalContext env;
   1815   Local<v8::Object> instance1 = templ1->NewInstance();
   1816   env->Global()->Set(v8_str("p"), instance1);
   1817   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
   1818   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
   1819   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
   1820   fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
   1821   Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
   1822   templ2->Set(isolate, "a", v8_num(12));
   1823   templ2->Set(isolate, "b", templ1);
   1824   Local<v8::Object> instance2 = templ2->NewInstance();
   1825   env->Global()->Set(v8_str("q"), instance2);
   1826   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
   1827   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
   1828   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
   1829   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
   1830 }
   1831 
   1832 
   1833 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1834   ApiTestFuzzer::Fuzz();
   1835   args.GetReturnValue().Set(v8_num(17.2));
   1836 }
   1837 
   1838 
   1839 static void GetKnurd(Local<String> property,
   1840                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   1841   ApiTestFuzzer::Fuzz();
   1842   info.GetReturnValue().Set(v8_num(15.2));
   1843 }
   1844 
   1845 
   1846 THREADED_TEST(DescriptorInheritance) {
   1847   v8::Isolate* isolate = CcTest::isolate();
   1848   v8::HandleScope scope(isolate);
   1849   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
   1850   super->PrototypeTemplate()->Set(isolate, "flabby",
   1851                                   v8::FunctionTemplate::New(isolate,
   1852                                                             GetFlabby));
   1853   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
   1854 
   1855   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
   1856 
   1857   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
   1858   base1->Inherit(super);
   1859   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
   1860 
   1861   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
   1862   base2->Inherit(super);
   1863   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
   1864 
   1865   LocalContext env;
   1866 
   1867   env->Global()->Set(v8_str("s"), super->GetFunction());
   1868   env->Global()->Set(v8_str("base1"), base1->GetFunction());
   1869   env->Global()->Set(v8_str("base2"), base2->GetFunction());
   1870 
   1871   // Checks right __proto__ chain.
   1872   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
   1873   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
   1874 
   1875   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
   1876 
   1877   // Instance accessor should not be visible on function object or its prototype
   1878   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
   1879   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
   1880   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
   1881 
   1882   env->Global()->Set(v8_str("obj"),
   1883                      base1->GetFunction()->NewInstance());
   1884   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
   1885   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
   1886   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
   1887   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
   1888   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
   1889 
   1890   env->Global()->Set(v8_str("obj2"),
   1891                      base2->GetFunction()->NewInstance());
   1892   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
   1893   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
   1894   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
   1895   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
   1896   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
   1897 
   1898   // base1 and base2 cannot cross reference to each's prototype
   1899   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
   1900   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
   1901 }
   1902 
   1903 
   1904 int echo_named_call_count;
   1905 
   1906 
   1907 static void EchoNamedProperty(Local<String> name,
   1908                               const v8::PropertyCallbackInfo<v8::Value>& info) {
   1909   ApiTestFuzzer::Fuzz();
   1910   CHECK_EQ(v8_str("data"), info.Data());
   1911   echo_named_call_count++;
   1912   info.GetReturnValue().Set(name);
   1913 }
   1914 
   1915 
   1916 // Helper functions for Interceptor/Accessor interaction tests
   1917 
   1918 void SimpleAccessorGetter(Local<String> name,
   1919                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   1920   Handle<Object> self = Handle<Object>::Cast(info.This());
   1921   info.GetReturnValue().Set(
   1922       self->Get(String::Concat(v8_str("accessor_"), name)));
   1923 }
   1924 
   1925 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
   1926                           const v8::PropertyCallbackInfo<void>& info) {
   1927   Handle<Object> self = Handle<Object>::Cast(info.This());
   1928   self->Set(String::Concat(v8_str("accessor_"), name), value);
   1929 }
   1930 
   1931 void SymbolAccessorGetter(Local<Name> name,
   1932                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   1933   CHECK(name->IsSymbol());
   1934   Local<Symbol> sym = Local<Symbol>::Cast(name);
   1935   if (sym->Name()->IsUndefined())
   1936     return;
   1937   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
   1938 }
   1939 
   1940 void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
   1941                           const v8::PropertyCallbackInfo<void>& info) {
   1942   CHECK(name->IsSymbol());
   1943   Local<Symbol> sym = Local<Symbol>::Cast(name);
   1944   if (sym->Name()->IsUndefined())
   1945     return;
   1946   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
   1947 }
   1948 
   1949 void EmptyInterceptorGetter(Local<String> name,
   1950                             const v8::PropertyCallbackInfo<v8::Value>& info) {
   1951 }
   1952 
   1953 void EmptyInterceptorSetter(Local<String> name,
   1954                             Local<Value> value,
   1955                             const v8::PropertyCallbackInfo<v8::Value>& info) {
   1956 }
   1957 
   1958 void InterceptorGetter(Local<String> name,
   1959                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   1960   // Intercept names that start with 'interceptor_'.
   1961   String::Utf8Value utf8(name);
   1962   char* name_str = *utf8;
   1963   char prefix[] = "interceptor_";
   1964   int i;
   1965   for (i = 0; name_str[i] && prefix[i]; ++i) {
   1966     if (name_str[i] != prefix[i]) return;
   1967   }
   1968   Handle<Object> self = Handle<Object>::Cast(info.This());
   1969   info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
   1970 }
   1971 
   1972 void InterceptorSetter(Local<String> name,
   1973                        Local<Value> value,
   1974                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   1975   // Intercept accesses that set certain integer values, for which the name does
   1976   // not start with 'accessor_'.
   1977   String::Utf8Value utf8(name);
   1978   char* name_str = *utf8;
   1979   char prefix[] = "accessor_";
   1980   int i;
   1981   for (i = 0; name_str[i] && prefix[i]; ++i) {
   1982     if (name_str[i] != prefix[i]) break;
   1983   }
   1984   if (!prefix[i]) return;
   1985 
   1986   if (value->IsInt32() && value->Int32Value() < 10000) {
   1987     Handle<Object> self = Handle<Object>::Cast(info.This());
   1988     self->SetHiddenValue(name, value);
   1989     info.GetReturnValue().Set(value);
   1990   }
   1991 }
   1992 
   1993 void AddAccessor(Handle<FunctionTemplate> templ,
   1994                  Handle<String> name,
   1995                  v8::AccessorGetterCallback getter,
   1996                  v8::AccessorSetterCallback setter) {
   1997   templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
   1998 }
   1999 
   2000 void AddInterceptor(Handle<FunctionTemplate> templ,
   2001                     v8::NamedPropertyGetterCallback getter,
   2002                     v8::NamedPropertySetterCallback setter) {
   2003   templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
   2004 }
   2005 
   2006 
   2007 void AddAccessor(Handle<FunctionTemplate> templ,
   2008                  Handle<Name> name,
   2009                  v8::AccessorNameGetterCallback getter,
   2010                  v8::AccessorNameSetterCallback setter) {
   2011   templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
   2012 }
   2013 
   2014 
   2015 THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
   2016   v8::HandleScope scope(CcTest::isolate());
   2017   Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
   2018   Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
   2019   child->Inherit(parent);
   2020   AddAccessor(parent, v8_str("age"),
   2021               SimpleAccessorGetter, SimpleAccessorSetter);
   2022   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   2023   LocalContext env;
   2024   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2025   CompileRun("var child = new Child;"
   2026              "child.age = 10;");
   2027   ExpectBoolean("child.hasOwnProperty('age')", false);
   2028   ExpectInt32("child.age", 10);
   2029   ExpectInt32("child.accessor_age", 10);
   2030 }
   2031 
   2032 
   2033 THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
   2034   v8::Isolate* isolate = CcTest::isolate();
   2035   v8::HandleScope scope(isolate);
   2036   LocalContext env;
   2037   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
   2038   i::Handle<i::JSObject> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
   2039   CHECK(a->map()->instance_descriptors()->IsFixedArray());
   2040   CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
   2041   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
   2042   CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
   2043   // But we should still have an ExecutableAccessorInfo.
   2044   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   2045   i::LookupResult lookup(i_isolate);
   2046   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
   2047   i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
   2048   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
   2049   CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
   2050 }
   2051 
   2052 
   2053 THREADED_TEST(EmptyInterceptorBreakTransitions) {
   2054   v8::HandleScope scope(CcTest::isolate());
   2055   Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
   2056   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   2057   LocalContext env;
   2058   env->Global()->Set(v8_str("Constructor"), templ->GetFunction());
   2059   CompileRun("var o1 = new Constructor;"
   2060              "o1.a = 1;"  // Ensure a and x share the descriptor array.
   2061              "Object.defineProperty(o1, 'x', {value: 10});");
   2062   CompileRun("var o2 = new Constructor;"
   2063              "o2.a = 1;"
   2064              "Object.defineProperty(o2, 'x', {value: 10});");
   2065 }
   2066 
   2067 
   2068 THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
   2069   v8::Isolate* isolate = CcTest::isolate();
   2070   v8::HandleScope scope(isolate);
   2071   Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
   2072   Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
   2073   child->Inherit(parent);
   2074   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   2075   LocalContext env;
   2076   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2077   CompileRun("var child = new Child;"
   2078              "var parent = child.__proto__;"
   2079              "Object.defineProperty(parent, 'age', "
   2080              "  {get: function(){ return this.accessor_age; }, "
   2081              "   set: function(v){ this.accessor_age = v; }, "
   2082              "   enumerable: true, configurable: true});"
   2083              "child.age = 10;");
   2084   ExpectBoolean("child.hasOwnProperty('age')", false);
   2085   ExpectInt32("child.age", 10);
   2086   ExpectInt32("child.accessor_age", 10);
   2087 }
   2088 
   2089 
   2090 THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
   2091   v8::Isolate* isolate = CcTest::isolate();
   2092   v8::HandleScope scope(isolate);
   2093   Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
   2094   Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
   2095   child->Inherit(parent);
   2096   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   2097   LocalContext env;
   2098   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2099   CompileRun("var child = new Child;"
   2100              "var parent = child.__proto__;"
   2101              "parent.name = 'Alice';");
   2102   ExpectBoolean("child.hasOwnProperty('name')", false);
   2103   ExpectString("child.name", "Alice");
   2104   CompileRun("child.name = 'Bob';");
   2105   ExpectString("child.name", "Bob");
   2106   ExpectBoolean("child.hasOwnProperty('name')", true);
   2107   ExpectString("parent.name", "Alice");
   2108 }
   2109 
   2110 
   2111 THREADED_TEST(SwitchFromInterceptorToAccessor) {
   2112   v8::HandleScope scope(CcTest::isolate());
   2113   Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
   2114   AddAccessor(templ, v8_str("age"),
   2115               SimpleAccessorGetter, SimpleAccessorSetter);
   2116   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   2117   LocalContext env;
   2118   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   2119   CompileRun("var obj = new Obj;"
   2120              "function setAge(i){ obj.age = i; };"
   2121              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2122   // All i < 10000 go to the interceptor.
   2123   ExpectInt32("obj.interceptor_age", 9999);
   2124   // The last i goes to the accessor.
   2125   ExpectInt32("obj.accessor_age", 10000);
   2126 }
   2127 
   2128 
   2129 THREADED_TEST(SwitchFromAccessorToInterceptor) {
   2130   v8::HandleScope scope(CcTest::isolate());
   2131   Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
   2132   AddAccessor(templ, v8_str("age"),
   2133               SimpleAccessorGetter, SimpleAccessorSetter);
   2134   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   2135   LocalContext env;
   2136   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   2137   CompileRun("var obj = new Obj;"
   2138              "function setAge(i){ obj.age = i; };"
   2139              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2140   // All i >= 10000 go to the accessor.
   2141   ExpectInt32("obj.accessor_age", 10000);
   2142   // The last i goes to the interceptor.
   2143   ExpectInt32("obj.interceptor_age", 9999);
   2144 }
   2145 
   2146 
   2147 THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
   2148   v8::HandleScope scope(CcTest::isolate());
   2149   Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
   2150   Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
   2151   child->Inherit(parent);
   2152   AddAccessor(parent, v8_str("age"),
   2153               SimpleAccessorGetter, SimpleAccessorSetter);
   2154   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2155   LocalContext env;
   2156   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2157   CompileRun("var child = new Child;"
   2158              "function setAge(i){ child.age = i; };"
   2159              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2160   // All i < 10000 go to the interceptor.
   2161   ExpectInt32("child.interceptor_age", 9999);
   2162   // The last i goes to the accessor.
   2163   ExpectInt32("child.accessor_age", 10000);
   2164 }
   2165 
   2166 
   2167 THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
   2168   v8::HandleScope scope(CcTest::isolate());
   2169   Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
   2170   Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
   2171   child->Inherit(parent);
   2172   AddAccessor(parent, v8_str("age"),
   2173               SimpleAccessorGetter, SimpleAccessorSetter);
   2174   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2175   LocalContext env;
   2176   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2177   CompileRun("var child = new Child;"
   2178              "function setAge(i){ child.age = i; };"
   2179              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2180   // All i >= 10000 go to the accessor.
   2181   ExpectInt32("child.accessor_age", 10000);
   2182   // The last i goes to the interceptor.
   2183   ExpectInt32("child.interceptor_age", 9999);
   2184 }
   2185 
   2186 
   2187 THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
   2188   v8::HandleScope scope(CcTest::isolate());
   2189   Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
   2190   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   2191   LocalContext env;
   2192   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   2193   CompileRun("var obj = new Obj;"
   2194              "function setter(i) { this.accessor_age = i; };"
   2195              "function getter() { return this.accessor_age; };"
   2196              "function setAge(i) { obj.age = i; };"
   2197              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   2198              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2199   // All i < 10000 go to the interceptor.
   2200   ExpectInt32("obj.interceptor_age", 9999);
   2201   // The last i goes to the JavaScript accessor.
   2202   ExpectInt32("obj.accessor_age", 10000);
   2203   // The installed JavaScript getter is still intact.
   2204   // This last part is a regression test for issue 1651 and relies on the fact
   2205   // that both interceptor and accessor are being installed on the same object.
   2206   ExpectInt32("obj.age", 10000);
   2207   ExpectBoolean("obj.hasOwnProperty('age')", true);
   2208   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
   2209 }
   2210 
   2211 
   2212 THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
   2213   v8::HandleScope scope(CcTest::isolate());
   2214   Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
   2215   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   2216   LocalContext env;
   2217   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   2218   CompileRun("var obj = new Obj;"
   2219              "function setter(i) { this.accessor_age = i; };"
   2220              "function getter() { return this.accessor_age; };"
   2221              "function setAge(i) { obj.age = i; };"
   2222              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   2223              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2224   // All i >= 10000 go to the accessor.
   2225   ExpectInt32("obj.accessor_age", 10000);
   2226   // The last i goes to the interceptor.
   2227   ExpectInt32("obj.interceptor_age", 9999);
   2228   // The installed JavaScript getter is still intact.
   2229   // This last part is a regression test for issue 1651 and relies on the fact
   2230   // that both interceptor and accessor are being installed on the same object.
   2231   ExpectInt32("obj.age", 10000);
   2232   ExpectBoolean("obj.hasOwnProperty('age')", true);
   2233   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
   2234 }
   2235 
   2236 
   2237 THREADED_TEST(SwitchFromInterceptorToProperty) {
   2238   v8::HandleScope scope(CcTest::isolate());
   2239   Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
   2240   Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
   2241   child->Inherit(parent);
   2242   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2243   LocalContext env;
   2244   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2245   CompileRun("var child = new Child;"
   2246              "function setAge(i){ child.age = i; };"
   2247              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2248   // All i < 10000 go to the interceptor.
   2249   ExpectInt32("child.interceptor_age", 9999);
   2250   // The last i goes to child's own property.
   2251   ExpectInt32("child.age", 10000);
   2252 }
   2253 
   2254 
   2255 THREADED_TEST(SwitchFromPropertyToInterceptor) {
   2256   v8::HandleScope scope(CcTest::isolate());
   2257   Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
   2258   Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
   2259   child->Inherit(parent);
   2260   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2261   LocalContext env;
   2262   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2263   CompileRun("var child = new Child;"
   2264              "function setAge(i){ child.age = i; };"
   2265              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2266   // All i >= 10000 go to child's own property.
   2267   ExpectInt32("child.age", 10000);
   2268   // The last i goes to the interceptor.
   2269   ExpectInt32("child.interceptor_age", 9999);
   2270 }
   2271 
   2272 
   2273 THREADED_TEST(NamedPropertyHandlerGetter) {
   2274   echo_named_call_count = 0;
   2275   v8::HandleScope scope(CcTest::isolate());
   2276   v8::Handle<v8::FunctionTemplate> templ =
   2277       v8::FunctionTemplate::New(CcTest::isolate());
   2278   templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
   2279                                                      0, 0, 0, 0,
   2280                                                      v8_str("data"));
   2281   LocalContext env;
   2282   env->Global()->Set(v8_str("obj"),
   2283                      templ->GetFunction()->NewInstance());
   2284   CHECK_EQ(echo_named_call_count, 0);
   2285   v8_compile("obj.x")->Run();
   2286   CHECK_EQ(echo_named_call_count, 1);
   2287   const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
   2288   v8::Handle<Value> str = CompileRun(code);
   2289   String::Utf8Value value(str);
   2290   CHECK_EQ(*value, "oddlepoddle");
   2291   // Check default behavior
   2292   CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
   2293   CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
   2294   CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
   2295 }
   2296 
   2297 
   2298 int echo_indexed_call_count = 0;
   2299 
   2300 
   2301 static void EchoIndexedProperty(
   2302     uint32_t index,
   2303     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2304   ApiTestFuzzer::Fuzz();
   2305   CHECK_EQ(v8_num(637), info.Data());
   2306   echo_indexed_call_count++;
   2307   info.GetReturnValue().Set(v8_num(index));
   2308 }
   2309 
   2310 
   2311 THREADED_TEST(IndexedPropertyHandlerGetter) {
   2312   v8::Isolate* isolate = CcTest::isolate();
   2313   v8::HandleScope scope(isolate);
   2314   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   2315   templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
   2316                                                        0, 0, 0, 0,
   2317                                                        v8_num(637));
   2318   LocalContext env;
   2319   env->Global()->Set(v8_str("obj"),
   2320                      templ->GetFunction()->NewInstance());
   2321   Local<Script> script = v8_compile("obj[900]");
   2322   CHECK_EQ(script->Run()->Int32Value(), 900);
   2323 }
   2324 
   2325 
   2326 v8::Handle<v8::Object> bottom;
   2327 
   2328 static void CheckThisIndexedPropertyHandler(
   2329     uint32_t index,
   2330     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2331   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
   2332   ApiTestFuzzer::Fuzz();
   2333   CHECK(info.This()->Equals(bottom));
   2334 }
   2335 
   2336 static void CheckThisNamedPropertyHandler(
   2337     Local<String> name,
   2338     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2339   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
   2340   ApiTestFuzzer::Fuzz();
   2341   CHECK(info.This()->Equals(bottom));
   2342 }
   2343 
   2344 void CheckThisIndexedPropertySetter(
   2345     uint32_t index,
   2346     Local<Value> value,
   2347     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2348   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
   2349   ApiTestFuzzer::Fuzz();
   2350   CHECK(info.This()->Equals(bottom));
   2351 }
   2352 
   2353 
   2354 void CheckThisNamedPropertySetter(
   2355     Local<String> property,
   2356     Local<Value> value,
   2357     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2358   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
   2359   ApiTestFuzzer::Fuzz();
   2360   CHECK(info.This()->Equals(bottom));
   2361 }
   2362 
   2363 void CheckThisIndexedPropertyQuery(
   2364     uint32_t index,
   2365     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   2366   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
   2367   ApiTestFuzzer::Fuzz();
   2368   CHECK(info.This()->Equals(bottom));
   2369 }
   2370 
   2371 
   2372 void CheckThisNamedPropertyQuery(
   2373     Local<String> property,
   2374     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   2375   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
   2376   ApiTestFuzzer::Fuzz();
   2377   CHECK(info.This()->Equals(bottom));
   2378 }
   2379 
   2380 
   2381 void CheckThisIndexedPropertyDeleter(
   2382     uint32_t index,
   2383     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   2384   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
   2385   ApiTestFuzzer::Fuzz();
   2386   CHECK(info.This()->Equals(bottom));
   2387 }
   2388 
   2389 
   2390 void CheckThisNamedPropertyDeleter(
   2391     Local<String> property,
   2392     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   2393   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
   2394   ApiTestFuzzer::Fuzz();
   2395   CHECK(info.This()->Equals(bottom));
   2396 }
   2397 
   2398 
   2399 void CheckThisIndexedPropertyEnumerator(
   2400     const v8::PropertyCallbackInfo<v8::Array>& info) {
   2401   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
   2402   ApiTestFuzzer::Fuzz();
   2403   CHECK(info.This()->Equals(bottom));
   2404 }
   2405 
   2406 
   2407 void CheckThisNamedPropertyEnumerator(
   2408     const v8::PropertyCallbackInfo<v8::Array>& info) {
   2409   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
   2410   ApiTestFuzzer::Fuzz();
   2411   CHECK(info.This()->Equals(bottom));
   2412 }
   2413 
   2414 
   2415 THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
   2416   LocalContext env;
   2417   v8::Isolate* isolate = env->GetIsolate();
   2418   v8::HandleScope scope(isolate);
   2419 
   2420   // Set up a prototype chain with three interceptors.
   2421   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   2422   templ->InstanceTemplate()->SetIndexedPropertyHandler(
   2423       CheckThisIndexedPropertyHandler,
   2424       CheckThisIndexedPropertySetter,
   2425       CheckThisIndexedPropertyQuery,
   2426       CheckThisIndexedPropertyDeleter,
   2427       CheckThisIndexedPropertyEnumerator);
   2428 
   2429   templ->InstanceTemplate()->SetNamedPropertyHandler(
   2430       CheckThisNamedPropertyHandler,
   2431       CheckThisNamedPropertySetter,
   2432       CheckThisNamedPropertyQuery,
   2433       CheckThisNamedPropertyDeleter,
   2434       CheckThisNamedPropertyEnumerator);
   2435 
   2436   bottom = templ->GetFunction()->NewInstance();
   2437   Local<v8::Object> top = templ->GetFunction()->NewInstance();
   2438   Local<v8::Object> middle = templ->GetFunction()->NewInstance();
   2439 
   2440   bottom->SetPrototype(middle);
   2441   middle->SetPrototype(top);
   2442   env->Global()->Set(v8_str("obj"), bottom);
   2443 
   2444   // Indexed and named get.
   2445   CompileRun("obj[0]");
   2446   CompileRun("obj.x");
   2447 
   2448   // Indexed and named set.
   2449   CompileRun("obj[1] = 42");
   2450   CompileRun("obj.y = 42");
   2451 
   2452   // Indexed and named query.
   2453   CompileRun("0 in obj");
   2454   CompileRun("'x' in obj");
   2455 
   2456   // Indexed and named deleter.
   2457   CompileRun("delete obj[0]");
   2458   CompileRun("delete obj.x");
   2459 
   2460   // Enumerators.
   2461   CompileRun("for (var p in obj) ;");
   2462 }
   2463 
   2464 
   2465 static void PrePropertyHandlerGet(
   2466     Local<String> key,
   2467     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2468   ApiTestFuzzer::Fuzz();
   2469   if (v8_str("pre")->Equals(key)) {
   2470     info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
   2471   }
   2472 }
   2473 
   2474 
   2475 static void PrePropertyHandlerQuery(
   2476     Local<String> key,
   2477     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   2478   if (v8_str("pre")->Equals(key)) {
   2479     info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
   2480   }
   2481 }
   2482 
   2483 
   2484 THREADED_TEST(PrePropertyHandler) {
   2485   v8::Isolate* isolate = CcTest::isolate();
   2486   v8::HandleScope scope(isolate);
   2487   v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   2488   desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
   2489                                                     0,
   2490                                                     PrePropertyHandlerQuery);
   2491   LocalContext env(NULL, desc->InstanceTemplate());
   2492   CompileRun("var pre = 'Object: pre'; var on = 'Object: on';");
   2493   v8::Handle<Value> result_pre = CompileRun("pre");
   2494   CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
   2495   v8::Handle<Value> result_on = CompileRun("on");
   2496   CHECK_EQ(v8_str("Object: on"), result_on);
   2497   v8::Handle<Value> result_post = CompileRun("post");
   2498   CHECK(result_post.IsEmpty());
   2499 }
   2500 
   2501 
   2502 THREADED_TEST(UndefinedIsNotEnumerable) {
   2503   LocalContext env;
   2504   v8::HandleScope scope(env->GetIsolate());
   2505   v8::Handle<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
   2506   CHECK(result->IsFalse());
   2507 }
   2508 
   2509 
   2510 v8::Handle<Script> call_recursively_script;
   2511 static const int kTargetRecursionDepth = 200;  // near maximum
   2512 
   2513 
   2514 static void CallScriptRecursivelyCall(
   2515     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2516   ApiTestFuzzer::Fuzz();
   2517   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   2518   if (depth == kTargetRecursionDepth) return;
   2519   args.This()->Set(v8_str("depth"),
   2520                    v8::Integer::New(args.GetIsolate(), depth + 1));
   2521   args.GetReturnValue().Set(call_recursively_script->Run());
   2522 }
   2523 
   2524 
   2525 static void CallFunctionRecursivelyCall(
   2526     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2527   ApiTestFuzzer::Fuzz();
   2528   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   2529   if (depth == kTargetRecursionDepth) {
   2530     printf("[depth = %d]\n", depth);
   2531     return;
   2532   }
   2533   args.This()->Set(v8_str("depth"),
   2534                    v8::Integer::New(args.GetIsolate(), depth + 1));
   2535   v8::Handle<Value> function =
   2536       args.This()->Get(v8_str("callFunctionRecursively"));
   2537   args.GetReturnValue().Set(
   2538       function.As<Function>()->Call(args.This(), 0, NULL));
   2539 }
   2540 
   2541 
   2542 THREADED_TEST(DeepCrossLanguageRecursion) {
   2543   v8::Isolate* isolate = CcTest::isolate();
   2544   v8::HandleScope scope(isolate);
   2545   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
   2546   global->Set(v8_str("callScriptRecursively"),
   2547               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
   2548   global->Set(v8_str("callFunctionRecursively"),
   2549               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
   2550   LocalContext env(NULL, global);
   2551 
   2552   env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
   2553   call_recursively_script = v8_compile("callScriptRecursively()");
   2554   call_recursively_script->Run();
   2555   call_recursively_script = v8::Handle<Script>();
   2556 
   2557   env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
   2558   CompileRun("callFunctionRecursively()");
   2559 }
   2560 
   2561 
   2562 static void ThrowingPropertyHandlerGet(
   2563     Local<String> key,
   2564     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2565   ApiTestFuzzer::Fuzz();
   2566   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
   2567 }
   2568 
   2569 
   2570 static void ThrowingPropertyHandlerSet(
   2571     Local<String> key,
   2572     Local<Value>,
   2573     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2574   info.GetIsolate()->ThrowException(key);
   2575   info.GetReturnValue().SetUndefined();  // not the same as empty handle
   2576 }
   2577 
   2578 
   2579 THREADED_TEST(CallbackExceptionRegression) {
   2580   v8::Isolate* isolate = CcTest::isolate();
   2581   v8::HandleScope scope(isolate);
   2582   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   2583   obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
   2584                                ThrowingPropertyHandlerSet);
   2585   LocalContext env;
   2586   env->Global()->Set(v8_str("obj"), obj->NewInstance());
   2587   v8::Handle<Value> otto = CompileRun(
   2588       "try { with (obj) { otto; } } catch (e) { e; }");
   2589   CHECK_EQ(v8_str("otto"), otto);
   2590   v8::Handle<Value> netto = CompileRun(
   2591       "try { with (obj) { netto = 4; } } catch (e) { e; }");
   2592   CHECK_EQ(v8_str("netto"), netto);
   2593 }
   2594 
   2595 
   2596 THREADED_TEST(FunctionPrototype) {
   2597   v8::Isolate* isolate = CcTest::isolate();
   2598   v8::HandleScope scope(isolate);
   2599   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
   2600   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
   2601   LocalContext env;
   2602   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
   2603   Local<Script> script = v8_compile("Foo.prototype.plak");
   2604   CHECK_EQ(script->Run()->Int32Value(), 321);
   2605 }
   2606 
   2607 
   2608 THREADED_TEST(InternalFields) {
   2609   LocalContext env;
   2610   v8::Isolate* isolate = env->GetIsolate();
   2611   v8::HandleScope scope(isolate);
   2612 
   2613   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   2614   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2615   instance_templ->SetInternalFieldCount(1);
   2616   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   2617   CHECK_EQ(1, obj->InternalFieldCount());
   2618   CHECK(obj->GetInternalField(0)->IsUndefined());
   2619   obj->SetInternalField(0, v8_num(17));
   2620   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
   2621 }
   2622 
   2623 
   2624 THREADED_TEST(GlobalObjectInternalFields) {
   2625   v8::Isolate* isolate = CcTest::isolate();
   2626   v8::HandleScope scope(isolate);
   2627   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   2628   global_template->SetInternalFieldCount(1);
   2629   LocalContext env(NULL, global_template);
   2630   v8::Handle<v8::Object> global_proxy = env->Global();
   2631   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
   2632   CHECK_EQ(1, global->InternalFieldCount());
   2633   CHECK(global->GetInternalField(0)->IsUndefined());
   2634   global->SetInternalField(0, v8_num(17));
   2635   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
   2636 }
   2637 
   2638 
   2639 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
   2640   LocalContext env;
   2641   v8::HandleScope scope(CcTest::isolate());
   2642 
   2643   v8::Local<v8::Object> global = env->Global();
   2644   global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
   2645   CHECK(global->HasRealIndexedProperty(0));
   2646 }
   2647 
   2648 
   2649 static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
   2650                                                void* value) {
   2651   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2652   obj->SetAlignedPointerInInternalField(0, value);
   2653   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2654   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
   2655 }
   2656 
   2657 
   2658 THREADED_TEST(InternalFieldsAlignedPointers) {
   2659   LocalContext env;
   2660   v8::Isolate* isolate = env->GetIsolate();
   2661   v8::HandleScope scope(isolate);
   2662 
   2663   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   2664   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2665   instance_templ->SetInternalFieldCount(1);
   2666   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   2667   CHECK_EQ(1, obj->InternalFieldCount());
   2668 
   2669   CheckAlignedPointerInInternalField(obj, NULL);
   2670 
   2671   int* heap_allocated = new int[100];
   2672   CheckAlignedPointerInInternalField(obj, heap_allocated);
   2673   delete[] heap_allocated;
   2674 
   2675   int stack_allocated[100];
   2676   CheckAlignedPointerInInternalField(obj, stack_allocated);
   2677 
   2678   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2679   CheckAlignedPointerInInternalField(obj, huge);
   2680 
   2681   v8::UniquePersistent<v8::Object> persistent(isolate, obj);
   2682   CHECK_EQ(1, Object::InternalFieldCount(persistent));
   2683   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
   2684 }
   2685 
   2686 
   2687 static void CheckAlignedPointerInEmbedderData(LocalContext* env,
   2688                                               int index,
   2689                                               void* value) {
   2690   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2691   (*env)->SetAlignedPointerInEmbedderData(index, value);
   2692   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2693   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
   2694 }
   2695 
   2696 
   2697 static void* AlignedTestPointer(int i) {
   2698   return reinterpret_cast<void*>(i * 1234);
   2699 }
   2700 
   2701 
   2702 THREADED_TEST(EmbedderDataAlignedPointers) {
   2703   LocalContext env;
   2704   v8::HandleScope scope(env->GetIsolate());
   2705 
   2706   CheckAlignedPointerInEmbedderData(&env, 0, NULL);
   2707 
   2708   int* heap_allocated = new int[100];
   2709   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
   2710   delete[] heap_allocated;
   2711 
   2712   int stack_allocated[100];
   2713   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
   2714 
   2715   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2716   CheckAlignedPointerInEmbedderData(&env, 3, huge);
   2717 
   2718   // Test growing of the embedder data's backing store.
   2719   for (int i = 0; i < 100; i++) {
   2720     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
   2721   }
   2722   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2723   for (int i = 0; i < 100; i++) {
   2724     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
   2725   }
   2726 }
   2727 
   2728 
   2729 static void CheckEmbedderData(LocalContext* env,
   2730                               int index,
   2731                               v8::Handle<Value> data) {
   2732   (*env)->SetEmbedderData(index, data);
   2733   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
   2734 }
   2735 
   2736 
   2737 THREADED_TEST(EmbedderData) {
   2738   LocalContext env;
   2739   v8::Isolate* isolate = env->GetIsolate();
   2740   v8::HandleScope scope(isolate);
   2741 
   2742   CheckEmbedderData(
   2743       &env, 3,
   2744       v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
   2745   CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(isolate,
   2746                                                      "over the lazy dog."));
   2747   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
   2748   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
   2749 }
   2750 
   2751 
   2752 THREADED_TEST(IdentityHash) {
   2753   LocalContext env;
   2754   v8::Isolate* isolate = env->GetIsolate();
   2755   v8::HandleScope scope(isolate);
   2756 
   2757   // Ensure that the test starts with an fresh heap to test whether the hash
   2758   // code is based on the address.
   2759   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2760   Local<v8::Object> obj = v8::Object::New(isolate);
   2761   int hash = obj->GetIdentityHash();
   2762   int hash1 = obj->GetIdentityHash();
   2763   CHECK_EQ(hash, hash1);
   2764   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
   2765   // Since the identity hash is essentially a random number two consecutive
   2766   // objects should not be assigned the same hash code. If the test below fails
   2767   // the random number generator should be evaluated.
   2768   CHECK_NE(hash, hash2);
   2769   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2770   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
   2771   // Make sure that the identity hash is not based on the initial address of
   2772   // the object alone. If the test below fails the random number generator
   2773   // should be evaluated.
   2774   CHECK_NE(hash, hash3);
   2775   int hash4 = obj->GetIdentityHash();
   2776   CHECK_EQ(hash, hash4);
   2777 
   2778   // Check identity hashes behaviour in the presence of JS accessors.
   2779   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
   2780   {
   2781     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
   2782     Local<v8::Object> o1 = v8::Object::New(isolate);
   2783     Local<v8::Object> o2 = v8::Object::New(isolate);
   2784     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2785   }
   2786   {
   2787     CompileRun(
   2788         "function cnst() { return 42; };\n"
   2789         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
   2790     Local<v8::Object> o1 = v8::Object::New(isolate);
   2791     Local<v8::Object> o2 = v8::Object::New(isolate);
   2792     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2793   }
   2794 }
   2795 
   2796 
   2797 THREADED_TEST(GlobalProxyIdentityHash) {
   2798   LocalContext env;
   2799   v8::Isolate* isolate = env->GetIsolate();
   2800   v8::HandleScope scope(isolate);
   2801   Handle<Object> global_proxy = env->Global();
   2802   int hash1 = global_proxy->GetIdentityHash();
   2803   // Hash should be retained after being detached.
   2804   env->DetachGlobal();
   2805   int hash2 = global_proxy->GetIdentityHash();
   2806   CHECK_EQ(hash1, hash2);
   2807   {
   2808     // Re-attach global proxy to a new context, hash should stay the same.
   2809     LocalContext env2(NULL, Handle<ObjectTemplate>(), global_proxy);
   2810     int hash3 = global_proxy->GetIdentityHash();
   2811     CHECK_EQ(hash1, hash3);
   2812   }
   2813 }
   2814 
   2815 
   2816 THREADED_TEST(SymbolProperties) {
   2817   LocalContext env;
   2818   v8::Isolate* isolate = env->GetIsolate();
   2819   v8::HandleScope scope(isolate);
   2820 
   2821   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   2822   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
   2823   v8::Local<v8::Symbol> sym2 =
   2824       v8::Symbol::New(isolate, v8_str("my-symbol"));
   2825   v8::Local<v8::Symbol> sym3 =
   2826       v8::Symbol::New(isolate, v8_str("sym3"));
   2827 
   2828   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2829 
   2830   // Check basic symbol functionality.
   2831   CHECK(sym1->IsSymbol());
   2832   CHECK(sym2->IsSymbol());
   2833   CHECK(!obj->IsSymbol());
   2834 
   2835   CHECK(sym1->Equals(sym1));
   2836   CHECK(sym2->Equals(sym2));
   2837   CHECK(!sym1->Equals(sym2));
   2838   CHECK(!sym2->Equals(sym1));
   2839   CHECK(sym1->StrictEquals(sym1));
   2840   CHECK(sym2->StrictEquals(sym2));
   2841   CHECK(!sym1->StrictEquals(sym2));
   2842   CHECK(!sym2->StrictEquals(sym1));
   2843 
   2844   CHECK(sym2->Name()->Equals(v8_str("my-symbol")));
   2845 
   2846   v8::Local<v8::Value> sym_val = sym2;
   2847   CHECK(sym_val->IsSymbol());
   2848   CHECK(sym_val->Equals(sym2));
   2849   CHECK(sym_val->StrictEquals(sym2));
   2850   CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
   2851 
   2852   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
   2853   CHECK(sym_obj->IsSymbolObject());
   2854   CHECK(!sym2->IsSymbolObject());
   2855   CHECK(!obj->IsSymbolObject());
   2856   CHECK(!sym_obj->Equals(sym2));
   2857   CHECK(!sym_obj->StrictEquals(sym2));
   2858   CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
   2859   CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
   2860 
   2861   // Make sure delete of a non-existent symbol property works.
   2862   CHECK(obj->Delete(sym1));
   2863   CHECK(!obj->Has(sym1));
   2864 
   2865   CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
   2866   CHECK(obj->Has(sym1));
   2867   CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
   2868   CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
   2869   CHECK(obj->Has(sym1));
   2870   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2871   CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
   2872 
   2873   CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
   2874   int num_props = obj->GetPropertyNames()->Length();
   2875   CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
   2876                  v8::Integer::New(isolate, 20)));
   2877   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2878   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
   2879 
   2880   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2881 
   2882   CHECK(obj->SetAccessor(sym3, SymbolAccessorGetter, SymbolAccessorSetter));
   2883   CHECK(obj->Get(sym3)->IsUndefined());
   2884   CHECK(obj->Set(sym3, v8::Integer::New(isolate, 42)));
   2885   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
   2886   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))->Equals(
   2887       v8::Integer::New(isolate, 42)));
   2888 
   2889   // Add another property and delete it afterwards to force the object in
   2890   // slow case.
   2891   CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
   2892   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2893   CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
   2894   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2895   CHECK_EQ(2, obj->GetOwnPropertyNames()->Length());
   2896 
   2897   CHECK(obj->Has(sym1));
   2898   CHECK(obj->Has(sym2));
   2899   CHECK(obj->Has(sym3));
   2900   CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
   2901   CHECK(obj->Delete(sym2));
   2902   CHECK(obj->Has(sym1));
   2903   CHECK(!obj->Has(sym2));
   2904   CHECK(obj->Has(sym3));
   2905   CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
   2906   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2907   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
   2908   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))->Equals(
   2909       v8::Integer::New(isolate, 42)));
   2910   CHECK_EQ(2, obj->GetOwnPropertyNames()->Length());
   2911 
   2912   // Symbol properties are inherited.
   2913   v8::Local<v8::Object> child = v8::Object::New(isolate);
   2914   child->SetPrototype(obj);
   2915   CHECK(child->Has(sym1));
   2916   CHECK_EQ(2002, child->Get(sym1)->Int32Value());
   2917   CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
   2918   CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))->Equals(
   2919       v8::Integer::New(isolate, 42)));
   2920   CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
   2921 }
   2922 
   2923 
   2924 THREADED_TEST(SymbolTemplateProperties) {
   2925   LocalContext env;
   2926   v8::Isolate* isolate = env->GetIsolate();
   2927   v8::HandleScope scope(isolate);
   2928   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
   2929   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
   2930   CHECK(!name.IsEmpty());
   2931   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
   2932   v8::Local<v8::Object> new_instance = foo->InstanceTemplate()->NewInstance();
   2933   CHECK(!new_instance.IsEmpty());
   2934   CHECK(new_instance->Has(name));
   2935 }
   2936 
   2937 
   2938 THREADED_TEST(PrivateProperties) {
   2939   LocalContext env;
   2940   v8::Isolate* isolate = env->GetIsolate();
   2941   v8::HandleScope scope(isolate);
   2942 
   2943   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   2944   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
   2945   v8::Local<v8::Private> priv2 =
   2946       v8::Private::New(isolate, v8_str("my-private"));
   2947 
   2948   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2949 
   2950   CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
   2951 
   2952   // Make sure delete of a non-existent private symbol property works.
   2953   CHECK(obj->DeletePrivate(priv1));
   2954   CHECK(!obj->HasPrivate(priv1));
   2955 
   2956   CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
   2957   CHECK(obj->HasPrivate(priv1));
   2958   CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
   2959   CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
   2960   CHECK(obj->HasPrivate(priv1));
   2961   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
   2962 
   2963   CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
   2964   int num_props = obj->GetPropertyNames()->Length();
   2965   CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
   2966                  v8::Integer::New(isolate, 20)));
   2967   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2968   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
   2969 
   2970   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   2971 
   2972   // Add another property and delete it afterwards to force the object in
   2973   // slow case.
   2974   CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
   2975   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
   2976   CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
   2977   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
   2978   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2979 
   2980   CHECK(obj->HasPrivate(priv1));
   2981   CHECK(obj->HasPrivate(priv2));
   2982   CHECK(obj->DeletePrivate(priv2));
   2983   CHECK(obj->HasPrivate(priv1));
   2984   CHECK(!obj->HasPrivate(priv2));
   2985   CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
   2986   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2987 
   2988   // Private properties are inherited (for the time being).
   2989   v8::Local<v8::Object> child = v8::Object::New(isolate);
   2990   child->SetPrototype(obj);
   2991   CHECK(child->HasPrivate(priv1));
   2992   CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
   2993   CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
   2994 }
   2995 
   2996 
   2997 THREADED_TEST(GlobalSymbols) {
   2998   LocalContext env;
   2999   v8::Isolate* isolate = env->GetIsolate();
   3000   v8::HandleScope scope(isolate);
   3001 
   3002   v8::Local<String> name = v8_str("my-symbol");
   3003   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
   3004   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
   3005   CHECK(glob2->SameValue(glob));
   3006 
   3007   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
   3008   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
   3009   CHECK(glob_api2->SameValue(glob_api));
   3010   CHECK(!glob_api->SameValue(glob));
   3011 
   3012   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
   3013   CHECK(!sym->SameValue(glob));
   3014 
   3015   CompileRun("var sym2 = Symbol.for('my-symbol')");
   3016   v8::Local<Value> sym2 = env->Global()->Get(v8_str("sym2"));
   3017   CHECK(sym2->SameValue(glob));
   3018   CHECK(!sym2->SameValue(glob_api));
   3019 }
   3020 
   3021 
   3022 static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
   3023                                  const char* name) {
   3024   LocalContext env;
   3025   v8::Isolate* isolate = env->GetIsolate();
   3026   v8::HandleScope scope(isolate);
   3027 
   3028   v8::Local<v8::Symbol> symbol = getter(isolate);
   3029   std::string script = std::string("var sym = ") + name;
   3030   CompileRun(script.c_str());
   3031   v8::Local<Value> value = env->Global()->Get(v8_str("sym"));
   3032 
   3033   CHECK(!value.IsEmpty());
   3034   CHECK(!symbol.IsEmpty());
   3035   CHECK(value->SameValue(symbol));
   3036 }
   3037 
   3038 
   3039 THREADED_TEST(WellKnownSymbols) {
   3040   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
   3041   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
   3042 }
   3043 
   3044 
   3045 THREADED_TEST(GlobalPrivates) {
   3046   LocalContext env;
   3047   v8::Isolate* isolate = env->GetIsolate();
   3048   v8::HandleScope scope(isolate);
   3049 
   3050   v8::Local<String> name = v8_str("my-private");
   3051   v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
   3052   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   3053   CHECK(obj->SetPrivate(glob, v8::Integer::New(isolate, 3)));
   3054 
   3055   v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
   3056   CHECK(obj->HasPrivate(glob2));
   3057 
   3058   v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
   3059   CHECK(!obj->HasPrivate(priv));
   3060 
   3061   CompileRun("var intern = %CreateGlobalPrivateSymbol('my-private')");
   3062   v8::Local<Value> intern = env->Global()->Get(v8_str("intern"));
   3063   CHECK(!obj->Has(intern));
   3064 }
   3065 
   3066 
   3067 class ScopedArrayBufferContents {
   3068  public:
   3069   explicit ScopedArrayBufferContents(
   3070       const v8::ArrayBuffer::Contents& contents)
   3071     : contents_(contents) {}
   3072   ~ScopedArrayBufferContents() { free(contents_.Data()); }
   3073   void* Data() const { return contents_.Data(); }
   3074   size_t ByteLength() const { return contents_.ByteLength(); }
   3075  private:
   3076   const v8::ArrayBuffer::Contents contents_;
   3077 };
   3078 
   3079 template <typename T>
   3080 static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
   3081   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
   3082   for (int i = 0; i < value->InternalFieldCount(); i++) {
   3083     CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
   3084   }
   3085 }
   3086 
   3087 
   3088 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
   3089   LocalContext env;
   3090   v8::Isolate* isolate = env->GetIsolate();
   3091   v8::HandleScope handle_scope(isolate);
   3092 
   3093   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
   3094   CheckInternalFieldsAreZero(ab);
   3095   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
   3096   CHECK(!ab->IsExternal());
   3097   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   3098 
   3099   ScopedArrayBufferContents ab_contents(ab->Externalize());
   3100   CHECK(ab->IsExternal());
   3101 
   3102   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
   3103   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
   3104   DCHECK(data != NULL);
   3105   env->Global()->Set(v8_str("ab"), ab);
   3106 
   3107   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
   3108   CHECK_EQ(1024, result->Int32Value());
   3109 
   3110   result = CompileRun("var u8 = new Uint8Array(ab);"
   3111                       "u8[0] = 0xFF;"
   3112                       "u8[1] = 0xAA;"
   3113                       "u8.length");
   3114   CHECK_EQ(1024, result->Int32Value());
   3115   CHECK_EQ(0xFF, data[0]);
   3116   CHECK_EQ(0xAA, data[1]);
   3117   data[0] = 0xCC;
   3118   data[1] = 0x11;
   3119   result = CompileRun("u8[0] + u8[1]");
   3120   CHECK_EQ(0xDD, result->Int32Value());
   3121 }
   3122 
   3123 
   3124 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
   3125   LocalContext env;
   3126   v8::Isolate* isolate = env->GetIsolate();
   3127   v8::HandleScope handle_scope(isolate);
   3128 
   3129 
   3130   v8::Local<v8::Value> result =
   3131       CompileRun("var ab1 = new ArrayBuffer(2);"
   3132                  "var u8_a = new Uint8Array(ab1);"
   3133                  "u8_a[0] = 0xAA;"
   3134                  "u8_a[1] = 0xFF; u8_a.buffer");
   3135   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
   3136   CheckInternalFieldsAreZero(ab1);
   3137   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
   3138   CHECK(!ab1->IsExternal());
   3139   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
   3140   CHECK(ab1->IsExternal());
   3141 
   3142   result = CompileRun("ab1.byteLength");
   3143   CHECK_EQ(2, result->Int32Value());
   3144   result = CompileRun("u8_a[0]");
   3145   CHECK_EQ(0xAA, result->Int32Value());
   3146   result = CompileRun("u8_a[1]");
   3147   CHECK_EQ(0xFF, result->Int32Value());
   3148   result = CompileRun("var u8_b = new Uint8Array(ab1);"
   3149                       "u8_b[0] = 0xBB;"
   3150                       "u8_a[0]");
   3151   CHECK_EQ(0xBB, result->Int32Value());
   3152   result = CompileRun("u8_b[1]");
   3153   CHECK_EQ(0xFF, result->Int32Value());
   3154 
   3155   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
   3156   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
   3157   CHECK_EQ(0xBB, ab1_data[0]);
   3158   CHECK_EQ(0xFF, ab1_data[1]);
   3159   ab1_data[0] = 0xCC;
   3160   ab1_data[1] = 0x11;
   3161   result = CompileRun("u8_a[0] + u8_a[1]");
   3162   CHECK_EQ(0xDD, result->Int32Value());
   3163 }
   3164 
   3165 
   3166 THREADED_TEST(ArrayBuffer_External) {
   3167   LocalContext env;
   3168   v8::Isolate* isolate = env->GetIsolate();
   3169   v8::HandleScope handle_scope(isolate);
   3170 
   3171   i::ScopedVector<uint8_t> my_data(100);
   3172   memset(my_data.start(), 0, 100);
   3173   Local<v8::ArrayBuffer> ab3 =
   3174       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
   3175   CheckInternalFieldsAreZero(ab3);
   3176   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
   3177   CHECK(ab3->IsExternal());
   3178 
   3179   env->Global()->Set(v8_str("ab3"), ab3);
   3180 
   3181   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
   3182   CHECK_EQ(100, result->Int32Value());
   3183 
   3184   result = CompileRun("var u8_b = new Uint8Array(ab3);"
   3185                       "u8_b[0] = 0xBB;"
   3186                       "u8_b[1] = 0xCC;"
   3187                       "u8_b.length");
   3188   CHECK_EQ(100, result->Int32Value());
   3189   CHECK_EQ(0xBB, my_data[0]);
   3190   CHECK_EQ(0xCC, my_data[1]);
   3191   my_data[0] = 0xCC;
   3192   my_data[1] = 0x11;
   3193   result = CompileRun("u8_b[0] + u8_b[1]");
   3194   CHECK_EQ(0xDD, result->Int32Value());
   3195 }
   3196 
   3197 
   3198 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
   3199   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
   3200   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
   3201 }
   3202 
   3203 
   3204 static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
   3205   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
   3206   CHECK_EQ(0, static_cast<int>(ta->Length()));
   3207   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
   3208 }
   3209 
   3210 
   3211 static void CheckIsTypedArrayVarNeutered(const char* name) {
   3212   i::ScopedVector<char> source(1024);
   3213   i::SNPrintF(source,
   3214       "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
   3215       name, name, name);
   3216   CHECK(CompileRun(source.start())->IsTrue());
   3217   v8::Handle<v8::TypedArray> ta =
   3218     v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
   3219   CheckIsNeutered(ta);
   3220 }
   3221 
   3222 
   3223 template <typename TypedArray, int kElementSize>
   3224 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
   3225                                          int byteOffset,
   3226                                          int length) {
   3227   v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
   3228   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   3229   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
   3230   CHECK_EQ(length, static_cast<int>(ta->Length()));
   3231   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
   3232   return ta;
   3233 }
   3234 
   3235 
   3236 THREADED_TEST(ArrayBuffer_NeuteringApi) {
   3237   LocalContext env;
   3238   v8::Isolate* isolate = env->GetIsolate();
   3239   v8::HandleScope handle_scope(isolate);
   3240 
   3241   v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
   3242 
   3243   v8::Handle<v8::Uint8Array> u8a =
   3244     CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
   3245   v8::Handle<v8::Uint8ClampedArray> u8c =
   3246     CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
   3247   v8::Handle<v8::Int8Array> i8a =
   3248     CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
   3249 
   3250   v8::Handle<v8::Uint16Array> u16a =
   3251     CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
   3252   v8::Handle<v8::Int16Array> i16a =
   3253     CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
   3254 
   3255   v8::Handle<v8::Uint32Array> u32a =
   3256     CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
   3257   v8::Handle<v8::Int32Array> i32a =
   3258     CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
   3259 
   3260   v8::Handle<v8::Float32Array> f32a =
   3261     CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
   3262   v8::Handle<v8::Float64Array> f64a =
   3263     CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
   3264 
   3265   v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
   3266   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   3267   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
   3268   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
   3269 
   3270   ScopedArrayBufferContents contents(buffer->Externalize());
   3271   buffer->Neuter();
   3272   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
   3273   CheckIsNeutered(u8a);
   3274   CheckIsNeutered(u8c);
   3275   CheckIsNeutered(i8a);
   3276   CheckIsNeutered(u16a);
   3277   CheckIsNeutered(i16a);
   3278   CheckIsNeutered(u32a);
   3279   CheckIsNeutered(i32a);
   3280   CheckIsNeutered(f32a);
   3281   CheckIsNeutered(f64a);
   3282   CheckDataViewIsNeutered(dv);
   3283 }
   3284 
   3285 
   3286 THREADED_TEST(ArrayBuffer_NeuteringScript) {
   3287   LocalContext env;
   3288   v8::Isolate* isolate = env->GetIsolate();
   3289   v8::HandleScope handle_scope(isolate);
   3290 
   3291   CompileRun(
   3292       "var ab = new ArrayBuffer(1024);"
   3293       "var u8a = new Uint8Array(ab, 1, 1023);"
   3294       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
   3295       "var i8a = new Int8Array(ab, 1, 1023);"
   3296       "var u16a = new Uint16Array(ab, 2, 511);"
   3297       "var i16a = new Int16Array(ab, 2, 511);"
   3298       "var u32a = new Uint32Array(ab, 4, 255);"
   3299       "var i32a = new Int32Array(ab, 4, 255);"
   3300       "var f32a = new Float32Array(ab, 4, 255);"
   3301       "var f64a = new Float64Array(ab, 8, 127);"
   3302       "var dv = new DataView(ab, 1, 1023);");
   3303 
   3304   v8::Handle<v8::ArrayBuffer> ab =
   3305       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
   3306 
   3307   v8::Handle<v8::DataView> dv =
   3308     v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
   3309 
   3310   ScopedArrayBufferContents contents(ab->Externalize());
   3311   ab->Neuter();
   3312   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
   3313   CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
   3314 
   3315   CheckIsTypedArrayVarNeutered("u8a");
   3316   CheckIsTypedArrayVarNeutered("u8c");
   3317   CheckIsTypedArrayVarNeutered("i8a");
   3318   CheckIsTypedArrayVarNeutered("u16a");
   3319   CheckIsTypedArrayVarNeutered("i16a");
   3320   CheckIsTypedArrayVarNeutered("u32a");
   3321   CheckIsTypedArrayVarNeutered("i32a");
   3322   CheckIsTypedArrayVarNeutered("f32a");
   3323   CheckIsTypedArrayVarNeutered("f64a");
   3324 
   3325   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
   3326   CheckDataViewIsNeutered(dv);
   3327 }
   3328 
   3329 
   3330 
   3331 THREADED_TEST(HiddenProperties) {
   3332   LocalContext env;
   3333   v8::Isolate* isolate = env->GetIsolate();
   3334   v8::HandleScope scope(isolate);
   3335 
   3336   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
   3337   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   3338   v8::Local<v8::String> empty = v8_str("");
   3339   v8::Local<v8::String> prop_name = v8_str("prop_name");
   3340 
   3341   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   3342 
   3343   // Make sure delete of a non-existent hidden value works
   3344   CHECK(obj->DeleteHiddenValue(key));
   3345 
   3346   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
   3347   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
   3348   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
   3349   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3350 
   3351   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   3352 
   3353   // Make sure we do not find the hidden property.
   3354   CHECK(!obj->Has(empty));
   3355   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3356   CHECK(obj->Get(empty)->IsUndefined());
   3357   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3358   CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
   3359   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3360   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
   3361 
   3362   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   3363 
   3364   // Add another property and delete it afterwards to force the object in
   3365   // slow case.
   3366   CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
   3367   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3368   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
   3369   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3370   CHECK(obj->Delete(prop_name));
   3371   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   3372 
   3373   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   3374 
   3375   CHECK(obj->SetHiddenValue(key, Handle<Value>()));
   3376   CHECK(obj->GetHiddenValue(key).IsEmpty());
   3377 
   3378   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
   3379   CHECK(obj->DeleteHiddenValue(key));
   3380   CHECK(obj->GetHiddenValue(key).IsEmpty());
   3381 }
   3382 
   3383 
   3384 THREADED_TEST(Regress97784) {
   3385   // Regression test for crbug.com/97784
   3386   // Messing with the Object.prototype should not have effect on
   3387   // hidden properties.
   3388   LocalContext env;
   3389   v8::HandleScope scope(env->GetIsolate());
   3390 
   3391   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
   3392   v8::Local<v8::String> key = v8_str("hidden");
   3393 
   3394   CompileRun(
   3395       "set_called = false;"
   3396       "Object.defineProperty("
   3397       "    Object.prototype,"
   3398       "    'hidden',"
   3399       "    {get: function() { return 45; },"
   3400       "     set: function() { set_called = true; }})");
   3401 
   3402   CHECK(obj->GetHiddenValue(key).IsEmpty());
   3403   // Make sure that the getter and setter from Object.prototype is not invoked.
   3404   // If it did we would have full access to the hidden properties in
   3405   // the accessor.
   3406   CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
   3407   ExpectFalse("set_called");
   3408   CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
   3409 }
   3410 
   3411 
   3412 static bool interceptor_for_hidden_properties_called;
   3413 static void InterceptorForHiddenProperties(
   3414     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   3415   interceptor_for_hidden_properties_called = true;
   3416 }
   3417 
   3418 
   3419 THREADED_TEST(HiddenPropertiesWithInterceptors) {
   3420   LocalContext context;
   3421   v8::Isolate* isolate = context->GetIsolate();
   3422   v8::HandleScope scope(isolate);
   3423 
   3424   interceptor_for_hidden_properties_called = false;
   3425 
   3426   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   3427 
   3428   // Associate an interceptor with an object and start setting hidden values.
   3429   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
   3430   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   3431   instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
   3432   Local<v8::Function> function = fun_templ->GetFunction();
   3433   Local<v8::Object> obj = function->NewInstance();
   3434   CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2302)));
   3435   CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
   3436   CHECK(!interceptor_for_hidden_properties_called);
   3437 }
   3438 
   3439 
   3440 THREADED_TEST(External) {
   3441   v8::HandleScope scope(CcTest::isolate());
   3442   int x = 3;
   3443   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
   3444   LocalContext env;
   3445   env->Global()->Set(v8_str("ext"), ext);
   3446   Local<Value> reext_obj = CompileRun("this.ext");
   3447   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
   3448   int* ptr = static_cast<int*>(reext->Value());
   3449   CHECK_EQ(x, 3);
   3450   *ptr = 10;
   3451   CHECK_EQ(x, 10);
   3452 
   3453   // Make sure unaligned pointers are wrapped properly.
   3454   char* data = i::StrDup("0123456789");
   3455   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
   3456   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
   3457   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
   3458   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
   3459 
   3460   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
   3461   CHECK_EQ('0', *char_ptr);
   3462   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
   3463   CHECK_EQ('1', *char_ptr);
   3464   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
   3465   CHECK_EQ('2', *char_ptr);
   3466   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
   3467   CHECK_EQ('3', *char_ptr);
   3468   i::DeleteArray(data);
   3469 }
   3470 
   3471 
   3472 THREADED_TEST(GlobalHandle) {
   3473   v8::Isolate* isolate = CcTest::isolate();
   3474   v8::Persistent<String> global;
   3475   {
   3476     v8::HandleScope scope(isolate);
   3477     global.Reset(isolate, v8_str("str"));
   3478   }
   3479   {
   3480     v8::HandleScope scope(isolate);
   3481     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3482   }
   3483   global.Reset();
   3484   {
   3485     v8::HandleScope scope(isolate);
   3486     global.Reset(isolate, v8_str("str"));
   3487   }
   3488   {
   3489     v8::HandleScope scope(isolate);
   3490     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3491   }
   3492   global.Reset();
   3493 }
   3494 
   3495 
   3496 THREADED_TEST(ResettingGlobalHandle) {
   3497   v8::Isolate* isolate = CcTest::isolate();
   3498   v8::Persistent<String> global;
   3499   {
   3500     v8::HandleScope scope(isolate);
   3501     global.Reset(isolate, v8_str("str"));
   3502   }
   3503   v8::internal::GlobalHandles* global_handles =
   3504       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3505   int initial_handle_count = global_handles->global_handles_count();
   3506   {
   3507     v8::HandleScope scope(isolate);
   3508     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3509   }
   3510   {
   3511     v8::HandleScope scope(isolate);
   3512     global.Reset(isolate, v8_str("longer"));
   3513   }
   3514   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
   3515   {
   3516     v8::HandleScope scope(isolate);
   3517     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
   3518   }
   3519   global.Reset();
   3520   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3521 }
   3522 
   3523 
   3524 THREADED_TEST(ResettingGlobalHandleToEmpty) {
   3525   v8::Isolate* isolate = CcTest::isolate();
   3526   v8::Persistent<String> global;
   3527   {
   3528     v8::HandleScope scope(isolate);
   3529     global.Reset(isolate, v8_str("str"));
   3530   }
   3531   v8::internal::GlobalHandles* global_handles =
   3532       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3533   int initial_handle_count = global_handles->global_handles_count();
   3534   {
   3535     v8::HandleScope scope(isolate);
   3536     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3537   }
   3538   {
   3539     v8::HandleScope scope(isolate);
   3540     Local<String> empty;
   3541     global.Reset(isolate, empty);
   3542   }
   3543   CHECK(global.IsEmpty());
   3544   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3545 }
   3546 
   3547 
   3548 template<class T>
   3549 static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
   3550   return unique.Pass();
   3551 }
   3552 
   3553 
   3554 template<class T>
   3555 static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
   3556                                             const v8::Persistent<T> & global) {
   3557   v8::UniquePersistent<String> unique(isolate, global);
   3558   return unique.Pass();
   3559 }
   3560 
   3561 
   3562 THREADED_TEST(UniquePersistent) {
   3563   v8::Isolate* isolate = CcTest::isolate();
   3564   v8::Persistent<String> global;
   3565   {
   3566     v8::HandleScope scope(isolate);
   3567     global.Reset(isolate, v8_str("str"));
   3568   }
   3569   v8::internal::GlobalHandles* global_handles =
   3570       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3571   int initial_handle_count = global_handles->global_handles_count();
   3572   {
   3573     v8::UniquePersistent<String> unique(isolate, global);
   3574     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3575     // Test assignment via Pass
   3576     {
   3577       v8::UniquePersistent<String> copy = unique.Pass();
   3578       CHECK(unique.IsEmpty());
   3579       CHECK(copy == global);
   3580       CHECK_EQ(initial_handle_count + 1,
   3581                global_handles->global_handles_count());
   3582       unique = copy.Pass();
   3583     }
   3584     // Test ctor via Pass
   3585     {
   3586       v8::UniquePersistent<String> copy(unique.Pass());
   3587       CHECK(unique.IsEmpty());
   3588       CHECK(copy == global);
   3589       CHECK_EQ(initial_handle_count + 1,
   3590                global_handles->global_handles_count());
   3591       unique = copy.Pass();
   3592     }
   3593     // Test pass through function call
   3594     {
   3595       v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
   3596       CHECK(unique.IsEmpty());
   3597       CHECK(copy == global);
   3598       CHECK_EQ(initial_handle_count + 1,
   3599                global_handles->global_handles_count());
   3600       unique = copy.Pass();
   3601     }
   3602     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3603   }
   3604   // Test pass from function call
   3605   {
   3606     v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
   3607     CHECK(unique == global);
   3608     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3609   }
   3610   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
   3611   global.Reset();
   3612 }
   3613 
   3614 
   3615 template<typename K, typename V>
   3616 class WeakStdMapTraits : public v8::StdMapTraits<K, V> {
   3617  public:
   3618   typedef typename v8::PersistentValueMap<K, V, WeakStdMapTraits<K, V> >
   3619       MapType;
   3620   static const v8::PersistentContainerCallbackType kCallbackType = v8::kWeak;
   3621   struct WeakCallbackDataType {
   3622     MapType* map;
   3623     K key;
   3624   };
   3625   static WeakCallbackDataType* WeakCallbackParameter(
   3626       MapType* map, const K& key, Local<V> value) {
   3627     WeakCallbackDataType* data = new WeakCallbackDataType;
   3628     data->map = map;
   3629     data->key = key;
   3630     return data;
   3631   }
   3632   static MapType* MapFromWeakCallbackData(
   3633       const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
   3634     return data.GetParameter()->map;
   3635   }
   3636   static K KeyFromWeakCallbackData(
   3637       const v8::WeakCallbackData<V, WeakCallbackDataType>& data) {
   3638     return data.GetParameter()->key;
   3639   }
   3640   static void DisposeCallbackData(WeakCallbackDataType* data) {
   3641     delete data;
   3642   }
   3643   static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<V> value,
   3644       K key) { }
   3645 };
   3646 
   3647 
   3648 template<typename Map>
   3649 static void TestPersistentValueMap() {
   3650   LocalContext env;
   3651   v8::Isolate* isolate = env->GetIsolate();
   3652   Map map(isolate);
   3653   v8::internal::GlobalHandles* global_handles =
   3654       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3655   int initial_handle_count = global_handles->global_handles_count();
   3656   CHECK_EQ(0, static_cast<int>(map.Size()));
   3657   {
   3658     HandleScope scope(isolate);
   3659     Local<v8::Object> obj = map.Get(7);
   3660     CHECK(obj.IsEmpty());
   3661     Local<v8::Object> expected = v8::Object::New(isolate);
   3662     map.Set(7, expected);
   3663     CHECK_EQ(1, static_cast<int>(map.Size()));
   3664     obj = map.Get(7);
   3665     CHECK_EQ(expected, obj);
   3666     {
   3667       typename Map::PersistentValueReference ref = map.GetReference(7);
   3668       CHECK_EQ(expected, ref.NewLocal(isolate));
   3669     }
   3670     v8::UniquePersistent<v8::Object> removed = map.Remove(7);
   3671     CHECK_EQ(0, static_cast<int>(map.Size()));
   3672     CHECK(expected == removed);
   3673     removed = map.Remove(7);
   3674     CHECK(removed.IsEmpty());
   3675     map.Set(8, expected);
   3676     CHECK_EQ(1, static_cast<int>(map.Size()));
   3677     map.Set(8, expected);
   3678     CHECK_EQ(1, static_cast<int>(map.Size()));
   3679     {
   3680       typename Map::PersistentValueReference ref;
   3681       Local<v8::Object> expected2 = v8::Object::New(isolate);
   3682       removed = map.Set(8,
   3683           v8::UniquePersistent<v8::Object>(isolate, expected2), &ref);
   3684       CHECK_EQ(1, static_cast<int>(map.Size()));
   3685       CHECK(expected == removed);
   3686       CHECK_EQ(expected2, ref.NewLocal(isolate));
   3687     }
   3688   }
   3689   CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3690   if (map.IsWeak()) {
   3691     reinterpret_cast<v8::internal::Isolate*>(isolate)->heap()->
   3692         CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3693   } else {
   3694     map.Clear();
   3695   }
   3696   CHECK_EQ(0, static_cast<int>(map.Size()));
   3697   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
   3698 }
   3699 
   3700 
   3701 TEST(PersistentValueMap) {
   3702   // Default case, w/o weak callbacks:
   3703   TestPersistentValueMap<v8::StdPersistentValueMap<int, v8::Object> >();
   3704 
   3705   // Custom traits with weak callbacks:
   3706   typedef v8::PersistentValueMap<int, v8::Object,
   3707       WeakStdMapTraits<int, v8::Object> > WeakPersistentValueMap;
   3708   TestPersistentValueMap<WeakPersistentValueMap>();
   3709 }
   3710 
   3711 
   3712 TEST(PersistentValueVector) {
   3713   LocalContext env;
   3714   v8::Isolate* isolate = env->GetIsolate();
   3715   v8::internal::GlobalHandles* global_handles =
   3716       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3717   int handle_count = global_handles->global_handles_count();
   3718   HandleScope scope(isolate);
   3719 
   3720   v8::PersistentValueVector<v8::Object> vector(isolate);
   3721 
   3722   Local<v8::Object> obj1 = v8::Object::New(isolate);
   3723   Local<v8::Object> obj2 = v8::Object::New(isolate);
   3724   v8::UniquePersistent<v8::Object> obj3(isolate, v8::Object::New(isolate));
   3725 
   3726   CHECK(vector.IsEmpty());
   3727   CHECK_EQ(0, static_cast<int>(vector.Size()));
   3728 
   3729   vector.ReserveCapacity(3);
   3730   CHECK(vector.IsEmpty());
   3731 
   3732   vector.Append(obj1);
   3733   vector.Append(obj2);
   3734   vector.Append(obj1);
   3735   vector.Append(obj3.Pass());
   3736   vector.Append(obj1);
   3737 
   3738   CHECK(!vector.IsEmpty());
   3739   CHECK_EQ(5, static_cast<int>(vector.Size()));
   3740   CHECK(obj3.IsEmpty());
   3741   CHECK_EQ(obj1, vector.Get(0));
   3742   CHECK_EQ(obj1, vector.Get(2));
   3743   CHECK_EQ(obj1, vector.Get(4));
   3744   CHECK_EQ(obj2, vector.Get(1));
   3745 
   3746   CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
   3747 
   3748   vector.Clear();
   3749   CHECK(vector.IsEmpty());
   3750   CHECK_EQ(0, static_cast<int>(vector.Size()));
   3751   CHECK_EQ(handle_count, global_handles->global_handles_count());
   3752 }
   3753 
   3754 
   3755 THREADED_TEST(GlobalHandleUpcast) {
   3756   v8::Isolate* isolate = CcTest::isolate();
   3757   v8::HandleScope scope(isolate);
   3758   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
   3759   v8::Persistent<String> global_string(isolate, local);
   3760   v8::Persistent<Value>& global_value =
   3761       v8::Persistent<Value>::Cast(global_string);
   3762   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
   3763   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
   3764   global_string.Reset();
   3765 }
   3766 
   3767 
   3768 THREADED_TEST(HandleEquality) {
   3769   v8::Isolate* isolate = CcTest::isolate();
   3770   v8::Persistent<String> global1;
   3771   v8::Persistent<String> global2;
   3772   {
   3773     v8::HandleScope scope(isolate);
   3774     global1.Reset(isolate, v8_str("str"));
   3775     global2.Reset(isolate, v8_str("str2"));
   3776   }
   3777   CHECK_EQ(global1 == global1, true);
   3778   CHECK_EQ(global1 != global1, false);
   3779   {
   3780     v8::HandleScope scope(isolate);
   3781     Local<String> local1 = Local<String>::New(isolate, global1);
   3782     Local<String> local2 = Local<String>::New(isolate, global2);
   3783 
   3784     CHECK_EQ(global1 == local1, true);
   3785     CHECK_EQ(global1 != local1, false);
   3786     CHECK_EQ(local1 == global1, true);
   3787     CHECK_EQ(local1 != global1, false);
   3788 
   3789     CHECK_EQ(global1 == local2, false);
   3790     CHECK_EQ(global1 != local2, true);
   3791     CHECK_EQ(local2 == global1, false);
   3792     CHECK_EQ(local2 != global1, true);
   3793 
   3794     CHECK_EQ(local1 == local2, false);
   3795     CHECK_EQ(local1 != local2, true);
   3796 
   3797     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
   3798     CHECK_EQ(local1 == anotherLocal1, true);
   3799     CHECK_EQ(local1 != anotherLocal1, false);
   3800   }
   3801   global1.Reset();
   3802   global2.Reset();
   3803 }
   3804 
   3805 
   3806 THREADED_TEST(LocalHandle) {
   3807   v8::HandleScope scope(CcTest::isolate());
   3808   v8::Local<String> local =
   3809       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
   3810   CHECK_EQ(local->Length(), 3);
   3811 }
   3812 
   3813 
   3814 class WeakCallCounter {
   3815  public:
   3816   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
   3817   int id() { return id_; }
   3818   void increment() { number_of_weak_calls_++; }
   3819   int NumberOfWeakCalls() { return number_of_weak_calls_; }
   3820  private:
   3821   int id_;
   3822   int number_of_weak_calls_;
   3823 };
   3824 
   3825 
   3826 template<typename T>
   3827 struct WeakCallCounterAndPersistent {
   3828   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
   3829       : counter(counter) {}
   3830   WeakCallCounter* counter;
   3831   v8::Persistent<T> handle;
   3832 };
   3833 
   3834 
   3835 template <typename T>
   3836 static void WeakPointerCallback(
   3837     const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T> >& data) {
   3838   CHECK_EQ(1234, data.GetParameter()->counter->id());
   3839   data.GetParameter()->counter->increment();
   3840   data.GetParameter()->handle.Reset();
   3841 }
   3842 
   3843 
   3844 template<typename T>
   3845 static UniqueId MakeUniqueId(const Persistent<T>& p) {
   3846   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
   3847 }
   3848 
   3849 
   3850 THREADED_TEST(ApiObjectGroups) {
   3851   LocalContext env;
   3852   v8::Isolate* iso = env->GetIsolate();
   3853   HandleScope scope(iso);
   3854 
   3855   WeakCallCounter counter(1234);
   3856 
   3857   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   3858   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   3859   WeakCallCounterAndPersistent<Value> g1c1(&counter);
   3860   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   3861   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   3862   WeakCallCounterAndPersistent<Value> g2c1(&counter);
   3863 
   3864   {
   3865     HandleScope scope(iso);
   3866     g1s1.handle.Reset(iso, Object::New(iso));
   3867     g1s2.handle.Reset(iso, Object::New(iso));
   3868     g1c1.handle.Reset(iso, Object::New(iso));
   3869     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
   3870     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
   3871     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
   3872 
   3873     g2s1.handle.Reset(iso, Object::New(iso));
   3874     g2s2.handle.Reset(iso, Object::New(iso));
   3875     g2c1.handle.Reset(iso, Object::New(iso));
   3876     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
   3877     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
   3878     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
   3879   }
   3880 
   3881   WeakCallCounterAndPersistent<Value> root(&counter);
   3882   root.handle.Reset(iso, g1s1.handle);  // make a root.
   3883 
   3884   // Connect group 1 and 2, make a cycle.
   3885   {
   3886     HandleScope scope(iso);
   3887     CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())->
   3888             Set(0, Local<Value>::New(iso, g2s2.handle)));
   3889     CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())->
   3890             Set(0, Local<Value>::New(iso, g1s1.handle)));
   3891   }
   3892 
   3893   {
   3894     UniqueId id1 = MakeUniqueId(g1s1.handle);
   3895     UniqueId id2 = MakeUniqueId(g2s2.handle);
   3896     iso->SetObjectGroupId(g1s1.handle, id1);
   3897     iso->SetObjectGroupId(g1s2.handle, id1);
   3898     iso->SetReferenceFromGroup(id1, g1c1.handle);
   3899     iso->SetObjectGroupId(g2s1.handle, id2);
   3900     iso->SetObjectGroupId(g2s2.handle, id2);
   3901     iso->SetReferenceFromGroup(id2, g2c1.handle);
   3902   }
   3903   // Do a single full GC, ensure incremental marking is stopped.
   3904   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   3905       iso)->heap();
   3906   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3907 
   3908   // All object should be alive.
   3909   CHECK_EQ(0, counter.NumberOfWeakCalls());
   3910 
   3911   // Weaken the root.
   3912   root.handle.SetWeak(&root, &WeakPointerCallback);
   3913   // But make children strong roots---all the objects (except for children)
   3914   // should be collectable now.
   3915   g1c1.handle.ClearWeak();
   3916   g2c1.handle.ClearWeak();
   3917 
   3918   // Groups are deleted, rebuild groups.
   3919   {
   3920     UniqueId id1 = MakeUniqueId(g1s1.handle);
   3921     UniqueId id2 = MakeUniqueId(g2s2.handle);
   3922     iso->SetObjectGroupId(g1s1.handle, id1);
   3923     iso->SetObjectGroupId(g1s2.handle, id1);
   3924     iso->SetReferenceFromGroup(id1, g1c1.handle);
   3925     iso->SetObjectGroupId(g2s1.handle, id2);
   3926     iso->SetObjectGroupId(g2s2.handle, id2);
   3927     iso->SetReferenceFromGroup(id2, g2c1.handle);
   3928   }
   3929 
   3930   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3931 
   3932   // All objects should be gone. 5 global handles in total.
   3933   CHECK_EQ(5, counter.NumberOfWeakCalls());
   3934 
   3935   // And now make children weak again and collect them.
   3936   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
   3937   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
   3938 
   3939   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3940   CHECK_EQ(7, counter.NumberOfWeakCalls());
   3941 }
   3942 
   3943 
   3944 THREADED_TEST(ApiObjectGroupsForSubtypes) {
   3945   LocalContext env;
   3946   v8::Isolate* iso = env->GetIsolate();
   3947   HandleScope scope(iso);
   3948 
   3949   WeakCallCounter counter(1234);
   3950 
   3951   WeakCallCounterAndPersistent<Object> g1s1(&counter);
   3952   WeakCallCounterAndPersistent<String> g1s2(&counter);
   3953   WeakCallCounterAndPersistent<String> g1c1(&counter);
   3954   WeakCallCounterAndPersistent<Object> g2s1(&counter);
   3955   WeakCallCounterAndPersistent<String> g2s2(&counter);
   3956   WeakCallCounterAndPersistent<String> g2c1(&counter);
   3957 
   3958   {
   3959     HandleScope scope(iso);
   3960     g1s1.handle.Reset(iso, Object::New(iso));
   3961     g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
   3962     g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
   3963     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
   3964     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
   3965     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
   3966 
   3967     g2s1.handle.Reset(iso, Object::New(iso));
   3968     g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
   3969     g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
   3970     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
   3971     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
   3972     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
   3973   }
   3974 
   3975   WeakCallCounterAndPersistent<Value> root(&counter);
   3976   root.handle.Reset(iso, g1s1.handle);  // make a root.
   3977 
   3978   // Connect group 1 and 2, make a cycle.
   3979   {
   3980     HandleScope scope(iso);
   3981     CHECK(Local<Object>::New(iso, g1s1.handle)
   3982               ->Set(0, Local<Object>::New(iso, g2s1.handle)));
   3983     CHECK(Local<Object>::New(iso, g2s1.handle)
   3984               ->Set(0, Local<Object>::New(iso, g1s1.handle)));
   3985   }
   3986 
   3987   {
   3988     UniqueId id1 = MakeUniqueId(g1s1.handle);
   3989     UniqueId id2 = MakeUniqueId(g2s2.handle);
   3990     iso->SetObjectGroupId(g1s1.handle, id1);
   3991     iso->SetObjectGroupId(g1s2.handle, id1);
   3992     iso->SetReference(g1s1.handle, g1c1.handle);
   3993     iso->SetObjectGroupId(g2s1.handle, id2);
   3994     iso->SetObjectGroupId(g2s2.handle, id2);
   3995     iso->SetReferenceFromGroup(id2, g2c1.handle);
   3996   }
   3997   // Do a single full GC, ensure incremental marking is stopped.
   3998   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   3999       iso)->heap();
   4000   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   4001 
   4002   // All object should be alive.
   4003   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4004 
   4005   // Weaken the root.
   4006   root.handle.SetWeak(&root, &WeakPointerCallback);
   4007   // But make children strong roots---all the objects (except for children)
   4008   // should be collectable now.
   4009   g1c1.handle.ClearWeak();
   4010   g2c1.handle.ClearWeak();
   4011 
   4012   // Groups are deleted, rebuild groups.
   4013   {
   4014     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4015     UniqueId id2 = MakeUniqueId(g2s2.handle);
   4016     iso->SetObjectGroupId(g1s1.handle, id1);
   4017     iso->SetObjectGroupId(g1s2.handle, id1);
   4018     iso->SetReference(g1s1.handle, g1c1.handle);
   4019     iso->SetObjectGroupId(g2s1.handle, id2);
   4020     iso->SetObjectGroupId(g2s2.handle, id2);
   4021     iso->SetReferenceFromGroup(id2, g2c1.handle);
   4022   }
   4023 
   4024   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   4025 
   4026   // All objects should be gone. 5 global handles in total.
   4027   CHECK_EQ(5, counter.NumberOfWeakCalls());
   4028 
   4029   // And now make children weak again and collect them.
   4030   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
   4031   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
   4032 
   4033   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   4034   CHECK_EQ(7, counter.NumberOfWeakCalls());
   4035 }
   4036 
   4037 
   4038 THREADED_TEST(ApiObjectGroupsCycle) {
   4039   LocalContext env;
   4040   v8::Isolate* iso = env->GetIsolate();
   4041   HandleScope scope(iso);
   4042 
   4043   WeakCallCounter counter(1234);
   4044 
   4045   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   4046   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   4047   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   4048   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   4049   WeakCallCounterAndPersistent<Value> g3s1(&counter);
   4050   WeakCallCounterAndPersistent<Value> g3s2(&counter);
   4051   WeakCallCounterAndPersistent<Value> g4s1(&counter);
   4052   WeakCallCounterAndPersistent<Value> g4s2(&counter);
   4053 
   4054   {
   4055     HandleScope scope(iso);
   4056     g1s1.handle.Reset(iso, Object::New(iso));
   4057     g1s2.handle.Reset(iso, Object::New(iso));
   4058     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
   4059     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
   4060     CHECK(g1s1.handle.IsWeak());
   4061     CHECK(g1s2.handle.IsWeak());
   4062 
   4063     g2s1.handle.Reset(iso, Object::New(iso));
   4064     g2s2.handle.Reset(iso, Object::New(iso));
   4065     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
   4066     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
   4067     CHECK(g2s1.handle.IsWeak());
   4068     CHECK(g2s2.handle.IsWeak());
   4069 
   4070     g3s1.handle.Reset(iso, Object::New(iso));
   4071     g3s2.handle.Reset(iso, Object::New(iso));
   4072     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
   4073     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
   4074     CHECK(g3s1.handle.IsWeak());
   4075     CHECK(g3s2.handle.IsWeak());
   4076 
   4077     g4s1.handle.Reset(iso, Object::New(iso));
   4078     g4s2.handle.Reset(iso, Object::New(iso));
   4079     g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
   4080     g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
   4081     CHECK(g4s1.handle.IsWeak());
   4082     CHECK(g4s2.handle.IsWeak());
   4083   }
   4084 
   4085   WeakCallCounterAndPersistent<Value> root(&counter);
   4086   root.handle.Reset(iso, g1s1.handle);  // make a root.
   4087 
   4088   // Connect groups.  We're building the following cycle:
   4089   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   4090   // groups.
   4091   {
   4092     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4093     UniqueId id2 = MakeUniqueId(g2s1.handle);
   4094     UniqueId id3 = MakeUniqueId(g3s1.handle);
   4095     UniqueId id4 = MakeUniqueId(g4s1.handle);
   4096     iso->SetObjectGroupId(g1s1.handle, id1);
   4097     iso->SetObjectGroupId(g1s2.handle, id1);
   4098     iso->SetReferenceFromGroup(id1, g2s1.handle);
   4099     iso->SetObjectGroupId(g2s1.handle, id2);
   4100     iso->SetObjectGroupId(g2s2.handle, id2);
   4101     iso->SetReferenceFromGroup(id2, g3s1.handle);
   4102     iso->SetObjectGroupId(g3s1.handle, id3);
   4103     iso->SetObjectGroupId(g3s2.handle, id3);
   4104     iso->SetReferenceFromGroup(id3, g4s1.handle);
   4105     iso->SetObjectGroupId(g4s1.handle, id4);
   4106     iso->SetObjectGroupId(g4s2.handle, id4);
   4107     iso->SetReferenceFromGroup(id4, g1s1.handle);
   4108   }
   4109   // Do a single full GC
   4110   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   4111       iso)->heap();
   4112   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   4113 
   4114   // All object should be alive.
   4115   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4116 
   4117   // Weaken the root.
   4118   root.handle.SetWeak(&root, &WeakPointerCallback);
   4119 
   4120   // Groups are deleted, rebuild groups.
   4121   {
   4122     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4123     UniqueId id2 = MakeUniqueId(g2s1.handle);
   4124     UniqueId id3 = MakeUniqueId(g3s1.handle);
   4125     UniqueId id4 = MakeUniqueId(g4s1.handle);
   4126     iso->SetObjectGroupId(g1s1.handle, id1);
   4127     iso->SetObjectGroupId(g1s2.handle, id1);
   4128     iso->SetReferenceFromGroup(id1, g2s1.handle);
   4129     iso->SetObjectGroupId(g2s1.handle, id2);
   4130     iso->SetObjectGroupId(g2s2.handle, id2);
   4131     iso->SetReferenceFromGroup(id2, g3s1.handle);
   4132     iso->SetObjectGroupId(g3s1.handle, id3);
   4133     iso->SetObjectGroupId(g3s2.handle, id3);
   4134     iso->SetReferenceFromGroup(id3, g4s1.handle);
   4135     iso->SetObjectGroupId(g4s1.handle, id4);
   4136     iso->SetObjectGroupId(g4s2.handle, id4);
   4137     iso->SetReferenceFromGroup(id4, g1s1.handle);
   4138   }
   4139 
   4140   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   4141 
   4142   // All objects should be gone. 9 global handles in total.
   4143   CHECK_EQ(9, counter.NumberOfWeakCalls());
   4144 }
   4145 
   4146 
   4147 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
   4148 // on the buildbots, so was made non-threaded for the time being.
   4149 TEST(ApiObjectGroupsCycleForScavenger) {
   4150   i::FLAG_stress_compaction = false;
   4151   i::FLAG_gc_global = false;
   4152   LocalContext env;
   4153   v8::Isolate* iso = env->GetIsolate();
   4154   HandleScope scope(iso);
   4155 
   4156   WeakCallCounter counter(1234);
   4157 
   4158   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   4159   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   4160   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   4161   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   4162   WeakCallCounterAndPersistent<Value> g3s1(&counter);
   4163   WeakCallCounterAndPersistent<Value> g3s2(&counter);
   4164 
   4165   {
   4166     HandleScope scope(iso);
   4167     g1s1.handle.Reset(iso, Object::New(iso));
   4168     g1s2.handle.Reset(iso, Object::New(iso));
   4169     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
   4170     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
   4171 
   4172     g2s1.handle.Reset(iso, Object::New(iso));
   4173     g2s2.handle.Reset(iso, Object::New(iso));
   4174     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
   4175     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
   4176 
   4177     g3s1.handle.Reset(iso, Object::New(iso));
   4178     g3s2.handle.Reset(iso, Object::New(iso));
   4179     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
   4180     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
   4181   }
   4182 
   4183   // Make a root.
   4184   WeakCallCounterAndPersistent<Value> root(&counter);
   4185   root.handle.Reset(iso, g1s1.handle);
   4186   root.handle.MarkPartiallyDependent();
   4187 
   4188   // Connect groups.  We're building the following cycle:
   4189   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   4190   // groups.
   4191   {
   4192     HandleScope handle_scope(iso);
   4193     g1s1.handle.MarkPartiallyDependent();
   4194     g1s2.handle.MarkPartiallyDependent();
   4195     g2s1.handle.MarkPartiallyDependent();
   4196     g2s2.handle.MarkPartiallyDependent();
   4197     g3s1.handle.MarkPartiallyDependent();
   4198     g3s2.handle.MarkPartiallyDependent();
   4199     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
   4200     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
   4201     Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
   4202         v8_str("x"), Local<Value>::New(iso, g2s1.handle));
   4203     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
   4204     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
   4205     Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
   4206         v8_str("x"), Local<Value>::New(iso, g3s1.handle));
   4207     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
   4208     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
   4209     Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
   4210         v8_str("x"), Local<Value>::New(iso, g1s1.handle));
   4211   }
   4212 
   4213   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   4214       iso)->heap();
   4215   heap->CollectAllGarbage(i::Heap::kNoGCFlags);
   4216 
   4217   // All objects should be alive.
   4218   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4219 
   4220   // Weaken the root.
   4221   root.handle.SetWeak(&root, &WeakPointerCallback);
   4222   root.handle.MarkPartiallyDependent();
   4223 
   4224   // Groups are deleted, rebuild groups.
   4225   {
   4226     HandleScope handle_scope(iso);
   4227     g1s1.handle.MarkPartiallyDependent();
   4228     g1s2.handle.MarkPartiallyDependent();
   4229     g2s1.handle.MarkPartiallyDependent();
   4230     g2s2.handle.MarkPartiallyDependent();
   4231     g3s1.handle.MarkPartiallyDependent();
   4232     g3s2.handle.MarkPartiallyDependent();
   4233     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
   4234     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
   4235     Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
   4236         v8_str("x"), Local<Value>::New(iso, g2s1.handle));
   4237     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
   4238     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
   4239     Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
   4240         v8_str("x"), Local<Value>::New(iso, g3s1.handle));
   4241     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
   4242     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
   4243     Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
   4244         v8_str("x"), Local<Value>::New(iso, g1s1.handle));
   4245   }
   4246 
   4247   heap->CollectAllGarbage(i::Heap::kNoGCFlags);
   4248 
   4249   // All objects should be gone. 7 global handles in total.
   4250   CHECK_EQ(7, counter.NumberOfWeakCalls());
   4251 }
   4252 
   4253 
   4254 THREADED_TEST(ScriptException) {
   4255   LocalContext env;
   4256   v8::HandleScope scope(env->GetIsolate());
   4257   Local<Script> script = v8_compile("throw 'panama!';");
   4258   v8::TryCatch try_catch;
   4259   Local<Value> result = script->Run();
   4260   CHECK(result.IsEmpty());
   4261   CHECK(try_catch.HasCaught());
   4262   String::Utf8Value exception_value(try_catch.Exception());
   4263   CHECK_EQ(*exception_value, "panama!");
   4264 }
   4265 
   4266 
   4267 TEST(TryCatchCustomException) {
   4268   LocalContext env;
   4269   v8::HandleScope scope(env->GetIsolate());
   4270   v8::TryCatch try_catch;
   4271   CompileRun("function CustomError() { this.a = 'b'; }"
   4272              "(function f() { throw new CustomError(); })();");
   4273   CHECK(try_catch.HasCaught());
   4274   CHECK(try_catch.Exception()->ToObject()->
   4275             Get(v8_str("a"))->Equals(v8_str("b")));
   4276 }
   4277 
   4278 
   4279 bool message_received;
   4280 
   4281 
   4282 static void check_message_0(v8::Handle<v8::Message> message,
   4283                             v8::Handle<Value> data) {
   4284   CHECK_EQ(5.76, data->NumberValue());
   4285   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
   4286   CHECK(!message->IsSharedCrossOrigin());
   4287   message_received = true;
   4288 }
   4289 
   4290 
   4291 THREADED_TEST(MessageHandler0) {
   4292   message_received = false;
   4293   v8::HandleScope scope(CcTest::isolate());
   4294   CHECK(!message_received);
   4295   LocalContext context;
   4296   v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
   4297   v8::Handle<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
   4298   script->Run();
   4299   CHECK(message_received);
   4300   // clear out the message listener
   4301   v8::V8::RemoveMessageListeners(check_message_0);
   4302 }
   4303 
   4304 
   4305 static void check_message_1(v8::Handle<v8::Message> message,
   4306                             v8::Handle<Value> data) {
   4307   CHECK(data->IsNumber());
   4308   CHECK_EQ(1337, data->Int32Value());
   4309   CHECK(!message->IsSharedCrossOrigin());
   4310   message_received = true;
   4311 }
   4312 
   4313 
   4314 TEST(MessageHandler1) {
   4315   message_received = false;
   4316   v8::HandleScope scope(CcTest::isolate());
   4317   CHECK(!message_received);
   4318   v8::V8::AddMessageListener(check_message_1);
   4319   LocalContext context;
   4320   CompileRun("throw 1337;");
   4321   CHECK(message_received);
   4322   // clear out the message listener
   4323   v8::V8::RemoveMessageListeners(check_message_1);
   4324 }
   4325 
   4326 
   4327 static void check_message_2(v8::Handle<v8::Message> message,
   4328                             v8::Handle<Value> data) {
   4329   LocalContext context;
   4330   CHECK(data->IsObject());
   4331   v8::Local<v8::Value> hidden_property =
   4332       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
   4333   CHECK(v8_str("hidden value")->Equals(hidden_property));
   4334   CHECK(!message->IsSharedCrossOrigin());
   4335   message_received = true;
   4336 }
   4337 
   4338 
   4339 TEST(MessageHandler2) {
   4340   message_received = false;
   4341   v8::HandleScope scope(CcTest::isolate());
   4342   CHECK(!message_received);
   4343   v8::V8::AddMessageListener(check_message_2);
   4344   LocalContext context;
   4345   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
   4346   v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
   4347                                            v8_str("hidden value"));
   4348   context->Global()->Set(v8_str("error"), error);
   4349   CompileRun("throw error;");
   4350   CHECK(message_received);
   4351   // clear out the message listener
   4352   v8::V8::RemoveMessageListeners(check_message_2);
   4353 }
   4354 
   4355 
   4356 static void check_message_3(v8::Handle<v8::Message> message,
   4357                             v8::Handle<Value> data) {
   4358   CHECK(message->IsSharedCrossOrigin());
   4359   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
   4360   message_received = true;
   4361 }
   4362 
   4363 
   4364 TEST(MessageHandler3) {
   4365   message_received = false;
   4366   v8::Isolate* isolate = CcTest::isolate();
   4367   v8::HandleScope scope(isolate);
   4368   CHECK(!message_received);
   4369   v8::V8::AddMessageListener(check_message_3);
   4370   LocalContext context;
   4371   v8::ScriptOrigin origin =
   4372       v8::ScriptOrigin(v8_str("6.75"),
   4373                        v8::Integer::New(isolate, 1),
   4374                        v8::Integer::New(isolate, 2),
   4375                        v8::True(isolate));
   4376   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   4377                                                   &origin);
   4378   script->Run();
   4379   CHECK(message_received);
   4380   // clear out the message listener
   4381   v8::V8::RemoveMessageListeners(check_message_3);
   4382 }
   4383 
   4384 
   4385 static void check_message_4(v8::Handle<v8::Message> message,
   4386                             v8::Handle<Value> data) {
   4387   CHECK(!message->IsSharedCrossOrigin());
   4388   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
   4389   message_received = true;
   4390 }
   4391 
   4392 
   4393 TEST(MessageHandler4) {
   4394   message_received = false;
   4395   v8::Isolate* isolate = CcTest::isolate();
   4396   v8::HandleScope scope(isolate);
   4397   CHECK(!message_received);
   4398   v8::V8::AddMessageListener(check_message_4);
   4399   LocalContext context;
   4400   v8::ScriptOrigin origin =
   4401       v8::ScriptOrigin(v8_str("6.75"),
   4402                        v8::Integer::New(isolate, 1),
   4403                        v8::Integer::New(isolate, 2),
   4404                        v8::False(isolate));
   4405   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   4406                                                   &origin);
   4407   script->Run();
   4408   CHECK(message_received);
   4409   // clear out the message listener
   4410   v8::V8::RemoveMessageListeners(check_message_4);
   4411 }
   4412 
   4413 
   4414 static void check_message_5a(v8::Handle<v8::Message> message,
   4415                             v8::Handle<Value> data) {
   4416   CHECK(message->IsSharedCrossOrigin());
   4417   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
   4418   message_received = true;
   4419 }
   4420 
   4421 
   4422 static void check_message_5b(v8::Handle<v8::Message> message,
   4423                             v8::Handle<Value> data) {
   4424   CHECK(!message->IsSharedCrossOrigin());
   4425   CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
   4426   message_received = true;
   4427 }
   4428 
   4429 
   4430 TEST(MessageHandler5) {
   4431   message_received = false;
   4432   v8::Isolate* isolate = CcTest::isolate();
   4433   v8::HandleScope scope(isolate);
   4434   CHECK(!message_received);
   4435   v8::V8::AddMessageListener(check_message_5a);
   4436   LocalContext context;
   4437   v8::ScriptOrigin origin =
   4438       v8::ScriptOrigin(v8_str("6.75"),
   4439                        v8::Integer::New(isolate, 1),
   4440                        v8::Integer::New(isolate, 2),
   4441                        v8::True(isolate));
   4442   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   4443                                                   &origin);
   4444   script->Run();
   4445   CHECK(message_received);
   4446   // clear out the message listener
   4447   v8::V8::RemoveMessageListeners(check_message_5a);
   4448 
   4449   message_received = false;
   4450   v8::V8::AddMessageListener(check_message_5b);
   4451   origin =
   4452       v8::ScriptOrigin(v8_str("6.75"),
   4453                        v8::Integer::New(isolate, 1),
   4454                        v8::Integer::New(isolate, 2),
   4455                        v8::False(isolate));
   4456   script = Script::Compile(v8_str("throw 'error'"),
   4457                            &origin);
   4458   script->Run();
   4459   CHECK(message_received);
   4460   // clear out the message listener
   4461   v8::V8::RemoveMessageListeners(check_message_5b);
   4462 }
   4463 
   4464 
   4465 THREADED_TEST(GetSetProperty) {
   4466   LocalContext context;
   4467   v8::Isolate* isolate = context->GetIsolate();
   4468   v8::HandleScope scope(isolate);
   4469   context->Global()->Set(v8_str("foo"), v8_num(14));
   4470   context->Global()->Set(v8_str("12"), v8_num(92));
   4471   context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
   4472   context->Global()->Set(v8_num(13), v8_num(56));
   4473   Local<Value> foo = CompileRun("this.foo");
   4474   CHECK_EQ(14, foo->Int32Value());
   4475   Local<Value> twelve = CompileRun("this[12]");
   4476   CHECK_EQ(92, twelve->Int32Value());
   4477   Local<Value> sixteen = CompileRun("this[16]");
   4478   CHECK_EQ(32, sixteen->Int32Value());
   4479   Local<Value> thirteen = CompileRun("this[13]");
   4480   CHECK_EQ(56, thirteen->Int32Value());
   4481   CHECK_EQ(92,
   4482            context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
   4483   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
   4484   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
   4485   CHECK_EQ(32,
   4486            context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
   4487   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
   4488   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
   4489   CHECK_EQ(56,
   4490            context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
   4491   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
   4492   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
   4493 }
   4494 
   4495 
   4496 THREADED_TEST(PropertyAttributes) {
   4497   LocalContext context;
   4498   v8::HandleScope scope(context->GetIsolate());
   4499   // none
   4500   Local<String> prop = v8_str("none");
   4501   context->Global()->Set(prop, v8_num(7));
   4502   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
   4503   // read-only
   4504   prop = v8_str("read_only");
   4505   context->Global()->ForceSet(prop, v8_num(7), v8::ReadOnly);
   4506   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   4507   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
   4508   CompileRun("read_only = 9");
   4509   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   4510   context->Global()->Set(prop, v8_num(10));
   4511   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   4512   // dont-delete
   4513   prop = v8_str("dont_delete");
   4514   context->Global()->ForceSet(prop, v8_num(13), v8::DontDelete);
   4515   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   4516   CompileRun("delete dont_delete");
   4517   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   4518   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
   4519   // dont-enum
   4520   prop = v8_str("dont_enum");
   4521   context->Global()->ForceSet(prop, v8_num(28), v8::DontEnum);
   4522   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
   4523   // absent
   4524   prop = v8_str("absent");
   4525   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
   4526   Local<Value> fake_prop = v8_num(1);
   4527   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
   4528   // exception
   4529   TryCatch try_catch;
   4530   Local<Value> exception =
   4531       CompileRun("({ toString: function() { throw 'exception';} })");
   4532   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
   4533   CHECK(try_catch.HasCaught());
   4534   String::Utf8Value exception_value(try_catch.Exception());
   4535   CHECK_EQ("exception", *exception_value);
   4536   try_catch.Reset();
   4537 }
   4538 
   4539 
   4540 THREADED_TEST(Array) {
   4541   LocalContext context;
   4542   v8::HandleScope scope(context->GetIsolate());
   4543   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
   4544   CHECK_EQ(0, array->Length());
   4545   CHECK(array->Get(0)->IsUndefined());
   4546   CHECK(!array->Has(0));
   4547   CHECK(array->Get(100)->IsUndefined());
   4548   CHECK(!array->Has(100));
   4549   array->Set(2, v8_num(7));
   4550   CHECK_EQ(3, array->Length());
   4551   CHECK(!array->Has(0));
   4552   CHECK(!array->Has(1));
   4553   CHECK(array->Has(2));
   4554   CHECK_EQ(7, array->Get(2)->Int32Value());
   4555   Local<Value> obj = CompileRun("[1, 2, 3]");
   4556   Local<v8::Array> arr = obj.As<v8::Array>();
   4557   CHECK_EQ(3, arr->Length());
   4558   CHECK_EQ(1, arr->Get(0)->Int32Value());
   4559   CHECK_EQ(2, arr->Get(1)->Int32Value());
   4560   CHECK_EQ(3, arr->Get(2)->Int32Value());
   4561   array = v8::Array::New(context->GetIsolate(), 27);
   4562   CHECK_EQ(27, array->Length());
   4563   array = v8::Array::New(context->GetIsolate(), -27);
   4564   CHECK_EQ(0, array->Length());
   4565 }
   4566 
   4567 
   4568 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4569   v8::EscapableHandleScope scope(args.GetIsolate());
   4570   ApiTestFuzzer::Fuzz();
   4571   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
   4572   for (int i = 0; i < args.Length(); i++)
   4573     result->Set(i, args[i]);
   4574   args.GetReturnValue().Set(scope.Escape(result));
   4575 }
   4576 
   4577 
   4578 THREADED_TEST(Vector) {
   4579   v8::Isolate* isolate = CcTest::isolate();
   4580   v8::HandleScope scope(isolate);
   4581   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
   4582   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
   4583   LocalContext context(0, global);
   4584 
   4585   const char* fun = "f()";
   4586   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
   4587   CHECK_EQ(0, a0->Length());
   4588 
   4589   const char* fun2 = "f(11)";
   4590   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
   4591   CHECK_EQ(1, a1->Length());
   4592   CHECK_EQ(11, a1->Get(0)->Int32Value());
   4593 
   4594   const char* fun3 = "f(12, 13)";
   4595   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
   4596   CHECK_EQ(2, a2->Length());
   4597   CHECK_EQ(12, a2->Get(0)->Int32Value());
   4598   CHECK_EQ(13, a2->Get(1)->Int32Value());
   4599 
   4600   const char* fun4 = "f(14, 15, 16)";
   4601   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
   4602   CHECK_EQ(3, a3->Length());
   4603   CHECK_EQ(14, a3->Get(0)->Int32Value());
   4604   CHECK_EQ(15, a3->Get(1)->Int32Value());
   4605   CHECK_EQ(16, a3->Get(2)->Int32Value());
   4606 
   4607   const char* fun5 = "f(17, 18, 19, 20)";
   4608   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
   4609   CHECK_EQ(4, a4->Length());
   4610   CHECK_EQ(17, a4->Get(0)->Int32Value());
   4611   CHECK_EQ(18, a4->Get(1)->Int32Value());
   4612   CHECK_EQ(19, a4->Get(2)->Int32Value());
   4613   CHECK_EQ(20, a4->Get(3)->Int32Value());
   4614 }
   4615 
   4616 
   4617 THREADED_TEST(FunctionCall) {
   4618   LocalContext context;
   4619   v8::Isolate* isolate = context->GetIsolate();
   4620   v8::HandleScope scope(isolate);
   4621   CompileRun(
   4622     "function Foo() {"
   4623     "  var result = [];"
   4624     "  for (var i = 0; i < arguments.length; i++) {"
   4625     "    result.push(arguments[i]);"
   4626     "  }"
   4627     "  return result;"
   4628     "}"
   4629     "function ReturnThisSloppy() {"
   4630     "  return this;"
   4631     "}"
   4632     "function ReturnThisStrict() {"
   4633     "  'use strict';"
   4634     "  return this;"
   4635     "}");
   4636   Local<Function> Foo =
   4637       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   4638   Local<Function> ReturnThisSloppy =
   4639       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
   4640   Local<Function> ReturnThisStrict =
   4641       Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
   4642 
   4643   v8::Handle<Value>* args0 = NULL;
   4644   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
   4645   CHECK_EQ(0, a0->Length());
   4646 
   4647   v8::Handle<Value> args1[] = { v8_num(1.1) };
   4648   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
   4649   CHECK_EQ(1, a1->Length());
   4650   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
   4651 
   4652   v8::Handle<Value> args2[] = { v8_num(2.2),
   4653                                 v8_num(3.3) };
   4654   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
   4655   CHECK_EQ(2, a2->Length());
   4656   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
   4657   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
   4658 
   4659   v8::Handle<Value> args3[] = { v8_num(4.4),
   4660                                 v8_num(5.5),
   4661                                 v8_num(6.6) };
   4662   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
   4663   CHECK_EQ(3, a3->Length());
   4664   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
   4665   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
   4666   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
   4667 
   4668   v8::Handle<Value> args4[] = { v8_num(7.7),
   4669                                 v8_num(8.8),
   4670                                 v8_num(9.9),
   4671                                 v8_num(10.11) };
   4672   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
   4673   CHECK_EQ(4, a4->Length());
   4674   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
   4675   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
   4676   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
   4677   CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
   4678 
   4679   Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
   4680   CHECK(r1->StrictEquals(context->Global()));
   4681   Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
   4682   CHECK(r2->StrictEquals(context->Global()));
   4683   Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
   4684   CHECK(r3->IsNumberObject());
   4685   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
   4686   Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
   4687   CHECK(r4->IsStringObject());
   4688   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   4689   Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
   4690   CHECK(r5->IsBooleanObject());
   4691   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
   4692 
   4693   Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
   4694   CHECK(r6->IsUndefined());
   4695   Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
   4696   CHECK(r7->IsNull());
   4697   Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
   4698   CHECK(r8->StrictEquals(v8_num(42)));
   4699   Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
   4700   CHECK(r9->StrictEquals(v8_str("hello")));
   4701   Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
   4702   CHECK(r10->StrictEquals(v8::True(isolate)));
   4703 }
   4704 
   4705 
   4706 THREADED_TEST(ConstructCall) {
   4707   LocalContext context;
   4708   v8::Isolate* isolate = context->GetIsolate();
   4709   v8::HandleScope scope(isolate);
   4710   CompileRun(
   4711     "function Foo() {"
   4712     "  var result = [];"
   4713     "  for (var i = 0; i < arguments.length; i++) {"
   4714     "    result.push(arguments[i]);"
   4715     "  }"
   4716     "  return result;"
   4717     "}");
   4718   Local<Function> Foo =
   4719       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   4720 
   4721   v8::Handle<Value>* args0 = NULL;
   4722   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
   4723   CHECK_EQ(0, a0->Length());
   4724 
   4725   v8::Handle<Value> args1[] = { v8_num(1.1) };
   4726   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
   4727   CHECK_EQ(1, a1->Length());
   4728   CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
   4729 
   4730   v8::Handle<Value> args2[] = { v8_num(2.2),
   4731                                 v8_num(3.3) };
   4732   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
   4733   CHECK_EQ(2, a2->Length());
   4734   CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
   4735   CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
   4736 
   4737   v8::Handle<Value> args3[] = { v8_num(4.4),
   4738                                 v8_num(5.5),
   4739                                 v8_num(6.6) };
   4740   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
   4741   CHECK_EQ(3, a3->Length());
   4742   CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
   4743   CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
   4744   CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
   4745 
   4746   v8::Handle<Value> args4[] = { v8_num(7.7),
   4747                                 v8_num(8.8),
   4748                                 v8_num(9.9),
   4749                                 v8_num(10.11) };
   4750   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
   4751   CHECK_EQ(4, a4->Length());
   4752   CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
   4753   CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
   4754   CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
   4755   CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
   4756 }
   4757 
   4758 
   4759 static void CheckUncle(v8::TryCatch* try_catch) {
   4760   CHECK(try_catch->HasCaught());
   4761   String::Utf8Value str_value(try_catch->Exception());
   4762   CHECK_EQ(*str_value, "uncle?");
   4763   try_catch->Reset();
   4764 }
   4765 
   4766 
   4767 THREADED_TEST(ConversionNumber) {
   4768   LocalContext env;
   4769   v8::HandleScope scope(env->GetIsolate());
   4770   // Very large number.
   4771   CompileRun("var obj = Math.pow(2,32) * 1237;");
   4772   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   4773   CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
   4774   CHECK_EQ(0, obj->ToInt32()->Value());
   4775   CHECK(0u == obj->ToUint32()->Value());  // NOLINT - no CHECK_EQ for unsigned.
   4776   // Large number.
   4777   CompileRun("var obj = -1234567890123;");
   4778   obj = env->Global()->Get(v8_str("obj"));
   4779   CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
   4780   CHECK_EQ(-1912276171, obj->ToInt32()->Value());
   4781   CHECK(2382691125u == obj->ToUint32()->Value());  // NOLINT
   4782   // Small positive integer.
   4783   CompileRun("var obj = 42;");
   4784   obj = env->Global()->Get(v8_str("obj"));
   4785   CHECK_EQ(42.0, obj->ToNumber()->Value());
   4786   CHECK_EQ(42, obj->ToInt32()->Value());
   4787   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   4788   // Negative integer.
   4789   CompileRun("var obj = -37;");
   4790   obj = env->Global()->Get(v8_str("obj"));
   4791   CHECK_EQ(-37.0, obj->ToNumber()->Value());
   4792   CHECK_EQ(-37, obj->ToInt32()->Value());
   4793   CHECK(4294967259u == obj->ToUint32()->Value());  // NOLINT
   4794   // Positive non-int32 integer.
   4795   CompileRun("var obj = 0x81234567;");
   4796   obj = env->Global()->Get(v8_str("obj"));
   4797   CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
   4798   CHECK_EQ(-2128394905, obj->ToInt32()->Value());
   4799   CHECK(2166572391u == obj->ToUint32()->Value());  // NOLINT
   4800   // Fraction.
   4801   CompileRun("var obj = 42.3;");
   4802   obj = env->Global()->Get(v8_str("obj"));
   4803   CHECK_EQ(42.3, obj->ToNumber()->Value());
   4804   CHECK_EQ(42, obj->ToInt32()->Value());
   4805   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   4806   // Large negative fraction.
   4807   CompileRun("var obj = -5726623061.75;");
   4808   obj = env->Global()->Get(v8_str("obj"));
   4809   CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
   4810   CHECK_EQ(-1431655765, obj->ToInt32()->Value());
   4811   CHECK(2863311531u == obj->ToUint32()->Value());  // NOLINT
   4812 }
   4813 
   4814 
   4815 THREADED_TEST(isNumberType) {
   4816   LocalContext env;
   4817   v8::HandleScope scope(env->GetIsolate());
   4818   // Very large number.
   4819   CompileRun("var obj = Math.pow(2,32) * 1237;");
   4820   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   4821   CHECK(!obj->IsInt32());
   4822   CHECK(!obj->IsUint32());
   4823   // Large negative number.
   4824   CompileRun("var obj = -1234567890123;");
   4825   obj = env->Global()->Get(v8_str("obj"));
   4826   CHECK(!obj->IsInt32());
   4827   CHECK(!obj->IsUint32());
   4828   // Small positive integer.
   4829   CompileRun("var obj = 42;");
   4830   obj = env->Global()->Get(v8_str("obj"));
   4831   CHECK(obj->IsInt32());
   4832   CHECK(obj->IsUint32());
   4833   // Negative integer.
   4834   CompileRun("var obj = -37;");
   4835   obj = env->Global()->Get(v8_str("obj"));
   4836   CHECK(obj->IsInt32());
   4837   CHECK(!obj->IsUint32());
   4838   // Positive non-int32 integer.
   4839   CompileRun("var obj = 0x81234567;");
   4840   obj = env->Global()->Get(v8_str("obj"));
   4841   CHECK(!obj->IsInt32());
   4842   CHECK(obj->IsUint32());
   4843   // Fraction.
   4844   CompileRun("var obj = 42.3;");
   4845   obj = env->Global()->Get(v8_str("obj"));
   4846   CHECK(!obj->IsInt32());
   4847   CHECK(!obj->IsUint32());
   4848   // Large negative fraction.
   4849   CompileRun("var obj = -5726623061.75;");
   4850   obj = env->Global()->Get(v8_str("obj"));
   4851   CHECK(!obj->IsInt32());
   4852   CHECK(!obj->IsUint32());
   4853   // Positive zero
   4854   CompileRun("var obj = 0.0;");
   4855   obj = env->Global()->Get(v8_str("obj"));
   4856   CHECK(obj->IsInt32());
   4857   CHECK(obj->IsUint32());
   4858   // Positive zero
   4859   CompileRun("var obj = -0.0;");
   4860   obj = env->Global()->Get(v8_str("obj"));
   4861   CHECK(!obj->IsInt32());
   4862   CHECK(!obj->IsUint32());
   4863 }
   4864 
   4865 
   4866 THREADED_TEST(ConversionException) {
   4867   LocalContext env;
   4868   v8::Isolate* isolate = env->GetIsolate();
   4869   v8::HandleScope scope(isolate);
   4870   CompileRun(
   4871     "function TestClass() { };"
   4872     "TestClass.prototype.toString = function () { throw 'uncle?'; };"
   4873     "var obj = new TestClass();");
   4874   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   4875 
   4876   v8::TryCatch try_catch;
   4877 
   4878   Local<Value> to_string_result = obj->ToString();
   4879   CHECK(to_string_result.IsEmpty());
   4880   CheckUncle(&try_catch);
   4881 
   4882   Local<Value> to_number_result = obj->ToNumber();
   4883   CHECK(to_number_result.IsEmpty());
   4884   CheckUncle(&try_catch);
   4885 
   4886   Local<Value> to_integer_result = obj->ToInteger();
   4887   CHECK(to_integer_result.IsEmpty());
   4888   CheckUncle(&try_catch);
   4889 
   4890   Local<Value> to_uint32_result = obj->ToUint32();
   4891   CHECK(to_uint32_result.IsEmpty());
   4892   CheckUncle(&try_catch);
   4893 
   4894   Local<Value> to_int32_result = obj->ToInt32();
   4895   CHECK(to_int32_result.IsEmpty());
   4896   CheckUncle(&try_catch);
   4897 
   4898   Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
   4899   CHECK(to_object_result.IsEmpty());
   4900   CHECK(try_catch.HasCaught());
   4901   try_catch.Reset();
   4902 
   4903   int32_t int32_value = obj->Int32Value();
   4904   CHECK_EQ(0, int32_value);
   4905   CheckUncle(&try_catch);
   4906 
   4907   uint32_t uint32_value = obj->Uint32Value();
   4908   CHECK_EQ(0, uint32_value);
   4909   CheckUncle(&try_catch);
   4910 
   4911   double number_value = obj->NumberValue();
   4912   CHECK_NE(0, std::isnan(number_value));
   4913   CheckUncle(&try_catch);
   4914 
   4915   int64_t integer_value = obj->IntegerValue();
   4916   CHECK_EQ(0.0, static_cast<double>(integer_value));
   4917   CheckUncle(&try_catch);
   4918 }
   4919 
   4920 
   4921 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4922   ApiTestFuzzer::Fuzz();
   4923   args.GetIsolate()->ThrowException(v8_str("konto"));
   4924 }
   4925 
   4926 
   4927 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4928   if (args.Length() < 1) {
   4929     args.GetReturnValue().Set(false);
   4930     return;
   4931   }
   4932   v8::HandleScope scope(args.GetIsolate());
   4933   v8::TryCatch try_catch;
   4934   Local<Value> result = CompileRun(args[0]->ToString());
   4935   CHECK(!try_catch.HasCaught() || result.IsEmpty());
   4936   args.GetReturnValue().Set(try_catch.HasCaught());
   4937 }
   4938 
   4939 
   4940 THREADED_TEST(APICatch) {
   4941   v8::Isolate* isolate = CcTest::isolate();
   4942   v8::HandleScope scope(isolate);
   4943   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   4944   templ->Set(v8_str("ThrowFromC"),
   4945              v8::FunctionTemplate::New(isolate, ThrowFromC));
   4946   LocalContext context(0, templ);
   4947   CompileRun(
   4948     "var thrown = false;"
   4949     "try {"
   4950     "  ThrowFromC();"
   4951     "} catch (e) {"
   4952     "  thrown = true;"
   4953     "}");
   4954   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
   4955   CHECK(thrown->BooleanValue());
   4956 }
   4957 
   4958 
   4959 THREADED_TEST(APIThrowTryCatch) {
   4960   v8::Isolate* isolate = CcTest::isolate();
   4961   v8::HandleScope scope(isolate);
   4962   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   4963   templ->Set(v8_str("ThrowFromC"),
   4964              v8::FunctionTemplate::New(isolate, ThrowFromC));
   4965   LocalContext context(0, templ);
   4966   v8::TryCatch try_catch;
   4967   CompileRun("ThrowFromC();");
   4968   CHECK(try_catch.HasCaught());
   4969 }
   4970 
   4971 
   4972 // Test that a try-finally block doesn't shadow a try-catch block
   4973 // when setting up an external handler.
   4974 //
   4975 // BUG(271): Some of the exception propagation does not work on the
   4976 // ARM simulator because the simulator separates the C++ stack and the
   4977 // JS stack.  This test therefore fails on the simulator.  The test is
   4978 // not threaded to allow the threading tests to run on the simulator.
   4979 TEST(TryCatchInTryFinally) {
   4980   v8::Isolate* isolate = CcTest::isolate();
   4981   v8::HandleScope scope(isolate);
   4982   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   4983   templ->Set(v8_str("CCatcher"),
   4984              v8::FunctionTemplate::New(isolate, CCatcher));
   4985   LocalContext context(0, templ);
   4986   Local<Value> result = CompileRun("try {"
   4987                                    "  try {"
   4988                                    "    CCatcher('throw 7;');"
   4989                                    "  } finally {"
   4990                                    "  }"
   4991                                    "} catch (e) {"
   4992                                    "}");
   4993   CHECK(result->IsTrue());
   4994 }
   4995 
   4996 
   4997 static void check_reference_error_message(
   4998     v8::Handle<v8::Message> message,
   4999     v8::Handle<v8::Value> data) {
   5000   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
   5001   CHECK(message->Get()->Equals(v8_str(reference_error)));
   5002 }
   5003 
   5004 
   5005 static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5006   ApiTestFuzzer::Fuzz();
   5007   CHECK(false);
   5008 }
   5009 
   5010 
   5011 // Test that overwritten methods are not invoked on uncaught exception
   5012 // formatting. However, they are invoked when performing normal error
   5013 // string conversions.
   5014 TEST(APIThrowMessageOverwrittenToString) {
   5015   v8::Isolate* isolate = CcTest::isolate();
   5016   v8::HandleScope scope(isolate);
   5017   v8::V8::AddMessageListener(check_reference_error_message);
   5018   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5019   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
   5020   LocalContext context(NULL, templ);
   5021   CompileRun("asdf;");
   5022   CompileRun("var limit = {};"
   5023              "limit.valueOf = fail;"
   5024              "Error.stackTraceLimit = limit;");
   5025   CompileRun("asdf");
   5026   CompileRun("Array.prototype.pop = fail;");
   5027   CompileRun("Object.prototype.hasOwnProperty = fail;");
   5028   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
   5029   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
   5030   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
   5031   CompileRun("ReferenceError.prototype.toString ="
   5032              "  function() { return 'Whoops' }");
   5033   CompileRun("asdf;");
   5034   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
   5035   CompileRun("asdf;");
   5036   CompileRun("ReferenceError.prototype.constructor = void 0;");
   5037   CompileRun("asdf;");
   5038   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
   5039   CompileRun("asdf;");
   5040   CompileRun("ReferenceError.prototype = new Object();");
   5041   CompileRun("asdf;");
   5042   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
   5043   CHECK(string->Equals(v8_str("Whoops")));
   5044   CompileRun("ReferenceError.prototype.constructor = new Object();"
   5045              "ReferenceError.prototype.constructor.name = 1;"
   5046              "Number.prototype.toString = function() { return 'Whoops'; };"
   5047              "ReferenceError.prototype.toString = Object.prototype.toString;");
   5048   CompileRun("asdf;");
   5049   v8::V8::RemoveMessageListeners(check_reference_error_message);
   5050 }
   5051 
   5052 
   5053 static void check_custom_error_tostring(
   5054     v8::Handle<v8::Message> message,
   5055     v8::Handle<v8::Value> data) {
   5056   const char* uncaught_error = "Uncaught MyError toString";
   5057   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
   5058 }
   5059 
   5060 
   5061 TEST(CustomErrorToString) {
   5062   LocalContext context;
   5063   v8::HandleScope scope(context->GetIsolate());
   5064   v8::V8::AddMessageListener(check_custom_error_tostring);
   5065   CompileRun(
   5066     "function MyError(name, message) {                   "
   5067     "  this.name = name;                                 "
   5068     "  this.message = message;                           "
   5069     "}                                                   "
   5070     "MyError.prototype = Object.create(Error.prototype); "
   5071     "MyError.prototype.toString = function() {           "
   5072     "  return 'MyError toString';                        "
   5073     "};                                                  "
   5074     "throw new MyError('my name', 'my message');         ");
   5075   v8::V8::RemoveMessageListeners(check_custom_error_tostring);
   5076 }
   5077 
   5078 
   5079 static void check_custom_error_message(
   5080     v8::Handle<v8::Message> message,
   5081     v8::Handle<v8::Value> data) {
   5082   const char* uncaught_error = "Uncaught MyError: my message";
   5083   printf("%s\n", *v8::String::Utf8Value(message->Get()));
   5084   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
   5085 }
   5086 
   5087 
   5088 TEST(CustomErrorMessage) {
   5089   LocalContext context;
   5090   v8::HandleScope scope(context->GetIsolate());
   5091   v8::V8::AddMessageListener(check_custom_error_message);
   5092 
   5093   // Handlebars.
   5094   CompileRun(
   5095     "function MyError(msg) {                             "
   5096     "  this.name = 'MyError';                            "
   5097     "  this.message = msg;                               "
   5098     "}                                                   "
   5099     "MyError.prototype = new Error();                    "
   5100     "throw new MyError('my message');                    ");
   5101 
   5102   // Closure.
   5103   CompileRun(
   5104     "function MyError(msg) {                             "
   5105     "  this.name = 'MyError';                            "
   5106     "  this.message = msg;                               "
   5107     "}                                                   "
   5108     "inherits = function(childCtor, parentCtor) {        "
   5109     "    function tempCtor() {};                         "
   5110     "    tempCtor.prototype = parentCtor.prototype;      "
   5111     "    childCtor.superClass_ = parentCtor.prototype;   "
   5112     "    childCtor.prototype = new tempCtor();           "
   5113     "    childCtor.prototype.constructor = childCtor;    "
   5114     "};                                                  "
   5115     "inherits(MyError, Error);                           "
   5116     "throw new MyError('my message');                    ");
   5117 
   5118   // Object.create.
   5119   CompileRun(
   5120     "function MyError(msg) {                             "
   5121     "  this.name = 'MyError';                            "
   5122     "  this.message = msg;                               "
   5123     "}                                                   "
   5124     "MyError.prototype = Object.create(Error.prototype); "
   5125     "throw new MyError('my message');                    ");
   5126 
   5127   v8::V8::RemoveMessageListeners(check_custom_error_message);
   5128 }
   5129 
   5130 
   5131 static void receive_message(v8::Handle<v8::Message> message,
   5132                             v8::Handle<v8::Value> data) {
   5133   message->Get();
   5134   message_received = true;
   5135 }
   5136 
   5137 
   5138 TEST(APIThrowMessage) {
   5139   message_received = false;
   5140   v8::Isolate* isolate = CcTest::isolate();
   5141   v8::HandleScope scope(isolate);
   5142   v8::V8::AddMessageListener(receive_message);
   5143   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5144   templ->Set(v8_str("ThrowFromC"),
   5145              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5146   LocalContext context(0, templ);
   5147   CompileRun("ThrowFromC();");
   5148   CHECK(message_received);
   5149   v8::V8::RemoveMessageListeners(receive_message);
   5150 }
   5151 
   5152 
   5153 TEST(APIThrowMessageAndVerboseTryCatch) {
   5154   message_received = false;
   5155   v8::Isolate* isolate = CcTest::isolate();
   5156   v8::HandleScope scope(isolate);
   5157   v8::V8::AddMessageListener(receive_message);
   5158   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5159   templ->Set(v8_str("ThrowFromC"),
   5160              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5161   LocalContext context(0, templ);
   5162   v8::TryCatch try_catch;
   5163   try_catch.SetVerbose(true);
   5164   Local<Value> result = CompileRun("ThrowFromC();");
   5165   CHECK(try_catch.HasCaught());
   5166   CHECK(result.IsEmpty());
   5167   CHECK(message_received);
   5168   v8::V8::RemoveMessageListeners(receive_message);
   5169 }
   5170 
   5171 
   5172 TEST(APIStackOverflowAndVerboseTryCatch) {
   5173   message_received = false;
   5174   LocalContext context;
   5175   v8::HandleScope scope(context->GetIsolate());
   5176   v8::V8::AddMessageListener(receive_message);
   5177   v8::TryCatch try_catch;
   5178   try_catch.SetVerbose(true);
   5179   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
   5180   CHECK(try_catch.HasCaught());
   5181   CHECK(result.IsEmpty());
   5182   CHECK(message_received);
   5183   v8::V8::RemoveMessageListeners(receive_message);
   5184 }
   5185 
   5186 
   5187 THREADED_TEST(ExternalScriptException) {
   5188   v8::Isolate* isolate = CcTest::isolate();
   5189   v8::HandleScope scope(isolate);
   5190   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5191   templ->Set(v8_str("ThrowFromC"),
   5192              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5193   LocalContext context(0, templ);
   5194 
   5195   v8::TryCatch try_catch;
   5196   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
   5197   CHECK(result.IsEmpty());
   5198   CHECK(try_catch.HasCaught());
   5199   String::Utf8Value exception_value(try_catch.Exception());
   5200   CHECK_EQ("konto", *exception_value);
   5201 }
   5202 
   5203 
   5204 
   5205 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5206   ApiTestFuzzer::Fuzz();
   5207   CHECK_EQ(4, args.Length());
   5208   int count = args[0]->Int32Value();
   5209   int cInterval = args[2]->Int32Value();
   5210   if (count == 0) {
   5211     args.GetIsolate()->ThrowException(v8_str("FromC"));
   5212     return;
   5213   } else {
   5214     Local<v8::Object> global =
   5215         args.GetIsolate()->GetCurrentContext()->Global();
   5216     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
   5217     v8::Handle<Value> argv[] = { v8_num(count - 1),
   5218                                  args[1],
   5219                                  args[2],
   5220                                  args[3] };
   5221     if (count % cInterval == 0) {
   5222       v8::TryCatch try_catch;
   5223       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
   5224       int expected = args[3]->Int32Value();
   5225       if (try_catch.HasCaught()) {
   5226         CHECK_EQ(expected, count);
   5227         CHECK(result.IsEmpty());
   5228         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   5229       } else {
   5230         CHECK_NE(expected, count);
   5231       }
   5232       args.GetReturnValue().Set(result);
   5233       return;
   5234     } else {
   5235       args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
   5236       return;
   5237     }
   5238   }
   5239 }
   5240 
   5241 
   5242 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5243   ApiTestFuzzer::Fuzz();
   5244   CHECK_EQ(3, args.Length());
   5245   bool equality = args[0]->BooleanValue();
   5246   int count = args[1]->Int32Value();
   5247   int expected = args[2]->Int32Value();
   5248   if (equality) {
   5249     CHECK_EQ(count, expected);
   5250   } else {
   5251     CHECK_NE(count, expected);
   5252   }
   5253 }
   5254 
   5255 
   5256 THREADED_TEST(EvalInTryFinally) {
   5257   LocalContext context;
   5258   v8::HandleScope scope(context->GetIsolate());
   5259   v8::TryCatch try_catch;
   5260   CompileRun("(function() {"
   5261              "  try {"
   5262              "    eval('asldkf (*&^&*^');"
   5263              "  } finally {"
   5264              "    return;"
   5265              "  }"
   5266              "})()");
   5267   CHECK(!try_catch.HasCaught());
   5268 }
   5269 
   5270 
   5271 // This test works by making a stack of alternating JavaScript and C
   5272 // activations.  These activations set up exception handlers with regular
   5273 // intervals, one interval for C activations and another for JavaScript
   5274 // activations.  When enough activations have been created an exception is
   5275 // thrown and we check that the right activation catches the exception and that
   5276 // no other activations do.  The right activation is always the topmost one with
   5277 // a handler, regardless of whether it is in JavaScript or C.
   5278 //
   5279 // The notation used to describe a test case looks like this:
   5280 //
   5281 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
   5282 //
   5283 // Each entry is an activation, either JS or C.  The index is the count at that
   5284 // level.  Stars identify activations with exception handlers, the @ identifies
   5285 // the exception handler that should catch the exception.
   5286 //
   5287 // BUG(271): Some of the exception propagation does not work on the
   5288 // ARM simulator because the simulator separates the C++ stack and the
   5289 // JS stack.  This test therefore fails on the simulator.  The test is
   5290 // not threaded to allow the threading tests to run on the simulator.
   5291 TEST(ExceptionOrder) {
   5292   v8::Isolate* isolate = CcTest::isolate();
   5293   v8::HandleScope scope(isolate);
   5294   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5295   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
   5296   templ->Set(v8_str("CThrowCountDown"),
   5297              v8::FunctionTemplate::New(isolate, CThrowCountDown));
   5298   LocalContext context(0, templ);
   5299   CompileRun(
   5300     "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
   5301     "  if (count == 0) throw 'FromJS';"
   5302     "  if (count % jsInterval == 0) {"
   5303     "    try {"
   5304     "      var value = CThrowCountDown(count - 1,"
   5305     "                                  jsInterval,"
   5306     "                                  cInterval,"
   5307     "                                  expected);"
   5308     "      check(false, count, expected);"
   5309     "      return value;"
   5310     "    } catch (e) {"
   5311     "      check(true, count, expected);"
   5312     "    }"
   5313     "  } else {"
   5314     "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
   5315     "  }"
   5316     "}");
   5317   Local<Function> fun =
   5318       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
   5319 
   5320   const int argc = 4;
   5321   //                             count      jsInterval cInterval  expected
   5322 
   5323   // *JS[4] *C[3] @JS[2] C[1] JS[0]
   5324   v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
   5325   fun->Call(fun, argc, a0);
   5326 
   5327   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
   5328   v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
   5329   fun->Call(fun, argc, a1);
   5330 
   5331   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
   5332   v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
   5333   fun->Call(fun, argc, a2);
   5334 
   5335   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
   5336   v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
   5337   fun->Call(fun, argc, a3);
   5338 
   5339   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
   5340   v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
   5341   fun->Call(fun, argc, a4);
   5342 
   5343   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
   5344   v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
   5345   fun->Call(fun, argc, a5);
   5346 }
   5347 
   5348 
   5349 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5350   ApiTestFuzzer::Fuzz();
   5351   CHECK_EQ(1, args.Length());
   5352   args.GetIsolate()->ThrowException(args[0]);
   5353 }
   5354 
   5355 
   5356 THREADED_TEST(ThrowValues) {
   5357   v8::Isolate* isolate = CcTest::isolate();
   5358   v8::HandleScope scope(isolate);
   5359   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5360   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
   5361   LocalContext context(0, templ);
   5362   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   5363     "function Run(obj) {"
   5364     "  try {"
   5365     "    Throw(obj);"
   5366     "  } catch (e) {"
   5367     "    return e;"
   5368     "  }"
   5369     "  return 'no exception';"
   5370     "}"
   5371     "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
   5372   CHECK_EQ(5, result->Length());
   5373   CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
   5374   CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
   5375   CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
   5376   CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
   5377   CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
   5378   CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
   5379   CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
   5380 }
   5381 
   5382 
   5383 THREADED_TEST(CatchZero) {
   5384   LocalContext context;
   5385   v8::HandleScope scope(context->GetIsolate());
   5386   v8::TryCatch try_catch;
   5387   CHECK(!try_catch.HasCaught());
   5388   CompileRun("throw 10");
   5389   CHECK(try_catch.HasCaught());
   5390   CHECK_EQ(10, try_catch.Exception()->Int32Value());
   5391   try_catch.Reset();
   5392   CHECK(!try_catch.HasCaught());
   5393   CompileRun("throw 0");
   5394   CHECK(try_catch.HasCaught());
   5395   CHECK_EQ(0, try_catch.Exception()->Int32Value());
   5396 }
   5397 
   5398 
   5399 THREADED_TEST(CatchExceptionFromWith) {
   5400   LocalContext context;
   5401   v8::HandleScope scope(context->GetIsolate());
   5402   v8::TryCatch try_catch;
   5403   CHECK(!try_catch.HasCaught());
   5404   CompileRun("var o = {}; with (o) { throw 42; }");
   5405   CHECK(try_catch.HasCaught());
   5406 }
   5407 
   5408 
   5409 THREADED_TEST(TryCatchAndFinallyHidingException) {
   5410   LocalContext context;
   5411   v8::HandleScope scope(context->GetIsolate());
   5412   v8::TryCatch try_catch;
   5413   CHECK(!try_catch.HasCaught());
   5414   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
   5415   CompileRun("f({toString: function() { throw 42; }});");
   5416   CHECK(!try_catch.HasCaught());
   5417 }
   5418 
   5419 
   5420 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5421   v8::TryCatch try_catch;
   5422 }
   5423 
   5424 
   5425 THREADED_TEST(TryCatchAndFinally) {
   5426   LocalContext context;
   5427   v8::Isolate* isolate = context->GetIsolate();
   5428   v8::HandleScope scope(isolate);
   5429   context->Global()->Set(
   5430       v8_str("native_with_try_catch"),
   5431       v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
   5432   v8::TryCatch try_catch;
   5433   CHECK(!try_catch.HasCaught());
   5434   CompileRun(
   5435       "try {\n"
   5436       "  throw new Error('a');\n"
   5437       "} finally {\n"
   5438       "  native_with_try_catch();\n"
   5439       "}\n");
   5440   CHECK(try_catch.HasCaught());
   5441 }
   5442 
   5443 
   5444 static void TryCatchNested1Helper(int depth) {
   5445   if (depth > 0) {
   5446     v8::TryCatch try_catch;
   5447     try_catch.SetVerbose(true);
   5448     TryCatchNested1Helper(depth - 1);
   5449     CHECK(try_catch.HasCaught());
   5450     try_catch.ReThrow();
   5451   } else {
   5452     CcTest::isolate()->ThrowException(v8_str("E1"));
   5453   }
   5454 }
   5455 
   5456 
   5457 static void TryCatchNested2Helper(int depth) {
   5458   if (depth > 0) {
   5459     v8::TryCatch try_catch;
   5460     try_catch.SetVerbose(true);
   5461     TryCatchNested2Helper(depth - 1);
   5462     CHECK(try_catch.HasCaught());
   5463     try_catch.ReThrow();
   5464   } else {
   5465     CompileRun("throw 'E2';");
   5466   }
   5467 }
   5468 
   5469 
   5470 TEST(TryCatchNested) {
   5471   v8::V8::Initialize();
   5472   LocalContext context;
   5473   v8::HandleScope scope(context->GetIsolate());
   5474 
   5475   {
   5476     // Test nested try-catch with a native throw in the end.
   5477     v8::TryCatch try_catch;
   5478     TryCatchNested1Helper(5);
   5479     CHECK(try_catch.HasCaught());
   5480     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
   5481   }
   5482 
   5483   {
   5484     // Test nested try-catch with a JavaScript throw in the end.
   5485     v8::TryCatch try_catch;
   5486     TryCatchNested2Helper(5);
   5487     CHECK(try_catch.HasCaught());
   5488     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
   5489   }
   5490 }
   5491 
   5492 
   5493 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
   5494   CHECK(try_catch->HasCaught());
   5495   Handle<Message> message = try_catch->Message();
   5496   Handle<Value> resource = message->GetScriptOrigin().ResourceName();
   5497   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
   5498   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
   5499                      "Uncaught Error: a"));
   5500   CHECK_EQ(1, message->GetLineNumber());
   5501   CHECK_EQ(6, message->GetStartColumn());
   5502 }
   5503 
   5504 
   5505 void TryCatchMixedNestingHelper(
   5506     const v8::FunctionCallbackInfo<v8::Value>& args) {
   5507   ApiTestFuzzer::Fuzz();
   5508   v8::TryCatch try_catch;
   5509   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
   5510   CHECK(try_catch.HasCaught());
   5511   TryCatchMixedNestingCheck(&try_catch);
   5512   try_catch.ReThrow();
   5513 }
   5514 
   5515 
   5516 // This test ensures that an outer TryCatch in the following situation:
   5517 //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
   5518 // does not clobber the Message object generated for the inner TryCatch.
   5519 // This exercises the ability of TryCatch.ReThrow() to restore the
   5520 // inner pending Message before throwing the exception again.
   5521 TEST(TryCatchMixedNesting) {
   5522   v8::Isolate* isolate = CcTest::isolate();
   5523   v8::HandleScope scope(isolate);
   5524   v8::V8::Initialize();
   5525   v8::TryCatch try_catch;
   5526   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5527   templ->Set(v8_str("TryCatchMixedNestingHelper"),
   5528              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
   5529   LocalContext context(0, templ);
   5530   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
   5531   TryCatchMixedNestingCheck(&try_catch);
   5532 }
   5533 
   5534 
   5535 void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5536   ApiTestFuzzer::Fuzz();
   5537   v8::TryCatch try_catch;
   5538   args.GetIsolate()->ThrowException(v8_str("boom"));
   5539   CHECK(try_catch.HasCaught());
   5540 }
   5541 
   5542 
   5543 TEST(TryCatchNative) {
   5544   v8::Isolate* isolate = CcTest::isolate();
   5545   v8::HandleScope scope(isolate);
   5546   v8::V8::Initialize();
   5547   v8::TryCatch try_catch;
   5548   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5549   templ->Set(v8_str("TryCatchNativeHelper"),
   5550              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
   5551   LocalContext context(0, templ);
   5552   CompileRun("TryCatchNativeHelper();");
   5553   CHECK(!try_catch.HasCaught());
   5554 }
   5555 
   5556 
   5557 void TryCatchNativeResetHelper(
   5558     const v8::FunctionCallbackInfo<v8::Value>& args) {
   5559   ApiTestFuzzer::Fuzz();
   5560   v8::TryCatch try_catch;
   5561   args.GetIsolate()->ThrowException(v8_str("boom"));
   5562   CHECK(try_catch.HasCaught());
   5563   try_catch.Reset();
   5564   CHECK(!try_catch.HasCaught());
   5565 }
   5566 
   5567 
   5568 TEST(TryCatchNativeReset) {
   5569   v8::Isolate* isolate = CcTest::isolate();
   5570   v8::HandleScope scope(isolate);
   5571   v8::V8::Initialize();
   5572   v8::TryCatch try_catch;
   5573   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5574   templ->Set(v8_str("TryCatchNativeResetHelper"),
   5575              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
   5576   LocalContext context(0, templ);
   5577   CompileRun("TryCatchNativeResetHelper();");
   5578   CHECK(!try_catch.HasCaught());
   5579 }
   5580 
   5581 
   5582 THREADED_TEST(Equality) {
   5583   LocalContext context;
   5584   v8::Isolate* isolate = context->GetIsolate();
   5585   v8::HandleScope scope(context->GetIsolate());
   5586   // Check that equality works at all before relying on CHECK_EQ
   5587   CHECK(v8_str("a")->Equals(v8_str("a")));
   5588   CHECK(!v8_str("a")->Equals(v8_str("b")));
   5589 
   5590   CHECK_EQ(v8_str("a"), v8_str("a"));
   5591   CHECK_NE(v8_str("a"), v8_str("b"));
   5592   CHECK_EQ(v8_num(1), v8_num(1));
   5593   CHECK_EQ(v8_num(1.00), v8_num(1));
   5594   CHECK_NE(v8_num(1), v8_num(2));
   5595 
   5596   // Assume String is not internalized.
   5597   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
   5598   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
   5599   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
   5600   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   5601   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
   5602   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
   5603   Local<Value> not_a_number = v8_num(v8::base::OS::nan_value());
   5604   CHECK(!not_a_number->StrictEquals(not_a_number));
   5605   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
   5606   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
   5607 
   5608   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
   5609   v8::Persistent<v8::Object> alias(isolate, obj);
   5610   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
   5611   alias.Reset();
   5612 
   5613   CHECK(v8_str("a")->SameValue(v8_str("a")));
   5614   CHECK(!v8_str("a")->SameValue(v8_str("b")));
   5615   CHECK(!v8_str("5")->SameValue(v8_num(5)));
   5616   CHECK(v8_num(1)->SameValue(v8_num(1)));
   5617   CHECK(!v8_num(1)->SameValue(v8_num(2)));
   5618   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
   5619   CHECK(not_a_number->SameValue(not_a_number));
   5620   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
   5621   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
   5622 }
   5623 
   5624 
   5625 THREADED_TEST(MultiRun) {
   5626   LocalContext context;
   5627   v8::HandleScope scope(context->GetIsolate());
   5628   Local<Script> script = v8_compile("x");
   5629   for (int i = 0; i < 10; i++)
   5630     script->Run();
   5631 }
   5632 
   5633 
   5634 static void GetXValue(Local<String> name,
   5635                       const v8::PropertyCallbackInfo<v8::Value>& info) {
   5636   ApiTestFuzzer::Fuzz();
   5637   CHECK_EQ(info.Data(), v8_str("donut"));
   5638   CHECK_EQ(name, v8_str("x"));
   5639   info.GetReturnValue().Set(name);
   5640 }
   5641 
   5642 
   5643 THREADED_TEST(SimplePropertyRead) {
   5644   LocalContext context;
   5645   v8::Isolate* isolate = context->GetIsolate();
   5646   v8::HandleScope scope(isolate);
   5647   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5648   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   5649   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5650   Local<Script> script = v8_compile("obj.x");
   5651   for (int i = 0; i < 10; i++) {
   5652     Local<Value> result = script->Run();
   5653     CHECK_EQ(result, v8_str("x"));
   5654   }
   5655 }
   5656 
   5657 
   5658 THREADED_TEST(DefinePropertyOnAPIAccessor) {
   5659   LocalContext context;
   5660   v8::Isolate* isolate = context->GetIsolate();
   5661   v8::HandleScope scope(isolate);
   5662   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5663   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   5664   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5665 
   5666   // Uses getOwnPropertyDescriptor to check the configurable status
   5667   Local<Script> script_desc = v8_compile(
   5668       "var prop = Object.getOwnPropertyDescriptor( "
   5669       "obj, 'x');"
   5670       "prop.configurable;");
   5671   Local<Value> result = script_desc->Run();
   5672   CHECK_EQ(result->BooleanValue(), true);
   5673 
   5674   // Redefine get - but still configurable
   5675   Local<Script> script_define = v8_compile(
   5676       "var desc = { get: function(){return 42; },"
   5677       "            configurable: true };"
   5678       "Object.defineProperty(obj, 'x', desc);"
   5679       "obj.x");
   5680   result = script_define->Run();
   5681   CHECK_EQ(result, v8_num(42));
   5682 
   5683   // Check that the accessor is still configurable
   5684   result = script_desc->Run();
   5685   CHECK_EQ(result->BooleanValue(), true);
   5686 
   5687   // Redefine to a non-configurable
   5688   script_define = v8_compile(
   5689       "var desc = { get: function(){return 43; },"
   5690       "             configurable: false };"
   5691       "Object.defineProperty(obj, 'x', desc);"
   5692       "obj.x");
   5693   result = script_define->Run();
   5694   CHECK_EQ(result, v8_num(43));
   5695   result = script_desc->Run();
   5696   CHECK_EQ(result->BooleanValue(), false);
   5697 
   5698   // Make sure that it is not possible to redefine again
   5699   v8::TryCatch try_catch;
   5700   result = script_define->Run();
   5701   CHECK(try_catch.HasCaught());
   5702   String::Utf8Value exception_value(try_catch.Exception());
   5703   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5704 }
   5705 
   5706 
   5707 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
   5708   v8::Isolate* isolate = CcTest::isolate();
   5709   v8::HandleScope scope(isolate);
   5710   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5711   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   5712   LocalContext context;
   5713   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5714 
   5715   Local<Script> script_desc = v8_compile(
   5716       "var prop ="
   5717       "Object.getOwnPropertyDescriptor( "
   5718       "obj, 'x');"
   5719       "prop.configurable;");
   5720   Local<Value> result = script_desc->Run();
   5721   CHECK_EQ(result->BooleanValue(), true);
   5722 
   5723   Local<Script> script_define = v8_compile(
   5724       "var desc = {get: function(){return 42; },"
   5725       "            configurable: true };"
   5726       "Object.defineProperty(obj, 'x', desc);"
   5727       "obj.x");
   5728   result = script_define->Run();
   5729   CHECK_EQ(result, v8_num(42));
   5730 
   5731 
   5732   result = script_desc->Run();
   5733   CHECK_EQ(result->BooleanValue(), true);
   5734 
   5735 
   5736   script_define = v8_compile(
   5737       "var desc = {get: function(){return 43; },"
   5738       "            configurable: false };"
   5739       "Object.defineProperty(obj, 'x', desc);"
   5740       "obj.x");
   5741   result = script_define->Run();
   5742   CHECK_EQ(result, v8_num(43));
   5743   result = script_desc->Run();
   5744 
   5745   CHECK_EQ(result->BooleanValue(), false);
   5746 
   5747   v8::TryCatch try_catch;
   5748   result = script_define->Run();
   5749   CHECK(try_catch.HasCaught());
   5750   String::Utf8Value exception_value(try_catch.Exception());
   5751   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5752 }
   5753 
   5754 
   5755 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
   5756                                                 char const* name) {
   5757   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
   5758 }
   5759 
   5760 
   5761 THREADED_TEST(DefineAPIAccessorOnObject) {
   5762   v8::Isolate* isolate = CcTest::isolate();
   5763   v8::HandleScope scope(isolate);
   5764   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5765   LocalContext context;
   5766 
   5767   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   5768   CompileRun("var obj2 = {};");
   5769 
   5770   CHECK(CompileRun("obj1.x")->IsUndefined());
   5771   CHECK(CompileRun("obj2.x")->IsUndefined());
   5772 
   5773   CHECK(GetGlobalProperty(&context, "obj1")->
   5774       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5775 
   5776   ExpectString("obj1.x", "x");
   5777   CHECK(CompileRun("obj2.x")->IsUndefined());
   5778 
   5779   CHECK(GetGlobalProperty(&context, "obj2")->
   5780       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5781 
   5782   ExpectString("obj1.x", "x");
   5783   ExpectString("obj2.x", "x");
   5784 
   5785   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5786   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5787 
   5788   CompileRun("Object.defineProperty(obj1, 'x',"
   5789              "{ get: function() { return 'y'; }, configurable: true })");
   5790 
   5791   ExpectString("obj1.x", "y");
   5792   ExpectString("obj2.x", "x");
   5793 
   5794   CompileRun("Object.defineProperty(obj2, 'x',"
   5795              "{ get: function() { return 'y'; }, configurable: true })");
   5796 
   5797   ExpectString("obj1.x", "y");
   5798   ExpectString("obj2.x", "y");
   5799 
   5800   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5801   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5802 
   5803   CHECK(GetGlobalProperty(&context, "obj1")->
   5804       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5805   CHECK(GetGlobalProperty(&context, "obj2")->
   5806       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5807 
   5808   ExpectString("obj1.x", "x");
   5809   ExpectString("obj2.x", "x");
   5810 
   5811   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5812   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5813 
   5814   // Define getters/setters, but now make them not configurable.
   5815   CompileRun("Object.defineProperty(obj1, 'x',"
   5816              "{ get: function() { return 'z'; }, configurable: false })");
   5817   CompileRun("Object.defineProperty(obj2, 'x',"
   5818              "{ get: function() { return 'z'; }, configurable: false })");
   5819 
   5820   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5821   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5822 
   5823   ExpectString("obj1.x", "z");
   5824   ExpectString("obj2.x", "z");
   5825 
   5826   CHECK(!GetGlobalProperty(&context, "obj1")->
   5827       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5828   CHECK(!GetGlobalProperty(&context, "obj2")->
   5829       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5830 
   5831   ExpectString("obj1.x", "z");
   5832   ExpectString("obj2.x", "z");
   5833 }
   5834 
   5835 
   5836 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
   5837   v8::Isolate* isolate = CcTest::isolate();
   5838   v8::HandleScope scope(isolate);
   5839   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5840   LocalContext context;
   5841 
   5842   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   5843   CompileRun("var obj2 = {};");
   5844 
   5845   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   5846         v8_str("x"),
   5847         GetXValue, NULL,
   5848         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   5849   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   5850         v8_str("x"),
   5851         GetXValue, NULL,
   5852         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   5853 
   5854   ExpectString("obj1.x", "x");
   5855   ExpectString("obj2.x", "x");
   5856 
   5857   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5858   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5859 
   5860   CHECK(!GetGlobalProperty(&context, "obj1")->
   5861       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5862   CHECK(!GetGlobalProperty(&context, "obj2")->
   5863       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5864 
   5865   {
   5866     v8::TryCatch try_catch;
   5867     CompileRun("Object.defineProperty(obj1, 'x',"
   5868         "{get: function() { return 'func'; }})");
   5869     CHECK(try_catch.HasCaught());
   5870     String::Utf8Value exception_value(try_catch.Exception());
   5871     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5872   }
   5873   {
   5874     v8::TryCatch try_catch;
   5875     CompileRun("Object.defineProperty(obj2, 'x',"
   5876         "{get: function() { return 'func'; }})");
   5877     CHECK(try_catch.HasCaught());
   5878     String::Utf8Value exception_value(try_catch.Exception());
   5879     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5880   }
   5881 }
   5882 
   5883 
   5884 static void Get239Value(Local<String> name,
   5885                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   5886   ApiTestFuzzer::Fuzz();
   5887   CHECK_EQ(info.Data(), v8_str("donut"));
   5888   CHECK_EQ(name, v8_str("239"));
   5889   info.GetReturnValue().Set(name);
   5890 }
   5891 
   5892 
   5893 THREADED_TEST(ElementAPIAccessor) {
   5894   v8::Isolate* isolate = CcTest::isolate();
   5895   v8::HandleScope scope(isolate);
   5896   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5897   LocalContext context;
   5898 
   5899   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   5900   CompileRun("var obj2 = {};");
   5901 
   5902   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   5903         v8_str("239"),
   5904         Get239Value, NULL,
   5905         v8_str("donut")));
   5906   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   5907         v8_str("239"),
   5908         Get239Value, NULL,
   5909         v8_str("donut")));
   5910 
   5911   ExpectString("obj1[239]", "239");
   5912   ExpectString("obj2[239]", "239");
   5913   ExpectString("obj1['239']", "239");
   5914   ExpectString("obj2['239']", "239");
   5915 }
   5916 
   5917 
   5918 v8::Persistent<Value> xValue;
   5919 
   5920 
   5921 static void SetXValue(Local<String> name,
   5922                       Local<Value> value,
   5923                       const v8::PropertyCallbackInfo<void>& info) {
   5924   CHECK_EQ(value, v8_num(4));
   5925   CHECK_EQ(info.Data(), v8_str("donut"));
   5926   CHECK_EQ(name, v8_str("x"));
   5927   CHECK(xValue.IsEmpty());
   5928   xValue.Reset(info.GetIsolate(), value);
   5929 }
   5930 
   5931 
   5932 THREADED_TEST(SimplePropertyWrite) {
   5933   v8::Isolate* isolate = CcTest::isolate();
   5934   v8::HandleScope scope(isolate);
   5935   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5936   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
   5937   LocalContext context;
   5938   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5939   Local<Script> script = v8_compile("obj.x = 4");
   5940   for (int i = 0; i < 10; i++) {
   5941     CHECK(xValue.IsEmpty());
   5942     script->Run();
   5943     CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
   5944     xValue.Reset();
   5945   }
   5946 }
   5947 
   5948 
   5949 THREADED_TEST(SetterOnly) {
   5950   v8::Isolate* isolate = CcTest::isolate();
   5951   v8::HandleScope scope(isolate);
   5952   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5953   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
   5954   LocalContext context;
   5955   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5956   Local<Script> script = v8_compile("obj.x = 4; obj.x");
   5957   for (int i = 0; i < 10; i++) {
   5958     CHECK(xValue.IsEmpty());
   5959     script->Run();
   5960     CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
   5961     xValue.Reset();
   5962   }
   5963 }
   5964 
   5965 
   5966 THREADED_TEST(NoAccessors) {
   5967   v8::Isolate* isolate = CcTest::isolate();
   5968   v8::HandleScope scope(isolate);
   5969   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5970   templ->SetAccessor(v8_str("x"),
   5971                      static_cast<v8::AccessorGetterCallback>(NULL),
   5972                      NULL,
   5973                      v8_str("donut"));
   5974   LocalContext context;
   5975   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5976   Local<Script> script = v8_compile("obj.x = 4; obj.x");
   5977   for (int i = 0; i < 10; i++) {
   5978     script->Run();
   5979   }
   5980 }
   5981 
   5982 
   5983 static void XPropertyGetter(Local<String> property,
   5984                             const v8::PropertyCallbackInfo<v8::Value>& info) {
   5985   ApiTestFuzzer::Fuzz();
   5986   CHECK(info.Data()->IsUndefined());
   5987   info.GetReturnValue().Set(property);
   5988 }
   5989 
   5990 
   5991 THREADED_TEST(NamedInterceptorPropertyRead) {
   5992   v8::Isolate* isolate = CcTest::isolate();
   5993   v8::HandleScope scope(isolate);
   5994   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5995   templ->SetNamedPropertyHandler(XPropertyGetter);
   5996   LocalContext context;
   5997   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5998   Local<Script> script = v8_compile("obj.x");
   5999   for (int i = 0; i < 10; i++) {
   6000     Local<Value> result = script->Run();
   6001     CHECK_EQ(result, v8_str("x"));
   6002   }
   6003 }
   6004 
   6005 
   6006 THREADED_TEST(NamedInterceptorDictionaryIC) {
   6007   v8::Isolate* isolate = CcTest::isolate();
   6008   v8::HandleScope scope(isolate);
   6009   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6010   templ->SetNamedPropertyHandler(XPropertyGetter);
   6011   LocalContext context;
   6012   // Create an object with a named interceptor.
   6013   context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
   6014   Local<Script> script = v8_compile("interceptor_obj.x");
   6015   for (int i = 0; i < 10; i++) {
   6016     Local<Value> result = script->Run();
   6017     CHECK_EQ(result, v8_str("x"));
   6018   }
   6019   // Create a slow case object and a function accessing a property in
   6020   // that slow case object (with dictionary probing in generated
   6021   // code). Then force object with a named interceptor into slow-case,
   6022   // pass it to the function, and check that the interceptor is called
   6023   // instead of accessing the local property.
   6024   Local<Value> result =
   6025       CompileRun("function get_x(o) { return o.x; };"
   6026                  "var obj = { x : 42, y : 0 };"
   6027                  "delete obj.y;"
   6028                  "for (var i = 0; i < 10; i++) get_x(obj);"
   6029                  "interceptor_obj.x = 42;"
   6030                  "interceptor_obj.y = 10;"
   6031                  "delete interceptor_obj.y;"
   6032                  "get_x(interceptor_obj)");
   6033   CHECK_EQ(result, v8_str("x"));
   6034 }
   6035 
   6036 
   6037 THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
   6038   v8::Isolate* isolate = CcTest::isolate();
   6039   v8::HandleScope scope(isolate);
   6040   v8::Local<Context> context1 = Context::New(isolate);
   6041 
   6042   context1->Enter();
   6043   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6044   templ->SetNamedPropertyHandler(XPropertyGetter);
   6045   // Create an object with a named interceptor.
   6046   v8::Local<v8::Object> object = templ->NewInstance();
   6047   context1->Global()->Set(v8_str("interceptor_obj"), object);
   6048 
   6049   // Force the object into the slow case.
   6050   CompileRun("interceptor_obj.y = 0;"
   6051              "delete interceptor_obj.y;");
   6052   context1->Exit();
   6053 
   6054   {
   6055     // Introduce the object into a different context.
   6056     // Repeat named loads to exercise ICs.
   6057     LocalContext context2;
   6058     context2->Global()->Set(v8_str("interceptor_obj"), object);
   6059     Local<Value> result =
   6060       CompileRun("function get_x(o) { return o.x; }"
   6061                  "interceptor_obj.x = 42;"
   6062                  "for (var i=0; i != 10; i++) {"
   6063                  "  get_x(interceptor_obj);"
   6064                  "}"
   6065                  "get_x(interceptor_obj)");
   6066     // Check that the interceptor was actually invoked.
   6067     CHECK_EQ(result, v8_str("x"));
   6068   }
   6069 
   6070   // Return to the original context and force some object to the slow case
   6071   // to cause the NormalizedMapCache to verify.
   6072   context1->Enter();
   6073   CompileRun("var obj = { x : 0 }; delete obj.x;");
   6074   context1->Exit();
   6075 }
   6076 
   6077 
   6078 static void SetXOnPrototypeGetter(
   6079     Local<String> property,
   6080     const v8::PropertyCallbackInfo<v8::Value>& info) {
   6081   // Set x on the prototype object and do not handle the get request.
   6082   v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
   6083   proto.As<v8::Object>()->Set(v8_str("x"),
   6084                               v8::Integer::New(info.GetIsolate(), 23));
   6085 }
   6086 
   6087 
   6088 // This is a regression test for http://crbug.com/20104. Map
   6089 // transitions should not interfere with post interceptor lookup.
   6090 THREADED_TEST(NamedInterceptorMapTransitionRead) {
   6091   v8::Isolate* isolate = CcTest::isolate();
   6092   v8::HandleScope scope(isolate);
   6093   Local<v8::FunctionTemplate> function_template =
   6094       v8::FunctionTemplate::New(isolate);
   6095   Local<v8::ObjectTemplate> instance_template
   6096       = function_template->InstanceTemplate();
   6097   instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
   6098   LocalContext context;
   6099   context->Global()->Set(v8_str("F"), function_template->GetFunction());
   6100   // Create an instance of F and introduce a map transition for x.
   6101   CompileRun("var o = new F(); o.x = 23;");
   6102   // Create an instance of F and invoke the getter. The result should be 23.
   6103   Local<Value> result = CompileRun("o = new F(); o.x");
   6104   CHECK_EQ(result->Int32Value(), 23);
   6105 }
   6106 
   6107 
   6108 static void IndexedPropertyGetter(
   6109     uint32_t index,
   6110     const v8::PropertyCallbackInfo<v8::Value>& info) {
   6111   ApiTestFuzzer::Fuzz();
   6112   if (index == 37) {
   6113     info.GetReturnValue().Set(v8_num(625));
   6114   }
   6115 }
   6116 
   6117 
   6118 static void IndexedPropertySetter(
   6119     uint32_t index,
   6120     Local<Value> value,
   6121     const v8::PropertyCallbackInfo<v8::Value>& info) {
   6122   ApiTestFuzzer::Fuzz();
   6123   if (index == 39) {
   6124     info.GetReturnValue().Set(value);
   6125   }
   6126 }
   6127 
   6128 
   6129 THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
   6130   v8::Isolate* isolate = CcTest::isolate();
   6131   v8::HandleScope scope(isolate);
   6132   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6133   templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
   6134                                    IndexedPropertySetter);
   6135   LocalContext context;
   6136   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   6137   Local<Script> getter_script = v8_compile(
   6138       "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];");
   6139   Local<Script> setter_script = v8_compile(
   6140       "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
   6141       "obj[17] = 23;"
   6142       "obj.foo;");
   6143   Local<Script> interceptor_setter_script = v8_compile(
   6144       "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
   6145       "obj[39] = 47;"
   6146       "obj.foo;");  // This setter should not run, due to the interceptor.
   6147   Local<Script> interceptor_getter_script = v8_compile(
   6148       "obj[37];");
   6149   Local<Value> result = getter_script->Run();
   6150   CHECK_EQ(v8_num(5), result);
   6151   result = setter_script->Run();
   6152   CHECK_EQ(v8_num(23), result);
   6153   result = interceptor_setter_script->Run();
   6154   CHECK_EQ(v8_num(23), result);
   6155   result = interceptor_getter_script->Run();
   6156   CHECK_EQ(v8_num(625), result);
   6157 }
   6158 
   6159 
   6160 static void UnboxedDoubleIndexedPropertyGetter(
   6161     uint32_t index,
   6162     const v8::PropertyCallbackInfo<v8::Value>& info) {
   6163   ApiTestFuzzer::Fuzz();
   6164   if (index < 25) {
   6165     info.GetReturnValue().Set(v8_num(index));
   6166   }
   6167 }
   6168 
   6169 
   6170 static void UnboxedDoubleIndexedPropertySetter(
   6171     uint32_t index,
   6172     Local<Value> value,
   6173     const v8::PropertyCallbackInfo<v8::Value>& info) {
   6174   ApiTestFuzzer::Fuzz();
   6175   if (index < 25) {
   6176     info.GetReturnValue().Set(v8_num(index));
   6177   }
   6178 }
   6179 
   6180 
   6181 void UnboxedDoubleIndexedPropertyEnumerator(
   6182     const v8::PropertyCallbackInfo<v8::Array>& info) {
   6183   // Force the list of returned keys to be stored in a FastDoubleArray.
   6184   Local<Script> indexed_property_names_script = v8_compile(
   6185       "keys = new Array(); keys[125000] = 1;"
   6186       "for(i = 0; i < 80000; i++) { keys[i] = i; };"
   6187       "keys.length = 25; keys;");
   6188   Local<Value> result = indexed_property_names_script->Run();
   6189   info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
   6190 }
   6191 
   6192 
   6193 // Make sure that the the interceptor code in the runtime properly handles
   6194 // merging property name lists for double-array-backed arrays.
   6195 THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
   6196   v8::Isolate* isolate = CcTest::isolate();
   6197   v8::HandleScope scope(isolate);
   6198   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6199   templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
   6200                                    UnboxedDoubleIndexedPropertySetter,
   6201                                    0,
   6202                                    0,
   6203                                    UnboxedDoubleIndexedPropertyEnumerator);
   6204   LocalContext context;
   6205   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   6206   // When obj is created, force it to be Stored in a FastDoubleArray.
   6207   Local<Script> create_unboxed_double_script = v8_compile(
   6208       "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
   6209       "key_count = 0; "
   6210       "for (x in obj) {key_count++;};"
   6211       "obj;");
   6212   Local<Value> result = create_unboxed_double_script->Run();
   6213   CHECK(result->ToObject()->HasRealIndexedProperty(2000));
   6214   Local<Script> key_count_check = v8_compile("key_count;");
   6215   result = key_count_check->Run();
   6216   CHECK_EQ(v8_num(40013), result);
   6217 }
   6218 
   6219 
   6220 void SloppyArgsIndexedPropertyEnumerator(
   6221     const v8::PropertyCallbackInfo<v8::Array>& info) {
   6222   // Force the list of returned keys to be stored in a Arguments object.
   6223   Local<Script> indexed_property_names_script = v8_compile(
   6224       "function f(w,x) {"
   6225       " return arguments;"
   6226       "}"
   6227       "keys = f(0, 1, 2, 3);"
   6228       "keys;");
   6229   Local<Object> result =
   6230       Local<Object>::Cast(indexed_property_names_script->Run());
   6231   // Have to populate the handle manually, as it's not Cast-able.
   6232   i::Handle<i::JSObject> o =
   6233       v8::Utils::OpenHandle<Object, i::JSObject>(result);
   6234   i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
   6235   info.GetReturnValue().Set(v8::Utils::ToLocal(array));
   6236 }
   6237 
   6238 
   6239 static void SloppyIndexedPropertyGetter(
   6240     uint32_t index,
   6241     const v8::PropertyCallbackInfo<v8::Value>& info) {
   6242   ApiTestFuzzer::Fuzz();
   6243   if (index < 4) {
   6244     info.GetReturnValue().Set(v8_num(index));
   6245   }
   6246 }
   6247 
   6248 
   6249 // Make sure that the the interceptor code in the runtime properly handles
   6250 // merging property name lists for non-string arguments arrays.
   6251 THREADED_TEST(IndexedInterceptorSloppyArgsWithIndexedAccessor) {
   6252   v8::Isolate* isolate = CcTest::isolate();
   6253   v8::HandleScope scope(isolate);
   6254   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6255   templ->SetIndexedPropertyHandler(SloppyIndexedPropertyGetter,
   6256                                    0,
   6257                                    0,
   6258                                    0,
   6259                                    SloppyArgsIndexedPropertyEnumerator);
   6260   LocalContext context;
   6261   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   6262   Local<Script> create_args_script = v8_compile(
   6263       "var key_count = 0;"
   6264       "for (x in obj) {key_count++;} key_count;");
   6265   Local<Value> result = create_args_script->Run();
   6266   CHECK_EQ(v8_num(4), result);
   6267 }
   6268 
   6269 
   6270 static void IdentityIndexedPropertyGetter(
   6271     uint32_t index,
   6272     const v8::PropertyCallbackInfo<v8::Value>& info) {
   6273   info.GetReturnValue().Set(index);
   6274 }
   6275 
   6276 
   6277 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
   6278   v8::Isolate* isolate = CcTest::isolate();
   6279   v8::HandleScope scope(isolate);
   6280   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6281   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6282 
   6283   LocalContext context;
   6284   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   6285 
   6286   // Check fast object case.
   6287   const char* fast_case_code =
   6288       "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
   6289   ExpectString(fast_case_code, "0");
   6290 
   6291   // Check slow case.
   6292   const char* slow_case_code =
   6293       "obj.x = 1; delete obj.x;"
   6294       "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
   6295   ExpectString(slow_case_code, "1");
   6296 }
   6297 
   6298 
   6299 THREADED_TEST(IndexedInterceptorWithNoSetter) {
   6300   v8::Isolate* isolate = CcTest::isolate();
   6301   v8::HandleScope scope(isolate);
   6302   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6303   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6304 
   6305   LocalContext context;
   6306   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   6307 
   6308   const char* code =
   6309       "try {"
   6310       "  obj[0] = 239;"
   6311       "  for (var i = 0; i < 100; i++) {"
   6312       "    var v = obj[0];"
   6313       "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6314       "  }"
   6315       "  'PASSED'"
   6316       "} catch(e) {"
   6317       "  e"
   6318       "}";
   6319   ExpectString(code, "PASSED");
   6320 }
   6321 
   6322 
   6323 THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
   6324   v8::Isolate* isolate = CcTest::isolate();
   6325   v8::HandleScope scope(isolate);
   6326   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6327   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6328 
   6329   LocalContext context;
   6330   Local<v8::Object> obj = templ->NewInstance();
   6331   obj->TurnOnAccessCheck();
   6332   context->Global()->Set(v8_str("obj"), obj);
   6333 
   6334   const char* code =
   6335       "var result = 'PASSED';"
   6336       "for (var i = 0; i < 100; i++) {"
   6337       "  try {"
   6338       "    var v = obj[0];"
   6339       "    result = 'Wrong value ' + v + ' at iteration ' + i;"
   6340       "    break;"
   6341       "  } catch (e) {"
   6342       "    /* pass */"
   6343       "  }"
   6344       "}"
   6345       "result";
   6346   ExpectString(code, "PASSED");
   6347 }
   6348 
   6349 
   6350 THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
   6351   i::FLAG_allow_natives_syntax = true;
   6352   v8::Isolate* isolate = CcTest::isolate();
   6353   v8::HandleScope scope(isolate);
   6354   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6355   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6356 
   6357   LocalContext context;
   6358   Local<v8::Object> obj = templ->NewInstance();
   6359   context->Global()->Set(v8_str("obj"), obj);
   6360 
   6361   const char* code =
   6362       "var result = 'PASSED';"
   6363       "for (var i = 0; i < 100; i++) {"
   6364       "  var expected = i;"
   6365       "  if (i == 5) {"
   6366       "    %EnableAccessChecks(obj);"
   6367       "  }"
   6368       "  try {"
   6369       "    var v = obj[i];"
   6370       "    if (i == 5) {"
   6371       "      result = 'Should not have reached this!';"
   6372       "      break;"
   6373       "    } else if (v != expected) {"
   6374       "      result = 'Wrong value ' + v + ' at iteration ' + i;"
   6375       "      break;"
   6376       "    }"
   6377       "  } catch (e) {"
   6378       "    if (i != 5) {"
   6379       "      result = e;"
   6380       "    }"
   6381       "  }"
   6382       "  if (i == 5) %DisableAccessChecks(obj);"
   6383       "}"
   6384       "result";
   6385   ExpectString(code, "PASSED");
   6386 }
   6387 
   6388 
   6389 THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
   6390   v8::Isolate* isolate = CcTest::isolate();
   6391   v8::HandleScope scope(isolate);
   6392   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6393   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6394 
   6395   LocalContext context;
   6396   Local<v8::Object> obj = templ->NewInstance();
   6397   context->Global()->Set(v8_str("obj"), obj);
   6398 
   6399   const char* code =
   6400       "try {"
   6401       "  for (var i = 0; i < 100; i++) {"
   6402       "    var v = obj[i];"
   6403       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6404       "  }"
   6405       "  'PASSED'"
   6406       "} catch(e) {"
   6407       "  e"
   6408       "}";
   6409   ExpectString(code, "PASSED");
   6410 }
   6411 
   6412 
   6413 THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
   6414   v8::Isolate* isolate = CcTest::isolate();
   6415   v8::HandleScope scope(isolate);
   6416   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6417   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6418 
   6419   LocalContext context;
   6420   Local<v8::Object> obj = templ->NewInstance();
   6421   context->Global()->Set(v8_str("obj"), obj);
   6422 
   6423   const char* code =
   6424       "try {"
   6425       "  for (var i = 0; i < 100; i++) {"
   6426       "    var expected = i;"
   6427       "    var key = i;"
   6428       "    if (i == 25) {"
   6429       "       key = -1;"
   6430       "       expected = undefined;"
   6431       "    }"
   6432       "    if (i == 50) {"
   6433       "       /* probe minimal Smi number on 32-bit platforms */"
   6434       "       key = -(1 << 30);"
   6435       "       expected = undefined;"
   6436       "    }"
   6437       "    if (i == 75) {"
   6438       "       /* probe minimal Smi number on 64-bit platforms */"
   6439       "       key = 1 << 31;"
   6440       "       expected = undefined;"
   6441       "    }"
   6442       "    var v = obj[key];"
   6443       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6444       "  }"
   6445       "  'PASSED'"
   6446       "} catch(e) {"
   6447       "  e"
   6448       "}";
   6449   ExpectString(code, "PASSED");
   6450 }
   6451 
   6452 
   6453 THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
   6454   v8::Isolate* isolate = CcTest::isolate();
   6455   v8::HandleScope scope(isolate);
   6456   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6457   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6458 
   6459   LocalContext context;
   6460   Local<v8::Object> obj = templ->NewInstance();
   6461   context->Global()->Set(v8_str("obj"), obj);
   6462 
   6463   const char* code =
   6464       "try {"
   6465       "  for (var i = 0; i < 100; i++) {"
   6466       "    var expected = i;"
   6467       "    var key = i;"
   6468       "    if (i == 50) {"
   6469       "       key = 'foobar';"
   6470       "       expected = undefined;"
   6471       "    }"
   6472       "    var v = obj[key];"
   6473       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6474       "  }"
   6475       "  'PASSED'"
   6476       "} catch(e) {"
   6477       "  e"
   6478       "}";
   6479   ExpectString(code, "PASSED");
   6480 }
   6481 
   6482 
   6483 THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
   6484   v8::Isolate* isolate = CcTest::isolate();
   6485   v8::HandleScope scope(isolate);
   6486   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6487   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6488 
   6489   LocalContext context;
   6490   Local<v8::Object> obj = templ->NewInstance();
   6491   context->Global()->Set(v8_str("obj"), obj);
   6492 
   6493   const char* code =
   6494       "var original = obj;"
   6495       "try {"
   6496       "  for (var i = 0; i < 100; i++) {"
   6497       "    var expected = i;"
   6498       "    if (i == 50) {"
   6499       "       obj = {50: 'foobar'};"
   6500       "       expected = 'foobar';"
   6501       "    }"
   6502       "    var v = obj[i];"
   6503       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6504       "    if (i == 50) obj = original;"
   6505       "  }"
   6506       "  'PASSED'"
   6507       "} catch(e) {"
   6508       "  e"
   6509       "}";
   6510   ExpectString(code, "PASSED");
   6511 }
   6512 
   6513 
   6514 THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
   6515   v8::Isolate* isolate = CcTest::isolate();
   6516   v8::HandleScope scope(isolate);
   6517   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6518   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6519 
   6520   LocalContext context;
   6521   Local<v8::Object> obj = templ->NewInstance();
   6522   context->Global()->Set(v8_str("obj"), obj);
   6523 
   6524   const char* code =
   6525       "var original = obj;"
   6526       "try {"
   6527       "  for (var i = 0; i < 100; i++) {"
   6528       "    var expected = i;"
   6529       "    if (i == 5) {"
   6530       "       obj = 239;"
   6531       "       expected = undefined;"
   6532       "    }"
   6533       "    var v = obj[i];"
   6534       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6535       "    if (i == 5) obj = original;"
   6536       "  }"
   6537       "  'PASSED'"
   6538       "} catch(e) {"
   6539       "  e"
   6540       "}";
   6541   ExpectString(code, "PASSED");
   6542 }
   6543 
   6544 
   6545 THREADED_TEST(IndexedInterceptorOnProto) {
   6546   v8::Isolate* isolate = CcTest::isolate();
   6547   v8::HandleScope scope(isolate);
   6548   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6549   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   6550 
   6551   LocalContext context;
   6552   Local<v8::Object> obj = templ->NewInstance();
   6553   context->Global()->Set(v8_str("obj"), obj);
   6554 
   6555   const char* code =
   6556       "var o = {__proto__: obj};"
   6557       "try {"
   6558       "  for (var i = 0; i < 100; i++) {"
   6559       "    var v = o[i];"
   6560       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   6561       "  }"
   6562       "  'PASSED'"
   6563       "} catch(e) {"
   6564       "  e"
   6565       "}";
   6566   ExpectString(code, "PASSED");
   6567 }
   6568 
   6569 
   6570 THREADED_TEST(MultiContexts) {
   6571   v8::Isolate* isolate = CcTest::isolate();
   6572   v8::HandleScope scope(isolate);
   6573   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6574   templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(isolate,
   6575                                                         DummyCallHandler));
   6576 
   6577   Local<String> password = v8_str("Password");
   6578 
   6579   // Create an environment
   6580   LocalContext context0(0, templ);
   6581   context0->SetSecurityToken(password);
   6582   v8::Handle<v8::Object> global0 = context0->Global();
   6583   global0->Set(v8_str("custom"), v8_num(1234));
   6584   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   6585 
   6586   // Create an independent environment
   6587   LocalContext context1(0, templ);
   6588   context1->SetSecurityToken(password);
   6589   v8::Handle<v8::Object> global1 = context1->Global();
   6590   global1->Set(v8_str("custom"), v8_num(1234));
   6591   CHECK_NE(global0, global1);
   6592   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   6593   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
   6594 
   6595   // Now create a new context with the old global
   6596   LocalContext context2(0, templ, global1);
   6597   context2->SetSecurityToken(password);
   6598   v8::Handle<v8::Object> global2 = context2->Global();
   6599   CHECK_EQ(global1, global2);
   6600   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
   6601   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
   6602 }
   6603 
   6604 
   6605 THREADED_TEST(FunctionPrototypeAcrossContexts) {
   6606   // Make sure that functions created by cloning boilerplates cannot
   6607   // communicate through their __proto__ field.
   6608 
   6609   v8::HandleScope scope(CcTest::isolate());
   6610 
   6611   LocalContext env0;
   6612   v8::Handle<v8::Object> global0 =
   6613       env0->Global();
   6614   v8::Handle<v8::Object> object0 =
   6615       global0->Get(v8_str("Object")).As<v8::Object>();
   6616   v8::Handle<v8::Object> tostring0 =
   6617       object0->Get(v8_str("toString")).As<v8::Object>();
   6618   v8::Handle<v8::Object> proto0 =
   6619       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
   6620   proto0->Set(v8_str("custom"), v8_num(1234));
   6621 
   6622   LocalContext env1;
   6623   v8::Handle<v8::Object> global1 =
   6624       env1->Global();
   6625   v8::Handle<v8::Object> object1 =
   6626       global1->Get(v8_str("Object")).As<v8::Object>();
   6627   v8::Handle<v8::Object> tostring1 =
   6628       object1->Get(v8_str("toString")).As<v8::Object>();
   6629   v8::Handle<v8::Object> proto1 =
   6630       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
   6631   CHECK(!proto1->Has(v8_str("custom")));
   6632 }
   6633 
   6634 
   6635 THREADED_TEST(Regress892105) {
   6636   // Make sure that object and array literals created by cloning
   6637   // boilerplates cannot communicate through their __proto__
   6638   // field. This is rather difficult to check, but we try to add stuff
   6639   // to Object.prototype and Array.prototype and create a new
   6640   // environment. This should succeed.
   6641 
   6642   v8::HandleScope scope(CcTest::isolate());
   6643 
   6644   Local<String> source = v8_str("Object.prototype.obj = 1234;"
   6645                                 "Array.prototype.arr = 4567;"
   6646                                 "8901");
   6647 
   6648   LocalContext env0;
   6649   Local<Script> script0 = v8_compile(source);
   6650   CHECK_EQ(8901.0, script0->Run()->NumberValue());
   6651 
   6652   LocalContext env1;
   6653   Local<Script> script1 = v8_compile(source);
   6654   CHECK_EQ(8901.0, script1->Run()->NumberValue());
   6655 }
   6656 
   6657 
   6658 THREADED_TEST(UndetectableObject) {
   6659   LocalContext env;
   6660   v8::HandleScope scope(env->GetIsolate());
   6661 
   6662   Local<v8::FunctionTemplate> desc =
   6663       v8::FunctionTemplate::New(env->GetIsolate());
   6664   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   6665 
   6666   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   6667   env->Global()->Set(v8_str("undetectable"), obj);
   6668 
   6669   ExpectString("undetectable.toString()", "[object Object]");
   6670   ExpectString("typeof undetectable", "undefined");
   6671   ExpectString("typeof(undetectable)", "undefined");
   6672   ExpectBoolean("typeof undetectable == 'undefined'", true);
   6673   ExpectBoolean("typeof undetectable == 'object'", false);
   6674   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   6675   ExpectBoolean("!undetectable", true);
   6676 
   6677   ExpectObject("true&&undetectable", obj);
   6678   ExpectBoolean("false&&undetectable", false);
   6679   ExpectBoolean("true||undetectable", true);
   6680   ExpectObject("false||undetectable", obj);
   6681 
   6682   ExpectObject("undetectable&&true", obj);
   6683   ExpectObject("undetectable&&false", obj);
   6684   ExpectBoolean("undetectable||true", true);
   6685   ExpectBoolean("undetectable||false", false);
   6686 
   6687   ExpectBoolean("undetectable==null", true);
   6688   ExpectBoolean("null==undetectable", true);
   6689   ExpectBoolean("undetectable==undefined", true);
   6690   ExpectBoolean("undefined==undetectable", true);
   6691   ExpectBoolean("undetectable==undetectable", true);
   6692 
   6693 
   6694   ExpectBoolean("undetectable===null", false);
   6695   ExpectBoolean("null===undetectable", false);
   6696   ExpectBoolean("undetectable===undefined", false);
   6697   ExpectBoolean("undefined===undetectable", false);
   6698   ExpectBoolean("undetectable===undetectable", true);
   6699 }
   6700 
   6701 
   6702 THREADED_TEST(VoidLiteral) {
   6703   LocalContext env;
   6704   v8::Isolate* isolate = env->GetIsolate();
   6705   v8::HandleScope scope(isolate);
   6706 
   6707   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   6708   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   6709 
   6710   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   6711   env->Global()->Set(v8_str("undetectable"), obj);
   6712 
   6713   ExpectBoolean("undefined == void 0", true);
   6714   ExpectBoolean("undetectable == void 0", true);
   6715   ExpectBoolean("null == void 0", true);
   6716   ExpectBoolean("undefined === void 0", true);
   6717   ExpectBoolean("undetectable === void 0", false);
   6718   ExpectBoolean("null === void 0", false);
   6719 
   6720   ExpectBoolean("void 0 == undefined", true);
   6721   ExpectBoolean("void 0 == undetectable", true);
   6722   ExpectBoolean("void 0 == null", true);
   6723   ExpectBoolean("void 0 === undefined", true);
   6724   ExpectBoolean("void 0 === undetectable", false);
   6725   ExpectBoolean("void 0 === null", false);
   6726 
   6727   ExpectString("(function() {"
   6728                "  try {"
   6729                "    return x === void 0;"
   6730                "  } catch(e) {"
   6731                "    return e.toString();"
   6732                "  }"
   6733                "})()",
   6734                "ReferenceError: x is not defined");
   6735   ExpectString("(function() {"
   6736                "  try {"
   6737                "    return void 0 === x;"
   6738                "  } catch(e) {"
   6739                "    return e.toString();"
   6740                "  }"
   6741                "})()",
   6742                "ReferenceError: x is not defined");
   6743 }
   6744 
   6745 
   6746 THREADED_TEST(ExtensibleOnUndetectable) {
   6747   LocalContext env;
   6748   v8::Isolate* isolate = env->GetIsolate();
   6749   v8::HandleScope scope(isolate);
   6750 
   6751   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   6752   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   6753 
   6754   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   6755   env->Global()->Set(v8_str("undetectable"), obj);
   6756 
   6757   Local<String> source = v8_str("undetectable.x = 42;"
   6758                                 "undetectable.x");
   6759 
   6760   Local<Script> script = v8_compile(source);
   6761 
   6762   CHECK_EQ(v8::Integer::New(isolate, 42), script->Run());
   6763 
   6764   ExpectBoolean("Object.isExtensible(undetectable)", true);
   6765 
   6766   source = v8_str("Object.preventExtensions(undetectable);");
   6767   script = v8_compile(source);
   6768   script->Run();
   6769   ExpectBoolean("Object.isExtensible(undetectable)", false);
   6770 
   6771   source = v8_str("undetectable.y = 2000;");
   6772   script = v8_compile(source);
   6773   script->Run();
   6774   ExpectBoolean("undetectable.y == undefined", true);
   6775 }
   6776 
   6777 
   6778 
   6779 THREADED_TEST(UndetectableString) {
   6780   LocalContext env;
   6781   v8::HandleScope scope(env->GetIsolate());
   6782 
   6783   Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
   6784                                           String::kUndetectableString);
   6785   env->Global()->Set(v8_str("undetectable"), obj);
   6786 
   6787   ExpectString("undetectable", "foo");
   6788   ExpectString("typeof undetectable", "undefined");
   6789   ExpectString("typeof(undetectable)", "undefined");
   6790   ExpectBoolean("typeof undetectable == 'undefined'", true);
   6791   ExpectBoolean("typeof undetectable == 'string'", false);
   6792   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   6793   ExpectBoolean("!undetectable", true);
   6794 
   6795   ExpectObject("true&&undetectable", obj);
   6796   ExpectBoolean("false&&undetectable", false);
   6797   ExpectBoolean("true||undetectable", true);
   6798   ExpectObject("false||undetectable", obj);
   6799 
   6800   ExpectObject("undetectable&&true", obj);
   6801   ExpectObject("undetectable&&false", obj);
   6802   ExpectBoolean("undetectable||true", true);
   6803   ExpectBoolean("undetectable||false", false);
   6804 
   6805   ExpectBoolean("undetectable==null", true);
   6806   ExpectBoolean("null==undetectable", true);
   6807   ExpectBoolean("undetectable==undefined", true);
   6808   ExpectBoolean("undefined==undetectable", true);
   6809   ExpectBoolean("undetectable==undetectable", true);
   6810 
   6811 
   6812   ExpectBoolean("undetectable===null", false);
   6813   ExpectBoolean("null===undetectable", false);
   6814   ExpectBoolean("undetectable===undefined", false);
   6815   ExpectBoolean("undefined===undetectable", false);
   6816   ExpectBoolean("undetectable===undetectable", true);
   6817 }
   6818 
   6819 
   6820 TEST(UndetectableOptimized) {
   6821   i::FLAG_allow_natives_syntax = true;
   6822   LocalContext env;
   6823   v8::HandleScope scope(env->GetIsolate());
   6824 
   6825   Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
   6826                                           String::kUndetectableString);
   6827   env->Global()->Set(v8_str("undetectable"), obj);
   6828   env->Global()->Set(v8_str("detectable"), v8_str("bar"));
   6829 
   6830   ExpectString(
   6831       "function testBranch() {"
   6832       "  if (!%_IsUndetectableObject(undetectable)) throw 1;"
   6833       "  if (%_IsUndetectableObject(detectable)) throw 2;"
   6834       "}\n"
   6835       "function testBool() {"
   6836       "  var b1 = !%_IsUndetectableObject(undetectable);"
   6837       "  var b2 = %_IsUndetectableObject(detectable);"
   6838       "  if (b1) throw 3;"
   6839       "  if (b2) throw 4;"
   6840       "  return b1 == b2;"
   6841       "}\n"
   6842       "%OptimizeFunctionOnNextCall(testBranch);"
   6843       "%OptimizeFunctionOnNextCall(testBool);"
   6844       "for (var i = 0; i < 10; i++) {"
   6845       "  testBranch();"
   6846       "  testBool();"
   6847       "}\n"
   6848       "\"PASS\"",
   6849       "PASS");
   6850 }
   6851 
   6852 
   6853 // The point of this test is type checking. We run it only so compilers
   6854 // don't complain about an unused function.
   6855 TEST(PersistentHandles) {
   6856   LocalContext env;
   6857   v8::Isolate* isolate = CcTest::isolate();
   6858   v8::HandleScope scope(isolate);
   6859   Local<String> str = v8_str("foo");
   6860   v8::Persistent<String> p_str(isolate, str);
   6861   p_str.Reset();
   6862   Local<Script> scr = v8_compile("");
   6863   v8::Persistent<Script> p_scr(isolate, scr);
   6864   p_scr.Reset();
   6865   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6866   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
   6867   p_templ.Reset();
   6868 }
   6869 
   6870 
   6871 static void HandleLogDelegator(
   6872     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6873   ApiTestFuzzer::Fuzz();
   6874 }
   6875 
   6876 
   6877 THREADED_TEST(GlobalObjectTemplate) {
   6878   v8::Isolate* isolate = CcTest::isolate();
   6879   v8::HandleScope handle_scope(isolate);
   6880   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   6881   global_template->Set(v8_str("JSNI_Log"),
   6882                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
   6883   v8::Local<Context> context = Context::New(isolate, 0, global_template);
   6884   Context::Scope context_scope(context);
   6885   CompileRun("JSNI_Log('LOG')");
   6886 }
   6887 
   6888 
   6889 static const char* kSimpleExtensionSource =
   6890   "function Foo() {"
   6891   "  return 4;"
   6892   "}";
   6893 
   6894 
   6895 TEST(SimpleExtensions) {
   6896   v8::HandleScope handle_scope(CcTest::isolate());
   6897   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
   6898   const char* extension_names[] = { "simpletest" };
   6899   v8::ExtensionConfiguration extensions(1, extension_names);
   6900   v8::Handle<Context> context =
   6901       Context::New(CcTest::isolate(), &extensions);
   6902   Context::Scope lock(context);
   6903   v8::Handle<Value> result = CompileRun("Foo()");
   6904   CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
   6905 }
   6906 
   6907 
   6908 static const char* kStackTraceFromExtensionSource =
   6909   "function foo() {"
   6910   "  throw new Error();"
   6911   "}"
   6912   "function bar() {"
   6913   "  foo();"
   6914   "}";
   6915 
   6916 
   6917 TEST(StackTraceInExtension) {
   6918   v8::HandleScope handle_scope(CcTest::isolate());
   6919   v8::RegisterExtension(new Extension("stacktracetest",
   6920                         kStackTraceFromExtensionSource));
   6921   const char* extension_names[] = { "stacktracetest" };
   6922   v8::ExtensionConfiguration extensions(1, extension_names);
   6923   v8::Handle<Context> context =
   6924       Context::New(CcTest::isolate(), &extensions);
   6925   Context::Scope lock(context);
   6926   CompileRun("function user() { bar(); }"
   6927              "var error;"
   6928              "try{ user(); } catch (e) { error = e; }");
   6929   CHECK_EQ(-1, CompileRun("error.stack.indexOf('foo')")->Int32Value());
   6930   CHECK_EQ(-1, CompileRun("error.stack.indexOf('bar')")->Int32Value());
   6931   CHECK_NE(-1, CompileRun("error.stack.indexOf('user')")->Int32Value());
   6932 }
   6933 
   6934 
   6935 TEST(NullExtensions) {
   6936   v8::HandleScope handle_scope(CcTest::isolate());
   6937   v8::RegisterExtension(new Extension("nulltest", NULL));
   6938   const char* extension_names[] = { "nulltest" };
   6939   v8::ExtensionConfiguration extensions(1, extension_names);
   6940   v8::Handle<Context> context =
   6941       Context::New(CcTest::isolate(), &extensions);
   6942   Context::Scope lock(context);
   6943   v8::Handle<Value> result = CompileRun("1+3");
   6944   CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
   6945 }
   6946 
   6947 
   6948 static const char* kEmbeddedExtensionSource =
   6949     "function Ret54321(){return 54321;}~~@@$"
   6950     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
   6951 static const int kEmbeddedExtensionSourceValidLen = 34;
   6952 
   6953 
   6954 TEST(ExtensionMissingSourceLength) {
   6955   v8::HandleScope handle_scope(CcTest::isolate());
   6956   v8::RegisterExtension(new Extension("srclentest_fail",
   6957                                       kEmbeddedExtensionSource));
   6958   const char* extension_names[] = { "srclentest_fail" };
   6959   v8::ExtensionConfiguration extensions(1, extension_names);
   6960   v8::Handle<Context> context =
   6961       Context::New(CcTest::isolate(), &extensions);
   6962   CHECK_EQ(0, *context);
   6963 }
   6964 
   6965 
   6966 TEST(ExtensionWithSourceLength) {
   6967   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
   6968        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
   6969     v8::HandleScope handle_scope(CcTest::isolate());
   6970     i::ScopedVector<char> extension_name(32);
   6971     i::SNPrintF(extension_name, "ext #%d", source_len);
   6972     v8::RegisterExtension(new Extension(extension_name.start(),
   6973                                         kEmbeddedExtensionSource, 0, 0,
   6974                                         source_len));
   6975     const char* extension_names[1] = { extension_name.start() };
   6976     v8::ExtensionConfiguration extensions(1, extension_names);
   6977     v8::Handle<Context> context =
   6978       Context::New(CcTest::isolate(), &extensions);
   6979     if (source_len == kEmbeddedExtensionSourceValidLen) {
   6980       Context::Scope lock(context);
   6981       v8::Handle<Value> result = CompileRun("Ret54321()");
   6982       CHECK_EQ(v8::Integer::New(CcTest::isolate(), 54321), result);
   6983     } else {
   6984       // Anything but exactly the right length should fail to compile.
   6985       CHECK_EQ(0, *context);
   6986     }
   6987   }
   6988 }
   6989 
   6990 
   6991 static const char* kEvalExtensionSource1 =
   6992   "function UseEval1() {"
   6993   "  var x = 42;"
   6994   "  return eval('x');"
   6995   "}";
   6996 
   6997 
   6998 static const char* kEvalExtensionSource2 =
   6999   "(function() {"
   7000   "  var x = 42;"
   7001   "  function e() {"
   7002   "    return eval('x');"
   7003   "  }"
   7004   "  this.UseEval2 = e;"
   7005   "})()";
   7006 
   7007 
   7008 TEST(UseEvalFromExtension) {
   7009   v8::HandleScope handle_scope(CcTest::isolate());
   7010   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
   7011   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
   7012   const char* extension_names[] = { "evaltest1", "evaltest2" };
   7013   v8::ExtensionConfiguration extensions(2, extension_names);
   7014   v8::Handle<Context> context =
   7015       Context::New(CcTest::isolate(), &extensions);
   7016   Context::Scope lock(context);
   7017   v8::Handle<Value> result = CompileRun("UseEval1()");
   7018   CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
   7019   result = CompileRun("UseEval2()");
   7020   CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
   7021 }
   7022 
   7023 
   7024 static const char* kWithExtensionSource1 =
   7025   "function UseWith1() {"
   7026   "  var x = 42;"
   7027   "  with({x:87}) { return x; }"
   7028   "}";
   7029 
   7030 
   7031 
   7032 static const char* kWithExtensionSource2 =
   7033   "(function() {"
   7034   "  var x = 42;"
   7035   "  function e() {"
   7036   "    with ({x:87}) { return x; }"
   7037   "  }"
   7038   "  this.UseWith2 = e;"
   7039   "})()";
   7040 
   7041 
   7042 TEST(UseWithFromExtension) {
   7043   v8::HandleScope handle_scope(CcTest::isolate());
   7044   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
   7045   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
   7046   const char* extension_names[] = { "withtest1", "withtest2" };
   7047   v8::ExtensionConfiguration extensions(2, extension_names);
   7048   v8::Handle<Context> context =
   7049       Context::New(CcTest::isolate(), &extensions);
   7050   Context::Scope lock(context);
   7051   v8::Handle<Value> result = CompileRun("UseWith1()");
   7052   CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
   7053   result = CompileRun("UseWith2()");
   7054   CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
   7055 }
   7056 
   7057 
   7058 TEST(AutoExtensions) {
   7059   v8::HandleScope handle_scope(CcTest::isolate());
   7060   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
   7061   extension->set_auto_enable(true);
   7062   v8::RegisterExtension(extension);
   7063   v8::Handle<Context> context =
   7064       Context::New(CcTest::isolate());
   7065   Context::Scope lock(context);
   7066   v8::Handle<Value> result = CompileRun("Foo()");
   7067   CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
   7068 }
   7069 
   7070 
   7071 static const char* kSyntaxErrorInExtensionSource =
   7072     "[";
   7073 
   7074 
   7075 // Test that a syntax error in an extension does not cause a fatal
   7076 // error but results in an empty context.
   7077 TEST(SyntaxErrorExtensions) {
   7078   v8::HandleScope handle_scope(CcTest::isolate());
   7079   v8::RegisterExtension(new Extension("syntaxerror",
   7080                                       kSyntaxErrorInExtensionSource));
   7081   const char* extension_names[] = { "syntaxerror" };
   7082   v8::ExtensionConfiguration extensions(1, extension_names);
   7083   v8::Handle<Context> context =
   7084       Context::New(CcTest::isolate(), &extensions);
   7085   CHECK(context.IsEmpty());
   7086 }
   7087 
   7088 
   7089 static const char* kExceptionInExtensionSource =
   7090     "throw 42";
   7091 
   7092 
   7093 // Test that an exception when installing an extension does not cause
   7094 // a fatal error but results in an empty context.
   7095 TEST(ExceptionExtensions) {
   7096   v8::HandleScope handle_scope(CcTest::isolate());
   7097   v8::RegisterExtension(new Extension("exception",
   7098                                       kExceptionInExtensionSource));
   7099   const char* extension_names[] = { "exception" };
   7100   v8::ExtensionConfiguration extensions(1, extension_names);
   7101   v8::Handle<Context> context =
   7102       Context::New(CcTest::isolate(), &extensions);
   7103   CHECK(context.IsEmpty());
   7104 }
   7105 
   7106 
   7107 static const char* kNativeCallInExtensionSource =
   7108     "function call_runtime_last_index_of(x) {"
   7109     "  return %StringLastIndexOf(x, 'bob', 10);"
   7110     "}";
   7111 
   7112 
   7113 static const char* kNativeCallTest =
   7114     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
   7115 
   7116 // Test that a native runtime calls are supported in extensions.
   7117 TEST(NativeCallInExtensions) {
   7118   v8::HandleScope handle_scope(CcTest::isolate());
   7119   v8::RegisterExtension(new Extension("nativecall",
   7120                                       kNativeCallInExtensionSource));
   7121   const char* extension_names[] = { "nativecall" };
   7122   v8::ExtensionConfiguration extensions(1, extension_names);
   7123   v8::Handle<Context> context =
   7124       Context::New(CcTest::isolate(), &extensions);
   7125   Context::Scope lock(context);
   7126   v8::Handle<Value> result = CompileRun(kNativeCallTest);
   7127   CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 3));
   7128 }
   7129 
   7130 
   7131 class NativeFunctionExtension : public Extension {
   7132  public:
   7133   NativeFunctionExtension(const char* name,
   7134                           const char* source,
   7135                           v8::FunctionCallback fun = &Echo)
   7136       : Extension(name, source),
   7137         function_(fun) { }
   7138 
   7139   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
   7140       v8::Isolate* isolate,
   7141       v8::Handle<v8::String> name) {
   7142     return v8::FunctionTemplate::New(isolate, function_);
   7143   }
   7144 
   7145   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
   7146     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
   7147   }
   7148  private:
   7149   v8::FunctionCallback function_;
   7150 };
   7151 
   7152 
   7153 TEST(NativeFunctionDeclaration) {
   7154   v8::HandleScope handle_scope(CcTest::isolate());
   7155   const char* name = "nativedecl";
   7156   v8::RegisterExtension(new NativeFunctionExtension(name,
   7157                                                     "native function foo();"));
   7158   const char* extension_names[] = { name };
   7159   v8::ExtensionConfiguration extensions(1, extension_names);
   7160   v8::Handle<Context> context =
   7161       Context::New(CcTest::isolate(), &extensions);
   7162   Context::Scope lock(context);
   7163   v8::Handle<Value> result = CompileRun("foo(42);");
   7164   CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
   7165 }
   7166 
   7167 
   7168 TEST(NativeFunctionDeclarationError) {
   7169   v8::HandleScope handle_scope(CcTest::isolate());
   7170   const char* name = "nativedeclerr";
   7171   // Syntax error in extension code.
   7172   v8::RegisterExtension(new NativeFunctionExtension(name,
   7173                                                     "native\nfunction foo();"));
   7174   const char* extension_names[] = { name };
   7175   v8::ExtensionConfiguration extensions(1, extension_names);
   7176   v8::Handle<Context> context =
   7177       Context::New(CcTest::isolate(), &extensions);
   7178   CHECK(context.IsEmpty());
   7179 }
   7180 
   7181 
   7182 TEST(NativeFunctionDeclarationErrorEscape) {
   7183   v8::HandleScope handle_scope(CcTest::isolate());
   7184   const char* name = "nativedeclerresc";
   7185   // Syntax error in extension code - escape code in "native" means that
   7186   // it's not treated as a keyword.
   7187   v8::RegisterExtension(new NativeFunctionExtension(
   7188       name,
   7189       "nativ\\u0065 function foo();"));
   7190   const char* extension_names[] = { name };
   7191   v8::ExtensionConfiguration extensions(1, extension_names);
   7192   v8::Handle<Context> context =
   7193       Context::New(CcTest::isolate(), &extensions);
   7194   CHECK(context.IsEmpty());
   7195 }
   7196 
   7197 
   7198 static void CheckDependencies(const char* name, const char* expected) {
   7199   v8::HandleScope handle_scope(CcTest::isolate());
   7200   v8::ExtensionConfiguration config(1, &name);
   7201   LocalContext context(&config);
   7202   CHECK_EQ(String::NewFromUtf8(CcTest::isolate(), expected),
   7203            context->Global()->Get(v8_str("loaded")));
   7204 }
   7205 
   7206 
   7207 /*
   7208  * Configuration:
   7209  *
   7210  *     /-- B <--\
   7211  * A <-          -- D <-- E
   7212  *     \-- C <--/
   7213  */
   7214 THREADED_TEST(ExtensionDependency) {
   7215   static const char* kEDeps[] = { "D" };
   7216   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
   7217   static const char* kDDeps[] = { "B", "C" };
   7218   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
   7219   static const char* kBCDeps[] = { "A" };
   7220   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
   7221   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
   7222   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
   7223   CheckDependencies("A", "undefinedA");
   7224   CheckDependencies("B", "undefinedAB");
   7225   CheckDependencies("C", "undefinedAC");
   7226   CheckDependencies("D", "undefinedABCD");
   7227   CheckDependencies("E", "undefinedABCDE");
   7228   v8::HandleScope handle_scope(CcTest::isolate());
   7229   static const char* exts[2] = { "C", "E" };
   7230   v8::ExtensionConfiguration config(2, exts);
   7231   LocalContext context(&config);
   7232   CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
   7233 }
   7234 
   7235 
   7236 static const char* kExtensionTestScript =
   7237   "native function A();"
   7238   "native function B();"
   7239   "native function C();"
   7240   "function Foo(i) {"
   7241   "  if (i == 0) return A();"
   7242   "  if (i == 1) return B();"
   7243   "  if (i == 2) return C();"
   7244   "}";
   7245 
   7246 
   7247 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
   7248   ApiTestFuzzer::Fuzz();
   7249   if (args.IsConstructCall()) {
   7250     args.This()->Set(v8_str("data"), args.Data());
   7251     args.GetReturnValue().SetNull();
   7252     return;
   7253   }
   7254   args.GetReturnValue().Set(args.Data());
   7255 }
   7256 
   7257 
   7258 class FunctionExtension : public Extension {
   7259  public:
   7260   FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
   7261   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
   7262       v8::Isolate* isolate,
   7263       v8::Handle<String> name);
   7264 };
   7265 
   7266 
   7267 static int lookup_count = 0;
   7268 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
   7269     v8::Isolate* isolate, v8::Handle<String> name) {
   7270   lookup_count++;
   7271   if (name->Equals(v8_str("A"))) {
   7272     return v8::FunctionTemplate::New(
   7273         isolate, CallFun, v8::Integer::New(isolate, 8));
   7274   } else if (name->Equals(v8_str("B"))) {
   7275     return v8::FunctionTemplate::New(
   7276         isolate, CallFun, v8::Integer::New(isolate, 7));
   7277   } else if (name->Equals(v8_str("C"))) {
   7278     return v8::FunctionTemplate::New(
   7279         isolate, CallFun, v8::Integer::New(isolate, 6));
   7280   } else {
   7281     return v8::Handle<v8::FunctionTemplate>();
   7282   }
   7283 }
   7284 
   7285 
   7286 THREADED_TEST(FunctionLookup) {
   7287   v8::RegisterExtension(new FunctionExtension());
   7288   v8::HandleScope handle_scope(CcTest::isolate());
   7289   static const char* exts[1] = { "functiontest" };
   7290   v8::ExtensionConfiguration config(1, exts);
   7291   LocalContext context(&config);
   7292   CHECK_EQ(3, lookup_count);
   7293   CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
   7294            CompileRun("Foo(0)"));
   7295   CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
   7296            CompileRun("Foo(1)"));
   7297   CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
   7298            CompileRun("Foo(2)"));
   7299 }
   7300 
   7301 
   7302 THREADED_TEST(NativeFunctionConstructCall) {
   7303   v8::RegisterExtension(new FunctionExtension());
   7304   v8::HandleScope handle_scope(CcTest::isolate());
   7305   static const char* exts[1] = { "functiontest" };
   7306   v8::ExtensionConfiguration config(1, exts);
   7307   LocalContext context(&config);
   7308   for (int i = 0; i < 10; i++) {
   7309     // Run a few times to ensure that allocation of objects doesn't
   7310     // change behavior of a constructor function.
   7311     CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
   7312              CompileRun("(new A()).data"));
   7313     CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
   7314              CompileRun("(new B()).data"));
   7315     CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
   7316              CompileRun("(new C()).data"));
   7317   }
   7318 }
   7319 
   7320 
   7321 static const char* last_location;
   7322 static const char* last_message;
   7323 void StoringErrorCallback(const char* location, const char* message) {
   7324   if (last_location == NULL) {
   7325     last_location = location;
   7326     last_message = message;
   7327   }
   7328 }
   7329 
   7330 
   7331 // ErrorReporting creates a circular extensions configuration and
   7332 // tests that the fatal error handler gets called.  This renders V8
   7333 // unusable and therefore this test cannot be run in parallel.
   7334 TEST(ErrorReporting) {
   7335   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   7336   static const char* aDeps[] = { "B" };
   7337   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
   7338   static const char* bDeps[] = { "A" };
   7339   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
   7340   last_location = NULL;
   7341   v8::ExtensionConfiguration config(1, bDeps);
   7342   v8::Handle<Context> context =
   7343       Context::New(CcTest::isolate(), &config);
   7344   CHECK(context.IsEmpty());
   7345   CHECK_NE(last_location, NULL);
   7346 }
   7347 
   7348 
   7349 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
   7350                                              v8::Handle<Value> data) {
   7351   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
   7352   CHECK_EQ(v8::Undefined(CcTest::isolate()),
   7353       message->GetScriptOrigin().ResourceName());
   7354   message->GetLineNumber();
   7355   message->GetSourceLine();
   7356 }
   7357 
   7358 
   7359 THREADED_TEST(ErrorWithMissingScriptInfo) {
   7360   LocalContext context;
   7361   v8::HandleScope scope(context->GetIsolate());
   7362   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
   7363   CompileRun("throw Error()");
   7364   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
   7365 }
   7366 
   7367 
   7368 struct FlagAndPersistent {
   7369   bool flag;
   7370   v8::Persistent<v8::Object> handle;
   7371 };
   7372 
   7373 
   7374 static void DisposeAndSetFlag(
   7375     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
   7376   data.GetParameter()->handle.Reset();
   7377   data.GetParameter()->flag = true;
   7378 }
   7379 
   7380 
   7381 THREADED_TEST(IndependentWeakHandle) {
   7382   v8::Isolate* iso = CcTest::isolate();
   7383   v8::HandleScope scope(iso);
   7384   v8::Handle<Context> context = Context::New(iso);
   7385   Context::Scope context_scope(context);
   7386 
   7387   FlagAndPersistent object_a, object_b;
   7388 
   7389   {
   7390     v8::HandleScope handle_scope(iso);
   7391     object_a.handle.Reset(iso, v8::Object::New(iso));
   7392     object_b.handle.Reset(iso, v8::Object::New(iso));
   7393   }
   7394 
   7395   object_a.flag = false;
   7396   object_b.flag = false;
   7397   object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag);
   7398   object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag);
   7399   CHECK(!object_b.handle.IsIndependent());
   7400   object_a.handle.MarkIndependent();
   7401   object_b.handle.MarkIndependent();
   7402   CHECK(object_b.handle.IsIndependent());
   7403   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7404   CHECK(object_a.flag);
   7405   CHECK(object_b.flag);
   7406 }
   7407 
   7408 
   7409 static void InvokeScavenge() {
   7410   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7411 }
   7412 
   7413 
   7414 static void InvokeMarkSweep() {
   7415   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   7416 }
   7417 
   7418 
   7419 static void ForceScavenge(
   7420     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
   7421   data.GetParameter()->handle.Reset();
   7422   data.GetParameter()->flag = true;
   7423   InvokeScavenge();
   7424 }
   7425 
   7426 
   7427 static void ForceMarkSweep(
   7428     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
   7429   data.GetParameter()->handle.Reset();
   7430   data.GetParameter()->flag = true;
   7431   InvokeMarkSweep();
   7432 }
   7433 
   7434 
   7435 THREADED_TEST(GCFromWeakCallbacks) {
   7436   v8::Isolate* isolate = CcTest::isolate();
   7437   v8::HandleScope scope(isolate);
   7438   v8::Handle<Context> context = Context::New(isolate);
   7439   Context::Scope context_scope(context);
   7440 
   7441   static const int kNumberOfGCTypes = 2;
   7442   typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
   7443       Callback;
   7444   Callback gc_forcing_callback[kNumberOfGCTypes] =
   7445       {&ForceScavenge, &ForceMarkSweep};
   7446 
   7447   typedef void (*GCInvoker)();
   7448   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
   7449 
   7450   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
   7451     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
   7452       FlagAndPersistent object;
   7453       {
   7454         v8::HandleScope handle_scope(isolate);
   7455         object.handle.Reset(isolate, v8::Object::New(isolate));
   7456       }
   7457       object.flag = false;
   7458       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
   7459       object.handle.MarkIndependent();
   7460       invoke_gc[outer_gc]();
   7461       CHECK(object.flag);
   7462     }
   7463   }
   7464 }
   7465 
   7466 
   7467 static void RevivingCallback(
   7468     const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
   7469   data.GetParameter()->handle.ClearWeak();
   7470   data.GetParameter()->flag = true;
   7471 }
   7472 
   7473 
   7474 THREADED_TEST(IndependentHandleRevival) {
   7475   v8::Isolate* isolate = CcTest::isolate();
   7476   v8::HandleScope scope(isolate);
   7477   v8::Handle<Context> context = Context::New(isolate);
   7478   Context::Scope context_scope(context);
   7479 
   7480   FlagAndPersistent object;
   7481   {
   7482     v8::HandleScope handle_scope(isolate);
   7483     v8::Local<v8::Object> o = v8::Object::New(isolate);
   7484     object.handle.Reset(isolate, o);
   7485     o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
   7486     v8::Local<String> y_str = v8_str("y");
   7487     o->Set(y_str, y_str);
   7488   }
   7489   object.flag = false;
   7490   object.handle.SetWeak(&object, &RevivingCallback);
   7491   object.handle.MarkIndependent();
   7492   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7493   CHECK(object.flag);
   7494   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   7495   {
   7496     v8::HandleScope handle_scope(isolate);
   7497     v8::Local<v8::Object> o =
   7498         v8::Local<v8::Object>::New(isolate, object.handle);
   7499     v8::Local<String> y_str = v8_str("y");
   7500     CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x")));
   7501     CHECK(o->Get(y_str)->Equals(y_str));
   7502   }
   7503 }
   7504 
   7505 
   7506 v8::Handle<Function> args_fun;
   7507 
   7508 
   7509 static void ArgumentsTestCallback(
   7510     const v8::FunctionCallbackInfo<v8::Value>& args) {
   7511   ApiTestFuzzer::Fuzz();
   7512   v8::Isolate* isolate = args.GetIsolate();
   7513   CHECK_EQ(args_fun, args.Callee());
   7514   CHECK_EQ(3, args.Length());
   7515   CHECK_EQ(v8::Integer::New(isolate, 1), args[0]);
   7516   CHECK_EQ(v8::Integer::New(isolate, 2), args[1]);
   7517   CHECK_EQ(v8::Integer::New(isolate, 3), args[2]);
   7518   CHECK_EQ(v8::Undefined(isolate), args[3]);
   7519   v8::HandleScope scope(args.GetIsolate());
   7520   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   7521 }
   7522 
   7523 
   7524 THREADED_TEST(Arguments) {
   7525   v8::Isolate* isolate = CcTest::isolate();
   7526   v8::HandleScope scope(isolate);
   7527   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
   7528   global->Set(v8_str("f"),
   7529               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
   7530   LocalContext context(NULL, global);
   7531   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
   7532   v8_compile("f(1, 2, 3)")->Run();
   7533 }
   7534 
   7535 
   7536 static void NoBlockGetterX(Local<String> name,
   7537                            const v8::PropertyCallbackInfo<v8::Value>&) {
   7538 }
   7539 
   7540 
   7541 static void NoBlockGetterI(uint32_t index,
   7542                            const v8::PropertyCallbackInfo<v8::Value>&) {
   7543 }
   7544 
   7545 
   7546 static void PDeleter(Local<String> name,
   7547                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   7548   if (!name->Equals(v8_str("foo"))) {
   7549     return;  // not intercepted
   7550   }
   7551 
   7552   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
   7553 }
   7554 
   7555 
   7556 static void IDeleter(uint32_t index,
   7557                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   7558   if (index != 2) {
   7559     return;  // not intercepted
   7560   }
   7561 
   7562   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
   7563 }
   7564 
   7565 
   7566 THREADED_TEST(Deleter) {
   7567   v8::Isolate* isolate = CcTest::isolate();
   7568   v8::HandleScope scope(isolate);
   7569   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   7570   obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
   7571   obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
   7572   LocalContext context;
   7573   context->Global()->Set(v8_str("k"), obj->NewInstance());
   7574   CompileRun(
   7575     "k.foo = 'foo';"
   7576     "k.bar = 'bar';"
   7577     "k[2] = 2;"
   7578     "k[4] = 4;");
   7579   CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
   7580   CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
   7581 
   7582   CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
   7583   CHECK(v8_compile("k.bar")->Run()->IsUndefined());
   7584 
   7585   CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
   7586   CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
   7587 
   7588   CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
   7589   CHECK(v8_compile("k[4]")->Run()->IsUndefined());
   7590 }
   7591 
   7592 
   7593 static void GetK(Local<String> name,
   7594                  const v8::PropertyCallbackInfo<v8::Value>& info) {
   7595   ApiTestFuzzer::Fuzz();
   7596   if (name->Equals(v8_str("foo")) ||
   7597       name->Equals(v8_str("bar")) ||
   7598       name->Equals(v8_str("baz"))) {
   7599     info.GetReturnValue().SetUndefined();
   7600   }
   7601 }
   7602 
   7603 
   7604 static void IndexedGetK(uint32_t index,
   7605                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   7606   ApiTestFuzzer::Fuzz();
   7607   if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
   7608 }
   7609 
   7610 
   7611 static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
   7612   ApiTestFuzzer::Fuzz();
   7613   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
   7614   result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"));
   7615   result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"));
   7616   result->Set(v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"));
   7617   info.GetReturnValue().Set(result);
   7618 }
   7619 
   7620 
   7621 static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
   7622   ApiTestFuzzer::Fuzz();
   7623   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
   7624   result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("0"));
   7625   result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("1"));
   7626   info.GetReturnValue().Set(result);
   7627 }
   7628 
   7629 
   7630 THREADED_TEST(Enumerators) {
   7631   v8::Isolate* isolate = CcTest::isolate();
   7632   v8::HandleScope scope(isolate);
   7633   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   7634   obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
   7635   obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
   7636   LocalContext context;
   7637   context->Global()->Set(v8_str("k"), obj->NewInstance());
   7638   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   7639     "k[10] = 0;"
   7640     "k.a = 0;"
   7641     "k[5] = 0;"
   7642     "k.b = 0;"
   7643     "k[4294967295] = 0;"
   7644     "k.c = 0;"
   7645     "k[4294967296] = 0;"
   7646     "k.d = 0;"
   7647     "k[140000] = 0;"
   7648     "k.e = 0;"
   7649     "k[30000000000] = 0;"
   7650     "k.f = 0;"
   7651     "var result = [];"
   7652     "for (var prop in k) {"
   7653     "  result.push(prop);"
   7654     "}"
   7655     "result"));
   7656   // Check that we get all the property names returned including the
   7657   // ones from the enumerators in the right order: indexed properties
   7658   // in numerical order, indexed interceptor properties, named
   7659   // properties in insertion order, named interceptor properties.
   7660   // This order is not mandated by the spec, so this test is just
   7661   // documenting our behavior.
   7662   CHECK_EQ(17, result->Length());
   7663   // Indexed properties in numerical order.
   7664   CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(isolate, 0)));
   7665   CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(isolate, 1)));
   7666   CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(isolate, 2)));
   7667   CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(isolate, 3)));
   7668   // Indexed interceptor properties in the order they are returned
   7669   // from the enumerator interceptor.
   7670   CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(isolate, 4)));
   7671   CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(isolate, 5)));
   7672   // Named properties in insertion order.
   7673   CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(isolate, 6)));
   7674   CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(isolate, 7)));
   7675   CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(isolate, 8)));
   7676   CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(isolate, 9)));
   7677   CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(isolate, 10)));
   7678   CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(isolate, 11)));
   7679   CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(isolate, 12)));
   7680   CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(isolate, 13)));
   7681   // Named interceptor properties.
   7682   CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(isolate, 14)));
   7683   CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(isolate, 15)));
   7684   CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(isolate, 16)));
   7685 }
   7686 
   7687 
   7688 int p_getter_count;
   7689 int p_getter_count2;
   7690 
   7691 
   7692 static void PGetter(Local<String> name,
   7693                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   7694   ApiTestFuzzer::Fuzz();
   7695   p_getter_count++;
   7696   v8::Handle<v8::Object> global =
   7697       info.GetIsolate()->GetCurrentContext()->Global();
   7698   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   7699   if (name->Equals(v8_str("p1"))) {
   7700     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   7701   } else if (name->Equals(v8_str("p2"))) {
   7702     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   7703   } else if (name->Equals(v8_str("p3"))) {
   7704     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   7705   } else if (name->Equals(v8_str("p4"))) {
   7706     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   7707   }
   7708 }
   7709 
   7710 
   7711 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
   7712   ApiTestFuzzer::Fuzz();
   7713   LocalContext context;
   7714   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   7715   CompileRun(
   7716     "o1.__proto__ = { };"
   7717     "var o2 = { __proto__: o1 };"
   7718     "var o3 = { __proto__: o2 };"
   7719     "var o4 = { __proto__: o3 };"
   7720     "for (var i = 0; i < 10; i++) o4.p4;"
   7721     "for (var i = 0; i < 10; i++) o3.p3;"
   7722     "for (var i = 0; i < 10; i++) o2.p2;"
   7723     "for (var i = 0; i < 10; i++) o1.p1;");
   7724 }
   7725 
   7726 
   7727 static void PGetter2(Local<String> name,
   7728                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   7729   ApiTestFuzzer::Fuzz();
   7730   p_getter_count2++;
   7731   v8::Handle<v8::Object> global =
   7732       info.GetIsolate()->GetCurrentContext()->Global();
   7733   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   7734   if (name->Equals(v8_str("p1"))) {
   7735     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   7736   } else if (name->Equals(v8_str("p2"))) {
   7737     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   7738   } else if (name->Equals(v8_str("p3"))) {
   7739     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   7740   } else if (name->Equals(v8_str("p4"))) {
   7741     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   7742   }
   7743 }
   7744 
   7745 
   7746 THREADED_TEST(GetterHolders) {
   7747   v8::Isolate* isolate = CcTest::isolate();
   7748   v8::HandleScope scope(isolate);
   7749   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   7750   obj->SetAccessor(v8_str("p1"), PGetter);
   7751   obj->SetAccessor(v8_str("p2"), PGetter);
   7752   obj->SetAccessor(v8_str("p3"), PGetter);
   7753   obj->SetAccessor(v8_str("p4"), PGetter);
   7754   p_getter_count = 0;
   7755   RunHolderTest(obj);
   7756   CHECK_EQ(40, p_getter_count);
   7757 }
   7758 
   7759 
   7760 THREADED_TEST(PreInterceptorHolders) {
   7761   v8::Isolate* isolate = CcTest::isolate();
   7762   v8::HandleScope scope(isolate);
   7763   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   7764   obj->SetNamedPropertyHandler(PGetter2);
   7765   p_getter_count2 = 0;
   7766   RunHolderTest(obj);
   7767   CHECK_EQ(40, p_getter_count2);
   7768 }
   7769 
   7770 
   7771 THREADED_TEST(ObjectInstantiation) {
   7772   v8::Isolate* isolate = CcTest::isolate();
   7773   v8::HandleScope scope(isolate);
   7774   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   7775   templ->SetAccessor(v8_str("t"), PGetter2);
   7776   LocalContext context;
   7777   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7778   for (int i = 0; i < 100; i++) {
   7779     v8::HandleScope inner_scope(CcTest::isolate());
   7780     v8::Handle<v8::Object> obj = templ->NewInstance();
   7781     CHECK_NE(obj, context->Global()->Get(v8_str("o")));
   7782     context->Global()->Set(v8_str("o2"), obj);
   7783     v8::Handle<Value> value =
   7784         CompileRun("o.__proto__ === o2.__proto__");
   7785     CHECK_EQ(v8::True(isolate), value);
   7786     context->Global()->Set(v8_str("o"), obj);
   7787   }
   7788 }
   7789 
   7790 
   7791 static int StrCmp16(uint16_t* a, uint16_t* b) {
   7792   while (true) {
   7793     if (*a == 0 && *b == 0) return 0;
   7794     if (*a != *b) return 0 + *a - *b;
   7795     a++;
   7796     b++;
   7797   }
   7798 }
   7799 
   7800 
   7801 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
   7802   while (true) {
   7803     if (n-- == 0) return 0;
   7804     if (*a == 0 && *b == 0) return 0;
   7805     if (*a != *b) return 0 + *a - *b;
   7806     a++;
   7807     b++;
   7808   }
   7809 }
   7810 
   7811 
   7812 int GetUtf8Length(Handle<String> str) {
   7813   int len = str->Utf8Length();
   7814   if (len < 0) {
   7815     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
   7816     i::String::Flatten(istr);
   7817     len = str->Utf8Length();
   7818   }
   7819   return len;
   7820 }
   7821 
   7822 
   7823 THREADED_TEST(StringWrite) {
   7824   LocalContext context;
   7825   v8::HandleScope scope(context->GetIsolate());
   7826   v8::Handle<String> str = v8_str("abcde");
   7827   // abc<Icelandic eth><Unicode snowman>.
   7828   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
   7829   v8::Handle<String> str3 = v8::String::NewFromUtf8(
   7830       context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
   7831   // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
   7832   uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
   7833   v8::Handle<String> orphans_str = v8::String::NewFromTwoByte(
   7834       context->GetIsolate(), orphans, v8::String::kNormalString, 8);
   7835   // single lead surrogate
   7836   uint16_t lead[1] = { 0xd800 };
   7837   v8::Handle<String> lead_str = v8::String::NewFromTwoByte(
   7838       context->GetIsolate(), lead, v8::String::kNormalString, 1);
   7839   // single trail surrogate
   7840   uint16_t trail[1] = { 0xdc00 };
   7841   v8::Handle<String> trail_str = v8::String::NewFromTwoByte(
   7842       context->GetIsolate(), trail, v8::String::kNormalString, 1);
   7843   // surrogate pair
   7844   uint16_t pair[2] = { 0xd800,  0xdc00 };
   7845   v8::Handle<String> pair_str = v8::String::NewFromTwoByte(
   7846       context->GetIsolate(), pair, v8::String::kNormalString, 2);
   7847   const int kStride = 4;  // Must match stride in for loops in JS below.
   7848   CompileRun(
   7849       "var left = '';"
   7850       "for (var i = 0; i < 0xd800; i += 4) {"
   7851       "  left = left + String.fromCharCode(i);"
   7852       "}");
   7853   CompileRun(
   7854       "var right = '';"
   7855       "for (var i = 0; i < 0xd800; i += 4) {"
   7856       "  right = String.fromCharCode(i) + right;"
   7857       "}");
   7858   v8::Handle<v8::Object> global = context->Global();
   7859   Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
   7860   Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
   7861 
   7862   CHECK_EQ(5, str2->Length());
   7863   CHECK_EQ(0xd800 / kStride, left_tree->Length());
   7864   CHECK_EQ(0xd800 / kStride, right_tree->Length());
   7865 
   7866   char buf[100];
   7867   char utf8buf[0xd800 * 3];
   7868   uint16_t wbuf[100];
   7869   int len;
   7870   int charlen;
   7871 
   7872   memset(utf8buf, 0x1, 1000);
   7873   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   7874   CHECK_EQ(9, len);
   7875   CHECK_EQ(5, charlen);
   7876   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   7877 
   7878   memset(utf8buf, 0x1, 1000);
   7879   len = str2->WriteUtf8(utf8buf, 8, &charlen);
   7880   CHECK_EQ(8, len);
   7881   CHECK_EQ(5, charlen);
   7882   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
   7883 
   7884   memset(utf8buf, 0x1, 1000);
   7885   len = str2->WriteUtf8(utf8buf, 7, &charlen);
   7886   CHECK_EQ(5, len);
   7887   CHECK_EQ(4, charlen);
   7888   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   7889 
   7890   memset(utf8buf, 0x1, 1000);
   7891   len = str2->WriteUtf8(utf8buf, 6, &charlen);
   7892   CHECK_EQ(5, len);
   7893   CHECK_EQ(4, charlen);
   7894   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   7895 
   7896   memset(utf8buf, 0x1, 1000);
   7897   len = str2->WriteUtf8(utf8buf, 5, &charlen);
   7898   CHECK_EQ(5, len);
   7899   CHECK_EQ(4, charlen);
   7900   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   7901 
   7902   memset(utf8buf, 0x1, 1000);
   7903   len = str2->WriteUtf8(utf8buf, 4, &charlen);
   7904   CHECK_EQ(3, len);
   7905   CHECK_EQ(3, charlen);
   7906   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   7907 
   7908   memset(utf8buf, 0x1, 1000);
   7909   len = str2->WriteUtf8(utf8buf, 3, &charlen);
   7910   CHECK_EQ(3, len);
   7911   CHECK_EQ(3, charlen);
   7912   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   7913 
   7914   memset(utf8buf, 0x1, 1000);
   7915   len = str2->WriteUtf8(utf8buf, 2, &charlen);
   7916   CHECK_EQ(2, len);
   7917   CHECK_EQ(2, charlen);
   7918   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
   7919 
   7920   // allow orphan surrogates by default
   7921   memset(utf8buf, 0x1, 1000);
   7922   len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   7923   CHECK_EQ(13, len);
   7924   CHECK_EQ(8, charlen);
   7925   CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
   7926 
   7927   // replace orphan surrogates with unicode replacement character
   7928   memset(utf8buf, 0x1, 1000);
   7929   len = orphans_str->WriteUtf8(utf8buf,
   7930                                sizeof(utf8buf),
   7931                                &charlen,
   7932                                String::REPLACE_INVALID_UTF8);
   7933   CHECK_EQ(13, len);
   7934   CHECK_EQ(8, charlen);
   7935   CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
   7936 
   7937   // replace single lead surrogate with unicode replacement character
   7938   memset(utf8buf, 0x1, 1000);
   7939   len = lead_str->WriteUtf8(utf8buf,
   7940                             sizeof(utf8buf),
   7941                             &charlen,
   7942                             String::REPLACE_INVALID_UTF8);
   7943   CHECK_EQ(4, len);
   7944   CHECK_EQ(1, charlen);
   7945   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
   7946 
   7947   // replace single trail surrogate with unicode replacement character
   7948   memset(utf8buf, 0x1, 1000);
   7949   len = trail_str->WriteUtf8(utf8buf,
   7950                              sizeof(utf8buf),
   7951                              &charlen,
   7952                              String::REPLACE_INVALID_UTF8);
   7953   CHECK_EQ(4, len);
   7954   CHECK_EQ(1, charlen);
   7955   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
   7956 
   7957   // do not replace / write anything if surrogate pair does not fit the buffer
   7958   // space
   7959   memset(utf8buf, 0x1, 1000);
   7960   len = pair_str->WriteUtf8(utf8buf,
   7961                              3,
   7962                              &charlen,
   7963                              String::REPLACE_INVALID_UTF8);
   7964   CHECK_EQ(0, len);
   7965   CHECK_EQ(0, charlen);
   7966 
   7967   memset(utf8buf, 0x1, sizeof(utf8buf));
   7968   len = GetUtf8Length(left_tree);
   7969   int utf8_expected =
   7970       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
   7971   CHECK_EQ(utf8_expected, len);
   7972   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   7973   CHECK_EQ(utf8_expected, len);
   7974   CHECK_EQ(0xd800 / kStride, charlen);
   7975   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
   7976   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
   7977   CHECK_EQ(0xc0 - kStride,
   7978            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
   7979   CHECK_EQ(1, utf8buf[utf8_expected]);
   7980 
   7981   memset(utf8buf, 0x1, sizeof(utf8buf));
   7982   len = GetUtf8Length(right_tree);
   7983   CHECK_EQ(utf8_expected, len);
   7984   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   7985   CHECK_EQ(utf8_expected, len);
   7986   CHECK_EQ(0xd800 / kStride, charlen);
   7987   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
   7988   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
   7989   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
   7990   CHECK_EQ(1, utf8buf[utf8_expected]);
   7991 
   7992   memset(buf, 0x1, sizeof(buf));
   7993   memset(wbuf, 0x1, sizeof(wbuf));
   7994   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   7995   CHECK_EQ(5, len);
   7996   len = str->Write(wbuf);
   7997   CHECK_EQ(5, len);
   7998   CHECK_EQ(0, strcmp("abcde", buf));
   7999   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   8000   CHECK_EQ(0, StrCmp16(answer1, wbuf));
   8001 
   8002   memset(buf, 0x1, sizeof(buf));
   8003   memset(wbuf, 0x1, sizeof(wbuf));
   8004   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
   8005   CHECK_EQ(4, len);
   8006   len = str->Write(wbuf, 0, 4);
   8007   CHECK_EQ(4, len);
   8008   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
   8009   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
   8010   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
   8011 
   8012   memset(buf, 0x1, sizeof(buf));
   8013   memset(wbuf, 0x1, sizeof(wbuf));
   8014   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
   8015   CHECK_EQ(5, len);
   8016   len = str->Write(wbuf, 0, 5);
   8017   CHECK_EQ(5, len);
   8018   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
   8019   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
   8020   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
   8021 
   8022   memset(buf, 0x1, sizeof(buf));
   8023   memset(wbuf, 0x1, sizeof(wbuf));
   8024   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
   8025   CHECK_EQ(5, len);
   8026   len = str->Write(wbuf, 0, 6);
   8027   CHECK_EQ(5, len);
   8028   CHECK_EQ(0, strcmp("abcde", buf));
   8029   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   8030   CHECK_EQ(0, StrCmp16(answer4, wbuf));
   8031 
   8032   memset(buf, 0x1, sizeof(buf));
   8033   memset(wbuf, 0x1, sizeof(wbuf));
   8034   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
   8035   CHECK_EQ(1, len);
   8036   len = str->Write(wbuf, 4, -1);
   8037   CHECK_EQ(1, len);
   8038   CHECK_EQ(0, strcmp("e", buf));
   8039   uint16_t answer5[] = {'e', '\0'};
   8040   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   8041 
   8042   memset(buf, 0x1, sizeof(buf));
   8043   memset(wbuf, 0x1, sizeof(wbuf));
   8044   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
   8045   CHECK_EQ(1, len);
   8046   len = str->Write(wbuf, 4, 6);
   8047   CHECK_EQ(1, len);
   8048   CHECK_EQ(0, strcmp("e", buf));
   8049   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   8050 
   8051   memset(buf, 0x1, sizeof(buf));
   8052   memset(wbuf, 0x1, sizeof(wbuf));
   8053   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
   8054   CHECK_EQ(1, len);
   8055   len = str->Write(wbuf, 4, 1);
   8056   CHECK_EQ(1, len);
   8057   CHECK_EQ(0, strncmp("e\1", buf, 2));
   8058   uint16_t answer6[] = {'e', 0x101};
   8059   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
   8060 
   8061   memset(buf, 0x1, sizeof(buf));
   8062   memset(wbuf, 0x1, sizeof(wbuf));
   8063   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
   8064   CHECK_EQ(1, len);
   8065   len = str->Write(wbuf, 3, 1);
   8066   CHECK_EQ(1, len);
   8067   CHECK_EQ(0, strncmp("d\1", buf, 2));
   8068   uint16_t answer7[] = {'d', 0x101};
   8069   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
   8070 
   8071   memset(wbuf, 0x1, sizeof(wbuf));
   8072   wbuf[5] = 'X';
   8073   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
   8074   CHECK_EQ(5, len);
   8075   CHECK_EQ('X', wbuf[5]);
   8076   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
   8077   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   8078   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
   8079   CHECK_NE(0, StrCmp16(answer8b, wbuf));
   8080   wbuf[5] = '\0';
   8081   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
   8082 
   8083   memset(buf, 0x1, sizeof(buf));
   8084   buf[5] = 'X';
   8085   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
   8086                           0,
   8087                           6,
   8088                           String::NO_NULL_TERMINATION);
   8089   CHECK_EQ(5, len);
   8090   CHECK_EQ('X', buf[5]);
   8091   CHECK_EQ(0, strncmp("abcde", buf, 5));
   8092   CHECK_NE(0, strcmp("abcde", buf));
   8093   buf[5] = '\0';
   8094   CHECK_EQ(0, strcmp("abcde", buf));
   8095 
   8096   memset(utf8buf, 0x1, sizeof(utf8buf));
   8097   utf8buf[8] = 'X';
   8098   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   8099                         String::NO_NULL_TERMINATION);
   8100   CHECK_EQ(8, len);
   8101   CHECK_EQ('X', utf8buf[8]);
   8102   CHECK_EQ(5, charlen);
   8103   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
   8104   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   8105   utf8buf[8] = '\0';
   8106   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   8107 
   8108   memset(utf8buf, 0x1, sizeof(utf8buf));
   8109   utf8buf[5] = 'X';
   8110   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   8111                         String::NO_NULL_TERMINATION);
   8112   CHECK_EQ(5, len);
   8113   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
   8114   CHECK_EQ(5, charlen);
   8115   utf8buf[5] = '\0';
   8116   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
   8117 
   8118   memset(buf, 0x1, sizeof(buf));
   8119   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   8120   CHECK_EQ(7, len);
   8121   CHECK_EQ(0, strcmp("abc", buf));
   8122   CHECK_EQ(0, buf[3]);
   8123   CHECK_EQ(0, strcmp("def", buf + 4));
   8124 
   8125   CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
   8126   CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
   8127   CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
   8128 }
   8129 
   8130 
   8131 static void Utf16Helper(
   8132     LocalContext& context,  // NOLINT
   8133     const char* name,
   8134     const char* lengths_name,
   8135     int len) {
   8136   Local<v8::Array> a =
   8137       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
   8138   Local<v8::Array> alens =
   8139       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
   8140   for (int i = 0; i < len; i++) {
   8141     Local<v8::String> string =
   8142       Local<v8::String>::Cast(a->Get(i));
   8143     Local<v8::Number> expected_len =
   8144       Local<v8::Number>::Cast(alens->Get(i));
   8145     int length = GetUtf8Length(string);
   8146     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
   8147   }
   8148 }
   8149 
   8150 
   8151 static uint16_t StringGet(Handle<String> str, int index) {
   8152   i::Handle<i::String> istring =
   8153       v8::Utils::OpenHandle(String::Cast(*str));
   8154   return istring->Get(index);
   8155 }
   8156 
   8157 
   8158 static void WriteUtf8Helper(
   8159     LocalContext& context,  // NOLINT
   8160     const char* name,
   8161     const char* lengths_name,
   8162     int len) {
   8163   Local<v8::Array> b =
   8164       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
   8165   Local<v8::Array> alens =
   8166       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
   8167   char buffer[1000];
   8168   char buffer2[1000];
   8169   for (int i = 0; i < len; i++) {
   8170     Local<v8::String> string =
   8171       Local<v8::String>::Cast(b->Get(i));
   8172     Local<v8::Number> expected_len =
   8173       Local<v8::Number>::Cast(alens->Get(i));
   8174     int utf8_length = static_cast<int>(expected_len->Value());
   8175     for (int j = utf8_length + 1; j >= 0; j--) {
   8176       memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
   8177       memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
   8178       int nchars;
   8179       int utf8_written =
   8180           string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
   8181       int utf8_written2 =
   8182           string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
   8183       CHECK_GE(utf8_length + 1, utf8_written);
   8184       CHECK_GE(utf8_length, utf8_written2);
   8185       for (int k = 0; k < utf8_written2; k++) {
   8186         CHECK_EQ(buffer[k], buffer2[k]);
   8187       }
   8188       CHECK(nchars * 3 >= utf8_written - 1);
   8189       CHECK(nchars <= utf8_written);
   8190       if (j == utf8_length + 1) {
   8191         CHECK_EQ(utf8_written2, utf8_length);
   8192         CHECK_EQ(utf8_written2 + 1, utf8_written);
   8193       }
   8194       CHECK_EQ(buffer[utf8_written], 42);
   8195       if (j > utf8_length) {
   8196         if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
   8197         if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
   8198         Handle<String> roundtrip = v8_str(buffer);
   8199         CHECK(roundtrip->Equals(string));
   8200       } else {
   8201         if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
   8202       }
   8203       if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
   8204       if (nchars >= 2) {
   8205         uint16_t trail = StringGet(string, nchars - 1);
   8206         uint16_t lead = StringGet(string, nchars - 2);
   8207         if (((lead & 0xfc00) == 0xd800) &&
   8208             ((trail & 0xfc00) == 0xdc00)) {
   8209           unsigned char u1 = buffer2[utf8_written2 - 4];
   8210           unsigned char u2 = buffer2[utf8_written2 - 3];
   8211           unsigned char u3 = buffer2[utf8_written2 - 2];
   8212           unsigned char u4 = buffer2[utf8_written2 - 1];
   8213           CHECK_EQ((u1 & 0xf8), 0xf0);
   8214           CHECK_EQ((u2 & 0xc0), 0x80);
   8215           CHECK_EQ((u3 & 0xc0), 0x80);
   8216           CHECK_EQ((u4 & 0xc0), 0x80);
   8217           uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
   8218           CHECK_EQ((u4 & 0x3f), (c & 0x3f));
   8219           CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
   8220           CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
   8221           CHECK_EQ((u1 & 0x3), c >> 18);
   8222         }
   8223       }
   8224     }
   8225   }
   8226 }
   8227 
   8228 
   8229 THREADED_TEST(Utf16) {
   8230   LocalContext context;
   8231   v8::HandleScope scope(context->GetIsolate());
   8232   CompileRun(
   8233       "var pad = '01234567890123456789';"
   8234       "var p = [];"
   8235       "var plens = [20, 3, 3];"
   8236       "p.push('01234567890123456789');"
   8237       "var lead = 0xd800;"
   8238       "var trail = 0xdc00;"
   8239       "p.push(String.fromCharCode(0xd800));"
   8240       "p.push(String.fromCharCode(0xdc00));"
   8241       "var a = [];"
   8242       "var b = [];"
   8243       "var c = [];"
   8244       "var alens = [];"
   8245       "for (var i = 0; i < 3; i++) {"
   8246       "  p[1] = String.fromCharCode(lead++);"
   8247       "  for (var j = 0; j < 3; j++) {"
   8248       "    p[2] = String.fromCharCode(trail++);"
   8249       "    a.push(p[i] + p[j]);"
   8250       "    b.push(p[i] + p[j]);"
   8251       "    c.push(p[i] + p[j]);"
   8252       "    alens.push(plens[i] + plens[j]);"
   8253       "  }"
   8254       "}"
   8255       "alens[5] -= 2;"  // Here the surrogate pairs match up.
   8256       "var a2 = [];"
   8257       "var b2 = [];"
   8258       "var c2 = [];"
   8259       "var a2lens = [];"
   8260       "for (var m = 0; m < 9; m++) {"
   8261       "  for (var n = 0; n < 9; n++) {"
   8262       "    a2.push(a[m] + a[n]);"
   8263       "    b2.push(b[m] + b[n]);"
   8264       "    var newc = 'x' + c[m] + c[n] + 'y';"
   8265       "    c2.push(newc.substring(1, newc.length - 1));"
   8266       "    var utf = alens[m] + alens[n];"  // And here.
   8267            // The 'n's that start with 0xdc.. are 6-8
   8268            // The 'm's that end with 0xd8.. are 1, 4 and 7
   8269       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
   8270       "    a2lens.push(utf);"
   8271       "  }"
   8272       "}");
   8273   Utf16Helper(context, "a", "alens", 9);
   8274   Utf16Helper(context, "a2", "a2lens", 81);
   8275   WriteUtf8Helper(context, "b", "alens", 9);
   8276   WriteUtf8Helper(context, "b2", "a2lens", 81);
   8277   WriteUtf8Helper(context, "c2", "a2lens", 81);
   8278 }
   8279 
   8280 
   8281 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
   8282   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
   8283   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
   8284   return *is1 == *is2;
   8285 }
   8286 
   8287 static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
   8288                              const char* b) {
   8289   Handle<String> symbol1 =
   8290       v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
   8291   Handle<String> symbol2 =
   8292       v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
   8293   CHECK(SameSymbol(symbol1, symbol2));
   8294 }
   8295 
   8296 
   8297 THREADED_TEST(Utf16Symbol) {
   8298   LocalContext context;
   8299   v8::HandleScope scope(context->GetIsolate());
   8300 
   8301   Handle<String> symbol1 = v8::String::NewFromUtf8(
   8302       context->GetIsolate(), "abc", v8::String::kInternalizedString);
   8303   Handle<String> symbol2 = v8::String::NewFromUtf8(
   8304       context->GetIsolate(), "abc", v8::String::kInternalizedString);
   8305   CHECK(SameSymbol(symbol1, symbol2));
   8306 
   8307   SameSymbolHelper(context->GetIsolate(),
   8308                    "\360\220\220\205",  // 4 byte encoding.
   8309                    "\355\240\201\355\260\205");  // 2 3-byte surrogates.
   8310   SameSymbolHelper(context->GetIsolate(),
   8311                    "\355\240\201\355\260\206",  // 2 3-byte surrogates.
   8312                    "\360\220\220\206");  // 4 byte encoding.
   8313   SameSymbolHelper(context->GetIsolate(),
   8314                    "x\360\220\220\205",  // 4 byte encoding.
   8315                    "x\355\240\201\355\260\205");  // 2 3-byte surrogates.
   8316   SameSymbolHelper(context->GetIsolate(),
   8317                    "x\355\240\201\355\260\206",  // 2 3-byte surrogates.
   8318                    "x\360\220\220\206");  // 4 byte encoding.
   8319   CompileRun(
   8320       "var sym0 = 'benedictus';"
   8321       "var sym0b = 'S\303\270ren';"
   8322       "var sym1 = '\355\240\201\355\260\207';"
   8323       "var sym2 = '\360\220\220\210';"
   8324       "var sym3 = 'x\355\240\201\355\260\207';"
   8325       "var sym4 = 'x\360\220\220\210';"
   8326       "if (sym1.length != 2) throw sym1;"
   8327       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
   8328       "if (sym2.length != 2) throw sym2;"
   8329       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
   8330       "if (sym3.length != 3) throw sym3;"
   8331       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
   8332       "if (sym4.length != 3) throw sym4;"
   8333       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
   8334   Handle<String> sym0 = v8::String::NewFromUtf8(
   8335       context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
   8336   Handle<String> sym0b = v8::String::NewFromUtf8(
   8337       context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
   8338   Handle<String> sym1 =
   8339       v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
   8340                               v8::String::kInternalizedString);
   8341   Handle<String> sym2 =
   8342       v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
   8343                               v8::String::kInternalizedString);
   8344   Handle<String> sym3 = v8::String::NewFromUtf8(
   8345       context->GetIsolate(), "x\355\240\201\355\260\207",
   8346       v8::String::kInternalizedString);
   8347   Handle<String> sym4 =
   8348       v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
   8349                               v8::String::kInternalizedString);
   8350   v8::Local<v8::Object> global = context->Global();
   8351   Local<Value> s0 = global->Get(v8_str("sym0"));
   8352   Local<Value> s0b = global->Get(v8_str("sym0b"));
   8353   Local<Value> s1 = global->Get(v8_str("sym1"));
   8354   Local<Value> s2 = global->Get(v8_str("sym2"));
   8355   Local<Value> s3 = global->Get(v8_str("sym3"));
   8356   Local<Value> s4 = global->Get(v8_str("sym4"));
   8357   CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
   8358   CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
   8359   CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
   8360   CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
   8361   CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
   8362   CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
   8363 }
   8364 
   8365 
   8366 THREADED_TEST(ToArrayIndex) {
   8367   LocalContext context;
   8368   v8::Isolate* isolate = context->GetIsolate();
   8369   v8::HandleScope scope(isolate);
   8370 
   8371   v8::Handle<String> str = v8_str("42");
   8372   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
   8373   CHECK(!index.IsEmpty());
   8374   CHECK_EQ(42.0, index->Uint32Value());
   8375   str = v8_str("42asdf");
   8376   index = str->ToArrayIndex();
   8377   CHECK(index.IsEmpty());
   8378   str = v8_str("-42");
   8379   index = str->ToArrayIndex();
   8380   CHECK(index.IsEmpty());
   8381   str = v8_str("4294967295");
   8382   index = str->ToArrayIndex();
   8383   CHECK(!index.IsEmpty());
   8384   CHECK_EQ(4294967295.0, index->Uint32Value());
   8385   v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
   8386   index = num->ToArrayIndex();
   8387   CHECK(!index.IsEmpty());
   8388   CHECK_EQ(1.0, index->Uint32Value());
   8389   num = v8::Number::New(isolate, -1);
   8390   index = num->ToArrayIndex();
   8391   CHECK(index.IsEmpty());
   8392   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
   8393   index = obj->ToArrayIndex();
   8394   CHECK(index.IsEmpty());
   8395 }
   8396 
   8397 
   8398 THREADED_TEST(ErrorConstruction) {
   8399   LocalContext context;
   8400   v8::HandleScope scope(context->GetIsolate());
   8401 
   8402   v8::Handle<String> foo = v8_str("foo");
   8403   v8::Handle<String> message = v8_str("message");
   8404   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
   8405   CHECK(range_error->IsObject());
   8406   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
   8407   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
   8408   CHECK(reference_error->IsObject());
   8409   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
   8410   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
   8411   CHECK(syntax_error->IsObject());
   8412   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
   8413   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
   8414   CHECK(type_error->IsObject());
   8415   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
   8416   v8::Handle<Value> error = v8::Exception::Error(foo);
   8417   CHECK(error->IsObject());
   8418   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
   8419 }
   8420 
   8421 
   8422 static void YGetter(Local<String> name,
   8423                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8424   ApiTestFuzzer::Fuzz();
   8425   info.GetReturnValue().Set(v8_num(10));
   8426 }
   8427 
   8428 
   8429 static void YSetter(Local<String> name,
   8430                     Local<Value> value,
   8431                     const v8::PropertyCallbackInfo<void>& info) {
   8432   Local<Object> this_obj = Local<Object>::Cast(info.This());
   8433   if (this_obj->Has(name)) this_obj->Delete(name);
   8434   this_obj->Set(name, value);
   8435 }
   8436 
   8437 
   8438 THREADED_TEST(DeleteAccessor) {
   8439   v8::Isolate* isolate = CcTest::isolate();
   8440   v8::HandleScope scope(isolate);
   8441   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   8442   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
   8443   LocalContext context;
   8444   v8::Handle<v8::Object> holder = obj->NewInstance();
   8445   context->Global()->Set(v8_str("holder"), holder);
   8446   v8::Handle<Value> result = CompileRun(
   8447       "holder.y = 11; holder.y = 12; holder.y");
   8448   CHECK_EQ(12, result->Uint32Value());
   8449 }
   8450 
   8451 
   8452 THREADED_TEST(TypeSwitch) {
   8453   v8::Isolate* isolate = CcTest::isolate();
   8454   v8::HandleScope scope(isolate);
   8455   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
   8456   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
   8457   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
   8458   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
   8459   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
   8460   LocalContext context;
   8461   v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
   8462   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
   8463   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
   8464   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
   8465   for (int i = 0; i < 10; i++) {
   8466     CHECK_EQ(0, type_switch->match(obj0));
   8467     CHECK_EQ(1, type_switch->match(obj1));
   8468     CHECK_EQ(2, type_switch->match(obj2));
   8469     CHECK_EQ(3, type_switch->match(obj3));
   8470     CHECK_EQ(3, type_switch->match(obj3));
   8471     CHECK_EQ(2, type_switch->match(obj2));
   8472     CHECK_EQ(1, type_switch->match(obj1));
   8473     CHECK_EQ(0, type_switch->match(obj0));
   8474   }
   8475 }
   8476 
   8477 
   8478 static int trouble_nesting = 0;
   8479 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   8480   ApiTestFuzzer::Fuzz();
   8481   trouble_nesting++;
   8482 
   8483   // Call a JS function that throws an uncaught exception.
   8484   Local<v8::Object> arg_this =
   8485       args.GetIsolate()->GetCurrentContext()->Global();
   8486   Local<Value> trouble_callee = (trouble_nesting == 3) ?
   8487     arg_this->Get(v8_str("trouble_callee")) :
   8488     arg_this->Get(v8_str("trouble_caller"));
   8489   CHECK(trouble_callee->IsFunction());
   8490   args.GetReturnValue().Set(
   8491       Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
   8492 }
   8493 
   8494 
   8495 static int report_count = 0;
   8496 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
   8497                                              v8::Handle<Value>) {
   8498   report_count++;
   8499 }
   8500 
   8501 
   8502 // Counts uncaught exceptions, but other tests running in parallel
   8503 // also have uncaught exceptions.
   8504 TEST(ApiUncaughtException) {
   8505   report_count = 0;
   8506   LocalContext env;
   8507   v8::Isolate* isolate = env->GetIsolate();
   8508   v8::HandleScope scope(isolate);
   8509   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
   8510 
   8511   Local<v8::FunctionTemplate> fun =
   8512       v8::FunctionTemplate::New(isolate, TroubleCallback);
   8513   v8::Local<v8::Object> global = env->Global();
   8514   global->Set(v8_str("trouble"), fun->GetFunction());
   8515 
   8516   CompileRun(
   8517       "function trouble_callee() {"
   8518       "  var x = null;"
   8519       "  return x.foo;"
   8520       "};"
   8521       "function trouble_caller() {"
   8522       "  trouble();"
   8523       "};");
   8524   Local<Value> trouble = global->Get(v8_str("trouble"));
   8525   CHECK(trouble->IsFunction());
   8526   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
   8527   CHECK(trouble_callee->IsFunction());
   8528   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
   8529   CHECK(trouble_caller->IsFunction());
   8530   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
   8531   CHECK_EQ(1, report_count);
   8532   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
   8533 }
   8534 
   8535 static const char* script_resource_name = "ExceptionInNativeScript.js";
   8536 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
   8537                                                 v8::Handle<Value>) {
   8538   v8::Handle<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
   8539   CHECK(!name_val.IsEmpty() && name_val->IsString());
   8540   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
   8541   CHECK_EQ(script_resource_name, *name);
   8542   CHECK_EQ(3, message->GetLineNumber());
   8543   v8::String::Utf8Value source_line(message->GetSourceLine());
   8544   CHECK_EQ("  new o.foo();", *source_line);
   8545 }
   8546 
   8547 
   8548 TEST(ExceptionInNativeScript) {
   8549   LocalContext env;
   8550   v8::Isolate* isolate = env->GetIsolate();
   8551   v8::HandleScope scope(isolate);
   8552   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
   8553 
   8554   Local<v8::FunctionTemplate> fun =
   8555       v8::FunctionTemplate::New(isolate, TroubleCallback);
   8556   v8::Local<v8::Object> global = env->Global();
   8557   global->Set(v8_str("trouble"), fun->GetFunction());
   8558 
   8559   CompileRunWithOrigin(
   8560       "function trouble() {\n"
   8561       "  var o = {};\n"
   8562       "  new o.foo();\n"
   8563       "};",
   8564       script_resource_name);
   8565   Local<Value> trouble = global->Get(v8_str("trouble"));
   8566   CHECK(trouble->IsFunction());
   8567   Function::Cast(*trouble)->Call(global, 0, NULL);
   8568   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
   8569 }
   8570 
   8571 
   8572 TEST(CompilationErrorUsingTryCatchHandler) {
   8573   LocalContext env;
   8574   v8::HandleScope scope(env->GetIsolate());
   8575   v8::TryCatch try_catch;
   8576   v8_compile("This doesn't &*&@#$&*^ compile.");
   8577   CHECK_NE(NULL, *try_catch.Exception());
   8578   CHECK(try_catch.HasCaught());
   8579 }
   8580 
   8581 
   8582 TEST(TryCatchFinallyUsingTryCatchHandler) {
   8583   LocalContext env;
   8584   v8::HandleScope scope(env->GetIsolate());
   8585   v8::TryCatch try_catch;
   8586   CompileRun("try { throw ''; } catch (e) {}");
   8587   CHECK(!try_catch.HasCaught());
   8588   CompileRun("try { throw ''; } finally {}");
   8589   CHECK(try_catch.HasCaught());
   8590   try_catch.Reset();
   8591   CompileRun(
   8592       "(function() {"
   8593       "try { throw ''; } finally { return; }"
   8594       "})()");
   8595   CHECK(!try_catch.HasCaught());
   8596   CompileRun(
   8597       "(function()"
   8598       "  { try { throw ''; } finally { throw 0; }"
   8599       "})()");
   8600   CHECK(try_catch.HasCaught());
   8601 }
   8602 
   8603 
   8604 void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
   8605   v8::HandleScope scope(args.GetIsolate());
   8606   CompileRun(args[0]->ToString());
   8607 }
   8608 
   8609 
   8610 TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
   8611   v8::Isolate* isolate = CcTest::isolate();
   8612   v8::HandleScope scope(isolate);
   8613   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   8614   templ->Set(v8_str("CEvaluate"),
   8615              v8::FunctionTemplate::New(isolate, CEvaluate));
   8616   LocalContext context(0, templ);
   8617   v8::TryCatch try_catch;
   8618   CompileRun("try {"
   8619              "  CEvaluate('throw 1;');"
   8620              "} finally {"
   8621              "}");
   8622   CHECK(try_catch.HasCaught());
   8623   CHECK(!try_catch.Message().IsEmpty());
   8624   String::Utf8Value exception_value(try_catch.Exception());
   8625   CHECK_EQ(*exception_value, "1");
   8626   try_catch.Reset();
   8627   CompileRun("try {"
   8628              "  CEvaluate('throw 1;');"
   8629              "} finally {"
   8630              "  throw 2;"
   8631              "}");
   8632   CHECK(try_catch.HasCaught());
   8633   CHECK(!try_catch.Message().IsEmpty());
   8634   String::Utf8Value finally_exception_value(try_catch.Exception());
   8635   CHECK_EQ(*finally_exception_value, "2");
   8636 }
   8637 
   8638 
   8639 // For use within the TestSecurityHandler() test.
   8640 static bool g_security_callback_result = false;
   8641 static bool NamedSecurityTestCallback(Local<v8::Object> global,
   8642                                       Local<Value> name,
   8643                                       v8::AccessType type,
   8644                                       Local<Value> data) {
   8645   printf("a\n");
   8646   // Always allow read access.
   8647   if (type == v8::ACCESS_GET)
   8648     return true;
   8649 
   8650   // Sometimes allow other access.
   8651   return g_security_callback_result;
   8652 }
   8653 
   8654 
   8655 static bool IndexedSecurityTestCallback(Local<v8::Object> global,
   8656                                         uint32_t key,
   8657                                         v8::AccessType type,
   8658                                         Local<Value> data) {
   8659   printf("b\n");
   8660   // Always allow read access.
   8661   if (type == v8::ACCESS_GET)
   8662     return true;
   8663 
   8664   // Sometimes allow other access.
   8665   return g_security_callback_result;
   8666 }
   8667 
   8668 
   8669 // SecurityHandler can't be run twice
   8670 TEST(SecurityHandler) {
   8671   v8::Isolate* isolate = CcTest::isolate();
   8672   v8::HandleScope scope0(isolate);
   8673   v8::Handle<v8::ObjectTemplate> global_template =
   8674       v8::ObjectTemplate::New(isolate);
   8675   global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
   8676                                            IndexedSecurityTestCallback);
   8677   // Create an environment
   8678   v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
   8679   context0->Enter();
   8680 
   8681   v8::Handle<v8::Object> global0 = context0->Global();
   8682   v8::Handle<Script> script0 = v8_compile("foo = 111");
   8683   script0->Run();
   8684   global0->Set(v8_str("0"), v8_num(999));
   8685   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
   8686   CHECK_EQ(111, foo0->Int32Value());
   8687   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
   8688   CHECK_EQ(999, z0->Int32Value());
   8689 
   8690   // Create another environment, should fail security checks.
   8691   v8::HandleScope scope1(isolate);
   8692 
   8693   v8::Handle<Context> context1 =
   8694     Context::New(isolate, NULL, global_template);
   8695   context1->Enter();
   8696 
   8697   v8::Handle<v8::Object> global1 = context1->Global();
   8698   global1->Set(v8_str("othercontext"), global0);
   8699   // This set will fail the security check.
   8700   v8::Handle<Script> script1 =
   8701     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
   8702   script1->Run();
   8703   // This read will pass the security check.
   8704   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
   8705   CHECK_EQ(111, foo1->Int32Value());
   8706   // This read will pass the security check.
   8707   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
   8708   CHECK_EQ(999, z1->Int32Value());
   8709 
   8710   // Create another environment, should pass security checks.
   8711   { g_security_callback_result = true;  // allow security handler to pass.
   8712     v8::HandleScope scope2(isolate);
   8713     LocalContext context2;
   8714     v8::Handle<v8::Object> global2 = context2->Global();
   8715     global2->Set(v8_str("othercontext"), global0);
   8716     v8::Handle<Script> script2 =
   8717         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
   8718     script2->Run();
   8719     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
   8720     CHECK_EQ(333, foo2->Int32Value());
   8721     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
   8722     CHECK_EQ(888, z2->Int32Value());
   8723   }
   8724 
   8725   context1->Exit();
   8726   context0->Exit();
   8727 }
   8728 
   8729 
   8730 THREADED_TEST(SecurityChecks) {
   8731   LocalContext env1;
   8732   v8::HandleScope handle_scope(env1->GetIsolate());
   8733   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8734 
   8735   Local<Value> foo = v8_str("foo");
   8736   Local<Value> bar = v8_str("bar");
   8737 
   8738   // Set to the same domain.
   8739   env1->SetSecurityToken(foo);
   8740 
   8741   // Create a function in env1.
   8742   CompileRun("spy=function(){return spy;}");
   8743   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
   8744   CHECK(spy->IsFunction());
   8745 
   8746   // Create another function accessing global objects.
   8747   CompileRun("spy2=function(){return new this.Array();}");
   8748   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
   8749   CHECK(spy2->IsFunction());
   8750 
   8751   // Switch to env2 in the same domain and invoke spy on env2.
   8752   {
   8753     env2->SetSecurityToken(foo);
   8754     // Enter env2
   8755     Context::Scope scope_env2(env2);
   8756     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
   8757     CHECK(result->IsFunction());
   8758   }
   8759 
   8760   {
   8761     env2->SetSecurityToken(bar);
   8762     Context::Scope scope_env2(env2);
   8763 
   8764     // Call cross_domain_call, it should throw an exception
   8765     v8::TryCatch try_catch;
   8766     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
   8767     CHECK(try_catch.HasCaught());
   8768   }
   8769 }
   8770 
   8771 
   8772 // Regression test case for issue 1183439.
   8773 THREADED_TEST(SecurityChecksForPrototypeChain) {
   8774   LocalContext current;
   8775   v8::HandleScope scope(current->GetIsolate());
   8776   v8::Handle<Context> other = Context::New(current->GetIsolate());
   8777 
   8778   // Change context to be able to get to the Object function in the
   8779   // other context without hitting the security checks.
   8780   v8::Local<Value> other_object;
   8781   { Context::Scope scope(other);
   8782     other_object = other->Global()->Get(v8_str("Object"));
   8783     other->Global()->Set(v8_num(42), v8_num(87));
   8784   }
   8785 
   8786   current->Global()->Set(v8_str("other"), other->Global());
   8787   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
   8788 
   8789   // Make sure the security check fails here and we get an undefined
   8790   // result instead of getting the Object function. Repeat in a loop
   8791   // to make sure to exercise the IC code.
   8792   v8::Local<Script> access_other0 = v8_compile("other.Object");
   8793   v8::Local<Script> access_other1 = v8_compile("other[42]");
   8794   for (int i = 0; i < 5; i++) {
   8795     CHECK(access_other0->Run().IsEmpty());
   8796     CHECK(access_other1->Run().IsEmpty());
   8797   }
   8798 
   8799   // Create an object that has 'other' in its prototype chain and make
   8800   // sure we cannot access the Object function indirectly through
   8801   // that. Repeat in a loop to make sure to exercise the IC code.
   8802   v8_compile("function F() { };"
   8803              "F.prototype = other;"
   8804              "var f = new F();")->Run();
   8805   v8::Local<Script> access_f0 = v8_compile("f.Object");
   8806   v8::Local<Script> access_f1 = v8_compile("f[42]");
   8807   for (int j = 0; j < 5; j++) {
   8808     CHECK(access_f0->Run().IsEmpty());
   8809     CHECK(access_f1->Run().IsEmpty());
   8810   }
   8811 
   8812   // Now it gets hairy: Set the prototype for the other global object
   8813   // to be the current global object. The prototype chain for 'f' now
   8814   // goes through 'other' but ends up in the current global object.
   8815   { Context::Scope scope(other);
   8816     other->Global()->Set(v8_str("__proto__"), current->Global());
   8817   }
   8818   // Set a named and an index property on the current global
   8819   // object. To force the lookup to go through the other global object,
   8820   // the properties must not exist in the other global object.
   8821   current->Global()->Set(v8_str("foo"), v8_num(100));
   8822   current->Global()->Set(v8_num(99), v8_num(101));
   8823   // Try to read the properties from f and make sure that the access
   8824   // gets stopped by the security checks on the other global object.
   8825   Local<Script> access_f2 = v8_compile("f.foo");
   8826   Local<Script> access_f3 = v8_compile("f[99]");
   8827   for (int k = 0; k < 5; k++) {
   8828     CHECK(access_f2->Run().IsEmpty());
   8829     CHECK(access_f3->Run().IsEmpty());
   8830   }
   8831 }
   8832 
   8833 
   8834 static bool named_security_check_with_gc_called;
   8835 
   8836 static bool NamedSecurityCallbackWithGC(Local<v8::Object> global,
   8837                                         Local<Value> name,
   8838                                         v8::AccessType type,
   8839                                         Local<Value> data) {
   8840   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   8841   named_security_check_with_gc_called = true;
   8842   return true;
   8843 }
   8844 
   8845 
   8846 static bool indexed_security_check_with_gc_called;
   8847 
   8848 static bool IndexedSecurityTestCallbackWithGC(Local<v8::Object> global,
   8849                                               uint32_t key,
   8850                                               v8::AccessType type,
   8851                                               Local<Value> data) {
   8852   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   8853   indexed_security_check_with_gc_called = true;
   8854   return true;
   8855 }
   8856 
   8857 
   8858 TEST(SecurityTestGCAllowed) {
   8859   v8::Isolate* isolate = CcTest::isolate();
   8860   v8::HandleScope handle_scope(isolate);
   8861   v8::Handle<v8::ObjectTemplate> object_template =
   8862       v8::ObjectTemplate::New(isolate);
   8863   object_template->SetAccessCheckCallbacks(NamedSecurityCallbackWithGC,
   8864                                            IndexedSecurityTestCallbackWithGC);
   8865 
   8866   v8::Handle<Context> context = Context::New(isolate);
   8867   v8::Context::Scope context_scope(context);
   8868 
   8869   context->Global()->Set(v8_str("obj"), object_template->NewInstance());
   8870 
   8871   named_security_check_with_gc_called = false;
   8872   CompileRun("obj.foo = new String(1001);");
   8873   CHECK(named_security_check_with_gc_called);
   8874 
   8875   indexed_security_check_with_gc_called = false;
   8876   CompileRun("obj[0] = new String(1002);");
   8877   CHECK(indexed_security_check_with_gc_called);
   8878 
   8879   named_security_check_with_gc_called = false;
   8880   CHECK(CompileRun("obj.foo")->ToString()->Equals(v8_str("1001")));
   8881   CHECK(named_security_check_with_gc_called);
   8882 
   8883   indexed_security_check_with_gc_called = false;
   8884   CHECK(CompileRun("obj[0]")->ToString()->Equals(v8_str("1002")));
   8885   CHECK(indexed_security_check_with_gc_called);
   8886 }
   8887 
   8888 
   8889 THREADED_TEST(CrossDomainDelete) {
   8890   LocalContext env1;
   8891   v8::HandleScope handle_scope(env1->GetIsolate());
   8892   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8893 
   8894   Local<Value> foo = v8_str("foo");
   8895   Local<Value> bar = v8_str("bar");
   8896 
   8897   // Set to the same domain.
   8898   env1->SetSecurityToken(foo);
   8899   env2->SetSecurityToken(foo);
   8900 
   8901   env1->Global()->Set(v8_str("prop"), v8_num(3));
   8902   env2->Global()->Set(v8_str("env1"), env1->Global());
   8903 
   8904   // Change env2 to a different domain and delete env1.prop.
   8905   env2->SetSecurityToken(bar);
   8906   {
   8907     Context::Scope scope_env2(env2);
   8908     Local<Value> result =
   8909         CompileRun("delete env1.prop");
   8910     CHECK(result.IsEmpty());
   8911   }
   8912 
   8913   // Check that env1.prop still exists.
   8914   Local<Value> v = env1->Global()->Get(v8_str("prop"));
   8915   CHECK(v->IsNumber());
   8916   CHECK_EQ(3, v->Int32Value());
   8917 }
   8918 
   8919 
   8920 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
   8921   LocalContext env1;
   8922   v8::HandleScope handle_scope(env1->GetIsolate());
   8923   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8924 
   8925   Local<Value> foo = v8_str("foo");
   8926   Local<Value> bar = v8_str("bar");
   8927 
   8928   // Set to the same domain.
   8929   env1->SetSecurityToken(foo);
   8930   env2->SetSecurityToken(foo);
   8931 
   8932   env1->Global()->Set(v8_str("prop"), v8_num(3));
   8933   env2->Global()->Set(v8_str("env1"), env1->Global());
   8934 
   8935   // env1.prop is enumerable in env2.
   8936   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
   8937   {
   8938     Context::Scope scope_env2(env2);
   8939     Local<Value> result = CompileRun(test);
   8940     CHECK(result->IsTrue());
   8941   }
   8942 
   8943   // Change env2 to a different domain and test again.
   8944   env2->SetSecurityToken(bar);
   8945   {
   8946     Context::Scope scope_env2(env2);
   8947     Local<Value> result = CompileRun(test);
   8948     CHECK(result.IsEmpty());
   8949   }
   8950 }
   8951 
   8952 
   8953 THREADED_TEST(CrossDomainForIn) {
   8954   LocalContext env1;
   8955   v8::HandleScope handle_scope(env1->GetIsolate());
   8956   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8957 
   8958   Local<Value> foo = v8_str("foo");
   8959   Local<Value> bar = v8_str("bar");
   8960 
   8961   // Set to the same domain.
   8962   env1->SetSecurityToken(foo);
   8963   env2->SetSecurityToken(foo);
   8964 
   8965   env1->Global()->Set(v8_str("prop"), v8_num(3));
   8966   env2->Global()->Set(v8_str("env1"), env1->Global());
   8967 
   8968   // Change env2 to a different domain and set env1's global object
   8969   // as the __proto__ of an object in env2 and enumerate properties
   8970   // in for-in. It shouldn't enumerate properties on env1's global
   8971   // object.
   8972   env2->SetSecurityToken(bar);
   8973   {
   8974     Context::Scope scope_env2(env2);
   8975     Local<Value> result = CompileRun(
   8976         "(function() {"
   8977         "  var obj = { '__proto__': env1 };"
   8978         "  try {"
   8979         "    for (var p in obj) {"
   8980         "      if (p == 'prop') return false;"
   8981         "    }"
   8982         "    return false;"
   8983         "  } catch (e) {"
   8984         "    return true;"
   8985         "  }"
   8986         "})()");
   8987     CHECK(result->IsTrue());
   8988   }
   8989 }
   8990 
   8991 
   8992 TEST(ContextDetachGlobal) {
   8993   LocalContext env1;
   8994   v8::HandleScope handle_scope(env1->GetIsolate());
   8995   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8996 
   8997   Local<v8::Object> global1 = env1->Global();
   8998 
   8999   Local<Value> foo = v8_str("foo");
   9000 
   9001   // Set to the same domain.
   9002   env1->SetSecurityToken(foo);
   9003   env2->SetSecurityToken(foo);
   9004 
   9005   // Enter env2
   9006   env2->Enter();
   9007 
   9008   // Create a function in env2 and add a reference to it in env1.
   9009   Local<v8::Object> global2 = env2->Global();
   9010   global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
   9011   CompileRun("function getProp() {return prop;}");
   9012 
   9013   env1->Global()->Set(v8_str("getProp"),
   9014                       global2->Get(v8_str("getProp")));
   9015 
   9016   // Detach env2's global, and reuse the global object of env2
   9017   env2->Exit();
   9018   env2->DetachGlobal();
   9019 
   9020   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
   9021                                           0,
   9022                                           v8::Handle<v8::ObjectTemplate>(),
   9023                                           global2);
   9024   env3->SetSecurityToken(v8_str("bar"));
   9025   env3->Enter();
   9026 
   9027   Local<v8::Object> global3 = env3->Global();
   9028   CHECK_EQ(global2, global3);
   9029   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
   9030   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
   9031   global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
   9032   global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
   9033   env3->Exit();
   9034 
   9035   // Call getProp in env1, and it should return the value 1
   9036   {
   9037     Local<Value> get_prop = global1->Get(v8_str("getProp"));
   9038     CHECK(get_prop->IsFunction());
   9039     v8::TryCatch try_catch;
   9040     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
   9041     CHECK(!try_catch.HasCaught());
   9042     CHECK_EQ(1, r->Int32Value());
   9043   }
   9044 
   9045   // Check that env3 is not accessible from env1
   9046   {
   9047     Local<Value> r = global3->Get(v8_str("prop2"));
   9048     CHECK(r.IsEmpty());
   9049   }
   9050 }
   9051 
   9052 
   9053 TEST(DetachGlobal) {
   9054   LocalContext env1;
   9055   v8::HandleScope scope(env1->GetIsolate());
   9056 
   9057   // Create second environment.
   9058   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   9059 
   9060   Local<Value> foo = v8_str("foo");
   9061 
   9062   // Set same security token for env1 and env2.
   9063   env1->SetSecurityToken(foo);
   9064   env2->SetSecurityToken(foo);
   9065 
   9066   // Create a property on the global object in env2.
   9067   {
   9068     v8::Context::Scope scope(env2);
   9069     env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
   9070   }
   9071 
   9072   // Create a reference to env2 global from env1 global.
   9073   env1->Global()->Set(v8_str("other"), env2->Global());
   9074 
   9075   // Check that we have access to other.p in env2 from env1.
   9076   Local<Value> result = CompileRun("other.p");
   9077   CHECK(result->IsInt32());
   9078   CHECK_EQ(42, result->Int32Value());
   9079 
   9080   // Hold on to global from env2 and detach global from env2.
   9081   Local<v8::Object> global2 = env2->Global();
   9082   env2->DetachGlobal();
   9083 
   9084   // Check that the global has been detached. No other.p property can
   9085   // be found.
   9086   result = CompileRun("other.p");
   9087   CHECK(result.IsEmpty());
   9088 
   9089   // Reuse global2 for env3.
   9090   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
   9091                                           0,
   9092                                           v8::Handle<v8::ObjectTemplate>(),
   9093                                           global2);
   9094   CHECK_EQ(global2, env3->Global());
   9095 
   9096   // Start by using the same security token for env3 as for env1 and env2.
   9097   env3->SetSecurityToken(foo);
   9098 
   9099   // Create a property on the global object in env3.
   9100   {
   9101     v8::Context::Scope scope(env3);
   9102     env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
   9103   }
   9104 
   9105   // Check that other.p is now the property in env3 and that we have access.
   9106   result = CompileRun("other.p");
   9107   CHECK(result->IsInt32());
   9108   CHECK_EQ(24, result->Int32Value());
   9109 
   9110   // Change security token for env3 to something different from env1 and env2.
   9111   env3->SetSecurityToken(v8_str("bar"));
   9112 
   9113   // Check that we do not have access to other.p in env1. |other| is now
   9114   // the global object for env3 which has a different security token,
   9115   // so access should be blocked.
   9116   result = CompileRun("other.p");
   9117   CHECK(result.IsEmpty());
   9118 }
   9119 
   9120 
   9121 void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
   9122   info.GetReturnValue().Set(
   9123       info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
   9124 }
   9125 
   9126 
   9127 TEST(DetachedAccesses) {
   9128   LocalContext env1;
   9129   v8::HandleScope scope(env1->GetIsolate());
   9130 
   9131   // Create second environment.
   9132   Local<ObjectTemplate> inner_global_template =
   9133       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
   9134   inner_global_template ->SetAccessorProperty(
   9135       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
   9136   v8::Local<Context> env2 =
   9137       Context::New(env1->GetIsolate(), NULL, inner_global_template);
   9138 
   9139   Local<Value> foo = v8_str("foo");
   9140 
   9141   // Set same security token for env1 and env2.
   9142   env1->SetSecurityToken(foo);
   9143   env2->SetSecurityToken(foo);
   9144 
   9145   env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
   9146 
   9147   {
   9148     v8::Context::Scope scope(env2);
   9149     env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
   9150     CompileRun(
   9151         "function bound_x() { return x; }"
   9152         "function get_x()   { return this.x; }"
   9153         "function get_x_w() { return (function() {return this.x;})(); }");
   9154     env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
   9155     env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
   9156     env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
   9157     env1->Global()->Set(
   9158         v8_str("this_x"),
   9159         CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
   9160   }
   9161 
   9162   Local<Object> env2_global = env2->Global();
   9163   env2_global->TurnOnAccessCheck();
   9164   env2->DetachGlobal();
   9165 
   9166   Local<Value> result;
   9167   result = CompileRun("bound_x()");
   9168   CHECK_EQ(v8_str("env2_x"), result);
   9169   result = CompileRun("get_x()");
   9170   CHECK(result.IsEmpty());
   9171   result = CompileRun("get_x_w()");
   9172   CHECK(result.IsEmpty());
   9173   result = CompileRun("this_x()");
   9174   CHECK_EQ(v8_str("env2_x"), result);
   9175 
   9176   // Reattach env2's proxy
   9177   env2 = Context::New(env1->GetIsolate(),
   9178                       0,
   9179                       v8::Handle<v8::ObjectTemplate>(),
   9180                       env2_global);
   9181   env2->SetSecurityToken(foo);
   9182   {
   9183     v8::Context::Scope scope(env2);
   9184     env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
   9185     env2->Global()->Set(v8_str("env1"), env1->Global());
   9186     result = CompileRun(
   9187         "results = [];"
   9188         "for (var i = 0; i < 4; i++ ) {"
   9189         "  results.push(env1.bound_x());"
   9190         "  results.push(env1.get_x());"
   9191         "  results.push(env1.get_x_w());"
   9192         "  results.push(env1.this_x());"
   9193         "}"
   9194         "results");
   9195     Local<v8::Array> results = Local<v8::Array>::Cast(result);
   9196     CHECK_EQ(16, results->Length());
   9197     for (int i = 0; i < 16; i += 4) {
   9198       CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
   9199       CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
   9200       CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
   9201       CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
   9202     }
   9203   }
   9204 
   9205   result = CompileRun(
   9206       "results = [];"
   9207       "for (var i = 0; i < 4; i++ ) {"
   9208       "  results.push(bound_x());"
   9209       "  results.push(get_x());"
   9210       "  results.push(get_x_w());"
   9211       "  results.push(this_x());"
   9212       "}"
   9213       "results");
   9214   Local<v8::Array> results = Local<v8::Array>::Cast(result);
   9215   CHECK_EQ(16, results->Length());
   9216   for (int i = 0; i < 16; i += 4) {
   9217     CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
   9218     CHECK_EQ(v8_str("env3_x"), results->Get(i + 1));
   9219     CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
   9220     CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
   9221   }
   9222 
   9223   result = CompileRun(
   9224       "results = [];"
   9225       "for (var i = 0; i < 4; i++ ) {"
   9226       "  results.push(this.bound_x());"
   9227       "  results.push(this.get_x());"
   9228       "  results.push(this.get_x_w());"
   9229       "  results.push(this.this_x());"
   9230       "}"
   9231       "results");
   9232   results = Local<v8::Array>::Cast(result);
   9233   CHECK_EQ(16, results->Length());
   9234   for (int i = 0; i < 16; i += 4) {
   9235     CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
   9236     CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
   9237     CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
   9238     CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
   9239   }
   9240 }
   9241 
   9242 
   9243 static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
   9244 static bool NamedAccessBlocker(Local<v8::Object> global,
   9245                                Local<Value> name,
   9246                                v8::AccessType type,
   9247                                Local<Value> data) {
   9248   return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
   9249       allowed_access_type[type];
   9250 }
   9251 
   9252 
   9253 static bool IndexedAccessBlocker(Local<v8::Object> global,
   9254                                  uint32_t key,
   9255                                  v8::AccessType type,
   9256                                  Local<Value> data) {
   9257   return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
   9258       allowed_access_type[type];
   9259 }
   9260 
   9261 
   9262 static int g_echo_value = -1;
   9263 
   9264 
   9265 static void EchoGetter(
   9266     Local<String> name,
   9267     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9268   info.GetReturnValue().Set(v8_num(g_echo_value));
   9269 }
   9270 
   9271 
   9272 static void EchoSetter(Local<String> name,
   9273                        Local<Value> value,
   9274                        const v8::PropertyCallbackInfo<void>&) {
   9275   if (value->IsNumber())
   9276     g_echo_value = value->Int32Value();
   9277 }
   9278 
   9279 
   9280 static void UnreachableGetter(
   9281     Local<String> name,
   9282     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9283   CHECK(false);  // This function should not be called..
   9284 }
   9285 
   9286 
   9287 static void UnreachableSetter(Local<String>,
   9288                               Local<Value>,
   9289                               const v8::PropertyCallbackInfo<void>&) {
   9290   CHECK(false);  // This function should nto be called.
   9291 }
   9292 
   9293 
   9294 static void UnreachableFunction(
   9295     const v8::FunctionCallbackInfo<v8::Value>& info) {
   9296   CHECK(false);  // This function should not be called..
   9297 }
   9298 
   9299 
   9300 TEST(AccessControl) {
   9301   v8::Isolate* isolate = CcTest::isolate();
   9302   v8::HandleScope handle_scope(isolate);
   9303   v8::Handle<v8::ObjectTemplate> global_template =
   9304       v8::ObjectTemplate::New(isolate);
   9305 
   9306   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   9307                                            IndexedAccessBlocker);
   9308 
   9309   // Add an accessor accessible by cross-domain JS code.
   9310   global_template->SetAccessor(
   9311       v8_str("accessible_prop"),
   9312       EchoGetter, EchoSetter,
   9313       v8::Handle<Value>(),
   9314       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   9315 
   9316 
   9317   // Add an accessor that is not accessible by cross-domain JS code.
   9318   global_template->SetAccessor(v8_str("blocked_prop"),
   9319                                UnreachableGetter, UnreachableSetter,
   9320                                v8::Handle<Value>(),
   9321                                v8::DEFAULT);
   9322 
   9323   global_template->SetAccessorProperty(
   9324       v8_str("blocked_js_prop"),
   9325       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   9326       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   9327       v8::None,
   9328       v8::DEFAULT);
   9329 
   9330   // Create an environment
   9331   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   9332   context0->Enter();
   9333 
   9334   v8::Handle<v8::Object> global0 = context0->Global();
   9335 
   9336   // Define a property with JS getter and setter.
   9337   CompileRun(
   9338       "function getter() { return 'getter'; };\n"
   9339       "function setter() { return 'setter'; }\n"
   9340       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   9341 
   9342   Local<Value> getter = global0->Get(v8_str("getter"));
   9343   Local<Value> setter = global0->Get(v8_str("setter"));
   9344 
   9345   // And define normal element.
   9346   global0->Set(239, v8_str("239"));
   9347 
   9348   // Define an element with JS getter and setter.
   9349   CompileRun(
   9350       "function el_getter() { return 'el_getter'; };\n"
   9351       "function el_setter() { return 'el_setter'; };\n"
   9352       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   9353 
   9354   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
   9355   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
   9356 
   9357   v8::HandleScope scope1(isolate);
   9358 
   9359   v8::Local<Context> context1 = Context::New(isolate);
   9360   context1->Enter();
   9361 
   9362   v8::Handle<v8::Object> global1 = context1->Global();
   9363   global1->Set(v8_str("other"), global0);
   9364 
   9365   // Access blocked property.
   9366   CompileRun("other.blocked_prop = 1");
   9367 
   9368   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   9369   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   9370             .IsEmpty());
   9371   CHECK(
   9372       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
   9373 
   9374   // Access blocked element.
   9375   CHECK(CompileRun("other[239] = 1").IsEmpty());
   9376 
   9377   CHECK(CompileRun("other[239]").IsEmpty());
   9378   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
   9379   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
   9380 
   9381   // Enable ACCESS_HAS
   9382   allowed_access_type[v8::ACCESS_HAS] = true;
   9383   CHECK(CompileRun("other[239]").IsEmpty());
   9384   // ... and now we can get the descriptor...
   9385   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239').value")
   9386             .IsEmpty());
   9387   // ... and enumerate the property.
   9388   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   9389   allowed_access_type[v8::ACCESS_HAS] = false;
   9390 
   9391   // Access a property with JS accessor.
   9392   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
   9393 
   9394   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
   9395   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
   9396             .IsEmpty());
   9397 
   9398   // Enable both ACCESS_HAS and ACCESS_GET.
   9399   allowed_access_type[v8::ACCESS_HAS] = true;
   9400   allowed_access_type[v8::ACCESS_GET] = true;
   9401 
   9402   ExpectString("other.js_accessor_p", "getter");
   9403   ExpectObject(
   9404       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   9405   ExpectObject(
   9406       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   9407   ExpectUndefined(
   9408       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   9409 
   9410   allowed_access_type[v8::ACCESS_HAS] = false;
   9411   allowed_access_type[v8::ACCESS_GET] = false;
   9412 
   9413   // Access an element with JS accessor.
   9414   CHECK(CompileRun("other[42] = 2").IsEmpty());
   9415 
   9416   CHECK(CompileRun("other[42]").IsEmpty());
   9417   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
   9418 
   9419   // Enable both ACCESS_HAS and ACCESS_GET.
   9420   allowed_access_type[v8::ACCESS_HAS] = true;
   9421   allowed_access_type[v8::ACCESS_GET] = true;
   9422 
   9423   ExpectString("other[42]", "el_getter");
   9424   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   9425   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   9426   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   9427 
   9428   allowed_access_type[v8::ACCESS_HAS] = false;
   9429   allowed_access_type[v8::ACCESS_GET] = false;
   9430 
   9431   v8::Handle<Value> value;
   9432 
   9433   // Access accessible property
   9434   value = CompileRun("other.accessible_prop = 3");
   9435   CHECK(value->IsNumber());
   9436   CHECK_EQ(3, value->Int32Value());
   9437   CHECK_EQ(3, g_echo_value);
   9438 
   9439   value = CompileRun("other.accessible_prop");
   9440   CHECK(value->IsNumber());
   9441   CHECK_EQ(3, value->Int32Value());
   9442 
   9443   value = CompileRun(
   9444       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   9445   CHECK(value->IsNumber());
   9446   CHECK_EQ(3, value->Int32Value());
   9447 
   9448   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   9449   CHECK(value->IsTrue());
   9450 
   9451   // Enumeration doesn't enumerate accessors from inaccessible objects in
   9452   // the prototype chain even if the accessors are in themselves accessible.
   9453   value = CompileRun(
   9454       "(function() {"
   9455       "  var obj = { '__proto__': other };"
   9456       "  try {"
   9457       "    for (var p in obj) {"
   9458       "      if (p == 'accessible_prop' ||"
   9459       "          p == 'blocked_js_prop' ||"
   9460       "          p == 'blocked_js_prop') {"
   9461       "        return false;"
   9462       "      }"
   9463       "    }"
   9464       "    return false;"
   9465       "  } catch (e) {"
   9466       "    return true;"
   9467       "  }"
   9468       "})()");
   9469   CHECK(value->IsTrue());
   9470 
   9471   context1->Exit();
   9472   context0->Exit();
   9473 }
   9474 
   9475 
   9476 TEST(AccessControlES5) {
   9477   v8::Isolate* isolate = CcTest::isolate();
   9478   v8::HandleScope handle_scope(isolate);
   9479   v8::Handle<v8::ObjectTemplate> global_template =
   9480       v8::ObjectTemplate::New(isolate);
   9481 
   9482   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   9483                                            IndexedAccessBlocker);
   9484 
   9485   // Add accessible accessor.
   9486   global_template->SetAccessor(
   9487       v8_str("accessible_prop"),
   9488       EchoGetter, EchoSetter,
   9489       v8::Handle<Value>(),
   9490       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   9491 
   9492 
   9493   // Add an accessor that is not accessible by cross-domain JS code.
   9494   global_template->SetAccessor(v8_str("blocked_prop"),
   9495                                UnreachableGetter, UnreachableSetter,
   9496                                v8::Handle<Value>(),
   9497                                v8::DEFAULT);
   9498 
   9499   // Create an environment
   9500   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   9501   context0->Enter();
   9502 
   9503   v8::Handle<v8::Object> global0 = context0->Global();
   9504 
   9505   v8::Local<Context> context1 = Context::New(isolate);
   9506   context1->Enter();
   9507   v8::Handle<v8::Object> global1 = context1->Global();
   9508   global1->Set(v8_str("other"), global0);
   9509 
   9510   // Regression test for issue 1154.
   9511   CHECK(CompileRun("Object.keys(other)").IsEmpty());
   9512   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   9513 
   9514   // Regression test for issue 1027.
   9515   CompileRun("Object.defineProperty(\n"
   9516              "  other, 'blocked_prop', {configurable: false})");
   9517   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   9518   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   9519             .IsEmpty());
   9520 
   9521   // Regression test for issue 1171.
   9522   ExpectTrue("Object.isExtensible(other)");
   9523   CompileRun("Object.preventExtensions(other)");
   9524   ExpectTrue("Object.isExtensible(other)");
   9525 
   9526   // Object.seal and Object.freeze.
   9527   CompileRun("Object.freeze(other)");
   9528   ExpectTrue("Object.isExtensible(other)");
   9529 
   9530   CompileRun("Object.seal(other)");
   9531   ExpectTrue("Object.isExtensible(other)");
   9532 
   9533   // Regression test for issue 1250.
   9534   // Make sure that we can set the accessible accessors value using normal
   9535   // assignment.
   9536   CompileRun("other.accessible_prop = 42");
   9537   CHECK_EQ(42, g_echo_value);
   9538 
   9539   v8::Handle<Value> value;
   9540   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
   9541   value = CompileRun("other.accessible_prop == 42");
   9542   CHECK(value->IsTrue());
   9543 }
   9544 
   9545 
   9546 static bool BlockEverythingNamed(Local<v8::Object> object, Local<Value> name,
   9547                                  v8::AccessType type, Local<Value> data) {
   9548   return false;
   9549 }
   9550 
   9551 
   9552 static bool BlockEverythingIndexed(Local<v8::Object> object, uint32_t key,
   9553                                    v8::AccessType type, Local<Value> data) {
   9554   return false;
   9555 }
   9556 
   9557 
   9558 THREADED_TEST(AccessControlGetOwnPropertyNames) {
   9559   v8::Isolate* isolate = CcTest::isolate();
   9560   v8::HandleScope handle_scope(isolate);
   9561   v8::Handle<v8::ObjectTemplate> obj_template =
   9562       v8::ObjectTemplate::New(isolate);
   9563 
   9564   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   9565   obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
   9566                                         BlockEverythingIndexed);
   9567 
   9568   // Create an environment
   9569   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
   9570   context0->Enter();
   9571 
   9572   v8::Handle<v8::Object> global0 = context0->Global();
   9573 
   9574   v8::HandleScope scope1(CcTest::isolate());
   9575 
   9576   v8::Local<Context> context1 = Context::New(isolate);
   9577   context1->Enter();
   9578 
   9579   v8::Handle<v8::Object> global1 = context1->Global();
   9580   global1->Set(v8_str("other"), global0);
   9581   global1->Set(v8_str("object"), obj_template->NewInstance());
   9582 
   9583   v8::Handle<Value> value;
   9584 
   9585   // Attempt to get the property names of the other global object and
   9586   // of an object that requires access checks.  Accessing the other
   9587   // global object should be blocked by access checks on the global
   9588   // proxy object.  Accessing the object that requires access checks
   9589   // is blocked by the access checks on the object itself.
   9590   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
   9591   CHECK(value.IsEmpty());
   9592 
   9593   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
   9594   CHECK(value.IsEmpty());
   9595 
   9596   context1->Exit();
   9597   context0->Exit();
   9598 }
   9599 
   9600 
   9601 TEST(SuperAccessControl) {
   9602   i::FLAG_harmony_classes = true;
   9603   v8::Isolate* isolate = CcTest::isolate();
   9604   v8::HandleScope handle_scope(isolate);
   9605   v8::Handle<v8::ObjectTemplate> obj_template =
   9606       v8::ObjectTemplate::New(isolate);
   9607   obj_template->SetAccessCheckCallbacks(BlockEverythingNamed,
   9608                                         BlockEverythingIndexed);
   9609   LocalContext env;
   9610   env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
   9611 
   9612   v8::TryCatch try_catch;
   9613   CompileRun(
   9614       "function f() { return super.hasOwnProperty; };"
   9615       "var m = f.toMethod(prohibited);"
   9616       "m();");
   9617   CHECK(try_catch.HasCaught());
   9618 }
   9619 
   9620 
   9621 static void IndexedPropertyEnumerator(
   9622     const v8::PropertyCallbackInfo<v8::Array>& info) {
   9623   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
   9624   result->Set(0, v8::Integer::New(info.GetIsolate(), 7));
   9625   result->Set(1, v8::Object::New(info.GetIsolate()));
   9626   info.GetReturnValue().Set(result);
   9627 }
   9628 
   9629 
   9630 static void NamedPropertyEnumerator(
   9631     const v8::PropertyCallbackInfo<v8::Array>& info) {
   9632   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
   9633   result->Set(0, v8_str("x"));
   9634   result->Set(1, v8::Object::New(info.GetIsolate()));
   9635   info.GetReturnValue().Set(result);
   9636 }
   9637 
   9638 
   9639 THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
   9640   v8::Isolate* isolate = CcTest::isolate();
   9641   v8::HandleScope handle_scope(isolate);
   9642   v8::Handle<v8::ObjectTemplate> obj_template =
   9643       v8::ObjectTemplate::New(isolate);
   9644 
   9645   obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
   9646   obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
   9647   obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
   9648                                           IndexedPropertyEnumerator);
   9649   obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
   9650                                         NamedPropertyEnumerator);
   9651 
   9652   LocalContext context;
   9653   v8::Handle<v8::Object> global = context->Global();
   9654   global->Set(v8_str("object"), obj_template->NewInstance());
   9655 
   9656   v8::Handle<v8::Value> result =
   9657       CompileRun("Object.getOwnPropertyNames(object)");
   9658   CHECK(result->IsArray());
   9659   v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
   9660   CHECK_EQ(3, result_array->Length());
   9661   CHECK(result_array->Get(0)->IsString());
   9662   CHECK(result_array->Get(1)->IsString());
   9663   CHECK(result_array->Get(2)->IsString());
   9664   CHECK_EQ(v8_str("7"), result_array->Get(0));
   9665   CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
   9666   CHECK_EQ(v8_str("x"), result_array->Get(2));
   9667 }
   9668 
   9669 
   9670 static void ConstTenGetter(Local<String> name,
   9671                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   9672   info.GetReturnValue().Set(v8_num(10));
   9673 }
   9674 
   9675 
   9676 THREADED_TEST(CrossDomainAccessors) {
   9677   v8::Isolate* isolate = CcTest::isolate();
   9678   v8::HandleScope handle_scope(isolate);
   9679 
   9680   v8::Handle<v8::FunctionTemplate> func_template =
   9681       v8::FunctionTemplate::New(isolate);
   9682 
   9683   v8::Handle<v8::ObjectTemplate> global_template =
   9684       func_template->InstanceTemplate();
   9685 
   9686   v8::Handle<v8::ObjectTemplate> proto_template =
   9687       func_template->PrototypeTemplate();
   9688 
   9689   // Add an accessor to proto that's accessible by cross-domain JS code.
   9690   proto_template->SetAccessor(v8_str("accessible"),
   9691                               ConstTenGetter, 0,
   9692                               v8::Handle<Value>(),
   9693                               v8::ALL_CAN_READ);
   9694 
   9695   // Add an accessor that is not accessible by cross-domain JS code.
   9696   global_template->SetAccessor(v8_str("unreachable"),
   9697                                UnreachableGetter, 0,
   9698                                v8::Handle<Value>(),
   9699                                v8::DEFAULT);
   9700 
   9701   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   9702   context0->Enter();
   9703 
   9704   Local<v8::Object> global = context0->Global();
   9705   // Add a normal property that shadows 'accessible'
   9706   global->Set(v8_str("accessible"), v8_num(11));
   9707 
   9708   // Enter a new context.
   9709   v8::HandleScope scope1(CcTest::isolate());
   9710   v8::Local<Context> context1 = Context::New(isolate);
   9711   context1->Enter();
   9712 
   9713   v8::Handle<v8::Object> global1 = context1->Global();
   9714   global1->Set(v8_str("other"), global);
   9715 
   9716   // Should return 10, instead of 11
   9717   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
   9718   CHECK(value->IsNumber());
   9719   CHECK_EQ(10, value->Int32Value());
   9720 
   9721   value = v8_compile("other.unreachable")->Run();
   9722   CHECK(value.IsEmpty());
   9723 
   9724   context1->Exit();
   9725   context0->Exit();
   9726 }
   9727 
   9728 
   9729 static int named_access_count = 0;
   9730 static int indexed_access_count = 0;
   9731 
   9732 static bool NamedAccessCounter(Local<v8::Object> global,
   9733                                Local<Value> name,
   9734                                v8::AccessType type,
   9735                                Local<Value> data) {
   9736   named_access_count++;
   9737   return true;
   9738 }
   9739 
   9740 
   9741 static bool IndexedAccessCounter(Local<v8::Object> global,
   9742                                  uint32_t key,
   9743                                  v8::AccessType type,
   9744                                  Local<Value> data) {
   9745   indexed_access_count++;
   9746   return true;
   9747 }
   9748 
   9749 
   9750 // This one is too easily disturbed by other tests.
   9751 TEST(AccessControlIC) {
   9752   named_access_count = 0;
   9753   indexed_access_count = 0;
   9754 
   9755   v8::Isolate* isolate = CcTest::isolate();
   9756   v8::HandleScope handle_scope(isolate);
   9757 
   9758   // Create an environment.
   9759   v8::Local<Context> context0 = Context::New(isolate);
   9760   context0->Enter();
   9761 
   9762   // Create an object that requires access-check functions to be
   9763   // called for cross-domain access.
   9764   v8::Handle<v8::ObjectTemplate> object_template =
   9765       v8::ObjectTemplate::New(isolate);
   9766   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   9767                                            IndexedAccessCounter);
   9768   Local<v8::Object> object = object_template->NewInstance();
   9769 
   9770   v8::HandleScope scope1(isolate);
   9771 
   9772   // Create another environment.
   9773   v8::Local<Context> context1 = Context::New(isolate);
   9774   context1->Enter();
   9775 
   9776   // Make easy access to the object from the other environment.
   9777   v8::Handle<v8::Object> global1 = context1->Global();
   9778   global1->Set(v8_str("obj"), object);
   9779 
   9780   v8::Handle<Value> value;
   9781 
   9782   // Check that the named access-control function is called every time.
   9783   CompileRun("function testProp(obj) {"
   9784              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   9785              "  for (var j = 0; j < 10; j++) obj.prop;"
   9786              "  return obj.prop"
   9787              "}");
   9788   value = CompileRun("testProp(obj)");
   9789   CHECK(value->IsNumber());
   9790   CHECK_EQ(1, value->Int32Value());
   9791   CHECK_EQ(21, named_access_count);
   9792 
   9793   // Check that the named access-control function is called every time.
   9794   CompileRun("var p = 'prop';"
   9795              "function testKeyed(obj) {"
   9796              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   9797              "  for (var j = 0; j < 10; j++) obj[p];"
   9798              "  return obj[p];"
   9799              "}");
   9800   // Use obj which requires access checks.  No inline caching is used
   9801   // in that case.
   9802   value = CompileRun("testKeyed(obj)");
   9803   CHECK(value->IsNumber());
   9804   CHECK_EQ(1, value->Int32Value());
   9805   CHECK_EQ(42, named_access_count);
   9806   // Force the inline caches into generic state and try again.
   9807   CompileRun("testKeyed({ a: 0 })");
   9808   CompileRun("testKeyed({ b: 0 })");
   9809   value = CompileRun("testKeyed(obj)");
   9810   CHECK(value->IsNumber());
   9811   CHECK_EQ(1, value->Int32Value());
   9812   CHECK_EQ(63, named_access_count);
   9813 
   9814   // Check that the indexed access-control function is called every time.
   9815   CompileRun("function testIndexed(obj) {"
   9816              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   9817              "  for (var j = 0; j < 10; j++) obj[0];"
   9818              "  return obj[0]"
   9819              "}");
   9820   value = CompileRun("testIndexed(obj)");
   9821   CHECK(value->IsNumber());
   9822   CHECK_EQ(1, value->Int32Value());
   9823   CHECK_EQ(21, indexed_access_count);
   9824   // Force the inline caches into generic state.
   9825   CompileRun("testIndexed(new Array(1))");
   9826   // Test that the indexed access check is called.
   9827   value = CompileRun("testIndexed(obj)");
   9828   CHECK(value->IsNumber());
   9829   CHECK_EQ(1, value->Int32Value());
   9830   CHECK_EQ(42, indexed_access_count);
   9831 
   9832   // Check that the named access check is called when invoking
   9833   // functions on an object that requires access checks.
   9834   CompileRun("obj.f = function() {}");
   9835   CompileRun("function testCallNormal(obj) {"
   9836              "  for (var i = 0; i < 10; i++) obj.f();"
   9837              "}");
   9838   CompileRun("testCallNormal(obj)");
   9839   CHECK_EQ(74, named_access_count);
   9840 
   9841   // Force obj into slow case.
   9842   value = CompileRun("delete obj.prop");
   9843   CHECK(value->BooleanValue());
   9844   // Force inline caches into dictionary probing mode.
   9845   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   9846   // Test that the named access check is called.
   9847   value = CompileRun("testProp(obj);");
   9848   CHECK(value->IsNumber());
   9849   CHECK_EQ(1, value->Int32Value());
   9850   CHECK_EQ(96, named_access_count);
   9851 
   9852   // Force the call inline cache into dictionary probing mode.
   9853   CompileRun("o.f = function() {}; testCallNormal(o)");
   9854   // Test that the named access check is still called for each
   9855   // invocation of the function.
   9856   value = CompileRun("testCallNormal(obj)");
   9857   CHECK_EQ(106, named_access_count);
   9858 
   9859   context1->Exit();
   9860   context0->Exit();
   9861 }
   9862 
   9863 
   9864 static bool NamedAccessFlatten(Local<v8::Object> global,
   9865                                Local<Value> name,
   9866                                v8::AccessType type,
   9867                                Local<Value> data) {
   9868   char buf[100];
   9869   int len;
   9870 
   9871   CHECK(name->IsString());
   9872 
   9873   memset(buf, 0x1, sizeof(buf));
   9874   len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   9875   CHECK_EQ(4, len);
   9876 
   9877   uint16_t buf2[100];
   9878 
   9879   memset(buf, 0x1, sizeof(buf));
   9880   len = name.As<String>()->Write(buf2);
   9881   CHECK_EQ(4, len);
   9882 
   9883   return true;
   9884 }
   9885 
   9886 
   9887 static bool IndexedAccessFlatten(Local<v8::Object> global,
   9888                                  uint32_t key,
   9889                                  v8::AccessType type,
   9890                                  Local<Value> data) {
   9891   return true;
   9892 }
   9893 
   9894 
   9895 // Regression test.  In access checks, operations that may cause
   9896 // garbage collection are not allowed.  It used to be the case that
   9897 // using the Write operation on a string could cause a garbage
   9898 // collection due to flattening of the string.  This is no longer the
   9899 // case.
   9900 THREADED_TEST(AccessControlFlatten) {
   9901   named_access_count = 0;
   9902   indexed_access_count = 0;
   9903 
   9904   v8::Isolate* isolate = CcTest::isolate();
   9905   v8::HandleScope handle_scope(isolate);
   9906 
   9907   // Create an environment.
   9908   v8::Local<Context> context0 = Context::New(isolate);
   9909   context0->Enter();
   9910 
   9911   // Create an object that requires access-check functions to be
   9912   // called for cross-domain access.
   9913   v8::Handle<v8::ObjectTemplate> object_template =
   9914       v8::ObjectTemplate::New(isolate);
   9915   object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
   9916                                            IndexedAccessFlatten);
   9917   Local<v8::Object> object = object_template->NewInstance();
   9918 
   9919   v8::HandleScope scope1(isolate);
   9920 
   9921   // Create another environment.
   9922   v8::Local<Context> context1 = Context::New(isolate);
   9923   context1->Enter();
   9924 
   9925   // Make easy access to the object from the other environment.
   9926   v8::Handle<v8::Object> global1 = context1->Global();
   9927   global1->Set(v8_str("obj"), object);
   9928 
   9929   v8::Handle<Value> value;
   9930 
   9931   value = v8_compile("var p = 'as' + 'df';")->Run();
   9932   value = v8_compile("obj[p];")->Run();
   9933 
   9934   context1->Exit();
   9935   context0->Exit();
   9936 }
   9937 
   9938 
   9939 static void AccessControlNamedGetter(
   9940     Local<String>,
   9941     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9942   info.GetReturnValue().Set(42);
   9943 }
   9944 
   9945 
   9946 static void AccessControlNamedSetter(
   9947     Local<String>,
   9948     Local<Value> value,
   9949     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9950   info.GetReturnValue().Set(value);
   9951 }
   9952 
   9953 
   9954 static void AccessControlIndexedGetter(
   9955       uint32_t index,
   9956       const v8::PropertyCallbackInfo<v8::Value>& info) {
   9957   info.GetReturnValue().Set(v8_num(42));
   9958 }
   9959 
   9960 
   9961 static void AccessControlIndexedSetter(
   9962     uint32_t,
   9963     Local<Value> value,
   9964     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9965   info.GetReturnValue().Set(value);
   9966 }
   9967 
   9968 
   9969 THREADED_TEST(AccessControlInterceptorIC) {
   9970   named_access_count = 0;
   9971   indexed_access_count = 0;
   9972 
   9973   v8::Isolate* isolate = CcTest::isolate();
   9974   v8::HandleScope handle_scope(isolate);
   9975 
   9976   // Create an environment.
   9977   v8::Local<Context> context0 = Context::New(isolate);
   9978   context0->Enter();
   9979 
   9980   // Create an object that requires access-check functions to be
   9981   // called for cross-domain access.  The object also has interceptors
   9982   // interceptor.
   9983   v8::Handle<v8::ObjectTemplate> object_template =
   9984       v8::ObjectTemplate::New(isolate);
   9985   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   9986                                            IndexedAccessCounter);
   9987   object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
   9988                                            AccessControlNamedSetter);
   9989   object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
   9990                                              AccessControlIndexedSetter);
   9991   Local<v8::Object> object = object_template->NewInstance();
   9992 
   9993   v8::HandleScope scope1(isolate);
   9994 
   9995   // Create another environment.
   9996   v8::Local<Context> context1 = Context::New(isolate);
   9997   context1->Enter();
   9998 
   9999   // Make easy access to the object from the other environment.
   10000   v8::Handle<v8::Object> global1 = context1->Global();
   10001   global1->Set(v8_str("obj"), object);
   10002 
   10003   v8::Handle<Value> value;
   10004 
   10005   // Check that the named access-control function is called every time
   10006   // eventhough there is an interceptor on the object.
   10007   value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
   10008   value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
   10009                      "obj.x")->Run();
   10010   CHECK(value->IsNumber());
   10011   CHECK_EQ(42, value->Int32Value());
   10012   CHECK_EQ(21, named_access_count);
   10013 
   10014   value = v8_compile("var p = 'x';")->Run();
   10015   value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
   10016   value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
   10017                      "obj[p]")->Run();
   10018   CHECK(value->IsNumber());
   10019   CHECK_EQ(42, value->Int32Value());
   10020   CHECK_EQ(42, named_access_count);
   10021 
   10022   // Check that the indexed access-control function is called every
   10023   // time eventhough there is an interceptor on the object.
   10024   value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
   10025   value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
   10026                      "obj[0]")->Run();
   10027   CHECK(value->IsNumber());
   10028   CHECK_EQ(42, value->Int32Value());
   10029   CHECK_EQ(21, indexed_access_count);
   10030 
   10031   context1->Exit();
   10032   context0->Exit();
   10033 }
   10034 
   10035 
   10036 THREADED_TEST(Version) {
   10037   v8::V8::GetVersion();
   10038 }
   10039 
   10040 
   10041 static void InstanceFunctionCallback(
   10042     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10043   ApiTestFuzzer::Fuzz();
   10044   args.GetReturnValue().Set(v8_num(12));
   10045 }
   10046 
   10047 
   10048 THREADED_TEST(InstanceProperties) {
   10049   LocalContext context;
   10050   v8::Isolate* isolate = context->GetIsolate();
   10051   v8::HandleScope handle_scope(isolate);
   10052 
   10053   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10054   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10055 
   10056   instance->Set(v8_str("x"), v8_num(42));
   10057   instance->Set(v8_str("f"),
   10058                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
   10059 
   10060   Local<Value> o = t->GetFunction()->NewInstance();
   10061 
   10062   context->Global()->Set(v8_str("i"), o);
   10063   Local<Value> value = CompileRun("i.x");
   10064   CHECK_EQ(42, value->Int32Value());
   10065 
   10066   value = CompileRun("i.f()");
   10067   CHECK_EQ(12, value->Int32Value());
   10068 }
   10069 
   10070 
   10071 static void GlobalObjectInstancePropertiesGet(
   10072     Local<String> key,
   10073     const v8::PropertyCallbackInfo<v8::Value>&) {
   10074   ApiTestFuzzer::Fuzz();
   10075 }
   10076 
   10077 
   10078 THREADED_TEST(GlobalObjectInstanceProperties) {
   10079   v8::Isolate* isolate = CcTest::isolate();
   10080   v8::HandleScope handle_scope(isolate);
   10081 
   10082   Local<Value> global_object;
   10083 
   10084   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10085   t->InstanceTemplate()->SetNamedPropertyHandler(
   10086       GlobalObjectInstancePropertiesGet);
   10087   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10088   instance_template->Set(v8_str("x"), v8_num(42));
   10089   instance_template->Set(v8_str("f"),
   10090                          v8::FunctionTemplate::New(isolate,
   10091                                                    InstanceFunctionCallback));
   10092 
   10093   // The script to check how Crankshaft compiles missing global function
   10094   // invocations.  function g is not defined and should throw on call.
   10095   const char* script =
   10096       "function wrapper(call) {"
   10097       "  var x = 0, y = 1;"
   10098       "  for (var i = 0; i < 1000; i++) {"
   10099       "    x += i * 100;"
   10100       "    y += i * 100;"
   10101       "  }"
   10102       "  if (call) g();"
   10103       "}"
   10104       "for (var i = 0; i < 17; i++) wrapper(false);"
   10105       "var thrown = 0;"
   10106       "try { wrapper(true); } catch (e) { thrown = 1; };"
   10107       "thrown";
   10108 
   10109   {
   10110     LocalContext env(NULL, instance_template);
   10111     // Hold on to the global object so it can be used again in another
   10112     // environment initialization.
   10113     global_object = env->Global();
   10114 
   10115     Local<Value> value = CompileRun("x");
   10116     CHECK_EQ(42, value->Int32Value());
   10117     value = CompileRun("f()");
   10118     CHECK_EQ(12, value->Int32Value());
   10119     value = CompileRun(script);
   10120     CHECK_EQ(1, value->Int32Value());
   10121   }
   10122 
   10123   {
   10124     // Create new environment reusing the global object.
   10125     LocalContext env(NULL, instance_template, global_object);
   10126     Local<Value> value = CompileRun("x");
   10127     CHECK_EQ(42, value->Int32Value());
   10128     value = CompileRun("f()");
   10129     CHECK_EQ(12, value->Int32Value());
   10130     value = CompileRun(script);
   10131     CHECK_EQ(1, value->Int32Value());
   10132   }
   10133 }
   10134 
   10135 
   10136 THREADED_TEST(CallKnownGlobalReceiver) {
   10137   v8::Isolate* isolate = CcTest::isolate();
   10138   v8::HandleScope handle_scope(isolate);
   10139 
   10140   Local<Value> global_object;
   10141 
   10142   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10143   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10144 
   10145   // The script to check that we leave global object not
   10146   // global object proxy on stack when we deoptimize from inside
   10147   // arguments evaluation.
   10148   // To provoke error we need to both force deoptimization
   10149   // from arguments evaluation and to force CallIC to take
   10150   // CallIC_Miss code path that can't cope with global proxy.
   10151   const char* script =
   10152       "function bar(x, y) { try { } finally { } }"
   10153       "function baz(x) { try { } finally { } }"
   10154       "function bom(x) { try { } finally { } }"
   10155       "function foo(x) { bar([x], bom(2)); }"
   10156       "for (var i = 0; i < 10000; i++) foo(1);"
   10157       "foo";
   10158 
   10159   Local<Value> foo;
   10160   {
   10161     LocalContext env(NULL, instance_template);
   10162     // Hold on to the global object so it can be used again in another
   10163     // environment initialization.
   10164     global_object = env->Global();
   10165     foo = CompileRun(script);
   10166   }
   10167 
   10168   {
   10169     // Create new environment reusing the global object.
   10170     LocalContext env(NULL, instance_template, global_object);
   10171     env->Global()->Set(v8_str("foo"), foo);
   10172     CompileRun("foo()");
   10173   }
   10174 }
   10175 
   10176 
   10177 static void ShadowFunctionCallback(
   10178     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10179   ApiTestFuzzer::Fuzz();
   10180   args.GetReturnValue().Set(v8_num(42));
   10181 }
   10182 
   10183 
   10184 static int shadow_y;
   10185 static int shadow_y_setter_call_count;
   10186 static int shadow_y_getter_call_count;
   10187 
   10188 
   10189 static void ShadowYSetter(Local<String>,
   10190                           Local<Value>,
   10191                           const v8::PropertyCallbackInfo<void>&) {
   10192   shadow_y_setter_call_count++;
   10193   shadow_y = 42;
   10194 }
   10195 
   10196 
   10197 static void ShadowYGetter(Local<String> name,
   10198                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   10199   ApiTestFuzzer::Fuzz();
   10200   shadow_y_getter_call_count++;
   10201   info.GetReturnValue().Set(v8_num(shadow_y));
   10202 }
   10203 
   10204 
   10205 static void ShadowIndexedGet(uint32_t index,
   10206                              const v8::PropertyCallbackInfo<v8::Value>&) {
   10207 }
   10208 
   10209 
   10210 static void ShadowNamedGet(Local<String> key,
   10211                            const v8::PropertyCallbackInfo<v8::Value>&) {
   10212 }
   10213 
   10214 
   10215 THREADED_TEST(ShadowObject) {
   10216   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   10217   v8::Isolate* isolate = CcTest::isolate();
   10218   v8::HandleScope handle_scope(isolate);
   10219 
   10220   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   10221   LocalContext context(NULL, global_template);
   10222 
   10223   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10224   t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
   10225   t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
   10226   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   10227   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10228 
   10229   proto->Set(v8_str("f"),
   10230              v8::FunctionTemplate::New(isolate,
   10231                                        ShadowFunctionCallback,
   10232                                        Local<Value>()));
   10233   proto->Set(v8_str("x"), v8_num(12));
   10234 
   10235   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   10236 
   10237   Local<Value> o = t->GetFunction()->NewInstance();
   10238   context->Global()->Set(v8_str("__proto__"), o);
   10239 
   10240   Local<Value> value =
   10241       CompileRun("this.propertyIsEnumerable(0)");
   10242   CHECK(value->IsBoolean());
   10243   CHECK(!value->BooleanValue());
   10244 
   10245   value = CompileRun("x");
   10246   CHECK_EQ(12, value->Int32Value());
   10247 
   10248   value = CompileRun("f()");
   10249   CHECK_EQ(42, value->Int32Value());
   10250 
   10251   CompileRun("y = 43");
   10252   CHECK_EQ(1, shadow_y_setter_call_count);
   10253   value = CompileRun("y");
   10254   CHECK_EQ(1, shadow_y_getter_call_count);
   10255   CHECK_EQ(42, value->Int32Value());
   10256 }
   10257 
   10258 
   10259 THREADED_TEST(HiddenPrototype) {
   10260   LocalContext context;
   10261   v8::Isolate* isolate = context->GetIsolate();
   10262   v8::HandleScope handle_scope(isolate);
   10263 
   10264   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   10265   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10266   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10267   t1->SetHiddenPrototype(true);
   10268   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   10269   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10270   t2->SetHiddenPrototype(true);
   10271   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   10272   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10273   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   10274 
   10275   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   10276   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   10277   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   10278   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   10279 
   10280   // Setting the prototype on an object skips hidden prototypes.
   10281   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   10282   o0->Set(v8_str("__proto__"), o1);
   10283   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   10284   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   10285   o0->Set(v8_str("__proto__"), o2);
   10286   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   10287   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   10288   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   10289   o0->Set(v8_str("__proto__"), o3);
   10290   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   10291   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   10292   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   10293   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   10294 
   10295   // Getting the prototype of o0 should get the first visible one
   10296   // which is o3.  Therefore, z should not be defined on the prototype
   10297   // object.
   10298   Local<Value> proto = o0->Get(v8_str("__proto__"));
   10299   CHECK(proto->IsObject());
   10300   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
   10301 }
   10302 
   10303 
   10304 THREADED_TEST(HiddenPrototypeSet) {
   10305   LocalContext context;
   10306   v8::Isolate* isolate = context->GetIsolate();
   10307   v8::HandleScope handle_scope(isolate);
   10308 
   10309   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
   10310   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
   10311   ht->SetHiddenPrototype(true);
   10312   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
   10313   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10314 
   10315   Local<v8::Object> o = ot->GetFunction()->NewInstance();
   10316   Local<v8::Object> h = ht->GetFunction()->NewInstance();
   10317   Local<v8::Object> p = pt->GetFunction()->NewInstance();
   10318   o->Set(v8_str("__proto__"), h);
   10319   h->Set(v8_str("__proto__"), p);
   10320 
   10321   // Setting a property that exists on the hidden prototype goes there.
   10322   o->Set(v8_str("x"), v8_num(7));
   10323   CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
   10324   CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
   10325   CHECK(p->Get(v8_str("x"))->IsUndefined());
   10326 
   10327   // Setting a new property should not be forwarded to the hidden prototype.
   10328   o->Set(v8_str("y"), v8_num(6));
   10329   CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
   10330   CHECK(h->Get(v8_str("y"))->IsUndefined());
   10331   CHECK(p->Get(v8_str("y"))->IsUndefined());
   10332 
   10333   // Setting a property that only exists on a prototype of the hidden prototype
   10334   // is treated normally again.
   10335   p->Set(v8_str("z"), v8_num(8));
   10336   CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
   10337   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
   10338   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
   10339   o->Set(v8_str("z"), v8_num(9));
   10340   CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
   10341   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
   10342   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
   10343 }
   10344 
   10345 
   10346 // Regression test for issue 2457.
   10347 THREADED_TEST(HiddenPrototypeIdentityHash) {
   10348   LocalContext context;
   10349   v8::HandleScope handle_scope(context->GetIsolate());
   10350 
   10351   Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
   10352   t->SetHiddenPrototype(true);
   10353   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
   10354   Handle<Object> p = t->GetFunction()->NewInstance();
   10355   Handle<Object> o = Object::New(context->GetIsolate());
   10356   o->SetPrototype(p);
   10357 
   10358   int hash = o->GetIdentityHash();
   10359   USE(hash);
   10360   o->Set(v8_str("foo"), v8_num(42));
   10361   DCHECK_EQ(hash, o->GetIdentityHash());
   10362 }
   10363 
   10364 
   10365 THREADED_TEST(SetPrototype) {
   10366   LocalContext context;
   10367   v8::Isolate* isolate = context->GetIsolate();
   10368   v8::HandleScope handle_scope(isolate);
   10369 
   10370   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   10371   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10372   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10373   t1->SetHiddenPrototype(true);
   10374   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   10375   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10376   t2->SetHiddenPrototype(true);
   10377   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   10378   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10379   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   10380 
   10381   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   10382   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   10383   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   10384   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   10385 
   10386   // Setting the prototype on an object does not skip hidden prototypes.
   10387   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   10388   CHECK(o0->SetPrototype(o1));
   10389   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   10390   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   10391   CHECK(o1->SetPrototype(o2));
   10392   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   10393   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   10394   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   10395   CHECK(o2->SetPrototype(o3));
   10396   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   10397   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   10398   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   10399   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   10400 
   10401   // Getting the prototype of o0 should get the first visible one
   10402   // which is o3.  Therefore, z should not be defined on the prototype
   10403   // object.
   10404   Local<Value> proto = o0->Get(v8_str("__proto__"));
   10405   CHECK(proto->IsObject());
   10406   CHECK_EQ(proto.As<v8::Object>(), o3);
   10407 
   10408   // However, Object::GetPrototype ignores hidden prototype.
   10409   Local<Value> proto0 = o0->GetPrototype();
   10410   CHECK(proto0->IsObject());
   10411   CHECK_EQ(proto0.As<v8::Object>(), o1);
   10412 
   10413   Local<Value> proto1 = o1->GetPrototype();
   10414   CHECK(proto1->IsObject());
   10415   CHECK_EQ(proto1.As<v8::Object>(), o2);
   10416 
   10417   Local<Value> proto2 = o2->GetPrototype();
   10418   CHECK(proto2->IsObject());
   10419   CHECK_EQ(proto2.As<v8::Object>(), o3);
   10420 }
   10421 
   10422 
   10423 // Getting property names of an object with a prototype chain that
   10424 // triggers dictionary elements in GetOwnPropertyNames() shouldn't
   10425 // crash the runtime.
   10426 THREADED_TEST(Regress91517) {
   10427   i::FLAG_allow_natives_syntax = true;
   10428   LocalContext context;
   10429   v8::Isolate* isolate = context->GetIsolate();
   10430   v8::HandleScope handle_scope(isolate);
   10431 
   10432   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10433   t1->SetHiddenPrototype(true);
   10434   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   10435   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10436   t2->SetHiddenPrototype(true);
   10437   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   10438   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
   10439   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   10440   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10441   t3->SetHiddenPrototype(true);
   10442   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   10443   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
   10444   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   10445 
   10446   // Force dictionary-based properties.
   10447   i::ScopedVector<char> name_buf(1024);
   10448   for (int i = 1; i <= 1000; i++) {
   10449     i::SNPrintF(name_buf, "sdf%d", i);
   10450     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   10451   }
   10452 
   10453   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   10454   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   10455   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   10456   Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
   10457 
   10458   // Create prototype chain of hidden prototypes.
   10459   CHECK(o4->SetPrototype(o3));
   10460   CHECK(o3->SetPrototype(o2));
   10461   CHECK(o2->SetPrototype(o1));
   10462 
   10463   // Call the runtime version of GetOwnPropertyNames() on the natively
   10464   // created object through JavaScript.
   10465   context->Global()->Set(v8_str("obj"), o4);
   10466   // PROPERTY_ATTRIBUTES_NONE = 0
   10467   CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
   10468 
   10469   ExpectInt32("names.length", 1006);
   10470   ExpectTrue("names.indexOf(\"baz\") >= 0");
   10471   ExpectTrue("names.indexOf(\"boo\") >= 0");
   10472   ExpectTrue("names.indexOf(\"foo\") >= 0");
   10473   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
   10474   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
   10475   ExpectFalse("names[1005] == undefined");
   10476 }
   10477 
   10478 
   10479 // Getting property names of an object with a hidden and inherited
   10480 // prototype should not duplicate the accessor properties inherited.
   10481 THREADED_TEST(Regress269562) {
   10482   i::FLAG_allow_natives_syntax = true;
   10483   LocalContext context;
   10484   v8::HandleScope handle_scope(context->GetIsolate());
   10485 
   10486   Local<v8::FunctionTemplate> t1 =
   10487       v8::FunctionTemplate::New(context->GetIsolate());
   10488   t1->SetHiddenPrototype(true);
   10489 
   10490   Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
   10491   i1->SetAccessor(v8_str("foo"),
   10492                   SimpleAccessorGetter, SimpleAccessorSetter);
   10493   i1->SetAccessor(v8_str("bar"),
   10494                   SimpleAccessorGetter, SimpleAccessorSetter);
   10495   i1->SetAccessor(v8_str("baz"),
   10496                   SimpleAccessorGetter, SimpleAccessorSetter);
   10497   i1->Set(v8_str("n1"), v8_num(1));
   10498   i1->Set(v8_str("n2"), v8_num(2));
   10499 
   10500   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   10501   Local<v8::FunctionTemplate> t2 =
   10502       v8::FunctionTemplate::New(context->GetIsolate());
   10503   t2->SetHiddenPrototype(true);
   10504 
   10505   // Inherit from t1 and mark prototype as hidden.
   10506   t2->Inherit(t1);
   10507   t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
   10508 
   10509   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   10510   CHECK(o2->SetPrototype(o1));
   10511 
   10512   v8::Local<v8::Symbol> sym =
   10513       v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
   10514   o1->Set(sym, v8_num(3));
   10515   o1->SetHiddenValue(
   10516       v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
   10517 
   10518   // Call the runtime version of GetOwnPropertyNames() on
   10519   // the natively created object through JavaScript.
   10520   context->Global()->Set(v8_str("obj"), o2);
   10521   context->Global()->Set(v8_str("sym"), sym);
   10522   // PROPERTY_ATTRIBUTES_NONE = 0
   10523   CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
   10524 
   10525   ExpectInt32("names.length", 7);
   10526   ExpectTrue("names.indexOf(\"foo\") >= 0");
   10527   ExpectTrue("names.indexOf(\"bar\") >= 0");
   10528   ExpectTrue("names.indexOf(\"baz\") >= 0");
   10529   ExpectTrue("names.indexOf(\"n1\") >= 0");
   10530   ExpectTrue("names.indexOf(\"n2\") >= 0");
   10531   ExpectTrue("names.indexOf(sym) >= 0");
   10532   ExpectTrue("names.indexOf(\"mine\") >= 0");
   10533 }
   10534 
   10535 
   10536 THREADED_TEST(FunctionReadOnlyPrototype) {
   10537   LocalContext context;
   10538   v8::Isolate* isolate = context->GetIsolate();
   10539   v8::HandleScope handle_scope(isolate);
   10540 
   10541   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10542   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   10543   t1->ReadOnlyPrototype();
   10544   context->Global()->Set(v8_str("func1"), t1->GetFunction());
   10545   // Configured value of ReadOnly flag.
   10546   CHECK(CompileRun(
   10547       "(function() {"
   10548       "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   10549       "  return (descriptor['writable'] == false);"
   10550       "})()")->BooleanValue());
   10551   CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
   10552   CHECK_EQ(42,
   10553            CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
   10554 
   10555   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10556   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   10557   context->Global()->Set(v8_str("func2"), t2->GetFunction());
   10558   // Default value of ReadOnly flag.
   10559   CHECK(CompileRun(
   10560       "(function() {"
   10561       "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   10562       "  return (descriptor['writable'] == true);"
   10563       "})()")->BooleanValue());
   10564   CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
   10565 }
   10566 
   10567 
   10568 THREADED_TEST(SetPrototypeThrows) {
   10569   LocalContext context;
   10570   v8::Isolate* isolate = context->GetIsolate();
   10571   v8::HandleScope handle_scope(isolate);
   10572 
   10573   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10574 
   10575   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
   10576   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
   10577 
   10578   CHECK(o0->SetPrototype(o1));
   10579   // If setting the prototype leads to the cycle, SetPrototype should
   10580   // return false and keep VM in sane state.
   10581   v8::TryCatch try_catch;
   10582   CHECK(!o1->SetPrototype(o0));
   10583   CHECK(!try_catch.HasCaught());
   10584   DCHECK(!CcTest::i_isolate()->has_pending_exception());
   10585 
   10586   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
   10587 }
   10588 
   10589 
   10590 THREADED_TEST(FunctionRemovePrototype) {
   10591   LocalContext context;
   10592   v8::Isolate* isolate = context->GetIsolate();
   10593   v8::HandleScope handle_scope(isolate);
   10594 
   10595   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10596   t1->RemovePrototype();
   10597   Local<v8::Function> fun = t1->GetFunction();
   10598   context->Global()->Set(v8_str("fun"), fun);
   10599   CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
   10600 
   10601   v8::TryCatch try_catch;
   10602   CompileRun("new fun()");
   10603   CHECK(try_catch.HasCaught());
   10604 
   10605   try_catch.Reset();
   10606   fun->NewInstance();
   10607   CHECK(try_catch.HasCaught());
   10608 }
   10609 
   10610 
   10611 THREADED_TEST(GetterSetterExceptions) {
   10612   LocalContext context;
   10613   v8::Isolate* isolate = context->GetIsolate();
   10614   v8::HandleScope handle_scope(isolate);
   10615   CompileRun(
   10616     "function Foo() { };"
   10617     "function Throw() { throw 5; };"
   10618     "var x = { };"
   10619     "x.__defineSetter__('set', Throw);"
   10620     "x.__defineGetter__('get', Throw);");
   10621   Local<v8::Object> x =
   10622       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
   10623   v8::TryCatch try_catch;
   10624   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
   10625   x->Get(v8_str("get"));
   10626   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
   10627   x->Get(v8_str("get"));
   10628   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
   10629   x->Get(v8_str("get"));
   10630   x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
   10631   x->Get(v8_str("get"));
   10632 }
   10633 
   10634 
   10635 THREADED_TEST(Constructor) {
   10636   LocalContext context;
   10637   v8::Isolate* isolate = context->GetIsolate();
   10638   v8::HandleScope handle_scope(isolate);
   10639   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   10640   templ->SetClassName(v8_str("Fun"));
   10641   Local<Function> cons = templ->GetFunction();
   10642   context->Global()->Set(v8_str("Fun"), cons);
   10643   Local<v8::Object> inst = cons->NewInstance();
   10644   i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
   10645   CHECK(obj->IsJSObject());
   10646   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   10647   CHECK(value->BooleanValue());
   10648 }
   10649 
   10650 
   10651 static void ConstructorCallback(
   10652     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10653   ApiTestFuzzer::Fuzz();
   10654   Local<Object> This;
   10655 
   10656   if (args.IsConstructCall()) {
   10657     Local<Object> Holder = args.Holder();
   10658     This = Object::New(args.GetIsolate());
   10659     Local<Value> proto = Holder->GetPrototype();
   10660     if (proto->IsObject()) {
   10661       This->SetPrototype(proto);
   10662     }
   10663   } else {
   10664     This = args.This();
   10665   }
   10666 
   10667   This->Set(v8_str("a"), args[0]);
   10668   args.GetReturnValue().Set(This);
   10669 }
   10670 
   10671 
   10672 static void FakeConstructorCallback(
   10673     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10674   ApiTestFuzzer::Fuzz();
   10675   args.GetReturnValue().Set(args[0]);
   10676 }
   10677 
   10678 
   10679 THREADED_TEST(ConstructorForObject) {
   10680   LocalContext context;
   10681   v8::Isolate* isolate = context->GetIsolate();
   10682   v8::HandleScope handle_scope(isolate);
   10683 
   10684   { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   10685     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
   10686     Local<Object> instance = instance_template->NewInstance();
   10687     context->Global()->Set(v8_str("obj"), instance);
   10688     v8::TryCatch try_catch;
   10689     Local<Value> value;
   10690     CHECK(!try_catch.HasCaught());
   10691 
   10692     // Call the Object's constructor with a 32-bit signed integer.
   10693     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
   10694     CHECK(!try_catch.HasCaught());
   10695     CHECK(value->IsInt32());
   10696     CHECK_EQ(28, value->Int32Value());
   10697 
   10698     Local<Value> args1[] = { v8_num(28) };
   10699     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
   10700     CHECK(value_obj1->IsObject());
   10701     Local<Object> object1 = Local<Object>::Cast(value_obj1);
   10702     value = object1->Get(v8_str("a"));
   10703     CHECK(value->IsInt32());
   10704     CHECK(!try_catch.HasCaught());
   10705     CHECK_EQ(28, value->Int32Value());
   10706 
   10707     // Call the Object's constructor with a String.
   10708     value = CompileRun(
   10709         "(function() { var o = new obj('tipli'); return o.a; })()");
   10710     CHECK(!try_catch.HasCaught());
   10711     CHECK(value->IsString());
   10712     String::Utf8Value string_value1(value->ToString());
   10713     CHECK_EQ("tipli", *string_value1);
   10714 
   10715     Local<Value> args2[] = { v8_str("tipli") };
   10716     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
   10717     CHECK(value_obj2->IsObject());
   10718     Local<Object> object2 = Local<Object>::Cast(value_obj2);
   10719     value = object2->Get(v8_str("a"));
   10720     CHECK(!try_catch.HasCaught());
   10721     CHECK(value->IsString());
   10722     String::Utf8Value string_value2(value->ToString());
   10723     CHECK_EQ("tipli", *string_value2);
   10724 
   10725     // Call the Object's constructor with a Boolean.
   10726     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
   10727     CHECK(!try_catch.HasCaught());
   10728     CHECK(value->IsBoolean());
   10729     CHECK_EQ(true, value->BooleanValue());
   10730 
   10731     Handle<Value> args3[] = { v8::True(isolate) };
   10732     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
   10733     CHECK(value_obj3->IsObject());
   10734     Local<Object> object3 = Local<Object>::Cast(value_obj3);
   10735     value = object3->Get(v8_str("a"));
   10736     CHECK(!try_catch.HasCaught());
   10737     CHECK(value->IsBoolean());
   10738     CHECK_EQ(true, value->BooleanValue());
   10739 
   10740     // Call the Object's constructor with undefined.
   10741     Handle<Value> args4[] = { v8::Undefined(isolate) };
   10742     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
   10743     CHECK(value_obj4->IsObject());
   10744     Local<Object> object4 = Local<Object>::Cast(value_obj4);
   10745     value = object4->Get(v8_str("a"));
   10746     CHECK(!try_catch.HasCaught());
   10747     CHECK(value->IsUndefined());
   10748 
   10749     // Call the Object's constructor with null.
   10750     Handle<Value> args5[] = { v8::Null(isolate) };
   10751     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
   10752     CHECK(value_obj5->IsObject());
   10753     Local<Object> object5 = Local<Object>::Cast(value_obj5);
   10754     value = object5->Get(v8_str("a"));
   10755     CHECK(!try_catch.HasCaught());
   10756     CHECK(value->IsNull());
   10757   }
   10758 
   10759   // Check exception handling when there is no constructor set for the Object.
   10760   { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   10761     Local<Object> instance = instance_template->NewInstance();
   10762     context->Global()->Set(v8_str("obj2"), instance);
   10763     v8::TryCatch try_catch;
   10764     Local<Value> value;
   10765     CHECK(!try_catch.HasCaught());
   10766 
   10767     value = CompileRun("new obj2(28)");
   10768     CHECK(try_catch.HasCaught());
   10769     String::Utf8Value exception_value1(try_catch.Exception());
   10770     CHECK_EQ("TypeError: object is not a function", *exception_value1);
   10771     try_catch.Reset();
   10772 
   10773     Local<Value> args[] = { v8_num(29) };
   10774     value = instance->CallAsConstructor(1, args);
   10775     CHECK(try_catch.HasCaught());
   10776     String::Utf8Value exception_value2(try_catch.Exception());
   10777     CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
   10778     try_catch.Reset();
   10779   }
   10780 
   10781   // Check the case when constructor throws exception.
   10782   { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   10783     instance_template->SetCallAsFunctionHandler(ThrowValue);
   10784     Local<Object> instance = instance_template->NewInstance();
   10785     context->Global()->Set(v8_str("obj3"), instance);
   10786     v8::TryCatch try_catch;
   10787     Local<Value> value;
   10788     CHECK(!try_catch.HasCaught());
   10789 
   10790     value = CompileRun("new obj3(22)");
   10791     CHECK(try_catch.HasCaught());
   10792     String::Utf8Value exception_value1(try_catch.Exception());
   10793     CHECK_EQ("22", *exception_value1);
   10794     try_catch.Reset();
   10795 
   10796     Local<Value> args[] = { v8_num(23) };
   10797     value = instance->CallAsConstructor(1, args);
   10798     CHECK(try_catch.HasCaught());
   10799     String::Utf8Value exception_value2(try_catch.Exception());
   10800     CHECK_EQ("23", *exception_value2);
   10801     try_catch.Reset();
   10802   }
   10803 
   10804   // Check whether constructor returns with an object or non-object.
   10805   { Local<FunctionTemplate> function_template =
   10806         FunctionTemplate::New(isolate, FakeConstructorCallback);
   10807     Local<Function> function = function_template->GetFunction();
   10808     Local<Object> instance1 = function;
   10809     context->Global()->Set(v8_str("obj4"), instance1);
   10810     v8::TryCatch try_catch;
   10811     Local<Value> value;
   10812     CHECK(!try_catch.HasCaught());
   10813 
   10814     CHECK(instance1->IsObject());
   10815     CHECK(instance1->IsFunction());
   10816 
   10817     value = CompileRun("new obj4(28)");
   10818     CHECK(!try_catch.HasCaught());
   10819     CHECK(value->IsObject());
   10820 
   10821     Local<Value> args1[] = { v8_num(28) };
   10822     value = instance1->CallAsConstructor(1, args1);
   10823     CHECK(!try_catch.HasCaught());
   10824     CHECK(value->IsObject());
   10825 
   10826     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   10827     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
   10828     Local<Object> instance2 = instance_template->NewInstance();
   10829     context->Global()->Set(v8_str("obj5"), instance2);
   10830     CHECK(!try_catch.HasCaught());
   10831 
   10832     CHECK(instance2->IsObject());
   10833     CHECK(!instance2->IsFunction());
   10834 
   10835     value = CompileRun("new obj5(28)");
   10836     CHECK(!try_catch.HasCaught());
   10837     CHECK(!value->IsObject());
   10838 
   10839     Local<Value> args2[] = { v8_num(28) };
   10840     value = instance2->CallAsConstructor(1, args2);
   10841     CHECK(!try_catch.HasCaught());
   10842     CHECK(!value->IsObject());
   10843   }
   10844 }
   10845 
   10846 
   10847 THREADED_TEST(FunctionDescriptorException) {
   10848   LocalContext context;
   10849   v8::Isolate* isolate = context->GetIsolate();
   10850   v8::HandleScope handle_scope(isolate);
   10851   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   10852   templ->SetClassName(v8_str("Fun"));
   10853   Local<Function> cons = templ->GetFunction();
   10854   context->Global()->Set(v8_str("Fun"), cons);
   10855   Local<Value> value = CompileRun(
   10856     "function test() {"
   10857     "  try {"
   10858     "    (new Fun()).blah()"
   10859     "  } catch (e) {"
   10860     "    var str = String(e);"
   10861     // "    if (str.indexOf('TypeError') == -1) return 1;"
   10862     // "    if (str.indexOf('[object Fun]') != -1) return 2;"
   10863     // "    if (str.indexOf('#<Fun>') == -1) return 3;"
   10864     "    return 0;"
   10865     "  }"
   10866     "  return 4;"
   10867     "}"
   10868     "test();");
   10869   CHECK_EQ(0, value->Int32Value());
   10870 }
   10871 
   10872 
   10873 THREADED_TEST(EvalAliasedDynamic) {
   10874   LocalContext current;
   10875   v8::HandleScope scope(current->GetIsolate());
   10876 
   10877   // Tests where aliased eval can only be resolved dynamically.
   10878   Local<Script> script = v8_compile(
   10879       "function f(x) { "
   10880       "  var foo = 2;"
   10881       "  with (x) { return eval('foo'); }"
   10882       "}"
   10883       "foo = 0;"
   10884       "result1 = f(new Object());"
   10885       "result2 = f(this);"
   10886       "var x = new Object();"
   10887       "x.eval = function(x) { return 1; };"
   10888       "result3 = f(x);");
   10889   script->Run();
   10890   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
   10891   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
   10892   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
   10893 
   10894   v8::TryCatch try_catch;
   10895   script = v8_compile(
   10896       "function f(x) { "
   10897       "  var bar = 2;"
   10898       "  with (x) { return eval('bar'); }"
   10899       "}"
   10900       "result4 = f(this)");
   10901   script->Run();
   10902   CHECK(!try_catch.HasCaught());
   10903   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
   10904 
   10905   try_catch.Reset();
   10906 }
   10907 
   10908 
   10909 THREADED_TEST(CrossEval) {
   10910   v8::HandleScope scope(CcTest::isolate());
   10911   LocalContext other;
   10912   LocalContext current;
   10913 
   10914   Local<String> token = v8_str("<security token>");
   10915   other->SetSecurityToken(token);
   10916   current->SetSecurityToken(token);
   10917 
   10918   // Set up reference from current to other.
   10919   current->Global()->Set(v8_str("other"), other->Global());
   10920 
   10921   // Check that new variables are introduced in other context.
   10922   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
   10923   script->Run();
   10924   Local<Value> foo = other->Global()->Get(v8_str("foo"));
   10925   CHECK_EQ(1234, foo->Int32Value());
   10926   CHECK(!current->Global()->Has(v8_str("foo")));
   10927 
   10928   // Check that writing to non-existing properties introduces them in
   10929   // the other context.
   10930   script = v8_compile("other.eval('na = 1234')");
   10931   script->Run();
   10932   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
   10933   CHECK(!current->Global()->Has(v8_str("na")));
   10934 
   10935   // Check that global variables in current context are not visible in other
   10936   // context.
   10937   v8::TryCatch try_catch;
   10938   script = v8_compile("var bar = 42; other.eval('bar');");
   10939   Local<Value> result = script->Run();
   10940   CHECK(try_catch.HasCaught());
   10941   try_catch.Reset();
   10942 
   10943   // Check that local variables in current context are not visible in other
   10944   // context.
   10945   script = v8_compile(
   10946       "(function() { "
   10947       "  var baz = 87;"
   10948       "  return other.eval('baz');"
   10949       "})();");
   10950   result = script->Run();
   10951   CHECK(try_catch.HasCaught());
   10952   try_catch.Reset();
   10953 
   10954   // Check that global variables in the other environment are visible
   10955   // when evaluting code.
   10956   other->Global()->Set(v8_str("bis"), v8_num(1234));
   10957   script = v8_compile("other.eval('bis')");
   10958   CHECK_EQ(1234, script->Run()->Int32Value());
   10959   CHECK(!try_catch.HasCaught());
   10960 
   10961   // Check that the 'this' pointer points to the global object evaluating
   10962   // code.
   10963   other->Global()->Set(v8_str("t"), other->Global());
   10964   script = v8_compile("other.eval('this == t')");
   10965   result = script->Run();
   10966   CHECK(result->IsTrue());
   10967   CHECK(!try_catch.HasCaught());
   10968 
   10969   // Check that variables introduced in with-statement are not visible in
   10970   // other context.
   10971   script = v8_compile("with({x:2}){other.eval('x')}");
   10972   result = script->Run();
   10973   CHECK(try_catch.HasCaught());
   10974   try_catch.Reset();
   10975 
   10976   // Check that you cannot use 'eval.call' with another object than the
   10977   // current global object.
   10978   script = v8_compile("other.y = 1; eval.call(other, 'y')");
   10979   result = script->Run();
   10980   CHECK(try_catch.HasCaught());
   10981 }
   10982 
   10983 
   10984 // Test that calling eval in a context which has been detached from
   10985 // its global throws an exception.  This behavior is consistent with
   10986 // other JavaScript implementations.
   10987 THREADED_TEST(EvalInDetachedGlobal) {
   10988   v8::Isolate* isolate = CcTest::isolate();
   10989   v8::HandleScope scope(isolate);
   10990 
   10991   v8::Local<Context> context0 = Context::New(isolate);
   10992   v8::Local<Context> context1 = Context::New(isolate);
   10993 
   10994   // Set up function in context0 that uses eval from context0.
   10995   context0->Enter();
   10996   v8::Handle<v8::Value> fun =
   10997       CompileRun("var x = 42;"
   10998                  "(function() {"
   10999                  "  var e = eval;"
   11000                  "  return function(s) { return e(s); }"
   11001                  "})()");
   11002   context0->Exit();
   11003 
   11004   // Put the function into context1 and call it before and after
   11005   // detaching the global.  Before detaching, the call succeeds and
   11006   // after detaching and exception is thrown.
   11007   context1->Enter();
   11008   context1->Global()->Set(v8_str("fun"), fun);
   11009   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
   11010   CHECK_EQ(42, x_value->Int32Value());
   11011   context0->DetachGlobal();
   11012   v8::TryCatch catcher;
   11013   x_value = CompileRun("fun('x')");
   11014   CHECK(x_value.IsEmpty());
   11015   CHECK(catcher.HasCaught());
   11016   context1->Exit();
   11017 }
   11018 
   11019 
   11020 THREADED_TEST(CrossLazyLoad) {
   11021   v8::HandleScope scope(CcTest::isolate());
   11022   LocalContext other;
   11023   LocalContext current;
   11024 
   11025   Local<String> token = v8_str("<security token>");
   11026   other->SetSecurityToken(token);
   11027   current->SetSecurityToken(token);
   11028 
   11029   // Set up reference from current to other.
   11030   current->Global()->Set(v8_str("other"), other->Global());
   11031 
   11032   // Trigger lazy loading in other context.
   11033   Local<Script> script = v8_compile("other.eval('new Date(42)')");
   11034   Local<Value> value = script->Run();
   11035   CHECK_EQ(42.0, value->NumberValue());
   11036 }
   11037 
   11038 
   11039 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11040   ApiTestFuzzer::Fuzz();
   11041   if (args.IsConstructCall()) {
   11042     if (args[0]->IsInt32()) {
   11043       args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
   11044       return;
   11045     }
   11046   }
   11047 
   11048   args.GetReturnValue().Set(args[0]);
   11049 }
   11050 
   11051 
   11052 static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11053   args.GetReturnValue().Set(args.This());
   11054 }
   11055 
   11056 
   11057 // Test that a call handler can be set for objects which will allow
   11058 // non-function objects created through the API to be called as
   11059 // functions.
   11060 THREADED_TEST(CallAsFunction) {
   11061   LocalContext context;
   11062   v8::Isolate* isolate = context->GetIsolate();
   11063   v8::HandleScope scope(isolate);
   11064 
   11065   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11066     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11067     instance_template->SetCallAsFunctionHandler(call_as_function);
   11068     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   11069     context->Global()->Set(v8_str("obj"), instance);
   11070     v8::TryCatch try_catch;
   11071     Local<Value> value;
   11072     CHECK(!try_catch.HasCaught());
   11073 
   11074     value = CompileRun("obj(42)");
   11075     CHECK(!try_catch.HasCaught());
   11076     CHECK_EQ(42, value->Int32Value());
   11077 
   11078     value = CompileRun("(function(o){return o(49)})(obj)");
   11079     CHECK(!try_catch.HasCaught());
   11080     CHECK_EQ(49, value->Int32Value());
   11081 
   11082     // test special case of call as function
   11083     value = CompileRun("[obj]['0'](45)");
   11084     CHECK(!try_catch.HasCaught());
   11085     CHECK_EQ(45, value->Int32Value());
   11086 
   11087     value = CompileRun("obj.call = Function.prototype.call;"
   11088                        "obj.call(null, 87)");
   11089     CHECK(!try_catch.HasCaught());
   11090     CHECK_EQ(87, value->Int32Value());
   11091 
   11092     // Regression tests for bug #1116356: Calling call through call/apply
   11093     // must work for non-function receivers.
   11094     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   11095     value = CompileRun(apply_99);
   11096     CHECK(!try_catch.HasCaught());
   11097     CHECK_EQ(99, value->Int32Value());
   11098 
   11099     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   11100     value = CompileRun(call_17);
   11101     CHECK(!try_catch.HasCaught());
   11102     CHECK_EQ(17, value->Int32Value());
   11103 
   11104     // Check that the call-as-function handler can be called through
   11105     // new.
   11106     value = CompileRun("new obj(43)");
   11107     CHECK(!try_catch.HasCaught());
   11108     CHECK_EQ(-43, value->Int32Value());
   11109 
   11110     // Check that the call-as-function handler can be called through
   11111     // the API.
   11112     v8::Handle<Value> args[] = { v8_num(28) };
   11113     value = instance->CallAsFunction(instance, 1, args);
   11114     CHECK(!try_catch.HasCaught());
   11115     CHECK_EQ(28, value->Int32Value());
   11116   }
   11117 
   11118   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11119     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   11120     USE(instance_template);
   11121     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   11122     context->Global()->Set(v8_str("obj2"), instance);
   11123     v8::TryCatch try_catch;
   11124     Local<Value> value;
   11125     CHECK(!try_catch.HasCaught());
   11126 
   11127     // Call an object without call-as-function handler through the JS
   11128     value = CompileRun("obj2(28)");
   11129     CHECK(value.IsEmpty());
   11130     CHECK(try_catch.HasCaught());
   11131     String::Utf8Value exception_value1(try_catch.Exception());
   11132     // TODO(verwaest): Better message
   11133     CHECK_EQ("TypeError: object is not a function",
   11134              *exception_value1);
   11135     try_catch.Reset();
   11136 
   11137     // Call an object without call-as-function handler through the API
   11138     value = CompileRun("obj2(28)");
   11139     v8::Handle<Value> args[] = { v8_num(28) };
   11140     value = instance->CallAsFunction(instance, 1, args);
   11141     CHECK(value.IsEmpty());
   11142     CHECK(try_catch.HasCaught());
   11143     String::Utf8Value exception_value2(try_catch.Exception());
   11144     CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
   11145     try_catch.Reset();
   11146   }
   11147 
   11148   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11149     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11150     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11151     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   11152     context->Global()->Set(v8_str("obj3"), instance);
   11153     v8::TryCatch try_catch;
   11154     Local<Value> value;
   11155     CHECK(!try_catch.HasCaught());
   11156 
   11157     // Catch the exception which is thrown by call-as-function handler
   11158     value = CompileRun("obj3(22)");
   11159     CHECK(try_catch.HasCaught());
   11160     String::Utf8Value exception_value1(try_catch.Exception());
   11161     CHECK_EQ("22", *exception_value1);
   11162     try_catch.Reset();
   11163 
   11164     v8::Handle<Value> args[] = { v8_num(23) };
   11165     value = instance->CallAsFunction(instance, 1, args);
   11166     CHECK(try_catch.HasCaught());
   11167     String::Utf8Value exception_value2(try_catch.Exception());
   11168     CHECK_EQ("23", *exception_value2);
   11169     try_catch.Reset();
   11170   }
   11171 
   11172   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11173     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11174     instance_template->SetCallAsFunctionHandler(ReturnThis);
   11175     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   11176 
   11177     Local<v8::Value> a1 =
   11178         instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
   11179     CHECK(a1->StrictEquals(instance));
   11180     Local<v8::Value> a2 =
   11181         instance->CallAsFunction(v8::Null(isolate), 0, NULL);
   11182     CHECK(a2->StrictEquals(instance));
   11183     Local<v8::Value> a3 =
   11184         instance->CallAsFunction(v8_num(42), 0, NULL);
   11185     CHECK(a3->StrictEquals(instance));
   11186     Local<v8::Value> a4 =
   11187         instance->CallAsFunction(v8_str("hello"), 0, NULL);
   11188     CHECK(a4->StrictEquals(instance));
   11189     Local<v8::Value> a5 =
   11190         instance->CallAsFunction(v8::True(isolate), 0, NULL);
   11191     CHECK(a5->StrictEquals(instance));
   11192   }
   11193 
   11194   { CompileRun(
   11195       "function ReturnThisSloppy() {"
   11196       "  return this;"
   11197       "}"
   11198       "function ReturnThisStrict() {"
   11199       "  'use strict';"
   11200       "  return this;"
   11201       "}");
   11202     Local<Function> ReturnThisSloppy =
   11203         Local<Function>::Cast(
   11204             context->Global()->Get(v8_str("ReturnThisSloppy")));
   11205     Local<Function> ReturnThisStrict =
   11206         Local<Function>::Cast(
   11207             context->Global()->Get(v8_str("ReturnThisStrict")));
   11208 
   11209     Local<v8::Value> a1 =
   11210         ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
   11211     CHECK(a1->StrictEquals(context->Global()));
   11212     Local<v8::Value> a2 =
   11213         ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
   11214     CHECK(a2->StrictEquals(context->Global()));
   11215     Local<v8::Value> a3 =
   11216         ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
   11217     CHECK(a3->IsNumberObject());
   11218     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
   11219     Local<v8::Value> a4 =
   11220         ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
   11221     CHECK(a4->IsStringObject());
   11222     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   11223     Local<v8::Value> a5 =
   11224         ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
   11225     CHECK(a5->IsBooleanObject());
   11226     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
   11227 
   11228     Local<v8::Value> a6 =
   11229         ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
   11230     CHECK(a6->IsUndefined());
   11231     Local<v8::Value> a7 =
   11232         ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
   11233     CHECK(a7->IsNull());
   11234     Local<v8::Value> a8 =
   11235         ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
   11236     CHECK(a8->StrictEquals(v8_num(42)));
   11237     Local<v8::Value> a9 =
   11238         ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
   11239     CHECK(a9->StrictEquals(v8_str("hello")));
   11240     Local<v8::Value> a10 =
   11241         ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
   11242     CHECK(a10->StrictEquals(v8::True(isolate)));
   11243   }
   11244 }
   11245 
   11246 
   11247 // Check whether a non-function object is callable.
   11248 THREADED_TEST(CallableObject) {
   11249   LocalContext context;
   11250   v8::Isolate* isolate = context->GetIsolate();
   11251   v8::HandleScope scope(isolate);
   11252 
   11253   { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11254     instance_template->SetCallAsFunctionHandler(call_as_function);
   11255     Local<Object> instance = instance_template->NewInstance();
   11256     v8::TryCatch try_catch;
   11257 
   11258     CHECK(instance->IsCallable());
   11259     CHECK(!try_catch.HasCaught());
   11260   }
   11261 
   11262   { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11263     Local<Object> instance = instance_template->NewInstance();
   11264     v8::TryCatch try_catch;
   11265 
   11266     CHECK(!instance->IsCallable());
   11267     CHECK(!try_catch.HasCaught());
   11268   }
   11269 
   11270   { Local<FunctionTemplate> function_template =
   11271         FunctionTemplate::New(isolate, call_as_function);
   11272     Local<Function> function = function_template->GetFunction();
   11273     Local<Object> instance = function;
   11274     v8::TryCatch try_catch;
   11275 
   11276     CHECK(instance->IsCallable());
   11277     CHECK(!try_catch.HasCaught());
   11278   }
   11279 
   11280   { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
   11281     Local<Function> function = function_template->GetFunction();
   11282     Local<Object> instance = function;
   11283     v8::TryCatch try_catch;
   11284 
   11285     CHECK(instance->IsCallable());
   11286     CHECK(!try_catch.HasCaught());
   11287   }
   11288 }
   11289 
   11290 
   11291 static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
   11292   v8::HandleScope scope(isolate);
   11293   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
   11294   for (int i = 0; i < iterations; i++) {
   11295     Local<v8::Number> n(v8::Integer::New(isolate, 42));
   11296   }
   11297   return Recurse(isolate, depth - 1, iterations);
   11298 }
   11299 
   11300 
   11301 THREADED_TEST(HandleIteration) {
   11302   static const int kIterations = 500;
   11303   static const int kNesting = 200;
   11304   LocalContext context;
   11305   v8::Isolate* isolate = context->GetIsolate();
   11306   v8::HandleScope scope0(isolate);
   11307   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   11308   {
   11309     v8::HandleScope scope1(isolate);
   11310     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   11311     for (int i = 0; i < kIterations; i++) {
   11312       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   11313       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
   11314     }
   11315 
   11316     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   11317     {
   11318       v8::HandleScope scope2(CcTest::isolate());
   11319       for (int j = 0; j < kIterations; j++) {
   11320         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   11321         CHECK_EQ(j + 1 + kIterations,
   11322                  v8::HandleScope::NumberOfHandles(isolate));
   11323       }
   11324     }
   11325     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   11326   }
   11327   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   11328   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
   11329 }
   11330 
   11331 
   11332 static void InterceptorHasOwnPropertyGetter(
   11333     Local<String> name,
   11334     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11335   ApiTestFuzzer::Fuzz();
   11336 }
   11337 
   11338 
   11339 THREADED_TEST(InterceptorHasOwnProperty) {
   11340   LocalContext context;
   11341   v8::Isolate* isolate = context->GetIsolate();
   11342   v8::HandleScope scope(isolate);
   11343   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
   11344   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   11345   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
   11346   Local<Function> function = fun_templ->GetFunction();
   11347   context->Global()->Set(v8_str("constructor"), function);
   11348   v8::Handle<Value> value = CompileRun(
   11349       "var o = new constructor();"
   11350       "o.hasOwnProperty('ostehaps');");
   11351   CHECK_EQ(false, value->BooleanValue());
   11352   value = CompileRun(
   11353       "o.ostehaps = 42;"
   11354       "o.hasOwnProperty('ostehaps');");
   11355   CHECK_EQ(true, value->BooleanValue());
   11356   value = CompileRun(
   11357       "var p = new constructor();"
   11358       "p.hasOwnProperty('ostehaps');");
   11359   CHECK_EQ(false, value->BooleanValue());
   11360 }
   11361 
   11362 
   11363 static void InterceptorHasOwnPropertyGetterGC(
   11364     Local<String> name,
   11365     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11366   ApiTestFuzzer::Fuzz();
   11367   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   11368 }
   11369 
   11370 
   11371 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
   11372   LocalContext context;
   11373   v8::Isolate* isolate = context->GetIsolate();
   11374   v8::HandleScope scope(isolate);
   11375   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
   11376   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   11377   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
   11378   Local<Function> function = fun_templ->GetFunction();
   11379   context->Global()->Set(v8_str("constructor"), function);
   11380   // Let's first make some stuff so we can be sure to get a good GC.
   11381   CompileRun(
   11382       "function makestr(size) {"
   11383       "  switch (size) {"
   11384       "    case 1: return 'f';"
   11385       "    case 2: return 'fo';"
   11386       "    case 3: return 'foo';"
   11387       "  }"
   11388       "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
   11389       "}"
   11390       "var x = makestr(12345);"
   11391       "x = makestr(31415);"
   11392       "x = makestr(23456);");
   11393   v8::Handle<Value> value = CompileRun(
   11394       "var o = new constructor();"
   11395       "o.__proto__ = new String(x);"
   11396       "o.hasOwnProperty('ostehaps');");
   11397   CHECK_EQ(false, value->BooleanValue());
   11398 }
   11399 
   11400 
   11401 typedef void (*NamedPropertyGetter)(
   11402     Local<String> property,
   11403     const v8::PropertyCallbackInfo<v8::Value>& info);
   11404 
   11405 
   11406 static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
   11407                                    const char* source,
   11408                                    int expected) {
   11409   v8::Isolate* isolate = CcTest::isolate();
   11410   v8::HandleScope scope(isolate);
   11411   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11412   templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
   11413   LocalContext context;
   11414   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11415   v8::Handle<Value> value = CompileRun(source);
   11416   CHECK_EQ(expected, value->Int32Value());
   11417 }
   11418 
   11419 
   11420 static void InterceptorLoadICGetter(
   11421     Local<String> name,
   11422     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11423   ApiTestFuzzer::Fuzz();
   11424   v8::Isolate* isolate = CcTest::isolate();
   11425   CHECK_EQ(isolate, info.GetIsolate());
   11426   CHECK_EQ(v8_str("data"), info.Data());
   11427   CHECK_EQ(v8_str("x"), name);
   11428   info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
   11429 }
   11430 
   11431 
   11432 // This test should hit the load IC for the interceptor case.
   11433 THREADED_TEST(InterceptorLoadIC) {
   11434   CheckInterceptorLoadIC(InterceptorLoadICGetter,
   11435     "var result = 0;"
   11436     "for (var i = 0; i < 1000; i++) {"
   11437     "  result = o.x;"
   11438     "}",
   11439     42);
   11440 }
   11441 
   11442 
   11443 // Below go several tests which verify that JITing for various
   11444 // configurations of interceptor and explicit fields works fine
   11445 // (those cases are special cased to get better performance).
   11446 
   11447 static void InterceptorLoadXICGetter(
   11448     Local<String> name,
   11449     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11450   ApiTestFuzzer::Fuzz();
   11451   info.GetReturnValue().Set(
   11452       v8_str("x")->Equals(name) ?
   11453           v8::Handle<v8::Value>(v8::Integer::New(info.GetIsolate(), 42)) :
   11454           v8::Handle<v8::Value>());
   11455 }
   11456 
   11457 
   11458 THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
   11459   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11460     "var result = 0;"
   11461     "o.y = 239;"
   11462     "for (var i = 0; i < 1000; i++) {"
   11463     "  result = o.y;"
   11464     "}",
   11465     239);
   11466 }
   11467 
   11468 
   11469 THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
   11470   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11471     "var result = 0;"
   11472     "o.__proto__ = { 'y': 239 };"
   11473     "for (var i = 0; i < 1000; i++) {"
   11474     "  result = o.y + o.x;"
   11475     "}",
   11476     239 + 42);
   11477 }
   11478 
   11479 
   11480 THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
   11481   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11482     "var result = 0;"
   11483     "o.__proto__.y = 239;"
   11484     "for (var i = 0; i < 1000; i++) {"
   11485     "  result = o.y + o.x;"
   11486     "}",
   11487     239 + 42);
   11488 }
   11489 
   11490 
   11491 THREADED_TEST(InterceptorLoadICUndefined) {
   11492   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11493     "var result = 0;"
   11494     "for (var i = 0; i < 1000; i++) {"
   11495     "  result = (o.y == undefined) ? 239 : 42;"
   11496     "}",
   11497     239);
   11498 }
   11499 
   11500 
   11501 THREADED_TEST(InterceptorLoadICWithOverride) {
   11502   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11503     "fst = new Object();  fst.__proto__ = o;"
   11504     "snd = new Object();  snd.__proto__ = fst;"
   11505     "var result1 = 0;"
   11506     "for (var i = 0; i < 1000;  i++) {"
   11507     "  result1 = snd.x;"
   11508     "}"
   11509     "fst.x = 239;"
   11510     "var result = 0;"
   11511     "for (var i = 0; i < 1000; i++) {"
   11512     "  result = snd.x;"
   11513     "}"
   11514     "result + result1",
   11515     239 + 42);
   11516 }
   11517 
   11518 
   11519 // Test the case when we stored field into
   11520 // a stub, but interceptor produced value on its own.
   11521 THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
   11522   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11523     "proto = new Object();"
   11524     "o.__proto__ = proto;"
   11525     "proto.x = 239;"
   11526     "for (var i = 0; i < 1000; i++) {"
   11527     "  o.x;"
   11528     // Now it should be ICed and keep a reference to x defined on proto
   11529     "}"
   11530     "var result = 0;"
   11531     "for (var i = 0; i < 1000; i++) {"
   11532     "  result += o.x;"
   11533     "}"
   11534     "result;",
   11535     42 * 1000);
   11536 }
   11537 
   11538 
   11539 // Test the case when we stored field into
   11540 // a stub, but it got invalidated later on.
   11541 THREADED_TEST(InterceptorLoadICInvalidatedField) {
   11542   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11543     "proto1 = new Object();"
   11544     "proto2 = new Object();"
   11545     "o.__proto__ = proto1;"
   11546     "proto1.__proto__ = proto2;"
   11547     "proto2.y = 239;"
   11548     "for (var i = 0; i < 1000; i++) {"
   11549     "  o.y;"
   11550     // Now it should be ICed and keep a reference to y defined on proto2
   11551     "}"
   11552     "proto1.y = 42;"
   11553     "var result = 0;"
   11554     "for (var i = 0; i < 1000; i++) {"
   11555     "  result += o.y;"
   11556     "}"
   11557     "result;",
   11558     42 * 1000);
   11559 }
   11560 
   11561 
   11562 static int interceptor_load_not_handled_calls = 0;
   11563 static void InterceptorLoadNotHandled(
   11564     Local<String> name,
   11565     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11566   ++interceptor_load_not_handled_calls;
   11567 }
   11568 
   11569 
   11570 // Test how post-interceptor lookups are done in the non-cacheable
   11571 // case: the interceptor should not be invoked during this lookup.
   11572 THREADED_TEST(InterceptorLoadICPostInterceptor) {
   11573   interceptor_load_not_handled_calls = 0;
   11574   CheckInterceptorLoadIC(InterceptorLoadNotHandled,
   11575     "receiver = new Object();"
   11576     "receiver.__proto__ = o;"
   11577     "proto = new Object();"
   11578     "/* Make proto a slow-case object. */"
   11579     "for (var i = 0; i < 1000; i++) {"
   11580     "  proto[\"xxxxxxxx\" + i] = [];"
   11581     "}"
   11582     "proto.x = 17;"
   11583     "o.__proto__ = proto;"
   11584     "var result = 0;"
   11585     "for (var i = 0; i < 1000; i++) {"
   11586     "  result += receiver.x;"
   11587     "}"
   11588     "result;",
   11589     17 * 1000);
   11590   CHECK_EQ(1000, interceptor_load_not_handled_calls);
   11591 }
   11592 
   11593 
   11594 // Test the case when we stored field into
   11595 // a stub, but it got invalidated later on due to override on
   11596 // global object which is between interceptor and fields' holders.
   11597 THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
   11598   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   11599     "o.__proto__ = this;"  // set a global to be a proto of o.
   11600     "this.__proto__.y = 239;"
   11601     "for (var i = 0; i < 10; i++) {"
   11602     "  if (o.y != 239) throw 'oops: ' + o.y;"
   11603     // Now it should be ICed and keep a reference to y defined on field_holder.
   11604     "}"
   11605     "this.y = 42;"  // Assign on a global.
   11606     "var result = 0;"
   11607     "for (var i = 0; i < 10; i++) {"
   11608     "  result += o.y;"
   11609     "}"
   11610     "result;",
   11611     42 * 10);
   11612 }
   11613 
   11614 
   11615 static void SetOnThis(Local<String> name,
   11616                       Local<Value> value,
   11617                       const v8::PropertyCallbackInfo<void>& info) {
   11618   Local<Object>::Cast(info.This())->ForceSet(name, value);
   11619 }
   11620 
   11621 
   11622 THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
   11623   v8::Isolate* isolate = CcTest::isolate();
   11624   v8::HandleScope scope(isolate);
   11625   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11626   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11627   templ->SetAccessor(v8_str("y"), Return239Callback);
   11628   LocalContext context;
   11629   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11630 
   11631   // Check the case when receiver and interceptor's holder
   11632   // are the same objects.
   11633   v8::Handle<Value> value = CompileRun(
   11634       "var result = 0;"
   11635       "for (var i = 0; i < 7; i++) {"
   11636       "  result = o.y;"
   11637       "}");
   11638   CHECK_EQ(239, value->Int32Value());
   11639 
   11640   // Check the case when interceptor's holder is in proto chain
   11641   // of receiver.
   11642   value = CompileRun(
   11643       "r = { __proto__: o };"
   11644       "var result = 0;"
   11645       "for (var i = 0; i < 7; i++) {"
   11646       "  result = r.y;"
   11647       "}");
   11648   CHECK_EQ(239, value->Int32Value());
   11649 }
   11650 
   11651 
   11652 THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
   11653   v8::Isolate* isolate = CcTest::isolate();
   11654   v8::HandleScope scope(isolate);
   11655   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
   11656   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11657   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
   11658   templ_p->SetAccessor(v8_str("y"), Return239Callback);
   11659 
   11660   LocalContext context;
   11661   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11662   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   11663 
   11664   // Check the case when receiver and interceptor's holder
   11665   // are the same objects.
   11666   v8::Handle<Value> value = CompileRun(
   11667       "o.__proto__ = p;"
   11668       "var result = 0;"
   11669       "for (var i = 0; i < 7; i++) {"
   11670       "  result = o.x + o.y;"
   11671       "}");
   11672   CHECK_EQ(239 + 42, value->Int32Value());
   11673 
   11674   // Check the case when interceptor's holder is in proto chain
   11675   // of receiver.
   11676   value = CompileRun(
   11677       "r = { __proto__: o };"
   11678       "var result = 0;"
   11679       "for (var i = 0; i < 7; i++) {"
   11680       "  result = r.x + r.y;"
   11681       "}");
   11682   CHECK_EQ(239 + 42, value->Int32Value());
   11683 }
   11684 
   11685 
   11686 THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
   11687   v8::Isolate* isolate = CcTest::isolate();
   11688   v8::HandleScope scope(isolate);
   11689   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11690   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11691   templ->SetAccessor(v8_str("y"), Return239Callback);
   11692 
   11693   LocalContext context;
   11694   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11695 
   11696   v8::Handle<Value> value = CompileRun(
   11697     "fst = new Object();  fst.__proto__ = o;"
   11698     "snd = new Object();  snd.__proto__ = fst;"
   11699     "var result1 = 0;"
   11700     "for (var i = 0; i < 7;  i++) {"
   11701     "  result1 = snd.x;"
   11702     "}"
   11703     "fst.x = 239;"
   11704     "var result = 0;"
   11705     "for (var i = 0; i < 7; i++) {"
   11706     "  result = snd.x;"
   11707     "}"
   11708     "result + result1");
   11709   CHECK_EQ(239 + 42, value->Int32Value());
   11710 }
   11711 
   11712 
   11713 // Test the case when we stored callback into
   11714 // a stub, but interceptor produced value on its own.
   11715 THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
   11716   v8::Isolate* isolate = CcTest::isolate();
   11717   v8::HandleScope scope(isolate);
   11718   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
   11719   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11720   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
   11721   templ_p->SetAccessor(v8_str("y"), Return239Callback);
   11722 
   11723   LocalContext context;
   11724   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11725   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   11726 
   11727   v8::Handle<Value> value = CompileRun(
   11728     "o.__proto__ = p;"
   11729     "for (var i = 0; i < 7; i++) {"
   11730     "  o.x;"
   11731     // Now it should be ICed and keep a reference to x defined on p
   11732     "}"
   11733     "var result = 0;"
   11734     "for (var i = 0; i < 7; i++) {"
   11735     "  result += o.x;"
   11736     "}"
   11737     "result");
   11738   CHECK_EQ(42 * 7, value->Int32Value());
   11739 }
   11740 
   11741 
   11742 // Test the case when we stored callback into
   11743 // a stub, but it got invalidated later on.
   11744 THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
   11745   v8::Isolate* isolate = CcTest::isolate();
   11746   v8::HandleScope scope(isolate);
   11747   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
   11748   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11749   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
   11750   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
   11751 
   11752   LocalContext context;
   11753   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11754   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   11755 
   11756   v8::Handle<Value> value = CompileRun(
   11757     "inbetween = new Object();"
   11758     "o.__proto__ = inbetween;"
   11759     "inbetween.__proto__ = p;"
   11760     "for (var i = 0; i < 10; i++) {"
   11761     "  o.y;"
   11762     // Now it should be ICed and keep a reference to y defined on p
   11763     "}"
   11764     "inbetween.y = 42;"
   11765     "var result = 0;"
   11766     "for (var i = 0; i < 10; i++) {"
   11767     "  result += o.y;"
   11768     "}"
   11769     "result");
   11770   CHECK_EQ(42 * 10, value->Int32Value());
   11771 }
   11772 
   11773 
   11774 // Test the case when we stored callback into
   11775 // a stub, but it got invalidated later on due to override on
   11776 // global object which is between interceptor and callbacks' holders.
   11777 THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
   11778   v8::Isolate* isolate = CcTest::isolate();
   11779   v8::HandleScope scope(isolate);
   11780   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
   11781   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11782   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
   11783   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
   11784 
   11785   LocalContext context;
   11786   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11787   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   11788 
   11789   v8::Handle<Value> value = CompileRun(
   11790     "o.__proto__ = this;"
   11791     "this.__proto__ = p;"
   11792     "for (var i = 0; i < 10; i++) {"
   11793     "  if (o.y != 239) throw 'oops: ' + o.y;"
   11794     // Now it should be ICed and keep a reference to y defined on p
   11795     "}"
   11796     "this.y = 42;"
   11797     "var result = 0;"
   11798     "for (var i = 0; i < 10; i++) {"
   11799     "  result += o.y;"
   11800     "}"
   11801     "result");
   11802   CHECK_EQ(42 * 10, value->Int32Value());
   11803 }
   11804 
   11805 
   11806 static void InterceptorLoadICGetter0(
   11807     Local<String> name,
   11808     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11809   ApiTestFuzzer::Fuzz();
   11810   CHECK(v8_str("x")->Equals(name));
   11811   info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
   11812 }
   11813 
   11814 
   11815 THREADED_TEST(InterceptorReturningZero) {
   11816   CheckInterceptorLoadIC(InterceptorLoadICGetter0,
   11817      "o.x == undefined ? 1 : 0",
   11818      0);
   11819 }
   11820 
   11821 
   11822 static void InterceptorStoreICSetter(
   11823     Local<String> key,
   11824     Local<Value> value,
   11825     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11826   CHECK(v8_str("x")->Equals(key));
   11827   CHECK_EQ(42, value->Int32Value());
   11828   info.GetReturnValue().Set(value);
   11829 }
   11830 
   11831 
   11832 // This test should hit the store IC for the interceptor case.
   11833 THREADED_TEST(InterceptorStoreIC) {
   11834   v8::Isolate* isolate = CcTest::isolate();
   11835   v8::HandleScope scope(isolate);
   11836   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11837   templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
   11838                                  InterceptorStoreICSetter,
   11839                                  0, 0, 0, v8_str("data"));
   11840   LocalContext context;
   11841   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11842   CompileRun(
   11843       "for (var i = 0; i < 1000; i++) {"
   11844       "  o.x = 42;"
   11845       "}");
   11846 }
   11847 
   11848 
   11849 THREADED_TEST(InterceptorStoreICWithNoSetter) {
   11850   v8::Isolate* isolate = CcTest::isolate();
   11851   v8::HandleScope scope(isolate);
   11852   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11853   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11854   LocalContext context;
   11855   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11856   v8::Handle<Value> value = CompileRun(
   11857     "for (var i = 0; i < 1000; i++) {"
   11858     "  o.y = 239;"
   11859     "}"
   11860     "42 + o.y");
   11861   CHECK_EQ(239 + 42, value->Int32Value());
   11862 }
   11863 
   11864 
   11865 
   11866 
   11867 v8::Handle<Value> call_ic_function;
   11868 v8::Handle<Value> call_ic_function2;
   11869 v8::Handle<Value> call_ic_function3;
   11870 
   11871 static void InterceptorCallICGetter(
   11872     Local<String> name,
   11873     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11874   ApiTestFuzzer::Fuzz();
   11875   CHECK(v8_str("x")->Equals(name));
   11876   info.GetReturnValue().Set(call_ic_function);
   11877 }
   11878 
   11879 
   11880 // This test should hit the call IC for the interceptor case.
   11881 THREADED_TEST(InterceptorCallIC) {
   11882   v8::Isolate* isolate = CcTest::isolate();
   11883   v8::HandleScope scope(isolate);
   11884   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11885   templ->SetNamedPropertyHandler(InterceptorCallICGetter);
   11886   LocalContext context;
   11887   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11888   call_ic_function =
   11889       v8_compile("function f(x) { return x + 1; }; f")->Run();
   11890   v8::Handle<Value> value = CompileRun(
   11891     "var result = 0;"
   11892     "for (var i = 0; i < 1000; i++) {"
   11893     "  result = o.x(41);"
   11894     "}");
   11895   CHECK_EQ(42, value->Int32Value());
   11896 }
   11897 
   11898 
   11899 // This test checks that if interceptor doesn't provide
   11900 // a value, we can fetch regular value.
   11901 THREADED_TEST(InterceptorCallICSeesOthers) {
   11902   v8::Isolate* isolate = CcTest::isolate();
   11903   v8::HandleScope scope(isolate);
   11904   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11905   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11906   LocalContext context;
   11907   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11908   v8::Handle<Value> value = CompileRun(
   11909     "o.x = function f(x) { return x + 1; };"
   11910     "var result = 0;"
   11911     "for (var i = 0; i < 7; i++) {"
   11912     "  result = o.x(41);"
   11913     "}");
   11914   CHECK_EQ(42, value->Int32Value());
   11915 }
   11916 
   11917 
   11918 static v8::Handle<Value> call_ic_function4;
   11919 static void InterceptorCallICGetter4(
   11920     Local<String> name,
   11921     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11922   ApiTestFuzzer::Fuzz();
   11923   CHECK(v8_str("x")->Equals(name));
   11924   info.GetReturnValue().Set(call_ic_function4);
   11925 }
   11926 
   11927 
   11928 // This test checks that if interceptor provides a function,
   11929 // even if we cached shadowed variant, interceptor's function
   11930 // is invoked
   11931 THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
   11932   v8::Isolate* isolate = CcTest::isolate();
   11933   v8::HandleScope scope(isolate);
   11934   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11935   templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
   11936   LocalContext context;
   11937   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11938   call_ic_function4 =
   11939       v8_compile("function f(x) { return x - 1; }; f")->Run();
   11940   v8::Handle<Value> value = CompileRun(
   11941     "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
   11942     "var result = 0;"
   11943     "for (var i = 0; i < 1000; i++) {"
   11944     "  result = o.x(42);"
   11945     "}");
   11946   CHECK_EQ(41, value->Int32Value());
   11947 }
   11948 
   11949 
   11950 // Test the case when we stored cacheable lookup into
   11951 // a stub, but it got invalidated later on
   11952 THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
   11953   v8::Isolate* isolate = CcTest::isolate();
   11954   v8::HandleScope scope(isolate);
   11955   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11956   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11957   LocalContext context;
   11958   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11959   v8::Handle<Value> value = CompileRun(
   11960     "proto1 = new Object();"
   11961     "proto2 = new Object();"
   11962     "o.__proto__ = proto1;"
   11963     "proto1.__proto__ = proto2;"
   11964     "proto2.y = function(x) { return x + 1; };"
   11965     // Invoke it many times to compile a stub
   11966     "for (var i = 0; i < 7; i++) {"
   11967     "  o.y(42);"
   11968     "}"
   11969     "proto1.y = function(x) { return x - 1; };"
   11970     "var result = 0;"
   11971     "for (var i = 0; i < 7; i++) {"
   11972     "  result += o.y(42);"
   11973     "}");
   11974   CHECK_EQ(41 * 7, value->Int32Value());
   11975 }
   11976 
   11977 
   11978 // This test checks that if interceptor doesn't provide a function,
   11979 // cached constant function is used
   11980 THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
   11981   v8::Isolate* isolate = CcTest::isolate();
   11982   v8::HandleScope scope(isolate);
   11983   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   11984   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11985   LocalContext context;
   11986   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11987   v8::Handle<Value> value = CompileRun(
   11988     "function inc(x) { return x + 1; };"
   11989     "inc(1);"
   11990     "o.x = inc;"
   11991     "var result = 0;"
   11992     "for (var i = 0; i < 1000; i++) {"
   11993     "  result = o.x(42);"
   11994     "}");
   11995   CHECK_EQ(43, value->Int32Value());
   11996 }
   11997 
   11998 
   11999 static v8::Handle<Value> call_ic_function5;
   12000 static void InterceptorCallICGetter5(
   12001     Local<String> name,
   12002     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12003   ApiTestFuzzer::Fuzz();
   12004   if (v8_str("x")->Equals(name))
   12005     info.GetReturnValue().Set(call_ic_function5);
   12006 }
   12007 
   12008 
   12009 // This test checks that if interceptor provides a function,
   12010 // even if we cached constant function, interceptor's function
   12011 // is invoked
   12012 THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
   12013   v8::Isolate* isolate = CcTest::isolate();
   12014   v8::HandleScope scope(isolate);
   12015   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12016   templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
   12017   LocalContext context;
   12018   context->Global()->Set(v8_str("o"), templ->NewInstance());
   12019   call_ic_function5 =
   12020       v8_compile("function f(x) { return x - 1; }; f")->Run();
   12021   v8::Handle<Value> value = CompileRun(
   12022     "function inc(x) { return x + 1; };"
   12023     "inc(1);"
   12024     "o.x = inc;"
   12025     "var result = 0;"
   12026     "for (var i = 0; i < 1000; i++) {"
   12027     "  result = o.x(42);"
   12028     "}");
   12029   CHECK_EQ(41, value->Int32Value());
   12030 }
   12031 
   12032 
   12033 static v8::Handle<Value> call_ic_function6;
   12034 static void InterceptorCallICGetter6(
   12035     Local<String> name,
   12036     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12037   ApiTestFuzzer::Fuzz();
   12038   if (v8_str("x")->Equals(name))
   12039     info.GetReturnValue().Set(call_ic_function6);
   12040 }
   12041 
   12042 
   12043 // Same test as above, except the code is wrapped in a function
   12044 // to test the optimized compiler.
   12045 THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
   12046   i::FLAG_allow_natives_syntax = true;
   12047   v8::Isolate* isolate = CcTest::isolate();
   12048   v8::HandleScope scope(isolate);
   12049   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12050   templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
   12051   LocalContext context;
   12052   context->Global()->Set(v8_str("o"), templ->NewInstance());
   12053   call_ic_function6 =
   12054       v8_compile("function f(x) { return x - 1; }; f")->Run();
   12055   v8::Handle<Value> value = CompileRun(
   12056     "function inc(x) { return x + 1; };"
   12057     "inc(1);"
   12058     "o.x = inc;"
   12059     "function test() {"
   12060     "  var result = 0;"
   12061     "  for (var i = 0; i < 1000; i++) {"
   12062     "    result = o.x(42);"
   12063     "  }"
   12064     "  return result;"
   12065     "};"
   12066     "test();"
   12067     "test();"
   12068     "test();"
   12069     "%OptimizeFunctionOnNextCall(test);"
   12070     "test()");
   12071   CHECK_EQ(41, value->Int32Value());
   12072 }
   12073 
   12074 
   12075 // Test the case when we stored constant function into
   12076 // a stub, but it got invalidated later on
   12077 THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
   12078   v8::Isolate* isolate = CcTest::isolate();
   12079   v8::HandleScope scope(isolate);
   12080   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12081   templ->SetNamedPropertyHandler(NoBlockGetterX);
   12082   LocalContext context;
   12083   context->Global()->Set(v8_str("o"), templ->NewInstance());
   12084   v8::Handle<Value> value = CompileRun(
   12085     "function inc(x) { return x + 1; };"
   12086     "inc(1);"
   12087     "proto1 = new Object();"
   12088     "proto2 = new Object();"
   12089     "o.__proto__ = proto1;"
   12090     "proto1.__proto__ = proto2;"
   12091     "proto2.y = inc;"
   12092     // Invoke it many times to compile a stub
   12093     "for (var i = 0; i < 7; i++) {"
   12094     "  o.y(42);"
   12095     "}"
   12096     "proto1.y = function(x) { return x - 1; };"
   12097     "var result = 0;"
   12098     "for (var i = 0; i < 7; i++) {"
   12099     "  result += o.y(42);"
   12100     "}");
   12101   CHECK_EQ(41 * 7, value->Int32Value());
   12102 }
   12103 
   12104 
   12105 // Test the case when we stored constant function into
   12106 // a stub, but it got invalidated later on due to override on
   12107 // global object which is between interceptor and constant function' holders.
   12108 THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
   12109   v8::Isolate* isolate = CcTest::isolate();
   12110   v8::HandleScope scope(isolate);
   12111   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12112   templ->SetNamedPropertyHandler(NoBlockGetterX);
   12113   LocalContext context;
   12114   context->Global()->Set(v8_str("o"), templ->NewInstance());
   12115   v8::Handle<Value> value = CompileRun(
   12116     "function inc(x) { return x + 1; };"
   12117     "inc(1);"
   12118     "o.__proto__ = this;"
   12119     "this.__proto__.y = inc;"
   12120     // Invoke it many times to compile a stub
   12121     "for (var i = 0; i < 7; i++) {"
   12122     "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
   12123     "}"
   12124     "this.y = function(x) { return x - 1; };"
   12125     "var result = 0;"
   12126     "for (var i = 0; i < 7; i++) {"
   12127     "  result += o.y(42);"
   12128     "}");
   12129   CHECK_EQ(41 * 7, value->Int32Value());
   12130 }
   12131 
   12132 
   12133 // Test the case when actual function to call sits on global object.
   12134 THREADED_TEST(InterceptorCallICCachedFromGlobal) {
   12135   v8::Isolate* isolate = CcTest::isolate();
   12136   v8::HandleScope scope(isolate);
   12137   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
   12138   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   12139 
   12140   LocalContext context;
   12141   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   12142 
   12143   v8::Handle<Value> value = CompileRun(
   12144     "try {"
   12145     "  o.__proto__ = this;"
   12146     "  for (var i = 0; i < 10; i++) {"
   12147     "    var v = o.parseFloat('239');"
   12148     "    if (v != 239) throw v;"
   12149       // Now it should be ICed and keep a reference to parseFloat.
   12150     "  }"
   12151     "  var result = 0;"
   12152     "  for (var i = 0; i < 10; i++) {"
   12153     "    result += o.parseFloat('239');"
   12154     "  }"
   12155     "  result"
   12156     "} catch(e) {"
   12157     "  e"
   12158     "};");
   12159   CHECK_EQ(239 * 10, value->Int32Value());
   12160 }
   12161 
   12162 static void InterceptorCallICFastApi(
   12163     Local<String> name,
   12164     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12165   ApiTestFuzzer::Fuzz();
   12166   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
   12167   int* call_count =
   12168       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
   12169   ++(*call_count);
   12170   if ((*call_count) % 20 == 0) {
   12171     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   12172   }
   12173 }
   12174 
   12175 static void FastApiCallback_TrivialSignature(
   12176     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12177   ApiTestFuzzer::Fuzz();
   12178   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
   12179   v8::Isolate* isolate = CcTest::isolate();
   12180   CHECK_EQ(isolate, args.GetIsolate());
   12181   CHECK_EQ(args.This(), args.Holder());
   12182   CHECK(args.Data()->Equals(v8_str("method_data")));
   12183   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
   12184 }
   12185 
   12186 static void FastApiCallback_SimpleSignature(
   12187     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12188   ApiTestFuzzer::Fuzz();
   12189   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
   12190   v8::Isolate* isolate = CcTest::isolate();
   12191   CHECK_EQ(isolate, args.GetIsolate());
   12192   CHECK_EQ(args.This()->GetPrototype(), args.Holder());
   12193   CHECK(args.Data()->Equals(v8_str("method_data")));
   12194   // Note, we're using HasRealNamedProperty instead of Has to avoid
   12195   // invoking the interceptor again.
   12196   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
   12197   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
   12198 }
   12199 
   12200 
   12201 // Helper to maximize the odds of object moving.
   12202 static void GenerateSomeGarbage() {
   12203   CompileRun(
   12204       "var garbage;"
   12205       "for (var i = 0; i < 1000; i++) {"
   12206       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   12207       "}"
   12208       "garbage = undefined;");
   12209 }
   12210 
   12211 
   12212 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12213   static int count = 0;
   12214   if (count++ % 3 == 0) {
   12215     CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   12216         // This should move the stub
   12217     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   12218   }
   12219 }
   12220 
   12221 
   12222 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   12223   LocalContext context;
   12224   v8::Isolate* isolate = context->GetIsolate();
   12225   v8::HandleScope scope(isolate);
   12226   v8::Handle<v8::ObjectTemplate> nativeobject_templ =
   12227       v8::ObjectTemplate::New(isolate);
   12228   nativeobject_templ->Set(isolate, "callback",
   12229                           v8::FunctionTemplate::New(isolate,
   12230                                                     DirectApiCallback));
   12231   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   12232   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   12233   // call the api function multiple times to ensure direct call stub creation.
   12234   CompileRun(
   12235         "function f() {"
   12236         "  for (var i = 1; i <= 30; i++) {"
   12237         "    nativeobject.callback();"
   12238         "  }"
   12239         "}"
   12240         "f();");
   12241 }
   12242 
   12243 
   12244 void ThrowingDirectApiCallback(
   12245     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12246   args.GetIsolate()->ThrowException(v8_str("g"));
   12247 }
   12248 
   12249 
   12250 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   12251   LocalContext context;
   12252   v8::Isolate* isolate = context->GetIsolate();
   12253   v8::HandleScope scope(isolate);
   12254   v8::Handle<v8::ObjectTemplate> nativeobject_templ =
   12255       v8::ObjectTemplate::New(isolate);
   12256   nativeobject_templ->Set(isolate, "callback",
   12257                           v8::FunctionTemplate::New(isolate,
   12258                                                     ThrowingDirectApiCallback));
   12259   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   12260   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   12261   // call the api function multiple times to ensure direct call stub creation.
   12262   v8::Handle<Value> result = CompileRun(
   12263       "var result = '';"
   12264       "function f() {"
   12265       "  for (var i = 1; i <= 5; i++) {"
   12266       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   12267       "  }"
   12268       "}"
   12269       "f(); result;");
   12270   CHECK_EQ(v8_str("ggggg"), result);
   12271 }
   12272 
   12273 
   12274 static Handle<Value> DoDirectGetter() {
   12275   if (++p_getter_count % 3 == 0) {
   12276     CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   12277     GenerateSomeGarbage();
   12278   }
   12279   return v8_str("Direct Getter Result");
   12280 }
   12281 
   12282 static void DirectGetterCallback(
   12283     Local<String> name,
   12284     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12285   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
   12286   info.GetReturnValue().Set(DoDirectGetter());
   12287 }
   12288 
   12289 
   12290 template<typename Accessor>
   12291 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
   12292   LocalContext context;
   12293   v8::Isolate* isolate = context->GetIsolate();
   12294   v8::HandleScope scope(isolate);
   12295   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12296   obj->SetAccessor(v8_str("p1"), accessor);
   12297   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   12298   p_getter_count = 0;
   12299   v8::Handle<v8::Value> result = CompileRun(
   12300       "function f() {"
   12301       "  for (var i = 0; i < 30; i++) o1.p1;"
   12302       "  return o1.p1"
   12303       "}"
   12304       "f();");
   12305   CHECK_EQ(v8_str("Direct Getter Result"), result);
   12306   CHECK_EQ(31, p_getter_count);
   12307 }
   12308 
   12309 
   12310 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   12311   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
   12312 }
   12313 
   12314 
   12315 void ThrowingDirectGetterCallback(
   12316     Local<String> name,
   12317     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12318   info.GetIsolate()->ThrowException(v8_str("g"));
   12319 }
   12320 
   12321 
   12322 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   12323   LocalContext context;
   12324   v8::Isolate* isolate = context->GetIsolate();
   12325   v8::HandleScope scope(isolate);
   12326   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12327   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   12328   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   12329   v8::Handle<Value> result = CompileRun(
   12330       "var result = '';"
   12331       "for (var i = 0; i < 5; i++) {"
   12332       "    try { o1.p1; } catch (e) { result += e; }"
   12333       "}"
   12334       "result;");
   12335   CHECK_EQ(v8_str("ggggg"), result);
   12336 }
   12337 
   12338 
   12339 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   12340   int interceptor_call_count = 0;
   12341   v8::Isolate* isolate = CcTest::isolate();
   12342   v8::HandleScope scope(isolate);
   12343   v8::Handle<v8::FunctionTemplate> fun_templ =
   12344       v8::FunctionTemplate::New(isolate);
   12345   v8::Handle<v8::FunctionTemplate> method_templ =
   12346       v8::FunctionTemplate::New(isolate,
   12347                                 FastApiCallback_TrivialSignature,
   12348                                 v8_str("method_data"),
   12349                                 v8::Handle<v8::Signature>());
   12350   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12351   proto_templ->Set(v8_str("method"), method_templ);
   12352   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12353   templ->SetNamedPropertyHandler(
   12354       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12355       v8::External::New(isolate, &interceptor_call_count));
   12356   LocalContext context;
   12357   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12358   GenerateSomeGarbage();
   12359   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12360   CompileRun(
   12361       "var result = 0;"
   12362       "for (var i = 0; i < 100; i++) {"
   12363       "  result = o.method(41);"
   12364       "}");
   12365   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   12366   CHECK_EQ(100, interceptor_call_count);
   12367 }
   12368 
   12369 
   12370 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
   12371   int interceptor_call_count = 0;
   12372   v8::Isolate* isolate = CcTest::isolate();
   12373   v8::HandleScope scope(isolate);
   12374   v8::Handle<v8::FunctionTemplate> fun_templ =
   12375       v8::FunctionTemplate::New(isolate);
   12376   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12377       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12378       v8::Signature::New(isolate, fun_templ));
   12379   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12380   proto_templ->Set(v8_str("method"), method_templ);
   12381   fun_templ->SetHiddenPrototype(true);
   12382   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12383   templ->SetNamedPropertyHandler(
   12384       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12385       v8::External::New(isolate, &interceptor_call_count));
   12386   LocalContext context;
   12387   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12388   GenerateSomeGarbage();
   12389   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12390   CompileRun(
   12391       "o.foo = 17;"
   12392       "var receiver = {};"
   12393       "receiver.__proto__ = o;"
   12394       "var result = 0;"
   12395       "for (var i = 0; i < 100; i++) {"
   12396       "  result = receiver.method(41);"
   12397       "}");
   12398   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   12399   CHECK_EQ(100, interceptor_call_count);
   12400 }
   12401 
   12402 
   12403 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
   12404   int interceptor_call_count = 0;
   12405   v8::Isolate* isolate = CcTest::isolate();
   12406   v8::HandleScope scope(isolate);
   12407   v8::Handle<v8::FunctionTemplate> fun_templ =
   12408       v8::FunctionTemplate::New(isolate);
   12409   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12410       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12411       v8::Signature::New(isolate, fun_templ));
   12412   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12413   proto_templ->Set(v8_str("method"), method_templ);
   12414   fun_templ->SetHiddenPrototype(true);
   12415   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12416   templ->SetNamedPropertyHandler(
   12417       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12418       v8::External::New(isolate, &interceptor_call_count));
   12419   LocalContext context;
   12420   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12421   GenerateSomeGarbage();
   12422   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12423   CompileRun(
   12424       "o.foo = 17;"
   12425       "var receiver = {};"
   12426       "receiver.__proto__ = o;"
   12427       "var result = 0;"
   12428       "var saved_result = 0;"
   12429       "for (var i = 0; i < 100; i++) {"
   12430       "  result = receiver.method(41);"
   12431       "  if (i == 50) {"
   12432       "    saved_result = result;"
   12433       "    receiver = {method: function(x) { return x - 1 }};"
   12434       "  }"
   12435       "}");
   12436   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   12437   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12438   CHECK_GE(interceptor_call_count, 50);
   12439 }
   12440 
   12441 
   12442 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
   12443   int interceptor_call_count = 0;
   12444   v8::Isolate* isolate = CcTest::isolate();
   12445   v8::HandleScope scope(isolate);
   12446   v8::Handle<v8::FunctionTemplate> fun_templ =
   12447       v8::FunctionTemplate::New(isolate);
   12448   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12449       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12450       v8::Signature::New(isolate, fun_templ));
   12451   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12452   proto_templ->Set(v8_str("method"), method_templ);
   12453   fun_templ->SetHiddenPrototype(true);
   12454   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12455   templ->SetNamedPropertyHandler(
   12456       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12457       v8::External::New(isolate, &interceptor_call_count));
   12458   LocalContext context;
   12459   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12460   GenerateSomeGarbage();
   12461   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12462   CompileRun(
   12463       "o.foo = 17;"
   12464       "var receiver = {};"
   12465       "receiver.__proto__ = o;"
   12466       "var result = 0;"
   12467       "var saved_result = 0;"
   12468       "for (var i = 0; i < 100; i++) {"
   12469       "  result = receiver.method(41);"
   12470       "  if (i == 50) {"
   12471       "    saved_result = result;"
   12472       "    o.method = function(x) { return x - 1 };"
   12473       "  }"
   12474       "}");
   12475   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   12476   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12477   CHECK_GE(interceptor_call_count, 50);
   12478 }
   12479 
   12480 
   12481 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
   12482   int interceptor_call_count = 0;
   12483   v8::Isolate* isolate = CcTest::isolate();
   12484   v8::HandleScope scope(isolate);
   12485   v8::Handle<v8::FunctionTemplate> fun_templ =
   12486       v8::FunctionTemplate::New(isolate);
   12487   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12488       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12489       v8::Signature::New(isolate, fun_templ));
   12490   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12491   proto_templ->Set(v8_str("method"), method_templ);
   12492   fun_templ->SetHiddenPrototype(true);
   12493   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12494   templ->SetNamedPropertyHandler(
   12495       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12496       v8::External::New(isolate, &interceptor_call_count));
   12497   LocalContext context;
   12498   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12499   GenerateSomeGarbage();
   12500   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12501   v8::TryCatch try_catch;
   12502   CompileRun(
   12503       "o.foo = 17;"
   12504       "var receiver = {};"
   12505       "receiver.__proto__ = o;"
   12506       "var result = 0;"
   12507       "var saved_result = 0;"
   12508       "for (var i = 0; i < 100; i++) {"
   12509       "  result = receiver.method(41);"
   12510       "  if (i == 50) {"
   12511       "    saved_result = result;"
   12512       "    receiver = 333;"
   12513       "  }"
   12514       "}");
   12515   CHECK(try_catch.HasCaught());
   12516   // TODO(verwaest): Adjust message.
   12517   CHECK_EQ(v8_str("TypeError: undefined is not a function"),
   12518            try_catch.Exception()->ToString());
   12519   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12520   CHECK_GE(interceptor_call_count, 50);
   12521 }
   12522 
   12523 
   12524 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
   12525   int interceptor_call_count = 0;
   12526   v8::Isolate* isolate = CcTest::isolate();
   12527   v8::HandleScope scope(isolate);
   12528   v8::Handle<v8::FunctionTemplate> fun_templ =
   12529       v8::FunctionTemplate::New(isolate);
   12530   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12531       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12532       v8::Signature::New(isolate, fun_templ));
   12533   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12534   proto_templ->Set(v8_str("method"), method_templ);
   12535   fun_templ->SetHiddenPrototype(true);
   12536   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12537   templ->SetNamedPropertyHandler(
   12538       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12539       v8::External::New(isolate, &interceptor_call_count));
   12540   LocalContext context;
   12541   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12542   GenerateSomeGarbage();
   12543   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12544   v8::TryCatch try_catch;
   12545   CompileRun(
   12546       "o.foo = 17;"
   12547       "var receiver = {};"
   12548       "receiver.__proto__ = o;"
   12549       "var result = 0;"
   12550       "var saved_result = 0;"
   12551       "for (var i = 0; i < 100; i++) {"
   12552       "  result = receiver.method(41);"
   12553       "  if (i == 50) {"
   12554       "    saved_result = result;"
   12555       "    receiver = {method: receiver.method};"
   12556       "  }"
   12557       "}");
   12558   CHECK(try_catch.HasCaught());
   12559   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
   12560            try_catch.Exception()->ToString());
   12561   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12562   CHECK_GE(interceptor_call_count, 50);
   12563 }
   12564 
   12565 
   12566 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   12567   v8::Isolate* isolate = CcTest::isolate();
   12568   v8::HandleScope scope(isolate);
   12569   v8::Handle<v8::FunctionTemplate> fun_templ =
   12570       v8::FunctionTemplate::New(isolate);
   12571   v8::Handle<v8::FunctionTemplate> method_templ =
   12572       v8::FunctionTemplate::New(isolate,
   12573                                 FastApiCallback_TrivialSignature,
   12574                                 v8_str("method_data"),
   12575                                 v8::Handle<v8::Signature>());
   12576   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12577   proto_templ->Set(v8_str("method"), method_templ);
   12578   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12579   USE(templ);
   12580   LocalContext context;
   12581   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12582   GenerateSomeGarbage();
   12583   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12584   CompileRun(
   12585       "var result = 0;"
   12586       "for (var i = 0; i < 100; i++) {"
   12587       "  result = o.method(41);"
   12588       "}");
   12589 
   12590   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   12591 }
   12592 
   12593 
   12594 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
   12595   v8::Isolate* isolate = CcTest::isolate();
   12596   v8::HandleScope scope(isolate);
   12597   v8::Handle<v8::FunctionTemplate> fun_templ =
   12598       v8::FunctionTemplate::New(isolate);
   12599   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12600       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12601       v8::Signature::New(isolate, fun_templ));
   12602   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12603   proto_templ->Set(v8_str("method"), method_templ);
   12604   fun_templ->SetHiddenPrototype(true);
   12605   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12606   CHECK(!templ.IsEmpty());
   12607   LocalContext context;
   12608   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12609   GenerateSomeGarbage();
   12610   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12611   CompileRun(
   12612       "o.foo = 17;"
   12613       "var receiver = {};"
   12614       "receiver.__proto__ = o;"
   12615       "var result = 0;"
   12616       "for (var i = 0; i < 100; i++) {"
   12617       "  result = receiver.method(41);"
   12618       "}");
   12619 
   12620   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   12621 }
   12622 
   12623 
   12624 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   12625   v8::Isolate* isolate = CcTest::isolate();
   12626   v8::HandleScope scope(isolate);
   12627   v8::Handle<v8::FunctionTemplate> fun_templ =
   12628       v8::FunctionTemplate::New(isolate);
   12629   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12630       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12631       v8::Signature::New(isolate, fun_templ));
   12632   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12633   proto_templ->Set(v8_str("method"), method_templ);
   12634   fun_templ->SetHiddenPrototype(true);
   12635   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12636   CHECK(!templ.IsEmpty());
   12637   LocalContext context;
   12638   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12639   GenerateSomeGarbage();
   12640   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12641   CompileRun(
   12642       "o.foo = 17;"
   12643       "var receiver = {};"
   12644       "receiver.__proto__ = o;"
   12645       "var result = 0;"
   12646       "var saved_result = 0;"
   12647       "for (var i = 0; i < 100; i++) {"
   12648       "  result = receiver.method(41);"
   12649       "  if (i == 50) {"
   12650       "    saved_result = result;"
   12651       "    receiver = {method: function(x) { return x - 1 }};"
   12652       "  }"
   12653       "}");
   12654   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   12655   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12656 }
   12657 
   12658 
   12659 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   12660   v8::Isolate* isolate = CcTest::isolate();
   12661   v8::HandleScope scope(isolate);
   12662   v8::Handle<v8::FunctionTemplate> fun_templ =
   12663       v8::FunctionTemplate::New(isolate);
   12664   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12665       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12666       v8::Signature::New(isolate, fun_templ));
   12667   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12668   proto_templ->Set(v8_str("method"), method_templ);
   12669   fun_templ->SetHiddenPrototype(true);
   12670   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12671   CHECK(!templ.IsEmpty());
   12672   LocalContext context;
   12673   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12674   GenerateSomeGarbage();
   12675   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12676   v8::TryCatch try_catch;
   12677   CompileRun(
   12678       "o.foo = 17;"
   12679       "var receiver = {};"
   12680       "receiver.__proto__ = o;"
   12681       "var result = 0;"
   12682       "var saved_result = 0;"
   12683       "for (var i = 0; i < 100; i++) {"
   12684       "  result = receiver.method(41);"
   12685       "  if (i == 50) {"
   12686       "    saved_result = result;"
   12687       "    receiver = 333;"
   12688       "  }"
   12689       "}");
   12690   CHECK(try_catch.HasCaught());
   12691   // TODO(verwaest): Adjust message.
   12692   CHECK_EQ(v8_str("TypeError: undefined is not a function"),
   12693            try_catch.Exception()->ToString());
   12694   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12695 }
   12696 
   12697 
   12698 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
   12699   v8::Isolate* isolate = CcTest::isolate();
   12700   v8::HandleScope scope(isolate);
   12701   v8::Handle<v8::FunctionTemplate> fun_templ =
   12702       v8::FunctionTemplate::New(isolate);
   12703   v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12704       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12705       v8::Signature::New(isolate, fun_templ));
   12706   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12707   proto_templ->Set(v8_str("method"), method_templ);
   12708   fun_templ->SetHiddenPrototype(true);
   12709   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12710   CHECK(!templ.IsEmpty());
   12711   LocalContext context;
   12712   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   12713   GenerateSomeGarbage();
   12714   context->Global()->Set(v8_str("o"), fun->NewInstance());
   12715   v8::TryCatch try_catch;
   12716   CompileRun(
   12717       "o.foo = 17;"
   12718       "var receiver = {};"
   12719       "receiver.__proto__ = o;"
   12720       "var result = 0;"
   12721       "var saved_result = 0;"
   12722       "for (var i = 0; i < 100; i++) {"
   12723       "  result = receiver.method(41);"
   12724       "  if (i == 50) {"
   12725       "    saved_result = result;"
   12726       "    receiver = Object.create(receiver);"
   12727       "  }"
   12728       "}");
   12729   CHECK(try_catch.HasCaught());
   12730   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
   12731            try_catch.Exception()->ToString());
   12732   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12733 }
   12734 
   12735 
   12736 v8::Handle<Value> keyed_call_ic_function;
   12737 
   12738 static void InterceptorKeyedCallICGetter(
   12739     Local<String> name,
   12740     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12741   ApiTestFuzzer::Fuzz();
   12742   if (v8_str("x")->Equals(name)) {
   12743     info.GetReturnValue().Set(keyed_call_ic_function);
   12744   }
   12745 }
   12746 
   12747 
   12748 // Test the case when we stored cacheable lookup into
   12749 // a stub, but the function name changed (to another cacheable function).
   12750 THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
   12751   v8::Isolate* isolate = CcTest::isolate();
   12752   v8::HandleScope scope(isolate);
   12753   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12754   templ->SetNamedPropertyHandler(NoBlockGetterX);
   12755   LocalContext context;
   12756   context->Global()->Set(v8_str("o"), templ->NewInstance());
   12757   CompileRun(
   12758     "proto = new Object();"
   12759     "proto.y = function(x) { return x + 1; };"
   12760     "proto.z = function(x) { return x - 1; };"
   12761     "o.__proto__ = proto;"
   12762     "var result = 0;"
   12763     "var method = 'y';"
   12764     "for (var i = 0; i < 10; i++) {"
   12765     "  if (i == 5) { method = 'z'; };"
   12766     "  result += o[method](41);"
   12767     "}");
   12768   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12769 }
   12770 
   12771 
   12772 // Test the case when we stored cacheable lookup into
   12773 // a stub, but the function name changed (and the new function is present
   12774 // both before and after the interceptor in the prototype chain).
   12775 THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
   12776   v8::Isolate* isolate = CcTest::isolate();
   12777   v8::HandleScope scope(isolate);
   12778   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12779   templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
   12780   LocalContext context;
   12781   context->Global()->Set(v8_str("proto1"), templ->NewInstance());
   12782   keyed_call_ic_function =
   12783       v8_compile("function f(x) { return x - 1; }; f")->Run();
   12784   CompileRun(
   12785     "o = new Object();"
   12786     "proto2 = new Object();"
   12787     "o.y = function(x) { return x + 1; };"
   12788     "proto2.y = function(x) { return x + 2; };"
   12789     "o.__proto__ = proto1;"
   12790     "proto1.__proto__ = proto2;"
   12791     "var result = 0;"
   12792     "var method = 'x';"
   12793     "for (var i = 0; i < 10; i++) {"
   12794     "  if (i == 5) { method = 'y'; };"
   12795     "  result += o[method](41);"
   12796     "}");
   12797   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12798 }
   12799 
   12800 
   12801 // Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
   12802 // on the global object.
   12803 THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
   12804   v8::Isolate* isolate = CcTest::isolate();
   12805   v8::HandleScope scope(isolate);
   12806   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12807   templ->SetNamedPropertyHandler(NoBlockGetterX);
   12808   LocalContext context;
   12809   context->Global()->Set(v8_str("o"), templ->NewInstance());
   12810   CompileRun(
   12811     "function inc(x) { return x + 1; };"
   12812     "inc(1);"
   12813     "function dec(x) { return x - 1; };"
   12814     "dec(1);"
   12815     "o.__proto__ = this;"
   12816     "this.__proto__.x = inc;"
   12817     "this.__proto__.y = dec;"
   12818     "var result = 0;"
   12819     "var method = 'x';"
   12820     "for (var i = 0; i < 10; i++) {"
   12821     "  if (i == 5) { method = 'y'; };"
   12822     "  result += o[method](41);"
   12823     "}");
   12824   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12825 }
   12826 
   12827 
   12828 // Test the case when actual function to call sits on global object.
   12829 THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
   12830   v8::Isolate* isolate = CcTest::isolate();
   12831   v8::HandleScope scope(isolate);
   12832   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
   12833   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   12834   LocalContext context;
   12835   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   12836 
   12837   CompileRun(
   12838     "function len(x) { return x.length; };"
   12839     "o.__proto__ = this;"
   12840     "var m = 'parseFloat';"
   12841     "var result = 0;"
   12842     "for (var i = 0; i < 10; i++) {"
   12843     "  if (i == 5) {"
   12844     "    m = 'len';"
   12845     "    saved_result = result;"
   12846     "  };"
   12847     "  result = o[m]('239');"
   12848     "}");
   12849   CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
   12850   CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   12851 }
   12852 
   12853 
   12854 // Test the map transition before the interceptor.
   12855 THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
   12856   v8::Isolate* isolate = CcTest::isolate();
   12857   v8::HandleScope scope(isolate);
   12858   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
   12859   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   12860   LocalContext context;
   12861   context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
   12862 
   12863   CompileRun(
   12864     "var o = new Object();"
   12865     "o.__proto__ = proto;"
   12866     "o.method = function(x) { return x + 1; };"
   12867     "var m = 'method';"
   12868     "var result = 0;"
   12869     "for (var i = 0; i < 10; i++) {"
   12870     "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
   12871     "  result += o[m](41);"
   12872     "}");
   12873   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12874 }
   12875 
   12876 
   12877 // Test the map transition after the interceptor.
   12878 THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
   12879   v8::Isolate* isolate = CcTest::isolate();
   12880   v8::HandleScope scope(isolate);
   12881   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
   12882   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   12883   LocalContext context;
   12884   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   12885 
   12886   CompileRun(
   12887     "var proto = new Object();"
   12888     "o.__proto__ = proto;"
   12889     "proto.method = function(x) { return x + 1; };"
   12890     "var m = 'method';"
   12891     "var result = 0;"
   12892     "for (var i = 0; i < 10; i++) {"
   12893     "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
   12894     "  result += o[m](41);"
   12895     "}");
   12896   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   12897 }
   12898 
   12899 
   12900 static int interceptor_call_count = 0;
   12901 
   12902 static void InterceptorICRefErrorGetter(
   12903     Local<String> name,
   12904     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12905   ApiTestFuzzer::Fuzz();
   12906   if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
   12907     info.GetReturnValue().Set(call_ic_function2);
   12908   }
   12909 }
   12910 
   12911 
   12912 // This test should hit load and call ICs for the interceptor case.
   12913 // Once in a while, the interceptor will reply that a property was not
   12914 // found in which case we should get a reference error.
   12915 THREADED_TEST(InterceptorICReferenceErrors) {
   12916   v8::Isolate* isolate = CcTest::isolate();
   12917   v8::HandleScope scope(isolate);
   12918   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12919   templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
   12920   LocalContext context(0, templ, v8::Handle<Value>());
   12921   call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
   12922   v8::Handle<Value> value = CompileRun(
   12923     "function f() {"
   12924     "  for (var i = 0; i < 1000; i++) {"
   12925     "    try { x; } catch(e) { return true; }"
   12926     "  }"
   12927     "  return false;"
   12928     "};"
   12929     "f();");
   12930   CHECK_EQ(true, value->BooleanValue());
   12931   interceptor_call_count = 0;
   12932   value = CompileRun(
   12933     "function g() {"
   12934     "  for (var i = 0; i < 1000; i++) {"
   12935     "    try { x(42); } catch(e) { return true; }"
   12936     "  }"
   12937     "  return false;"
   12938     "};"
   12939     "g();");
   12940   CHECK_EQ(true, value->BooleanValue());
   12941 }
   12942 
   12943 
   12944 static int interceptor_ic_exception_get_count = 0;
   12945 
   12946 static void InterceptorICExceptionGetter(
   12947     Local<String> name,
   12948     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12949   ApiTestFuzzer::Fuzz();
   12950   if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
   12951     info.GetReturnValue().Set(call_ic_function3);
   12952   }
   12953   if (interceptor_ic_exception_get_count == 20) {
   12954     info.GetIsolate()->ThrowException(v8_num(42));
   12955     return;
   12956   }
   12957 }
   12958 
   12959 
   12960 // Test interceptor load/call IC where the interceptor throws an
   12961 // exception once in a while.
   12962 THREADED_TEST(InterceptorICGetterExceptions) {
   12963   interceptor_ic_exception_get_count = 0;
   12964   v8::Isolate* isolate = CcTest::isolate();
   12965   v8::HandleScope scope(isolate);
   12966   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12967   templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
   12968   LocalContext context(0, templ, v8::Handle<Value>());
   12969   call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
   12970   v8::Handle<Value> value = CompileRun(
   12971     "function f() {"
   12972     "  for (var i = 0; i < 100; i++) {"
   12973     "    try { x; } catch(e) { return true; }"
   12974     "  }"
   12975     "  return false;"
   12976     "};"
   12977     "f();");
   12978   CHECK_EQ(true, value->BooleanValue());
   12979   interceptor_ic_exception_get_count = 0;
   12980   value = CompileRun(
   12981     "function f() {"
   12982     "  for (var i = 0; i < 100; i++) {"
   12983     "    try { x(42); } catch(e) { return true; }"
   12984     "  }"
   12985     "  return false;"
   12986     "};"
   12987     "f();");
   12988   CHECK_EQ(true, value->BooleanValue());
   12989 }
   12990 
   12991 
   12992 static int interceptor_ic_exception_set_count = 0;
   12993 
   12994 static void InterceptorICExceptionSetter(
   12995       Local<String> key,
   12996       Local<Value> value,
   12997       const v8::PropertyCallbackInfo<v8::Value>& info) {
   12998   ApiTestFuzzer::Fuzz();
   12999   if (++interceptor_ic_exception_set_count > 20) {
   13000     info.GetIsolate()->ThrowException(v8_num(42));
   13001   }
   13002 }
   13003 
   13004 
   13005 // Test interceptor store IC where the interceptor throws an exception
   13006 // once in a while.
   13007 THREADED_TEST(InterceptorICSetterExceptions) {
   13008   interceptor_ic_exception_set_count = 0;
   13009   v8::Isolate* isolate = CcTest::isolate();
   13010   v8::HandleScope scope(isolate);
   13011   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   13012   templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
   13013   LocalContext context(0, templ, v8::Handle<Value>());
   13014   v8::Handle<Value> value = CompileRun(
   13015     "function f() {"
   13016     "  for (var i = 0; i < 100; i++) {"
   13017     "    try { x = 42; } catch(e) { return true; }"
   13018     "  }"
   13019     "  return false;"
   13020     "};"
   13021     "f();");
   13022   CHECK_EQ(true, value->BooleanValue());
   13023 }
   13024 
   13025 
   13026 // Test that we ignore null interceptors.
   13027 THREADED_TEST(NullNamedInterceptor) {
   13028   v8::Isolate* isolate = CcTest::isolate();
   13029   v8::HandleScope scope(isolate);
   13030   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   13031   templ->SetNamedPropertyHandler(
   13032       static_cast<v8::NamedPropertyGetterCallback>(0));
   13033   LocalContext context;
   13034   templ->Set(CcTest::isolate(), "x", v8_num(42));
   13035   v8::Handle<v8::Object> obj = templ->NewInstance();
   13036   context->Global()->Set(v8_str("obj"), obj);
   13037   v8::Handle<Value> value = CompileRun("obj.x");
   13038   CHECK(value->IsInt32());
   13039   CHECK_EQ(42, value->Int32Value());
   13040 }
   13041 
   13042 
   13043 // Test that we ignore null interceptors.
   13044 THREADED_TEST(NullIndexedInterceptor) {
   13045   v8::Isolate* isolate = CcTest::isolate();
   13046   v8::HandleScope scope(isolate);
   13047   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   13048   templ->SetIndexedPropertyHandler(
   13049       static_cast<v8::IndexedPropertyGetterCallback>(0));
   13050   LocalContext context;
   13051   templ->Set(CcTest::isolate(), "42", v8_num(42));
   13052   v8::Handle<v8::Object> obj = templ->NewInstance();
   13053   context->Global()->Set(v8_str("obj"), obj);
   13054   v8::Handle<Value> value = CompileRun("obj[42]");
   13055   CHECK(value->IsInt32());
   13056   CHECK_EQ(42, value->Int32Value());
   13057 }
   13058 
   13059 
   13060 THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
   13061   v8::Isolate* isolate = CcTest::isolate();
   13062   v8::HandleScope scope(isolate);
   13063   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13064   templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   13065   LocalContext env;
   13066   env->Global()->Set(v8_str("obj"),
   13067                      templ->GetFunction()->NewInstance());
   13068   ExpectTrue("obj.x === 42");
   13069   ExpectTrue("!obj.propertyIsEnumerable('x')");
   13070 }
   13071 
   13072 
   13073 static void ThrowingGetter(Local<String> name,
   13074                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   13075   ApiTestFuzzer::Fuzz();
   13076   info.GetIsolate()->ThrowException(Handle<Value>());
   13077   info.GetReturnValue().SetUndefined();
   13078 }
   13079 
   13080 
   13081 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   13082   LocalContext context;
   13083   HandleScope scope(context->GetIsolate());
   13084 
   13085   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   13086   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   13087   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   13088 
   13089   Local<Object> instance = templ->GetFunction()->NewInstance();
   13090 
   13091   Local<Object> another = Object::New(context->GetIsolate());
   13092   another->SetPrototype(instance);
   13093 
   13094   Local<Object> with_js_getter = CompileRun(
   13095       "o = {};\n"
   13096       "o.__defineGetter__('f', function() { throw undefined; });\n"
   13097       "o\n").As<Object>();
   13098   CHECK(!with_js_getter.IsEmpty());
   13099 
   13100   TryCatch try_catch;
   13101 
   13102   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
   13103   CHECK(try_catch.HasCaught());
   13104   try_catch.Reset();
   13105   CHECK(result.IsEmpty());
   13106 
   13107   result = another->GetRealNamedProperty(v8_str("f"));
   13108   CHECK(try_catch.HasCaught());
   13109   try_catch.Reset();
   13110   CHECK(result.IsEmpty());
   13111 
   13112   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
   13113   CHECK(try_catch.HasCaught());
   13114   try_catch.Reset();
   13115   CHECK(result.IsEmpty());
   13116 
   13117   result = another->Get(v8_str("f"));
   13118   CHECK(try_catch.HasCaught());
   13119   try_catch.Reset();
   13120   CHECK(result.IsEmpty());
   13121 
   13122   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
   13123   CHECK(try_catch.HasCaught());
   13124   try_catch.Reset();
   13125   CHECK(result.IsEmpty());
   13126 
   13127   result = with_js_getter->Get(v8_str("f"));
   13128   CHECK(try_catch.HasCaught());
   13129   try_catch.Reset();
   13130   CHECK(result.IsEmpty());
   13131 }
   13132 
   13133 
   13134 static void ThrowingCallbackWithTryCatch(
   13135     const v8::FunctionCallbackInfo<v8::Value>& args) {
   13136   TryCatch try_catch;
   13137   // Verboseness is important: it triggers message delivery which can call into
   13138   // external code.
   13139   try_catch.SetVerbose(true);
   13140   CompileRun("throw 'from JS';");
   13141   CHECK(try_catch.HasCaught());
   13142   CHECK(!CcTest::i_isolate()->has_pending_exception());
   13143   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   13144 }
   13145 
   13146 
   13147 static int call_depth;
   13148 
   13149 
   13150 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
   13151   TryCatch try_catch;
   13152 }
   13153 
   13154 
   13155 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
   13156   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   13157 }
   13158 
   13159 
   13160 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
   13161   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
   13162 }
   13163 
   13164 
   13165 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
   13166   Handle<String> errorMessageString = message->Get();
   13167   CHECK(!errorMessageString.IsEmpty());
   13168   message->GetStackTrace();
   13169   message->GetScriptOrigin().ResourceName();
   13170 }
   13171 
   13172 
   13173 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   13174   LocalContext context;
   13175   v8::Isolate* isolate = context->GetIsolate();
   13176   HandleScope scope(isolate);
   13177 
   13178   Local<Function> func =
   13179       FunctionTemplate::New(isolate,
   13180                             ThrowingCallbackWithTryCatch)->GetFunction();
   13181   context->Global()->Set(v8_str("func"), func);
   13182 
   13183   MessageCallback callbacks[] =
   13184       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
   13185   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   13186     MessageCallback callback = callbacks[i];
   13187     if (callback != NULL) {
   13188       V8::AddMessageListener(callback);
   13189     }
   13190     // Some small number to control number of times message handler should
   13191     // throw an exception.
   13192     call_depth = 5;
   13193     ExpectFalse(
   13194         "var thrown = false;\n"
   13195         "try { func(); } catch(e) { thrown = true; }\n"
   13196         "thrown\n");
   13197     if (callback != NULL) {
   13198       V8::RemoveMessageListeners(callback);
   13199     }
   13200   }
   13201 }
   13202 
   13203 
   13204 static void ParentGetter(Local<String> name,
   13205                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   13206   ApiTestFuzzer::Fuzz();
   13207   info.GetReturnValue().Set(v8_num(1));
   13208 }
   13209 
   13210 
   13211 static void ChildGetter(Local<String> name,
   13212                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   13213   ApiTestFuzzer::Fuzz();
   13214   info.GetReturnValue().Set(v8_num(42));
   13215 }
   13216 
   13217 
   13218 THREADED_TEST(Overriding) {
   13219   LocalContext context;
   13220   v8::Isolate* isolate = context->GetIsolate();
   13221   v8::HandleScope scope(isolate);
   13222 
   13223   // Parent template.
   13224   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
   13225   Local<ObjectTemplate> parent_instance_templ =
   13226       parent_templ->InstanceTemplate();
   13227   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   13228 
   13229   // Template that inherits from the parent template.
   13230   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
   13231   Local<ObjectTemplate> child_instance_templ =
   13232       child_templ->InstanceTemplate();
   13233   child_templ->Inherit(parent_templ);
   13234   // Override 'f'.  The child version of 'f' should get called for child
   13235   // instances.
   13236   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   13237   // Add 'g' twice.  The 'g' added last should get called for instances.
   13238   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   13239   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   13240 
   13241   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   13242   // so 'h' can be shadowed on the instance object.
   13243   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   13244   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
   13245       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   13246 
   13247   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   13248   // but the attribute does not have effect because it is duplicated with
   13249   // NULL setter.
   13250   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
   13251       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   13252 
   13253 
   13254 
   13255   // Instantiate the child template.
   13256   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
   13257 
   13258   // Check that the child function overrides the parent one.
   13259   context->Global()->Set(v8_str("o"), instance);
   13260   Local<Value> value = v8_compile("o.f")->Run();
   13261   // Check that the 'g' that was added last is hit.
   13262   CHECK_EQ(42, value->Int32Value());
   13263   value = v8_compile("o.g")->Run();
   13264   CHECK_EQ(42, value->Int32Value());
   13265 
   13266   // Check that 'h' cannot be shadowed.
   13267   value = v8_compile("o.h = 3; o.h")->Run();
   13268   CHECK_EQ(1, value->Int32Value());
   13269 
   13270   // Check that 'i' cannot be shadowed or changed.
   13271   value = v8_compile("o.i = 3; o.i")->Run();
   13272   CHECK_EQ(42, value->Int32Value());
   13273 }
   13274 
   13275 
   13276 static void IsConstructHandler(
   13277     const v8::FunctionCallbackInfo<v8::Value>& args) {
   13278   ApiTestFuzzer::Fuzz();
   13279   args.GetReturnValue().Set(args.IsConstructCall());
   13280 }
   13281 
   13282 
   13283 THREADED_TEST(IsConstructCall) {
   13284   v8::Isolate* isolate = CcTest::isolate();
   13285   v8::HandleScope scope(isolate);
   13286 
   13287   // Function template with call handler.
   13288   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13289   templ->SetCallHandler(IsConstructHandler);
   13290 
   13291   LocalContext context;
   13292 
   13293   context->Global()->Set(v8_str("f"), templ->GetFunction());
   13294   Local<Value> value = v8_compile("f()")->Run();
   13295   CHECK(!value->BooleanValue());
   13296   value = v8_compile("new f()")->Run();
   13297   CHECK(value->BooleanValue());
   13298 }
   13299 
   13300 
   13301 THREADED_TEST(ObjectProtoToString) {
   13302   v8::Isolate* isolate = CcTest::isolate();
   13303   v8::HandleScope scope(isolate);
   13304   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13305   templ->SetClassName(v8_str("MyClass"));
   13306 
   13307   LocalContext context;
   13308 
   13309   Local<String> customized_tostring = v8_str("customized toString");
   13310 
   13311   // Replace Object.prototype.toString
   13312   v8_compile("Object.prototype.toString = function() {"
   13313                   "  return 'customized toString';"
   13314                   "}")->Run();
   13315 
   13316   // Normal ToString call should call replaced Object.prototype.toString
   13317   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
   13318   Local<String> value = instance->ToString();
   13319   CHECK(value->IsString() && value->Equals(customized_tostring));
   13320 
   13321   // ObjectProtoToString should not call replace toString function.
   13322   value = instance->ObjectProtoToString();
   13323   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
   13324 
   13325   // Check global
   13326   value = context->Global()->ObjectProtoToString();
   13327   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
   13328 
   13329   // Check ordinary object
   13330   Local<Value> object = v8_compile("new Object()")->Run();
   13331   value = object.As<v8::Object>()->ObjectProtoToString();
   13332   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
   13333 }
   13334 
   13335 
   13336 THREADED_TEST(ObjectGetConstructorName) {
   13337   LocalContext context;
   13338   v8::HandleScope scope(context->GetIsolate());
   13339   v8_compile("function Parent() {};"
   13340              "function Child() {};"
   13341              "Child.prototype = new Parent();"
   13342              "var outer = { inner: function() { } };"
   13343              "var p = new Parent();"
   13344              "var c = new Child();"
   13345              "var x = new outer.inner();")->Run();
   13346 
   13347   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
   13348   CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
   13349       v8_str("Parent")));
   13350 
   13351   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
   13352   CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
   13353       v8_str("Child")));
   13354 
   13355   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
   13356   CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
   13357       v8_str("outer.inner")));
   13358 }
   13359 
   13360 
   13361 bool ApiTestFuzzer::fuzzing_ = false;
   13362 v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
   13363 int ApiTestFuzzer::active_tests_;
   13364 int ApiTestFuzzer::tests_being_run_;
   13365 int ApiTestFuzzer::current_;
   13366 
   13367 
   13368 // We are in a callback and want to switch to another thread (if we
   13369 // are currently running the thread fuzzing test).
   13370 void ApiTestFuzzer::Fuzz() {
   13371   if (!fuzzing_) return;
   13372   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   13373   test->ContextSwitch();
   13374 }
   13375 
   13376 
   13377 // Let the next thread go.  Since it is also waiting on the V8 lock it may
   13378 // not start immediately.
   13379 bool ApiTestFuzzer::NextThread() {
   13380   int test_position = GetNextTestNumber();
   13381   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   13382   if (test_position == current_) {
   13383     if (kLogThreading)
   13384       printf("Stay with %s\n", test_name);
   13385     return false;
   13386   }
   13387   if (kLogThreading) {
   13388     printf("Switch from %s to %s\n",
   13389            test_name,
   13390            RegisterThreadedTest::nth(test_position)->name());
   13391   }
   13392   current_ = test_position;
   13393   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
   13394   return true;
   13395 }
   13396 
   13397 
   13398 void ApiTestFuzzer::Run() {
   13399   // When it is our turn...
   13400   gate_.Wait();
   13401   {
   13402     // ... get the V8 lock and start running the test.
   13403     v8::Locker locker(CcTest::isolate());
   13404     CallTest();
   13405   }
   13406   // This test finished.
   13407   active_ = false;
   13408   active_tests_--;
   13409   // If it was the last then signal that fact.
   13410   if (active_tests_ == 0) {
   13411     all_tests_done_.Signal();
   13412   } else {
   13413     // Otherwise select a new test and start that.
   13414     NextThread();
   13415   }
   13416 }
   13417 
   13418 
   13419 static unsigned linear_congruential_generator;
   13420 
   13421 
   13422 void ApiTestFuzzer::SetUp(PartOfTest part) {
   13423   linear_congruential_generator = i::FLAG_testing_prng_seed;
   13424   fuzzing_ = true;
   13425   int count = RegisterThreadedTest::count();
   13426   int start =  count * part / (LAST_PART + 1);
   13427   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   13428   active_tests_ = tests_being_run_ = end - start + 1;
   13429   for (int i = 0; i < tests_being_run_; i++) {
   13430     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   13431   }
   13432   for (int i = 0; i < active_tests_; i++) {
   13433     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   13434   }
   13435 }
   13436 
   13437 
   13438 static void CallTestNumber(int test_number) {
   13439   (RegisterThreadedTest::nth(test_number)->callback())();
   13440 }
   13441 
   13442 
   13443 void ApiTestFuzzer::RunAllTests() {
   13444   // Set off the first test.
   13445   current_ = -1;
   13446   NextThread();
   13447   // Wait till they are all done.
   13448   all_tests_done_.Wait();
   13449 }
   13450 
   13451 
   13452 int ApiTestFuzzer::GetNextTestNumber() {
   13453   int next_test;
   13454   do {
   13455     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   13456     linear_congruential_generator *= 1664525u;
   13457     linear_congruential_generator += 1013904223u;
   13458   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   13459   return next_test;
   13460 }
   13461 
   13462 
   13463 void ApiTestFuzzer::ContextSwitch() {
   13464   // If the new thread is the same as the current thread there is nothing to do.
   13465   if (NextThread()) {
   13466     // Now it can start.
   13467     v8::Unlocker unlocker(CcTest::isolate());
   13468     // Wait till someone starts us again.
   13469     gate_.Wait();
   13470     // And we're off.
   13471   }
   13472 }
   13473 
   13474 
   13475 void ApiTestFuzzer::TearDown() {
   13476   fuzzing_ = false;
   13477   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   13478     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   13479     if (fuzzer != NULL) fuzzer->Join();
   13480   }
   13481 }
   13482 
   13483 
   13484 // Lets not be needlessly self-referential.
   13485 TEST(Threading1) {
   13486   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
   13487   ApiTestFuzzer::RunAllTests();
   13488   ApiTestFuzzer::TearDown();
   13489 }
   13490 
   13491 
   13492 TEST(Threading2) {
   13493   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
   13494   ApiTestFuzzer::RunAllTests();
   13495   ApiTestFuzzer::TearDown();
   13496 }
   13497 
   13498 
   13499 TEST(Threading3) {
   13500   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
   13501   ApiTestFuzzer::RunAllTests();
   13502   ApiTestFuzzer::TearDown();
   13503 }
   13504 
   13505 
   13506 TEST(Threading4) {
   13507   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
   13508   ApiTestFuzzer::RunAllTests();
   13509   ApiTestFuzzer::TearDown();
   13510 }
   13511 
   13512 
   13513 void ApiTestFuzzer::CallTest() {
   13514   v8::Isolate::Scope scope(CcTest::isolate());
   13515   if (kLogThreading)
   13516     printf("Start test %d\n", test_number_);
   13517   CallTestNumber(test_number_);
   13518   if (kLogThreading)
   13519     printf("End test %d\n", test_number_);
   13520 }
   13521 
   13522 
   13523 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13524   v8::Isolate* isolate = args.GetIsolate();
   13525   CHECK(v8::Locker::IsLocked(isolate));
   13526   ApiTestFuzzer::Fuzz();
   13527   v8::Unlocker unlocker(isolate);
   13528   const char* code = "throw 7;";
   13529   {
   13530     v8::Locker nested_locker(isolate);
   13531     v8::HandleScope scope(isolate);
   13532     v8::Handle<Value> exception;
   13533     { v8::TryCatch try_catch;
   13534       v8::Handle<Value> value = CompileRun(code);
   13535       CHECK(value.IsEmpty());
   13536       CHECK(try_catch.HasCaught());
   13537       // Make sure to wrap the exception in a new handle because
   13538       // the handle returned from the TryCatch is destroyed
   13539       // when the TryCatch is destroyed.
   13540       exception = Local<Value>::New(isolate, try_catch.Exception());
   13541     }
   13542     args.GetIsolate()->ThrowException(exception);
   13543   }
   13544 }
   13545 
   13546 
   13547 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13548   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13549   ApiTestFuzzer::Fuzz();
   13550   v8::Unlocker unlocker(CcTest::isolate());
   13551   const char* code = "throw 7;";
   13552   {
   13553     v8::Locker nested_locker(CcTest::isolate());
   13554     v8::HandleScope scope(args.GetIsolate());
   13555     v8::Handle<Value> value = CompileRun(code);
   13556     CHECK(value.IsEmpty());
   13557     args.GetReturnValue().Set(v8_str("foo"));
   13558   }
   13559 }
   13560 
   13561 
   13562 // These are locking tests that don't need to be run again
   13563 // as part of the locking aggregation tests.
   13564 TEST(NestedLockers) {
   13565   v8::Isolate* isolate = CcTest::isolate();
   13566   v8::Locker locker(isolate);
   13567   CHECK(v8::Locker::IsLocked(isolate));
   13568   LocalContext env;
   13569   v8::HandleScope scope(env->GetIsolate());
   13570   Local<v8::FunctionTemplate> fun_templ =
   13571       v8::FunctionTemplate::New(isolate, ThrowInJS);
   13572   Local<Function> fun = fun_templ->GetFunction();
   13573   env->Global()->Set(v8_str("throw_in_js"), fun);
   13574   Local<Script> script = v8_compile("(function () {"
   13575                                     "  try {"
   13576                                     "    throw_in_js();"
   13577                                     "    return 42;"
   13578                                     "  } catch (e) {"
   13579                                     "    return e * 13;"
   13580                                     "  }"
   13581                                     "})();");
   13582   CHECK_EQ(91, script->Run()->Int32Value());
   13583 }
   13584 
   13585 
   13586 // These are locking tests that don't need to be run again
   13587 // as part of the locking aggregation tests.
   13588 TEST(NestedLockersNoTryCatch) {
   13589   v8::Locker locker(CcTest::isolate());
   13590   LocalContext env;
   13591   v8::HandleScope scope(env->GetIsolate());
   13592   Local<v8::FunctionTemplate> fun_templ =
   13593       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
   13594   Local<Function> fun = fun_templ->GetFunction();
   13595   env->Global()->Set(v8_str("throw_in_js"), fun);
   13596   Local<Script> script = v8_compile("(function () {"
   13597                                     "  try {"
   13598                                     "    throw_in_js();"
   13599                                     "    return 42;"
   13600                                     "  } catch (e) {"
   13601                                     "    return e * 13;"
   13602                                     "  }"
   13603                                     "})();");
   13604   CHECK_EQ(91, script->Run()->Int32Value());
   13605 }
   13606 
   13607 
   13608 THREADED_TEST(RecursiveLocking) {
   13609   v8::Locker locker(CcTest::isolate());
   13610   {
   13611     v8::Locker locker2(CcTest::isolate());
   13612     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13613   }
   13614 }
   13615 
   13616 
   13617 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13618   ApiTestFuzzer::Fuzz();
   13619   v8::Unlocker unlocker(CcTest::isolate());
   13620 }
   13621 
   13622 
   13623 THREADED_TEST(LockUnlockLock) {
   13624   {
   13625     v8::Locker locker(CcTest::isolate());
   13626     v8::HandleScope scope(CcTest::isolate());
   13627     LocalContext env;
   13628     Local<v8::FunctionTemplate> fun_templ =
   13629         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13630     Local<Function> fun = fun_templ->GetFunction();
   13631     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   13632     Local<Script> script = v8_compile("(function () {"
   13633                                       "  unlock_for_a_moment();"
   13634                                       "  return 42;"
   13635                                       "})();");
   13636     CHECK_EQ(42, script->Run()->Int32Value());
   13637   }
   13638   {
   13639     v8::Locker locker(CcTest::isolate());
   13640     v8::HandleScope scope(CcTest::isolate());
   13641     LocalContext env;
   13642     Local<v8::FunctionTemplate> fun_templ =
   13643         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13644     Local<Function> fun = fun_templ->GetFunction();
   13645     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   13646     Local<Script> script = v8_compile("(function () {"
   13647                                       "  unlock_for_a_moment();"
   13648                                       "  return 42;"
   13649                                       "})();");
   13650     CHECK_EQ(42, script->Run()->Int32Value());
   13651   }
   13652 }
   13653 
   13654 
   13655 static int GetGlobalObjectsCount() {
   13656   int count = 0;
   13657   i::HeapIterator it(CcTest::heap());
   13658   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
   13659     if (object->IsJSGlobalObject()) count++;
   13660   return count;
   13661 }
   13662 
   13663 
   13664 static void CheckSurvivingGlobalObjectsCount(int expected) {
   13665   // We need to collect all garbage twice to be sure that everything
   13666   // has been collected.  This is because inline caches are cleared in
   13667   // the first garbage collection but some of the maps have already
   13668   // been marked at that point.  Therefore some of the maps are not
   13669   // collected until the second garbage collection.
   13670   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   13671   CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
   13672   int count = GetGlobalObjectsCount();
   13673 #ifdef DEBUG
   13674   if (count != expected) CcTest::heap()->TracePathToGlobal();
   13675 #endif
   13676   CHECK_EQ(expected, count);
   13677 }
   13678 
   13679 
   13680 TEST(DontLeakGlobalObjects) {
   13681   // Regression test for issues 1139850 and 1174891.
   13682 
   13683   i::FLAG_expose_gc = true;
   13684   v8::V8::Initialize();
   13685 
   13686   for (int i = 0; i < 5; i++) {
   13687     { v8::HandleScope scope(CcTest::isolate());
   13688       LocalContext context;
   13689     }
   13690     CcTest::isolate()->ContextDisposedNotification();
   13691     CheckSurvivingGlobalObjectsCount(0);
   13692 
   13693     { v8::HandleScope scope(CcTest::isolate());
   13694       LocalContext context;
   13695       v8_compile("Date")->Run();
   13696     }
   13697     CcTest::isolate()->ContextDisposedNotification();
   13698     CheckSurvivingGlobalObjectsCount(0);
   13699 
   13700     { v8::HandleScope scope(CcTest::isolate());
   13701       LocalContext context;
   13702       v8_compile("/aaa/")->Run();
   13703     }
   13704     CcTest::isolate()->ContextDisposedNotification();
   13705     CheckSurvivingGlobalObjectsCount(0);
   13706 
   13707     { v8::HandleScope scope(CcTest::isolate());
   13708       const char* extension_list[] = { "v8/gc" };
   13709       v8::ExtensionConfiguration extensions(1, extension_list);
   13710       LocalContext context(&extensions);
   13711       v8_compile("gc();")->Run();
   13712     }
   13713     CcTest::isolate()->ContextDisposedNotification();
   13714     CheckSurvivingGlobalObjectsCount(0);
   13715   }
   13716 }
   13717 
   13718 
   13719 TEST(CopyablePersistent) {
   13720   LocalContext context;
   13721   v8::Isolate* isolate = context->GetIsolate();
   13722   i::GlobalHandles* globals =
   13723       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13724   int initial_handles = globals->global_handles_count();
   13725   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
   13726       CopyableObject;
   13727   {
   13728     CopyableObject handle1;
   13729     {
   13730       v8::HandleScope scope(isolate);
   13731       handle1.Reset(isolate, v8::Object::New(isolate));
   13732     }
   13733     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
   13734     CopyableObject  handle2;
   13735     handle2 = handle1;
   13736     CHECK(handle1 == handle2);
   13737     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
   13738     CopyableObject handle3(handle2);
   13739     CHECK(handle1 == handle3);
   13740     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
   13741   }
   13742   // Verify autodispose
   13743   CHECK_EQ(initial_handles, globals->global_handles_count());
   13744 }
   13745 
   13746 
   13747 static void WeakApiCallback(
   13748     const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
   13749   Local<Value> value = data.GetValue()->Get(v8_str("key"));
   13750   CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
   13751   data.GetParameter()->Reset();
   13752   delete data.GetParameter();
   13753 }
   13754 
   13755 
   13756 TEST(WeakCallbackApi) {
   13757   LocalContext context;
   13758   v8::Isolate* isolate = context->GetIsolate();
   13759   i::GlobalHandles* globals =
   13760       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13761   int initial_handles = globals->global_handles_count();
   13762   {
   13763     v8::HandleScope scope(isolate);
   13764     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   13765     obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
   13766     v8::Persistent<v8::Object>* handle =
   13767         new v8::Persistent<v8::Object>(isolate, obj);
   13768     handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
   13769                                                              WeakApiCallback);
   13770   }
   13771   reinterpret_cast<i::Isolate*>(isolate)->heap()->
   13772       CollectAllGarbage(i::Heap::kNoGCFlags);
   13773   // Verify disposed.
   13774   CHECK_EQ(initial_handles, globals->global_handles_count());
   13775 }
   13776 
   13777 
   13778 v8::Persistent<v8::Object> some_object;
   13779 v8::Persistent<v8::Object> bad_handle;
   13780 
   13781 void NewPersistentHandleCallback(
   13782     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
   13783   v8::HandleScope scope(data.GetIsolate());
   13784   bad_handle.Reset(data.GetIsolate(), some_object);
   13785   data.GetParameter()->Reset();
   13786 }
   13787 
   13788 
   13789 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   13790   LocalContext context;
   13791   v8::Isolate* isolate = context->GetIsolate();
   13792 
   13793   v8::Persistent<v8::Object> handle1, handle2;
   13794   {
   13795     v8::HandleScope scope(isolate);
   13796     some_object.Reset(isolate, v8::Object::New(isolate));
   13797     handle1.Reset(isolate, v8::Object::New(isolate));
   13798     handle2.Reset(isolate, v8::Object::New(isolate));
   13799   }
   13800   // Note: order is implementation dependent alas: currently
   13801   // global handle nodes are processed by PostGarbageCollectionProcessing
   13802   // in reverse allocation order, so if second allocated handle is deleted,
   13803   // weak callback of the first handle would be able to 'reallocate' it.
   13804   handle1.SetWeak(&handle1, NewPersistentHandleCallback);
   13805   handle2.Reset();
   13806   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   13807 }
   13808 
   13809 
   13810 v8::Persistent<v8::Object> to_be_disposed;
   13811 
   13812 void DisposeAndForceGcCallback(
   13813     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
   13814   to_be_disposed.Reset();
   13815   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   13816   data.GetParameter()->Reset();
   13817 }
   13818 
   13819 
   13820 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   13821   LocalContext context;
   13822   v8::Isolate* isolate = context->GetIsolate();
   13823 
   13824   v8::Persistent<v8::Object> handle1, handle2;
   13825   {
   13826     v8::HandleScope scope(isolate);
   13827     handle1.Reset(isolate, v8::Object::New(isolate));
   13828     handle2.Reset(isolate, v8::Object::New(isolate));
   13829   }
   13830   handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
   13831   to_be_disposed.Reset(isolate, handle2);
   13832   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   13833 }
   13834 
   13835 void DisposingCallback(
   13836     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
   13837   data.GetParameter()->Reset();
   13838 }
   13839 
   13840 void HandleCreatingCallback(
   13841     const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
   13842   v8::HandleScope scope(data.GetIsolate());
   13843   v8::Persistent<v8::Object>(data.GetIsolate(),
   13844                              v8::Object::New(data.GetIsolate()));
   13845   data.GetParameter()->Reset();
   13846 }
   13847 
   13848 
   13849 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   13850   LocalContext context;
   13851   v8::Isolate* isolate = context->GetIsolate();
   13852 
   13853   v8::Persistent<v8::Object> handle1, handle2, handle3;
   13854   {
   13855     v8::HandleScope scope(isolate);
   13856     handle3.Reset(isolate, v8::Object::New(isolate));
   13857     handle2.Reset(isolate, v8::Object::New(isolate));
   13858     handle1.Reset(isolate, v8::Object::New(isolate));
   13859   }
   13860   handle2.SetWeak(&handle2, DisposingCallback);
   13861   handle3.SetWeak(&handle3, HandleCreatingCallback);
   13862   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   13863 }
   13864 
   13865 
   13866 THREADED_TEST(CheckForCrossContextObjectLiterals) {
   13867   v8::V8::Initialize();
   13868 
   13869   const int nof = 2;
   13870   const char* sources[nof] = {
   13871     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   13872     "Object()"
   13873   };
   13874 
   13875   for (int i = 0; i < nof; i++) {
   13876     const char* source = sources[i];
   13877     { v8::HandleScope scope(CcTest::isolate());
   13878       LocalContext context;
   13879       CompileRun(source);
   13880     }
   13881     { v8::HandleScope scope(CcTest::isolate());
   13882       LocalContext context;
   13883       CompileRun(source);
   13884     }
   13885   }
   13886 }
   13887 
   13888 
   13889 static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
   13890   v8::EscapableHandleScope inner(env->GetIsolate());
   13891   env->Enter();
   13892   v8::Local<Value> three = v8_num(3);
   13893   v8::Local<Value> value = inner.Escape(three);
   13894   env->Exit();
   13895   return value;
   13896 }
   13897 
   13898 
   13899 THREADED_TEST(NestedHandleScopeAndContexts) {
   13900   v8::Isolate* isolate = CcTest::isolate();
   13901   v8::HandleScope outer(isolate);
   13902   v8::Local<Context> env = Context::New(isolate);
   13903   env->Enter();
   13904   v8::Handle<Value> value = NestedScope(env);
   13905   v8::Handle<String> str(value->ToString());
   13906   CHECK(!str.IsEmpty());
   13907   env->Exit();
   13908 }
   13909 
   13910 
   13911 static bool MatchPointers(void* key1, void* key2) {
   13912   return key1 == key2;
   13913 }
   13914 
   13915 
   13916 struct SymbolInfo {
   13917   size_t id;
   13918   size_t size;
   13919   std::string name;
   13920 };
   13921 
   13922 
   13923 class SetFunctionEntryHookTest {
   13924  public:
   13925   SetFunctionEntryHookTest() {
   13926     CHECK(instance_ == NULL);
   13927     instance_ = this;
   13928   }
   13929   ~SetFunctionEntryHookTest() {
   13930     CHECK(instance_ == this);
   13931     instance_ = NULL;
   13932   }
   13933   void Reset() {
   13934     symbols_.clear();
   13935     symbol_locations_.clear();
   13936     invocations_.clear();
   13937   }
   13938   void RunTest();
   13939   void OnJitEvent(const v8::JitCodeEvent* event);
   13940   static void JitEvent(const v8::JitCodeEvent* event) {
   13941     CHECK(instance_ != NULL);
   13942     instance_->OnJitEvent(event);
   13943   }
   13944 
   13945   void OnEntryHook(uintptr_t function,
   13946                    uintptr_t return_addr_location);
   13947   static void EntryHook(uintptr_t function,
   13948                         uintptr_t return_addr_location) {
   13949     CHECK(instance_ != NULL);
   13950     instance_->OnEntryHook(function, return_addr_location);
   13951   }
   13952 
   13953   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13954     CHECK(instance_ != NULL);
   13955     args.GetReturnValue().Set(v8_num(42));
   13956   }
   13957   void RunLoopInNewEnv(v8::Isolate* isolate);
   13958 
   13959   // Records addr as location of symbol.
   13960   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
   13961 
   13962   // Finds the symbol containing addr
   13963   SymbolInfo* FindSymbolForAddr(i::Address addr);
   13964   // Returns the number of invocations where the caller name contains
   13965   // \p caller_name and the function name contains \p function_name.
   13966   int CountInvocations(const char* caller_name,
   13967                        const char* function_name);
   13968 
   13969   i::Handle<i::JSFunction> foo_func_;
   13970   i::Handle<i::JSFunction> bar_func_;
   13971 
   13972   typedef std::map<size_t, SymbolInfo> SymbolMap;
   13973   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
   13974   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
   13975   SymbolMap symbols_;
   13976   SymbolLocationMap symbol_locations_;
   13977   InvocationMap invocations_;
   13978 
   13979   static SetFunctionEntryHookTest* instance_;
   13980 };
   13981 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
   13982 
   13983 
   13984 // Returns true if addr is in the range [start, start+len).
   13985 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
   13986   if (start <= addr && start + len > addr)
   13987     return true;
   13988 
   13989   return false;
   13990 }
   13991 
   13992 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
   13993                                               SymbolInfo* symbol) {
   13994   // Insert the symbol at the new location.
   13995   SymbolLocationMap::iterator it =
   13996       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
   13997   // Now erase symbols to the left and right that overlap this one.
   13998   while (it != symbol_locations_.begin()) {
   13999     SymbolLocationMap::iterator left = it;
   14000     --left;
   14001     if (!Overlaps(left->first, left->second->size, addr))
   14002       break;
   14003     symbol_locations_.erase(left);
   14004   }
   14005 
   14006   // Now erase symbols to the left and right that overlap this one.
   14007   while (true) {
   14008     SymbolLocationMap::iterator right = it;
   14009     ++right;
   14010     if (right == symbol_locations_.end())
   14011         break;
   14012     if (!Overlaps(addr, symbol->size, right->first))
   14013       break;
   14014     symbol_locations_.erase(right);
   14015   }
   14016 }
   14017 
   14018 
   14019 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
   14020   switch (event->type) {
   14021     case v8::JitCodeEvent::CODE_ADDED: {
   14022         CHECK(event->code_start != NULL);
   14023         CHECK_NE(0, static_cast<int>(event->code_len));
   14024         CHECK(event->name.str != NULL);
   14025         size_t symbol_id = symbols_.size();
   14026 
   14027         // Record the new symbol.
   14028         SymbolInfo& info = symbols_[symbol_id];
   14029         info.id = symbol_id;
   14030         info.size = event->code_len;
   14031         info.name.assign(event->name.str, event->name.str + event->name.len);
   14032 
   14033         // And record it's location.
   14034         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
   14035       }
   14036       break;
   14037 
   14038     case v8::JitCodeEvent::CODE_MOVED: {
   14039         // We would like to never see code move that we haven't seen before,
   14040         // but the code creation event does not happen until the line endings
   14041         // have been calculated (this is so that we can report the line in the
   14042         // script at which the function source is found, see
   14043         // Compiler::RecordFunctionCompilation) and the line endings
   14044         // calculations can cause a GC, which can move the newly created code
   14045         // before its existence can be logged.
   14046         SymbolLocationMap::iterator it(
   14047             symbol_locations_.find(
   14048                 reinterpret_cast<i::Address>(event->code_start)));
   14049         if (it != symbol_locations_.end()) {
   14050           // Found a symbol at this location, move it.
   14051           SymbolInfo* info = it->second;
   14052           symbol_locations_.erase(it);
   14053           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
   14054                          info);
   14055         }
   14056       }
   14057     default:
   14058       break;
   14059   }
   14060 }
   14061 
   14062 void SetFunctionEntryHookTest::OnEntryHook(
   14063     uintptr_t function, uintptr_t return_addr_location) {
   14064   // Get the function's code object.
   14065   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
   14066       reinterpret_cast<i::Address>(function));
   14067   CHECK(function_code != NULL);
   14068 
   14069   // Then try and look up the caller's code object.
   14070   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
   14071 
   14072   // Count the invocation.
   14073   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
   14074   SymbolInfo* function_symbol =
   14075       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
   14076   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
   14077 
   14078   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
   14079     // Check that we have a symbol for the "bar" function at the right location.
   14080     SymbolLocationMap::iterator it(
   14081         symbol_locations_.find(function_code->instruction_start()));
   14082     CHECK(it != symbol_locations_.end());
   14083   }
   14084 
   14085   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
   14086     // Check that we have a symbol for "foo" at the right location.
   14087     SymbolLocationMap::iterator it(
   14088         symbol_locations_.find(function_code->instruction_start()));
   14089     CHECK(it != symbol_locations_.end());
   14090   }
   14091 }
   14092 
   14093 
   14094 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
   14095   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
   14096   // Do we have a direct hit on a symbol?
   14097   if (it != symbol_locations_.end()) {
   14098     if (it->first == addr)
   14099       return it->second;
   14100   }
   14101 
   14102   // If not a direct hit, it'll have to be the previous symbol.
   14103   if (it == symbol_locations_.begin())
   14104     return NULL;
   14105 
   14106   --it;
   14107   size_t offs = addr - it->first;
   14108   if (offs < it->second->size)
   14109     return it->second;
   14110 
   14111   return NULL;
   14112 }
   14113 
   14114 
   14115 int SetFunctionEntryHookTest::CountInvocations(
   14116     const char* caller_name, const char* function_name) {
   14117   InvocationMap::iterator it(invocations_.begin());
   14118   int invocations = 0;
   14119   for (; it != invocations_.end(); ++it) {
   14120     SymbolInfo* caller = it->first.first;
   14121     SymbolInfo* function = it->first.second;
   14122 
   14123     // Filter out non-matching functions.
   14124     if (function_name != NULL) {
   14125       if (function->name.find(function_name) == std::string::npos)
   14126         continue;
   14127     }
   14128 
   14129     // Filter out non-matching callers.
   14130     if (caller_name != NULL) {
   14131       if (caller == NULL)
   14132         continue;
   14133       if (caller->name.find(caller_name) == std::string::npos)
   14134         continue;
   14135     }
   14136 
   14137     // It matches add the invocation count to the tally.
   14138     invocations += it->second;
   14139   }
   14140 
   14141   return invocations;
   14142 }
   14143 
   14144 
   14145 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
   14146   v8::HandleScope outer(isolate);
   14147   v8::Local<Context> env = Context::New(isolate);
   14148   env->Enter();
   14149 
   14150   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   14151   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
   14152   env->Global()->Set(v8_str("obj"), t->NewInstance());
   14153 
   14154   const char* script =
   14155       "function bar() {\n"
   14156       "  var sum = 0;\n"
   14157       "  for (i = 0; i < 100; ++i)\n"
   14158       "    sum = foo(i);\n"
   14159       "  return sum;\n"
   14160       "}\n"
   14161       "function foo(i) { return i * i; }\n"
   14162       "// Invoke on the runtime function.\n"
   14163       "obj.asdf()";
   14164   CompileRun(script);
   14165   bar_func_ = i::Handle<i::JSFunction>::cast(
   14166           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
   14167   DCHECK(!bar_func_.is_null());
   14168 
   14169   foo_func_ =
   14170       i::Handle<i::JSFunction>::cast(
   14171            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
   14172   DCHECK(!foo_func_.is_null());
   14173 
   14174   v8::Handle<v8::Value> value = CompileRun("bar();");
   14175   CHECK(value->IsNumber());
   14176   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   14177 
   14178   // Test the optimized codegen path.
   14179   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
   14180                      "bar();");
   14181   CHECK(value->IsNumber());
   14182   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   14183 
   14184   env->Exit();
   14185 }
   14186 
   14187 
   14188 void SetFunctionEntryHookTest::RunTest() {
   14189   // Work in a new isolate throughout.
   14190   v8::Isolate::CreateParams create_params;
   14191   create_params.entry_hook = EntryHook;
   14192   create_params.code_event_handler = JitEvent;
   14193   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14194 
   14195   {
   14196     v8::Isolate::Scope scope(isolate);
   14197 
   14198     RunLoopInNewEnv(isolate);
   14199 
   14200     // Check the exepected invocation counts.
   14201     CHECK_EQ(2, CountInvocations(NULL, "bar"));
   14202     CHECK_EQ(200, CountInvocations("bar", "foo"));
   14203     CHECK_EQ(200, CountInvocations(NULL, "foo"));
   14204 
   14205     // Verify that we have an entry hook on some specific stubs.
   14206     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
   14207     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
   14208     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
   14209   }
   14210   isolate->Dispose();
   14211 
   14212   Reset();
   14213 
   14214   // Make sure a second isolate is unaffected by the previous entry hook.
   14215   isolate = v8::Isolate::New();
   14216   {
   14217     v8::Isolate::Scope scope(isolate);
   14218 
   14219     // Reset the entry count to zero and set the entry hook.
   14220     RunLoopInNewEnv(isolate);
   14221 
   14222     // We should record no invocations in this isolate.
   14223     CHECK_EQ(0, static_cast<int>(invocations_.size()));
   14224   }
   14225 
   14226   isolate->Dispose();
   14227 }
   14228 
   14229 
   14230 TEST(SetFunctionEntryHook) {
   14231   // FunctionEntryHook does not work well with experimental natives.
   14232   // Experimental natives are compiled during snapshot deserialization.
   14233   // This test breaks because InstallGetter (function from snapshot that
   14234   // only gets called from experimental natives) is compiled with entry hooks.
   14235   i::FLAG_allow_natives_syntax = true;
   14236   i::FLAG_use_inlining = false;
   14237 
   14238   SetFunctionEntryHookTest test;
   14239   test.RunTest();
   14240 }
   14241 
   14242 
   14243 static i::HashMap* code_map = NULL;
   14244 static i::HashMap* jitcode_line_info = NULL;
   14245 static int saw_bar = 0;
   14246 static int move_events = 0;
   14247 
   14248 
   14249 static bool FunctionNameIs(const char* expected,
   14250                            const v8::JitCodeEvent* event) {
   14251   // Log lines for functions are of the general form:
   14252   // "LazyCompile:<type><function_name>", where the type is one of
   14253   // "*", "~" or "".
   14254   static const char kPreamble[] = "LazyCompile:";
   14255   static size_t kPreambleLen = sizeof(kPreamble) - 1;
   14256 
   14257   if (event->name.len < sizeof(kPreamble) - 1 ||
   14258       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
   14259     return false;
   14260   }
   14261 
   14262   const char* tail = event->name.str + kPreambleLen;
   14263   size_t tail_len = event->name.len - kPreambleLen;
   14264   size_t expected_len = strlen(expected);
   14265   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
   14266     --tail_len;
   14267     ++tail;
   14268   }
   14269 
   14270   // Check for tails like 'bar :1'.
   14271   if (tail_len > expected_len + 2 &&
   14272       tail[expected_len] == ' ' &&
   14273       tail[expected_len + 1] == ':' &&
   14274       tail[expected_len + 2] &&
   14275       !strncmp(tail, expected, expected_len)) {
   14276     return true;
   14277   }
   14278 
   14279   if (tail_len != expected_len)
   14280     return false;
   14281 
   14282   return strncmp(tail, expected, expected_len) == 0;
   14283 }
   14284 
   14285 
   14286 static void event_handler(const v8::JitCodeEvent* event) {
   14287   CHECK(event != NULL);
   14288   CHECK(code_map != NULL);
   14289   CHECK(jitcode_line_info != NULL);
   14290 
   14291   class DummyJitCodeLineInfo {
   14292   };
   14293 
   14294   switch (event->type) {
   14295     case v8::JitCodeEvent::CODE_ADDED: {
   14296         CHECK(event->code_start != NULL);
   14297         CHECK_NE(0, static_cast<int>(event->code_len));
   14298         CHECK(event->name.str != NULL);
   14299         i::HashMap::Entry* entry =
   14300             code_map->Lookup(event->code_start,
   14301                              i::ComputePointerHash(event->code_start),
   14302                              true);
   14303         entry->value = reinterpret_cast<void*>(event->code_len);
   14304 
   14305         if (FunctionNameIs("bar", event)) {
   14306           ++saw_bar;
   14307         }
   14308       }
   14309       break;
   14310 
   14311     case v8::JitCodeEvent::CODE_MOVED: {
   14312         uint32_t hash = i::ComputePointerHash(event->code_start);
   14313         // We would like to never see code move that we haven't seen before,
   14314         // but the code creation event does not happen until the line endings
   14315         // have been calculated (this is so that we can report the line in the
   14316         // script at which the function source is found, see
   14317         // Compiler::RecordFunctionCompilation) and the line endings
   14318         // calculations can cause a GC, which can move the newly created code
   14319         // before its existence can be logged.
   14320         i::HashMap::Entry* entry =
   14321             code_map->Lookup(event->code_start, hash, false);
   14322         if (entry != NULL) {
   14323           ++move_events;
   14324 
   14325           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
   14326           code_map->Remove(event->code_start, hash);
   14327 
   14328           entry = code_map->Lookup(event->new_code_start,
   14329                                    i::ComputePointerHash(event->new_code_start),
   14330                                    true);
   14331           CHECK(entry != NULL);
   14332           entry->value = reinterpret_cast<void*>(event->code_len);
   14333         }
   14334       }
   14335       break;
   14336 
   14337     case v8::JitCodeEvent::CODE_REMOVED:
   14338       // Object/code removal events are currently not dispatched from the GC.
   14339       CHECK(false);
   14340       break;
   14341 
   14342     // For CODE_START_LINE_INFO_RECORDING event, we will create one
   14343     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
   14344     // record it in jitcode_line_info.
   14345     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
   14346         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
   14347         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
   14348         temp_event->user_data = line_info;
   14349         i::HashMap::Entry* entry =
   14350             jitcode_line_info->Lookup(line_info,
   14351                                       i::ComputePointerHash(line_info),
   14352                                       true);
   14353         entry->value = reinterpret_cast<void*>(line_info);
   14354       }
   14355       break;
   14356     // For these two events, we will check whether the event->user_data
   14357     // data structure is created before during CODE_START_LINE_INFO_RECORDING
   14358     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
   14359     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
   14360         CHECK(event->user_data != NULL);
   14361         uint32_t hash = i::ComputePointerHash(event->user_data);
   14362         i::HashMap::Entry* entry =
   14363             jitcode_line_info->Lookup(event->user_data, hash, false);
   14364         CHECK(entry != NULL);
   14365         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
   14366       }
   14367       break;
   14368 
   14369     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
   14370         CHECK(event->user_data != NULL);
   14371         uint32_t hash = i::ComputePointerHash(event->user_data);
   14372         i::HashMap::Entry* entry =
   14373             jitcode_line_info->Lookup(event->user_data, hash, false);
   14374         CHECK(entry != NULL);
   14375       }
   14376       break;
   14377 
   14378     default:
   14379       // Impossible event.
   14380       CHECK(false);
   14381       break;
   14382   }
   14383 }
   14384 
   14385 
   14386 UNINITIALIZED_TEST(SetJitCodeEventHandler) {
   14387   i::FLAG_stress_compaction = true;
   14388   i::FLAG_incremental_marking = false;
   14389   if (i::FLAG_never_compact) return;
   14390   const char* script =
   14391     "function bar() {"
   14392     "  var sum = 0;"
   14393     "  for (i = 0; i < 100; ++i)"
   14394     "    sum = foo(i);"
   14395     "  return sum;"
   14396     "}"
   14397     "function foo(i) { return i * i; };"
   14398     "bar();";
   14399 
   14400   // Run this test in a new isolate to make sure we don't
   14401   // have remnants of state from other code.
   14402   v8::Isolate* isolate = v8::Isolate::New();
   14403   isolate->Enter();
   14404   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   14405   i::Heap* heap = i_isolate->heap();
   14406 
   14407   {
   14408     v8::HandleScope scope(isolate);
   14409     i::HashMap code(MatchPointers);
   14410     code_map = &code;
   14411 
   14412     i::HashMap lineinfo(MatchPointers);
   14413     jitcode_line_info = &lineinfo;
   14414 
   14415     saw_bar = 0;
   14416     move_events = 0;
   14417 
   14418     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
   14419 
   14420     // Generate new code objects sparsely distributed across several
   14421     // different fragmented code-space pages.
   14422     const int kIterations = 10;
   14423     for (int i = 0; i < kIterations; ++i) {
   14424       LocalContext env(isolate);
   14425       i::AlwaysAllocateScope always_allocate(i_isolate);
   14426       SimulateFullSpace(heap->code_space());
   14427       CompileRun(script);
   14428 
   14429       // Keep a strong reference to the code object in the handle scope.
   14430       i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
   14431           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
   14432       i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
   14433           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
   14434 
   14435       // Clear the compilation cache to get more wastage.
   14436       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
   14437     }
   14438 
   14439     // Force code movement.
   14440     heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
   14441 
   14442     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   14443 
   14444     CHECK_LE(kIterations, saw_bar);
   14445     CHECK_LT(0, move_events);
   14446 
   14447     code_map = NULL;
   14448     jitcode_line_info = NULL;
   14449   }
   14450 
   14451   isolate->Exit();
   14452   isolate->Dispose();
   14453 
   14454   // Do this in a new isolate.
   14455   isolate = v8::Isolate::New();
   14456   isolate->Enter();
   14457 
   14458   // Verify that we get callbacks for existing code objects when we
   14459   // request enumeration of existing code.
   14460   {
   14461     v8::HandleScope scope(isolate);
   14462     LocalContext env(isolate);
   14463     CompileRun(script);
   14464 
   14465     // Now get code through initial iteration.
   14466     i::HashMap code(MatchPointers);
   14467     code_map = &code;
   14468 
   14469     i::HashMap lineinfo(MatchPointers);
   14470     jitcode_line_info = &lineinfo;
   14471 
   14472     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
   14473                                     event_handler);
   14474     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   14475 
   14476     jitcode_line_info = NULL;
   14477     // We expect that we got some events. Note that if we could get code removal
   14478     // notifications, we could compare two collections, one created by listening
   14479     // from the time of creation of an isolate, and the other by subscribing
   14480     // with EnumExisting.
   14481     CHECK_LT(0, code.occupancy());
   14482 
   14483     code_map = NULL;
   14484   }
   14485 
   14486   isolate->Exit();
   14487   isolate->Dispose();
   14488 }
   14489 
   14490 
   14491 THREADED_TEST(ExternalAllocatedMemory) {
   14492   v8::Isolate* isolate = CcTest::isolate();
   14493   v8::HandleScope outer(isolate);
   14494   v8::Local<Context> env(Context::New(isolate));
   14495   CHECK(!env.IsEmpty());
   14496   const int64_t kSize = 1024*1024;
   14497   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
   14498   CHECK_EQ(baseline + kSize,
   14499            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
   14500   CHECK_EQ(baseline,
   14501            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
   14502 }
   14503 
   14504 
   14505 // Regression test for issue 54, object templates with internal fields
   14506 // but no accessors or interceptors did not get their internal field
   14507 // count set on instances.
   14508 THREADED_TEST(Regress54) {
   14509   LocalContext context;
   14510   v8::Isolate* isolate = context->GetIsolate();
   14511   v8::HandleScope outer(isolate);
   14512   static v8::Persistent<v8::ObjectTemplate> templ;
   14513   if (templ.IsEmpty()) {
   14514     v8::EscapableHandleScope inner(isolate);
   14515     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
   14516     local->SetInternalFieldCount(1);
   14517     templ.Reset(isolate, inner.Escape(local));
   14518   }
   14519   v8::Handle<v8::Object> result =
   14520       v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
   14521   CHECK_EQ(1, result->InternalFieldCount());
   14522 }
   14523 
   14524 
   14525 // If part of the threaded tests, this test makes ThreadingTest fail
   14526 // on mac.
   14527 TEST(CatchStackOverflow) {
   14528   LocalContext context;
   14529   v8::HandleScope scope(context->GetIsolate());
   14530   v8::TryCatch try_catch;
   14531   v8::Handle<v8::Value> result = CompileRun(
   14532     "function f() {"
   14533     "  return f();"
   14534     "}"
   14535     ""
   14536     "f();");
   14537   CHECK(result.IsEmpty());
   14538 }
   14539 
   14540 
   14541 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
   14542                                     const char* resource_name,
   14543                                     int line_offset) {
   14544   v8::HandleScope scope(CcTest::isolate());
   14545   v8::TryCatch try_catch;
   14546   v8::Handle<v8::Value> result = script->Run();
   14547   CHECK(result.IsEmpty());
   14548   CHECK(try_catch.HasCaught());
   14549   v8::Handle<v8::Message> message = try_catch.Message();
   14550   CHECK(!message.IsEmpty());
   14551   CHECK_EQ(10 + line_offset, message->GetLineNumber());
   14552   CHECK_EQ(91, message->GetStartPosition());
   14553   CHECK_EQ(92, message->GetEndPosition());
   14554   CHECK_EQ(2, message->GetStartColumn());
   14555   CHECK_EQ(3, message->GetEndColumn());
   14556   v8::String::Utf8Value line(message->GetSourceLine());
   14557   CHECK_EQ("  throw 'nirk';", *line);
   14558   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
   14559   CHECK_EQ(resource_name, *name);
   14560 }
   14561 
   14562 
   14563 THREADED_TEST(TryCatchSourceInfo) {
   14564   LocalContext context;
   14565   v8::HandleScope scope(context->GetIsolate());
   14566   v8::Local<v8::String> source = v8_str(
   14567       "function Foo() {\n"
   14568       "  return Bar();\n"
   14569       "}\n"
   14570       "\n"
   14571       "function Bar() {\n"
   14572       "  return Baz();\n"
   14573       "}\n"
   14574       "\n"
   14575       "function Baz() {\n"
   14576       "  throw 'nirk';\n"
   14577       "}\n"
   14578       "\n"
   14579       "Foo();\n");
   14580 
   14581   const char* resource_name;
   14582   v8::Handle<v8::Script> script;
   14583   resource_name = "test.js";
   14584   script = CompileWithOrigin(source, resource_name);
   14585   CheckTryCatchSourceInfo(script, resource_name, 0);
   14586 
   14587   resource_name = "test1.js";
   14588   v8::ScriptOrigin origin1(
   14589       v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
   14590   script = v8::Script::Compile(source, &origin1);
   14591   CheckTryCatchSourceInfo(script, resource_name, 0);
   14592 
   14593   resource_name = "test2.js";
   14594   v8::ScriptOrigin origin2(
   14595       v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
   14596       v8::Integer::New(context->GetIsolate(), 7));
   14597   script = v8::Script::Compile(source, &origin2);
   14598   CheckTryCatchSourceInfo(script, resource_name, 7);
   14599 }
   14600 
   14601 
   14602 THREADED_TEST(CompilationCache) {
   14603   LocalContext context;
   14604   v8::HandleScope scope(context->GetIsolate());
   14605   v8::Handle<v8::String> source0 =
   14606       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
   14607   v8::Handle<v8::String> source1 =
   14608       v8::String::NewFromUtf8(context->GetIsolate(), "1234");
   14609   v8::Handle<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
   14610   v8::Handle<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
   14611   v8::Handle<v8::Script> script2 =
   14612       v8::Script::Compile(source0);  // different origin
   14613   CHECK_EQ(1234, script0->Run()->Int32Value());
   14614   CHECK_EQ(1234, script1->Run()->Int32Value());
   14615   CHECK_EQ(1234, script2->Run()->Int32Value());
   14616 }
   14617 
   14618 
   14619 static void FunctionNameCallback(
   14620     const v8::FunctionCallbackInfo<v8::Value>& args) {
   14621   ApiTestFuzzer::Fuzz();
   14622   args.GetReturnValue().Set(v8_num(42));
   14623 }
   14624 
   14625 
   14626 THREADED_TEST(CallbackFunctionName) {
   14627   LocalContext context;
   14628   v8::Isolate* isolate = context->GetIsolate();
   14629   v8::HandleScope scope(isolate);
   14630   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   14631   t->Set(v8_str("asdf"),
   14632          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
   14633   context->Global()->Set(v8_str("obj"), t->NewInstance());
   14634   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
   14635   CHECK(value->IsString());
   14636   v8::String::Utf8Value name(value);
   14637   CHECK_EQ("asdf", *name);
   14638 }
   14639 
   14640 
   14641 THREADED_TEST(DateAccess) {
   14642   LocalContext context;
   14643   v8::HandleScope scope(context->GetIsolate());
   14644   v8::Handle<v8::Value> date =
   14645       v8::Date::New(context->GetIsolate(), 1224744689038.0);
   14646   CHECK(date->IsDate());
   14647   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
   14648 }
   14649 
   14650 
   14651 void CheckProperties(v8::Isolate* isolate,
   14652                      v8::Handle<v8::Value> val,
   14653                      int elmc,
   14654                      const char* elmv[]) {
   14655   v8::Handle<v8::Object> obj = val.As<v8::Object>();
   14656   v8::Handle<v8::Array> props = obj->GetPropertyNames();
   14657   CHECK_EQ(elmc, props->Length());
   14658   for (int i = 0; i < elmc; i++) {
   14659     v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
   14660     CHECK_EQ(elmv[i], *elm);
   14661   }
   14662 }
   14663 
   14664 
   14665 void CheckOwnProperties(v8::Isolate* isolate,
   14666                         v8::Handle<v8::Value> val,
   14667                         int elmc,
   14668                         const char* elmv[]) {
   14669   v8::Handle<v8::Object> obj = val.As<v8::Object>();
   14670   v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
   14671   CHECK_EQ(elmc, props->Length());
   14672   for (int i = 0; i < elmc; i++) {
   14673     v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
   14674     CHECK_EQ(elmv[i], *elm);
   14675   }
   14676 }
   14677 
   14678 
   14679 THREADED_TEST(PropertyEnumeration) {
   14680   LocalContext context;
   14681   v8::Isolate* isolate = context->GetIsolate();
   14682   v8::HandleScope scope(isolate);
   14683   v8::Handle<v8::Value> obj = CompileRun(
   14684       "var result = [];"
   14685       "result[0] = {};"
   14686       "result[1] = {a: 1, b: 2};"
   14687       "result[2] = [1, 2, 3];"
   14688       "var proto = {x: 1, y: 2, z: 3};"
   14689       "var x = { __proto__: proto, w: 0, z: 1 };"
   14690       "result[3] = x;"
   14691       "result;");
   14692   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   14693   CHECK_EQ(4, elms->Length());
   14694   int elmc0 = 0;
   14695   const char** elmv0 = NULL;
   14696   CheckProperties(
   14697       isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
   14698   CheckOwnProperties(
   14699       isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
   14700   int elmc1 = 2;
   14701   const char* elmv1[] = {"a", "b"};
   14702   CheckProperties(
   14703       isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
   14704   CheckOwnProperties(
   14705       isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
   14706   int elmc2 = 3;
   14707   const char* elmv2[] = {"0", "1", "2"};
   14708   CheckProperties(
   14709       isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
   14710   CheckOwnProperties(
   14711       isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
   14712   int elmc3 = 4;
   14713   const char* elmv3[] = {"w", "z", "x", "y"};
   14714   CheckProperties(
   14715       isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
   14716   int elmc4 = 2;
   14717   const char* elmv4[] = {"w", "z"};
   14718   CheckOwnProperties(
   14719       isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
   14720 }
   14721 
   14722 
   14723 THREADED_TEST(PropertyEnumeration2) {
   14724   LocalContext context;
   14725   v8::Isolate* isolate = context->GetIsolate();
   14726   v8::HandleScope scope(isolate);
   14727   v8::Handle<v8::Value> obj = CompileRun(
   14728       "var result = [];"
   14729       "result[0] = {};"
   14730       "result[1] = {a: 1, b: 2};"
   14731       "result[2] = [1, 2, 3];"
   14732       "var proto = {x: 1, y: 2, z: 3};"
   14733       "var x = { __proto__: proto, w: 0, z: 1 };"
   14734       "result[3] = x;"
   14735       "result;");
   14736   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   14737   CHECK_EQ(4, elms->Length());
   14738   int elmc0 = 0;
   14739   const char** elmv0 = NULL;
   14740   CheckProperties(isolate,
   14741                   elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
   14742 
   14743   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
   14744   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
   14745   CHECK_EQ(0, props->Length());
   14746   for (uint32_t i = 0; i < props->Length(); i++) {
   14747     printf("p[%d]\n", i);
   14748   }
   14749 }
   14750 
   14751 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
   14752                                   Local<Value> name,
   14753                                   v8::AccessType type,
   14754                                   Local<Value> data) {
   14755   return type != v8::ACCESS_SET;
   14756 }
   14757 
   14758 
   14759 static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
   14760                                     uint32_t key,
   14761                                     v8::AccessType type,
   14762                                     Local<Value> data) {
   14763   return type != v8::ACCESS_SET;
   14764 }
   14765 
   14766 
   14767 THREADED_TEST(DisableAccessChecksWhileConfiguring) {
   14768   LocalContext context;
   14769   v8::Isolate* isolate = context->GetIsolate();
   14770   v8::HandleScope scope(isolate);
   14771   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   14772   templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   14773                                  IndexedSetAccessBlocker);
   14774   templ->Set(v8_str("x"), v8::True(isolate));
   14775   Local<v8::Object> instance = templ->NewInstance();
   14776   context->Global()->Set(v8_str("obj"), instance);
   14777   Local<Value> value = CompileRun("obj.x");
   14778   CHECK(value->BooleanValue());
   14779 }
   14780 
   14781 
   14782 static bool NamedGetAccessBlocker(Local<v8::Object> obj,
   14783                                   Local<Value> name,
   14784                                   v8::AccessType type,
   14785                                   Local<Value> data) {
   14786   return false;
   14787 }
   14788 
   14789 
   14790 static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
   14791                                     uint32_t key,
   14792                                     v8::AccessType type,
   14793                                     Local<Value> data) {
   14794   return false;
   14795 }
   14796 
   14797 
   14798 
   14799 THREADED_TEST(AccessChecksReenabledCorrectly) {
   14800   LocalContext context;
   14801   v8::Isolate* isolate = context->GetIsolate();
   14802   v8::HandleScope scope(isolate);
   14803   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   14804   templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   14805                                  IndexedGetAccessBlocker);
   14806   templ->Set(v8_str("a"), v8_str("a"));
   14807   // Add more than 8 (see kMaxFastProperties) properties
   14808   // so that the constructor will force copying map.
   14809   // Cannot sprintf, gcc complains unsafety.
   14810   char buf[4];
   14811   for (char i = '0'; i <= '9' ; i++) {
   14812     buf[0] = i;
   14813     for (char j = '0'; j <= '9'; j++) {
   14814       buf[1] = j;
   14815       for (char k = '0'; k <= '9'; k++) {
   14816         buf[2] = k;
   14817         buf[3] = 0;
   14818         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
   14819       }
   14820     }
   14821   }
   14822 
   14823   Local<v8::Object> instance_1 = templ->NewInstance();
   14824   context->Global()->Set(v8_str("obj_1"), instance_1);
   14825 
   14826   Local<Value> value_1 = CompileRun("obj_1.a");
   14827   CHECK(value_1.IsEmpty());
   14828 
   14829   Local<v8::Object> instance_2 = templ->NewInstance();
   14830   context->Global()->Set(v8_str("obj_2"), instance_2);
   14831 
   14832   Local<Value> value_2 = CompileRun("obj_2.a");
   14833   CHECK(value_2.IsEmpty());
   14834 }
   14835 
   14836 
   14837 // This tests that access check information remains on the global
   14838 // object template when creating contexts.
   14839 THREADED_TEST(AccessControlRepeatedContextCreation) {
   14840   v8::Isolate* isolate = CcTest::isolate();
   14841   v8::HandleScope handle_scope(isolate);
   14842   v8::Handle<v8::ObjectTemplate> global_template =
   14843       v8::ObjectTemplate::New(isolate);
   14844   global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   14845                                            IndexedSetAccessBlocker);
   14846   i::Handle<i::ObjectTemplateInfo> internal_template =
   14847       v8::Utils::OpenHandle(*global_template);
   14848   CHECK(!internal_template->constructor()->IsUndefined());
   14849   i::Handle<i::FunctionTemplateInfo> constructor(
   14850       i::FunctionTemplateInfo::cast(internal_template->constructor()));
   14851   CHECK(!constructor->access_check_info()->IsUndefined());
   14852   v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
   14853   CHECK(!context0.IsEmpty());
   14854   CHECK(!constructor->access_check_info()->IsUndefined());
   14855 }
   14856 
   14857 
   14858 THREADED_TEST(TurnOnAccessCheck) {
   14859   v8::Isolate* isolate = CcTest::isolate();
   14860   v8::HandleScope handle_scope(isolate);
   14861 
   14862   // Create an environment with access check to the global object disabled by
   14863   // default.
   14864   v8::Handle<v8::ObjectTemplate> global_template =
   14865       v8::ObjectTemplate::New(isolate);
   14866   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   14867                                            IndexedGetAccessBlocker,
   14868                                            v8::Handle<v8::Value>(),
   14869                                            false);
   14870   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
   14871   Context::Scope context_scope(context);
   14872 
   14873   // Set up a property and a number of functions.
   14874   context->Global()->Set(v8_str("a"), v8_num(1));
   14875   CompileRun("function f1() {return a;}"
   14876              "function f2() {return a;}"
   14877              "function g1() {return h();}"
   14878              "function g2() {return h();}"
   14879              "function h() {return 1;}");
   14880   Local<Function> f1 =
   14881       Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   14882   Local<Function> f2 =
   14883       Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   14884   Local<Function> g1 =
   14885       Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   14886   Local<Function> g2 =
   14887       Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   14888   Local<Function> h =
   14889       Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   14890 
   14891   // Get the global object.
   14892   v8::Handle<v8::Object> global = context->Global();
   14893 
   14894   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   14895   // uses the runtime system to retreive property a whereas f2 uses global load
   14896   // inline cache.
   14897   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   14898   for (int i = 0; i < 4; i++) {
   14899     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   14900   }
   14901 
   14902   // Same for g1 and g2.
   14903   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   14904   for (int i = 0; i < 4; i++) {
   14905     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   14906   }
   14907 
   14908   // Detach the global and turn on access check.
   14909   Local<Object> hidden_global = Local<Object>::Cast(
   14910       context->Global()->GetPrototype());
   14911   context->DetachGlobal();
   14912   hidden_global->TurnOnAccessCheck();
   14913 
   14914   // Failing access check results in exception.
   14915   CHECK(f1->Call(global, 0, NULL).IsEmpty());
   14916   CHECK(f2->Call(global, 0, NULL).IsEmpty());
   14917   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   14918   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   14919 
   14920   // No failing access check when just returning a constant.
   14921   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   14922 }
   14923 
   14924 
   14925 static const char* kPropertyA = "a";
   14926 static const char* kPropertyH = "h";
   14927 
   14928 static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
   14929                                        Local<Value> name,
   14930                                        v8::AccessType type,
   14931                                        Local<Value> data) {
   14932   if (!name->IsString()) return false;
   14933   i::Handle<i::String> name_handle =
   14934       v8::Utils::OpenHandle(String::Cast(*name));
   14935   return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
   14936       && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
   14937 }
   14938 
   14939 
   14940 THREADED_TEST(TurnOnAccessCheckAndRecompile) {
   14941   v8::Isolate* isolate = CcTest::isolate();
   14942   v8::HandleScope handle_scope(isolate);
   14943 
   14944   // Create an environment with access check to the global object disabled by
   14945   // default. When the registered access checker will block access to properties
   14946   // a and h.
   14947   v8::Handle<v8::ObjectTemplate> global_template =
   14948      v8::ObjectTemplate::New(isolate);
   14949   global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
   14950                                            IndexedGetAccessBlocker,
   14951                                            v8::Handle<v8::Value>(),
   14952                                            false);
   14953   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
   14954   Context::Scope context_scope(context);
   14955 
   14956   // Set up a property and a number of functions.
   14957   context->Global()->Set(v8_str("a"), v8_num(1));
   14958   static const char* source = "function f1() {return a;}"
   14959                               "function f2() {return a;}"
   14960                               "function g1() {return h();}"
   14961                               "function g2() {return h();}"
   14962                               "function h() {return 1;}";
   14963 
   14964   CompileRun(source);
   14965   Local<Function> f1;
   14966   Local<Function> f2;
   14967   Local<Function> g1;
   14968   Local<Function> g2;
   14969   Local<Function> h;
   14970   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   14971   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   14972   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   14973   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   14974   h =  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   14975 
   14976   // Get the global object.
   14977   v8::Handle<v8::Object> global = context->Global();
   14978 
   14979   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   14980   // uses the runtime system to retreive property a whereas f2 uses global load
   14981   // inline cache.
   14982   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   14983   for (int i = 0; i < 4; i++) {
   14984     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   14985   }
   14986 
   14987   // Same for g1 and g2.
   14988   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   14989   for (int i = 0; i < 4; i++) {
   14990     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   14991   }
   14992 
   14993   // Detach the global and turn on access check now blocking access to property
   14994   // a and function h.
   14995   Local<Object> hidden_global = Local<Object>::Cast(
   14996       context->Global()->GetPrototype());
   14997   context->DetachGlobal();
   14998   hidden_global->TurnOnAccessCheck();
   14999 
   15000   // Failing access check results in exception.
   15001   CHECK(f1->Call(global, 0, NULL).IsEmpty());
   15002   CHECK(f2->Call(global, 0, NULL).IsEmpty());
   15003   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   15004   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   15005 
   15006   // No failing access check when just returning a constant.
   15007   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   15008 
   15009   // Now compile the source again. And get the newly compiled functions, except
   15010   // for h for which access is blocked.
   15011   CompileRun(source);
   15012   f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
   15013   f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
   15014   g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
   15015   g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
   15016   CHECK(hidden_global->Get(v8_str("h")).IsEmpty());
   15017 
   15018   // Failing access check results in exception.
   15019   v8::Local<v8::Value> result = f1->Call(global, 0, NULL);
   15020   CHECK(result.IsEmpty());
   15021   CHECK(f1->Call(global, 0, NULL).IsEmpty());
   15022   CHECK(f2->Call(global, 0, NULL).IsEmpty());
   15023   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   15024   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   15025 }
   15026 
   15027 
   15028 // Tests that ScriptData can be serialized and deserialized.
   15029 TEST(PreCompileSerialization) {
   15030   v8::V8::Initialize();
   15031   LocalContext env;
   15032   v8::Isolate* isolate = env->GetIsolate();
   15033   HandleScope handle_scope(isolate);
   15034 
   15035   i::FLAG_min_preparse_length = 0;
   15036   const char* script = "function foo(a) { return a+1; }";
   15037   v8::ScriptCompiler::Source source(v8_str(script));
   15038   v8::ScriptCompiler::Compile(isolate, &source,
   15039                               v8::ScriptCompiler::kProduceParserCache);
   15040   // Serialize.
   15041   const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
   15042   i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
   15043   i::MemCopy(serialized_data, cd->data, cd->length);
   15044 
   15045   // Deserialize.
   15046   i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
   15047 
   15048   // Verify that the original is the same as the deserialized.
   15049   CHECK_EQ(cd->length, deserialized->length());
   15050   CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
   15051 
   15052   delete deserialized;
   15053   i::DeleteArray(serialized_data);
   15054 }
   15055 
   15056 
   15057 // This tests that we do not allow dictionary load/call inline caches
   15058 // to use functions that have not yet been compiled.  The potential
   15059 // problem of loading a function that has not yet been compiled can
   15060 // arise because we share code between contexts via the compilation
   15061 // cache.
   15062 THREADED_TEST(DictionaryICLoadedFunction) {
   15063   v8::HandleScope scope(CcTest::isolate());
   15064   // Test LoadIC.
   15065   for (int i = 0; i < 2; i++) {
   15066     LocalContext context;
   15067     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
   15068     context->Global()->Delete(v8_str("tmp"));
   15069     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   15070   }
   15071   // Test CallIC.
   15072   for (int i = 0; i < 2; i++) {
   15073     LocalContext context;
   15074     context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
   15075     context->Global()->Delete(v8_str("tmp"));
   15076     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   15077   }
   15078 }
   15079 
   15080 
   15081 // Test that cross-context new calls use the context of the callee to
   15082 // create the new JavaScript object.
   15083 THREADED_TEST(CrossContextNew) {
   15084   v8::Isolate* isolate = CcTest::isolate();
   15085   v8::HandleScope scope(isolate);
   15086   v8::Local<Context> context0 = Context::New(isolate);
   15087   v8::Local<Context> context1 = Context::New(isolate);
   15088 
   15089   // Allow cross-domain access.
   15090   Local<String> token = v8_str("<security token>");
   15091   context0->SetSecurityToken(token);
   15092   context1->SetSecurityToken(token);
   15093 
   15094   // Set an 'x' property on the Object prototype and define a
   15095   // constructor function in context0.
   15096   context0->Enter();
   15097   CompileRun("Object.prototype.x = 42; function C() {};");
   15098   context0->Exit();
   15099 
   15100   // Call the constructor function from context0 and check that the
   15101   // result has the 'x' property.
   15102   context1->Enter();
   15103   context1->Global()->Set(v8_str("other"), context0->Global());
   15104   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   15105   CHECK(value->IsInt32());
   15106   CHECK_EQ(42, value->Int32Value());
   15107   context1->Exit();
   15108 }
   15109 
   15110 
   15111 // Verify that we can clone an object
   15112 TEST(ObjectClone) {
   15113   LocalContext env;
   15114   v8::Isolate* isolate = env->GetIsolate();
   15115   v8::HandleScope scope(isolate);
   15116 
   15117   const char* sample =
   15118     "var rv = {};"      \
   15119     "rv.alpha = 'hello';" \
   15120     "rv.beta = 123;"     \
   15121     "rv;";
   15122 
   15123   // Create an object, verify basics.
   15124   Local<Value> val = CompileRun(sample);
   15125   CHECK(val->IsObject());
   15126   Local<v8::Object> obj = val.As<v8::Object>();
   15127   obj->Set(v8_str("gamma"), v8_str("cloneme"));
   15128 
   15129   CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
   15130   CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
   15131   CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
   15132 
   15133   // Clone it.
   15134   Local<v8::Object> clone = obj->Clone();
   15135   CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
   15136   CHECK_EQ(v8::Integer::New(isolate, 123), clone->Get(v8_str("beta")));
   15137   CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
   15138 
   15139   // Set a property on the clone, verify each object.
   15140   clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
   15141   CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
   15142   CHECK_EQ(v8::Integer::New(isolate, 456), clone->Get(v8_str("beta")));
   15143 }
   15144 
   15145 
   15146 class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
   15147  public:
   15148   explicit OneByteVectorResource(i::Vector<const char> vector)
   15149       : data_(vector) {}
   15150   virtual ~OneByteVectorResource() {}
   15151   virtual size_t length() const { return data_.length(); }
   15152   virtual const char* data() const { return data_.start(); }
   15153  private:
   15154   i::Vector<const char> data_;
   15155 };
   15156 
   15157 
   15158 class UC16VectorResource : public v8::String::ExternalStringResource {
   15159  public:
   15160   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   15161       : data_(vector) {}
   15162   virtual ~UC16VectorResource() {}
   15163   virtual size_t length() const { return data_.length(); }
   15164   virtual const i::uc16* data() const { return data_.start(); }
   15165  private:
   15166   i::Vector<const i::uc16> data_;
   15167 };
   15168 
   15169 
   15170 static void MorphAString(i::String* string,
   15171                          OneByteVectorResource* one_byte_resource,
   15172                          UC16VectorResource* uc16_resource) {
   15173   CHECK(i::StringShape(string).IsExternal());
   15174   if (string->IsOneByteRepresentation()) {
   15175     // Check old map is not internalized or long.
   15176     CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
   15177     // Morph external string to be TwoByte string.
   15178     string->set_map(CcTest::heap()->external_string_map());
   15179     i::ExternalTwoByteString* morphed =
   15180          i::ExternalTwoByteString::cast(string);
   15181     morphed->set_resource(uc16_resource);
   15182   } else {
   15183     // Check old map is not internalized or long.
   15184     CHECK(string->map() == CcTest::heap()->external_string_map());
   15185     // Morph external string to be one-byte string.
   15186     string->set_map(CcTest::heap()->external_one_byte_string_map());
   15187     i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
   15188     morphed->set_resource(one_byte_resource);
   15189   }
   15190 }
   15191 
   15192 
   15193 // Test that we can still flatten a string if the components it is built up
   15194 // from have been turned into 16 bit strings in the mean time.
   15195 THREADED_TEST(MorphCompositeStringTest) {
   15196   char utf_buffer[129];
   15197   const char* c_string = "Now is the time for all good men"
   15198                          " to come to the aid of the party";
   15199   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   15200   {
   15201     LocalContext env;
   15202     i::Factory* factory = CcTest::i_isolate()->factory();
   15203     v8::HandleScope scope(env->GetIsolate());
   15204     OneByteVectorResource one_byte_resource(
   15205         i::Vector<const char>(c_string, i::StrLength(c_string)));
   15206     UC16VectorResource uc16_resource(
   15207         i::Vector<const uint16_t>(two_byte_string,
   15208                                   i::StrLength(c_string)));
   15209 
   15210     Local<String> lhs(
   15211         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
   15212                                         &one_byte_resource).ToHandleChecked()));
   15213     Local<String> rhs(
   15214         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
   15215                                         &one_byte_resource).ToHandleChecked()));
   15216 
   15217     env->Global()->Set(v8_str("lhs"), lhs);
   15218     env->Global()->Set(v8_str("rhs"), rhs);
   15219 
   15220     CompileRun(
   15221         "var cons = lhs + rhs;"
   15222         "var slice = lhs.substring(1, lhs.length - 1);"
   15223         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   15224 
   15225     CHECK(lhs->IsOneByte());
   15226     CHECK(rhs->IsOneByte());
   15227 
   15228     MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
   15229                  &uc16_resource);
   15230     MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
   15231                  &uc16_resource);
   15232 
   15233     // This should UTF-8 without flattening, since everything is ASCII.
   15234     Handle<String> cons = v8_compile("cons")->Run().As<String>();
   15235     CHECK_EQ(128, cons->Utf8Length());
   15236     int nchars = -1;
   15237     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
   15238     CHECK_EQ(128, nchars);
   15239     CHECK_EQ(0, strcmp(
   15240         utf_buffer,
   15241         "Now is the time for all good men to come to the aid of the party"
   15242         "Now is the time for all good men to come to the aid of the party"));
   15243 
   15244     // Now do some stuff to make sure the strings are flattened, etc.
   15245     CompileRun(
   15246         "/[^a-z]/.test(cons);"
   15247         "/[^a-z]/.test(slice);"
   15248         "/[^a-z]/.test(slice_on_cons);");
   15249     const char* expected_cons =
   15250         "Now is the time for all good men to come to the aid of the party"
   15251         "Now is the time for all good men to come to the aid of the party";
   15252     const char* expected_slice =
   15253         "ow is the time for all good men to come to the aid of the part";
   15254     const char* expected_slice_on_cons =
   15255         "ow is the time for all good men to come to the aid of the party"
   15256         "Now is the time for all good men to come to the aid of the part";
   15257     CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_cons),
   15258              env->Global()->Get(v8_str("cons")));
   15259     CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
   15260              env->Global()->Get(v8_str("slice")));
   15261     CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
   15262              env->Global()->Get(v8_str("slice_on_cons")));
   15263   }
   15264   i::DeleteArray(two_byte_string);
   15265 }
   15266 
   15267 
   15268 TEST(CompileExternalTwoByteSource) {
   15269   LocalContext context;
   15270   v8::HandleScope scope(context->GetIsolate());
   15271 
   15272   // This is a very short list of sources, which currently is to check for a
   15273   // regression caused by r2703.
   15274   const char* one_byte_sources[] = {
   15275       "0.5",
   15276       "-0.5",   // This mainly testes PushBack in the Scanner.
   15277       "--0.5",  // This mainly testes PushBack in the Scanner.
   15278       NULL};
   15279 
   15280   // Compile the sources as external two byte strings.
   15281   for (int i = 0; one_byte_sources[i] != NULL; i++) {
   15282     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
   15283     TestResource* uc16_resource = new TestResource(two_byte_string);
   15284     v8::Local<v8::String> source =
   15285         v8::String::NewExternal(context->GetIsolate(), uc16_resource);
   15286     v8::Script::Compile(source);
   15287   }
   15288 }
   15289 
   15290 
   15291 #ifndef V8_INTERPRETED_REGEXP
   15292 
   15293 struct RegExpInterruptionData {
   15294   int loop_count;
   15295   UC16VectorResource* string_resource;
   15296   v8::Persistent<v8::String> string;
   15297 } regexp_interruption_data;
   15298 
   15299 
   15300 class RegExpInterruptionThread : public v8::base::Thread {
   15301  public:
   15302   explicit RegExpInterruptionThread(v8::Isolate* isolate)
   15303       : Thread(Options("TimeoutThread")), isolate_(isolate) {}
   15304 
   15305   virtual void Run() {
   15306     for (regexp_interruption_data.loop_count = 0;
   15307          regexp_interruption_data.loop_count < 7;
   15308          regexp_interruption_data.loop_count++) {
   15309       v8::base::OS::Sleep(50);  // Wait a bit before requesting GC.
   15310       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
   15311     }
   15312     v8::base::OS::Sleep(50);  // Wait a bit before terminating.
   15313     v8::V8::TerminateExecution(isolate_);
   15314   }
   15315 
   15316  private:
   15317   v8::Isolate* isolate_;
   15318 };
   15319 
   15320 
   15321 void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
   15322   if (regexp_interruption_data.loop_count != 2) return;
   15323   v8::HandleScope scope(CcTest::isolate());
   15324   v8::Local<v8::String> string = v8::Local<v8::String>::New(
   15325       CcTest::isolate(), regexp_interruption_data.string);
   15326   string->MakeExternal(regexp_interruption_data.string_resource);
   15327 }
   15328 
   15329 
   15330 // Test that RegExp execution can be interrupted.  Specifically, we test
   15331 // * interrupting with GC
   15332 // * turn the subject string from one-byte internal to two-byte external string
   15333 // * force termination
   15334 TEST(RegExpInterruption) {
   15335   v8::HandleScope scope(CcTest::isolate());
   15336   LocalContext env;
   15337 
   15338   RegExpInterruptionThread timeout_thread(CcTest::isolate());
   15339 
   15340   v8::V8::AddGCPrologueCallback(RunBeforeGC);
   15341   static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
   15342   i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
   15343   v8::Local<v8::String> string = v8_str(one_byte_content);
   15344 
   15345   CcTest::global()->Set(v8_str("a"), string);
   15346   regexp_interruption_data.string.Reset(CcTest::isolate(), string);
   15347   regexp_interruption_data.string_resource = new UC16VectorResource(
   15348       i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
   15349 
   15350   v8::TryCatch try_catch;
   15351   timeout_thread.Start();
   15352 
   15353   CompileRun("/((a*)*)*b/.exec(a)");
   15354   CHECK(try_catch.HasTerminated());
   15355 
   15356   timeout_thread.Join();
   15357 
   15358   regexp_interruption_data.string.Reset();
   15359   i::DeleteArray(uc16_content);
   15360 }
   15361 
   15362 #endif  // V8_INTERPRETED_REGEXP
   15363 
   15364 
   15365 // Test that we cannot set a property on the global object if there
   15366 // is a read-only property in the prototype chain.
   15367 TEST(ReadOnlyPropertyInGlobalProto) {
   15368   v8::Isolate* isolate = CcTest::isolate();
   15369   v8::HandleScope scope(isolate);
   15370   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15371   LocalContext context(0, templ);
   15372   v8::Handle<v8::Object> global = context->Global();
   15373   v8::Handle<v8::Object> global_proto =
   15374       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
   15375   global_proto->ForceSet(v8_str("x"), v8::Integer::New(isolate, 0),
   15376                          v8::ReadOnly);
   15377   global_proto->ForceSet(v8_str("y"), v8::Integer::New(isolate, 0),
   15378                          v8::ReadOnly);
   15379   // Check without 'eval' or 'with'.
   15380   v8::Handle<v8::Value> res =
   15381       CompileRun("function f() { x = 42; return x; }; f()");
   15382   CHECK_EQ(v8::Integer::New(isolate, 0), res);
   15383   // Check with 'eval'.
   15384   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
   15385   CHECK_EQ(v8::Integer::New(isolate, 0), res);
   15386   // Check with 'with'.
   15387   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
   15388   CHECK_EQ(v8::Integer::New(isolate, 0), res);
   15389 }
   15390 
   15391 static int force_set_set_count = 0;
   15392 static int force_set_get_count = 0;
   15393 bool pass_on_get = false;
   15394 
   15395 static void ForceSetGetter(v8::Local<v8::String> name,
   15396                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   15397   force_set_get_count++;
   15398   if (pass_on_get) {
   15399     return;
   15400   }
   15401   info.GetReturnValue().Set(3);
   15402 }
   15403 
   15404 static void ForceSetSetter(v8::Local<v8::String> name,
   15405                            v8::Local<v8::Value> value,
   15406                            const v8::PropertyCallbackInfo<void>& info) {
   15407   force_set_set_count++;
   15408 }
   15409 
   15410 static void ForceSetInterceptSetter(
   15411     v8::Local<v8::String> name,
   15412     v8::Local<v8::Value> value,
   15413     const v8::PropertyCallbackInfo<v8::Value>& info) {
   15414   force_set_set_count++;
   15415   info.GetReturnValue().SetUndefined();
   15416 }
   15417 
   15418 
   15419 TEST(ForceSet) {
   15420   force_set_get_count = 0;
   15421   force_set_set_count = 0;
   15422   pass_on_get = false;
   15423 
   15424   v8::Isolate* isolate = CcTest::isolate();
   15425   v8::HandleScope scope(isolate);
   15426   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15427   v8::Handle<v8::String> access_property =
   15428       v8::String::NewFromUtf8(isolate, "a");
   15429   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
   15430   LocalContext context(NULL, templ);
   15431   v8::Handle<v8::Object> global = context->Global();
   15432 
   15433   // Ordinary properties
   15434   v8::Handle<v8::String> simple_property =
   15435       v8::String::NewFromUtf8(isolate, "p");
   15436   global->ForceSet(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
   15437   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   15438   // This should fail because the property is read-only
   15439   global->Set(simple_property, v8::Int32::New(isolate, 5));
   15440   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   15441   // This should succeed even though the property is read-only
   15442   global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
   15443   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
   15444 
   15445   // Accessors
   15446   CHECK_EQ(0, force_set_set_count);
   15447   CHECK_EQ(0, force_set_get_count);
   15448   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   15449   // CHECK_EQ the property shouldn't override it, just call the setter
   15450   // which in this case does nothing.
   15451   global->Set(access_property, v8::Int32::New(isolate, 7));
   15452   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   15453   CHECK_EQ(1, force_set_set_count);
   15454   CHECK_EQ(2, force_set_get_count);
   15455   // Forcing the property to be set should override the accessor without
   15456   // calling it
   15457   global->ForceSet(access_property, v8::Int32::New(isolate, 8));
   15458   CHECK_EQ(8, global->Get(access_property)->Int32Value());
   15459   CHECK_EQ(1, force_set_set_count);
   15460   CHECK_EQ(2, force_set_get_count);
   15461 }
   15462 
   15463 
   15464 TEST(ForceSetWithInterceptor) {
   15465   force_set_get_count = 0;
   15466   force_set_set_count = 0;
   15467   pass_on_get = false;
   15468 
   15469   v8::Isolate* isolate = CcTest::isolate();
   15470   v8::HandleScope scope(isolate);
   15471   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15472   templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
   15473   LocalContext context(NULL, templ);
   15474   v8::Handle<v8::Object> global = context->Global();
   15475 
   15476   v8::Handle<v8::String> some_property =
   15477       v8::String::NewFromUtf8(isolate, "a");
   15478   CHECK_EQ(0, force_set_set_count);
   15479   CHECK_EQ(0, force_set_get_count);
   15480   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   15481   // Setting the property shouldn't override it, just call the setter
   15482   // which in this case does nothing.
   15483   global->Set(some_property, v8::Int32::New(isolate, 7));
   15484   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   15485   CHECK_EQ(1, force_set_set_count);
   15486   CHECK_EQ(2, force_set_get_count);
   15487   // Getting the property when the interceptor returns an empty handle
   15488   // should yield undefined, since the property isn't present on the
   15489   // object itself yet.
   15490   pass_on_get = true;
   15491   CHECK(global->Get(some_property)->IsUndefined());
   15492   CHECK_EQ(1, force_set_set_count);
   15493   CHECK_EQ(3, force_set_get_count);
   15494   // Forcing the property to be set should cause the value to be
   15495   // set locally without calling the interceptor.
   15496   global->ForceSet(some_property, v8::Int32::New(isolate, 8));
   15497   CHECK_EQ(8, global->Get(some_property)->Int32Value());
   15498   CHECK_EQ(1, force_set_set_count);
   15499   CHECK_EQ(4, force_set_get_count);
   15500   // Reenabling the interceptor should cause it to take precedence over
   15501   // the property
   15502   pass_on_get = false;
   15503   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   15504   CHECK_EQ(1, force_set_set_count);
   15505   CHECK_EQ(5, force_set_get_count);
   15506   // The interceptor should also work for other properties
   15507   CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
   15508                   ->Int32Value());
   15509   CHECK_EQ(1, force_set_set_count);
   15510   CHECK_EQ(6, force_set_get_count);
   15511 }
   15512 
   15513 
   15514 THREADED_TEST(ForceDelete) {
   15515   v8::Isolate* isolate = CcTest::isolate();
   15516   v8::HandleScope scope(isolate);
   15517   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15518   LocalContext context(NULL, templ);
   15519   v8::Handle<v8::Object> global = context->Global();
   15520 
   15521   // Ordinary properties
   15522   v8::Handle<v8::String> simple_property =
   15523       v8::String::NewFromUtf8(isolate, "p");
   15524   global->ForceSet(simple_property, v8::Int32::New(isolate, 4), v8::DontDelete);
   15525   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   15526   // This should fail because the property is dont-delete.
   15527   CHECK(!global->Delete(simple_property));
   15528   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   15529   // This should succeed even though the property is dont-delete.
   15530   CHECK(global->ForceDelete(simple_property));
   15531   CHECK(global->Get(simple_property)->IsUndefined());
   15532 }
   15533 
   15534 
   15535 static int force_delete_interceptor_count = 0;
   15536 static bool pass_on_delete = false;
   15537 
   15538 
   15539 static void ForceDeleteDeleter(
   15540     v8::Local<v8::String> name,
   15541     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   15542   force_delete_interceptor_count++;
   15543   if (pass_on_delete) return;
   15544   info.GetReturnValue().Set(true);
   15545 }
   15546 
   15547 
   15548 THREADED_TEST(ForceDeleteWithInterceptor) {
   15549   force_delete_interceptor_count = 0;
   15550   pass_on_delete = false;
   15551 
   15552   v8::Isolate* isolate = CcTest::isolate();
   15553   v8::HandleScope scope(isolate);
   15554   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15555   templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
   15556   LocalContext context(NULL, templ);
   15557   v8::Handle<v8::Object> global = context->Global();
   15558 
   15559   v8::Handle<v8::String> some_property =
   15560       v8::String::NewFromUtf8(isolate, "a");
   15561   global->ForceSet(some_property, v8::Integer::New(isolate, 42),
   15562                    v8::DontDelete);
   15563 
   15564   // Deleting a property should get intercepted and nothing should
   15565   // happen.
   15566   CHECK_EQ(0, force_delete_interceptor_count);
   15567   CHECK(global->Delete(some_property));
   15568   CHECK_EQ(1, force_delete_interceptor_count);
   15569   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   15570   // Deleting the property when the interceptor returns an empty
   15571   // handle should not delete the property since it is DontDelete.
   15572   pass_on_delete = true;
   15573   CHECK(!global->Delete(some_property));
   15574   CHECK_EQ(2, force_delete_interceptor_count);
   15575   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   15576   // Forcing the property to be deleted should delete the value
   15577   // without calling the interceptor.
   15578   CHECK(global->ForceDelete(some_property));
   15579   CHECK(global->Get(some_property)->IsUndefined());
   15580   CHECK_EQ(2, force_delete_interceptor_count);
   15581 }
   15582 
   15583 
   15584 // Make sure that forcing a delete invalidates any IC stubs, so we
   15585 // don't read the hole value.
   15586 THREADED_TEST(ForceDeleteIC) {
   15587   LocalContext context;
   15588   v8::HandleScope scope(context->GetIsolate());
   15589   // Create a DontDelete variable on the global object.
   15590   CompileRun("this.__proto__ = { foo: 'horse' };"
   15591              "var foo = 'fish';"
   15592              "function f() { return foo.length; }");
   15593   // Initialize the IC for foo in f.
   15594   CompileRun("for (var i = 0; i < 4; i++) f();");
   15595   // Make sure the value of foo is correct before the deletion.
   15596   CHECK_EQ(4, CompileRun("f()")->Int32Value());
   15597   // Force the deletion of foo.
   15598   CHECK(context->Global()->ForceDelete(v8_str("foo")));
   15599   // Make sure the value for foo is read from the prototype, and that
   15600   // we don't get in trouble with reading the deleted cell value
   15601   // sentinel.
   15602   CHECK_EQ(5, CompileRun("f()")->Int32Value());
   15603 }
   15604 
   15605 
   15606 TEST(InlinedFunctionAcrossContexts) {
   15607   i::FLAG_allow_natives_syntax = true;
   15608   v8::Isolate* isolate = CcTest::isolate();
   15609   v8::HandleScope outer_scope(isolate);
   15610   v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
   15611   v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
   15612   ctx1->Enter();
   15613 
   15614   {
   15615     v8::HandleScope inner_scope(CcTest::isolate());
   15616     CompileRun("var G = 42; function foo() { return G; }");
   15617     v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
   15618     ctx2->Enter();
   15619     ctx2->Global()->Set(v8_str("o"), foo);
   15620     v8::Local<v8::Value> res = CompileRun(
   15621         "function f() { return o(); }"
   15622         "for (var i = 0; i < 10; ++i) f();"
   15623         "%OptimizeFunctionOnNextCall(f);"
   15624         "f();");
   15625     CHECK_EQ(42, res->Int32Value());
   15626     ctx2->Exit();
   15627     v8::Handle<v8::String> G_property =
   15628         v8::String::NewFromUtf8(CcTest::isolate(), "G");
   15629     CHECK(ctx1->Global()->ForceDelete(G_property));
   15630     ctx2->Enter();
   15631     ExpectString(
   15632         "(function() {"
   15633         "  try {"
   15634         "    return f();"
   15635         "  } catch(e) {"
   15636         "    return e.toString();"
   15637         "  }"
   15638         " })()",
   15639         "ReferenceError: G is not defined");
   15640     ctx2->Exit();
   15641     ctx1->Exit();
   15642   }
   15643 }
   15644 
   15645 
   15646 static v8::Local<Context> calling_context0;
   15647 static v8::Local<Context> calling_context1;
   15648 static v8::Local<Context> calling_context2;
   15649 
   15650 
   15651 // Check that the call to the callback is initiated in
   15652 // calling_context2, the directly calling context is calling_context1
   15653 // and the callback itself is in calling_context0.
   15654 static void GetCallingContextCallback(
   15655     const v8::FunctionCallbackInfo<v8::Value>& args) {
   15656   ApiTestFuzzer::Fuzz();
   15657   CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
   15658   CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
   15659   CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
   15660   args.GetReturnValue().Set(42);
   15661 }
   15662 
   15663 
   15664 THREADED_TEST(GetCurrentContextWhenNotInContext) {
   15665   i::Isolate* isolate = CcTest::i_isolate();
   15666   CHECK(isolate != NULL);
   15667   CHECK(isolate->context() == NULL);
   15668   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   15669   v8::HandleScope scope(v8_isolate);
   15670   // The following should not crash, but return an empty handle.
   15671   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
   15672   CHECK(current.IsEmpty());
   15673 }
   15674 
   15675 
   15676 THREADED_TEST(GetCallingContext) {
   15677   v8::Isolate* isolate = CcTest::isolate();
   15678   v8::HandleScope scope(isolate);
   15679 
   15680   Local<Context> calling_context0(Context::New(isolate));
   15681   Local<Context> calling_context1(Context::New(isolate));
   15682   Local<Context> calling_context2(Context::New(isolate));
   15683   ::calling_context0 = calling_context0;
   15684   ::calling_context1 = calling_context1;
   15685   ::calling_context2 = calling_context2;
   15686 
   15687   // Allow cross-domain access.
   15688   Local<String> token = v8_str("<security token>");
   15689   calling_context0->SetSecurityToken(token);
   15690   calling_context1->SetSecurityToken(token);
   15691   calling_context2->SetSecurityToken(token);
   15692 
   15693   // Create an object with a C++ callback in context0.
   15694   calling_context0->Enter();
   15695   Local<v8::FunctionTemplate> callback_templ =
   15696       v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
   15697   calling_context0->Global()->Set(v8_str("callback"),
   15698                                   callback_templ->GetFunction());
   15699   calling_context0->Exit();
   15700 
   15701   // Expose context0 in context1 and set up a function that calls the
   15702   // callback function.
   15703   calling_context1->Enter();
   15704   calling_context1->Global()->Set(v8_str("context0"),
   15705                                   calling_context0->Global());
   15706   CompileRun("function f() { context0.callback() }");
   15707   calling_context1->Exit();
   15708 
   15709   // Expose context1 in context2 and call the callback function in
   15710   // context0 indirectly through f in context1.
   15711   calling_context2->Enter();
   15712   calling_context2->Global()->Set(v8_str("context1"),
   15713                                   calling_context1->Global());
   15714   CompileRun("context1.f()");
   15715   calling_context2->Exit();
   15716   ::calling_context0.Clear();
   15717   ::calling_context1.Clear();
   15718   ::calling_context2.Clear();
   15719 }
   15720 
   15721 
   15722 // Check that a variable declaration with no explicit initialization
   15723 // value does shadow an existing property in the prototype chain.
   15724 THREADED_TEST(InitGlobalVarInProtoChain) {
   15725   LocalContext context;
   15726   v8::HandleScope scope(context->GetIsolate());
   15727   // Introduce a variable in the prototype chain.
   15728   CompileRun("__proto__.x = 42");
   15729   v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
   15730   CHECK(!result->IsUndefined());
   15731   CHECK_EQ(43, result->Int32Value());
   15732 }
   15733 
   15734 
   15735 // Regression test for issue 398.
   15736 // If a function is added to an object, creating a constant function
   15737 // field, and the result is cloned, replacing the constant function on the
   15738 // original should not affect the clone.
   15739 // See http://code.google.com/p/v8/issues/detail?id=398
   15740 THREADED_TEST(ReplaceConstantFunction) {
   15741   LocalContext context;
   15742   v8::Isolate* isolate = context->GetIsolate();
   15743   v8::HandleScope scope(isolate);
   15744   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
   15745   v8::Handle<v8::FunctionTemplate> func_templ =
   15746       v8::FunctionTemplate::New(isolate);
   15747   v8::Handle<v8::String> foo_string =
   15748       v8::String::NewFromUtf8(isolate, "foo");
   15749   obj->Set(foo_string, func_templ->GetFunction());
   15750   v8::Handle<v8::Object> obj_clone = obj->Clone();
   15751   obj_clone->Set(foo_string,
   15752                  v8::String::NewFromUtf8(isolate, "Hello"));
   15753   CHECK(!obj->Get(foo_string)->IsUndefined());
   15754 }
   15755 
   15756 
   15757 static void CheckElementValue(i::Isolate* isolate,
   15758                               int expected,
   15759                               i::Handle<i::Object> obj,
   15760                               int offset) {
   15761   i::Object* element =
   15762       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
   15763   CHECK_EQ(expected, i::Smi::cast(element)->value());
   15764 }
   15765 
   15766 
   15767 THREADED_TEST(PixelArray) {
   15768   LocalContext context;
   15769   i::Isolate* isolate = CcTest::i_isolate();
   15770   i::Factory* factory = isolate->factory();
   15771   v8::HandleScope scope(context->GetIsolate());
   15772   const int kElementCount = 260;
   15773   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   15774   i::Handle<i::ExternalUint8ClampedArray> pixels =
   15775       i::Handle<i::ExternalUint8ClampedArray>::cast(
   15776           factory->NewExternalArray(kElementCount,
   15777                                     v8::kExternalUint8ClampedArray,
   15778                                     pixel_data));
   15779   // Force GC to trigger verification.
   15780   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   15781   for (int i = 0; i < kElementCount; i++) {
   15782     pixels->set(i, i % 256);
   15783   }
   15784   // Force GC to trigger verification.
   15785   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   15786   for (int i = 0; i < kElementCount; i++) {
   15787     CHECK_EQ(i % 256, pixels->get_scalar(i));
   15788     CHECK_EQ(i % 256, pixel_data[i]);
   15789   }
   15790 
   15791   v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
   15792   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   15793   // Set the elements to be the pixels.
   15794   // jsobj->set_elements(*pixels);
   15795   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   15796   CheckElementValue(isolate, 1, jsobj, 1);
   15797   obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
   15798   context->Global()->Set(v8_str("pixels"), obj);
   15799   v8::Handle<v8::Value> result = CompileRun("pixels.field");
   15800   CHECK_EQ(1503, result->Int32Value());
   15801   result = CompileRun("pixels[1]");
   15802   CHECK_EQ(1, result->Int32Value());
   15803 
   15804   result = CompileRun("var sum = 0;"
   15805                       "for (var i = 0; i < 8; i++) {"
   15806                       "  sum += pixels[i] = pixels[i] = -i;"
   15807                       "}"
   15808                       "sum;");
   15809   CHECK_EQ(-28, result->Int32Value());
   15810 
   15811   result = CompileRun("var sum = 0;"
   15812                       "for (var i = 0; i < 8; i++) {"
   15813                       "  sum += pixels[i] = pixels[i] = 0;"
   15814                       "}"
   15815                       "sum;");
   15816   CHECK_EQ(0, result->Int32Value());
   15817 
   15818   result = CompileRun("var sum = 0;"
   15819                       "for (var i = 0; i < 8; i++) {"
   15820                       "  sum += pixels[i] = pixels[i] = 255;"
   15821                       "}"
   15822                       "sum;");
   15823   CHECK_EQ(8 * 255, result->Int32Value());
   15824 
   15825   result = CompileRun("var sum = 0;"
   15826                       "for (var i = 0; i < 8; i++) {"
   15827                       "  sum += pixels[i] = pixels[i] = 256 + i;"
   15828                       "}"
   15829                       "sum;");
   15830   CHECK_EQ(2076, result->Int32Value());
   15831 
   15832   result = CompileRun("var sum = 0;"
   15833                       "for (var i = 0; i < 8; i++) {"
   15834                       "  sum += pixels[i] = pixels[i] = i;"
   15835                       "}"
   15836                       "sum;");
   15837   CHECK_EQ(28, result->Int32Value());
   15838 
   15839   result = CompileRun("var sum = 0;"
   15840                       "for (var i = 0; i < 8; i++) {"
   15841                       "  sum += pixels[i];"
   15842                       "}"
   15843                       "sum;");
   15844   CHECK_EQ(28, result->Int32Value());
   15845 
   15846   i::Handle<i::Smi> value(i::Smi::FromInt(2),
   15847                           reinterpret_cast<i::Isolate*>(context->GetIsolate()));
   15848   i::Handle<i::Object> no_failure;
   15849   no_failure = i::JSObject::SetElement(
   15850       jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
   15851   DCHECK(!no_failure.is_null());
   15852   USE(no_failure);
   15853   CheckElementValue(isolate, 2, jsobj, 1);
   15854   *value.location() = i::Smi::FromInt(256);
   15855   no_failure = i::JSObject::SetElement(
   15856       jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
   15857   DCHECK(!no_failure.is_null());
   15858   USE(no_failure);
   15859   CheckElementValue(isolate, 255, jsobj, 1);
   15860   *value.location() = i::Smi::FromInt(-1);
   15861   no_failure = i::JSObject::SetElement(
   15862       jsobj, 1, value, NONE, i::SLOPPY).ToHandleChecked();
   15863   DCHECK(!no_failure.is_null());
   15864   USE(no_failure);
   15865   CheckElementValue(isolate, 0, jsobj, 1);
   15866 
   15867   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15868                       "  pixels[i] = (i * 65) - 109;"
   15869                       "}"
   15870                       "pixels[1] + pixels[6];");
   15871   CHECK_EQ(255, result->Int32Value());
   15872   CheckElementValue(isolate, 0, jsobj, 0);
   15873   CheckElementValue(isolate, 0, jsobj, 1);
   15874   CheckElementValue(isolate, 21, jsobj, 2);
   15875   CheckElementValue(isolate, 86, jsobj, 3);
   15876   CheckElementValue(isolate, 151, jsobj, 4);
   15877   CheckElementValue(isolate, 216, jsobj, 5);
   15878   CheckElementValue(isolate, 255, jsobj, 6);
   15879   CheckElementValue(isolate, 255, jsobj, 7);
   15880   result = CompileRun("var sum = 0;"
   15881                       "for (var i = 0; i < 8; i++) {"
   15882                       "  sum += pixels[i];"
   15883                       "}"
   15884                       "sum;");
   15885   CHECK_EQ(984, result->Int32Value());
   15886 
   15887   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15888                       "  pixels[i] = (i * 1.1);"
   15889                       "}"
   15890                       "pixels[1] + pixels[6];");
   15891   CHECK_EQ(8, result->Int32Value());
   15892   CheckElementValue(isolate, 0, jsobj, 0);
   15893   CheckElementValue(isolate, 1, jsobj, 1);
   15894   CheckElementValue(isolate, 2, jsobj, 2);
   15895   CheckElementValue(isolate, 3, jsobj, 3);
   15896   CheckElementValue(isolate, 4, jsobj, 4);
   15897   CheckElementValue(isolate, 6, jsobj, 5);
   15898   CheckElementValue(isolate, 7, jsobj, 6);
   15899   CheckElementValue(isolate, 8, jsobj, 7);
   15900 
   15901   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15902                       "  pixels[7] = undefined;"
   15903                       "}"
   15904                       "pixels[7];");
   15905   CHECK_EQ(0, result->Int32Value());
   15906   CheckElementValue(isolate, 0, jsobj, 7);
   15907 
   15908   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15909                       "  pixels[6] = '2.3';"
   15910                       "}"
   15911                       "pixels[6];");
   15912   CHECK_EQ(2, result->Int32Value());
   15913   CheckElementValue(isolate, 2, jsobj, 6);
   15914 
   15915   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15916                       "  pixels[5] = NaN;"
   15917                       "}"
   15918                       "pixels[5];");
   15919   CHECK_EQ(0, result->Int32Value());
   15920   CheckElementValue(isolate, 0, jsobj, 5);
   15921 
   15922   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15923                       "  pixels[8] = Infinity;"
   15924                       "}"
   15925                       "pixels[8];");
   15926   CHECK_EQ(255, result->Int32Value());
   15927   CheckElementValue(isolate, 255, jsobj, 8);
   15928 
   15929   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15930                       "  pixels[9] = -Infinity;"
   15931                       "}"
   15932                       "pixels[9];");
   15933   CHECK_EQ(0, result->Int32Value());
   15934   CheckElementValue(isolate, 0, jsobj, 9);
   15935 
   15936   result = CompileRun("pixels[3] = 33;"
   15937                       "delete pixels[3];"
   15938                       "pixels[3];");
   15939   CHECK_EQ(33, result->Int32Value());
   15940 
   15941   result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
   15942                       "pixels[2] = 12; pixels[3] = 13;"
   15943                       "pixels.__defineGetter__('2',"
   15944                       "function() { return 120; });"
   15945                       "pixels[2];");
   15946   CHECK_EQ(12, result->Int32Value());
   15947 
   15948   result = CompileRun("var js_array = new Array(40);"
   15949                       "js_array[0] = 77;"
   15950                       "js_array;");
   15951   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   15952 
   15953   result = CompileRun("pixels[1] = 23;"
   15954                       "pixels.__proto__ = [];"
   15955                       "js_array.__proto__ = pixels;"
   15956                       "js_array.concat(pixels);");
   15957   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   15958   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   15959 
   15960   result = CompileRun("pixels[1] = 23;");
   15961   CHECK_EQ(23, result->Int32Value());
   15962 
   15963   // Test for index greater than 255.  Regression test for:
   15964   // http://code.google.com/p/chromium/issues/detail?id=26337.
   15965   result = CompileRun("pixels[256] = 255;");
   15966   CHECK_EQ(255, result->Int32Value());
   15967   result = CompileRun("var i = 0;"
   15968                       "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
   15969                       "i");
   15970   CHECK_EQ(255, result->Int32Value());
   15971 
   15972   // Make sure that pixel array ICs recognize when a non-pixel array
   15973   // is passed to it.
   15974   result = CompileRun("function pa_load(p) {"
   15975                       "  var sum = 0;"
   15976                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   15977                       "  return sum;"
   15978                       "}"
   15979                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15980                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   15981                       "just_ints = new Object();"
   15982                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15983                       "for (var i = 0; i < 10; ++i) {"
   15984                       "  result = pa_load(just_ints);"
   15985                       "}"
   15986                       "result");
   15987   CHECK_EQ(32640, result->Int32Value());
   15988 
   15989   // Make sure that pixel array ICs recognize out-of-bound accesses.
   15990   result = CompileRun("function pa_load(p, start) {"
   15991                       "  var sum = 0;"
   15992                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   15993                       "  return sum;"
   15994                       "}"
   15995                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15996                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   15997                       "for (var i = 0; i < 10; ++i) {"
   15998                       "  result = pa_load(pixels,-10);"
   15999                       "}"
   16000                       "result");
   16001   CHECK_EQ(0, result->Int32Value());
   16002 
   16003   // Make sure that generic ICs properly handles a pixel array.
   16004   result = CompileRun("function pa_load(p) {"
   16005                       "  var sum = 0;"
   16006                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   16007                       "  return sum;"
   16008                       "}"
   16009                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   16010                       "just_ints = new Object();"
   16011                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   16012                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   16013                       "for (var i = 0; i < 10; ++i) {"
   16014                       "  result = pa_load(pixels);"
   16015                       "}"
   16016                       "result");
   16017   CHECK_EQ(32640, result->Int32Value());
   16018 
   16019   // Make sure that generic load ICs recognize out-of-bound accesses in
   16020   // pixel arrays.
   16021   result = CompileRun("function pa_load(p, start) {"
   16022                       "  var sum = 0;"
   16023                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   16024                       "  return sum;"
   16025                       "}"
   16026                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   16027                       "just_ints = new Object();"
   16028                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   16029                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
   16030                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   16031                       "for (var i = 0; i < 10; ++i) {"
   16032                       "  result = pa_load(pixels,-10);"
   16033                       "}"
   16034                       "result");
   16035   CHECK_EQ(0, result->Int32Value());
   16036 
   16037   // Make sure that generic ICs properly handles other types than pixel
   16038   // arrays (that the inlined fast pixel array test leaves the right information
   16039   // in the right registers).
   16040   result = CompileRun("function pa_load(p) {"
   16041                       "  var sum = 0;"
   16042                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   16043                       "  return sum;"
   16044                       "}"
   16045                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   16046                       "just_ints = new Object();"
   16047                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   16048                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   16049                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   16050                       "sparse_array = new Object();"
   16051                       "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
   16052                       "sparse_array[1000000] = 3;"
   16053                       "for (var i = 0; i < 10; ++i) {"
   16054                       "  result = pa_load(sparse_array);"
   16055                       "}"
   16056                       "result");
   16057   CHECK_EQ(32640, result->Int32Value());
   16058 
   16059   // Make sure that pixel array store ICs clamp values correctly.
   16060   result = CompileRun("function pa_store(p) {"
   16061                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   16062                       "}"
   16063                       "pa_store(pixels);"
   16064                       "var sum = 0;"
   16065                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   16066                       "sum");
   16067   CHECK_EQ(48896, result->Int32Value());
   16068 
   16069   // Make sure that pixel array stores correctly handle accesses outside
   16070   // of the pixel array..
   16071   result = CompileRun("function pa_store(p,start) {"
   16072                       "  for (var j = 0; j < 256; j++) {"
   16073                       "    p[j+start] = j * 2;"
   16074                       "  }"
   16075                       "}"
   16076                       "pa_store(pixels,0);"
   16077                       "pa_store(pixels,-128);"
   16078                       "var sum = 0;"
   16079                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   16080                       "sum");
   16081   CHECK_EQ(65280, result->Int32Value());
   16082 
   16083   // Make sure that the generic store stub correctly handle accesses outside
   16084   // of the pixel array..
   16085   result = CompileRun("function pa_store(p,start) {"
   16086                       "  for (var j = 0; j < 256; j++) {"
   16087                       "    p[j+start] = j * 2;"
   16088                       "  }"
   16089                       "}"
   16090                       "pa_store(pixels,0);"
   16091                       "just_ints = new Object();"
   16092                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   16093                       "pa_store(just_ints, 0);"
   16094                       "pa_store(pixels,-128);"
   16095                       "var sum = 0;"
   16096                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   16097                       "sum");
   16098   CHECK_EQ(65280, result->Int32Value());
   16099 
   16100   // Make sure that the generic keyed store stub clamps pixel array values
   16101   // correctly.
   16102   result = CompileRun("function pa_store(p) {"
   16103                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   16104                       "}"
   16105                       "pa_store(pixels);"
   16106                       "just_ints = new Object();"
   16107                       "pa_store(just_ints);"
   16108                       "pa_store(pixels);"
   16109                       "var sum = 0;"
   16110                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   16111                       "sum");
   16112   CHECK_EQ(48896, result->Int32Value());
   16113 
   16114   // Make sure that pixel array loads are optimized by crankshaft.
   16115   result = CompileRun("function pa_load(p) {"
   16116                       "  var sum = 0;"
   16117                       "  for (var i=0; i<256; ++i) {"
   16118                       "    sum += p[i];"
   16119                       "  }"
   16120                       "  return sum; "
   16121                       "}"
   16122                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   16123                       "for (var i = 0; i < 5000; ++i) {"
   16124                       "  result = pa_load(pixels);"
   16125                       "}"
   16126                       "result");
   16127   CHECK_EQ(32640, result->Int32Value());
   16128 
   16129   // Make sure that pixel array stores are optimized by crankshaft.
   16130   result = CompileRun("function pa_init(p) {"
   16131                       "for (var i = 0; i < 256; ++i) { p[i] = i; }"
   16132                       "}"
   16133                       "function pa_load(p) {"
   16134                       "  var sum = 0;"
   16135                       "  for (var i=0; i<256; ++i) {"
   16136                       "    sum += p[i];"
   16137                       "  }"
   16138                       "  return sum; "
   16139                       "}"
   16140                       "for (var i = 0; i < 5000; ++i) {"
   16141                       "  pa_init(pixels);"
   16142                       "}"
   16143                       "result = pa_load(pixels);"
   16144                       "result");
   16145   CHECK_EQ(32640, result->Int32Value());
   16146 
   16147   free(pixel_data);
   16148 }
   16149 
   16150 
   16151 THREADED_TEST(PixelArrayInfo) {
   16152   LocalContext context;
   16153   v8::HandleScope scope(context->GetIsolate());
   16154   for (int size = 0; size < 100; size += 10) {
   16155     uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
   16156     v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
   16157     obj->SetIndexedPropertiesToPixelData(pixel_data, size);
   16158     CHECK(obj->HasIndexedPropertiesInPixelData());
   16159     CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
   16160     CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
   16161     free(pixel_data);
   16162   }
   16163 }
   16164 
   16165 
   16166 static void NotHandledIndexedPropertyGetter(
   16167     uint32_t index,
   16168     const v8::PropertyCallbackInfo<v8::Value>& info) {
   16169   ApiTestFuzzer::Fuzz();
   16170 }
   16171 
   16172 
   16173 static void NotHandledIndexedPropertySetter(
   16174     uint32_t index,
   16175     Local<Value> value,
   16176     const v8::PropertyCallbackInfo<v8::Value>& info) {
   16177   ApiTestFuzzer::Fuzz();
   16178 }
   16179 
   16180 
   16181 THREADED_TEST(PixelArrayWithInterceptor) {
   16182   LocalContext context;
   16183   i::Factory* factory = CcTest::i_isolate()->factory();
   16184   v8::Isolate* isolate = context->GetIsolate();
   16185   v8::HandleScope scope(isolate);
   16186   const int kElementCount = 260;
   16187   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   16188   i::Handle<i::ExternalUint8ClampedArray> pixels =
   16189       i::Handle<i::ExternalUint8ClampedArray>::cast(
   16190           factory->NewExternalArray(kElementCount,
   16191                                     v8::kExternalUint8ClampedArray,
   16192                                     pixel_data));
   16193   for (int i = 0; i < kElementCount; i++) {
   16194     pixels->set(i, i % 256);
   16195   }
   16196   v8::Handle<v8::ObjectTemplate> templ =
   16197       v8::ObjectTemplate::New(context->GetIsolate());
   16198   templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
   16199                                    NotHandledIndexedPropertySetter);
   16200   v8::Handle<v8::Object> obj = templ->NewInstance();
   16201   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   16202   context->Global()->Set(v8_str("pixels"), obj);
   16203   v8::Handle<v8::Value> result = CompileRun("pixels[1]");
   16204   CHECK_EQ(1, result->Int32Value());
   16205   result = CompileRun("var sum = 0;"
   16206                       "for (var i = 0; i < 8; i++) {"
   16207                       "  sum += pixels[i] = pixels[i] = -i;"
   16208                       "}"
   16209                       "sum;");
   16210   CHECK_EQ(-28, result->Int32Value());
   16211   result = CompileRun("pixels.hasOwnProperty('1')");
   16212   CHECK(result->BooleanValue());
   16213   free(pixel_data);
   16214 }
   16215 
   16216 
   16217 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
   16218   switch (array_type) {
   16219     case v8::kExternalInt8Array:
   16220     case v8::kExternalUint8Array:
   16221     case v8::kExternalUint8ClampedArray:
   16222       return 1;
   16223       break;
   16224     case v8::kExternalInt16Array:
   16225     case v8::kExternalUint16Array:
   16226       return 2;
   16227       break;
   16228     case v8::kExternalInt32Array:
   16229     case v8::kExternalUint32Array:
   16230     case v8::kExternalFloat32Array:
   16231       return 4;
   16232       break;
   16233     case v8::kExternalFloat64Array:
   16234       return 8;
   16235       break;
   16236     default:
   16237       UNREACHABLE();
   16238       return -1;
   16239   }
   16240   UNREACHABLE();
   16241   return -1;
   16242 }
   16243 
   16244 
   16245 template <class ExternalArrayClass, class ElementType>
   16246 static void ObjectWithExternalArrayTestHelper(
   16247     Handle<Context> context,
   16248     v8::Handle<Object> obj,
   16249     int element_count,
   16250     v8::ExternalArrayType array_type,
   16251     int64_t low, int64_t high) {
   16252   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   16253   i::Isolate* isolate = jsobj->GetIsolate();
   16254   obj->Set(v8_str("field"),
   16255            v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
   16256   context->Global()->Set(v8_str("ext_array"), obj);
   16257   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
   16258   CHECK_EQ(1503, result->Int32Value());
   16259   result = CompileRun("ext_array[1]");
   16260   CHECK_EQ(1, result->Int32Value());
   16261 
   16262   // Check assigned smis
   16263   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16264                       "  ext_array[i] = i;"
   16265                       "}"
   16266                       "var sum = 0;"
   16267                       "for (var i = 0; i < 8; i++) {"
   16268                       "  sum += ext_array[i];"
   16269                       "}"
   16270                       "sum;");
   16271 
   16272   CHECK_EQ(28, result->Int32Value());
   16273   // Check pass through of assigned smis
   16274   result = CompileRun("var sum = 0;"
   16275                       "for (var i = 0; i < 8; i++) {"
   16276                       "  sum += ext_array[i] = ext_array[i] = -i;"
   16277                       "}"
   16278                       "sum;");
   16279   CHECK_EQ(-28, result->Int32Value());
   16280 
   16281 
   16282   // Check assigned smis in reverse order
   16283   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   16284                       "  ext_array[i] = i;"
   16285                       "}"
   16286                       "var sum = 0;"
   16287                       "for (var i = 0; i < 8; i++) {"
   16288                       "  sum += ext_array[i];"
   16289                       "}"
   16290                       "sum;");
   16291   CHECK_EQ(28, result->Int32Value());
   16292 
   16293   // Check pass through of assigned HeapNumbers
   16294   result = CompileRun("var sum = 0;"
   16295                       "for (var i = 0; i < 16; i+=2) {"
   16296                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   16297                       "}"
   16298                       "sum;");
   16299   CHECK_EQ(-28, result->Int32Value());
   16300 
   16301   // Check assigned HeapNumbers
   16302   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   16303                       "  ext_array[i] = (i * 0.5);"
   16304                       "}"
   16305                       "var sum = 0;"
   16306                       "for (var i = 0; i < 16; i+=2) {"
   16307                       "  sum += ext_array[i];"
   16308                       "}"
   16309                       "sum;");
   16310   CHECK_EQ(28, result->Int32Value());
   16311 
   16312   // Check assigned HeapNumbers in reverse order
   16313   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   16314                       "  ext_array[i] = (i * 0.5);"
   16315                       "}"
   16316                       "var sum = 0;"
   16317                       "for (var i = 0; i < 16; i+=2) {"
   16318                       "  sum += ext_array[i];"
   16319                       "}"
   16320                       "sum;");
   16321   CHECK_EQ(28, result->Int32Value());
   16322 
   16323   i::ScopedVector<char> test_buf(1024);
   16324 
   16325   // Check legal boundary conditions.
   16326   // The repeated loads and stores ensure the ICs are exercised.
   16327   const char* boundary_program =
   16328       "var res = 0;"
   16329       "for (var i = 0; i < 16; i++) {"
   16330       "  ext_array[i] = %lld;"
   16331       "  if (i > 8) {"
   16332       "    res = ext_array[i];"
   16333       "  }"
   16334       "}"
   16335       "res;";
   16336   i::SNPrintF(test_buf,
   16337               boundary_program,
   16338               low);
   16339   result = CompileRun(test_buf.start());
   16340   CHECK_EQ(low, result->IntegerValue());
   16341 
   16342   i::SNPrintF(test_buf,
   16343               boundary_program,
   16344               high);
   16345   result = CompileRun(test_buf.start());
   16346   CHECK_EQ(high, result->IntegerValue());
   16347 
   16348   // Check misprediction of type in IC.
   16349   result = CompileRun("var tmp_array = ext_array;"
   16350                       "var sum = 0;"
   16351                       "for (var i = 0; i < 8; i++) {"
   16352                       "  tmp_array[i] = i;"
   16353                       "  sum += tmp_array[i];"
   16354                       "  if (i == 4) {"
   16355                       "    tmp_array = {};"
   16356                       "  }"
   16357                       "}"
   16358                       "sum;");
   16359   // Force GC to trigger verification.
   16360   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   16361   CHECK_EQ(28, result->Int32Value());
   16362 
   16363   // Make sure out-of-range loads do not throw.
   16364   i::SNPrintF(test_buf,
   16365               "var caught_exception = false;"
   16366               "try {"
   16367               "  ext_array[%d];"
   16368               "} catch (e) {"
   16369               "  caught_exception = true;"
   16370               "}"
   16371               "caught_exception;",
   16372               element_count);
   16373   result = CompileRun(test_buf.start());
   16374   CHECK_EQ(false, result->BooleanValue());
   16375 
   16376   // Make sure out-of-range stores do not throw.
   16377   i::SNPrintF(test_buf,
   16378               "var caught_exception = false;"
   16379               "try {"
   16380               "  ext_array[%d] = 1;"
   16381               "} catch (e) {"
   16382               "  caught_exception = true;"
   16383               "}"
   16384               "caught_exception;",
   16385               element_count);
   16386   result = CompileRun(test_buf.start());
   16387   CHECK_EQ(false, result->BooleanValue());
   16388 
   16389   // Check other boundary conditions, values and operations.
   16390   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16391                       "  ext_array[7] = undefined;"
   16392                       "}"
   16393                       "ext_array[7];");
   16394   CHECK_EQ(0, result->Int32Value());
   16395   if (array_type == v8::kExternalFloat64Array ||
   16396       array_type == v8::kExternalFloat32Array) {
   16397     CHECK_EQ(static_cast<int>(v8::base::OS::nan_value()),
   16398              static_cast<int>(
   16399                  i::Object::GetElement(
   16400                      isolate, jsobj, 7).ToHandleChecked()->Number()));
   16401   } else {
   16402     CheckElementValue(isolate, 0, jsobj, 7);
   16403   }
   16404 
   16405   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16406                       "  ext_array[6] = '2.3';"
   16407                       "}"
   16408                       "ext_array[6];");
   16409   CHECK_EQ(2, result->Int32Value());
   16410   CHECK_EQ(2,
   16411            static_cast<int>(
   16412                i::Object::GetElement(
   16413                    isolate, jsobj, 6).ToHandleChecked()->Number()));
   16414 
   16415   if (array_type != v8::kExternalFloat32Array &&
   16416       array_type != v8::kExternalFloat64Array) {
   16417     // Though the specification doesn't state it, be explicit about
   16418     // converting NaNs and +/-Infinity to zero.
   16419     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16420                         "  ext_array[i] = 5;"
   16421                         "}"
   16422                         "for (var i = 0; i < 8; i++) {"
   16423                         "  ext_array[i] = NaN;"
   16424                         "}"
   16425                         "ext_array[5];");
   16426     CHECK_EQ(0, result->Int32Value());
   16427     CheckElementValue(isolate, 0, jsobj, 5);
   16428 
   16429     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16430                         "  ext_array[i] = 5;"
   16431                         "}"
   16432                         "for (var i = 0; i < 8; i++) {"
   16433                         "  ext_array[i] = Infinity;"
   16434                         "}"
   16435                         "ext_array[5];");
   16436     int expected_value =
   16437         (array_type == v8::kExternalUint8ClampedArray) ? 255 : 0;
   16438     CHECK_EQ(expected_value, result->Int32Value());
   16439     CheckElementValue(isolate, expected_value, jsobj, 5);
   16440 
   16441     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16442                         "  ext_array[i] = 5;"
   16443                         "}"
   16444                         "for (var i = 0; i < 8; i++) {"
   16445                         "  ext_array[i] = -Infinity;"
   16446                         "}"
   16447                         "ext_array[5];");
   16448     CHECK_EQ(0, result->Int32Value());
   16449     CheckElementValue(isolate, 0, jsobj, 5);
   16450 
   16451     // Check truncation behavior of integral arrays.
   16452     const char* unsigned_data =
   16453         "var source_data = [0.6, 10.6];"
   16454         "var expected_results = [0, 10];";
   16455     const char* signed_data =
   16456         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   16457         "var expected_results = [0, 10, 0, -10];";
   16458     const char* pixel_data =
   16459         "var source_data = [0.6, 10.6];"
   16460         "var expected_results = [1, 11];";
   16461     bool is_unsigned =
   16462         (array_type == v8::kExternalUint8Array ||
   16463          array_type == v8::kExternalUint16Array ||
   16464          array_type == v8::kExternalUint32Array);
   16465     bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
   16466 
   16467     i::SNPrintF(test_buf,
   16468                 "%s"
   16469                 "var all_passed = true;"
   16470                 "for (var i = 0; i < source_data.length; i++) {"
   16471                 "  for (var j = 0; j < 8; j++) {"
   16472                 "    ext_array[j] = source_data[i];"
   16473                 "  }"
   16474                 "  all_passed = all_passed &&"
   16475                 "               (ext_array[5] == expected_results[i]);"
   16476                 "}"
   16477                 "all_passed;",
   16478                 (is_unsigned ?
   16479                      unsigned_data :
   16480                      (is_pixel_data ? pixel_data : signed_data)));
   16481     result = CompileRun(test_buf.start());
   16482     CHECK_EQ(true, result->BooleanValue());
   16483   }
   16484 
   16485   i::Handle<ExternalArrayClass> array(
   16486       ExternalArrayClass::cast(jsobj->elements()));
   16487   for (int i = 0; i < element_count; i++) {
   16488     array->set(i, static_cast<ElementType>(i));
   16489   }
   16490 
   16491   // Test complex assignments
   16492   result = CompileRun("function ee_op_test_complex_func(sum) {"
   16493                       " for (var i = 0; i < 40; ++i) {"
   16494                       "   sum += (ext_array[i] += 1);"
   16495                       "   sum += (ext_array[i] -= 1);"
   16496                       " } "
   16497                       " return sum;"
   16498                       "}"
   16499                       "sum=0;"
   16500                       "for (var i=0;i<10000;++i) {"
   16501                       "  sum=ee_op_test_complex_func(sum);"
   16502                       "}"
   16503                       "sum;");
   16504   CHECK_EQ(16000000, result->Int32Value());
   16505 
   16506   // Test count operations
   16507   result = CompileRun("function ee_op_test_count_func(sum) {"
   16508                       " for (var i = 0; i < 40; ++i) {"
   16509                       "   sum += (++ext_array[i]);"
   16510                       "   sum += (--ext_array[i]);"
   16511                       " } "
   16512                       " return sum;"
   16513                       "}"
   16514                       "sum=0;"
   16515                       "for (var i=0;i<10000;++i) {"
   16516                       "  sum=ee_op_test_count_func(sum);"
   16517                       "}"
   16518                       "sum;");
   16519   CHECK_EQ(16000000, result->Int32Value());
   16520 
   16521   result = CompileRun("ext_array[3] = 33;"
   16522                       "delete ext_array[3];"
   16523                       "ext_array[3];");
   16524   CHECK_EQ(33, result->Int32Value());
   16525 
   16526   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
   16527                       "ext_array[2] = 12; ext_array[3] = 13;"
   16528                       "ext_array.__defineGetter__('2',"
   16529                       "function() { return 120; });"
   16530                       "ext_array[2];");
   16531   CHECK_EQ(12, result->Int32Value());
   16532 
   16533   result = CompileRun("var js_array = new Array(40);"
   16534                       "js_array[0] = 77;"
   16535                       "js_array;");
   16536   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   16537 
   16538   result = CompileRun("ext_array[1] = 23;"
   16539                       "ext_array.__proto__ = [];"
   16540                       "js_array.__proto__ = ext_array;"
   16541                       "js_array.concat(ext_array);");
   16542   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   16543   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   16544 
   16545   result = CompileRun("ext_array[1] = 23;");
   16546   CHECK_EQ(23, result->Int32Value());
   16547 }
   16548 
   16549 
   16550 template <class FixedTypedArrayClass,
   16551           i::ElementsKind elements_kind,
   16552           class ElementType>
   16553 static void FixedTypedArrayTestHelper(
   16554     v8::ExternalArrayType array_type,
   16555     ElementType low,
   16556     ElementType high) {
   16557   i::FLAG_allow_natives_syntax = true;
   16558   LocalContext context;
   16559   i::Isolate* isolate = CcTest::i_isolate();
   16560   i::Factory* factory = isolate->factory();
   16561   v8::HandleScope scope(context->GetIsolate());
   16562   const int kElementCount = 260;
   16563   i::Handle<FixedTypedArrayClass> fixed_array =
   16564     i::Handle<FixedTypedArrayClass>::cast(
   16565         factory->NewFixedTypedArray(kElementCount, array_type));
   16566   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
   16567            fixed_array->map()->instance_type());
   16568   CHECK_EQ(kElementCount, fixed_array->length());
   16569   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   16570   for (int i = 0; i < kElementCount; i++) {
   16571     fixed_array->set(i, static_cast<ElementType>(i));
   16572   }
   16573   // Force GC to trigger verification.
   16574   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   16575   for (int i = 0; i < kElementCount; i++) {
   16576     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
   16577              static_cast<int64_t>(fixed_array->get_scalar(i)));
   16578   }
   16579   v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
   16580   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   16581   i::Handle<i::Map> fixed_array_map =
   16582       i::JSObject::GetElementsTransitionMap(jsobj, elements_kind);
   16583   jsobj->set_map(*fixed_array_map);
   16584   jsobj->set_elements(*fixed_array);
   16585 
   16586   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
   16587       context.local(), obj, kElementCount, array_type,
   16588       static_cast<int64_t>(low),
   16589       static_cast<int64_t>(high));
   16590 }
   16591 
   16592 
   16593 THREADED_TEST(FixedUint8Array) {
   16594   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
   16595     v8::kExternalUint8Array,
   16596     0x0, 0xFF);
   16597 }
   16598 
   16599 
   16600 THREADED_TEST(FixedUint8ClampedArray) {
   16601   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
   16602                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
   16603     v8::kExternalUint8ClampedArray,
   16604     0x0, 0xFF);
   16605 }
   16606 
   16607 
   16608 THREADED_TEST(FixedInt8Array) {
   16609   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
   16610     v8::kExternalInt8Array,
   16611     -0x80, 0x7F);
   16612 }
   16613 
   16614 
   16615 THREADED_TEST(FixedUint16Array) {
   16616   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
   16617     v8::kExternalUint16Array,
   16618     0x0, 0xFFFF);
   16619 }
   16620 
   16621 
   16622 THREADED_TEST(FixedInt16Array) {
   16623   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
   16624     v8::kExternalInt16Array,
   16625     -0x8000, 0x7FFF);
   16626 }
   16627 
   16628 
   16629 THREADED_TEST(FixedUint32Array) {
   16630   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
   16631     v8::kExternalUint32Array,
   16632     0x0, UINT_MAX);
   16633 }
   16634 
   16635 
   16636 THREADED_TEST(FixedInt32Array) {
   16637   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
   16638     v8::kExternalInt32Array,
   16639     INT_MIN, INT_MAX);
   16640 }
   16641 
   16642 
   16643 THREADED_TEST(FixedFloat32Array) {
   16644   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
   16645     v8::kExternalFloat32Array,
   16646     -500, 500);
   16647 }
   16648 
   16649 
   16650 THREADED_TEST(FixedFloat64Array) {
   16651   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
   16652     v8::kExternalFloat64Array,
   16653     -500, 500);
   16654 }
   16655 
   16656 
   16657 template <class ExternalArrayClass, class ElementType>
   16658 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
   16659                                     int64_t low,
   16660                                     int64_t high) {
   16661   LocalContext context;
   16662   i::Isolate* isolate = CcTest::i_isolate();
   16663   i::Factory* factory = isolate->factory();
   16664   v8::HandleScope scope(context->GetIsolate());
   16665   const int kElementCount = 40;
   16666   int element_size = ExternalArrayElementSize(array_type);
   16667   ElementType* array_data =
   16668       static_cast<ElementType*>(malloc(kElementCount * element_size));
   16669   i::Handle<ExternalArrayClass> array =
   16670       i::Handle<ExternalArrayClass>::cast(
   16671           factory->NewExternalArray(kElementCount, array_type, array_data));
   16672   // Force GC to trigger verification.
   16673   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   16674   for (int i = 0; i < kElementCount; i++) {
   16675     array->set(i, static_cast<ElementType>(i));
   16676   }
   16677   // Force GC to trigger verification.
   16678   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   16679   for (int i = 0; i < kElementCount; i++) {
   16680     CHECK_EQ(static_cast<int64_t>(i),
   16681              static_cast<int64_t>(array->get_scalar(i)));
   16682     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
   16683   }
   16684 
   16685   v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
   16686   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   16687   // Set the elements to be the external array.
   16688   obj->SetIndexedPropertiesToExternalArrayData(array_data,
   16689                                                array_type,
   16690                                                kElementCount);
   16691   CHECK_EQ(1,
   16692            static_cast<int>(
   16693                i::Object::GetElement(
   16694                    isolate, jsobj, 1).ToHandleChecked()->Number()));
   16695 
   16696   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   16697       context.local(), obj, kElementCount, array_type, low, high);
   16698 
   16699   v8::Handle<v8::Value> result;
   16700 
   16701   // Test more complex manipulations which cause eax to contain values
   16702   // that won't be completely overwritten by loads from the arrays.
   16703   // This catches bugs in the instructions used for the KeyedLoadIC
   16704   // for byte and word types.
   16705   {
   16706     const int kXSize = 300;
   16707     const int kYSize = 300;
   16708     const int kLargeElementCount = kXSize * kYSize * 4;
   16709     ElementType* large_array_data =
   16710         static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
   16711     v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
   16712     // Set the elements to be the external array.
   16713     large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
   16714                                                        array_type,
   16715                                                        kLargeElementCount);
   16716     context->Global()->Set(v8_str("large_array"), large_obj);
   16717     // Initialize contents of a few rows.
   16718     for (int x = 0; x < 300; x++) {
   16719       int row = 0;
   16720       int offset = row * 300 * 4;
   16721       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   16722       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   16723       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   16724       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   16725       row = 150;
   16726       offset = row * 300 * 4;
   16727       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   16728       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   16729       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   16730       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   16731       row = 298;
   16732       offset = row * 300 * 4;
   16733       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   16734       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   16735       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   16736       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   16737     }
   16738     // The goal of the code below is to make "offset" large enough
   16739     // that the computation of the index (which goes into eax) has
   16740     // high bits set which will not be overwritten by a byte or short
   16741     // load.
   16742     result = CompileRun("var failed = false;"
   16743                         "var offset = 0;"
   16744                         "for (var i = 0; i < 300; i++) {"
   16745                         "  if (large_array[4 * i] != 127 ||"
   16746                         "      large_array[4 * i + 1] != 0 ||"
   16747                         "      large_array[4 * i + 2] != 0 ||"
   16748                         "      large_array[4 * i + 3] != 127) {"
   16749                         "    failed = true;"
   16750                         "  }"
   16751                         "}"
   16752                         "offset = 150 * 300 * 4;"
   16753                         "for (var i = 0; i < 300; i++) {"
   16754                         "  if (large_array[offset + 4 * i] != 127 ||"
   16755                         "      large_array[offset + 4 * i + 1] != 0 ||"
   16756                         "      large_array[offset + 4 * i + 2] != 0 ||"
   16757                         "      large_array[offset + 4 * i + 3] != 127) {"
   16758                         "    failed = true;"
   16759                         "  }"
   16760                         "}"
   16761                         "offset = 298 * 300 * 4;"
   16762                         "for (var i = 0; i < 300; i++) {"
   16763                         "  if (large_array[offset + 4 * i] != 127 ||"
   16764                         "      large_array[offset + 4 * i + 1] != 0 ||"
   16765                         "      large_array[offset + 4 * i + 2] != 0 ||"
   16766                         "      large_array[offset + 4 * i + 3] != 127) {"
   16767                         "    failed = true;"
   16768                         "  }"
   16769                         "}"
   16770                         "!failed;");
   16771     CHECK_EQ(true, result->BooleanValue());
   16772     free(large_array_data);
   16773   }
   16774 
   16775   // The "" property descriptor is overloaded to store information about
   16776   // the external array. Ensure that setting and accessing the "" property
   16777   // works (it should overwrite the information cached about the external
   16778   // array in the DescriptorArray) in various situations.
   16779   result = CompileRun("ext_array[''] = 23; ext_array['']");
   16780   CHECK_EQ(23, result->Int32Value());
   16781 
   16782   // Property "" set after the external array is associated with the object.
   16783   {
   16784     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
   16785     obj2->Set(v8_str("ee_test_field"),
   16786               v8::Int32::New(context->GetIsolate(), 256));
   16787     obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
   16788     // Set the elements to be the external array.
   16789     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   16790                                                   array_type,
   16791                                                   kElementCount);
   16792     context->Global()->Set(v8_str("ext_array"), obj2);
   16793     result = CompileRun("ext_array['']");
   16794     CHECK_EQ(1503, result->Int32Value());
   16795   }
   16796 
   16797   // Property "" set after the external array is associated with the object.
   16798   {
   16799     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
   16800     obj2->Set(v8_str("ee_test_field_2"),
   16801               v8::Int32::New(context->GetIsolate(), 256));
   16802     // Set the elements to be the external array.
   16803     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   16804                                                   array_type,
   16805                                                   kElementCount);
   16806     obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
   16807     context->Global()->Set(v8_str("ext_array"), obj2);
   16808     result = CompileRun("ext_array['']");
   16809     CHECK_EQ(1503, result->Int32Value());
   16810   }
   16811 
   16812   // Should reuse the map from previous test.
   16813   {
   16814     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
   16815     obj2->Set(v8_str("ee_test_field_2"),
   16816               v8::Int32::New(context->GetIsolate(), 256));
   16817     // Set the elements to be the external array. Should re-use the map
   16818     // from previous test.
   16819     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   16820                                                   array_type,
   16821                                                   kElementCount);
   16822     context->Global()->Set(v8_str("ext_array"), obj2);
   16823     result = CompileRun("ext_array['']");
   16824   }
   16825 
   16826   // Property "" is a constant function that shouldn't not be interfered with
   16827   // when an external array is set.
   16828   {
   16829     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
   16830     // Start
   16831     obj2->Set(v8_str("ee_test_field3"),
   16832               v8::Int32::New(context->GetIsolate(), 256));
   16833 
   16834     // Add a constant function to an object.
   16835     context->Global()->Set(v8_str("ext_array"), obj2);
   16836     result = CompileRun("ext_array[''] = function() {return 1503;};"
   16837                         "ext_array['']();");
   16838 
   16839     // Add an external array transition to the same map that
   16840     // has the constant transition.
   16841     v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
   16842     obj3->Set(v8_str("ee_test_field3"),
   16843               v8::Int32::New(context->GetIsolate(), 256));
   16844     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   16845                                                   array_type,
   16846                                                   kElementCount);
   16847     context->Global()->Set(v8_str("ext_array"), obj3);
   16848   }
   16849 
   16850   // If a external array transition is in the map, it should get clobbered
   16851   // by a constant function.
   16852   {
   16853     // Add an external array transition.
   16854     v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
   16855     obj3->Set(v8_str("ee_test_field4"),
   16856               v8::Int32::New(context->GetIsolate(), 256));
   16857     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   16858                                                   array_type,
   16859                                                   kElementCount);
   16860 
   16861     // Add a constant function to the same map that just got an external array
   16862     // transition.
   16863     v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
   16864     obj2->Set(v8_str("ee_test_field4"),
   16865               v8::Int32::New(context->GetIsolate(), 256));
   16866     context->Global()->Set(v8_str("ext_array"), obj2);
   16867     result = CompileRun("ext_array[''] = function() {return 1503;};"
   16868                         "ext_array['']();");
   16869   }
   16870 
   16871   free(array_data);
   16872 }
   16873 
   16874 
   16875 THREADED_TEST(ExternalInt8Array) {
   16876   ExternalArrayTestHelper<i::ExternalInt8Array, int8_t>(
   16877       v8::kExternalInt8Array,
   16878       -128,
   16879       127);
   16880 }
   16881 
   16882 
   16883 THREADED_TEST(ExternalUint8Array) {
   16884   ExternalArrayTestHelper<i::ExternalUint8Array, uint8_t>(
   16885       v8::kExternalUint8Array,
   16886       0,
   16887       255);
   16888 }
   16889 
   16890 
   16891 THREADED_TEST(ExternalUint8ClampedArray) {
   16892   ExternalArrayTestHelper<i::ExternalUint8ClampedArray, uint8_t>(
   16893       v8::kExternalUint8ClampedArray,
   16894       0,
   16895       255);
   16896 }
   16897 
   16898 
   16899 THREADED_TEST(ExternalInt16Array) {
   16900   ExternalArrayTestHelper<i::ExternalInt16Array, int16_t>(
   16901       v8::kExternalInt16Array,
   16902       -32768,
   16903       32767);
   16904 }
   16905 
   16906 
   16907 THREADED_TEST(ExternalUint16Array) {
   16908   ExternalArrayTestHelper<i::ExternalUint16Array, uint16_t>(
   16909       v8::kExternalUint16Array,
   16910       0,
   16911       65535);
   16912 }
   16913 
   16914 
   16915 THREADED_TEST(ExternalInt32Array) {
   16916   ExternalArrayTestHelper<i::ExternalInt32Array, int32_t>(
   16917       v8::kExternalInt32Array,
   16918       INT_MIN,   // -2147483648
   16919       INT_MAX);  //  2147483647
   16920 }
   16921 
   16922 
   16923 THREADED_TEST(ExternalUint32Array) {
   16924   ExternalArrayTestHelper<i::ExternalUint32Array, uint32_t>(
   16925       v8::kExternalUint32Array,
   16926       0,
   16927       UINT_MAX);  // 4294967295
   16928 }
   16929 
   16930 
   16931 THREADED_TEST(ExternalFloat32Array) {
   16932   ExternalArrayTestHelper<i::ExternalFloat32Array, float>(
   16933       v8::kExternalFloat32Array,
   16934       -500,
   16935       500);
   16936 }
   16937 
   16938 
   16939 THREADED_TEST(ExternalFloat64Array) {
   16940   ExternalArrayTestHelper<i::ExternalFloat64Array, double>(
   16941       v8::kExternalFloat64Array,
   16942       -500,
   16943       500);
   16944 }
   16945 
   16946 
   16947 THREADED_TEST(ExternalArrays) {
   16948   TestExternalInt8Array();
   16949   TestExternalUint8Array();
   16950   TestExternalInt16Array();
   16951   TestExternalUint16Array();
   16952   TestExternalInt32Array();
   16953   TestExternalUint32Array();
   16954   TestExternalFloat32Array();
   16955 }
   16956 
   16957 
   16958 void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
   16959   LocalContext context;
   16960   v8::HandleScope scope(context->GetIsolate());
   16961   for (int size = 0; size < 100; size += 10) {
   16962     int element_size = ExternalArrayElementSize(array_type);
   16963     void* external_data = malloc(size * element_size);
   16964     v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
   16965     obj->SetIndexedPropertiesToExternalArrayData(
   16966         external_data, array_type, size);
   16967     CHECK(obj->HasIndexedPropertiesInExternalArrayData());
   16968     CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
   16969     CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
   16970     CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
   16971     free(external_data);
   16972   }
   16973 }
   16974 
   16975 
   16976 THREADED_TEST(ExternalArrayInfo) {
   16977   ExternalArrayInfoTestHelper(v8::kExternalInt8Array);
   16978   ExternalArrayInfoTestHelper(v8::kExternalUint8Array);
   16979   ExternalArrayInfoTestHelper(v8::kExternalInt16Array);
   16980   ExternalArrayInfoTestHelper(v8::kExternalUint16Array);
   16981   ExternalArrayInfoTestHelper(v8::kExternalInt32Array);
   16982   ExternalArrayInfoTestHelper(v8::kExternalUint32Array);
   16983   ExternalArrayInfoTestHelper(v8::kExternalFloat32Array);
   16984   ExternalArrayInfoTestHelper(v8::kExternalFloat64Array);
   16985   ExternalArrayInfoTestHelper(v8::kExternalUint8ClampedArray);
   16986 }
   16987 
   16988 
   16989 void ExtArrayLimitsHelper(v8::Isolate* isolate,
   16990                           v8::ExternalArrayType array_type,
   16991                           int size) {
   16992   v8::Handle<v8::Object> obj = v8::Object::New(isolate);
   16993   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   16994   last_location = last_message = NULL;
   16995   obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
   16996   CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
   16997   CHECK_NE(NULL, last_location);
   16998   CHECK_NE(NULL, last_message);
   16999 }
   17000 
   17001 
   17002 TEST(ExternalArrayLimits) {
   17003   LocalContext context;
   17004   v8::Isolate* isolate = context->GetIsolate();
   17005   v8::HandleScope scope(isolate);
   17006   ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0x40000000);
   17007   ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0xffffffff);
   17008   ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0x40000000);
   17009   ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0xffffffff);
   17010   ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0x40000000);
   17011   ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0xffffffff);
   17012   ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0x40000000);
   17013   ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0xffffffff);
   17014   ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0x40000000);
   17015   ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0xffffffff);
   17016   ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0x40000000);
   17017   ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0xffffffff);
   17018   ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0x40000000);
   17019   ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0xffffffff);
   17020   ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0x40000000);
   17021   ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0xffffffff);
   17022   ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0x40000000);
   17023   ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0xffffffff);
   17024 }
   17025 
   17026 
   17027 template <typename ElementType, typename TypedArray,
   17028           class ExternalArrayClass>
   17029 void TypedArrayTestHelper(v8::ExternalArrayType array_type,
   17030                           int64_t low, int64_t high) {
   17031   const int kElementCount = 50;
   17032 
   17033   i::ScopedVector<ElementType> backing_store(kElementCount+2);
   17034 
   17035   LocalContext env;
   17036   v8::Isolate* isolate = env->GetIsolate();
   17037   v8::HandleScope handle_scope(isolate);
   17038 
   17039   Local<v8::ArrayBuffer> ab =
   17040       v8::ArrayBuffer::New(isolate, backing_store.start(),
   17041                            (kElementCount + 2) * sizeof(ElementType));
   17042   Local<TypedArray> ta =
   17043       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
   17044   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   17045   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
   17046   CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
   17047   CHECK_EQ(kElementCount*sizeof(ElementType),
   17048            static_cast<int>(ta->ByteLength()));
   17049   CHECK_EQ(ab, ta->Buffer());
   17050 
   17051   ElementType* data = backing_store.start() + 2;
   17052   for (int i = 0; i < kElementCount; i++) {
   17053     data[i] = static_cast<ElementType>(i);
   17054   }
   17055 
   17056   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   17057       env.local(), ta, kElementCount, array_type, low, high);
   17058 }
   17059 
   17060 
   17061 THREADED_TEST(Uint8Array) {
   17062   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>(
   17063       v8::kExternalUint8Array, 0, 0xFF);
   17064 }
   17065 
   17066 
   17067 THREADED_TEST(Int8Array) {
   17068   TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>(
   17069       v8::kExternalInt8Array, -0x80, 0x7F);
   17070 }
   17071 
   17072 
   17073 THREADED_TEST(Uint16Array) {
   17074   TypedArrayTestHelper<uint16_t,
   17075                        v8::Uint16Array,
   17076                        i::ExternalUint16Array>(
   17077       v8::kExternalUint16Array, 0, 0xFFFF);
   17078 }
   17079 
   17080 
   17081 THREADED_TEST(Int16Array) {
   17082   TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>(
   17083       v8::kExternalInt16Array, -0x8000, 0x7FFF);
   17084 }
   17085 
   17086 
   17087 THREADED_TEST(Uint32Array) {
   17088   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>(
   17089       v8::kExternalUint32Array, 0, UINT_MAX);
   17090 }
   17091 
   17092 
   17093 THREADED_TEST(Int32Array) {
   17094   TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>(
   17095       v8::kExternalInt32Array, INT_MIN, INT_MAX);
   17096 }
   17097 
   17098 
   17099 THREADED_TEST(Float32Array) {
   17100   TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>(
   17101       v8::kExternalFloat32Array, -500, 500);
   17102 }
   17103 
   17104 
   17105 THREADED_TEST(Float64Array) {
   17106   TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>(
   17107       v8::kExternalFloat64Array, -500, 500);
   17108 }
   17109 
   17110 
   17111 THREADED_TEST(Uint8ClampedArray) {
   17112   TypedArrayTestHelper<uint8_t,
   17113                        v8::Uint8ClampedArray, i::ExternalUint8ClampedArray>(
   17114       v8::kExternalUint8ClampedArray, 0, 0xFF);
   17115 }
   17116 
   17117 
   17118 THREADED_TEST(DataView) {
   17119   const int kSize = 50;
   17120 
   17121   i::ScopedVector<uint8_t> backing_store(kSize+2);
   17122 
   17123   LocalContext env;
   17124   v8::Isolate* isolate = env->GetIsolate();
   17125   v8::HandleScope handle_scope(isolate);
   17126 
   17127   Local<v8::ArrayBuffer> ab =
   17128       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   17129   Local<v8::DataView> dv =
   17130       v8::DataView::New(ab, 2, kSize);
   17131   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   17132   CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
   17133   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   17134   CHECK_EQ(ab, dv->Buffer());
   17135 }
   17136 
   17137 
   17138 #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
   17139   THREADED_TEST(Is##View) {                                                   \
   17140     LocalContext env;                                                         \
   17141     v8::Isolate* isolate = env->GetIsolate();                                 \
   17142     v8::HandleScope handle_scope(isolate);                                    \
   17143                                                                               \
   17144     Handle<Value> result = CompileRun(                                        \
   17145         "var ab = new ArrayBuffer(128);"                                      \
   17146         "new " #View "(ab)");                                                 \
   17147     CHECK(result->IsArrayBufferView());                                       \
   17148     CHECK(result->Is##View());                                                \
   17149     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
   17150   }
   17151 
   17152 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
   17153 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
   17154 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
   17155 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
   17156 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
   17157 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
   17158 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
   17159 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
   17160 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
   17161 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
   17162 
   17163 #undef IS_ARRAY_BUFFER_VIEW_TEST
   17164 
   17165 
   17166 
   17167 THREADED_TEST(ScriptContextDependence) {
   17168   LocalContext c1;
   17169   v8::HandleScope scope(c1->GetIsolate());
   17170   const char *source = "foo";
   17171   v8::Handle<v8::Script> dep = v8_compile(source);
   17172   v8::ScriptCompiler::Source script_source(v8::String::NewFromUtf8(
   17173       c1->GetIsolate(), source));
   17174   v8::Handle<v8::UnboundScript> indep =
   17175       v8::ScriptCompiler::CompileUnbound(c1->GetIsolate(), &script_source);
   17176   c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
   17177                     v8::Integer::New(c1->GetIsolate(), 100));
   17178   CHECK_EQ(dep->Run()->Int32Value(), 100);
   17179   CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 100);
   17180   LocalContext c2;
   17181   c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
   17182                     v8::Integer::New(c2->GetIsolate(), 101));
   17183   CHECK_EQ(dep->Run()->Int32Value(), 100);
   17184   CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 101);
   17185 }
   17186 
   17187 
   17188 THREADED_TEST(StackTrace) {
   17189   LocalContext context;
   17190   v8::HandleScope scope(context->GetIsolate());
   17191   v8::TryCatch try_catch;
   17192   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   17193   v8::Handle<v8::String> src =
   17194       v8::String::NewFromUtf8(context->GetIsolate(), source);
   17195   v8::Handle<v8::String> origin =
   17196       v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
   17197   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
   17198   v8::ScriptCompiler::CompileUnbound(context->GetIsolate(), &script_source)
   17199       ->BindToCurrentContext()
   17200       ->Run();
   17201   CHECK(try_catch.HasCaught());
   17202   v8::String::Utf8Value stack(try_catch.StackTrace());
   17203   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
   17204 }
   17205 
   17206 
   17207 // Checks that a StackFrame has certain expected values.
   17208 void checkStackFrame(const char* expected_script_name,
   17209     const char* expected_func_name, int expected_line_number,
   17210     int expected_column, bool is_eval, bool is_constructor,
   17211     v8::Handle<v8::StackFrame> frame) {
   17212   v8::HandleScope scope(CcTest::isolate());
   17213   v8::String::Utf8Value func_name(frame->GetFunctionName());
   17214   v8::String::Utf8Value script_name(frame->GetScriptName());
   17215   if (*script_name == NULL) {
   17216     // The situation where there is no associated script, like for evals.
   17217     CHECK(expected_script_name == NULL);
   17218   } else {
   17219     CHECK(strstr(*script_name, expected_script_name) != NULL);
   17220   }
   17221   CHECK(strstr(*func_name, expected_func_name) != NULL);
   17222   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   17223   CHECK_EQ(expected_column, frame->GetColumn());
   17224   CHECK_EQ(is_eval, frame->IsEval());
   17225   CHECK_EQ(is_constructor, frame->IsConstructor());
   17226 }
   17227 
   17228 
   17229 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
   17230   v8::HandleScope scope(args.GetIsolate());
   17231   const char* origin = "capture-stack-trace-test";
   17232   const int kOverviewTest = 1;
   17233   const int kDetailedTest = 2;
   17234 
   17235   DCHECK(args.Length() == 1);
   17236 
   17237   int testGroup = args[0]->Int32Value();
   17238   if (testGroup == kOverviewTest) {
   17239     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17240         args.GetIsolate(), 10, v8::StackTrace::kOverview);
   17241     CHECK_EQ(4, stackTrace->GetFrameCount());
   17242     checkStackFrame(origin, "bar", 2, 10, false, false,
   17243                     stackTrace->GetFrame(0));
   17244     checkStackFrame(origin, "foo", 6, 3, false, false,
   17245                     stackTrace->GetFrame(1));
   17246     // This is the source string inside the eval which has the call to foo.
   17247     checkStackFrame(NULL, "", 1, 5, false, false,
   17248                     stackTrace->GetFrame(2));
   17249     // The last frame is an anonymous function which has the initial eval call.
   17250     checkStackFrame(origin, "", 8, 7, false, false,
   17251                     stackTrace->GetFrame(3));
   17252 
   17253     CHECK(stackTrace->AsArray()->IsArray());
   17254   } else if (testGroup == kDetailedTest) {
   17255     v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17256         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17257     CHECK_EQ(4, stackTrace->GetFrameCount());
   17258     checkStackFrame(origin, "bat", 4, 22, false, false,
   17259                     stackTrace->GetFrame(0));
   17260     checkStackFrame(origin, "baz", 8, 3, false, true,
   17261                     stackTrace->GetFrame(1));
   17262     bool is_eval = true;
   17263     // This is the source string inside the eval which has the call to baz.
   17264     checkStackFrame(NULL, "", 1, 5, is_eval, false,
   17265                     stackTrace->GetFrame(2));
   17266     // The last frame is an anonymous function which has the initial eval call.
   17267     checkStackFrame(origin, "", 10, 1, false, false,
   17268                     stackTrace->GetFrame(3));
   17269 
   17270     CHECK(stackTrace->AsArray()->IsArray());
   17271   }
   17272 }
   17273 
   17274 
   17275 // Tests the C++ StackTrace API.
   17276 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   17277 // THREADED_TEST(CaptureStackTrace) {
   17278 TEST(CaptureStackTrace) {
   17279   v8::Isolate* isolate = CcTest::isolate();
   17280   v8::HandleScope scope(isolate);
   17281   v8::Handle<v8::String> origin =
   17282       v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
   17283   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17284   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   17285              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
   17286   LocalContext context(0, templ);
   17287 
   17288   // Test getting OVERVIEW information. Should ignore information that is not
   17289   // script name, function name, line number, and column offset.
   17290   const char *overview_source =
   17291     "function bar() {\n"
   17292     "  var y; AnalyzeStackInNativeCode(1);\n"
   17293     "}\n"
   17294     "function foo() {\n"
   17295     "\n"
   17296     "  bar();\n"
   17297     "}\n"
   17298     "var x;eval('new foo();');";
   17299   v8::Handle<v8::String> overview_src =
   17300       v8::String::NewFromUtf8(isolate, overview_source);
   17301   v8::ScriptCompiler::Source script_source(overview_src,
   17302                                            v8::ScriptOrigin(origin));
   17303   v8::Handle<Value> overview_result(
   17304       v8::ScriptCompiler::CompileUnbound(isolate, &script_source)
   17305           ->BindToCurrentContext()
   17306           ->Run());
   17307   CHECK(!overview_result.IsEmpty());
   17308   CHECK(overview_result->IsObject());
   17309 
   17310   // Test getting DETAILED information.
   17311   const char *detailed_source =
   17312     "function bat() {AnalyzeStackInNativeCode(2);\n"
   17313     "}\n"
   17314     "\n"
   17315     "function baz() {\n"
   17316     "  bat();\n"
   17317     "}\n"
   17318     "eval('new baz();');";
   17319   v8::Handle<v8::String> detailed_src =
   17320       v8::String::NewFromUtf8(isolate, detailed_source);
   17321   // Make the script using a non-zero line and column offset.
   17322   v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
   17323   v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
   17324   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   17325   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
   17326   v8::Handle<v8::UnboundScript> detailed_script(
   17327       v8::ScriptCompiler::CompileUnbound(isolate, &script_source2));
   17328   v8::Handle<Value> detailed_result(
   17329       detailed_script->BindToCurrentContext()->Run());
   17330   CHECK(!detailed_result.IsEmpty());
   17331   CHECK(detailed_result->IsObject());
   17332 }
   17333 
   17334 
   17335 static void StackTraceForUncaughtExceptionListener(
   17336     v8::Handle<v8::Message> message,
   17337     v8::Handle<Value>) {
   17338   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   17339   CHECK_EQ(2, stack_trace->GetFrameCount());
   17340   checkStackFrame("origin", "foo", 2, 3, false, false,
   17341                   stack_trace->GetFrame(0));
   17342   checkStackFrame("origin", "bar", 5, 3, false, false,
   17343                   stack_trace->GetFrame(1));
   17344 }
   17345 
   17346 
   17347 TEST(CaptureStackTraceForUncaughtException) {
   17348   report_count = 0;
   17349   LocalContext env;
   17350   v8::HandleScope scope(env->GetIsolate());
   17351   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
   17352   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   17353 
   17354   CompileRunWithOrigin(
   17355       "function foo() {\n"
   17356       "  throw 1;\n"
   17357       "};\n"
   17358       "function bar() {\n"
   17359       "  foo();\n"
   17360       "};",
   17361       "origin");
   17362   v8::Local<v8::Object> global = env->Global();
   17363   Local<Value> trouble = global->Get(v8_str("bar"));
   17364   CHECK(trouble->IsFunction());
   17365   Function::Cast(*trouble)->Call(global, 0, NULL);
   17366   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   17367   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   17368 }
   17369 
   17370 
   17371 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   17372   LocalContext env;
   17373   v8::HandleScope scope(env->GetIsolate());
   17374   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
   17375                                                     1024,
   17376                                                     v8::StackTrace::kDetailed);
   17377 
   17378   CompileRun(
   17379       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   17380       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   17381       "    'isConstructor'];\n"
   17382       "for (var i = 0; i < setters.length; i++) {\n"
   17383       "  var prop = setters[i];\n"
   17384       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   17385       "}\n");
   17386   CompileRun("throw 'exception';");
   17387   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   17388 }
   17389 
   17390 
   17391 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
   17392                                      v8::Handle<v8::Value> data) {
   17393   // Use the frame where JavaScript is called from.
   17394   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   17395   CHECK(!stack_trace.IsEmpty());
   17396   int frame_count = stack_trace->GetFrameCount();
   17397   CHECK_EQ(3, frame_count);
   17398   int line_number[] = {1, 2, 5};
   17399   for (int i = 0; i < frame_count; i++) {
   17400     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   17401   }
   17402 }
   17403 
   17404 
   17405 // Test that we only return the stack trace at the site where the exception
   17406 // is first thrown (not where it is rethrown).
   17407 TEST(RethrowStackTrace) {
   17408   LocalContext env;
   17409   v8::HandleScope scope(env->GetIsolate());
   17410   // We make sure that
   17411   // - the stack trace of the ReferenceError in g() is reported.
   17412   // - the stack trace is not overwritten when e1 is rethrown by t().
   17413   // - the stack trace of e2 does not overwrite that of e1.
   17414   const char* source =
   17415       "function g() { error; }          \n"
   17416       "function f() { g(); }            \n"
   17417       "function t(e) { throw e; }       \n"
   17418       "try {                            \n"
   17419       "  f();                           \n"
   17420       "} catch (e1) {                   \n"
   17421       "  try {                          \n"
   17422       "    error;                       \n"
   17423       "  } catch (e2) {                 \n"
   17424       "    t(e1);                       \n"
   17425       "  }                              \n"
   17426       "}                                \n";
   17427   v8::V8::AddMessageListener(RethrowStackTraceHandler);
   17428   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   17429   CompileRun(source);
   17430   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   17431   v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
   17432 }
   17433 
   17434 
   17435 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
   17436                                               v8::Handle<v8::Value> data) {
   17437   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   17438   CHECK(!stack_trace.IsEmpty());
   17439   int frame_count = stack_trace->GetFrameCount();
   17440   CHECK_EQ(2, frame_count);
   17441   int line_number[] = {3, 7};
   17442   for (int i = 0; i < frame_count; i++) {
   17443     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   17444   }
   17445 }
   17446 
   17447 
   17448 // Test that we do not recognize identity for primitive exceptions.
   17449 TEST(RethrowPrimitiveStackTrace) {
   17450   LocalContext env;
   17451   v8::HandleScope scope(env->GetIsolate());
   17452   // We do not capture stack trace for non Error objects on creation time.
   17453   // Instead, we capture the stack trace on last throw.
   17454   const char* source =
   17455       "function g() { throw 404; }      \n"
   17456       "function f() { g(); }            \n"
   17457       "function t(e) { throw e; }       \n"
   17458       "try {                            \n"
   17459       "  f();                           \n"
   17460       "} catch (e1) {                   \n"
   17461       "  t(e1)                          \n"
   17462       "}                                \n";
   17463   v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
   17464   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   17465   CompileRun(source);
   17466   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   17467   v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   17468 }
   17469 
   17470 
   17471 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
   17472                                               v8::Handle<v8::Value> data) {
   17473   // Use the frame where JavaScript is called from.
   17474   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   17475   CHECK(!stack_trace.IsEmpty());
   17476   CHECK_EQ(1, stack_trace->GetFrameCount());
   17477   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
   17478 }
   17479 
   17480 
   17481 // Test that the stack trace is captured when the error object is created and
   17482 // not where it is thrown.
   17483 TEST(RethrowExistingStackTrace) {
   17484   LocalContext env;
   17485   v8::HandleScope scope(env->GetIsolate());
   17486   const char* source =
   17487       "var e = new Error();           \n"
   17488       "throw e;                       \n";
   17489   v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
   17490   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   17491   CompileRun(source);
   17492   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   17493   v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
   17494 }
   17495 
   17496 
   17497 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
   17498                                                v8::Handle<v8::Value> data) {
   17499   // Use the frame where JavaScript is called from.
   17500   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   17501   CHECK(!stack_trace.IsEmpty());
   17502   CHECK_EQ(1, stack_trace->GetFrameCount());
   17503   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
   17504 }
   17505 
   17506 
   17507 // Test that the stack trace is captured where the bogus Error object is thrown.
   17508 TEST(RethrowBogusErrorStackTrace) {
   17509   LocalContext env;
   17510   v8::HandleScope scope(env->GetIsolate());
   17511   const char* source =
   17512       "var e = {__proto__: new Error()} \n"
   17513       "throw e;                         \n";
   17514   v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
   17515   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   17516   CompileRun(source);
   17517   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   17518   v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   17519 }
   17520 
   17521 
   17522 void AnalyzeStackOfEvalWithSourceURL(
   17523     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17524   v8::HandleScope scope(args.GetIsolate());
   17525   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17526       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17527   CHECK_EQ(5, stackTrace->GetFrameCount());
   17528   v8::Handle<v8::String> url = v8_str("eval_url");
   17529   for (int i = 0; i < 3; i++) {
   17530     v8::Handle<v8::String> name =
   17531         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17532     CHECK(!name.IsEmpty());
   17533     CHECK_EQ(url, name);
   17534   }
   17535 }
   17536 
   17537 
   17538 TEST(SourceURLInStackTrace) {
   17539   v8::Isolate* isolate = CcTest::isolate();
   17540   v8::HandleScope scope(isolate);
   17541   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17542   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   17543              v8::FunctionTemplate::New(isolate,
   17544                                        AnalyzeStackOfEvalWithSourceURL));
   17545   LocalContext context(0, templ);
   17546 
   17547   const char *source =
   17548     "function outer() {\n"
   17549     "function bar() {\n"
   17550     "  AnalyzeStackOfEvalWithSourceURL();\n"
   17551     "}\n"
   17552     "function foo() {\n"
   17553     "\n"
   17554     "  bar();\n"
   17555     "}\n"
   17556     "foo();\n"
   17557     "}\n"
   17558     "eval('(' + outer +')()%s');";
   17559 
   17560   i::ScopedVector<char> code(1024);
   17561   i::SNPrintF(code, source, "//# sourceURL=eval_url");
   17562   CHECK(CompileRun(code.start())->IsUndefined());
   17563   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
   17564   CHECK(CompileRun(code.start())->IsUndefined());
   17565 }
   17566 
   17567 
   17568 static int scriptIdInStack[2];
   17569 
   17570 void AnalyzeScriptIdInStack(
   17571     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17572   v8::HandleScope scope(args.GetIsolate());
   17573   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17574       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
   17575   CHECK_EQ(2, stackTrace->GetFrameCount());
   17576   for (int i = 0; i < 2; i++) {
   17577     scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
   17578   }
   17579 }
   17580 
   17581 
   17582 TEST(ScriptIdInStackTrace) {
   17583   v8::Isolate* isolate = CcTest::isolate();
   17584   v8::HandleScope scope(isolate);
   17585   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17586   templ->Set(v8_str("AnalyzeScriptIdInStack"),
   17587              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
   17588   LocalContext context(0, templ);
   17589 
   17590   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
   17591     isolate,
   17592     "function foo() {\n"
   17593     "  AnalyzeScriptIdInStack();"
   17594     "}\n"
   17595     "foo();\n");
   17596   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
   17597   script->Run();
   17598   for (int i = 0; i < 2; i++) {
   17599     CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
   17600     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
   17601   }
   17602 }
   17603 
   17604 
   17605 void AnalyzeStackOfInlineScriptWithSourceURL(
   17606     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17607   v8::HandleScope scope(args.GetIsolate());
   17608   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17609       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17610   CHECK_EQ(4, stackTrace->GetFrameCount());
   17611   v8::Handle<v8::String> url = v8_str("url");
   17612   for (int i = 0; i < 3; i++) {
   17613     v8::Handle<v8::String> name =
   17614         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17615     CHECK(!name.IsEmpty());
   17616     CHECK_EQ(url, name);
   17617   }
   17618 }
   17619 
   17620 
   17621 TEST(InlineScriptWithSourceURLInStackTrace) {
   17622   v8::Isolate* isolate = CcTest::isolate();
   17623   v8::HandleScope scope(isolate);
   17624   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17625   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
   17626              v8::FunctionTemplate::New(
   17627                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
   17628   LocalContext context(0, templ);
   17629 
   17630   const char *source =
   17631     "function outer() {\n"
   17632     "function bar() {\n"
   17633     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
   17634     "}\n"
   17635     "function foo() {\n"
   17636     "\n"
   17637     "  bar();\n"
   17638     "}\n"
   17639     "foo();\n"
   17640     "}\n"
   17641     "outer()\n%s";
   17642 
   17643   i::ScopedVector<char> code(1024);
   17644   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17645   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17646   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   17647   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17648 }
   17649 
   17650 
   17651 void AnalyzeStackOfDynamicScriptWithSourceURL(
   17652     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17653   v8::HandleScope scope(args.GetIsolate());
   17654   v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17655       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17656   CHECK_EQ(4, stackTrace->GetFrameCount());
   17657   v8::Handle<v8::String> url = v8_str("source_url");
   17658   for (int i = 0; i < 3; i++) {
   17659     v8::Handle<v8::String> name =
   17660         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17661     CHECK(!name.IsEmpty());
   17662     CHECK_EQ(url, name);
   17663   }
   17664 }
   17665 
   17666 
   17667 TEST(DynamicWithSourceURLInStackTrace) {
   17668   v8::Isolate* isolate = CcTest::isolate();
   17669   v8::HandleScope scope(isolate);
   17670   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17671   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
   17672              v8::FunctionTemplate::New(
   17673                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
   17674   LocalContext context(0, templ);
   17675 
   17676   const char *source =
   17677     "function outer() {\n"
   17678     "function bar() {\n"
   17679     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
   17680     "}\n"
   17681     "function foo() {\n"
   17682     "\n"
   17683     "  bar();\n"
   17684     "}\n"
   17685     "foo();\n"
   17686     "}\n"
   17687     "outer()\n%s";
   17688 
   17689   i::ScopedVector<char> code(1024);
   17690   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17691   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   17692   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   17693   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   17694 }
   17695 
   17696 
   17697 TEST(DynamicWithSourceURLInStackTraceString) {
   17698   LocalContext context;
   17699   v8::HandleScope scope(context->GetIsolate());
   17700 
   17701   const char *source =
   17702     "function outer() {\n"
   17703     "  function foo() {\n"
   17704     "    FAIL.FAIL;\n"
   17705     "  }\n"
   17706     "  foo();\n"
   17707     "}\n"
   17708     "outer()\n%s";
   17709 
   17710   i::ScopedVector<char> code(1024);
   17711   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17712   v8::TryCatch try_catch;
   17713   CompileRunWithOrigin(code.start(), "", 0, 0);
   17714   CHECK(try_catch.HasCaught());
   17715   v8::String::Utf8Value stack(try_catch.StackTrace());
   17716   CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
   17717 }
   17718 
   17719 
   17720 TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   17721   LocalContext context;
   17722   v8::HandleScope scope(context->GetIsolate());
   17723 
   17724   const char *source =
   17725     "function outer() {\n"
   17726     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
   17727     "  //# sourceURL=source_url\";\n"
   17728     "  eval(scriptContents);\n"
   17729     "  foo(); }\n"
   17730     "outer();\n"
   17731     "//# sourceURL=outer_url";
   17732 
   17733   v8::TryCatch try_catch;
   17734   CompileRun(source);
   17735   CHECK(try_catch.HasCaught());
   17736 
   17737   Local<v8::Message> message = try_catch.Message();
   17738   Handle<Value> sourceURL =
   17739     message->GetScriptOrigin().ResourceName();
   17740   CHECK_EQ(*v8::String::Utf8Value(sourceURL), "source_url");
   17741 }
   17742 
   17743 
   17744 TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   17745   LocalContext context;
   17746   v8::HandleScope scope(context->GetIsolate());
   17747 
   17748   const char *source =
   17749     "function outer() {\n"
   17750     "  var scriptContents = \"function boo(){ boo(); }\\\n"
   17751     "  //# sourceURL=source_url\";\n"
   17752     "  eval(scriptContents);\n"
   17753     "  boo(); }\n"
   17754     "outer();\n"
   17755     "//# sourceURL=outer_url";
   17756 
   17757   v8::TryCatch try_catch;
   17758   CompileRun(source);
   17759   CHECK(try_catch.HasCaught());
   17760 
   17761   Local<v8::Message> message = try_catch.Message();
   17762   Handle<Value> sourceURL =
   17763     message->GetScriptOrigin().ResourceName();
   17764   CHECK_EQ(*v8::String::Utf8Value(sourceURL), "source_url");
   17765 }
   17766 
   17767 
   17768 static void CreateGarbageInOldSpace() {
   17769   i::Factory* factory = CcTest::i_isolate()->factory();
   17770   v8::HandleScope scope(CcTest::isolate());
   17771   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   17772   for (int i = 0; i < 1000; i++) {
   17773     factory->NewFixedArray(1000, i::TENURED);
   17774   }
   17775 }
   17776 
   17777 
   17778 // Test that idle notification can be handled and eventually returns true.
   17779 TEST(IdleNotification) {
   17780   const intptr_t MB = 1024 * 1024;
   17781   const int IdlePauseInMs = 1000;
   17782   LocalContext env;
   17783   v8::HandleScope scope(env->GetIsolate());
   17784   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17785   CreateGarbageInOldSpace();
   17786   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17787   CHECK_GT(size_with_garbage, initial_size + MB);
   17788   bool finished = false;
   17789   for (int i = 0; i < 200 && !finished; i++) {
   17790     finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
   17791   }
   17792   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17793   CHECK(finished);
   17794   CHECK_LT(final_size, initial_size + 1);
   17795 }
   17796 
   17797 
   17798 // Test that idle notification can be handled and eventually collects garbage.
   17799 TEST(IdleNotificationWithSmallHint) {
   17800   const intptr_t MB = 1024 * 1024;
   17801   const int IdlePauseInMs = 900;
   17802   LocalContext env;
   17803   v8::HandleScope scope(env->GetIsolate());
   17804   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17805   CreateGarbageInOldSpace();
   17806   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17807   CHECK_GT(size_with_garbage, initial_size + MB);
   17808   bool finished = false;
   17809   for (int i = 0; i < 200 && !finished; i++) {
   17810     finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
   17811   }
   17812   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17813   CHECK(finished);
   17814   CHECK_LT(final_size, initial_size + 1);
   17815 }
   17816 
   17817 
   17818 // Test that idle notification can be handled and eventually collects garbage.
   17819 TEST(IdleNotificationWithLargeHint) {
   17820   const intptr_t MB = 1024 * 1024;
   17821   const int IdlePauseInMs = 900;
   17822   LocalContext env;
   17823   v8::HandleScope scope(env->GetIsolate());
   17824   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17825   CreateGarbageInOldSpace();
   17826   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17827   CHECK_GT(size_with_garbage, initial_size + MB);
   17828   bool finished = false;
   17829   for (int i = 0; i < 200 && !finished; i++) {
   17830     finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
   17831   }
   17832   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17833   CHECK(finished);
   17834   CHECK_LT(final_size, initial_size + 1);
   17835 }
   17836 
   17837 
   17838 TEST(Regress2107) {
   17839   const intptr_t MB = 1024 * 1024;
   17840   const int kIdlePauseInMs = 1000;
   17841   LocalContext env;
   17842   v8::Isolate* isolate = env->GetIsolate();
   17843   v8::HandleScope scope(env->GetIsolate());
   17844   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17845   // Send idle notification to start a round of incremental GCs.
   17846   env->GetIsolate()->IdleNotification(kIdlePauseInMs);
   17847   // Emulate 7 page reloads.
   17848   for (int i = 0; i < 7; i++) {
   17849     {
   17850       v8::HandleScope inner_scope(env->GetIsolate());
   17851       v8::Local<v8::Context> ctx = v8::Context::New(isolate);
   17852       ctx->Enter();
   17853       CreateGarbageInOldSpace();
   17854       ctx->Exit();
   17855     }
   17856     env->GetIsolate()->ContextDisposedNotification();
   17857     env->GetIsolate()->IdleNotification(kIdlePauseInMs);
   17858   }
   17859   // Create garbage and check that idle notification still collects it.
   17860   CreateGarbageInOldSpace();
   17861   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17862   CHECK_GT(size_with_garbage, initial_size + MB);
   17863   bool finished = false;
   17864   for (int i = 0; i < 200 && !finished; i++) {
   17865     finished = env->GetIsolate()->IdleNotification(kIdlePauseInMs);
   17866   }
   17867   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17868   CHECK_LT(final_size, initial_size + 1);
   17869 }
   17870 
   17871 
   17872 TEST(Regress2333) {
   17873   LocalContext env;
   17874   for (int i = 0; i < 3; i++) {
   17875     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   17876   }
   17877 }
   17878 
   17879 static uint32_t* stack_limit;
   17880 
   17881 static void GetStackLimitCallback(
   17882     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17883   stack_limit = reinterpret_cast<uint32_t*>(
   17884       CcTest::i_isolate()->stack_guard()->real_climit());
   17885 }
   17886 
   17887 
   17888 // Uses the address of a local variable to determine the stack top now.
   17889 // Given a size, returns an address that is that far from the current
   17890 // top of stack.
   17891 static uint32_t* ComputeStackLimit(uint32_t size) {
   17892   uint32_t* answer = &size - (size / sizeof(size));
   17893   // If the size is very large and the stack is very near the bottom of
   17894   // memory then the calculation above may wrap around and give an address
   17895   // that is above the (downwards-growing) stack.  In that case we return
   17896   // a very low address.
   17897   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   17898   return answer;
   17899 }
   17900 
   17901 
   17902 // We need at least 165kB for an x64 debug build with clang and ASAN.
   17903 static const int stack_breathing_room = 256 * i::KB;
   17904 
   17905 
   17906 TEST(SetStackLimit) {
   17907   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
   17908 
   17909   // Set stack limit.
   17910   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   17911 
   17912   // Execute a script.
   17913   LocalContext env;
   17914   v8::HandleScope scope(env->GetIsolate());
   17915   Local<v8::FunctionTemplate> fun_templ =
   17916       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
   17917   Local<Function> fun = fun_templ->GetFunction();
   17918   env->Global()->Set(v8_str("get_stack_limit"), fun);
   17919   CompileRun("get_stack_limit();");
   17920 
   17921   CHECK(stack_limit == set_limit);
   17922 }
   17923 
   17924 
   17925 TEST(SetStackLimitInThread) {
   17926   uint32_t* set_limit;
   17927   {
   17928     v8::Locker locker(CcTest::isolate());
   17929     set_limit = ComputeStackLimit(stack_breathing_room);
   17930 
   17931     // Set stack limit.
   17932     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   17933 
   17934     // Execute a script.
   17935     v8::HandleScope scope(CcTest::isolate());
   17936     LocalContext env;
   17937     Local<v8::FunctionTemplate> fun_templ =
   17938         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
   17939     Local<Function> fun = fun_templ->GetFunction();
   17940     env->Global()->Set(v8_str("get_stack_limit"), fun);
   17941     CompileRun("get_stack_limit();");
   17942 
   17943     CHECK(stack_limit == set_limit);
   17944   }
   17945   {
   17946     v8::Locker locker(CcTest::isolate());
   17947     CHECK(stack_limit == set_limit);
   17948   }
   17949 }
   17950 
   17951 
   17952 THREADED_TEST(GetHeapStatistics) {
   17953   LocalContext c1;
   17954   v8::HandleScope scope(c1->GetIsolate());
   17955   v8::HeapStatistics heap_statistics;
   17956   CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
   17957   CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
   17958   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
   17959   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   17960   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   17961 }
   17962 
   17963 
   17964 class VisitorImpl : public v8::ExternalResourceVisitor {
   17965  public:
   17966   explicit VisitorImpl(TestResource** resource) {
   17967     for (int i = 0; i < 4; i++) {
   17968       resource_[i] = resource[i];
   17969       found_resource_[i] = false;
   17970     }
   17971   }
   17972   virtual ~VisitorImpl() {}
   17973   virtual void VisitExternalString(v8::Handle<v8::String> string) {
   17974     if (!string->IsExternal()) {
   17975       CHECK(string->IsExternalOneByte());
   17976       return;
   17977     }
   17978     v8::String::ExternalStringResource* resource =
   17979         string->GetExternalStringResource();
   17980     CHECK(resource);
   17981     for (int i = 0; i < 4; i++) {
   17982       if (resource_[i] == resource) {
   17983         CHECK(!found_resource_[i]);
   17984         found_resource_[i] = true;
   17985       }
   17986     }
   17987   }
   17988   void CheckVisitedResources() {
   17989     for (int i = 0; i < 4; i++) {
   17990       CHECK(found_resource_[i]);
   17991     }
   17992   }
   17993 
   17994  private:
   17995   v8::String::ExternalStringResource* resource_[4];
   17996   bool found_resource_[4];
   17997 };
   17998 
   17999 
   18000 TEST(ExternalizeOldSpaceTwoByteCons) {
   18001   LocalContext env;
   18002   v8::HandleScope scope(env->GetIsolate());
   18003   v8::Local<v8::String> cons =
   18004       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
   18005   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18006   CcTest::heap()->CollectAllAvailableGarbage();
   18007   CHECK(CcTest::heap()->old_pointer_space()->Contains(
   18008             *v8::Utils::OpenHandle(*cons)));
   18009 
   18010   TestResource* resource = new TestResource(
   18011       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
   18012   cons->MakeExternal(resource);
   18013 
   18014   CHECK(cons->IsExternal());
   18015   CHECK_EQ(resource, cons->GetExternalStringResource());
   18016   String::Encoding encoding;
   18017   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18018   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
   18019 }
   18020 
   18021 
   18022 TEST(ExternalizeOldSpaceOneByteCons) {
   18023   LocalContext env;
   18024   v8::HandleScope scope(env->GetIsolate());
   18025   v8::Local<v8::String> cons =
   18026       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
   18027   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18028   CcTest::heap()->CollectAllAvailableGarbage();
   18029   CHECK(CcTest::heap()->old_pointer_space()->Contains(
   18030             *v8::Utils::OpenHandle(*cons)));
   18031 
   18032   TestOneByteResource* resource =
   18033       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
   18034   cons->MakeExternal(resource);
   18035 
   18036   CHECK(cons->IsExternalOneByte());
   18037   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
   18038   String::Encoding encoding;
   18039   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18040   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
   18041 }
   18042 
   18043 
   18044 TEST(VisitExternalStrings) {
   18045   LocalContext env;
   18046   v8::HandleScope scope(env->GetIsolate());
   18047   const char* string = "Some string";
   18048   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   18049   TestResource* resource[4];
   18050   resource[0] = new TestResource(two_byte_string);
   18051   v8::Local<v8::String> string0 =
   18052       v8::String::NewExternal(env->GetIsolate(), resource[0]);
   18053   resource[1] = new TestResource(two_byte_string, NULL, false);
   18054   v8::Local<v8::String> string1 =
   18055       v8::String::NewExternal(env->GetIsolate(), resource[1]);
   18056 
   18057   // Externalized symbol.
   18058   resource[2] = new TestResource(two_byte_string, NULL, false);
   18059   v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
   18060       env->GetIsolate(), string, v8::String::kInternalizedString);
   18061   CHECK(string2->MakeExternal(resource[2]));
   18062 
   18063   // Symbolized External.
   18064   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
   18065   v8::Local<v8::String> string3 =
   18066       v8::String::NewExternal(env->GetIsolate(), resource[3]);
   18067   CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
   18068   // Turn into a symbol.
   18069   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
   18070   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
   18071       string3_i).is_null());
   18072   CHECK(string3_i->IsInternalizedString());
   18073 
   18074   // We need to add usages for string* to avoid warnings in GCC 4.7
   18075   CHECK(string0->IsExternal());
   18076   CHECK(string1->IsExternal());
   18077   CHECK(string2->IsExternal());
   18078   CHECK(string3->IsExternal());
   18079 
   18080   VisitorImpl visitor(resource);
   18081   v8::V8::VisitExternalResources(&visitor);
   18082   visitor.CheckVisitedResources();
   18083 }
   18084 
   18085 
   18086 TEST(ExternalStringCollectedAtTearDown) {
   18087   int destroyed = 0;
   18088   v8::Isolate* isolate = v8::Isolate::New();
   18089   { v8::Isolate::Scope isolate_scope(isolate);
   18090     v8::HandleScope handle_scope(isolate);
   18091     const char* s = "One string to test them all, one string to find them.";
   18092     TestOneByteResource* inscription =
   18093         new TestOneByteResource(i::StrDup(s), &destroyed);
   18094     v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
   18095     // Ring is still alive.  Orcs are roaming freely across our lands.
   18096     CHECK_EQ(0, destroyed);
   18097     USE(ring);
   18098   }
   18099 
   18100   isolate->Dispose();
   18101   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18102   CHECK_EQ(1, destroyed);
   18103 }
   18104 
   18105 
   18106 TEST(ExternalInternalizedStringCollectedAtTearDown) {
   18107   int destroyed = 0;
   18108   v8::Isolate* isolate = v8::Isolate::New();
   18109   { v8::Isolate::Scope isolate_scope(isolate);
   18110     LocalContext env(isolate);
   18111     v8::HandleScope handle_scope(isolate);
   18112     CompileRun("var ring = 'One string to test them all';");
   18113     const char* s = "One string to test them all";
   18114     TestOneByteResource* inscription =
   18115         new TestOneByteResource(i::StrDup(s), &destroyed);
   18116     v8::Local<v8::String> ring = CompileRun("ring")->ToString();
   18117     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18118     ring->MakeExternal(inscription);
   18119     // Ring is still alive.  Orcs are roaming freely across our lands.
   18120     CHECK_EQ(0, destroyed);
   18121     USE(ring);
   18122   }
   18123 
   18124   isolate->Dispose();
   18125   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18126   CHECK_EQ(1, destroyed);
   18127 }
   18128 
   18129 
   18130 TEST(ExternalInternalizedStringCollectedAtGC) {
   18131   int destroyed = 0;
   18132   { LocalContext env;
   18133     v8::HandleScope handle_scope(env->GetIsolate());
   18134     CompileRun("var ring = 'One string to test them all';");
   18135     const char* s = "One string to test them all";
   18136     TestOneByteResource* inscription =
   18137         new TestOneByteResource(i::StrDup(s), &destroyed);
   18138     v8::Local<v8::String> ring = CompileRun("ring")->ToString();
   18139     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18140     ring->MakeExternal(inscription);
   18141     // Ring is still alive.  Orcs are roaming freely across our lands.
   18142     CHECK_EQ(0, destroyed);
   18143     USE(ring);
   18144   }
   18145 
   18146   // Garbage collector deals swift blows to evil.
   18147   CcTest::i_isolate()->compilation_cache()->Clear();
   18148   CcTest::heap()->CollectAllAvailableGarbage();
   18149 
   18150   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18151   CHECK_EQ(1, destroyed);
   18152 }
   18153 
   18154 
   18155 static double DoubleFromBits(uint64_t value) {
   18156   double target;
   18157   i::MemCopy(&target, &value, sizeof(target));
   18158   return target;
   18159 }
   18160 
   18161 
   18162 static uint64_t DoubleToBits(double value) {
   18163   uint64_t target;
   18164   i::MemCopy(&target, &value, sizeof(target));
   18165   return target;
   18166 }
   18167 
   18168 
   18169 static double DoubleToDateTime(double input) {
   18170   double date_limit = 864e13;
   18171   if (std::isnan(input) || input < -date_limit || input > date_limit) {
   18172     return v8::base::OS::nan_value();
   18173   }
   18174   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
   18175 }
   18176 
   18177 
   18178 // We don't have a consistent way to write 64-bit constants syntactically, so we
   18179 // split them into two 32-bit constants and combine them programmatically.
   18180 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   18181   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   18182 }
   18183 
   18184 
   18185 THREADED_TEST(QuietSignalingNaNs) {
   18186   LocalContext context;
   18187   v8::Isolate* isolate = context->GetIsolate();
   18188   v8::HandleScope scope(isolate);
   18189   v8::TryCatch try_catch;
   18190 
   18191   // Special double values.
   18192   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
   18193   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
   18194   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
   18195   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
   18196   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   18197   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
   18198   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   18199 
   18200   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   18201   // on either side of the epoch.
   18202   double date_limit = 864e13;
   18203 
   18204   double test_values[] = {
   18205       snan,
   18206       qnan,
   18207       infinity,
   18208       max_normal,
   18209       date_limit + 1,
   18210       date_limit,
   18211       min_normal,
   18212       max_denormal,
   18213       min_denormal,
   18214       0,
   18215       -0,
   18216       -min_denormal,
   18217       -max_denormal,
   18218       -min_normal,
   18219       -date_limit,
   18220       -date_limit - 1,
   18221       -max_normal,
   18222       -infinity,
   18223       -qnan,
   18224       -snan
   18225   };
   18226   int num_test_values = 20;
   18227 
   18228   for (int i = 0; i < num_test_values; i++) {
   18229     double test_value = test_values[i];
   18230 
   18231     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   18232     v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
   18233     double stored_number = number->NumberValue();
   18234     if (!std::isnan(test_value)) {
   18235       CHECK_EQ(test_value, stored_number);
   18236     } else {
   18237       uint64_t stored_bits = DoubleToBits(stored_number);
   18238       // Check if quiet nan (bits 51..62 all set).
   18239 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   18240     !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
   18241       // Most significant fraction bit for quiet nan is set to 0
   18242       // on MIPS architecture. Allowed by IEEE-754.
   18243       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   18244 #else
   18245       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   18246 #endif
   18247     }
   18248 
   18249     // Check that Date::New preserves non-NaNs in the date range and
   18250     // quiets SNaNs.
   18251     v8::Handle<v8::Value> date =
   18252         v8::Date::New(isolate, test_value);
   18253     double expected_stored_date = DoubleToDateTime(test_value);
   18254     double stored_date = date->NumberValue();
   18255     if (!std::isnan(expected_stored_date)) {
   18256       CHECK_EQ(expected_stored_date, stored_date);
   18257     } else {
   18258       uint64_t stored_bits = DoubleToBits(stored_date);
   18259       // Check if quiet nan (bits 51..62 all set).
   18260 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   18261     !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
   18262       // Most significant fraction bit for quiet nan is set to 0
   18263       // on MIPS architecture. Allowed by IEEE-754.
   18264       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   18265 #else
   18266       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   18267 #endif
   18268     }
   18269   }
   18270 }
   18271 
   18272 
   18273 static void SpaghettiIncident(
   18274     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18275   v8::HandleScope scope(args.GetIsolate());
   18276   v8::TryCatch tc;
   18277   v8::Handle<v8::String> str(args[0]->ToString());
   18278   USE(str);
   18279   if (tc.HasCaught())
   18280     tc.ReThrow();
   18281 }
   18282 
   18283 
   18284 // Test that an exception can be propagated down through a spaghetti
   18285 // stack using ReThrow.
   18286 THREADED_TEST(SpaghettiStackReThrow) {
   18287   v8::Isolate* isolate = CcTest::isolate();
   18288   v8::HandleScope scope(isolate);
   18289   LocalContext context;
   18290   context->Global()->Set(
   18291       v8::String::NewFromUtf8(isolate, "s"),
   18292       v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
   18293   v8::TryCatch try_catch;
   18294   CompileRun(
   18295       "var i = 0;"
   18296       "var o = {"
   18297       "  toString: function () {"
   18298       "    if (i == 10) {"
   18299       "      throw 'Hey!';"
   18300       "    } else {"
   18301       "      i++;"
   18302       "      return s(o);"
   18303       "    }"
   18304       "  }"
   18305       "};"
   18306       "s(o);");
   18307   CHECK(try_catch.HasCaught());
   18308   v8::String::Utf8Value value(try_catch.Exception());
   18309   CHECK_EQ(0, strcmp(*value, "Hey!"));
   18310 }
   18311 
   18312 
   18313 TEST(Regress528) {
   18314   v8::V8::Initialize();
   18315   v8::Isolate* isolate = CcTest::isolate();
   18316   v8::HandleScope scope(isolate);
   18317   v8::Local<Context> other_context;
   18318   int gc_count;
   18319 
   18320   // Create a context used to keep the code from aging in the compilation
   18321   // cache.
   18322   other_context = Context::New(isolate);
   18323 
   18324   // Context-dependent context data creates reference from the compilation
   18325   // cache to the global object.
   18326   const char* source_simple = "1";
   18327   {
   18328     v8::HandleScope scope(isolate);
   18329     v8::Local<Context> context = Context::New(isolate);
   18330 
   18331     context->Enter();
   18332     Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
   18333     context->SetEmbedderData(0, obj);
   18334     CompileRun(source_simple);
   18335     context->Exit();
   18336   }
   18337   isolate->ContextDisposedNotification();
   18338   for (gc_count = 1; gc_count < 10; gc_count++) {
   18339     other_context->Enter();
   18340     CompileRun(source_simple);
   18341     other_context->Exit();
   18342     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18343     if (GetGlobalObjectsCount() == 1) break;
   18344   }
   18345   CHECK_GE(2, gc_count);
   18346   CHECK_EQ(1, GetGlobalObjectsCount());
   18347 
   18348   // Eval in a function creates reference from the compilation cache to the
   18349   // global object.
   18350   const char* source_eval = "function f(){eval('1')}; f()";
   18351   {
   18352     v8::HandleScope scope(isolate);
   18353     v8::Local<Context> context = Context::New(isolate);
   18354 
   18355     context->Enter();
   18356     CompileRun(source_eval);
   18357     context->Exit();
   18358   }
   18359   isolate->ContextDisposedNotification();
   18360   for (gc_count = 1; gc_count < 10; gc_count++) {
   18361     other_context->Enter();
   18362     CompileRun(source_eval);
   18363     other_context->Exit();
   18364     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18365     if (GetGlobalObjectsCount() == 1) break;
   18366   }
   18367   CHECK_GE(2, gc_count);
   18368   CHECK_EQ(1, GetGlobalObjectsCount());
   18369 
   18370   // Looking up the line number for an exception creates reference from the
   18371   // compilation cache to the global object.
   18372   const char* source_exception = "function f(){throw 1;} f()";
   18373   {
   18374     v8::HandleScope scope(isolate);
   18375     v8::Local<Context> context = Context::New(isolate);
   18376 
   18377     context->Enter();
   18378     v8::TryCatch try_catch;
   18379     CompileRun(source_exception);
   18380     CHECK(try_catch.HasCaught());
   18381     v8::Handle<v8::Message> message = try_catch.Message();
   18382     CHECK(!message.IsEmpty());
   18383     CHECK_EQ(1, message->GetLineNumber());
   18384     context->Exit();
   18385   }
   18386   isolate->ContextDisposedNotification();
   18387   for (gc_count = 1; gc_count < 10; gc_count++) {
   18388     other_context->Enter();
   18389     CompileRun(source_exception);
   18390     other_context->Exit();
   18391     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18392     if (GetGlobalObjectsCount() == 1) break;
   18393   }
   18394   CHECK_GE(2, gc_count);
   18395   CHECK_EQ(1, GetGlobalObjectsCount());
   18396 
   18397   isolate->ContextDisposedNotification();
   18398 }
   18399 
   18400 
   18401 THREADED_TEST(ScriptOrigin) {
   18402   LocalContext env;
   18403   v8::HandleScope scope(env->GetIsolate());
   18404   v8::ScriptOrigin origin =
   18405       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
   18406   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
   18407       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
   18408   v8::Script::Compile(script, &origin)->Run();
   18409   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18410       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
   18411   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18412       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
   18413 
   18414   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   18415   CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
   18416   CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
   18417 
   18418   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   18419   CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
   18420   CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
   18421 }
   18422 
   18423 
   18424 THREADED_TEST(FunctionGetInferredName) {
   18425   LocalContext env;
   18426   v8::HandleScope scope(env->GetIsolate());
   18427   v8::ScriptOrigin origin =
   18428       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
   18429   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
   18430       env->GetIsolate(),
   18431       "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   18432   v8::Script::Compile(script, &origin)->Run();
   18433   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18434       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
   18435   CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
   18436 }
   18437 
   18438 
   18439 THREADED_TEST(FunctionGetDisplayName) {
   18440   LocalContext env;
   18441   v8::HandleScope scope(env->GetIsolate());
   18442   const char* code = "var error = false;"
   18443                      "function a() { this.x = 1; };"
   18444                      "a.displayName = 'display_a';"
   18445                      "var b = (function() {"
   18446                      "  var f = function() { this.x = 2; };"
   18447                      "  f.displayName = 'display_b';"
   18448                      "  return f;"
   18449                      "})();"
   18450                      "var c = function() {};"
   18451                      "c.__defineGetter__('displayName', function() {"
   18452                      "  error = true;"
   18453                      "  throw new Error();"
   18454                      "});"
   18455                      "function d() {};"
   18456                      "d.__defineGetter__('displayName', function() {"
   18457                      "  error = true;"
   18458                      "  return 'wrong_display_name';"
   18459                      "});"
   18460                      "function e() {};"
   18461                      "e.displayName = 'wrong_display_name';"
   18462                      "e.__defineSetter__('displayName', function() {"
   18463                      "  error = true;"
   18464                      "  throw new Error();"
   18465                      "});"
   18466                      "function f() {};"
   18467                      "f.displayName = { 'foo': 6, toString: function() {"
   18468                      "  error = true;"
   18469                      "  return 'wrong_display_name';"
   18470                      "}};"
   18471                      "var g = function() {"
   18472                      "  arguments.callee.displayName = 'set_in_runtime';"
   18473                      "}; g();"
   18474                      ;
   18475   v8::ScriptOrigin origin =
   18476       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
   18477   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
   18478       ->Run();
   18479   v8::Local<v8::Value> error =
   18480       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
   18481   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
   18482       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
   18483   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
   18484       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
   18485   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
   18486       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
   18487   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
   18488       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
   18489   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
   18490       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
   18491   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18492       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
   18493   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18494       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
   18495   CHECK_EQ(false, error->BooleanValue());
   18496   CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
   18497   CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
   18498   CHECK(c->GetDisplayName()->IsUndefined());
   18499   CHECK(d->GetDisplayName()->IsUndefined());
   18500   CHECK(e->GetDisplayName()->IsUndefined());
   18501   CHECK(f->GetDisplayName()->IsUndefined());
   18502   CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
   18503 }
   18504 
   18505 
   18506 THREADED_TEST(ScriptLineNumber) {
   18507   LocalContext env;
   18508   v8::HandleScope scope(env->GetIsolate());
   18509   v8::ScriptOrigin origin =
   18510       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
   18511   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
   18512       env->GetIsolate(), "function f() {}\n\nfunction g() {}");
   18513   v8::Script::Compile(script, &origin)->Run();
   18514   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18515       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
   18516   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18517       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
   18518   CHECK_EQ(0, f->GetScriptLineNumber());
   18519   CHECK_EQ(2, g->GetScriptLineNumber());
   18520 }
   18521 
   18522 
   18523 THREADED_TEST(ScriptColumnNumber) {
   18524   LocalContext env;
   18525   v8::Isolate* isolate = env->GetIsolate();
   18526   v8::HandleScope scope(isolate);
   18527   v8::ScriptOrigin origin =
   18528       v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
   18529                        v8::Integer::New(isolate, 3),
   18530                        v8::Integer::New(isolate, 2));
   18531   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
   18532       isolate, "function foo() {}\n\n     function bar() {}");
   18533   v8::Script::Compile(script, &origin)->Run();
   18534   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   18535       env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
   18536   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   18537       env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
   18538   CHECK_EQ(14, foo->GetScriptColumnNumber());
   18539   CHECK_EQ(17, bar->GetScriptColumnNumber());
   18540 }
   18541 
   18542 
   18543 THREADED_TEST(FunctionIsBuiltin) {
   18544   LocalContext env;
   18545   v8::Isolate* isolate = env->GetIsolate();
   18546   v8::HandleScope scope(isolate);
   18547   v8::Local<v8::Function> f;
   18548   f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
   18549   CHECK(f->IsBuiltin());
   18550   f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
   18551   CHECK(f->IsBuiltin());
   18552   f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
   18553   CHECK(f->IsBuiltin());
   18554   f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
   18555   CHECK(f->IsBuiltin());
   18556   f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
   18557   CHECK(!f->IsBuiltin());
   18558 }
   18559 
   18560 
   18561 THREADED_TEST(FunctionGetScriptId) {
   18562   LocalContext env;
   18563   v8::Isolate* isolate = env->GetIsolate();
   18564   v8::HandleScope scope(isolate);
   18565   v8::ScriptOrigin origin =
   18566       v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
   18567                        v8::Integer::New(isolate, 3),
   18568                        v8::Integer::New(isolate, 2));
   18569   v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
   18570       isolate, "function foo() {}\n\n     function bar() {}");
   18571   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
   18572   script->Run();
   18573   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   18574       env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
   18575   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   18576       env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
   18577   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
   18578   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
   18579 }
   18580 
   18581 
   18582 THREADED_TEST(FunctionGetBoundFunction) {
   18583   LocalContext env;
   18584   v8::HandleScope scope(env->GetIsolate());
   18585   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
   18586       env->GetIsolate(), "test"));
   18587   v8::Handle<v8::String> script = v8::String::NewFromUtf8(
   18588       env->GetIsolate(),
   18589       "var a = new Object();\n"
   18590       "a.x = 1;\n"
   18591       "function f () { return this.x };\n"
   18592       "var g = f.bind(a);\n"
   18593       "var b = g();");
   18594   v8::Script::Compile(script, &origin)->Run();
   18595   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18596       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
   18597   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18598       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
   18599   CHECK(g->GetBoundFunction()->IsFunction());
   18600   Local<v8::Function> original_function = Local<v8::Function>::Cast(
   18601       g->GetBoundFunction());
   18602   CHECK_EQ(f->GetName(), original_function->GetName());
   18603   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
   18604   CHECK_EQ(f->GetScriptColumnNumber(),
   18605            original_function->GetScriptColumnNumber());
   18606 }
   18607 
   18608 
   18609 static void GetterWhichReturns42(
   18610     Local<String> name,
   18611     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18612   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18613   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18614   info.GetReturnValue().Set(v8_num(42));
   18615 }
   18616 
   18617 
   18618 static void SetterWhichSetsYOnThisTo23(
   18619     Local<String> name,
   18620     Local<Value> value,
   18621     const v8::PropertyCallbackInfo<void>& info) {
   18622   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18623   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18624   Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
   18625 }
   18626 
   18627 
   18628 void FooGetInterceptor(Local<String> name,
   18629                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   18630   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18631   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18632   if (!name->Equals(v8_str("foo"))) return;
   18633   info.GetReturnValue().Set(v8_num(42));
   18634 }
   18635 
   18636 
   18637 void FooSetInterceptor(Local<String> name,
   18638                        Local<Value> value,
   18639                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   18640   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18641   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18642   if (!name->Equals(v8_str("foo"))) return;
   18643   Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
   18644   info.GetReturnValue().Set(v8_num(23));
   18645 }
   18646 
   18647 
   18648 TEST(SetterOnConstructorPrototype) {
   18649   v8::Isolate* isolate = CcTest::isolate();
   18650   v8::HandleScope scope(isolate);
   18651   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18652   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   18653                      SetterWhichSetsYOnThisTo23);
   18654   LocalContext context;
   18655   context->Global()->Set(v8_str("P"), templ->NewInstance());
   18656   CompileRun("function C1() {"
   18657              "  this.x = 23;"
   18658              "};"
   18659              "C1.prototype = P;"
   18660              "function C2() {"
   18661              "  this.x = 23"
   18662              "};"
   18663              "C2.prototype = { };"
   18664              "C2.prototype.__proto__ = P;");
   18665 
   18666   v8::Local<v8::Script> script;
   18667   script = v8_compile("new C1();");
   18668   for (int i = 0; i < 10; i++) {
   18669     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   18670     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   18671     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   18672   }
   18673 
   18674 script = v8_compile("new C2();");
   18675   for (int i = 0; i < 10; i++) {
   18676     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   18677     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
   18678     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
   18679   }
   18680 }
   18681 
   18682 
   18683 static void NamedPropertyGetterWhichReturns42(
   18684     Local<String> name,
   18685     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18686   info.GetReturnValue().Set(v8_num(42));
   18687 }
   18688 
   18689 
   18690 static void NamedPropertySetterWhichSetsYOnThisTo23(
   18691     Local<String> name,
   18692     Local<Value> value,
   18693     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18694   if (name->Equals(v8_str("x"))) {
   18695     Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
   18696   }
   18697 }
   18698 
   18699 
   18700 THREADED_TEST(InterceptorOnConstructorPrototype) {
   18701   v8::Isolate* isolate = CcTest::isolate();
   18702   v8::HandleScope scope(isolate);
   18703   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18704   templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
   18705                                  NamedPropertySetterWhichSetsYOnThisTo23);
   18706   LocalContext context;
   18707   context->Global()->Set(v8_str("P"), templ->NewInstance());
   18708   CompileRun("function C1() {"
   18709              "  this.x = 23;"
   18710              "};"
   18711              "C1.prototype = P;"
   18712              "function C2() {"
   18713              "  this.x = 23"
   18714              "};"
   18715              "C2.prototype = { };"
   18716              "C2.prototype.__proto__ = P;");
   18717 
   18718   v8::Local<v8::Script> script;
   18719   script = v8_compile("new C1();");
   18720   for (int i = 0; i < 10; i++) {
   18721     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   18722     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   18723     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   18724   }
   18725 
   18726   script = v8_compile("new C2();");
   18727   for (int i = 0; i < 10; i++) {
   18728     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   18729     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
   18730     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
   18731   }
   18732 }
   18733 
   18734 
   18735 TEST(Regress618) {
   18736   const char* source = "function C1() {"
   18737                        "  this.x = 23;"
   18738                        "};"
   18739                        "C1.prototype = P;";
   18740 
   18741   LocalContext context;
   18742   v8::Isolate* isolate = context->GetIsolate();
   18743   v8::HandleScope scope(isolate);
   18744   v8::Local<v8::Script> script;
   18745 
   18746   // Use a simple object as prototype.
   18747   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
   18748   prototype->Set(v8_str("y"), v8_num(42));
   18749   context->Global()->Set(v8_str("P"), prototype);
   18750 
   18751   // This compile will add the code to the compilation cache.
   18752   CompileRun(source);
   18753 
   18754   script = v8_compile("new C1();");
   18755   // Allow enough iterations for the inobject slack tracking logic
   18756   // to finalize instance size and install the fast construct stub.
   18757   for (int i = 0; i < 256; i++) {
   18758     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   18759     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   18760     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   18761   }
   18762 
   18763   // Use an API object with accessors as prototype.
   18764   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18765   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   18766                      SetterWhichSetsYOnThisTo23);
   18767   context->Global()->Set(v8_str("P"), templ->NewInstance());
   18768 
   18769   // This compile will get the code from the compilation cache.
   18770   CompileRun(source);
   18771 
   18772   script = v8_compile("new C1();");
   18773   for (int i = 0; i < 10; i++) {
   18774     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   18775     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   18776     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   18777   }
   18778 }
   18779 
   18780 v8::Isolate* gc_callbacks_isolate = NULL;
   18781 int prologue_call_count = 0;
   18782 int epilogue_call_count = 0;
   18783 int prologue_call_count_second = 0;
   18784 int epilogue_call_count_second = 0;
   18785 int prologue_call_count_alloc = 0;
   18786 int epilogue_call_count_alloc = 0;
   18787 
   18788 void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
   18789   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18790   ++prologue_call_count;
   18791 }
   18792 
   18793 
   18794 void PrologueCallback(v8::Isolate* isolate,
   18795                       v8::GCType,
   18796                       v8::GCCallbackFlags flags) {
   18797   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18798   CHECK_EQ(gc_callbacks_isolate, isolate);
   18799   ++prologue_call_count;
   18800 }
   18801 
   18802 
   18803 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
   18804   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18805   ++epilogue_call_count;
   18806 }
   18807 
   18808 
   18809 void EpilogueCallback(v8::Isolate* isolate,
   18810                       v8::GCType,
   18811                       v8::GCCallbackFlags flags) {
   18812   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18813   CHECK_EQ(gc_callbacks_isolate, isolate);
   18814   ++epilogue_call_count;
   18815 }
   18816 
   18817 
   18818 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
   18819   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18820   ++prologue_call_count_second;
   18821 }
   18822 
   18823 
   18824 void PrologueCallbackSecond(v8::Isolate* isolate,
   18825                             v8::GCType,
   18826                             v8::GCCallbackFlags flags) {
   18827   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18828   CHECK_EQ(gc_callbacks_isolate, isolate);
   18829   ++prologue_call_count_second;
   18830 }
   18831 
   18832 
   18833 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
   18834   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18835   ++epilogue_call_count_second;
   18836 }
   18837 
   18838 
   18839 void EpilogueCallbackSecond(v8::Isolate* isolate,
   18840                             v8::GCType,
   18841                             v8::GCCallbackFlags flags) {
   18842   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18843   CHECK_EQ(gc_callbacks_isolate, isolate);
   18844   ++epilogue_call_count_second;
   18845 }
   18846 
   18847 
   18848 void PrologueCallbackAlloc(v8::Isolate* isolate,
   18849                            v8::GCType,
   18850                            v8::GCCallbackFlags flags) {
   18851   v8::HandleScope scope(isolate);
   18852 
   18853   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18854   CHECK_EQ(gc_callbacks_isolate, isolate);
   18855   ++prologue_call_count_alloc;
   18856 
   18857   // Simulate full heap to see if we will reenter this callback
   18858   SimulateFullSpace(CcTest::heap()->new_space());
   18859 
   18860   Local<Object> obj = Object::New(isolate);
   18861   CHECK(!obj.IsEmpty());
   18862 
   18863   CcTest::heap()->CollectAllGarbage(
   18864       i::Heap::kAbortIncrementalMarkingMask);
   18865 }
   18866 
   18867 
   18868 void EpilogueCallbackAlloc(v8::Isolate* isolate,
   18869                            v8::GCType,
   18870                            v8::GCCallbackFlags flags) {
   18871   v8::HandleScope scope(isolate);
   18872 
   18873   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18874   CHECK_EQ(gc_callbacks_isolate, isolate);
   18875   ++epilogue_call_count_alloc;
   18876 
   18877   // Simulate full heap to see if we will reenter this callback
   18878   SimulateFullSpace(CcTest::heap()->new_space());
   18879 
   18880   Local<Object> obj = Object::New(isolate);
   18881   CHECK(!obj.IsEmpty());
   18882 
   18883   CcTest::heap()->CollectAllGarbage(
   18884       i::Heap::kAbortIncrementalMarkingMask);
   18885 }
   18886 
   18887 
   18888 TEST(GCCallbacksOld) {
   18889   LocalContext context;
   18890 
   18891   v8::V8::AddGCPrologueCallback(PrologueCallback);
   18892   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
   18893   CHECK_EQ(0, prologue_call_count);
   18894   CHECK_EQ(0, epilogue_call_count);
   18895   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18896   CHECK_EQ(1, prologue_call_count);
   18897   CHECK_EQ(1, epilogue_call_count);
   18898   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
   18899   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
   18900   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18901   CHECK_EQ(2, prologue_call_count);
   18902   CHECK_EQ(2, epilogue_call_count);
   18903   CHECK_EQ(1, prologue_call_count_second);
   18904   CHECK_EQ(1, epilogue_call_count_second);
   18905   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
   18906   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
   18907   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18908   CHECK_EQ(2, prologue_call_count);
   18909   CHECK_EQ(2, epilogue_call_count);
   18910   CHECK_EQ(2, prologue_call_count_second);
   18911   CHECK_EQ(2, epilogue_call_count_second);
   18912   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
   18913   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   18914   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18915   CHECK_EQ(2, prologue_call_count);
   18916   CHECK_EQ(2, epilogue_call_count);
   18917   CHECK_EQ(2, prologue_call_count_second);
   18918   CHECK_EQ(2, epilogue_call_count_second);
   18919 }
   18920 
   18921 
   18922 TEST(GCCallbacks) {
   18923   LocalContext context;
   18924   v8::Isolate* isolate = context->GetIsolate();
   18925   gc_callbacks_isolate = isolate;
   18926   isolate->AddGCPrologueCallback(PrologueCallback);
   18927   isolate->AddGCEpilogueCallback(EpilogueCallback);
   18928   CHECK_EQ(0, prologue_call_count);
   18929   CHECK_EQ(0, epilogue_call_count);
   18930   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18931   CHECK_EQ(1, prologue_call_count);
   18932   CHECK_EQ(1, epilogue_call_count);
   18933   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
   18934   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
   18935   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18936   CHECK_EQ(2, prologue_call_count);
   18937   CHECK_EQ(2, epilogue_call_count);
   18938   CHECK_EQ(1, prologue_call_count_second);
   18939   CHECK_EQ(1, epilogue_call_count_second);
   18940   isolate->RemoveGCPrologueCallback(PrologueCallback);
   18941   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
   18942   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18943   CHECK_EQ(2, prologue_call_count);
   18944   CHECK_EQ(2, epilogue_call_count);
   18945   CHECK_EQ(2, prologue_call_count_second);
   18946   CHECK_EQ(2, epilogue_call_count_second);
   18947   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
   18948   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   18949   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   18950   CHECK_EQ(2, prologue_call_count);
   18951   CHECK_EQ(2, epilogue_call_count);
   18952   CHECK_EQ(2, prologue_call_count_second);
   18953   CHECK_EQ(2, epilogue_call_count_second);
   18954 
   18955   CHECK_EQ(0, prologue_call_count_alloc);
   18956   CHECK_EQ(0, epilogue_call_count_alloc);
   18957   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
   18958   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
   18959   CcTest::heap()->CollectAllGarbage(
   18960       i::Heap::kAbortIncrementalMarkingMask);
   18961   CHECK_EQ(1, prologue_call_count_alloc);
   18962   CHECK_EQ(1, epilogue_call_count_alloc);
   18963   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
   18964   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
   18965 }
   18966 
   18967 
   18968 THREADED_TEST(AddToJSFunctionResultCache) {
   18969   i::FLAG_stress_compaction = false;
   18970   i::FLAG_allow_natives_syntax = true;
   18971   v8::HandleScope scope(CcTest::isolate());
   18972 
   18973   LocalContext context;
   18974 
   18975   const char* code =
   18976       "(function() {"
   18977       "  var key0 = 'a';"
   18978       "  var key1 = 'b';"
   18979       "  var r0 = %_GetFromCache(0, key0);"
   18980       "  var r1 = %_GetFromCache(0, key1);"
   18981       "  var r0_ = %_GetFromCache(0, key0);"
   18982       "  if (r0 !== r0_)"
   18983       "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
   18984       "  var r1_ = %_GetFromCache(0, key1);"
   18985       "  if (r1 !== r1_)"
   18986       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
   18987       "  return 'PASSED';"
   18988       "})()";
   18989   CcTest::heap()->ClearJSFunctionResultCaches();
   18990   ExpectString(code, "PASSED");
   18991 }
   18992 
   18993 
   18994 THREADED_TEST(FillJSFunctionResultCache) {
   18995   i::FLAG_allow_natives_syntax = true;
   18996   LocalContext context;
   18997   v8::HandleScope scope(context->GetIsolate());
   18998 
   18999   const char* code =
   19000       "(function() {"
   19001       "  var k = 'a';"
   19002       "  var r = %_GetFromCache(0, k);"
   19003       "  for (var i = 0; i < 16; i++) {"
   19004       "    %_GetFromCache(0, 'a' + i);"
   19005       "  };"
   19006       "  if (r === %_GetFromCache(0, k))"
   19007       "    return 'FAILED: k0CacheSize is too small';"
   19008       "  return 'PASSED';"
   19009       "})()";
   19010   CcTest::heap()->ClearJSFunctionResultCaches();
   19011   ExpectString(code, "PASSED");
   19012 }
   19013 
   19014 
   19015 THREADED_TEST(RoundRobinGetFromCache) {
   19016   i::FLAG_allow_natives_syntax = true;
   19017   LocalContext context;
   19018   v8::HandleScope scope(context->GetIsolate());
   19019 
   19020   const char* code =
   19021       "(function() {"
   19022       "  var keys = [];"
   19023       "  for (var i = 0; i < 16; i++) keys.push(i);"
   19024       "  var values = [];"
   19025       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   19026       "  for (var i = 0; i < 16; i++) {"
   19027       "    var v = %_GetFromCache(0, keys[i]);"
   19028       "    if (v.toString() !== values[i].toString())"
   19029       "      return 'Wrong value for ' + "
   19030       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   19031       "  };"
   19032       "  return 'PASSED';"
   19033       "})()";
   19034   CcTest::heap()->ClearJSFunctionResultCaches();
   19035   ExpectString(code, "PASSED");
   19036 }
   19037 
   19038 
   19039 THREADED_TEST(ReverseGetFromCache) {
   19040   i::FLAG_allow_natives_syntax = true;
   19041   LocalContext context;
   19042   v8::HandleScope scope(context->GetIsolate());
   19043 
   19044   const char* code =
   19045       "(function() {"
   19046       "  var keys = [];"
   19047       "  for (var i = 0; i < 16; i++) keys.push(i);"
   19048       "  var values = [];"
   19049       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   19050       "  for (var i = 15; i >= 16; i--) {"
   19051       "    var v = %_GetFromCache(0, keys[i]);"
   19052       "    if (v !== values[i])"
   19053       "      return 'Wrong value for ' + "
   19054       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   19055       "  };"
   19056       "  return 'PASSED';"
   19057       "})()";
   19058   CcTest::heap()->ClearJSFunctionResultCaches();
   19059   ExpectString(code, "PASSED");
   19060 }
   19061 
   19062 
   19063 THREADED_TEST(TestEviction) {
   19064   i::FLAG_allow_natives_syntax = true;
   19065   LocalContext context;
   19066   v8::HandleScope scope(context->GetIsolate());
   19067 
   19068   const char* code =
   19069       "(function() {"
   19070       "  for (var i = 0; i < 2*16; i++) {"
   19071       "    %_GetFromCache(0, 'a' + i);"
   19072       "  };"
   19073       "  return 'PASSED';"
   19074       "})()";
   19075   CcTest::heap()->ClearJSFunctionResultCaches();
   19076   ExpectString(code, "PASSED");
   19077 }
   19078 
   19079 
   19080 THREADED_TEST(TwoByteStringInOneByteCons) {
   19081   // See Chromium issue 47824.
   19082   LocalContext context;
   19083   v8::HandleScope scope(context->GetIsolate());
   19084 
   19085   const char* init_code =
   19086       "var str1 = 'abelspendabel';"
   19087       "var str2 = str1 + str1 + str1;"
   19088       "str2;";
   19089   Local<Value> result = CompileRun(init_code);
   19090 
   19091   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   19092   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   19093 
   19094   CHECK(result->IsString());
   19095   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   19096   int length = string->length();
   19097   CHECK(string->IsOneByteRepresentation());
   19098 
   19099   i::Handle<i::String> flat_string = i::String::Flatten(string);
   19100 
   19101   CHECK(string->IsOneByteRepresentation());
   19102   CHECK(flat_string->IsOneByteRepresentation());
   19103 
   19104   // Create external resource.
   19105   uint16_t* uc16_buffer = new uint16_t[length + 1];
   19106 
   19107   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   19108   uc16_buffer[length] = 0;
   19109 
   19110   TestResource resource(uc16_buffer);
   19111 
   19112   flat_string->MakeExternal(&resource);
   19113 
   19114   CHECK(flat_string->IsTwoByteRepresentation());
   19115 
   19116   // If the cons string has been short-circuited, skip the following checks.
   19117   if (!string.is_identical_to(flat_string)) {
   19118     // At this point, we should have a Cons string which is flat and one-byte,
   19119     // with a first half that is a two-byte string (although it only contains
   19120     // one-byte characters). This is a valid sequence of steps, and it can
   19121     // happen in real pages.
   19122     CHECK(string->IsOneByteRepresentation());
   19123     i::ConsString* cons = i::ConsString::cast(*string);
   19124     CHECK_EQ(0, cons->second()->length());
   19125     CHECK(cons->first()->IsTwoByteRepresentation());
   19126   }
   19127 
   19128   // Check that some string operations work.
   19129 
   19130   // Atom RegExp.
   19131   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   19132   CHECK_EQ(6, reresult->Int32Value());
   19133 
   19134   // Nonatom RegExp.
   19135   reresult = CompileRun("str2.match(/abe./g).length;");
   19136   CHECK_EQ(6, reresult->Int32Value());
   19137 
   19138   reresult = CompileRun("str2.search(/bel/g);");
   19139   CHECK_EQ(1, reresult->Int32Value());
   19140 
   19141   reresult = CompileRun("str2.search(/be./g);");
   19142   CHECK_EQ(1, reresult->Int32Value());
   19143 
   19144   ExpectTrue("/bel/g.test(str2);");
   19145 
   19146   ExpectTrue("/be./g.test(str2);");
   19147 
   19148   reresult = CompileRun("/bel/g.exec(str2);");
   19149   CHECK(!reresult->IsNull());
   19150 
   19151   reresult = CompileRun("/be./g.exec(str2);");
   19152   CHECK(!reresult->IsNull());
   19153 
   19154   ExpectString("str2.substring(2, 10);", "elspenda");
   19155 
   19156   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   19157 
   19158   ExpectString("str2.charAt(2);", "e");
   19159 
   19160   ExpectObject("str2.indexOf('els');", indexof);
   19161 
   19162   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   19163 
   19164   reresult = CompileRun("str2.charCodeAt(2);");
   19165   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
   19166 }
   19167 
   19168 
   19169 TEST(ContainsOnlyOneByte) {
   19170   v8::V8::Initialize();
   19171   v8::Isolate* isolate = CcTest::isolate();
   19172   v8::HandleScope scope(isolate);
   19173   // Make a buffer long enough that it won't automatically be converted.
   19174   const int length = 512;
   19175   // Ensure word aligned assignment.
   19176   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
   19177   i::SmartArrayPointer<uintptr_t>
   19178   aligned_contents(new uintptr_t[aligned_length]);
   19179   uint16_t* string_contents =
   19180       reinterpret_cast<uint16_t*>(aligned_contents.get());
   19181   // Set to contain only one byte.
   19182   for (int i = 0; i < length-1; i++) {
   19183     string_contents[i] = 0x41;
   19184   }
   19185   string_contents[length-1] = 0;
   19186   // Simple case.
   19187   Handle<String> string =
   19188       String::NewExternal(isolate,
   19189                           new TestResource(string_contents, NULL, false));
   19190   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19191   // Counter example.
   19192   string = String::NewFromTwoByte(isolate, string_contents);
   19193   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   19194   // Test left right and balanced cons strings.
   19195   Handle<String> base = String::NewFromUtf8(isolate, "a");
   19196   Handle<String> left = base;
   19197   Handle<String> right = base;
   19198   for (int i = 0; i < 1000; i++) {
   19199     left = String::Concat(base, left);
   19200     right = String::Concat(right, base);
   19201   }
   19202   Handle<String> balanced = String::Concat(left, base);
   19203   balanced = String::Concat(balanced, right);
   19204   Handle<String> cons_strings[] = {left, balanced, right};
   19205   Handle<String> two_byte =
   19206       String::NewExternal(isolate,
   19207                           new TestResource(string_contents, NULL, false));
   19208   USE(two_byte); USE(cons_strings);
   19209   for (size_t i = 0; i < arraysize(cons_strings); i++) {
   19210     // Base assumptions.
   19211     string = cons_strings[i];
   19212     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   19213     // Test left and right concatentation.
   19214     string = String::Concat(two_byte, cons_strings[i]);
   19215     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19216     string = String::Concat(cons_strings[i], two_byte);
   19217     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19218   }
   19219   // Set bits in different positions
   19220   // for strings of different lengths and alignments.
   19221   for (int alignment = 0; alignment < 7; alignment++) {
   19222     for (int size = 2; alignment + size < length; size *= 2) {
   19223       int zero_offset = size + alignment;
   19224       string_contents[zero_offset] = 0;
   19225       for (int i = 0; i < size; i++) {
   19226         int shift = 8 + (i % 7);
   19227         string_contents[alignment + i] = 1 << shift;
   19228         string = String::NewExternal(
   19229             isolate,
   19230             new TestResource(string_contents + alignment, NULL, false));
   19231         CHECK_EQ(size, string->Length());
   19232         CHECK(!string->ContainsOnlyOneByte());
   19233         string_contents[alignment + i] = 0x41;
   19234       }
   19235       string_contents[zero_offset] = 0x41;
   19236     }
   19237   }
   19238 }
   19239 
   19240 
   19241 // Failed access check callback that performs a GC on each invocation.
   19242 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   19243                                  v8::AccessType type,
   19244                                  Local<v8::Value> data) {
   19245   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   19246 }
   19247 
   19248 
   19249 TEST(GCInFailedAccessCheckCallback) {
   19250   // Install a failed access check callback that performs a GC on each
   19251   // invocation. Then force the callback to be called from va
   19252 
   19253   v8::V8::Initialize();
   19254   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   19255 
   19256   v8::Isolate* isolate = CcTest::isolate();
   19257   v8::HandleScope scope(isolate);
   19258 
   19259   // Create an ObjectTemplate for global objects and install access
   19260   // check callbacks that will block access.
   19261   v8::Handle<v8::ObjectTemplate> global_template =
   19262       v8::ObjectTemplate::New(isolate);
   19263   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   19264                                            IndexedGetAccessBlocker,
   19265                                            v8::Handle<v8::Value>(),
   19266                                            false);
   19267 
   19268   // Create a context and set an x property on it's global object.
   19269   LocalContext context0(NULL, global_template);
   19270   context0->Global()->Set(v8_str("x"), v8_num(42));
   19271   v8::Handle<v8::Object> global0 = context0->Global();
   19272 
   19273   // Create a context with a different security token so that the
   19274   // failed access check callback will be called on each access.
   19275   LocalContext context1(NULL, global_template);
   19276   context1->Global()->Set(v8_str("other"), global0);
   19277 
   19278   // Get property with failed access check.
   19279   ExpectUndefined("other.x");
   19280 
   19281   // Get element with failed access check.
   19282   ExpectUndefined("other[0]");
   19283 
   19284   // Set property with failed access check.
   19285   v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
   19286   CHECK(result->IsObject());
   19287 
   19288   // Set element with failed access check.
   19289   result = CompileRun("other[0] = new Object()");
   19290   CHECK(result->IsObject());
   19291 
   19292   // Get property attribute with failed access check.
   19293   ExpectFalse("\'x\' in other");
   19294 
   19295   // Get property attribute for element with failed access check.
   19296   ExpectFalse("0 in other");
   19297 
   19298   // Delete property.
   19299   ExpectFalse("delete other.x");
   19300 
   19301   // Delete element.
   19302   CHECK_EQ(false, global0->Delete(0));
   19303 
   19304   // DefineAccessor.
   19305   CHECK_EQ(false,
   19306            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
   19307 
   19308   // Define JavaScript accessor.
   19309   ExpectUndefined("Object.prototype.__defineGetter__.call("
   19310                   "    other, \'x\', function() { return 42; })");
   19311 
   19312   // LookupAccessor.
   19313   ExpectUndefined("Object.prototype.__lookupGetter__.call("
   19314                   "    other, \'x\')");
   19315 
   19316   // HasOwnElement.
   19317   ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
   19318 
   19319   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
   19320   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
   19321   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
   19322 
   19323   // Reset the failed access check callback so it does not influence
   19324   // the other tests.
   19325   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
   19326 }
   19327 
   19328 
   19329 TEST(IsolateNewDispose) {
   19330   v8::Isolate* current_isolate = CcTest::isolate();
   19331   v8::Isolate* isolate = v8::Isolate::New();
   19332   CHECK(isolate != NULL);
   19333   CHECK(current_isolate != isolate);
   19334   CHECK(current_isolate == CcTest::isolate());
   19335 
   19336   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   19337   last_location = last_message = NULL;
   19338   isolate->Dispose();
   19339   CHECK_EQ(last_location, NULL);
   19340   CHECK_EQ(last_message, NULL);
   19341 }
   19342 
   19343 
   19344 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
   19345   v8::Isolate* isolate = v8::Isolate::New();
   19346   {
   19347     v8::Isolate::Scope i_scope(isolate);
   19348     v8::HandleScope scope(isolate);
   19349     LocalContext context(isolate);
   19350     // Run something in this isolate.
   19351     ExpectTrue("true");
   19352     v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   19353     last_location = last_message = NULL;
   19354     // Still entered, should fail.
   19355     isolate->Dispose();
   19356     CHECK_NE(last_location, NULL);
   19357     CHECK_NE(last_message, NULL);
   19358   }
   19359   isolate->Dispose();
   19360 }
   19361 
   19362 
   19363 TEST(RunTwoIsolatesOnSingleThread) {
   19364   // Run isolate 1.
   19365   v8::Isolate* isolate1 = v8::Isolate::New();
   19366   isolate1->Enter();
   19367   v8::Persistent<v8::Context> context1;
   19368   {
   19369     v8::HandleScope scope(isolate1);
   19370     context1.Reset(isolate1, Context::New(isolate1));
   19371   }
   19372 
   19373   {
   19374     v8::HandleScope scope(isolate1);
   19375     v8::Local<v8::Context> context =
   19376         v8::Local<v8::Context>::New(isolate1, context1);
   19377     v8::Context::Scope context_scope(context);
   19378     // Run something in new isolate.
   19379     CompileRun("var foo = 'isolate 1';");
   19380     ExpectString("function f() { return foo; }; f()", "isolate 1");
   19381   }
   19382 
   19383   // Run isolate 2.
   19384   v8::Isolate* isolate2 = v8::Isolate::New();
   19385   v8::Persistent<v8::Context> context2;
   19386 
   19387   {
   19388     v8::Isolate::Scope iscope(isolate2);
   19389     v8::HandleScope scope(isolate2);
   19390     context2.Reset(isolate2, Context::New(isolate2));
   19391     v8::Local<v8::Context> context =
   19392         v8::Local<v8::Context>::New(isolate2, context2);
   19393     v8::Context::Scope context_scope(context);
   19394 
   19395     // Run something in new isolate.
   19396     CompileRun("var foo = 'isolate 2';");
   19397     ExpectString("function f() { return foo; }; f()", "isolate 2");
   19398   }
   19399 
   19400   {
   19401     v8::HandleScope scope(isolate1);
   19402     v8::Local<v8::Context> context =
   19403         v8::Local<v8::Context>::New(isolate1, context1);
   19404     v8::Context::Scope context_scope(context);
   19405     // Now again in isolate 1
   19406     ExpectString("function f() { return foo; }; f()", "isolate 1");
   19407   }
   19408 
   19409   isolate1->Exit();
   19410 
   19411   // Run some stuff in default isolate.
   19412   v8::Persistent<v8::Context> context_default;
   19413   {
   19414     v8::Isolate* isolate = CcTest::isolate();
   19415     v8::Isolate::Scope iscope(isolate);
   19416     v8::HandleScope scope(isolate);
   19417     context_default.Reset(isolate, Context::New(isolate));
   19418   }
   19419 
   19420   {
   19421     v8::HandleScope scope(CcTest::isolate());
   19422     v8::Local<v8::Context> context =
   19423         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   19424     v8::Context::Scope context_scope(context);
   19425     // Variables in other isolates should be not available, verify there
   19426     // is an exception.
   19427     ExpectTrue("function f() {"
   19428                "  try {"
   19429                "    foo;"
   19430                "    return false;"
   19431                "  } catch(e) {"
   19432                "    return true;"
   19433                "  }"
   19434                "};"
   19435                "var isDefaultIsolate = true;"
   19436                "f()");
   19437   }
   19438 
   19439   isolate1->Enter();
   19440 
   19441   {
   19442     v8::Isolate::Scope iscope(isolate2);
   19443     v8::HandleScope scope(isolate2);
   19444     v8::Local<v8::Context> context =
   19445         v8::Local<v8::Context>::New(isolate2, context2);
   19446     v8::Context::Scope context_scope(context);
   19447     ExpectString("function f() { return foo; }; f()", "isolate 2");
   19448   }
   19449 
   19450   {
   19451     v8::HandleScope scope(v8::Isolate::GetCurrent());
   19452     v8::Local<v8::Context> context =
   19453         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
   19454     v8::Context::Scope context_scope(context);
   19455     ExpectString("function f() { return foo; }; f()", "isolate 1");
   19456   }
   19457 
   19458   {
   19459     v8::Isolate::Scope iscope(isolate2);
   19460     context2.Reset();
   19461   }
   19462 
   19463   context1.Reset();
   19464   isolate1->Exit();
   19465 
   19466   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   19467   last_location = last_message = NULL;
   19468 
   19469   isolate1->Dispose();
   19470   CHECK_EQ(last_location, NULL);
   19471   CHECK_EQ(last_message, NULL);
   19472 
   19473   isolate2->Dispose();
   19474   CHECK_EQ(last_location, NULL);
   19475   CHECK_EQ(last_message, NULL);
   19476 
   19477   // Check that default isolate still runs.
   19478   {
   19479     v8::HandleScope scope(CcTest::isolate());
   19480     v8::Local<v8::Context> context =
   19481         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   19482     v8::Context::Scope context_scope(context);
   19483     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   19484   }
   19485 }
   19486 
   19487 
   19488 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   19489   v8::Isolate::Scope isolate_scope(isolate);
   19490   v8::HandleScope scope(isolate);
   19491   LocalContext context(isolate);
   19492   i::ScopedVector<char> code(1024);
   19493   i::SNPrintF(code, "function fib(n) {"
   19494                     "  if (n <= 2) return 1;"
   19495                     "  return fib(n-1) + fib(n-2);"
   19496                     "}"
   19497                     "fib(%d)", limit);
   19498   Local<Value> value = CompileRun(code.start());
   19499   CHECK(value->IsNumber());
   19500   return static_cast<int>(value->NumberValue());
   19501 }
   19502 
   19503 class IsolateThread : public v8::base::Thread {
   19504  public:
   19505   explicit IsolateThread(int fib_limit)
   19506       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
   19507 
   19508   void Run() {
   19509     v8::Isolate* isolate = v8::Isolate::New();
   19510     result_ = CalcFibonacci(isolate, fib_limit_);
   19511     isolate->Dispose();
   19512   }
   19513 
   19514   int result() { return result_; }
   19515 
   19516  private:
   19517   int fib_limit_;
   19518   int result_;
   19519 };
   19520 
   19521 
   19522 TEST(MultipleIsolatesOnIndividualThreads) {
   19523   IsolateThread thread1(21);
   19524   IsolateThread thread2(12);
   19525 
   19526   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   19527   thread1.Start();
   19528   thread2.Start();
   19529 
   19530   int result1 = CalcFibonacci(CcTest::isolate(), 21);
   19531   int result2 = CalcFibonacci(CcTest::isolate(), 12);
   19532 
   19533   thread1.Join();
   19534   thread2.Join();
   19535 
   19536   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   19537   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   19538   CHECK_EQ(result1, 10946);
   19539   CHECK_EQ(result2, 144);
   19540   CHECK_EQ(result1, thread1.result());
   19541   CHECK_EQ(result2, thread2.result());
   19542 }
   19543 
   19544 
   19545 TEST(IsolateDifferentContexts) {
   19546   v8::Isolate* isolate = v8::Isolate::New();
   19547   Local<v8::Context> context;
   19548   {
   19549     v8::Isolate::Scope isolate_scope(isolate);
   19550     v8::HandleScope handle_scope(isolate);
   19551     context = v8::Context::New(isolate);
   19552     v8::Context::Scope context_scope(context);
   19553     Local<Value> v = CompileRun("2");
   19554     CHECK(v->IsNumber());
   19555     CHECK_EQ(2, static_cast<int>(v->NumberValue()));
   19556   }
   19557   {
   19558     v8::Isolate::Scope isolate_scope(isolate);
   19559     v8::HandleScope handle_scope(isolate);
   19560     context = v8::Context::New(isolate);
   19561     v8::Context::Scope context_scope(context);
   19562     Local<Value> v = CompileRun("22");
   19563     CHECK(v->IsNumber());
   19564     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
   19565   }
   19566   isolate->Dispose();
   19567 }
   19568 
   19569 class InitDefaultIsolateThread : public v8::base::Thread {
   19570  public:
   19571   enum TestCase {
   19572     SetResourceConstraints,
   19573     SetFatalHandler,
   19574     SetCounterFunction,
   19575     SetCreateHistogramFunction,
   19576     SetAddHistogramSampleFunction
   19577   };
   19578 
   19579   explicit InitDefaultIsolateThread(TestCase testCase)
   19580       : Thread(Options("InitDefaultIsolateThread")),
   19581         testCase_(testCase),
   19582         result_(false) {}
   19583 
   19584   void Run() {
   19585     v8::Isolate::CreateParams create_params;
   19586     switch (testCase_) {
   19587       case SetResourceConstraints: {
   19588         create_params.constraints.set_max_semi_space_size(1);
   19589         create_params.constraints.set_max_old_space_size(4);
   19590         break;
   19591       }
   19592       default:
   19593         break;
   19594     }
   19595     v8::Isolate* isolate = v8::Isolate::New(create_params);
   19596     isolate->Enter();
   19597     switch (testCase_) {
   19598       case SetResourceConstraints:
   19599         // Already handled in pre-Isolate-creation block.
   19600         break;
   19601 
   19602       case SetFatalHandler:
   19603         v8::V8::SetFatalErrorHandler(NULL);
   19604         break;
   19605 
   19606       case SetCounterFunction:
   19607         CcTest::isolate()->SetCounterFunction(NULL);
   19608         break;
   19609 
   19610       case SetCreateHistogramFunction:
   19611         CcTest::isolate()->SetCreateHistogramFunction(NULL);
   19612         break;
   19613 
   19614       case SetAddHistogramSampleFunction:
   19615         CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
   19616         break;
   19617     }
   19618     isolate->Exit();
   19619     isolate->Dispose();
   19620     result_ = true;
   19621   }
   19622 
   19623   bool result() { return result_; }
   19624 
   19625  private:
   19626   TestCase testCase_;
   19627   bool result_;
   19628 };
   19629 
   19630 
   19631 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   19632   InitDefaultIsolateThread thread(testCase);
   19633   thread.Start();
   19634   thread.Join();
   19635   CHECK_EQ(thread.result(), true);
   19636 }
   19637 
   19638 
   19639 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
   19640   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
   19641 }
   19642 
   19643 
   19644 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
   19645   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   19646 }
   19647 
   19648 
   19649 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
   19650   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   19651 }
   19652 
   19653 
   19654 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
   19655   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   19656 }
   19657 
   19658 
   19659 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
   19660   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   19661 }
   19662 
   19663 
   19664 TEST(StringCheckMultipleContexts) {
   19665   const char* code =
   19666       "(function() { return \"a\".charAt(0); })()";
   19667 
   19668   {
   19669     // Run the code twice in the first context to initialize the call IC.
   19670     LocalContext context1;
   19671     v8::HandleScope scope(context1->GetIsolate());
   19672     ExpectString(code, "a");
   19673     ExpectString(code, "a");
   19674   }
   19675 
   19676   {
   19677     // Change the String.prototype in the second context and check
   19678     // that the right function gets called.
   19679     LocalContext context2;
   19680     v8::HandleScope scope(context2->GetIsolate());
   19681     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   19682     ExpectString(code, "not a");
   19683   }
   19684 }
   19685 
   19686 
   19687 TEST(NumberCheckMultipleContexts) {
   19688   const char* code =
   19689       "(function() { return (42).toString(); })()";
   19690 
   19691   {
   19692     // Run the code twice in the first context to initialize the call IC.
   19693     LocalContext context1;
   19694     v8::HandleScope scope(context1->GetIsolate());
   19695     ExpectString(code, "42");
   19696     ExpectString(code, "42");
   19697   }
   19698 
   19699   {
   19700     // Change the Number.prototype in the second context and check
   19701     // that the right function gets called.
   19702     LocalContext context2;
   19703     v8::HandleScope scope(context2->GetIsolate());
   19704     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   19705     ExpectString(code, "not 42");
   19706   }
   19707 }
   19708 
   19709 
   19710 TEST(BooleanCheckMultipleContexts) {
   19711   const char* code =
   19712       "(function() { return true.toString(); })()";
   19713 
   19714   {
   19715     // Run the code twice in the first context to initialize the call IC.
   19716     LocalContext context1;
   19717     v8::HandleScope scope(context1->GetIsolate());
   19718     ExpectString(code, "true");
   19719     ExpectString(code, "true");
   19720   }
   19721 
   19722   {
   19723     // Change the Boolean.prototype in the second context and check
   19724     // that the right function gets called.
   19725     LocalContext context2;
   19726     v8::HandleScope scope(context2->GetIsolate());
   19727     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   19728     ExpectString(code, "");
   19729   }
   19730 }
   19731 
   19732 
   19733 TEST(DontDeleteCellLoadIC) {
   19734   const char* function_code =
   19735       "function readCell() { while (true) { return cell; } }";
   19736 
   19737   {
   19738     // Run the code twice in the first context to initialize the load
   19739     // IC for a don't delete cell.
   19740     LocalContext context1;
   19741     v8::HandleScope scope(context1->GetIsolate());
   19742     CompileRun("var cell = \"first\";");
   19743     ExpectBoolean("delete cell", false);
   19744     CompileRun(function_code);
   19745     ExpectString("readCell()", "first");
   19746     ExpectString("readCell()", "first");
   19747   }
   19748 
   19749   {
   19750     // Use a deletable cell in the second context.
   19751     LocalContext context2;
   19752     v8::HandleScope scope(context2->GetIsolate());
   19753     CompileRun("cell = \"second\";");
   19754     CompileRun(function_code);
   19755     ExpectString("readCell()", "second");
   19756     ExpectBoolean("delete cell", true);
   19757     ExpectString("(function() {"
   19758                  "  try {"
   19759                  "    return readCell();"
   19760                  "  } catch(e) {"
   19761                  "    return e.toString();"
   19762                  "  }"
   19763                  "})()",
   19764                  "ReferenceError: cell is not defined");
   19765     CompileRun("cell = \"new_second\";");
   19766     CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   19767     ExpectString("readCell()", "new_second");
   19768     ExpectString("readCell()", "new_second");
   19769   }
   19770 }
   19771 
   19772 
   19773 TEST(DontDeleteCellLoadICForceDelete) {
   19774   const char* function_code =
   19775       "function readCell() { while (true) { return cell; } }";
   19776 
   19777   // Run the code twice to initialize the load IC for a don't delete
   19778   // cell.
   19779   LocalContext context;
   19780   v8::HandleScope scope(context->GetIsolate());
   19781   CompileRun("var cell = \"value\";");
   19782   ExpectBoolean("delete cell", false);
   19783   CompileRun(function_code);
   19784   ExpectString("readCell()", "value");
   19785   ExpectString("readCell()", "value");
   19786 
   19787   // Delete the cell using the API and check the inlined code works
   19788   // correctly.
   19789   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   19790   ExpectString("(function() {"
   19791                "  try {"
   19792                "    return readCell();"
   19793                "  } catch(e) {"
   19794                "    return e.toString();"
   19795                "  }"
   19796                "})()",
   19797                "ReferenceError: cell is not defined");
   19798 }
   19799 
   19800 
   19801 TEST(DontDeleteCellLoadICAPI) {
   19802   const char* function_code =
   19803       "function readCell() { while (true) { return cell; } }";
   19804 
   19805   // Run the code twice to initialize the load IC for a don't delete
   19806   // cell created using the API.
   19807   LocalContext context;
   19808   v8::HandleScope scope(context->GetIsolate());
   19809   context->Global()->ForceSet(v8_str("cell"), v8_str("value"), v8::DontDelete);
   19810   ExpectBoolean("delete cell", false);
   19811   CompileRun(function_code);
   19812   ExpectString("readCell()", "value");
   19813   ExpectString("readCell()", "value");
   19814 
   19815   // Delete the cell using the API and check the inlined code works
   19816   // correctly.
   19817   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   19818   ExpectString("(function() {"
   19819                "  try {"
   19820                "    return readCell();"
   19821                "  } catch(e) {"
   19822                "    return e.toString();"
   19823                "  }"
   19824                "})()",
   19825                "ReferenceError: cell is not defined");
   19826 }
   19827 
   19828 
   19829 class Visitor42 : public v8::PersistentHandleVisitor {
   19830  public:
   19831   explicit Visitor42(v8::Persistent<v8::Object>* object)
   19832       : counter_(0), object_(object) { }
   19833 
   19834   virtual void VisitPersistentHandle(Persistent<Value>* value,
   19835                                      uint16_t class_id) {
   19836     if (class_id != 42) return;
   19837     CHECK_EQ(42, value->WrapperClassId());
   19838     v8::Isolate* isolate = CcTest::isolate();
   19839     v8::HandleScope handle_scope(isolate);
   19840     v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
   19841     v8::Handle<v8::Value> object =
   19842         v8::Local<v8::Object>::New(isolate, *object_);
   19843     CHECK(handle->IsObject());
   19844     CHECK_EQ(Handle<Object>::Cast(handle), object);
   19845     ++counter_;
   19846   }
   19847 
   19848   int counter_;
   19849   v8::Persistent<v8::Object>* object_;
   19850 };
   19851 
   19852 
   19853 TEST(PersistentHandleVisitor) {
   19854   LocalContext context;
   19855   v8::Isolate* isolate = context->GetIsolate();
   19856   v8::HandleScope scope(isolate);
   19857   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   19858   CHECK_EQ(0, object.WrapperClassId());
   19859   object.SetWrapperClassId(42);
   19860   CHECK_EQ(42, object.WrapperClassId());
   19861 
   19862   Visitor42 visitor(&object);
   19863   v8::V8::VisitHandlesWithClassIds(&visitor);
   19864   CHECK_EQ(1, visitor.counter_);
   19865 
   19866   object.Reset();
   19867 }
   19868 
   19869 
   19870 TEST(WrapperClassId) {
   19871   LocalContext context;
   19872   v8::Isolate* isolate = context->GetIsolate();
   19873   v8::HandleScope scope(isolate);
   19874   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   19875   CHECK_EQ(0, object.WrapperClassId());
   19876   object.SetWrapperClassId(65535);
   19877   CHECK_EQ(65535, object.WrapperClassId());
   19878   object.Reset();
   19879 }
   19880 
   19881 
   19882 TEST(PersistentHandleInNewSpaceVisitor) {
   19883   LocalContext context;
   19884   v8::Isolate* isolate = context->GetIsolate();
   19885   v8::HandleScope scope(isolate);
   19886   v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
   19887   CHECK_EQ(0, object1.WrapperClassId());
   19888   object1.SetWrapperClassId(42);
   19889   CHECK_EQ(42, object1.WrapperClassId());
   19890 
   19891   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   19892   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
   19893 
   19894   v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
   19895   CHECK_EQ(0, object2.WrapperClassId());
   19896   object2.SetWrapperClassId(42);
   19897   CHECK_EQ(42, object2.WrapperClassId());
   19898 
   19899   Visitor42 visitor(&object2);
   19900   v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
   19901   CHECK_EQ(1, visitor.counter_);
   19902 
   19903   object1.Reset();
   19904   object2.Reset();
   19905 }
   19906 
   19907 
   19908 TEST(RegExp) {
   19909   LocalContext context;
   19910   v8::HandleScope scope(context->GetIsolate());
   19911 
   19912   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
   19913   CHECK(re->IsRegExp());
   19914   CHECK(re->GetSource()->Equals(v8_str("foo")));
   19915   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   19916 
   19917   re = v8::RegExp::New(v8_str("bar"),
   19918                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   19919                                                       v8::RegExp::kGlobal));
   19920   CHECK(re->IsRegExp());
   19921   CHECK(re->GetSource()->Equals(v8_str("bar")));
   19922   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   19923            static_cast<int>(re->GetFlags()));
   19924 
   19925   re = v8::RegExp::New(v8_str("baz"),
   19926                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   19927                                                       v8::RegExp::kMultiline));
   19928   CHECK(re->IsRegExp());
   19929   CHECK(re->GetSource()->Equals(v8_str("baz")));
   19930   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   19931            static_cast<int>(re->GetFlags()));
   19932 
   19933   re = CompileRun("/quux/").As<v8::RegExp>();
   19934   CHECK(re->IsRegExp());
   19935   CHECK(re->GetSource()->Equals(v8_str("quux")));
   19936   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   19937 
   19938   re = CompileRun("/quux/gm").As<v8::RegExp>();
   19939   CHECK(re->IsRegExp());
   19940   CHECK(re->GetSource()->Equals(v8_str("quux")));
   19941   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   19942            static_cast<int>(re->GetFlags()));
   19943 
   19944   // Override the RegExp constructor and check the API constructor
   19945   // still works.
   19946   CompileRun("RegExp = function() {}");
   19947 
   19948   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
   19949   CHECK(re->IsRegExp());
   19950   CHECK(re->GetSource()->Equals(v8_str("foobar")));
   19951   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   19952 
   19953   re = v8::RegExp::New(v8_str("foobarbaz"),
   19954                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   19955                                                       v8::RegExp::kMultiline));
   19956   CHECK(re->IsRegExp());
   19957   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
   19958   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   19959            static_cast<int>(re->GetFlags()));
   19960 
   19961   context->Global()->Set(v8_str("re"), re);
   19962   ExpectTrue("re.test('FoobarbaZ')");
   19963 
   19964   // RegExps are objects on which you can set properties.
   19965   re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
   19966   v8::Handle<v8::Value> value(CompileRun("re.property"));
   19967   CHECK_EQ(32, value->Int32Value());
   19968 
   19969   v8::TryCatch try_catch;
   19970   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
   19971   CHECK(re.IsEmpty());
   19972   CHECK(try_catch.HasCaught());
   19973   context->Global()->Set(v8_str("ex"), try_catch.Exception());
   19974   ExpectTrue("ex instanceof SyntaxError");
   19975 }
   19976 
   19977 
   19978 THREADED_TEST(Equals) {
   19979   LocalContext localContext;
   19980   v8::HandleScope handleScope(localContext->GetIsolate());
   19981 
   19982   v8::Handle<v8::Object> globalProxy = localContext->Global();
   19983   v8::Handle<Value> global = globalProxy->GetPrototype();
   19984 
   19985   CHECK(global->StrictEquals(global));
   19986   CHECK(!global->StrictEquals(globalProxy));
   19987   CHECK(!globalProxy->StrictEquals(global));
   19988   CHECK(globalProxy->StrictEquals(globalProxy));
   19989 
   19990   CHECK(global->Equals(global));
   19991   CHECK(!global->Equals(globalProxy));
   19992   CHECK(!globalProxy->Equals(global));
   19993   CHECK(globalProxy->Equals(globalProxy));
   19994 }
   19995 
   19996 
   19997 static void Getter(v8::Local<v8::String> property,
   19998                    const v8::PropertyCallbackInfo<v8::Value>& info ) {
   19999   info.GetReturnValue().Set(v8_str("42!"));
   20000 }
   20001 
   20002 
   20003 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
   20004   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
   20005   result->Set(0, v8_str("universalAnswer"));
   20006   info.GetReturnValue().Set(result);
   20007 }
   20008 
   20009 
   20010 TEST(NamedEnumeratorAndForIn) {
   20011   LocalContext context;
   20012   v8::Isolate* isolate = context->GetIsolate();
   20013   v8::HandleScope handle_scope(isolate);
   20014   v8::Context::Scope context_scope(context.local());
   20015 
   20016   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
   20017   tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
   20018   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
   20019   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   20020         "var result = []; for (var k in o) result.push(k); result"));
   20021   CHECK_EQ(1, result->Length());
   20022   CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
   20023 }
   20024 
   20025 
   20026 TEST(DefinePropertyPostDetach) {
   20027   LocalContext context;
   20028   v8::HandleScope scope(context->GetIsolate());
   20029   v8::Handle<v8::Object> proxy = context->Global();
   20030   v8::Handle<v8::Function> define_property =
   20031       CompileRun("(function() {"
   20032                  "  Object.defineProperty("
   20033                  "    this,"
   20034                  "    1,"
   20035                  "    { configurable: true, enumerable: true, value: 3 });"
   20036                  "})").As<Function>();
   20037   context->DetachGlobal();
   20038   define_property->Call(proxy, 0, NULL);
   20039 }
   20040 
   20041 
   20042 static void InstallContextId(v8::Handle<Context> context, int id) {
   20043   Context::Scope scope(context);
   20044   CompileRun("Object.prototype").As<Object>()->
   20045       Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
   20046 }
   20047 
   20048 
   20049 static void CheckContextId(v8::Handle<Object> object, int expected) {
   20050   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
   20051 }
   20052 
   20053 
   20054 THREADED_TEST(CreationContext) {
   20055   v8::Isolate* isolate = CcTest::isolate();
   20056   HandleScope handle_scope(isolate);
   20057   Handle<Context> context1 = Context::New(isolate);
   20058   InstallContextId(context1, 1);
   20059   Handle<Context> context2 = Context::New(isolate);
   20060   InstallContextId(context2, 2);
   20061   Handle<Context> context3 = Context::New(isolate);
   20062   InstallContextId(context3, 3);
   20063 
   20064   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
   20065 
   20066   Local<Object> object1;
   20067   Local<Function> func1;
   20068   {
   20069     Context::Scope scope(context1);
   20070     object1 = Object::New(isolate);
   20071     func1 = tmpl->GetFunction();
   20072   }
   20073 
   20074   Local<Object> object2;
   20075   Local<Function> func2;
   20076   {
   20077     Context::Scope scope(context2);
   20078     object2 = Object::New(isolate);
   20079     func2 = tmpl->GetFunction();
   20080   }
   20081 
   20082   Local<Object> instance1;
   20083   Local<Object> instance2;
   20084 
   20085   {
   20086     Context::Scope scope(context3);
   20087     instance1 = func1->NewInstance();
   20088     instance2 = func2->NewInstance();
   20089   }
   20090 
   20091   CHECK(object1->CreationContext() == context1);
   20092   CheckContextId(object1, 1);
   20093   CHECK(func1->CreationContext() == context1);
   20094   CheckContextId(func1, 1);
   20095   CHECK(instance1->CreationContext() == context1);
   20096   CheckContextId(instance1, 1);
   20097   CHECK(object2->CreationContext() == context2);
   20098   CheckContextId(object2, 2);
   20099   CHECK(func2->CreationContext() == context2);
   20100   CheckContextId(func2, 2);
   20101   CHECK(instance2->CreationContext() == context2);
   20102   CheckContextId(instance2, 2);
   20103 
   20104   {
   20105     Context::Scope scope(context1);
   20106     CHECK(object1->CreationContext() == context1);
   20107     CheckContextId(object1, 1);
   20108     CHECK(func1->CreationContext() == context1);
   20109     CheckContextId(func1, 1);
   20110     CHECK(instance1->CreationContext() == context1);
   20111     CheckContextId(instance1, 1);
   20112     CHECK(object2->CreationContext() == context2);
   20113     CheckContextId(object2, 2);
   20114     CHECK(func2->CreationContext() == context2);
   20115     CheckContextId(func2, 2);
   20116     CHECK(instance2->CreationContext() == context2);
   20117     CheckContextId(instance2, 2);
   20118   }
   20119 
   20120   {
   20121     Context::Scope scope(context2);
   20122     CHECK(object1->CreationContext() == context1);
   20123     CheckContextId(object1, 1);
   20124     CHECK(func1->CreationContext() == context1);
   20125     CheckContextId(func1, 1);
   20126     CHECK(instance1->CreationContext() == context1);
   20127     CheckContextId(instance1, 1);
   20128     CHECK(object2->CreationContext() == context2);
   20129     CheckContextId(object2, 2);
   20130     CHECK(func2->CreationContext() == context2);
   20131     CheckContextId(func2, 2);
   20132     CHECK(instance2->CreationContext() == context2);
   20133     CheckContextId(instance2, 2);
   20134   }
   20135 }
   20136 
   20137 
   20138 THREADED_TEST(CreationContextOfJsFunction) {
   20139   HandleScope handle_scope(CcTest::isolate());
   20140   Handle<Context> context = Context::New(CcTest::isolate());
   20141   InstallContextId(context, 1);
   20142 
   20143   Local<Object> function;
   20144   {
   20145     Context::Scope scope(context);
   20146     function = CompileRun("function foo() {}; foo").As<Object>();
   20147   }
   20148 
   20149   CHECK(function->CreationContext() == context);
   20150   CheckContextId(function, 1);
   20151 }
   20152 
   20153 
   20154 void HasOwnPropertyIndexedPropertyGetter(
   20155     uint32_t index,
   20156     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20157   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
   20158 }
   20159 
   20160 
   20161 void HasOwnPropertyNamedPropertyGetter(
   20162     Local<String> property,
   20163     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20164   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
   20165 }
   20166 
   20167 
   20168 void HasOwnPropertyIndexedPropertyQuery(
   20169     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20170   if (index == 42) info.GetReturnValue().Set(1);
   20171 }
   20172 
   20173 
   20174 void HasOwnPropertyNamedPropertyQuery(
   20175     Local<String> property,
   20176     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20177   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
   20178 }
   20179 
   20180 
   20181 void HasOwnPropertyNamedPropertyQuery2(
   20182     Local<String> property,
   20183     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20184   if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
   20185 }
   20186 
   20187 
   20188 void HasOwnPropertyAccessorGetter(
   20189     Local<String> property,
   20190     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20191   info.GetReturnValue().Set(v8_str("yes"));
   20192 }
   20193 
   20194 
   20195 TEST(HasOwnProperty) {
   20196   LocalContext env;
   20197   v8::Isolate* isolate = env->GetIsolate();
   20198   v8::HandleScope scope(isolate);
   20199   { // Check normal properties and defined getters.
   20200     Handle<Value> value = CompileRun(
   20201         "function Foo() {"
   20202         "    this.foo = 11;"
   20203         "    this.__defineGetter__('baz', function() { return 1; });"
   20204         "};"
   20205         "function Bar() { "
   20206         "    this.bar = 13;"
   20207         "    this.__defineGetter__('bla', function() { return 2; });"
   20208         "};"
   20209         "Bar.prototype = new Foo();"
   20210         "new Bar();");
   20211     CHECK(value->IsObject());
   20212     Handle<Object> object = value->ToObject();
   20213     CHECK(object->Has(v8_str("foo")));
   20214     CHECK(!object->HasOwnProperty(v8_str("foo")));
   20215     CHECK(object->HasOwnProperty(v8_str("bar")));
   20216     CHECK(object->Has(v8_str("baz")));
   20217     CHECK(!object->HasOwnProperty(v8_str("baz")));
   20218     CHECK(object->HasOwnProperty(v8_str("bla")));
   20219   }
   20220   { // Check named getter interceptors.
   20221     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20222     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
   20223     Handle<Object> instance = templ->NewInstance();
   20224     CHECK(!instance->HasOwnProperty(v8_str("42")));
   20225     CHECK(instance->HasOwnProperty(v8_str("foo")));
   20226     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   20227   }
   20228   { // Check indexed getter interceptors.
   20229     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20230     templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
   20231     Handle<Object> instance = templ->NewInstance();
   20232     CHECK(instance->HasOwnProperty(v8_str("42")));
   20233     CHECK(!instance->HasOwnProperty(v8_str("43")));
   20234     CHECK(!instance->HasOwnProperty(v8_str("foo")));
   20235   }
   20236   { // Check named query interceptors.
   20237     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20238     templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
   20239     Handle<Object> instance = templ->NewInstance();
   20240     CHECK(instance->HasOwnProperty(v8_str("foo")));
   20241     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   20242   }
   20243   { // Check indexed query interceptors.
   20244     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20245     templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
   20246     Handle<Object> instance = templ->NewInstance();
   20247     CHECK(instance->HasOwnProperty(v8_str("42")));
   20248     CHECK(!instance->HasOwnProperty(v8_str("41")));
   20249   }
   20250   { // Check callbacks.
   20251     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20252     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   20253     Handle<Object> instance = templ->NewInstance();
   20254     CHECK(instance->HasOwnProperty(v8_str("foo")));
   20255     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   20256   }
   20257   { // Check that query wins on disagreement.
   20258     Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20259     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
   20260                                    0,
   20261                                    HasOwnPropertyNamedPropertyQuery2);
   20262     Handle<Object> instance = templ->NewInstance();
   20263     CHECK(!instance->HasOwnProperty(v8_str("foo")));
   20264     CHECK(instance->HasOwnProperty(v8_str("bar")));
   20265   }
   20266 }
   20267 
   20268 
   20269 TEST(IndexedInterceptorWithStringProto) {
   20270   v8::Isolate* isolate = CcTest::isolate();
   20271   v8::HandleScope scope(isolate);
   20272   Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20273   templ->SetIndexedPropertyHandler(NULL,
   20274                                    NULL,
   20275                                    HasOwnPropertyIndexedPropertyQuery);
   20276   LocalContext context;
   20277   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   20278   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
   20279   // These should be intercepted.
   20280   CHECK(CompileRun("42 in obj")->BooleanValue());
   20281   CHECK(CompileRun("'42' in obj")->BooleanValue());
   20282   // These should fall through to the String prototype.
   20283   CHECK(CompileRun("0 in obj")->BooleanValue());
   20284   CHECK(CompileRun("'0' in obj")->BooleanValue());
   20285   // And these should both fail.
   20286   CHECK(!CompileRun("32 in obj")->BooleanValue());
   20287   CHECK(!CompileRun("'32' in obj")->BooleanValue());
   20288 }
   20289 
   20290 
   20291 void CheckCodeGenerationAllowed() {
   20292   Handle<Value> result = CompileRun("eval('42')");
   20293   CHECK_EQ(42, result->Int32Value());
   20294   result = CompileRun("(function(e) { return e('42'); })(eval)");
   20295   CHECK_EQ(42, result->Int32Value());
   20296   result = CompileRun("var f = new Function('return 42'); f()");
   20297   CHECK_EQ(42, result->Int32Value());
   20298 }
   20299 
   20300 
   20301 void CheckCodeGenerationDisallowed() {
   20302   TryCatch try_catch;
   20303 
   20304   Handle<Value> result = CompileRun("eval('42')");
   20305   CHECK(result.IsEmpty());
   20306   CHECK(try_catch.HasCaught());
   20307   try_catch.Reset();
   20308 
   20309   result = CompileRun("(function(e) { return e('42'); })(eval)");
   20310   CHECK(result.IsEmpty());
   20311   CHECK(try_catch.HasCaught());
   20312   try_catch.Reset();
   20313 
   20314   result = CompileRun("var f = new Function('return 42'); f()");
   20315   CHECK(result.IsEmpty());
   20316   CHECK(try_catch.HasCaught());
   20317 }
   20318 
   20319 
   20320 bool CodeGenerationAllowed(Local<Context> context) {
   20321   ApiTestFuzzer::Fuzz();
   20322   return true;
   20323 }
   20324 
   20325 
   20326 bool CodeGenerationDisallowed(Local<Context> context) {
   20327   ApiTestFuzzer::Fuzz();
   20328   return false;
   20329 }
   20330 
   20331 
   20332 THREADED_TEST(AllowCodeGenFromStrings) {
   20333   LocalContext context;
   20334   v8::HandleScope scope(context->GetIsolate());
   20335 
   20336   // eval and the Function constructor allowed by default.
   20337   CHECK(context->IsCodeGenerationFromStringsAllowed());
   20338   CheckCodeGenerationAllowed();
   20339 
   20340   // Disallow eval and the Function constructor.
   20341   context->AllowCodeGenerationFromStrings(false);
   20342   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   20343   CheckCodeGenerationDisallowed();
   20344 
   20345   // Allow again.
   20346   context->AllowCodeGenerationFromStrings(true);
   20347   CheckCodeGenerationAllowed();
   20348 
   20349   // Disallow but setting a global callback that will allow the calls.
   20350   context->AllowCodeGenerationFromStrings(false);
   20351   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
   20352   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   20353   CheckCodeGenerationAllowed();
   20354 
   20355   // Set a callback that disallows the code generation.
   20356   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
   20357   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   20358   CheckCodeGenerationDisallowed();
   20359 }
   20360 
   20361 
   20362 TEST(SetErrorMessageForCodeGenFromStrings) {
   20363   LocalContext context;
   20364   v8::HandleScope scope(context->GetIsolate());
   20365   TryCatch try_catch;
   20366 
   20367   Handle<String> message = v8_str("Message") ;
   20368   Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
   20369   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
   20370   context->AllowCodeGenerationFromStrings(false);
   20371   context->SetErrorMessageForCodeGenerationFromStrings(message);
   20372   Handle<Value> result = CompileRun("eval('42')");
   20373   CHECK(result.IsEmpty());
   20374   CHECK(try_catch.HasCaught());
   20375   Handle<String> actual_message = try_catch.Message()->Get();
   20376   CHECK(expected_message->Equals(actual_message));
   20377 }
   20378 
   20379 
   20380 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20381 }
   20382 
   20383 
   20384 THREADED_TEST(CallAPIFunctionOnNonObject) {
   20385   LocalContext context;
   20386   v8::Isolate* isolate = context->GetIsolate();
   20387   v8::HandleScope scope(isolate);
   20388   Handle<FunctionTemplate> templ =
   20389       v8::FunctionTemplate::New(isolate, NonObjectThis);
   20390   Handle<Function> function = templ->GetFunction();
   20391   context->Global()->Set(v8_str("f"), function);
   20392   TryCatch try_catch;
   20393   CompileRun("f.call(2)");
   20394 }
   20395 
   20396 
   20397 // Regression test for issue 1470.
   20398 THREADED_TEST(ReadOnlyIndexedProperties) {
   20399   v8::Isolate* isolate = CcTest::isolate();
   20400   v8::HandleScope scope(isolate);
   20401   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20402 
   20403   LocalContext context;
   20404   Local<v8::Object> obj = templ->NewInstance();
   20405   context->Global()->Set(v8_str("obj"), obj);
   20406   obj->ForceSet(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
   20407   obj->Set(v8_str("1"), v8_str("foobar"));
   20408   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
   20409   obj->ForceSet(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
   20410   obj->Set(v8_num(2), v8_str("foobar"));
   20411   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
   20412 
   20413   // Test non-smi case.
   20414   obj->ForceSet(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
   20415   obj->Set(v8_str("2000000000"), v8_str("foobar"));
   20416   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
   20417 }
   20418 
   20419 
   20420 THREADED_TEST(Regress1516) {
   20421   LocalContext context;
   20422   v8::HandleScope scope(context->GetIsolate());
   20423 
   20424   { v8::HandleScope temp_scope(context->GetIsolate());
   20425     CompileRun("({'a': 0})");
   20426   }
   20427 
   20428   int elements;
   20429   { i::MapCache* map_cache =
   20430         i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
   20431     elements = map_cache->NumberOfElements();
   20432     CHECK_LE(1, elements);
   20433   }
   20434 
   20435   CcTest::heap()->CollectAllGarbage(
   20436       i::Heap::kAbortIncrementalMarkingMask);
   20437   { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
   20438     if (raw_map_cache != CcTest::heap()->undefined_value()) {
   20439       i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
   20440       CHECK_GT(elements, map_cache->NumberOfElements());
   20441     }
   20442   }
   20443 }
   20444 
   20445 
   20446 static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
   20447                                                 Local<Value> name,
   20448                                                 v8::AccessType type,
   20449                                                 Local<Value> data) {
   20450   // Only block read access to __proto__.
   20451   if (type == v8::ACCESS_GET &&
   20452       name->IsString() &&
   20453       name->ToString()->Length() == 9 &&
   20454       name->ToString()->Utf8Length() == 9) {
   20455     char buffer[10];
   20456     CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
   20457     return strncmp(buffer, "__proto__", 9) != 0;
   20458   }
   20459 
   20460   return true;
   20461 }
   20462 
   20463 
   20464 THREADED_TEST(Regress93759) {
   20465   v8::Isolate* isolate = CcTest::isolate();
   20466   HandleScope scope(isolate);
   20467 
   20468   // Template for object with security check.
   20469   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
   20470   // We don't do indexing, so any callback can be used for that.
   20471   no_proto_template->SetAccessCheckCallbacks(
   20472       BlockProtoNamedSecurityTestCallback,
   20473       IndexedSecurityTestCallback);
   20474 
   20475   // Templates for objects with hidden prototypes and possibly security check.
   20476   Local<FunctionTemplate> hidden_proto_template =
   20477       v8::FunctionTemplate::New(isolate);
   20478   hidden_proto_template->SetHiddenPrototype(true);
   20479 
   20480   Local<FunctionTemplate> protected_hidden_proto_template =
   20481       v8::FunctionTemplate::New(isolate);
   20482   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
   20483       BlockProtoNamedSecurityTestCallback,
   20484       IndexedSecurityTestCallback);
   20485   protected_hidden_proto_template->SetHiddenPrototype(true);
   20486 
   20487   // Context for "foreign" objects used in test.
   20488   Local<Context> context = v8::Context::New(isolate);
   20489   context->Enter();
   20490 
   20491   // Plain object, no security check.
   20492   Local<Object> simple_object = Object::New(isolate);
   20493 
   20494   // Object with explicit security check.
   20495   Local<Object> protected_object =
   20496       no_proto_template->NewInstance();
   20497 
   20498   // JSGlobalProxy object, always have security check.
   20499   Local<Object> proxy_object =
   20500       context->Global();
   20501 
   20502   // Global object, the  prototype of proxy_object. No security checks.
   20503   Local<Object> global_object =
   20504       proxy_object->GetPrototype()->ToObject();
   20505 
   20506   // Hidden prototype without security check.
   20507   Local<Object> hidden_prototype =
   20508       hidden_proto_template->GetFunction()->NewInstance();
   20509   Local<Object> object_with_hidden =
   20510     Object::New(isolate);
   20511   object_with_hidden->SetPrototype(hidden_prototype);
   20512 
   20513   // Hidden prototype with security check on the hidden prototype.
   20514   Local<Object> protected_hidden_prototype =
   20515       protected_hidden_proto_template->GetFunction()->NewInstance();
   20516   Local<Object> object_with_protected_hidden =
   20517     Object::New(isolate);
   20518   object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
   20519 
   20520   context->Exit();
   20521 
   20522   // Template for object for second context. Values to test are put on it as
   20523   // properties.
   20524   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   20525   global_template->Set(v8_str("simple"), simple_object);
   20526   global_template->Set(v8_str("protected"), protected_object);
   20527   global_template->Set(v8_str("global"), global_object);
   20528   global_template->Set(v8_str("proxy"), proxy_object);
   20529   global_template->Set(v8_str("hidden"), object_with_hidden);
   20530   global_template->Set(v8_str("phidden"), object_with_protected_hidden);
   20531 
   20532   LocalContext context2(NULL, global_template);
   20533 
   20534   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
   20535   CHECK(result1->Equals(simple_object->GetPrototype()));
   20536 
   20537   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
   20538   CHECK(result2.IsEmpty());
   20539 
   20540   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
   20541   CHECK(result3->Equals(global_object->GetPrototype()));
   20542 
   20543   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
   20544   CHECK(result4.IsEmpty());
   20545 
   20546   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
   20547   CHECK(result5->Equals(
   20548       object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
   20549 
   20550   Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
   20551   CHECK(result6.IsEmpty());
   20552 }
   20553 
   20554 
   20555 THREADED_TEST(Regress125988) {
   20556   v8::HandleScope scope(CcTest::isolate());
   20557   Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
   20558   AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
   20559   LocalContext env;
   20560   env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
   20561   CompileRun("var a = new Object();"
   20562              "var b = new Intercept();"
   20563              "var c = new Object();"
   20564              "c.__proto__ = b;"
   20565              "b.__proto__ = a;"
   20566              "a.x = 23;"
   20567              "for (var i = 0; i < 3; i++) c.x;");
   20568   ExpectBoolean("c.hasOwnProperty('x')", false);
   20569   ExpectInt32("c.x", 23);
   20570   CompileRun("a.y = 42;"
   20571              "for (var i = 0; i < 3; i++) c.x;");
   20572   ExpectBoolean("c.hasOwnProperty('x')", false);
   20573   ExpectInt32("c.x", 23);
   20574   ExpectBoolean("c.hasOwnProperty('y')", false);
   20575   ExpectInt32("c.y", 42);
   20576 }
   20577 
   20578 
   20579 static void TestReceiver(Local<Value> expected_result,
   20580                          Local<Value> expected_receiver,
   20581                          const char* code) {
   20582   Local<Value> result = CompileRun(code);
   20583   CHECK(result->IsObject());
   20584   CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
   20585   CHECK(expected_result->Equals(result->ToObject()->Get(0)));
   20586 }
   20587 
   20588 
   20589 THREADED_TEST(ForeignFunctionReceiver) {
   20590   v8::Isolate* isolate = CcTest::isolate();
   20591   HandleScope scope(isolate);
   20592 
   20593   // Create two contexts with different "id" properties ('i' and 'o').
   20594   // Call a function both from its own context and from a the foreign
   20595   // context, and see what "this" is bound to (returning both "this"
   20596   // and "this.id" for comparison).
   20597 
   20598   Local<Context> foreign_context = v8::Context::New(isolate);
   20599   foreign_context->Enter();
   20600   Local<Value> foreign_function =
   20601     CompileRun("function func() { return { 0: this.id, "
   20602                "                           1: this, "
   20603                "                           toString: function() { "
   20604                "                               return this[0];"
   20605                "                           }"
   20606                "                         };"
   20607                "}"
   20608                "var id = 'i';"
   20609                "func;");
   20610   CHECK(foreign_function->IsFunction());
   20611   foreign_context->Exit();
   20612 
   20613   LocalContext context;
   20614 
   20615   Local<String> password = v8_str("Password");
   20616   // Don't get hit by security checks when accessing foreign_context's
   20617   // global receiver (aka. global proxy).
   20618   context->SetSecurityToken(password);
   20619   foreign_context->SetSecurityToken(password);
   20620 
   20621   Local<String> i = v8_str("i");
   20622   Local<String> o = v8_str("o");
   20623   Local<String> id = v8_str("id");
   20624 
   20625   CompileRun("function ownfunc() { return { 0: this.id, "
   20626              "                              1: this, "
   20627              "                              toString: function() { "
   20628              "                                  return this[0];"
   20629              "                              }"
   20630              "                             };"
   20631              "}"
   20632              "var id = 'o';"
   20633              "ownfunc");
   20634   context->Global()->Set(v8_str("func"), foreign_function);
   20635 
   20636   // Sanity check the contexts.
   20637   CHECK(i->Equals(foreign_context->Global()->Get(id)));
   20638   CHECK(o->Equals(context->Global()->Get(id)));
   20639 
   20640   // Checking local function's receiver.
   20641   // Calling function using its call/apply methods.
   20642   TestReceiver(o, context->Global(), "ownfunc.call()");
   20643   TestReceiver(o, context->Global(), "ownfunc.apply()");
   20644   // Making calls through built-in functions.
   20645   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   20646   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
   20647   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
   20648   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
   20649   // Calling with environment record as base.
   20650   TestReceiver(o, context->Global(), "ownfunc()");
   20651   // Calling with no base.
   20652   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   20653 
   20654   // Checking foreign function return value.
   20655   // Calling function using its call/apply methods.
   20656   TestReceiver(i, foreign_context->Global(), "func.call()");
   20657   TestReceiver(i, foreign_context->Global(), "func.apply()");
   20658   // Calling function using another context's call/apply methods.
   20659   TestReceiver(i, foreign_context->Global(),
   20660                "Function.prototype.call.call(func)");
   20661   TestReceiver(i, foreign_context->Global(),
   20662                "Function.prototype.call.apply(func)");
   20663   TestReceiver(i, foreign_context->Global(),
   20664                "Function.prototype.apply.call(func)");
   20665   TestReceiver(i, foreign_context->Global(),
   20666                "Function.prototype.apply.apply(func)");
   20667   // Making calls through built-in functions.
   20668   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   20669   // ToString(func()) is func()[0], i.e., the returned this.id.
   20670   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
   20671   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
   20672   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
   20673 
   20674   // Calling with environment record as base.
   20675   TestReceiver(i, foreign_context->Global(), "func()");
   20676   // Calling with no base.
   20677   TestReceiver(i, foreign_context->Global(), "(1,func)()");
   20678 }
   20679 
   20680 
   20681 uint8_t callback_fired = 0;
   20682 
   20683 
   20684 void CallCompletedCallback1() {
   20685   v8::base::OS::Print("Firing callback 1.\n");
   20686   callback_fired ^= 1;  // Toggle first bit.
   20687 }
   20688 
   20689 
   20690 void CallCompletedCallback2() {
   20691   v8::base::OS::Print("Firing callback 2.\n");
   20692   callback_fired ^= 2;  // Toggle second bit.
   20693 }
   20694 
   20695 
   20696 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20697   int32_t level = args[0]->Int32Value();
   20698   if (level < 3) {
   20699     level++;
   20700     v8::base::OS::Print("Entering recursion level %d.\n", level);
   20701     char script[64];
   20702     i::Vector<char> script_vector(script, sizeof(script));
   20703     i::SNPrintF(script_vector, "recursion(%d)", level);
   20704     CompileRun(script_vector.start());
   20705     v8::base::OS::Print("Leaving recursion level %d.\n", level);
   20706     CHECK_EQ(0, callback_fired);
   20707   } else {
   20708     v8::base::OS::Print("Recursion ends.\n");
   20709     CHECK_EQ(0, callback_fired);
   20710   }
   20711 }
   20712 
   20713 
   20714 TEST(CallCompletedCallback) {
   20715   LocalContext env;
   20716   v8::HandleScope scope(env->GetIsolate());
   20717   v8::Handle<v8::FunctionTemplate> recursive_runtime =
   20718       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
   20719   env->Global()->Set(v8_str("recursion"),
   20720                      recursive_runtime->GetFunction());
   20721   // Adding the same callback a second time has no effect.
   20722   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   20723   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   20724   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
   20725   v8::base::OS::Print("--- Script (1) ---\n");
   20726   Local<Script> script = v8::Script::Compile(
   20727       v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
   20728   script->Run();
   20729   CHECK_EQ(3, callback_fired);
   20730 
   20731   v8::base::OS::Print("\n--- Script (2) ---\n");
   20732   callback_fired = 0;
   20733   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
   20734   script->Run();
   20735   CHECK_EQ(2, callback_fired);
   20736 
   20737   v8::base::OS::Print("\n--- Function ---\n");
   20738   callback_fired = 0;
   20739   Local<Function> recursive_function =
   20740       Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
   20741   v8::Handle<Value> args[] = { v8_num(0) };
   20742   recursive_function->Call(env->Global(), 1, args);
   20743   CHECK_EQ(2, callback_fired);
   20744 }
   20745 
   20746 
   20747 void CallCompletedCallbackNoException() {
   20748   v8::HandleScope scope(CcTest::isolate());
   20749   CompileRun("1+1;");
   20750 }
   20751 
   20752 
   20753 void CallCompletedCallbackException() {
   20754   v8::HandleScope scope(CcTest::isolate());
   20755   CompileRun("throw 'second exception';");
   20756 }
   20757 
   20758 
   20759 TEST(CallCompletedCallbackOneException) {
   20760   LocalContext env;
   20761   v8::HandleScope scope(env->GetIsolate());
   20762   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
   20763   CompileRun("throw 'exception';");
   20764 }
   20765 
   20766 
   20767 TEST(CallCompletedCallbackTwoExceptions) {
   20768   LocalContext env;
   20769   v8::HandleScope scope(env->GetIsolate());
   20770   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
   20771   CompileRun("throw 'first exception';");
   20772 }
   20773 
   20774 
   20775 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
   20776   v8::HandleScope scope(info.GetIsolate());
   20777   CompileRun("ext1Calls++;");
   20778 }
   20779 
   20780 
   20781 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
   20782   v8::HandleScope scope(info.GetIsolate());
   20783   CompileRun("ext2Calls++;");
   20784 }
   20785 
   20786 
   20787 void* g_passed_to_three = NULL;
   20788 
   20789 
   20790 static void MicrotaskThree(void* data) {
   20791   g_passed_to_three = data;
   20792 }
   20793 
   20794 
   20795 TEST(EnqueueMicrotask) {
   20796   LocalContext env;
   20797   v8::HandleScope scope(env->GetIsolate());
   20798   CompileRun(
   20799       "var ext1Calls = 0;"
   20800       "var ext2Calls = 0;");
   20801   CompileRun("1+1;");
   20802   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
   20803   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
   20804 
   20805   env->GetIsolate()->EnqueueMicrotask(
   20806       Function::New(env->GetIsolate(), MicrotaskOne));
   20807   CompileRun("1+1;");
   20808   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
   20809   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
   20810 
   20811   env->GetIsolate()->EnqueueMicrotask(
   20812       Function::New(env->GetIsolate(), MicrotaskOne));
   20813   env->GetIsolate()->EnqueueMicrotask(
   20814       Function::New(env->GetIsolate(), MicrotaskTwo));
   20815   CompileRun("1+1;");
   20816   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20817   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
   20818 
   20819   env->GetIsolate()->EnqueueMicrotask(
   20820       Function::New(env->GetIsolate(), MicrotaskTwo));
   20821   CompileRun("1+1;");
   20822   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20823   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
   20824 
   20825   CompileRun("1+1;");
   20826   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20827   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
   20828 
   20829   g_passed_to_three = NULL;
   20830   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
   20831   CompileRun("1+1;");
   20832   CHECK_EQ(NULL, g_passed_to_three);
   20833   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20834   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
   20835 
   20836   int dummy;
   20837   env->GetIsolate()->EnqueueMicrotask(
   20838       Function::New(env->GetIsolate(), MicrotaskOne));
   20839   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
   20840   env->GetIsolate()->EnqueueMicrotask(
   20841       Function::New(env->GetIsolate(), MicrotaskTwo));
   20842   CompileRun("1+1;");
   20843   CHECK_EQ(&dummy, g_passed_to_three);
   20844   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value());
   20845   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
   20846   g_passed_to_three = NULL;
   20847 }
   20848 
   20849 
   20850 static void MicrotaskExceptionOne(
   20851     const v8::FunctionCallbackInfo<Value>& info) {
   20852   v8::HandleScope scope(info.GetIsolate());
   20853   CompileRun("exception1Calls++;");
   20854   info.GetIsolate()->ThrowException(
   20855       v8::Exception::Error(v8_str("first")));
   20856 }
   20857 
   20858 
   20859 static void MicrotaskExceptionTwo(
   20860     const v8::FunctionCallbackInfo<Value>& info) {
   20861   v8::HandleScope scope(info.GetIsolate());
   20862   CompileRun("exception2Calls++;");
   20863   info.GetIsolate()->ThrowException(
   20864       v8::Exception::Error(v8_str("second")));
   20865 }
   20866 
   20867 
   20868 TEST(RunMicrotasksIgnoresThrownExceptions) {
   20869   LocalContext env;
   20870   v8::Isolate* isolate = env->GetIsolate();
   20871   v8::HandleScope scope(isolate);
   20872   CompileRun(
   20873       "var exception1Calls = 0;"
   20874       "var exception2Calls = 0;");
   20875   isolate->EnqueueMicrotask(
   20876       Function::New(isolate, MicrotaskExceptionOne));
   20877   isolate->EnqueueMicrotask(
   20878       Function::New(isolate, MicrotaskExceptionTwo));
   20879   TryCatch try_catch;
   20880   CompileRun("1+1;");
   20881   CHECK(!try_catch.HasCaught());
   20882   CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value());
   20883   CHECK_EQ(1, CompileRun("exception2Calls")->Int32Value());
   20884 }
   20885 
   20886 
   20887 TEST(SetAutorunMicrotasks) {
   20888   LocalContext env;
   20889   v8::HandleScope scope(env->GetIsolate());
   20890   CompileRun(
   20891       "var ext1Calls = 0;"
   20892       "var ext2Calls = 0;");
   20893   CompileRun("1+1;");
   20894   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
   20895   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
   20896 
   20897   env->GetIsolate()->EnqueueMicrotask(
   20898       Function::New(env->GetIsolate(), MicrotaskOne));
   20899   CompileRun("1+1;");
   20900   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
   20901   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
   20902 
   20903   env->GetIsolate()->SetAutorunMicrotasks(false);
   20904   env->GetIsolate()->EnqueueMicrotask(
   20905       Function::New(env->GetIsolate(), MicrotaskOne));
   20906   env->GetIsolate()->EnqueueMicrotask(
   20907       Function::New(env->GetIsolate(), MicrotaskTwo));
   20908   CompileRun("1+1;");
   20909   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
   20910   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
   20911 
   20912   env->GetIsolate()->RunMicrotasks();
   20913   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20914   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
   20915 
   20916   env->GetIsolate()->EnqueueMicrotask(
   20917       Function::New(env->GetIsolate(), MicrotaskTwo));
   20918   CompileRun("1+1;");
   20919   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20920   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
   20921 
   20922   env->GetIsolate()->RunMicrotasks();
   20923   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20924   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
   20925 
   20926   env->GetIsolate()->SetAutorunMicrotasks(true);
   20927   env->GetIsolate()->EnqueueMicrotask(
   20928       Function::New(env->GetIsolate(), MicrotaskTwo));
   20929   CompileRun("1+1;");
   20930   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20931   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
   20932 
   20933   env->GetIsolate()->EnqueueMicrotask(
   20934       Function::New(env->GetIsolate(), MicrotaskTwo));
   20935   {
   20936     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
   20937     CompileRun("1+1;");
   20938     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20939     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
   20940   }
   20941 
   20942   CompileRun("1+1;");
   20943   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
   20944   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value());
   20945 }
   20946 
   20947 
   20948 TEST(RunMicrotasksWithoutEnteringContext) {
   20949   v8::Isolate* isolate = CcTest::isolate();
   20950   HandleScope handle_scope(isolate);
   20951   isolate->SetAutorunMicrotasks(false);
   20952   Handle<Context> context = Context::New(isolate);
   20953   {
   20954     Context::Scope context_scope(context);
   20955     CompileRun("var ext1Calls = 0;");
   20956     isolate->EnqueueMicrotask(Function::New(isolate, MicrotaskOne));
   20957   }
   20958   isolate->RunMicrotasks();
   20959   {
   20960     Context::Scope context_scope(context);
   20961     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
   20962   }
   20963   isolate->SetAutorunMicrotasks(true);
   20964 }
   20965 
   20966 
   20967 static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
   20968   v8::DebugEvent event = event_details.GetEvent();
   20969   if (event != v8::Break) return;
   20970   Handle<Object> exec_state = event_details.GetExecutionState();
   20971   Handle<Value> break_id = exec_state->Get(v8_str("break_id"));
   20972   CompileRun("function f(id) { new FrameDetails(id, 0); }");
   20973   Handle<Function> fun = Handle<Function>::Cast(
   20974       CcTest::global()->Get(v8_str("f"))->ToObject());
   20975   fun->Call(CcTest::global(), 1, &break_id);
   20976 }
   20977 
   20978 
   20979 TEST(Regress385349) {
   20980   i::FLAG_allow_natives_syntax = true;
   20981   v8::Isolate* isolate = CcTest::isolate();
   20982   HandleScope handle_scope(isolate);
   20983   isolate->SetAutorunMicrotasks(false);
   20984   Handle<Context> context = Context::New(isolate);
   20985   v8::Debug::SetDebugEventListener(DebugEventInObserver);
   20986   {
   20987     Context::Scope context_scope(context);
   20988     CompileRun("var obj = {};"
   20989                "Object.observe(obj, function(changes) { debugger; });"
   20990                "obj.a = 0;");
   20991   }
   20992   isolate->RunMicrotasks();
   20993   isolate->SetAutorunMicrotasks(true);
   20994   v8::Debug::SetDebugEventListener(NULL);
   20995 }
   20996 
   20997 
   20998 #ifdef DEBUG
   20999 static int probes_counter = 0;
   21000 static int misses_counter = 0;
   21001 static int updates_counter = 0;
   21002 
   21003 
   21004 static int* LookupCounter(const char* name) {
   21005   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
   21006     return &probes_counter;
   21007   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
   21008     return &misses_counter;
   21009   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
   21010     return &updates_counter;
   21011   }
   21012   return NULL;
   21013 }
   21014 
   21015 
   21016 static const char* kMegamorphicTestProgram =
   21017     "function ClassA() { };"
   21018     "function ClassB() { };"
   21019     "ClassA.prototype.foo = function() { };"
   21020     "ClassB.prototype.foo = function() { };"
   21021     "function fooify(obj) { obj.foo(); };"
   21022     "var a = new ClassA();"
   21023     "var b = new ClassB();"
   21024     "for (var i = 0; i < 10000; i++) {"
   21025     "  fooify(a);"
   21026     "  fooify(b);"
   21027     "}";
   21028 #endif
   21029 
   21030 
   21031 static void StubCacheHelper(bool primary) {
   21032 #ifdef DEBUG
   21033   i::FLAG_native_code_counters = true;
   21034   if (primary) {
   21035     i::FLAG_test_primary_stub_cache = true;
   21036   } else {
   21037     i::FLAG_test_secondary_stub_cache = true;
   21038   }
   21039   i::FLAG_crankshaft = false;
   21040   LocalContext env;
   21041   env->GetIsolate()->SetCounterFunction(LookupCounter);
   21042   v8::HandleScope scope(env->GetIsolate());
   21043   int initial_probes = probes_counter;
   21044   int initial_misses = misses_counter;
   21045   int initial_updates = updates_counter;
   21046   CompileRun(kMegamorphicTestProgram);
   21047   int probes = probes_counter - initial_probes;
   21048   int misses = misses_counter - initial_misses;
   21049   int updates = updates_counter - initial_updates;
   21050   CHECK_LT(updates, 10);
   21051   CHECK_LT(misses, 10);
   21052   // TODO(verwaest): Update this test to overflow the degree of polymorphism
   21053   // before megamorphism. The number of probes will only work once we teach the
   21054   // serializer to embed references to counters in the stubs, given that the
   21055   // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
   21056   CHECK_GE(probes, 0);
   21057 #endif
   21058 }
   21059 
   21060 
   21061 TEST(SecondaryStubCache) {
   21062   StubCacheHelper(true);
   21063 }
   21064 
   21065 
   21066 TEST(PrimaryStubCache) {
   21067   StubCacheHelper(false);
   21068 }
   21069 
   21070 
   21071 #ifdef DEBUG
   21072 static int cow_arrays_created_runtime = 0;
   21073 
   21074 
   21075 static int* LookupCounterCOWArrays(const char* name) {
   21076   if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
   21077     return &cow_arrays_created_runtime;
   21078   }
   21079   return NULL;
   21080 }
   21081 #endif
   21082 
   21083 
   21084 TEST(CheckCOWArraysCreatedRuntimeCounter) {
   21085 #ifdef DEBUG
   21086   i::FLAG_native_code_counters = true;
   21087   LocalContext env;
   21088   env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
   21089   v8::HandleScope scope(env->GetIsolate());
   21090   int initial_cow_arrays = cow_arrays_created_runtime;
   21091   CompileRun("var o = [1, 2, 3];");
   21092   CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
   21093   CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
   21094   CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
   21095   CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
   21096   CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
   21097 #endif
   21098 }
   21099 
   21100 
   21101 TEST(StaticGetters) {
   21102   LocalContext context;
   21103   i::Factory* factory = CcTest::i_isolate()->factory();
   21104   v8::Isolate* isolate = CcTest::isolate();
   21105   v8::HandleScope scope(isolate);
   21106   i::Handle<i::Object> undefined_value = factory->undefined_value();
   21107   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
   21108   i::Handle<i::Object> null_value = factory->null_value();
   21109   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
   21110   i::Handle<i::Object> true_value = factory->true_value();
   21111   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
   21112   i::Handle<i::Object> false_value = factory->false_value();
   21113   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
   21114 }
   21115 
   21116 
   21117 UNINITIALIZED_TEST(IsolateEmbedderData) {
   21118   CcTest::DisableAutomaticDispose();
   21119   v8::Isolate* isolate = v8::Isolate::New();
   21120   isolate->Enter();
   21121   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   21122   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21123     CHECK_EQ(NULL, isolate->GetData(slot));
   21124     CHECK_EQ(NULL, i_isolate->GetData(slot));
   21125   }
   21126   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21127     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   21128     isolate->SetData(slot, data);
   21129   }
   21130   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21131     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   21132     CHECK_EQ(data, isolate->GetData(slot));
   21133     CHECK_EQ(data, i_isolate->GetData(slot));
   21134   }
   21135   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21136     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   21137     isolate->SetData(slot, data);
   21138   }
   21139   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21140     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   21141     CHECK_EQ(data, isolate->GetData(slot));
   21142     CHECK_EQ(data, i_isolate->GetData(slot));
   21143   }
   21144   isolate->Exit();
   21145   isolate->Dispose();
   21146 }
   21147 
   21148 
   21149 TEST(StringEmpty) {
   21150   LocalContext context;
   21151   i::Factory* factory = CcTest::i_isolate()->factory();
   21152   v8::Isolate* isolate = CcTest::isolate();
   21153   v8::HandleScope scope(isolate);
   21154   i::Handle<i::Object> empty_string = factory->empty_string();
   21155   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
   21156 }
   21157 
   21158 
   21159 static int instance_checked_getter_count = 0;
   21160 static void InstanceCheckedGetter(
   21161     Local<String> name,
   21162     const v8::PropertyCallbackInfo<v8::Value>& info) {
   21163   CHECK_EQ(name, v8_str("foo"));
   21164   instance_checked_getter_count++;
   21165   info.GetReturnValue().Set(v8_num(11));
   21166 }
   21167 
   21168 
   21169 static int instance_checked_setter_count = 0;
   21170 static void InstanceCheckedSetter(Local<String> name,
   21171                       Local<Value> value,
   21172                       const v8::PropertyCallbackInfo<void>& info) {
   21173   CHECK_EQ(name, v8_str("foo"));
   21174   CHECK_EQ(value, v8_num(23));
   21175   instance_checked_setter_count++;
   21176 }
   21177 
   21178 
   21179 static void CheckInstanceCheckedResult(int getters, int setters,
   21180                                        bool expects_callbacks,
   21181                                        TryCatch* try_catch) {
   21182   if (expects_callbacks) {
   21183     CHECK(!try_catch->HasCaught());
   21184     CHECK_EQ(getters, instance_checked_getter_count);
   21185     CHECK_EQ(setters, instance_checked_setter_count);
   21186   } else {
   21187     CHECK(try_catch->HasCaught());
   21188     CHECK_EQ(0, instance_checked_getter_count);
   21189     CHECK_EQ(0, instance_checked_setter_count);
   21190   }
   21191   try_catch->Reset();
   21192 }
   21193 
   21194 
   21195 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
   21196   instance_checked_getter_count = 0;
   21197   instance_checked_setter_count = 0;
   21198   TryCatch try_catch;
   21199 
   21200   // Test path through generic runtime code.
   21201   CompileRun("obj.foo");
   21202   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
   21203   CompileRun("obj.foo = 23");
   21204   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
   21205 
   21206   // Test path through generated LoadIC and StoredIC.
   21207   CompileRun("function test_get(o) { o.foo; }"
   21208              "test_get(obj);");
   21209   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
   21210   CompileRun("test_get(obj);");
   21211   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
   21212   CompileRun("test_get(obj);");
   21213   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
   21214   CompileRun("function test_set(o) { o.foo = 23; }"
   21215              "test_set(obj);");
   21216   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
   21217   CompileRun("test_set(obj);");
   21218   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
   21219   CompileRun("test_set(obj);");
   21220   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
   21221 
   21222   // Test path through optimized code.
   21223   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
   21224              "test_get(obj);");
   21225   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
   21226   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
   21227              "test_set(obj);");
   21228   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
   21229 
   21230   // Cleanup so that closures start out fresh in next check.
   21231   CompileRun("%DeoptimizeFunction(test_get);"
   21232              "%ClearFunctionTypeFeedback(test_get);"
   21233              "%DeoptimizeFunction(test_set);"
   21234              "%ClearFunctionTypeFeedback(test_set);");
   21235 }
   21236 
   21237 
   21238 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
   21239   v8::internal::FLAG_allow_natives_syntax = true;
   21240   LocalContext context;
   21241   v8::HandleScope scope(context->GetIsolate());
   21242 
   21243   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   21244   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   21245   inst->SetAccessor(v8_str("foo"),
   21246                     InstanceCheckedGetter, InstanceCheckedSetter,
   21247                     Handle<Value>(),
   21248                     v8::DEFAULT,
   21249                     v8::None,
   21250                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   21251   context->Global()->Set(v8_str("f"), templ->GetFunction());
   21252 
   21253   printf("Testing positive ...\n");
   21254   CompileRun("var obj = new f();");
   21255   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   21256   CheckInstanceCheckedAccessors(true);
   21257 
   21258   printf("Testing negative ...\n");
   21259   CompileRun("var obj = {};"
   21260              "obj.__proto__ = new f();");
   21261   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   21262   CheckInstanceCheckedAccessors(false);
   21263 }
   21264 
   21265 
   21266 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
   21267   v8::internal::FLAG_allow_natives_syntax = true;
   21268   LocalContext context;
   21269   v8::HandleScope scope(context->GetIsolate());
   21270 
   21271   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   21272   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   21273   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   21274   inst->SetAccessor(v8_str("foo"),
   21275                     InstanceCheckedGetter, InstanceCheckedSetter,
   21276                     Handle<Value>(),
   21277                     v8::DEFAULT,
   21278                     v8::None,
   21279                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   21280   context->Global()->Set(v8_str("f"), templ->GetFunction());
   21281 
   21282   printf("Testing positive ...\n");
   21283   CompileRun("var obj = new f();");
   21284   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   21285   CheckInstanceCheckedAccessors(true);
   21286 
   21287   printf("Testing negative ...\n");
   21288   CompileRun("var obj = {};"
   21289              "obj.__proto__ = new f();");
   21290   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   21291   CheckInstanceCheckedAccessors(false);
   21292 }
   21293 
   21294 
   21295 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
   21296   v8::internal::FLAG_allow_natives_syntax = true;
   21297   LocalContext context;
   21298   v8::HandleScope scope(context->GetIsolate());
   21299 
   21300   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   21301   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
   21302   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
   21303                      InstanceCheckedSetter, Handle<Value>(), v8::DEFAULT,
   21304                      v8::None,
   21305                      v8::AccessorSignature::New(context->GetIsolate(), templ));
   21306   context->Global()->Set(v8_str("f"), templ->GetFunction());
   21307 
   21308   printf("Testing positive ...\n");
   21309   CompileRun("var obj = new f();");
   21310   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   21311   CheckInstanceCheckedAccessors(true);
   21312 
   21313   printf("Testing negative ...\n");
   21314   CompileRun("var obj = {};"
   21315              "obj.__proto__ = new f();");
   21316   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   21317   CheckInstanceCheckedAccessors(false);
   21318 
   21319   printf("Testing positive with modified prototype chain ...\n");
   21320   CompileRun("var obj = new f();"
   21321              "var pro = {};"
   21322              "pro.__proto__ = obj.__proto__;"
   21323              "obj.__proto__ = pro;");
   21324   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   21325   CheckInstanceCheckedAccessors(true);
   21326 }
   21327 
   21328 
   21329 TEST(TryFinallyMessage) {
   21330   LocalContext context;
   21331   v8::HandleScope scope(context->GetIsolate());
   21332   {
   21333     // Test that the original error message is not lost if there is a
   21334     // recursive call into Javascript is done in the finally block, e.g. to
   21335     // initialize an IC. (crbug.com/129171)
   21336     TryCatch try_catch;
   21337     const char* trigger_ic =
   21338         "try {                      \n"
   21339         "  throw new Error('test'); \n"
   21340         "} finally {                \n"
   21341         "  var x = 0;               \n"
   21342         "  x++;                     \n"  // Trigger an IC initialization here.
   21343         "}                          \n";
   21344     CompileRun(trigger_ic);
   21345     CHECK(try_catch.HasCaught());
   21346     Local<Message> message = try_catch.Message();
   21347     CHECK(!message.IsEmpty());
   21348     CHECK_EQ(2, message->GetLineNumber());
   21349   }
   21350 
   21351   {
   21352     // Test that the original exception message is indeed overwritten if
   21353     // a new error is thrown in the finally block.
   21354     TryCatch try_catch;
   21355     const char* throw_again =
   21356         "try {                       \n"
   21357         "  throw new Error('test');  \n"
   21358         "} finally {                 \n"
   21359         "  var x = 0;                \n"
   21360         "  x++;                      \n"
   21361         "  throw new Error('again'); \n"  // This is the new uncaught error.
   21362         "}                           \n";
   21363     CompileRun(throw_again);
   21364     CHECK(try_catch.HasCaught());
   21365     Local<Message> message = try_catch.Message();
   21366     CHECK(!message.IsEmpty());
   21367     CHECK_EQ(6, message->GetLineNumber());
   21368   }
   21369 }
   21370 
   21371 
   21372 static void Helper137002(bool do_store,
   21373                          bool polymorphic,
   21374                          bool remove_accessor,
   21375                          bool interceptor) {
   21376   LocalContext context;
   21377   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
   21378   if (interceptor) {
   21379     templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
   21380   } else {
   21381     templ->SetAccessor(v8_str("foo"),
   21382                        GetterWhichReturns42,
   21383                        SetterWhichSetsYOnThisTo23);
   21384   }
   21385   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   21386 
   21387   // Turn monomorphic on slow object with native accessor, then turn
   21388   // polymorphic, finally optimize to create negative lookup and fail.
   21389   CompileRun(do_store ?
   21390              "function f(x) { x.foo = void 0; }" :
   21391              "function f(x) { return x.foo; }");
   21392   CompileRun("obj.y = void 0;");
   21393   if (!interceptor) {
   21394     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
   21395   }
   21396   CompileRun("obj.__proto__ = null;"
   21397              "f(obj); f(obj); f(obj);");
   21398   if (polymorphic) {
   21399     CompileRun("f({});");
   21400   }
   21401   CompileRun("obj.y = void 0;"
   21402              "%OptimizeFunctionOnNextCall(f);");
   21403   if (remove_accessor) {
   21404     CompileRun("delete obj.foo;");
   21405   }
   21406   CompileRun("var result = f(obj);");
   21407   if (do_store) {
   21408     CompileRun("result = obj.y;");
   21409   }
   21410   if (remove_accessor && !interceptor) {
   21411     CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
   21412   } else {
   21413     CHECK_EQ(do_store ? 23 : 42,
   21414              context->Global()->Get(v8_str("result"))->Int32Value());
   21415   }
   21416 }
   21417 
   21418 
   21419 THREADED_TEST(Regress137002a) {
   21420   i::FLAG_allow_natives_syntax = true;
   21421   i::FLAG_compilation_cache = false;
   21422   v8::HandleScope scope(CcTest::isolate());
   21423   for (int i = 0; i < 16; i++) {
   21424     Helper137002(i & 8, i & 4, i & 2, i & 1);
   21425   }
   21426 }
   21427 
   21428 
   21429 THREADED_TEST(Regress137002b) {
   21430   i::FLAG_allow_natives_syntax = true;
   21431   LocalContext context;
   21432   v8::Isolate* isolate = context->GetIsolate();
   21433   v8::HandleScope scope(isolate);
   21434   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21435   templ->SetAccessor(v8_str("foo"),
   21436                      GetterWhichReturns42,
   21437                      SetterWhichSetsYOnThisTo23);
   21438   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   21439 
   21440   // Turn monomorphic on slow object with native accessor, then just
   21441   // delete the property and fail.
   21442   CompileRun("function load(x) { return x.foo; }"
   21443              "function store(x) { x.foo = void 0; }"
   21444              "function keyed_load(x, key) { return x[key]; }"
   21445              // Second version of function has a different source (add void 0)
   21446              // so that it does not share code with the first version.  This
   21447              // ensures that the ICs are monomorphic.
   21448              "function load2(x) { void 0; return x.foo; }"
   21449              "function store2(x) { void 0; x.foo = void 0; }"
   21450              "function keyed_load2(x, key) { void 0; return x[key]; }"
   21451 
   21452              "obj.y = void 0;"
   21453              "obj.__proto__ = null;"
   21454              "var subobj = {};"
   21455              "subobj.y = void 0;"
   21456              "subobj.__proto__ = obj;"
   21457              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   21458 
   21459              // Make the ICs monomorphic.
   21460              "load(obj); load(obj);"
   21461              "load2(subobj); load2(subobj);"
   21462              "store(obj); store(obj);"
   21463              "store2(subobj); store2(subobj);"
   21464              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
   21465              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
   21466 
   21467              // Actually test the shiny new ICs and better not crash. This
   21468              // serves as a regression test for issue 142088 as well.
   21469              "load(obj);"
   21470              "load2(subobj);"
   21471              "store(obj);"
   21472              "store2(subobj);"
   21473              "keyed_load(obj, 'foo');"
   21474              "keyed_load2(subobj, 'foo');"
   21475 
   21476              // Delete the accessor.  It better not be called any more now.
   21477              "delete obj.foo;"
   21478              "obj.y = void 0;"
   21479              "subobj.y = void 0;"
   21480 
   21481              "var load_result = load(obj);"
   21482              "var load_result2 = load2(subobj);"
   21483              "var keyed_load_result = keyed_load(obj, 'foo');"
   21484              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
   21485              "store(obj);"
   21486              "store2(subobj);"
   21487              "var y_from_obj = obj.y;"
   21488              "var y_from_subobj = subobj.y;");
   21489   CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
   21490   CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
   21491   CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
   21492   CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
   21493   CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
   21494   CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
   21495 }
   21496 
   21497 
   21498 THREADED_TEST(Regress142088) {
   21499   i::FLAG_allow_natives_syntax = true;
   21500   LocalContext context;
   21501   v8::Isolate* isolate = context->GetIsolate();
   21502   v8::HandleScope scope(isolate);
   21503   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21504   templ->SetAccessor(v8_str("foo"),
   21505                      GetterWhichReturns42,
   21506                      SetterWhichSetsYOnThisTo23);
   21507   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   21508 
   21509   CompileRun("function load(x) { return x.foo; }"
   21510              "var o = Object.create(obj);"
   21511              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   21512              "load(o); load(o); load(o); load(o);");
   21513 }
   21514 
   21515 
   21516 THREADED_TEST(Regress3337) {
   21517   LocalContext context;
   21518   v8::Isolate* isolate = context->GetIsolate();
   21519   v8::HandleScope scope(isolate);
   21520   Local<v8::Object> o1 = Object::New(isolate);
   21521   Local<v8::Object> o2 = Object::New(isolate);
   21522   i::Handle<i::JSObject> io1 = v8::Utils::OpenHandle(*o1);
   21523   i::Handle<i::JSObject> io2 = v8::Utils::OpenHandle(*o2);
   21524   CHECK(io1->map() == io2->map());
   21525   o1->SetIndexedPropertiesToExternalArrayData(
   21526       NULL, v8::kExternalUint32Array, 0);
   21527   o2->SetIndexedPropertiesToExternalArrayData(
   21528       NULL, v8::kExternalUint32Array, 0);
   21529   CHECK(io1->map() == io2->map());
   21530 }
   21531 
   21532 
   21533 THREADED_TEST(Regress137496) {
   21534   i::FLAG_expose_gc = true;
   21535   LocalContext context;
   21536   v8::HandleScope scope(context->GetIsolate());
   21537 
   21538   // Compile a try-finally clause where the finally block causes a GC
   21539   // while there still is a message pending for external reporting.
   21540   TryCatch try_catch;
   21541   try_catch.SetVerbose(true);
   21542   CompileRun("try { throw new Error(); } finally { gc(); }");
   21543   CHECK(try_catch.HasCaught());
   21544 }
   21545 
   21546 
   21547 THREADED_TEST(Regress149912) {
   21548   LocalContext context;
   21549   v8::HandleScope scope(context->GetIsolate());
   21550   Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   21551   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   21552   context->Global()->Set(v8_str("Bug"), templ->GetFunction());
   21553   CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
   21554 }
   21555 
   21556 
   21557 THREADED_TEST(Regress157124) {
   21558   LocalContext context;
   21559   v8::Isolate* isolate = context->GetIsolate();
   21560   v8::HandleScope scope(isolate);
   21561   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21562   Local<Object> obj = templ->NewInstance();
   21563   obj->GetIdentityHash();
   21564   obj->DeleteHiddenValue(v8_str("Bug"));
   21565 }
   21566 
   21567 
   21568 THREADED_TEST(Regress2535) {
   21569   LocalContext context;
   21570   v8::HandleScope scope(context->GetIsolate());
   21571   Local<Value> set_value = CompileRun("new Set();");
   21572   Local<Object> set_object(Local<Object>::Cast(set_value));
   21573   CHECK_EQ(0, set_object->InternalFieldCount());
   21574   Local<Value> map_value = CompileRun("new Map();");
   21575   Local<Object> map_object(Local<Object>::Cast(map_value));
   21576   CHECK_EQ(0, map_object->InternalFieldCount());
   21577 }
   21578 
   21579 
   21580 THREADED_TEST(Regress2746) {
   21581   LocalContext context;
   21582   v8::Isolate* isolate = context->GetIsolate();
   21583   v8::HandleScope scope(isolate);
   21584   Local<Object> obj = Object::New(isolate);
   21585   Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
   21586   obj->SetHiddenValue(key, v8::Undefined(isolate));
   21587   Local<Value> value = obj->GetHiddenValue(key);
   21588   CHECK(!value.IsEmpty());
   21589   CHECK(value->IsUndefined());
   21590 }
   21591 
   21592 
   21593 THREADED_TEST(Regress260106) {
   21594   LocalContext context;
   21595   v8::Isolate* isolate = context->GetIsolate();
   21596   v8::HandleScope scope(isolate);
   21597   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
   21598                                                         DummyCallHandler);
   21599   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
   21600   Local<Function> function = templ->GetFunction();
   21601   CHECK(!function.IsEmpty());
   21602   CHECK(function->IsFunction());
   21603 }
   21604 
   21605 
   21606 THREADED_TEST(JSONParseObject) {
   21607   LocalContext context;
   21608   HandleScope scope(context->GetIsolate());
   21609   Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
   21610   Handle<Object> global = context->Global();
   21611   global->Set(v8_str("obj"), obj);
   21612   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
   21613 }
   21614 
   21615 
   21616 THREADED_TEST(JSONParseNumber) {
   21617   LocalContext context;
   21618   HandleScope scope(context->GetIsolate());
   21619   Local<Value> obj = v8::JSON::Parse(v8_str("42"));
   21620   Handle<Object> global = context->Global();
   21621   global->Set(v8_str("obj"), obj);
   21622   ExpectString("JSON.stringify(obj)", "42");
   21623 }
   21624 
   21625 
   21626 #if V8_OS_POSIX && !V8_OS_NACL
   21627 class ThreadInterruptTest {
   21628  public:
   21629   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
   21630   ~ThreadInterruptTest() {}
   21631 
   21632   void RunTest() {
   21633     InterruptThread i_thread(this);
   21634     i_thread.Start();
   21635 
   21636     sem_.Wait();
   21637     CHECK_EQ(kExpectedValue, sem_value_);
   21638   }
   21639 
   21640  private:
   21641   static const int kExpectedValue = 1;
   21642 
   21643   class InterruptThread : public v8::base::Thread {
   21644    public:
   21645     explicit InterruptThread(ThreadInterruptTest* test)
   21646         : Thread(Options("InterruptThread")), test_(test) {}
   21647 
   21648     virtual void Run() {
   21649       struct sigaction action;
   21650 
   21651       // Ensure that we'll enter waiting condition
   21652       v8::base::OS::Sleep(100);
   21653 
   21654       // Setup signal handler
   21655       memset(&action, 0, sizeof(action));
   21656       action.sa_handler = SignalHandler;
   21657       sigaction(SIGCHLD, &action, NULL);
   21658 
   21659       // Send signal
   21660       kill(getpid(), SIGCHLD);
   21661 
   21662       // Ensure that if wait has returned because of error
   21663       v8::base::OS::Sleep(100);
   21664 
   21665       // Set value and signal semaphore
   21666       test_->sem_value_ = 1;
   21667       test_->sem_.Signal();
   21668     }
   21669 
   21670     static void SignalHandler(int signal) {
   21671     }
   21672 
   21673    private:
   21674      ThreadInterruptTest* test_;
   21675   };
   21676 
   21677   v8::base::Semaphore sem_;
   21678   volatile int sem_value_;
   21679 };
   21680 
   21681 
   21682 THREADED_TEST(SemaphoreInterruption) {
   21683   ThreadInterruptTest().RunTest();
   21684 }
   21685 
   21686 
   21687 #endif  // V8_OS_POSIX
   21688 
   21689 
   21690 static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
   21691                                      Local<Value> name,
   21692                                      v8::AccessType type,
   21693                                      Local<Value> data) {
   21694   i::PrintF("Named access blocked.\n");
   21695   return false;
   21696 }
   21697 
   21698 
   21699 static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
   21700                                      uint32_t key,
   21701                                      v8::AccessType type,
   21702                                      Local<Value> data) {
   21703   i::PrintF("Indexed access blocked.\n");
   21704   return false;
   21705 }
   21706 
   21707 
   21708 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21709   CHECK(false);
   21710 }
   21711 
   21712 
   21713 TEST(JSONStringifyAccessCheck) {
   21714   v8::V8::Initialize();
   21715   v8::Isolate* isolate = CcTest::isolate();
   21716   v8::HandleScope scope(isolate);
   21717 
   21718   // Create an ObjectTemplate for global objects and install access
   21719   // check callbacks that will block access.
   21720   v8::Handle<v8::ObjectTemplate> global_template =
   21721       v8::ObjectTemplate::New(isolate);
   21722   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
   21723                                            IndexAccessAlwaysBlocked);
   21724 
   21725   // Create a context and set an x property on it's global object.
   21726   LocalContext context0(NULL, global_template);
   21727   v8::Handle<v8::Object> global0 = context0->Global();
   21728   global0->Set(v8_str("x"), v8_num(42));
   21729   ExpectString("JSON.stringify(this)", "{\"x\":42}");
   21730 
   21731   for (int i = 0; i < 2; i++) {
   21732     if (i == 1) {
   21733       // Install a toJSON function on the second run.
   21734       v8::Handle<v8::FunctionTemplate> toJSON =
   21735           v8::FunctionTemplate::New(isolate, UnreachableCallback);
   21736 
   21737       global0->Set(v8_str("toJSON"), toJSON->GetFunction());
   21738     }
   21739     // Create a context with a different security token so that the
   21740     // failed access check callback will be called on each access.
   21741     LocalContext context1(NULL, global_template);
   21742     context1->Global()->Set(v8_str("other"), global0);
   21743 
   21744     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
   21745     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
   21746     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
   21747 
   21748     v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
   21749     array->Set(0, v8_str("a"));
   21750     array->Set(1, v8_str("b"));
   21751     context1->Global()->Set(v8_str("array"), array);
   21752     ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
   21753     array->TurnOnAccessCheck();
   21754     CHECK(CompileRun("JSON.stringify(array)").IsEmpty());
   21755     CHECK(CompileRun("JSON.stringify([array])").IsEmpty());
   21756     CHECK(CompileRun("JSON.stringify({'a' : array})").IsEmpty());
   21757   }
   21758 }
   21759 
   21760 
   21761 bool access_check_fail_thrown = false;
   21762 bool catch_callback_called = false;
   21763 
   21764 
   21765 // Failed access check callback that performs a GC on each invocation.
   21766 void FailedAccessCheckThrows(Local<v8::Object> target,
   21767                              v8::AccessType type,
   21768                              Local<v8::Value> data) {
   21769   access_check_fail_thrown = true;
   21770   i::PrintF("Access check failed. Error thrown.\n");
   21771   CcTest::isolate()->ThrowException(
   21772       v8::Exception::Error(v8_str("cross context")));
   21773 }
   21774 
   21775 
   21776 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21777   for (int i = 0; i < args.Length(); i++) {
   21778     i::PrintF("%s\n", *String::Utf8Value(args[i]));
   21779   }
   21780   catch_callback_called = true;
   21781 }
   21782 
   21783 
   21784 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21785   args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
   21786 }
   21787 
   21788 
   21789 void CheckCorrectThrow(const char* script) {
   21790   // Test that the script, when wrapped into a try-catch, triggers the catch
   21791   // clause due to failed access check throwing an exception.
   21792   // The subsequent try-catch should run without any exception.
   21793   access_check_fail_thrown = false;
   21794   catch_callback_called = false;
   21795   i::ScopedVector<char> source(1024);
   21796   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
   21797   CompileRun(source.start());
   21798   CHECK(access_check_fail_thrown);
   21799   CHECK(catch_callback_called);
   21800 
   21801   access_check_fail_thrown = false;
   21802   catch_callback_called = false;
   21803   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
   21804   CHECK(!access_check_fail_thrown);
   21805   CHECK(!catch_callback_called);
   21806 }
   21807 
   21808 
   21809 TEST(AccessCheckThrows) {
   21810   i::FLAG_allow_natives_syntax = true;
   21811   v8::V8::Initialize();
   21812   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   21813   v8::Isolate* isolate = CcTest::isolate();
   21814   v8::HandleScope scope(isolate);
   21815 
   21816   // Create an ObjectTemplate for global objects and install access
   21817   // check callbacks that will block access.
   21818   v8::Handle<v8::ObjectTemplate> global_template =
   21819       v8::ObjectTemplate::New(isolate);
   21820   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
   21821                                            IndexAccessAlwaysBlocked);
   21822 
   21823   // Create a context and set an x property on it's global object.
   21824   LocalContext context0(NULL, global_template);
   21825   v8::Handle<v8::Object> global0 = context0->Global();
   21826 
   21827   // Create a context with a different security token so that the
   21828   // failed access check callback will be called on each access.
   21829   LocalContext context1(NULL, global_template);
   21830   context1->Global()->Set(v8_str("other"), global0);
   21831 
   21832   v8::Handle<v8::FunctionTemplate> catcher_fun =
   21833       v8::FunctionTemplate::New(isolate, CatcherCallback);
   21834   context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
   21835 
   21836   v8::Handle<v8::FunctionTemplate> has_own_property_fun =
   21837       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
   21838   context1->Global()->Set(v8_str("has_own_property"),
   21839                           has_own_property_fun->GetFunction());
   21840 
   21841   { v8::TryCatch try_catch;
   21842     access_check_fail_thrown = false;
   21843     CompileRun("other.x;");
   21844     CHECK(access_check_fail_thrown);
   21845     CHECK(try_catch.HasCaught());
   21846   }
   21847 
   21848   CheckCorrectThrow("other.x");
   21849   CheckCorrectThrow("other[1]");
   21850   CheckCorrectThrow("JSON.stringify(other)");
   21851   CheckCorrectThrow("has_own_property(other, 'x')");
   21852   CheckCorrectThrow("%GetProperty(other, 'x')");
   21853   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
   21854   CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
   21855   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
   21856   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
   21857   CheckCorrectThrow("%HasOwnProperty(other, 'x')");
   21858   CheckCorrectThrow("%HasProperty(other, 'x')");
   21859   CheckCorrectThrow("%HasElement(other, 1)");
   21860   CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
   21861   CheckCorrectThrow("%GetPropertyNames(other)");
   21862   // PROPERTY_ATTRIBUTES_NONE = 0
   21863   CheckCorrectThrow("%GetOwnPropertyNames(other, 0)");
   21864   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
   21865                         "other, 'x', null, null, 1)");
   21866 
   21867   // Reset the failed access check callback so it does not influence
   21868   // the other tests.
   21869   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
   21870 }
   21871 
   21872 
   21873 THREADED_TEST(Regress256330) {
   21874   i::FLAG_allow_natives_syntax = true;
   21875   LocalContext context;
   21876   v8::HandleScope scope(context->GetIsolate());
   21877   Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   21878   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   21879   context->Global()->Set(v8_str("Bug"), templ->GetFunction());
   21880   CompileRun("\"use strict\"; var o = new Bug;"
   21881              "function f(o) { o.x = 10; };"
   21882              "f(o); f(o); f(o);"
   21883              "%OptimizeFunctionOnNextCall(f);"
   21884              "f(o);");
   21885   ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
   21886 }
   21887 
   21888 
   21889 THREADED_TEST(CrankshaftInterceptorSetter) {
   21890   i::FLAG_allow_natives_syntax = true;
   21891   v8::HandleScope scope(CcTest::isolate());
   21892   Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
   21893   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   21894   LocalContext env;
   21895   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   21896   CompileRun("var obj = new Obj;"
   21897              // Initialize fields to avoid transitions later.
   21898              "obj.age = 0;"
   21899              "obj.accessor_age = 42;"
   21900              "function setter(i) { this.accessor_age = i; };"
   21901              "function getter() { return this.accessor_age; };"
   21902              "function setAge(i) { obj.age = i; };"
   21903              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   21904              "setAge(1);"
   21905              "setAge(2);"
   21906              "setAge(3);"
   21907              "%OptimizeFunctionOnNextCall(setAge);"
   21908              "setAge(4);");
   21909   // All stores went through the interceptor.
   21910   ExpectInt32("obj.interceptor_age", 4);
   21911   ExpectInt32("obj.accessor_age", 42);
   21912 }
   21913 
   21914 
   21915 THREADED_TEST(CrankshaftInterceptorGetter) {
   21916   i::FLAG_allow_natives_syntax = true;
   21917   v8::HandleScope scope(CcTest::isolate());
   21918   Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
   21919   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   21920   LocalContext env;
   21921   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   21922   CompileRun("var obj = new Obj;"
   21923              // Initialize fields to avoid transitions later.
   21924              "obj.age = 1;"
   21925              "obj.accessor_age = 42;"
   21926              "function getter() { return this.accessor_age; };"
   21927              "function getAge() { return obj.interceptor_age; };"
   21928              "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
   21929              "getAge();"
   21930              "getAge();"
   21931              "getAge();"
   21932              "%OptimizeFunctionOnNextCall(getAge);");
   21933   // Access through interceptor.
   21934   ExpectInt32("getAge()", 1);
   21935 }
   21936 
   21937 
   21938 THREADED_TEST(CrankshaftInterceptorFieldRead) {
   21939   i::FLAG_allow_natives_syntax = true;
   21940   v8::HandleScope scope(CcTest::isolate());
   21941   Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
   21942   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   21943   LocalContext env;
   21944   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   21945   CompileRun("var obj = new Obj;"
   21946              "obj.__proto__.interceptor_age = 42;"
   21947              "obj.age = 100;"
   21948              "function getAge() { return obj.interceptor_age; };");
   21949   ExpectInt32("getAge();", 100);
   21950   ExpectInt32("getAge();", 100);
   21951   ExpectInt32("getAge();", 100);
   21952   CompileRun("%OptimizeFunctionOnNextCall(getAge);");
   21953   // Access through interceptor.
   21954   ExpectInt32("getAge();", 100);
   21955 }
   21956 
   21957 
   21958 THREADED_TEST(CrankshaftInterceptorFieldWrite) {
   21959   i::FLAG_allow_natives_syntax = true;
   21960   v8::HandleScope scope(CcTest::isolate());
   21961   Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
   21962   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   21963   LocalContext env;
   21964   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   21965   CompileRun("var obj = new Obj;"
   21966              "obj.age = 100000;"
   21967              "function setAge(i) { obj.age = i };"
   21968              "setAge(100);"
   21969              "setAge(101);"
   21970              "setAge(102);"
   21971              "%OptimizeFunctionOnNextCall(setAge);"
   21972              "setAge(103);");
   21973   ExpectInt32("obj.age", 100000);
   21974   ExpectInt32("obj.interceptor_age", 103);
   21975 }
   21976 
   21977 
   21978 class RequestInterruptTestBase {
   21979  public:
   21980   RequestInterruptTestBase()
   21981       : env_(),
   21982         isolate_(env_->GetIsolate()),
   21983         sem_(0),
   21984         warmup_(20000),
   21985         should_continue_(true) {
   21986   }
   21987 
   21988   virtual ~RequestInterruptTestBase() { }
   21989 
   21990   virtual void StartInterruptThread() = 0;
   21991 
   21992   virtual void TestBody() = 0;
   21993 
   21994   void RunTest() {
   21995     StartInterruptThread();
   21996 
   21997     v8::HandleScope handle_scope(isolate_);
   21998 
   21999     TestBody();
   22000 
   22001     isolate_->ClearInterrupt();
   22002 
   22003     // Verify we arrived here because interruptor was called
   22004     // not due to a bug causing us to exit the loop too early.
   22005     CHECK(!should_continue());
   22006   }
   22007 
   22008   void WakeUpInterruptor() {
   22009     sem_.Signal();
   22010   }
   22011 
   22012   bool should_continue() const { return should_continue_; }
   22013 
   22014   bool ShouldContinue() {
   22015     if (warmup_ > 0) {
   22016       if (--warmup_ == 0) {
   22017         WakeUpInterruptor();
   22018       }
   22019     }
   22020 
   22021     return should_continue_;
   22022   }
   22023 
   22024   static void ShouldContinueCallback(
   22025       const v8::FunctionCallbackInfo<Value>& info) {
   22026     RequestInterruptTestBase* test =
   22027         reinterpret_cast<RequestInterruptTestBase*>(
   22028             info.Data().As<v8::External>()->Value());
   22029     info.GetReturnValue().Set(test->ShouldContinue());
   22030   }
   22031 
   22032   LocalContext env_;
   22033   v8::Isolate* isolate_;
   22034   v8::base::Semaphore sem_;
   22035   int warmup_;
   22036   bool should_continue_;
   22037 };
   22038 
   22039 
   22040 class RequestInterruptTestBaseWithSimpleInterrupt
   22041     : public RequestInterruptTestBase {
   22042  public:
   22043   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
   22044 
   22045   virtual void StartInterruptThread() {
   22046     i_thread.Start();
   22047   }
   22048 
   22049  private:
   22050   class InterruptThread : public v8::base::Thread {
   22051    public:
   22052     explicit InterruptThread(RequestInterruptTestBase* test)
   22053         : Thread(Options("RequestInterruptTest")), test_(test) {}
   22054 
   22055     virtual void Run() {
   22056       test_->sem_.Wait();
   22057       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   22058     }
   22059 
   22060     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   22061       reinterpret_cast<RequestInterruptTestBase*>(data)->
   22062           should_continue_ = false;
   22063     }
   22064 
   22065    private:
   22066      RequestInterruptTestBase* test_;
   22067   };
   22068 
   22069   InterruptThread i_thread;
   22070 };
   22071 
   22072 
   22073 class RequestInterruptTestWithFunctionCall
   22074     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22075  public:
   22076   virtual void TestBody() {
   22077     Local<Function> func = Function::New(
   22078         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
   22079     env_->Global()->Set(v8_str("ShouldContinue"), func);
   22080 
   22081     CompileRun("while (ShouldContinue()) { }");
   22082   }
   22083 };
   22084 
   22085 
   22086 class RequestInterruptTestWithMethodCall
   22087     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22088  public:
   22089   virtual void TestBody() {
   22090     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22091     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   22092     proto->Set(v8_str("shouldContinue"), Function::New(
   22093         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
   22094     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
   22095 
   22096     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   22097   }
   22098 };
   22099 
   22100 
   22101 class RequestInterruptTestWithAccessor
   22102     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22103  public:
   22104   virtual void TestBody() {
   22105     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22106     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   22107     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
   22108         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
   22109     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
   22110 
   22111     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   22112   }
   22113 };
   22114 
   22115 
   22116 class RequestInterruptTestWithNativeAccessor
   22117     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22118  public:
   22119   virtual void TestBody() {
   22120     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22121     t->InstanceTemplate()->SetNativeDataProperty(
   22122         v8_str("shouldContinue"),
   22123         &ShouldContinueNativeGetter,
   22124         NULL,
   22125         v8::External::New(isolate_, this));
   22126     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
   22127 
   22128     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   22129   }
   22130 
   22131  private:
   22132   static void ShouldContinueNativeGetter(
   22133       Local<String> property,
   22134       const v8::PropertyCallbackInfo<v8::Value>& info) {
   22135     RequestInterruptTestBase* test =
   22136         reinterpret_cast<RequestInterruptTestBase*>(
   22137             info.Data().As<v8::External>()->Value());
   22138     info.GetReturnValue().Set(test->ShouldContinue());
   22139   }
   22140 };
   22141 
   22142 
   22143 class RequestInterruptTestWithMethodCallAndInterceptor
   22144     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22145  public:
   22146   virtual void TestBody() {
   22147     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22148     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   22149     proto->Set(v8_str("shouldContinue"), Function::New(
   22150         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
   22151     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
   22152     instance_template->SetNamedPropertyHandler(EmptyInterceptor);
   22153 
   22154     env_->Global()->Set(v8_str("Klass"), t->GetFunction());
   22155 
   22156     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   22157   }
   22158 
   22159  private:
   22160   static void EmptyInterceptor(
   22161       Local<String> property,
   22162       const v8::PropertyCallbackInfo<v8::Value>& info) {
   22163   }
   22164 };
   22165 
   22166 
   22167 class RequestInterruptTestWithMathAbs
   22168     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22169  public:
   22170   virtual void TestBody() {
   22171     env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
   22172         isolate_,
   22173         WakeUpInterruptorCallback,
   22174         v8::External::New(isolate_, this)));
   22175 
   22176     env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
   22177         isolate_,
   22178         ShouldContinueCallback,
   22179         v8::External::New(isolate_, this)));
   22180 
   22181     i::FLAG_allow_natives_syntax = true;
   22182     CompileRun("function loopish(o) {"
   22183                "  var pre = 10;"
   22184                "  while (o.abs(1) > 0) {"
   22185                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
   22186                "    if (pre > 0) {"
   22187                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
   22188                "    }"
   22189                "  }"
   22190                "}"
   22191                "var i = 50;"
   22192                "var obj = {abs: function () { return i-- }, x: null};"
   22193                "delete obj.x;"
   22194                "loopish(obj);"
   22195                "%OptimizeFunctionOnNextCall(loopish);"
   22196                "loopish(Math);");
   22197 
   22198     i::FLAG_allow_natives_syntax = false;
   22199   }
   22200 
   22201  private:
   22202   static void WakeUpInterruptorCallback(
   22203       const v8::FunctionCallbackInfo<Value>& info) {
   22204     if (!info[0]->BooleanValue()) return;
   22205 
   22206     RequestInterruptTestBase* test =
   22207         reinterpret_cast<RequestInterruptTestBase*>(
   22208             info.Data().As<v8::External>()->Value());
   22209     test->WakeUpInterruptor();
   22210   }
   22211 
   22212   static void ShouldContinueCallback(
   22213       const v8::FunctionCallbackInfo<Value>& info) {
   22214     RequestInterruptTestBase* test =
   22215         reinterpret_cast<RequestInterruptTestBase*>(
   22216             info.Data().As<v8::External>()->Value());
   22217     info.GetReturnValue().Set(test->should_continue());
   22218   }
   22219 };
   22220 
   22221 
   22222 TEST(RequestInterruptTestWithFunctionCall) {
   22223   RequestInterruptTestWithFunctionCall().RunTest();
   22224 }
   22225 
   22226 
   22227 TEST(RequestInterruptTestWithMethodCall) {
   22228   RequestInterruptTestWithMethodCall().RunTest();
   22229 }
   22230 
   22231 
   22232 TEST(RequestInterruptTestWithAccessor) {
   22233   RequestInterruptTestWithAccessor().RunTest();
   22234 }
   22235 
   22236 
   22237 TEST(RequestInterruptTestWithNativeAccessor) {
   22238   RequestInterruptTestWithNativeAccessor().RunTest();
   22239 }
   22240 
   22241 
   22242 TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
   22243   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
   22244 }
   22245 
   22246 
   22247 TEST(RequestInterruptTestWithMathAbs) {
   22248   RequestInterruptTestWithMathAbs().RunTest();
   22249 }
   22250 
   22251 
   22252 class ClearInterruptFromAnotherThread
   22253     : public RequestInterruptTestBase {
   22254  public:
   22255   ClearInterruptFromAnotherThread() : i_thread(this), sem2_(0) { }
   22256 
   22257   virtual void StartInterruptThread() {
   22258     i_thread.Start();
   22259   }
   22260 
   22261   virtual void TestBody() {
   22262     Local<Function> func = Function::New(
   22263         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
   22264     env_->Global()->Set(v8_str("ShouldContinue"), func);
   22265 
   22266     CompileRun("while (ShouldContinue()) { }");
   22267   }
   22268 
   22269  private:
   22270   class InterruptThread : public v8::base::Thread {
   22271    public:
   22272     explicit InterruptThread(ClearInterruptFromAnotherThread* test)
   22273         : Thread(Options("RequestInterruptTest")), test_(test) {}
   22274 
   22275     virtual void Run() {
   22276       test_->sem_.Wait();
   22277       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   22278       test_->sem_.Wait();
   22279       test_->isolate_->ClearInterrupt();
   22280       test_->sem2_.Signal();
   22281     }
   22282 
   22283     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   22284       ClearInterruptFromAnotherThread* test =
   22285           reinterpret_cast<ClearInterruptFromAnotherThread*>(data);
   22286       test->sem_.Signal();
   22287       bool success = test->sem2_.WaitFor(v8::base::TimeDelta::FromSeconds(2));
   22288       // Crash instead of timeout to make this failure more prominent.
   22289       CHECK(success);
   22290       test->should_continue_ = false;
   22291     }
   22292 
   22293    private:
   22294      ClearInterruptFromAnotherThread* test_;
   22295   };
   22296 
   22297   InterruptThread i_thread;
   22298   v8::base::Semaphore sem2_;
   22299 };
   22300 
   22301 
   22302 TEST(ClearInterruptFromAnotherThread) {
   22303   ClearInterruptFromAnotherThread().RunTest();
   22304 }
   22305 
   22306 
   22307 static Local<Value> function_new_expected_env;
   22308 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
   22309   CHECK_EQ(function_new_expected_env, info.Data());
   22310   info.GetReturnValue().Set(17);
   22311 }
   22312 
   22313 
   22314 THREADED_TEST(FunctionNew) {
   22315   LocalContext env;
   22316   v8::Isolate* isolate = env->GetIsolate();
   22317   v8::HandleScope scope(isolate);
   22318   Local<Object> data = v8::Object::New(isolate);
   22319   function_new_expected_env = data;
   22320   Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
   22321   env->Global()->Set(v8_str("func"), func);
   22322   Local<Value> result = CompileRun("func();");
   22323   CHECK_EQ(v8::Integer::New(isolate, 17), result);
   22324   // Verify function not cached
   22325   int serial_number =
   22326       i::Smi::cast(v8::Utils::OpenHandle(*func)
   22327           ->shared()->get_api_func_data()->serial_number())->value();
   22328   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   22329   i::Handle<i::JSObject> cache(i_isolate->native_context()->function_cache());
   22330   i::Handle<i::Object> elm =
   22331       i::Object::GetElement(i_isolate, cache, serial_number).ToHandleChecked();
   22332   CHECK(elm->IsUndefined());
   22333   // Verify that each Function::New creates a new function instance
   22334   Local<Object> data2 = v8::Object::New(isolate);
   22335   function_new_expected_env = data2;
   22336   Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
   22337   CHECK(!func2->IsNull());
   22338   CHECK_NE(func, func2);
   22339   env->Global()->Set(v8_str("func2"), func2);
   22340   Local<Value> result2 = CompileRun("func2();");
   22341   CHECK_EQ(v8::Integer::New(isolate, 17), result2);
   22342 }
   22343 
   22344 
   22345 TEST(EscapeableHandleScope) {
   22346   HandleScope outer_scope(CcTest::isolate());
   22347   LocalContext context;
   22348   const int runs = 10;
   22349   Local<String> values[runs];
   22350   for (int i = 0; i < runs; i++) {
   22351     v8::EscapableHandleScope inner_scope(CcTest::isolate());
   22352     Local<String> value;
   22353     if (i != 0) value = v8_str("escape value");
   22354     values[i] = inner_scope.Escape(value);
   22355   }
   22356   for (int i = 0; i < runs; i++) {
   22357     Local<String> expected;
   22358     if (i != 0) {
   22359       CHECK_EQ(v8_str("escape value"), values[i]);
   22360     } else {
   22361       CHECK(values[i].IsEmpty());
   22362     }
   22363   }
   22364 }
   22365 
   22366 
   22367 static void SetterWhichExpectsThisAndHolderToDiffer(
   22368     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
   22369   CHECK(info.Holder() != info.This());
   22370 }
   22371 
   22372 
   22373 TEST(Regress239669) {
   22374   LocalContext context;
   22375   v8::Isolate* isolate = context->GetIsolate();
   22376   v8::HandleScope scope(isolate);
   22377   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22378   templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
   22379   context->Global()->Set(v8_str("P"), templ->NewInstance());
   22380   CompileRun(
   22381       "function C1() {"
   22382       "  this.x = 23;"
   22383       "};"
   22384       "C1.prototype = P;"
   22385       "for (var i = 0; i < 4; i++ ) {"
   22386       "  new C1();"
   22387       "}");
   22388 }
   22389 
   22390 
   22391 class ApiCallOptimizationChecker {
   22392  private:
   22393   static Local<Object> data;
   22394   static Local<Object> receiver;
   22395   static Local<Object> holder;
   22396   static Local<Object> callee;
   22397   static int count;
   22398 
   22399   static void OptimizationCallback(
   22400       const v8::FunctionCallbackInfo<v8::Value>& info) {
   22401     CHECK(callee == info.Callee());
   22402     CHECK(data == info.Data());
   22403     CHECK(receiver == info.This());
   22404     if (info.Length() == 1) {
   22405       CHECK_EQ(v8_num(1), info[0]);
   22406     }
   22407     CHECK(holder == info.Holder());
   22408     count++;
   22409     info.GetReturnValue().Set(v8_str("returned"));
   22410   }
   22411 
   22412  public:
   22413   enum SignatureType {
   22414     kNoSignature,
   22415     kSignatureOnReceiver,
   22416     kSignatureOnPrototype
   22417   };
   22418 
   22419   void RunAll() {
   22420     SignatureType signature_types[] =
   22421       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
   22422     for (unsigned i = 0; i < arraysize(signature_types); i++) {
   22423       SignatureType signature_type = signature_types[i];
   22424       for (int j = 0; j < 2; j++) {
   22425         bool global = j == 0;
   22426         int key = signature_type +
   22427             arraysize(signature_types) * (global ? 1 : 0);
   22428         Run(signature_type, global, key);
   22429       }
   22430     }
   22431   }
   22432 
   22433   void Run(SignatureType signature_type, bool global, int key) {
   22434     v8::Isolate* isolate = CcTest::isolate();
   22435     v8::HandleScope scope(isolate);
   22436     // Build a template for signature checks.
   22437     Local<v8::ObjectTemplate> signature_template;
   22438     Local<v8::Signature> signature;
   22439     {
   22440       Local<v8::FunctionTemplate> parent_template =
   22441         FunctionTemplate::New(isolate);
   22442       parent_template->SetHiddenPrototype(true);
   22443       Local<v8::FunctionTemplate> function_template
   22444           = FunctionTemplate::New(isolate);
   22445       function_template->Inherit(parent_template);
   22446       switch (signature_type) {
   22447         case kNoSignature:
   22448           break;
   22449         case kSignatureOnReceiver:
   22450           signature = v8::Signature::New(isolate, function_template);
   22451           break;
   22452         case kSignatureOnPrototype:
   22453           signature = v8::Signature::New(isolate, parent_template);
   22454           break;
   22455       }
   22456       signature_template = function_template->InstanceTemplate();
   22457     }
   22458     // Global object must pass checks.
   22459     Local<v8::Context> context =
   22460         v8::Context::New(isolate, NULL, signature_template);
   22461     v8::Context::Scope context_scope(context);
   22462     // Install regular object that can pass signature checks.
   22463     Local<Object> function_receiver = signature_template->NewInstance();
   22464     context->Global()->Set(v8_str("function_receiver"), function_receiver);
   22465     // Get the holder objects.
   22466     Local<Object> inner_global =
   22467         Local<Object>::Cast(context->Global()->GetPrototype());
   22468     // Install functions on hidden prototype object if there is one.
   22469     data = Object::New(isolate);
   22470     Local<FunctionTemplate> function_template = FunctionTemplate::New(
   22471         isolate, OptimizationCallback, data, signature);
   22472     Local<Function> function = function_template->GetFunction();
   22473     Local<Object> global_holder = inner_global;
   22474     Local<Object> function_holder = function_receiver;
   22475     if (signature_type == kSignatureOnPrototype) {
   22476       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
   22477       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
   22478     }
   22479     global_holder->Set(v8_str("g_f"), function);
   22480     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
   22481     function_holder->Set(v8_str("f"), function);
   22482     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
   22483     // Initialize expected values.
   22484     callee = function;
   22485     count = 0;
   22486     if (global) {
   22487       receiver = context->Global();
   22488       holder = inner_global;
   22489     } else {
   22490       holder = function_receiver;
   22491       // If not using a signature, add something else to the prototype chain
   22492       // to test the case that holder != receiver
   22493       if (signature_type == kNoSignature) {
   22494         receiver = Local<Object>::Cast(CompileRun(
   22495             "var receiver_subclass = {};\n"
   22496             "receiver_subclass.__proto__ = function_receiver;\n"
   22497             "receiver_subclass"));
   22498       } else {
   22499         receiver = Local<Object>::Cast(CompileRun(
   22500           "var receiver_subclass = function_receiver;\n"
   22501           "receiver_subclass"));
   22502       }
   22503     }
   22504     // With no signature, the holder is not set.
   22505     if (signature_type == kNoSignature) holder = receiver;
   22506     // build wrap_function
   22507     i::ScopedVector<char> wrap_function(200);
   22508     if (global) {
   22509       i::SNPrintF(
   22510           wrap_function,
   22511           "function wrap_f_%d() { var f = g_f; return f(); }\n"
   22512           "function wrap_get_%d() { return this.g_acc; }\n"
   22513           "function wrap_set_%d() { return this.g_acc = 1; }\n",
   22514           key, key, key);
   22515     } else {
   22516       i::SNPrintF(
   22517           wrap_function,
   22518           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
   22519           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
   22520           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
   22521           key, key, key);
   22522     }
   22523     // build source string
   22524     i::ScopedVector<char> source(1000);
   22525     i::SNPrintF(
   22526         source,
   22527         "%s\n"  // wrap functions
   22528         "function wrap_f() { return wrap_f_%d(); }\n"
   22529         "function wrap_get() { return wrap_get_%d(); }\n"
   22530         "function wrap_set() { return wrap_set_%d(); }\n"
   22531         "check = function(returned) {\n"
   22532         "  if (returned !== 'returned') { throw returned; }\n"
   22533         "}\n"
   22534         "\n"
   22535         "check(wrap_f());\n"
   22536         "check(wrap_f());\n"
   22537         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
   22538         "check(wrap_f());\n"
   22539         "\n"
   22540         "check(wrap_get());\n"
   22541         "check(wrap_get());\n"
   22542         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
   22543         "check(wrap_get());\n"
   22544         "\n"
   22545         "check = function(returned) {\n"
   22546         "  if (returned !== 1) { throw returned; }\n"
   22547         "}\n"
   22548         "check(wrap_set());\n"
   22549         "check(wrap_set());\n"
   22550         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
   22551         "check(wrap_set());\n",
   22552         wrap_function.start(), key, key, key, key, key, key);
   22553     v8::TryCatch try_catch;
   22554     CompileRun(source.start());
   22555     DCHECK(!try_catch.HasCaught());
   22556     CHECK_EQ(9, count);
   22557   }
   22558 };
   22559 
   22560 
   22561 Local<Object> ApiCallOptimizationChecker::data;
   22562 Local<Object> ApiCallOptimizationChecker::receiver;
   22563 Local<Object> ApiCallOptimizationChecker::holder;
   22564 Local<Object> ApiCallOptimizationChecker::callee;
   22565 int ApiCallOptimizationChecker::count = 0;
   22566 
   22567 
   22568 TEST(TestFunctionCallOptimization) {
   22569   i::FLAG_allow_natives_syntax = true;
   22570   ApiCallOptimizationChecker checker;
   22571   checker.RunAll();
   22572 }
   22573 
   22574 
   22575 static const char* last_event_message;
   22576 static int last_event_status;
   22577 void StoringEventLoggerCallback(const char* message, int status) {
   22578     last_event_message = message;
   22579     last_event_status = status;
   22580 }
   22581 
   22582 
   22583 TEST(EventLogging) {
   22584   v8::Isolate* isolate = CcTest::isolate();
   22585   isolate->SetEventLogger(StoringEventLoggerCallback);
   22586   v8::internal::HistogramTimer histogramTimer(
   22587       "V8.Test", 0, 10000, 50,
   22588       reinterpret_cast<v8::internal::Isolate*>(isolate));
   22589   histogramTimer.Start();
   22590   CHECK_EQ("V8.Test", last_event_message);
   22591   CHECK_EQ(0, last_event_status);
   22592   histogramTimer.Stop();
   22593   CHECK_EQ("V8.Test", last_event_message);
   22594   CHECK_EQ(1, last_event_status);
   22595 }
   22596 
   22597 
   22598 TEST(Promises) {
   22599   LocalContext context;
   22600   v8::Isolate* isolate = context->GetIsolate();
   22601   v8::HandleScope scope(isolate);
   22602   Handle<Object> global = context->Global();
   22603 
   22604   // Creation.
   22605   Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
   22606   Handle<v8::Promise::Resolver> rr = v8::Promise::Resolver::New(isolate);
   22607   Handle<v8::Promise> p = pr->GetPromise();
   22608   Handle<v8::Promise> r = rr->GetPromise();
   22609 
   22610   // IsPromise predicate.
   22611   CHECK(p->IsPromise());
   22612   CHECK(r->IsPromise());
   22613   Handle<Value> o = v8::Object::New(isolate);
   22614   CHECK(!o->IsPromise());
   22615 
   22616   // Resolution and rejection.
   22617   pr->Resolve(v8::Integer::New(isolate, 1));
   22618   CHECK(p->IsPromise());
   22619   rr->Reject(v8::Integer::New(isolate, 2));
   22620   CHECK(r->IsPromise());
   22621 
   22622   // Chaining non-pending promises.
   22623   CompileRun(
   22624       "var x1 = 0;\n"
   22625       "var x2 = 0;\n"
   22626       "function f1(x) { x1 = x; return x+1 };\n"
   22627       "function f2(x) { x2 = x; return x+1 };\n");
   22628   Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
   22629   Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
   22630 
   22631   p->Chain(f1);
   22632   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22633   isolate->RunMicrotasks();
   22634   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
   22635 
   22636   p->Catch(f2);
   22637   isolate->RunMicrotasks();
   22638   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
   22639 
   22640   r->Catch(f2);
   22641   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
   22642   isolate->RunMicrotasks();
   22643   CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
   22644 
   22645   r->Chain(f1);
   22646   isolate->RunMicrotasks();
   22647   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
   22648 
   22649   // Chaining pending promises.
   22650   CompileRun("x1 = x2 = 0;");
   22651   pr = v8::Promise::Resolver::New(isolate);
   22652   rr = v8::Promise::Resolver::New(isolate);
   22653 
   22654   pr->GetPromise()->Chain(f1);
   22655   rr->GetPromise()->Catch(f2);
   22656   isolate->RunMicrotasks();
   22657   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22658   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
   22659 
   22660   pr->Resolve(v8::Integer::New(isolate, 1));
   22661   rr->Reject(v8::Integer::New(isolate, 2));
   22662   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22663   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
   22664 
   22665   isolate->RunMicrotasks();
   22666   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
   22667   CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
   22668 
   22669   // Multi-chaining.
   22670   CompileRun("x1 = x2 = 0;");
   22671   pr = v8::Promise::Resolver::New(isolate);
   22672   pr->GetPromise()->Chain(f1)->Chain(f2);
   22673   pr->Resolve(v8::Integer::New(isolate, 3));
   22674   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22675   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
   22676   isolate->RunMicrotasks();
   22677   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
   22678   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
   22679 
   22680   CompileRun("x1 = x2 = 0;");
   22681   rr = v8::Promise::Resolver::New(isolate);
   22682   rr->GetPromise()->Catch(f1)->Chain(f2);
   22683   rr->Reject(v8::Integer::New(isolate, 3));
   22684   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22685   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
   22686   isolate->RunMicrotasks();
   22687   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
   22688   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
   22689 }
   22690 
   22691 
   22692 TEST(PromiseThen) {
   22693   LocalContext context;
   22694   v8::Isolate* isolate = context->GetIsolate();
   22695   v8::HandleScope scope(isolate);
   22696   Handle<Object> global = context->Global();
   22697 
   22698   // Creation.
   22699   Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
   22700   Handle<v8::Promise::Resolver> qr = v8::Promise::Resolver::New(isolate);
   22701   Handle<v8::Promise> p = pr->GetPromise();
   22702   Handle<v8::Promise> q = qr->GetPromise();
   22703 
   22704   CHECK(p->IsPromise());
   22705   CHECK(q->IsPromise());
   22706 
   22707   pr->Resolve(v8::Integer::New(isolate, 1));
   22708   qr->Resolve(p);
   22709 
   22710   // Chaining non-pending promises.
   22711   CompileRun(
   22712       "var x1 = 0;\n"
   22713       "var x2 = 0;\n"
   22714       "function f1(x) { x1 = x; return x+1 };\n"
   22715       "function f2(x) { x2 = x; return x+1 };\n");
   22716   Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
   22717   Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
   22718 
   22719   // Chain
   22720   q->Chain(f1);
   22721   CHECK(global->Get(v8_str("x1"))->IsNumber());
   22722   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22723   isolate->RunMicrotasks();
   22724   CHECK(!global->Get(v8_str("x1"))->IsNumber());
   22725   CHECK_EQ(p, global->Get(v8_str("x1")));
   22726 
   22727   // Then
   22728   CompileRun("x1 = x2 = 0;");
   22729   q->Then(f1);
   22730   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22731   isolate->RunMicrotasks();
   22732   CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
   22733 
   22734   // Then
   22735   CompileRun("x1 = x2 = 0;");
   22736   pr = v8::Promise::Resolver::New(isolate);
   22737   qr = v8::Promise::Resolver::New(isolate);
   22738 
   22739   qr->Resolve(pr);
   22740   qr->GetPromise()->Then(f1)->Then(f2);
   22741 
   22742   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22743   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
   22744   isolate->RunMicrotasks();
   22745   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22746   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
   22747 
   22748   pr->Resolve(v8::Integer::New(isolate, 3));
   22749 
   22750   CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
   22751   CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
   22752   isolate->RunMicrotasks();
   22753   CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
   22754   CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
   22755 }
   22756 
   22757 
   22758 TEST(DisallowJavascriptExecutionScope) {
   22759   LocalContext context;
   22760   v8::Isolate* isolate = context->GetIsolate();
   22761   v8::HandleScope scope(isolate);
   22762   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   22763       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   22764   CompileRun("2+2");
   22765 }
   22766 
   22767 
   22768 TEST(AllowJavascriptExecutionScope) {
   22769   LocalContext context;
   22770   v8::Isolate* isolate = context->GetIsolate();
   22771   v8::HandleScope scope(isolate);
   22772   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   22773       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   22774   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   22775       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   22776   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
   22777     CompileRun("1+1");
   22778   }
   22779 }
   22780 
   22781 
   22782 TEST(ThrowOnJavascriptExecution) {
   22783   LocalContext context;
   22784   v8::Isolate* isolate = context->GetIsolate();
   22785   v8::HandleScope scope(isolate);
   22786   v8::TryCatch try_catch;
   22787   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   22788       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   22789   CompileRun("1+1");
   22790   CHECK(try_catch.HasCaught());
   22791 }
   22792 
   22793 
   22794 TEST(Regress354123) {
   22795   LocalContext current;
   22796   v8::Isolate* isolate = current->GetIsolate();
   22797   v8::HandleScope scope(isolate);
   22798 
   22799   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   22800   templ->SetAccessCheckCallbacks(NamedAccessCounter, IndexedAccessCounter);
   22801   current->Global()->Set(v8_str("friend"), templ->NewInstance());
   22802 
   22803   // Test access using __proto__ from the prototype chain.
   22804   named_access_count = 0;
   22805   CompileRun("friend.__proto__ = {};");
   22806   CHECK_EQ(2, named_access_count);
   22807   CompileRun("friend.__proto__;");
   22808   CHECK_EQ(4, named_access_count);
   22809 
   22810   // Test access using __proto__ as a hijacked function (A).
   22811   named_access_count = 0;
   22812   CompileRun("var p = Object.prototype;"
   22813              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
   22814              "f.call(friend, {});");
   22815   CHECK_EQ(1, named_access_count);
   22816   CompileRun("var p = Object.prototype;"
   22817              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
   22818              "f.call(friend);");
   22819   CHECK_EQ(2, named_access_count);
   22820 
   22821   // Test access using __proto__ as a hijacked function (B).
   22822   named_access_count = 0;
   22823   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
   22824              "f.call(friend, {});");
   22825   CHECK_EQ(1, named_access_count);
   22826   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
   22827              "f.call(friend);");
   22828   CHECK_EQ(2, named_access_count);
   22829 
   22830   // Test access using Object.setPrototypeOf reflective method.
   22831   named_access_count = 0;
   22832   CompileRun("Object.setPrototypeOf(friend, {});");
   22833   CHECK_EQ(1, named_access_count);
   22834   CompileRun("Object.getPrototypeOf(friend);");
   22835   CHECK_EQ(2, named_access_count);
   22836 }
   22837 
   22838 
   22839 TEST(CaptureStackTraceForStackOverflow) {
   22840   v8::internal::FLAG_stack_size = 150;
   22841   LocalContext current;
   22842   v8::Isolate* isolate = current->GetIsolate();
   22843   v8::HandleScope scope(isolate);
   22844   V8::SetCaptureStackTraceForUncaughtExceptions(
   22845       true, 10, v8::StackTrace::kDetailed);
   22846   v8::TryCatch try_catch;
   22847   CompileRun("(function f(x) { f(x+1); })(0)");
   22848   CHECK(try_catch.HasCaught());
   22849 }
   22850 
   22851 
   22852 TEST(ScriptNameAndLineNumber) {
   22853   LocalContext env;
   22854   v8::Isolate* isolate = env->GetIsolate();
   22855   v8::HandleScope scope(isolate);
   22856   const char* url = "http://www.foo.com/foo.js";
   22857   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   22858   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
   22859   Local<Script> script = v8::ScriptCompiler::Compile(
   22860       isolate, &script_source);
   22861   Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
   22862   CHECK(!script_name.IsEmpty());
   22863   CHECK(script_name->IsString());
   22864   String::Utf8Value utf8_name(script_name);
   22865   CHECK_EQ(url, *utf8_name);
   22866   int line_number = script->GetUnboundScript()->GetLineNumber(0);
   22867   CHECK_EQ(13, line_number);
   22868 }
   22869 
   22870 
   22871 void SourceURLHelper(const char* source, const char* expected_source_url,
   22872                      const char* expected_source_mapping_url) {
   22873   Local<Script> script = v8_compile(source);
   22874   if (expected_source_url != NULL) {
   22875     v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
   22876     CHECK_EQ(expected_source_url, *url);
   22877   } else {
   22878     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
   22879   }
   22880   if (expected_source_mapping_url != NULL) {
   22881     v8::String::Utf8Value url(
   22882         script->GetUnboundScript()->GetSourceMappingURL());
   22883     CHECK_EQ(expected_source_mapping_url, *url);
   22884   } else {
   22885     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
   22886   }
   22887 }
   22888 
   22889 
   22890 TEST(ScriptSourceURLAndSourceMappingURL) {
   22891   LocalContext env;
   22892   v8::Isolate* isolate = env->GetIsolate();
   22893   v8::HandleScope scope(isolate);
   22894   SourceURLHelper("function foo() {}\n"
   22895                   "//# sourceURL=bar1.js\n", "bar1.js", NULL);
   22896   SourceURLHelper("function foo() {}\n"
   22897                   "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
   22898 
   22899   // Both sourceURL and sourceMappingURL.
   22900   SourceURLHelper("function foo() {}\n"
   22901                   "//# sourceURL=bar3.js\n"
   22902                   "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
   22903 
   22904   // Two source URLs; the first one is ignored.
   22905   SourceURLHelper("function foo() {}\n"
   22906                   "//# sourceURL=ignoreme.js\n"
   22907                   "//# sourceURL=bar5.js\n", "bar5.js", NULL);
   22908   SourceURLHelper("function foo() {}\n"
   22909                   "//# sourceMappingURL=ignoreme.js\n"
   22910                   "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
   22911 
   22912   // SourceURL or sourceMappingURL in the middle of the script.
   22913   SourceURLHelper("function foo() {}\n"
   22914                   "//# sourceURL=bar7.js\n"
   22915                   "function baz() {}\n", "bar7.js", NULL);
   22916   SourceURLHelper("function foo() {}\n"
   22917                   "//# sourceMappingURL=bar8.js\n"
   22918                   "function baz() {}\n", NULL, "bar8.js");
   22919 
   22920   // Too much whitespace.
   22921   SourceURLHelper("function foo() {}\n"
   22922                   "//#  sourceURL=bar9.js\n"
   22923                   "//#  sourceMappingURL=bar10.js\n", NULL, NULL);
   22924   SourceURLHelper("function foo() {}\n"
   22925                   "//# sourceURL =bar11.js\n"
   22926                   "//# sourceMappingURL =bar12.js\n", NULL, NULL);
   22927 
   22928   // Disallowed characters in value.
   22929   SourceURLHelper("function foo() {}\n"
   22930                   "//# sourceURL=bar13 .js   \n"
   22931                   "//# sourceMappingURL=bar14 .js \n",
   22932                   NULL, NULL);
   22933   SourceURLHelper("function foo() {}\n"
   22934                   "//# sourceURL=bar15\t.js   \n"
   22935                   "//# sourceMappingURL=bar16\t.js \n",
   22936                   NULL, NULL);
   22937   SourceURLHelper("function foo() {}\n"
   22938                   "//# sourceURL=bar17'.js   \n"
   22939                   "//# sourceMappingURL=bar18'.js \n",
   22940                   NULL, NULL);
   22941   SourceURLHelper("function foo() {}\n"
   22942                   "//# sourceURL=bar19\".js   \n"
   22943                   "//# sourceMappingURL=bar20\".js \n",
   22944                   NULL, NULL);
   22945 
   22946   // Not too much whitespace.
   22947   SourceURLHelper("function foo() {}\n"
   22948                   "//# sourceURL=  bar21.js   \n"
   22949                   "//# sourceMappingURL=  bar22.js \n", "bar21.js", "bar22.js");
   22950 }
   22951 
   22952 
   22953 TEST(GetOwnPropertyDescriptor) {
   22954   LocalContext env;
   22955   v8::Isolate* isolate = env->GetIsolate();
   22956   v8::HandleScope scope(isolate);
   22957   CompileRun(
   22958     "var x = { value : 13};"
   22959     "Object.defineProperty(x, 'p0', {value : 12});"
   22960     "Object.defineProperty(x, 'p1', {"
   22961     "  set : function(value) { this.value = value; },"
   22962     "  get : function() { return this.value; },"
   22963     "});");
   22964   Local<Object> x = Local<Object>::Cast(env->Global()->Get(v8_str("x")));
   22965   Local<Value> desc = x->GetOwnPropertyDescriptor(v8_str("no_prop"));
   22966   CHECK(desc->IsUndefined());
   22967   desc = x->GetOwnPropertyDescriptor(v8_str("p0"));
   22968   CHECK_EQ(v8_num(12), Local<Object>::Cast(desc)->Get(v8_str("value")));
   22969   desc = x->GetOwnPropertyDescriptor(v8_str("p1"));
   22970   Local<Function> set =
   22971     Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("set")));
   22972   Local<Function> get =
   22973     Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("get")));
   22974   CHECK_EQ(v8_num(13), get->Call(x, 0, NULL));
   22975   Handle<Value> args[] = { v8_num(14) };
   22976   set->Call(x, 1, args);
   22977   CHECK_EQ(v8_num(14), get->Call(x, 0, NULL));
   22978 }
   22979 
   22980 
   22981 TEST(Regress411877) {
   22982   v8::Isolate* isolate = CcTest::isolate();
   22983   v8::HandleScope handle_scope(isolate);
   22984   v8::Handle<v8::ObjectTemplate> object_template =
   22985       v8::ObjectTemplate::New(isolate);
   22986   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   22987                                            IndexedAccessCounter);
   22988 
   22989   v8::Handle<Context> context = Context::New(isolate);
   22990   v8::Context::Scope context_scope(context);
   22991 
   22992   context->Global()->Set(v8_str("o"), object_template->NewInstance());
   22993   CompileRun("Object.getOwnPropertyNames(o)");
   22994 }
   22995 
   22996 
   22997 TEST(GetHiddenPropertyTableAfterAccessCheck) {
   22998   v8::Isolate* isolate = CcTest::isolate();
   22999   v8::HandleScope handle_scope(isolate);
   23000   v8::Handle<v8::ObjectTemplate> object_template =
   23001       v8::ObjectTemplate::New(isolate);
   23002   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   23003                                            IndexedAccessCounter);
   23004 
   23005   v8::Handle<Context> context = Context::New(isolate);
   23006   v8::Context::Scope context_scope(context);
   23007 
   23008   v8::Handle<v8::Object> obj = object_template->NewInstance();
   23009   obj->Set(v8_str("key"), v8_str("value"));
   23010   obj->Delete(v8_str("key"));
   23011 
   23012   obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2"));
   23013 }
   23014 
   23015 
   23016 TEST(Regress411793) {
   23017   v8::Isolate* isolate = CcTest::isolate();
   23018   v8::HandleScope handle_scope(isolate);
   23019   v8::Handle<v8::ObjectTemplate> object_template =
   23020       v8::ObjectTemplate::New(isolate);
   23021   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   23022                                            IndexedAccessCounter);
   23023 
   23024   v8::Handle<Context> context = Context::New(isolate);
   23025   v8::Context::Scope context_scope(context);
   23026 
   23027   context->Global()->Set(v8_str("o"), object_template->NewInstance());
   23028   CompileRun(
   23029       "Object.defineProperty(o, 'key', "
   23030       "    { get: function() {}, set: function() {} });");
   23031 }
   23032 
   23033 class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
   23034  public:
   23035   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
   23036 
   23037   virtual size_t GetMoreData(const uint8_t** src) {
   23038     // Unlike in real use cases, this function will never block.
   23039     if (chunks_[index_] == NULL) {
   23040       return 0;
   23041     }
   23042     // Copy the data, since the caller takes ownership of it.
   23043     size_t len = strlen(chunks_[index_]);
   23044     // We don't need to zero-terminate since we return the length.
   23045     uint8_t* copy = new uint8_t[len];
   23046     memcpy(copy, chunks_[index_], len);
   23047     *src = copy;
   23048     ++index_;
   23049     return len;
   23050   }
   23051 
   23052   // Helper for constructing a string from chunks (the compilation needs it
   23053   // too).
   23054   static char* FullSourceString(const char** chunks) {
   23055     size_t total_len = 0;
   23056     for (size_t i = 0; chunks[i] != NULL; ++i) {
   23057       total_len += strlen(chunks[i]);
   23058     }
   23059     char* full_string = new char[total_len + 1];
   23060     size_t offset = 0;
   23061     for (size_t i = 0; chunks[i] != NULL; ++i) {
   23062       size_t len = strlen(chunks[i]);
   23063       memcpy(full_string + offset, chunks[i], len);
   23064       offset += len;
   23065     }
   23066     full_string[total_len] = 0;
   23067     return full_string;
   23068   }
   23069 
   23070  private:
   23071   const char** chunks_;
   23072   unsigned index_;
   23073 };
   23074 
   23075 
   23076 // Helper function for running streaming tests.
   23077 void RunStreamingTest(const char** chunks,
   23078                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
   23079                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   23080                       bool expected_success = true) {
   23081   LocalContext env;
   23082   v8::Isolate* isolate = env->GetIsolate();
   23083   v8::HandleScope scope(isolate);
   23084   v8::TryCatch try_catch;
   23085 
   23086   v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
   23087                                             encoding);
   23088   v8::ScriptCompiler::ScriptStreamingTask* task =
   23089       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   23090 
   23091   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   23092   // task here in the main thread.
   23093   task->Run();
   23094   delete task;
   23095 
   23096   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   23097   char* full_source = TestSourceStream::FullSourceString(chunks);
   23098 
   23099   // The possible errors are only produced while compiling.
   23100   CHECK_EQ(false, try_catch.HasCaught());
   23101 
   23102   v8::Handle<Script> script = v8::ScriptCompiler::Compile(
   23103       isolate, &source, v8_str(full_source), origin);
   23104   if (expected_success) {
   23105     CHECK(!script.IsEmpty());
   23106     v8::Handle<Value> result(script->Run());
   23107     // All scripts are supposed to return the fixed value 13 when ran.
   23108     CHECK_EQ(13, result->Int32Value());
   23109   } else {
   23110     CHECK(script.IsEmpty());
   23111     CHECK(try_catch.HasCaught());
   23112   }
   23113   delete[] full_source;
   23114 }
   23115 
   23116 
   23117 TEST(StreamingSimpleScript) {
   23118   // This script is unrealistically small, since no one chunk is enough to fill
   23119   // the backing buffer of Scanner, let alone overflow it.
   23120   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   23121                           NULL};
   23122   RunStreamingTest(chunks);
   23123 }
   23124 
   23125 
   23126 TEST(StreamingBiggerScript) {
   23127   const char* chunk1 =
   23128       "function foo() {\n"
   23129       "  // Make this chunk sufficiently long so that it will overflow the\n"
   23130       "  // backing buffer of the Scanner.\n"
   23131       "  var i = 0;\n"
   23132       "  var result = 0;\n"
   23133       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   23134       "  result = 0;\n"
   23135       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   23136       "  result = 0;\n"
   23137       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   23138       "  result = 0;\n"
   23139       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   23140       "  return result;\n"
   23141       "}\n";
   23142   const char* chunks[] = {chunk1, "foo(); ", NULL};
   23143   RunStreamingTest(chunks);
   23144 }
   23145 
   23146 
   23147 TEST(StreamingScriptWithParseError) {
   23148   // Test that parse errors from streamed scripts are propagated correctly.
   23149   {
   23150     char chunk1[] =
   23151         "  // This will result in a parse error.\n"
   23152         "  var if else then foo";
   23153     char chunk2[] = "  13\n";
   23154     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23155 
   23156     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   23157                      false);
   23158   }
   23159   // Test that the next script succeeds normally.
   23160   {
   23161     char chunk1[] =
   23162         "  // This will be parsed successfully.\n"
   23163         "  function foo() { return ";
   23164     char chunk2[] = "  13; }\n";
   23165     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23166 
   23167     RunStreamingTest(chunks);
   23168   }
   23169 }
   23170 
   23171 
   23172 TEST(StreamingUtf8Script) {
   23173   // We'd want to write \uc481 instead of \xeb\x91\x80, but Windows compilers
   23174   // don't like it.
   23175   const char* chunk1 =
   23176       "function foo() {\n"
   23177       "  // This function will contain an UTF-8 character which is not in\n"
   23178       "  // ASCII.\n"
   23179       "  var foob\xeb\x91\x80r = 13;\n"
   23180       "  return foob\xeb\x91\x80r;\n"
   23181       "}\n";
   23182   const char* chunks[] = {chunk1, "foo(); ", NULL};
   23183   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23184 }
   23185 
   23186 
   23187 TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
   23188   // A sanity check to prove that the approach of splitting UTF-8
   23189   // characters is correct. Here is an UTF-8 character which will take three
   23190   // bytes.
   23191   const char* reference = "\xeb\x91\x80";
   23192   CHECK(3u == strlen(reference));  // NOLINT - no CHECK_EQ for unsigned.
   23193 
   23194   char chunk1[] =
   23195       "function foo() {\n"
   23196       "  // This function will contain an UTF-8 character which is not in\n"
   23197       "  // ASCII.\n"
   23198       "  var foob";
   23199   char chunk2[] =
   23200       "XXXr = 13;\n"
   23201       "  return foob\xeb\x91\x80r;\n"
   23202       "}\n";
   23203   for (int i = 0; i < 3; ++i) {
   23204     chunk2[i] = reference[i];
   23205   }
   23206   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23207   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23208 }
   23209 
   23210 
   23211 TEST(StreamingUtf8ScriptWithSplitCharacters) {
   23212   // Stream data where a multi-byte UTF-8 character is split between two data
   23213   // chunks.
   23214   const char* reference = "\xeb\x91\x80";
   23215   char chunk1[] =
   23216       "function foo() {\n"
   23217       "  // This function will contain an UTF-8 character which is not in\n"
   23218       "  // ASCII.\n"
   23219       "  var foobX";
   23220   char chunk2[] =
   23221       "XXr = 13;\n"
   23222       "  return foob\xeb\x91\x80r;\n"
   23223       "}\n";
   23224   chunk1[strlen(chunk1) - 1] = reference[0];
   23225   chunk2[0] = reference[1];
   23226   chunk2[1] = reference[2];
   23227   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23228   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23229 }
   23230 
   23231 
   23232 TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
   23233   // Tests edge cases which should still be decoded correctly.
   23234 
   23235   // Case 1: a chunk contains only bytes for a split character (and no other
   23236   // data). This kind of a chunk would be exceptionally small, but we should
   23237   // still decode it correctly.
   23238   const char* reference = "\xeb\x91\x80";
   23239   // The small chunk is at the beginning of the split character
   23240   {
   23241     char chunk1[] =
   23242         "function foo() {\n"
   23243         "  // This function will contain an UTF-8 character which is not in\n"
   23244         "  // ASCII.\n"
   23245         "  var foob";
   23246     char chunk2[] = "XX";
   23247     char chunk3[] =
   23248         "Xr = 13;\n"
   23249         "  return foob\xeb\x91\x80r;\n"
   23250         "}\n";
   23251     chunk2[0] = reference[0];
   23252     chunk2[1] = reference[1];
   23253     chunk3[0] = reference[2];
   23254     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
   23255     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23256   }
   23257   // The small chunk is at the end of a character
   23258   {
   23259     char chunk1[] =
   23260         "function foo() {\n"
   23261         "  // This function will contain an UTF-8 character which is not in\n"
   23262         "  // ASCII.\n"
   23263         "  var foobX";
   23264     char chunk2[] = "XX";
   23265     char chunk3[] =
   23266         "r = 13;\n"
   23267         "  return foob\xeb\x91\x80r;\n"
   23268         "}\n";
   23269     chunk1[strlen(chunk1) - 1] = reference[0];
   23270     chunk2[0] = reference[1];
   23271     chunk2[1] = reference[2];
   23272     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
   23273     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23274   }
   23275   // Case 2: the script ends with a multi-byte character. Make sure that it's
   23276   // decoded correctly and not just ignored.
   23277   {
   23278     char chunk1[] =
   23279         "var foob\xeb\x91\x80 = 13;\n"
   23280         "foob\xeb\x91\x80";
   23281     const char* chunks[] = {chunk1, NULL};
   23282     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23283   }
   23284 }
   23285 
   23286 
   23287 TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
   23288   // Test cases where a UTF-8 character is split over several chunks. Those
   23289   // cases are not supported (the embedder should give the data in big enough
   23290   // chunks), but we shouldn't crash, just produce a parse error.
   23291   const char* reference = "\xeb\x91\x80";
   23292   char chunk1[] =
   23293       "function foo() {\n"
   23294       "  // This function will contain an UTF-8 character which is not in\n"
   23295       "  // ASCII.\n"
   23296       "  var foobX";
   23297   char chunk2[] = "X";
   23298   char chunk3[] =
   23299       "Xr = 13;\n"
   23300       "  return foob\xeb\x91\x80r;\n"
   23301       "}\n";
   23302   chunk1[strlen(chunk1) - 1] = reference[0];
   23303   chunk2[0] = reference[1];
   23304   chunk3[0] = reference[2];
   23305   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
   23306 
   23307   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   23308 }
   23309 
   23310 
   23311 TEST(StreamingProducesParserCache) {
   23312   i::FLAG_min_preparse_length = 0;
   23313   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   23314                           NULL};
   23315 
   23316   LocalContext env;
   23317   v8::Isolate* isolate = env->GetIsolate();
   23318   v8::HandleScope scope(isolate);
   23319 
   23320   v8::ScriptCompiler::StreamedSource source(
   23321       new TestSourceStream(chunks),
   23322       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   23323   v8::ScriptCompiler::ScriptStreamingTask* task =
   23324       v8::ScriptCompiler::StartStreamingScript(
   23325           isolate, &source, v8::ScriptCompiler::kProduceParserCache);
   23326 
   23327   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   23328   // task here in the main thread.
   23329   task->Run();
   23330   delete task;
   23331 
   23332   const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
   23333   CHECK(cached_data != NULL);
   23334   CHECK(cached_data->data != NULL);
   23335   CHECK_GT(cached_data->length, 0);
   23336 }
   23337 
   23338 
   23339 TEST(StreamingScriptWithInvalidUtf8) {
   23340   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
   23341   // chunk don't produce a crash.
   23342   const char* reference = "\xeb\x91\x80\x80\x80";
   23343   char chunk1[] =
   23344       "function foo() {\n"
   23345       "  // This function will contain an UTF-8 character which is not in\n"
   23346       "  // ASCII.\n"
   23347       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
   23348   char chunk2[] =
   23349       "r = 13;\n"
   23350       "  return foob\xeb\x91\x80\x80\x80r;\n"
   23351       "}\n";
   23352   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
   23353 
   23354   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23355   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   23356 }
   23357