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 <limits.h>
     29 
     30 #ifndef WIN32
     31 #include <signal.h>  // kill
     32 #include <unistd.h>  // getpid
     33 #endif  // WIN32
     34 #include <string>
     35 #include <map>
     36 
     37 #include "v8.h"
     38 
     39 #include "api.h"
     40 #include "arguments.h"
     41 #include "cctest.h"
     42 #include "compilation-cache.h"
     43 #include "cpu-profiler.h"
     44 #include "execution.h"
     45 #include "isolate.h"
     46 #include "objects.h"
     47 #include "parser.h"
     48 #include "platform.h"
     49 #include "snapshot.h"
     50 #include "unicode-inl.h"
     51 #include "utils.h"
     52 #include "vm-state.h"
     53 
     54 static const bool kLogThreading = false;
     55 
     56 using ::v8::AccessorInfo;
     57 using ::v8::Arguments;
     58 using ::v8::Boolean;
     59 using ::v8::BooleanObject;
     60 using ::v8::Context;
     61 using ::v8::Extension;
     62 using ::v8::Function;
     63 using ::v8::FunctionTemplate;
     64 using ::v8::Handle;
     65 using ::v8::HandleScope;
     66 using ::v8::Local;
     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::TryCatch;
     76 using ::v8::Undefined;
     77 using ::v8::UniqueId;
     78 using ::v8::V8;
     79 using ::v8::Value;
     80 
     81 
     82 #define THREADED_PROFILED_TEST(Name)                                 \
     83   static void Test##Name();                                          \
     84   TEST(Name##WithProfiler) {                                         \
     85     RunWithProfiler(&Test##Name);                                    \
     86   }                                                                  \
     87   THREADED_TEST(Name)
     88 
     89 void RunWithProfiler(void (*test)()) {
     90   LocalContext env;
     91   v8::HandleScope scope(env->GetIsolate());
     92   v8::Local<v8::String> profile_name = v8::String::New("my_profile1");
     93   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
     94 
     95   cpu_profiler->StartCpuProfiling(profile_name);
     96   (*test)();
     97   cpu_profiler->DeleteAllCpuProfiles();
     98 }
     99 
    100 
    101 static void ExpectString(const char* code, const char* expected) {
    102   Local<Value> result = CompileRun(code);
    103   CHECK(result->IsString());
    104   String::Utf8Value utf8(result);
    105   CHECK_EQ(expected, *utf8);
    106 }
    107 
    108 
    109 static void ExpectInt32(const char* code, int expected) {
    110   Local<Value> result = CompileRun(code);
    111   CHECK(result->IsInt32());
    112   CHECK_EQ(expected, result->Int32Value());
    113 }
    114 
    115 
    116 static void ExpectBoolean(const char* code, bool expected) {
    117   Local<Value> result = CompileRun(code);
    118   CHECK(result->IsBoolean());
    119   CHECK_EQ(expected, result->BooleanValue());
    120 }
    121 
    122 
    123 static void ExpectTrue(const char* code) {
    124   ExpectBoolean(code, true);
    125 }
    126 
    127 
    128 static void ExpectFalse(const char* code) {
    129   ExpectBoolean(code, false);
    130 }
    131 
    132 
    133 static void ExpectObject(const char* code, Local<Value> expected) {
    134   Local<Value> result = CompileRun(code);
    135   CHECK(result->Equals(expected));
    136 }
    137 
    138 
    139 static void ExpectUndefined(const char* code) {
    140   Local<Value> result = CompileRun(code);
    141   CHECK(result->IsUndefined());
    142 }
    143 
    144 
    145 static int signature_callback_count;
    146 static void IncrementingSignatureCallback(
    147     const v8::FunctionCallbackInfo<v8::Value>& args) {
    148   ApiTestFuzzer::Fuzz();
    149   signature_callback_count++;
    150   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
    151   for (int i = 0; i < args.Length(); i++)
    152     result->Set(v8::Integer::New(i), args[i]);
    153   args.GetReturnValue().Set(result);
    154 }
    155 
    156 
    157 static void SignatureCallback(
    158     const v8::FunctionCallbackInfo<v8::Value>& args) {
    159   ApiTestFuzzer::Fuzz();
    160   v8::Handle<v8::Array> result = v8::Array::New(args.Length());
    161   for (int i = 0; i < args.Length(); i++) {
    162     result->Set(v8::Integer::New(i), args[i]);
    163   }
    164   args.GetReturnValue().Set(result);
    165 }
    166 
    167 
    168 THREADED_TEST(Handles) {
    169   v8::HandleScope scope(v8::Isolate::GetCurrent());
    170   Local<Context> local_env;
    171   {
    172     LocalContext env;
    173     local_env = env.local();
    174   }
    175 
    176   // Local context should still be live.
    177   CHECK(!local_env.IsEmpty());
    178   local_env->Enter();
    179 
    180   v8::Handle<v8::Primitive> undef = v8::Undefined();
    181   CHECK(!undef.IsEmpty());
    182   CHECK(undef->IsUndefined());
    183 
    184   const char* c_source = "1 + 2 + 3";
    185   Local<String> source = String::New(c_source);
    186   Local<Script> script = Script::Compile(source);
    187   CHECK_EQ(6, script->Run()->Int32Value());
    188 
    189   local_env->Exit();
    190 }
    191 
    192 
    193 THREADED_TEST(IsolateOfContext) {
    194   v8::HandleScope scope(v8::Isolate::GetCurrent());
    195   v8::Handle<Context> env = Context::New(v8::Isolate::GetCurrent());
    196 
    197   CHECK(!env->InContext());
    198   CHECK(env->GetIsolate() == v8::Isolate::GetCurrent());
    199   env->Enter();
    200   CHECK(env->InContext());
    201   CHECK(env->GetIsolate() == v8::Isolate::GetCurrent());
    202   env->Exit();
    203   CHECK(!env->InContext());
    204   CHECK(env->GetIsolate() == v8::Isolate::GetCurrent());
    205 }
    206 
    207 
    208 THREADED_TEST(ReceiverSignature) {
    209   LocalContext env;
    210   v8::HandleScope scope(env->GetIsolate());
    211   v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
    212   v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
    213   fun->PrototypeTemplate()->Set(
    214       v8_str("m"),
    215       v8::FunctionTemplate::New(IncrementingSignatureCallback,
    216                                 v8::Handle<Value>(),
    217                                 sig));
    218   env->Global()->Set(v8_str("Fun"), fun->GetFunction());
    219   signature_callback_count = 0;
    220   CompileRun(
    221       "var o = new Fun();"
    222       "o.m();");
    223   CHECK_EQ(1, signature_callback_count);
    224   v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
    225   sub_fun->Inherit(fun);
    226   env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction());
    227   CompileRun(
    228       "var o = new SubFun();"
    229       "o.m();");
    230   CHECK_EQ(2, signature_callback_count);
    231 
    232   v8::TryCatch try_catch;
    233   CompileRun(
    234       "var o = { };"
    235       "o.m = Fun.prototype.m;"
    236       "o.m();");
    237   CHECK_EQ(2, signature_callback_count);
    238   CHECK(try_catch.HasCaught());
    239   try_catch.Reset();
    240   v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
    241   sub_fun->Inherit(fun);
    242   env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
    243   CompileRun(
    244       "var o = new UnrelFun();"
    245       "o.m = Fun.prototype.m;"
    246       "o.m();");
    247   CHECK_EQ(2, signature_callback_count);
    248   CHECK(try_catch.HasCaught());
    249 }
    250 
    251 
    252 THREADED_TEST(ArgumentSignature) {
    253   LocalContext env;
    254   v8::HandleScope scope(env->GetIsolate());
    255   v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
    256   cons->SetClassName(v8_str("Cons"));
    257   v8::Handle<v8::Signature> sig =
    258       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 1, &cons);
    259   v8::Handle<v8::FunctionTemplate> fun =
    260       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
    261   env->Global()->Set(v8_str("Cons"), cons->GetFunction());
    262   env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
    263 
    264   v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
    265   CHECK(value1->IsTrue());
    266 
    267   v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
    268   CHECK(value2->IsTrue());
    269 
    270   v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
    271   CHECK(value3->IsTrue());
    272 
    273   v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
    274   cons1->SetClassName(v8_str("Cons1"));
    275   v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
    276   cons2->SetClassName(v8_str("Cons2"));
    277   v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
    278   cons3->SetClassName(v8_str("Cons3"));
    279 
    280   v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
    281   v8::Handle<v8::Signature> wsig =
    282       v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 3, args);
    283   v8::Handle<v8::FunctionTemplate> fun2 =
    284       v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
    285 
    286   env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
    287   env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
    288   env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
    289   env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
    290   v8::Handle<Value> value4 = CompileRun(
    291       "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
    292       "'[object Cons1],[object Cons2],[object Cons3]'");
    293   CHECK(value4->IsTrue());
    294 
    295   v8::Handle<Value> value5 = CompileRun(
    296       "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
    297   CHECK(value5->IsTrue());
    298 
    299   v8::Handle<Value> value6 = CompileRun(
    300       "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
    301   CHECK(value6->IsTrue());
    302 
    303   v8::Handle<Value> value7 = CompileRun(
    304       "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
    305       "'[object Cons1],[object Cons2],[object Cons3],d';");
    306   CHECK(value7->IsTrue());
    307 
    308   v8::Handle<Value> value8 = CompileRun(
    309       "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
    310   CHECK(value8->IsTrue());
    311 }
    312 
    313 
    314 THREADED_TEST(HulIgennem) {
    315   LocalContext env;
    316   v8::HandleScope scope(env->GetIsolate());
    317   v8::Handle<v8::Primitive> undef = v8::Undefined();
    318   Local<String> undef_str = undef->ToString();
    319   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
    320   undef_str->WriteUtf8(value);
    321   CHECK_EQ(0, strcmp(value, "undefined"));
    322   i::DeleteArray(value);
    323 }
    324 
    325 
    326 THREADED_TEST(Access) {
    327   LocalContext env;
    328   v8::HandleScope scope(env->GetIsolate());
    329   Local<v8::Object> obj = v8::Object::New();
    330   Local<Value> foo_before = obj->Get(v8_str("foo"));
    331   CHECK(foo_before->IsUndefined());
    332   Local<String> bar_str = v8_str("bar");
    333   obj->Set(v8_str("foo"), bar_str);
    334   Local<Value> foo_after = obj->Get(v8_str("foo"));
    335   CHECK(!foo_after->IsUndefined());
    336   CHECK(foo_after->IsString());
    337   CHECK_EQ(bar_str, foo_after);
    338 }
    339 
    340 
    341 THREADED_TEST(AccessElement) {
    342   LocalContext env;
    343   v8::HandleScope scope(env->GetIsolate());
    344   Local<v8::Object> obj = v8::Object::New();
    345   Local<Value> before = obj->Get(1);
    346   CHECK(before->IsUndefined());
    347   Local<String> bar_str = v8_str("bar");
    348   obj->Set(1, bar_str);
    349   Local<Value> after = obj->Get(1);
    350   CHECK(!after->IsUndefined());
    351   CHECK(after->IsString());
    352   CHECK_EQ(bar_str, after);
    353 
    354   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
    355   CHECK_EQ(v8_str("a"), value->Get(0));
    356   CHECK_EQ(v8_str("b"), value->Get(1));
    357 }
    358 
    359 
    360 THREADED_TEST(Script) {
    361   LocalContext env;
    362   v8::HandleScope scope(env->GetIsolate());
    363   const char* c_source = "1 + 2 + 3";
    364   Local<String> source = String::New(c_source);
    365   Local<Script> script = Script::Compile(source);
    366   CHECK_EQ(6, script->Run()->Int32Value());
    367 }
    368 
    369 
    370 static uint16_t* AsciiToTwoByteString(const char* source) {
    371   int array_length = i::StrLength(source) + 1;
    372   uint16_t* converted = i::NewArray<uint16_t>(array_length);
    373   for (int i = 0; i < array_length; i++) converted[i] = source[i];
    374   return converted;
    375 }
    376 
    377 
    378 class TestResource: public String::ExternalStringResource {
    379  public:
    380   explicit TestResource(uint16_t* data, int* counter = NULL)
    381     : data_(data), length_(0), counter_(counter) {
    382     while (data[length_]) ++length_;
    383   }
    384 
    385   ~TestResource() {
    386     i::DeleteArray(data_);
    387     if (counter_ != NULL) ++*counter_;
    388   }
    389 
    390   const uint16_t* data() const {
    391     return data_;
    392   }
    393 
    394   size_t length() const {
    395     return length_;
    396   }
    397  private:
    398   uint16_t* data_;
    399   size_t length_;
    400   int* counter_;
    401 };
    402 
    403 
    404 class TestAsciiResource: public String::ExternalAsciiStringResource {
    405  public:
    406   explicit TestAsciiResource(const char* data, int* counter = NULL)
    407     : data_(data), length_(strlen(data)), counter_(counter) { }
    408 
    409   ~TestAsciiResource() {
    410     i::DeleteArray(data_);
    411     if (counter_ != NULL) ++*counter_;
    412   }
    413 
    414   const char* data() const {
    415     return data_;
    416   }
    417 
    418   size_t length() const {
    419     return length_;
    420   }
    421  private:
    422   const char* data_;
    423   size_t length_;
    424   int* counter_;
    425 };
    426 
    427 
    428 THREADED_TEST(ScriptUsingStringResource) {
    429   int dispose_count = 0;
    430   const char* c_source = "1 + 2 * 3";
    431   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
    432   {
    433     LocalContext env;
    434     v8::HandleScope scope(env->GetIsolate());
    435     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
    436     Local<String> source = String::NewExternal(resource);
    437     Local<Script> script = Script::Compile(source);
    438     Local<Value> value = script->Run();
    439     CHECK(value->IsNumber());
    440     CHECK_EQ(7, value->Int32Value());
    441     CHECK(source->IsExternal());
    442     CHECK_EQ(resource,
    443              static_cast<TestResource*>(source->GetExternalStringResource()));
    444     String::Encoding encoding = String::UNKNOWN_ENCODING;
    445     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    446              source->GetExternalStringResourceBase(&encoding));
    447     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
    448     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    449     CHECK_EQ(0, dispose_count);
    450   }
    451   v8::internal::Isolate::Current()->compilation_cache()->Clear();
    452   HEAP->CollectAllAvailableGarbage();
    453   CHECK_EQ(1, dispose_count);
    454 }
    455 
    456 
    457 THREADED_TEST(ScriptUsingAsciiStringResource) {
    458   int dispose_count = 0;
    459   const char* c_source = "1 + 2 * 3";
    460   {
    461     LocalContext env;
    462     v8::HandleScope scope(env->GetIsolate());
    463     TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
    464                                                         &dispose_count);
    465     Local<String> source = String::NewExternal(resource);
    466     CHECK(source->IsExternalAscii());
    467     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    468              source->GetExternalAsciiStringResource());
    469     String::Encoding encoding = String::UNKNOWN_ENCODING;
    470     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    471              source->GetExternalStringResourceBase(&encoding));
    472     CHECK_EQ(String::ASCII_ENCODING, encoding);
    473     Local<Script> script = Script::Compile(source);
    474     Local<Value> value = script->Run();
    475     CHECK(value->IsNumber());
    476     CHECK_EQ(7, value->Int32Value());
    477     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    478     CHECK_EQ(0, dispose_count);
    479   }
    480   i::Isolate::Current()->compilation_cache()->Clear();
    481   HEAP->CollectAllAvailableGarbage();
    482   CHECK_EQ(1, dispose_count);
    483 }
    484 
    485 
    486 THREADED_TEST(ScriptMakingExternalString) {
    487   int dispose_count = 0;
    488   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
    489   {
    490     LocalContext env;
    491     v8::HandleScope scope(env->GetIsolate());
    492     Local<String> source = String::New(two_byte_source);
    493     // Trigger GCs so that the newly allocated string moves to old gen.
    494     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    495     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    496     CHECK_EQ(source->IsExternal(), false);
    497     CHECK_EQ(source->IsExternalAscii(), false);
    498     String::Encoding encoding = String::UNKNOWN_ENCODING;
    499     CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
    500     CHECK_EQ(String::ASCII_ENCODING, encoding);
    501     bool success = source->MakeExternal(new TestResource(two_byte_source,
    502                                                          &dispose_count));
    503     CHECK(success);
    504     Local<Script> script = Script::Compile(source);
    505     Local<Value> value = script->Run();
    506     CHECK(value->IsNumber());
    507     CHECK_EQ(7, value->Int32Value());
    508     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    509     CHECK_EQ(0, dispose_count);
    510   }
    511   i::Isolate::Current()->compilation_cache()->Clear();
    512   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
    513   CHECK_EQ(1, dispose_count);
    514 }
    515 
    516 
    517 THREADED_TEST(ScriptMakingExternalAsciiString) {
    518   int dispose_count = 0;
    519   const char* c_source = "1 + 2 * 3";
    520   {
    521     LocalContext env;
    522     v8::HandleScope scope(env->GetIsolate());
    523     Local<String> source = v8_str(c_source);
    524     // Trigger GCs so that the newly allocated string moves to old gen.
    525     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    526     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    527     bool success = source->MakeExternal(
    528         new TestAsciiResource(i::StrDup(c_source), &dispose_count));
    529     CHECK(success);
    530     Local<Script> script = Script::Compile(source);
    531     Local<Value> value = script->Run();
    532     CHECK(value->IsNumber());
    533     CHECK_EQ(7, value->Int32Value());
    534     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    535     CHECK_EQ(0, dispose_count);
    536   }
    537   i::Isolate::Current()->compilation_cache()->Clear();
    538   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
    539   CHECK_EQ(1, dispose_count);
    540 }
    541 
    542 
    543 TEST(MakingExternalStringConditions) {
    544   LocalContext env;
    545   v8::HandleScope scope(env->GetIsolate());
    546 
    547   // Free some space in the new space so that we can check freshness.
    548   HEAP->CollectGarbage(i::NEW_SPACE);
    549   HEAP->CollectGarbage(i::NEW_SPACE);
    550 
    551   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
    552   Local<String> small_string = String::New(two_byte_string);
    553   i::DeleteArray(two_byte_string);
    554 
    555   // We should refuse to externalize newly created small string.
    556   CHECK(!small_string->CanMakeExternal());
    557   // Trigger GCs so that the newly allocated string moves to old gen.
    558   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    559   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    560   // Old space strings should be accepted.
    561   CHECK(small_string->CanMakeExternal());
    562 
    563   two_byte_string = AsciiToTwoByteString("small string 2");
    564   small_string = String::New(two_byte_string);
    565   i::DeleteArray(two_byte_string);
    566 
    567   // We should refuse externalizing newly created small string.
    568   CHECK(!small_string->CanMakeExternal());
    569   for (int i = 0; i < 100; i++) {
    570     String::Value value(small_string);
    571   }
    572   // Frequently used strings should be accepted.
    573   CHECK(small_string->CanMakeExternal());
    574 
    575   const int buf_size = 10 * 1024;
    576   char* buf = i::NewArray<char>(buf_size);
    577   memset(buf, 'a', buf_size);
    578   buf[buf_size - 1] = '\0';
    579 
    580   two_byte_string = AsciiToTwoByteString(buf);
    581   Local<String> large_string = String::New(two_byte_string);
    582   i::DeleteArray(buf);
    583   i::DeleteArray(two_byte_string);
    584   // Large strings should be immediately accepted.
    585   CHECK(large_string->CanMakeExternal());
    586 }
    587 
    588 
    589 TEST(MakingExternalAsciiStringConditions) {
    590   LocalContext env;
    591   v8::HandleScope scope(env->GetIsolate());
    592 
    593   // Free some space in the new space so that we can check freshness.
    594   HEAP->CollectGarbage(i::NEW_SPACE);
    595   HEAP->CollectGarbage(i::NEW_SPACE);
    596 
    597   Local<String> small_string = String::New("s1");
    598   // We should refuse to externalize newly created small string.
    599   CHECK(!small_string->CanMakeExternal());
    600   // Trigger GCs so that the newly allocated string moves to old gen.
    601   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    602   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    603   // Old space strings should be accepted.
    604   CHECK(small_string->CanMakeExternal());
    605 
    606   small_string = String::New("small string 2");
    607   // We should refuse externalizing newly created small string.
    608   CHECK(!small_string->CanMakeExternal());
    609   for (int i = 0; i < 100; i++) {
    610     String::Value value(small_string);
    611   }
    612   // Frequently used strings should be accepted.
    613   CHECK(small_string->CanMakeExternal());
    614 
    615   const int buf_size = 10 * 1024;
    616   char* buf = i::NewArray<char>(buf_size);
    617   memset(buf, 'a', buf_size);
    618   buf[buf_size - 1] = '\0';
    619   Local<String> large_string = String::New(buf);
    620   i::DeleteArray(buf);
    621   // Large strings should be immediately accepted.
    622   CHECK(large_string->CanMakeExternal());
    623 }
    624 
    625 
    626 TEST(MakingExternalUnalignedAsciiString) {
    627   LocalContext env;
    628   v8::HandleScope scope(env->GetIsolate());
    629 
    630   CompileRun("function cons(a, b) { return a + b; }"
    631              "function slice(a) { return a.substring(1); }");
    632   // Create a cons string that will land in old pointer space.
    633   Local<String> cons = Local<String>::Cast(CompileRun(
    634       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
    635   // Create a sliced string that will land in old pointer space.
    636   Local<String> slice = Local<String>::Cast(CompileRun(
    637       "slice('abcdefghijklmnopqrstuvwxyz');"));
    638 
    639   // Trigger GCs so that the newly allocated string moves to old gen.
    640   SimulateFullSpace(HEAP->old_pointer_space());
    641   HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    642   HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    643 
    644   // Turn into external string with unaligned resource data.
    645   int dispose_count = 0;
    646   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
    647   bool success = cons->MakeExternal(
    648       new TestAsciiResource(i::StrDup(c_cons) + 1, &dispose_count));
    649   CHECK(success);
    650   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
    651   success = slice->MakeExternal(
    652       new TestAsciiResource(i::StrDup(c_slice) + 1, &dispose_count));
    653   CHECK(success);
    654 
    655   // Trigger GCs and force evacuation.
    656   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    657   HEAP->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
    658 }
    659 
    660 
    661 THREADED_TEST(UsingExternalString) {
    662   i::Factory* factory = i::Isolate::Current()->factory();
    663   {
    664     v8::HandleScope scope(v8::Isolate::GetCurrent());
    665     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    666     Local<String> string =
    667         String::NewExternal(new TestResource(two_byte_string));
    668     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    669     // Trigger GCs so that the newly allocated string moves to old gen.
    670     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    671     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    672     i::Handle<i::String> isymbol =
    673         factory->InternalizedStringFromString(istring);
    674     CHECK(isymbol->IsInternalizedString());
    675   }
    676   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    677   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    678 }
    679 
    680 
    681 THREADED_TEST(UsingExternalAsciiString) {
    682   i::Factory* factory = i::Isolate::Current()->factory();
    683   {
    684     v8::HandleScope scope(v8::Isolate::GetCurrent());
    685     const char* one_byte_string = "test string";
    686     Local<String> string = String::NewExternal(
    687         new TestAsciiResource(i::StrDup(one_byte_string)));
    688     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    689     // Trigger GCs so that the newly allocated string moves to old gen.
    690     HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    691     HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
    692     i::Handle<i::String> isymbol =
    693         factory->InternalizedStringFromString(istring);
    694     CHECK(isymbol->IsInternalizedString());
    695   }
    696   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    697   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    698 }
    699 
    700 
    701 THREADED_TEST(ScavengeExternalString) {
    702   i::FLAG_stress_compaction = false;
    703   i::FLAG_gc_global = false;
    704   int dispose_count = 0;
    705   bool in_new_space = false;
    706   {
    707     v8::HandleScope scope(v8::Isolate::GetCurrent());
    708     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    709     Local<String> string =
    710       String::NewExternal(new TestResource(two_byte_string,
    711                                            &dispose_count));
    712     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    713     HEAP->CollectGarbage(i::NEW_SPACE);
    714     in_new_space = HEAP->InNewSpace(*istring);
    715     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
    716     CHECK_EQ(0, dispose_count);
    717   }
    718   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    719   CHECK_EQ(1, dispose_count);
    720 }
    721 
    722 
    723 THREADED_TEST(ScavengeExternalAsciiString) {
    724   i::FLAG_stress_compaction = false;
    725   i::FLAG_gc_global = false;
    726   int dispose_count = 0;
    727   bool in_new_space = false;
    728   {
    729     v8::HandleScope scope(v8::Isolate::GetCurrent());
    730     const char* one_byte_string = "test string";
    731     Local<String> string = String::NewExternal(
    732         new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
    733     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    734     HEAP->CollectGarbage(i::NEW_SPACE);
    735     in_new_space = HEAP->InNewSpace(*istring);
    736     CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
    737     CHECK_EQ(0, dispose_count);
    738   }
    739   HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
    740   CHECK_EQ(1, dispose_count);
    741 }
    742 
    743 
    744 class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
    745  public:
    746   // Only used by non-threaded tests, so it can use static fields.
    747   static int dispose_calls;
    748   static int dispose_count;
    749 
    750   TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
    751       : TestAsciiResource(data, &dispose_count),
    752         dispose_(dispose) { }
    753 
    754   void Dispose() {
    755     ++dispose_calls;
    756     if (dispose_) delete this;
    757   }
    758  private:
    759   bool dispose_;
    760 };
    761 
    762 
    763 int TestAsciiResourceWithDisposeControl::dispose_count = 0;
    764 int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    765 
    766 
    767 TEST(ExternalStringWithDisposeHandling) {
    768   const char* c_source = "1 + 2 * 3";
    769 
    770   // Use a stack allocated external string resource allocated object.
    771   TestAsciiResourceWithDisposeControl::dispose_count = 0;
    772   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    773   TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
    774   {
    775     LocalContext env;
    776     v8::HandleScope scope(env->GetIsolate());
    777     Local<String> source =  String::NewExternal(&res_stack);
    778     Local<Script> script = Script::Compile(source);
    779     Local<Value> value = script->Run();
    780     CHECK(value->IsNumber());
    781     CHECK_EQ(7, value->Int32Value());
    782     HEAP->CollectAllAvailableGarbage();
    783     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
    784   }
    785   i::Isolate::Current()->compilation_cache()->Clear();
    786   HEAP->CollectAllAvailableGarbage();
    787   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
    788   CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
    789 
    790   // Use a heap allocated external string resource allocated object.
    791   TestAsciiResourceWithDisposeControl::dispose_count = 0;
    792   TestAsciiResourceWithDisposeControl::dispose_calls = 0;
    793   TestAsciiResource* res_heap =
    794       new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
    795   {
    796     LocalContext env;
    797     v8::HandleScope scope(env->GetIsolate());
    798     Local<String> source =  String::NewExternal(res_heap);
    799     Local<Script> script = Script::Compile(source);
    800     Local<Value> value = script->Run();
    801     CHECK(value->IsNumber());
    802     CHECK_EQ(7, value->Int32Value());
    803     HEAP->CollectAllAvailableGarbage();
    804     CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
    805   }
    806   i::Isolate::Current()->compilation_cache()->Clear();
    807   HEAP->CollectAllAvailableGarbage();
    808   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
    809   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
    810 }
    811 
    812 
    813 THREADED_TEST(StringConcat) {
    814   {
    815     LocalContext env;
    816     v8::HandleScope scope(env->GetIsolate());
    817     const char* one_byte_string_1 = "function a_times_t";
    818     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
    819     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
    820     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
    821     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    822     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    823     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
    824     Local<String> left = v8_str(one_byte_string_1);
    825 
    826     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
    827     Local<String> right = String::New(two_byte_source);
    828     i::DeleteArray(two_byte_source);
    829 
    830     Local<String> source = String::Concat(left, right);
    831     right = String::NewExternal(
    832         new TestAsciiResource(i::StrDup(one_byte_extern_1)));
    833     source = String::Concat(source, right);
    834     right = String::NewExternal(
    835         new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
    836     source = String::Concat(source, right);
    837     right = v8_str(one_byte_string_2);
    838     source = String::Concat(source, right);
    839 
    840     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
    841     right = String::New(two_byte_source);
    842     i::DeleteArray(two_byte_source);
    843 
    844     source = String::Concat(source, right);
    845     right = String::NewExternal(
    846         new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
    847     source = String::Concat(source, right);
    848     Local<Script> script = Script::Compile(source);
    849     Local<Value> value = script->Run();
    850     CHECK(value->IsNumber());
    851     CHECK_EQ(68, value->Int32Value());
    852   }
    853   i::Isolate::Current()->compilation_cache()->Clear();
    854   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    855   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
    856 }
    857 
    858 
    859 THREADED_TEST(GlobalProperties) {
    860   LocalContext env;
    861   v8::HandleScope scope(env->GetIsolate());
    862   v8::Handle<v8::Object> global = env->Global();
    863   global->Set(v8_str("pi"), v8_num(3.1415926));
    864   Local<Value> pi = global->Get(v8_str("pi"));
    865   CHECK_EQ(3.1415926, pi->NumberValue());
    866 }
    867 
    868 
    869 template<typename T>
    870 static void CheckReturnValue(const T& t, i::Address callback) {
    871   v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
    872   i::Object** o = *reinterpret_cast<i::Object***>(&rv);
    873   CHECK_EQ(v8::Isolate::GetCurrent(), t.GetIsolate());
    874   CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
    875   CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
    876   // Verify reset
    877   bool is_runtime = (*o)->IsTheHole();
    878   rv.Set(true);
    879   CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
    880   rv.Set(v8::Handle<v8::Object>());
    881   CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
    882   CHECK_EQ(is_runtime, (*o)->IsTheHole());
    883 
    884   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
    885   // If CPU profiler is active check that when API callback is invoked
    886   // VMState is set to EXTERNAL.
    887   if (isolate->cpu_profiler()->is_profiling()) {
    888     CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
    889     CHECK(isolate->external_callback_scope());
    890     CHECK_EQ(callback, isolate->external_callback_scope()->callback());
    891   }
    892 }
    893 
    894 
    895 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
    896                                  i::Address callback) {
    897   ApiTestFuzzer::Fuzz();
    898   CheckReturnValue(info, callback);
    899   info.GetReturnValue().Set(v8_str("bad value"));
    900   info.GetReturnValue().Set(v8_num(102));
    901 }
    902 
    903 
    904 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
    905   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
    906 }
    907 
    908 
    909 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
    910   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
    911 }
    912 
    913 static void construct_callback(
    914     const v8::FunctionCallbackInfo<Value>& info) {
    915   ApiTestFuzzer::Fuzz();
    916   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
    917   info.This()->Set(v8_str("x"), v8_num(1));
    918   info.This()->Set(v8_str("y"), v8_num(2));
    919   info.GetReturnValue().Set(v8_str("bad value"));
    920   info.GetReturnValue().Set(info.This());
    921 }
    922 
    923 
    924 static void Return239Callback(
    925     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
    926   ApiTestFuzzer::Fuzz();
    927   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
    928   info.GetReturnValue().Set(v8_str("bad value"));
    929   info.GetReturnValue().Set(v8_num(239));
    930 }
    931 
    932 
    933 template<typename Handler>
    934 static void TestFunctionTemplateInitializer(Handler handler,
    935                                             Handler handler_2) {
    936   // Test constructor calls.
    937   {
    938     LocalContext env;
    939     v8::HandleScope scope(env->GetIsolate());
    940 
    941     Local<v8::FunctionTemplate> fun_templ =
    942         v8::FunctionTemplate::New(handler);
    943     Local<Function> fun = fun_templ->GetFunction();
    944     env->Global()->Set(v8_str("obj"), fun);
    945     Local<Script> script = v8_compile("obj()");
    946     for (int i = 0; i < 30; i++) {
    947       CHECK_EQ(102, script->Run()->Int32Value());
    948     }
    949   }
    950   // Use SetCallHandler to initialize a function template, should work like
    951   // the previous one.
    952   {
    953     LocalContext env;
    954     v8::HandleScope scope(env->GetIsolate());
    955 
    956     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
    957     fun_templ->SetCallHandler(handler_2);
    958     Local<Function> fun = fun_templ->GetFunction();
    959     env->Global()->Set(v8_str("obj"), fun);
    960     Local<Script> script = v8_compile("obj()");
    961     for (int i = 0; i < 30; i++) {
    962       CHECK_EQ(102, script->Run()->Int32Value());
    963     }
    964   }
    965 }
    966 
    967 
    968 template<typename Constructor, typename Accessor>
    969 static void TestFunctionTemplateAccessor(Constructor constructor,
    970                                          Accessor accessor) {
    971   LocalContext env;
    972   v8::HandleScope scope(env->GetIsolate());
    973 
    974   Local<v8::FunctionTemplate> fun_templ =
    975       v8::FunctionTemplate::New(constructor);
    976   fun_templ->SetClassName(v8_str("funky"));
    977   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
    978   Local<Function> fun = fun_templ->GetFunction();
    979   env->Global()->Set(v8_str("obj"), fun);
    980   Local<Value> result = v8_compile("(new obj()).toString()")->Run();
    981   CHECK_EQ(v8_str("[object funky]"), result);
    982   CompileRun("var obj_instance = new obj();");
    983   Local<Script> script;
    984   script = v8_compile("obj_instance.x");
    985   for (int i = 0; i < 30; i++) {
    986     CHECK_EQ(1, script->Run()->Int32Value());
    987   }
    988   script = v8_compile("obj_instance.m");
    989   for (int i = 0; i < 30; i++) {
    990     CHECK_EQ(239, script->Run()->Int32Value());
    991   }
    992 }
    993 
    994 
    995 THREADED_PROFILED_TEST(FunctionTemplate) {
    996   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
    997   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
    998 }
    999 
   1000 
   1001 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   1002   ApiTestFuzzer::Fuzz();
   1003   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
   1004   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
   1005 }
   1006 
   1007 
   1008 template<typename Callback>
   1009 static void TestSimpleCallback(Callback callback) {
   1010   LocalContext env;
   1011   v8::HandleScope scope(env->GetIsolate());
   1012 
   1013   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   1014   object_template->Set("callback", v8::FunctionTemplate::New(callback));
   1015   v8::Local<v8::Object> object = object_template->NewInstance();
   1016   (*env)->Global()->Set(v8_str("callback_object"), object);
   1017   v8::Handle<v8::Script> script;
   1018   script = v8_compile("callback_object.callback(17)");
   1019   for (int i = 0; i < 30; i++) {
   1020     CHECK_EQ(51424, script->Run()->Int32Value());
   1021   }
   1022   script = v8_compile("callback_object.callback(17, 24)");
   1023   for (int i = 0; i < 30; i++) {
   1024     CHECK_EQ(51425, script->Run()->Int32Value());
   1025   }
   1026 }
   1027 
   1028 
   1029 THREADED_PROFILED_TEST(SimpleCallback) {
   1030   TestSimpleCallback(SimpleCallback);
   1031 }
   1032 
   1033 
   1034 template<typename T>
   1035 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
   1036 
   1037 // constant return values
   1038 static int32_t fast_return_value_int32 = 471;
   1039 static uint32_t fast_return_value_uint32 = 571;
   1040 static const double kFastReturnValueDouble = 2.7;
   1041 // variable return values
   1042 static bool fast_return_value_bool = false;
   1043 enum ReturnValueOddball {
   1044   kNullReturnValue,
   1045   kUndefinedReturnValue,
   1046   kEmptyStringReturnValue
   1047 };
   1048 static ReturnValueOddball fast_return_value_void;
   1049 static bool fast_return_value_object_is_empty = false;
   1050 
   1051 // Helper function to avoid compiler error: insufficient contextual information
   1052 // to determine type when applying FUNCTION_ADDR to a template function.
   1053 static i::Address address_of(v8::FunctionCallback callback) {
   1054   return FUNCTION_ADDR(callback);
   1055 }
   1056 
   1057 template<>
   1058 void FastReturnValueCallback<int32_t>(
   1059     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1060   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
   1061   info.GetReturnValue().Set(fast_return_value_int32);
   1062 }
   1063 
   1064 template<>
   1065 void FastReturnValueCallback<uint32_t>(
   1066     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1067   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
   1068   info.GetReturnValue().Set(fast_return_value_uint32);
   1069 }
   1070 
   1071 template<>
   1072 void FastReturnValueCallback<double>(
   1073     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1074   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
   1075   info.GetReturnValue().Set(kFastReturnValueDouble);
   1076 }
   1077 
   1078 template<>
   1079 void FastReturnValueCallback<bool>(
   1080     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1081   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
   1082   info.GetReturnValue().Set(fast_return_value_bool);
   1083 }
   1084 
   1085 template<>
   1086 void FastReturnValueCallback<void>(
   1087     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1088   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
   1089   switch (fast_return_value_void) {
   1090     case kNullReturnValue:
   1091       info.GetReturnValue().SetNull();
   1092       break;
   1093     case kUndefinedReturnValue:
   1094       info.GetReturnValue().SetUndefined();
   1095       break;
   1096     case kEmptyStringReturnValue:
   1097       info.GetReturnValue().SetEmptyString();
   1098       break;
   1099   }
   1100 }
   1101 
   1102 template<>
   1103 void FastReturnValueCallback<Object>(
   1104     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1105   v8::Handle<v8::Object> object;
   1106   if (!fast_return_value_object_is_empty) object = Object::New();
   1107   info.GetReturnValue().Set(object);
   1108 }
   1109 
   1110 template<typename T>
   1111 Handle<Value> TestFastReturnValues() {
   1112   LocalContext env;
   1113   v8::HandleScope scope(env->GetIsolate());
   1114   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   1115   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
   1116   object_template->Set("callback", v8::FunctionTemplate::New(callback));
   1117   v8::Local<v8::Object> object = object_template->NewInstance();
   1118   (*env)->Global()->Set(v8_str("callback_object"), object);
   1119   return scope.Close(CompileRun("callback_object.callback()"));
   1120 }
   1121 
   1122 
   1123 THREADED_PROFILED_TEST(FastReturnValues) {
   1124   LocalContext env;
   1125   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1126   v8::Handle<v8::Value> value;
   1127   // check int32_t and uint32_t
   1128   int32_t int_values[] = {
   1129       0, 234, -723,
   1130       i::Smi::kMinValue, i::Smi::kMaxValue
   1131   };
   1132   for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
   1133     for (int modifier = -1; modifier <= 1; modifier++) {
   1134       int int_value = int_values[i] + modifier;
   1135       // check int32_t
   1136       fast_return_value_int32 = int_value;
   1137       value = TestFastReturnValues<int32_t>();
   1138       CHECK(value->IsInt32());
   1139       CHECK(fast_return_value_int32 == value->Int32Value());
   1140       // check uint32_t
   1141       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
   1142       value = TestFastReturnValues<uint32_t>();
   1143       CHECK(value->IsUint32());
   1144       CHECK(fast_return_value_uint32 == value->Uint32Value());
   1145     }
   1146   }
   1147   // check double
   1148   value = TestFastReturnValues<double>();
   1149   CHECK(value->IsNumber());
   1150   CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
   1151   // check bool values
   1152   for (int i = 0; i < 2; i++) {
   1153     fast_return_value_bool = i == 0;
   1154     value = TestFastReturnValues<bool>();
   1155     CHECK(value->IsBoolean());
   1156     CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
   1157   }
   1158   // check oddballs
   1159   ReturnValueOddball oddballs[] = {
   1160       kNullReturnValue,
   1161       kUndefinedReturnValue,
   1162       kEmptyStringReturnValue
   1163   };
   1164   for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
   1165     fast_return_value_void = oddballs[i];
   1166     value = TestFastReturnValues<void>();
   1167     switch (fast_return_value_void) {
   1168       case kNullReturnValue:
   1169         CHECK(value->IsNull());
   1170         break;
   1171       case kUndefinedReturnValue:
   1172         CHECK(value->IsUndefined());
   1173         break;
   1174       case kEmptyStringReturnValue:
   1175         CHECK(value->IsString());
   1176         CHECK_EQ(0, v8::String::Cast(*value)->Length());
   1177         break;
   1178     }
   1179   }
   1180   // check handles
   1181   fast_return_value_object_is_empty = false;
   1182   value = TestFastReturnValues<Object>();
   1183   CHECK(value->IsObject());
   1184   fast_return_value_object_is_empty = true;
   1185   value = TestFastReturnValues<Object>();
   1186   CHECK(value->IsUndefined());
   1187 }
   1188 
   1189 
   1190 THREADED_TEST(FunctionTemplateSetLength) {
   1191   LocalContext env;
   1192   v8::HandleScope scope(env->GetIsolate());
   1193   {
   1194     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(
   1195         handle_callback, Handle<v8::Value>(), Handle<v8::Signature>(), 23);
   1196     Local<Function> fun = fun_templ->GetFunction();
   1197     env->Global()->Set(v8_str("obj"), fun);
   1198     Local<Script> script = v8_compile("obj.length");
   1199     CHECK_EQ(23, script->Run()->Int32Value());
   1200   }
   1201   {
   1202     Local<v8::FunctionTemplate> fun_templ =
   1203         v8::FunctionTemplate::New(handle_callback);
   1204     fun_templ->SetLength(22);
   1205     Local<Function> fun = fun_templ->GetFunction();
   1206     env->Global()->Set(v8_str("obj"), fun);
   1207     Local<Script> script = v8_compile("obj.length");
   1208     CHECK_EQ(22, script->Run()->Int32Value());
   1209   }
   1210   {
   1211     // Without setting length it defaults to 0.
   1212     Local<v8::FunctionTemplate> fun_templ =
   1213         v8::FunctionTemplate::New(handle_callback);
   1214     Local<Function> fun = fun_templ->GetFunction();
   1215     env->Global()->Set(v8_str("obj"), fun);
   1216     Local<Script> script = v8_compile("obj.length");
   1217     CHECK_EQ(0, script->Run()->Int32Value());
   1218   }
   1219 }
   1220 
   1221 
   1222 static void* expected_ptr;
   1223 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1224   void* ptr = v8::External::Cast(*args.Data())->Value();
   1225   CHECK_EQ(expected_ptr, ptr);
   1226   args.GetReturnValue().Set(true);
   1227 }
   1228 
   1229 
   1230 static void TestExternalPointerWrapping() {
   1231   LocalContext env;
   1232   v8::HandleScope scope(env->GetIsolate());
   1233 
   1234   v8::Handle<v8::Value> data = v8::External::New(expected_ptr);
   1235 
   1236   v8::Handle<v8::Object> obj = v8::Object::New();
   1237   obj->Set(v8_str("func"),
   1238            v8::FunctionTemplate::New(callback, data)->GetFunction());
   1239   env->Global()->Set(v8_str("obj"), obj);
   1240 
   1241   CHECK(CompileRun(
   1242         "function foo() {\n"
   1243         "  for (var i = 0; i < 13; i++) obj.func();\n"
   1244         "}\n"
   1245         "foo(), true")->BooleanValue());
   1246 }
   1247 
   1248 
   1249 THREADED_TEST(ExternalWrap) {
   1250   // Check heap allocated object.
   1251   int* ptr = new int;
   1252   expected_ptr = ptr;
   1253   TestExternalPointerWrapping();
   1254   delete ptr;
   1255 
   1256   // Check stack allocated object.
   1257   int foo;
   1258   expected_ptr = &foo;
   1259   TestExternalPointerWrapping();
   1260 
   1261   // Check not aligned addresses.
   1262   const int n = 100;
   1263   char* s = new char[n];
   1264   for (int i = 0; i < n; i++) {
   1265     expected_ptr = s + i;
   1266     TestExternalPointerWrapping();
   1267   }
   1268 
   1269   delete[] s;
   1270 
   1271   // Check several invalid addresses.
   1272   expected_ptr = reinterpret_cast<void*>(1);
   1273   TestExternalPointerWrapping();
   1274 
   1275   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
   1276   TestExternalPointerWrapping();
   1277 
   1278   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
   1279   TestExternalPointerWrapping();
   1280 
   1281 #if defined(V8_HOST_ARCH_X64)
   1282   // Check a value with a leading 1 bit in x64 Smi encoding.
   1283   expected_ptr = reinterpret_cast<void*>(0x400000000);
   1284   TestExternalPointerWrapping();
   1285 
   1286   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
   1287   TestExternalPointerWrapping();
   1288 
   1289   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
   1290   TestExternalPointerWrapping();
   1291 #endif
   1292 }
   1293 
   1294 
   1295 THREADED_TEST(FindInstanceInPrototypeChain) {
   1296   LocalContext env;
   1297   v8::HandleScope scope(env->GetIsolate());
   1298 
   1299   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
   1300   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
   1301   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
   1302   derived->Inherit(base);
   1303 
   1304   Local<v8::Function> base_function = base->GetFunction();
   1305   Local<v8::Function> derived_function = derived->GetFunction();
   1306   Local<v8::Function> other_function = other->GetFunction();
   1307 
   1308   Local<v8::Object> base_instance = base_function->NewInstance();
   1309   Local<v8::Object> derived_instance = derived_function->NewInstance();
   1310   Local<v8::Object> derived_instance2 = derived_function->NewInstance();
   1311   Local<v8::Object> other_instance = other_function->NewInstance();
   1312   derived_instance2->Set(v8_str("__proto__"), derived_instance);
   1313   other_instance->Set(v8_str("__proto__"), derived_instance2);
   1314 
   1315   // base_instance is only an instance of base.
   1316   CHECK_EQ(base_instance,
   1317            base_instance->FindInstanceInPrototypeChain(base));
   1318   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
   1319   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1320 
   1321   // derived_instance is an instance of base and derived.
   1322   CHECK_EQ(derived_instance,
   1323            derived_instance->FindInstanceInPrototypeChain(base));
   1324   CHECK_EQ(derived_instance,
   1325            derived_instance->FindInstanceInPrototypeChain(derived));
   1326   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1327 
   1328   // other_instance is an instance of other and its immediate
   1329   // prototype derived_instance2 is an instance of base and derived.
   1330   // Note, derived_instance is an instance of base and derived too,
   1331   // but it comes after derived_instance2 in the prototype chain of
   1332   // other_instance.
   1333   CHECK_EQ(derived_instance2,
   1334            other_instance->FindInstanceInPrototypeChain(base));
   1335   CHECK_EQ(derived_instance2,
   1336            other_instance->FindInstanceInPrototypeChain(derived));
   1337   CHECK_EQ(other_instance,
   1338            other_instance->FindInstanceInPrototypeChain(other));
   1339 }
   1340 
   1341 
   1342 THREADED_TEST(TinyInteger) {
   1343   LocalContext env;
   1344   v8::HandleScope scope(env->GetIsolate());
   1345   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   1346 
   1347   int32_t value = 239;
   1348   Local<v8::Integer> value_obj = v8::Integer::New(value);
   1349   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1350 
   1351   value_obj = v8::Integer::New(value, isolate);
   1352   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1353 }
   1354 
   1355 
   1356 THREADED_TEST(BigSmiInteger) {
   1357   LocalContext env;
   1358   v8::HandleScope scope(env->GetIsolate());
   1359   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   1360 
   1361   int32_t value = i::Smi::kMaxValue;
   1362   // We cannot add one to a Smi::kMaxValue without wrapping.
   1363   if (i::kSmiValueSize < 32) {
   1364     CHECK(i::Smi::IsValid(value));
   1365     CHECK(!i::Smi::IsValid(value + 1));
   1366 
   1367     Local<v8::Integer> value_obj = v8::Integer::New(value);
   1368     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1369 
   1370     value_obj = v8::Integer::New(value, isolate);
   1371     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1372   }
   1373 }
   1374 
   1375 
   1376 THREADED_TEST(BigInteger) {
   1377   LocalContext env;
   1378   v8::HandleScope scope(env->GetIsolate());
   1379   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   1380 
   1381   // We cannot add one to a Smi::kMaxValue without wrapping.
   1382   if (i::kSmiValueSize < 32) {
   1383     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
   1384     // The code will not be run in that case, due to the "if" guard.
   1385     int32_t value =
   1386         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
   1387     CHECK(value > i::Smi::kMaxValue);
   1388     CHECK(!i::Smi::IsValid(value));
   1389 
   1390     Local<v8::Integer> value_obj = v8::Integer::New(value);
   1391     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1392 
   1393     value_obj = v8::Integer::New(value, isolate);
   1394     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1395   }
   1396 }
   1397 
   1398 
   1399 THREADED_TEST(TinyUnsignedInteger) {
   1400   LocalContext env;
   1401   v8::HandleScope scope(env->GetIsolate());
   1402   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   1403 
   1404   uint32_t value = 239;
   1405 
   1406   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1407   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1408 
   1409   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
   1410   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1411 }
   1412 
   1413 
   1414 THREADED_TEST(BigUnsignedSmiInteger) {
   1415   LocalContext env;
   1416   v8::HandleScope scope(env->GetIsolate());
   1417   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   1418 
   1419   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
   1420   CHECK(i::Smi::IsValid(value));
   1421   CHECK(!i::Smi::IsValid(value + 1));
   1422 
   1423   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1424   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1425 
   1426   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
   1427   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1428 }
   1429 
   1430 
   1431 THREADED_TEST(BigUnsignedInteger) {
   1432   LocalContext env;
   1433   v8::HandleScope scope(env->GetIsolate());
   1434   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   1435 
   1436   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
   1437   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
   1438   CHECK(!i::Smi::IsValid(value));
   1439 
   1440   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1441   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1442 
   1443   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
   1444   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1445 }
   1446 
   1447 
   1448 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
   1449   LocalContext env;
   1450   v8::HandleScope scope(env->GetIsolate());
   1451   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   1452 
   1453   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
   1454   uint32_t value = INT32_MAX_AS_UINT + 1;
   1455   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
   1456 
   1457   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
   1458   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1459 
   1460   value_obj = v8::Integer::NewFromUnsigned(value, isolate);
   1461   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1462 }
   1463 
   1464 
   1465 THREADED_TEST(IsNativeError) {
   1466   LocalContext env;
   1467   v8::HandleScope scope(env->GetIsolate());
   1468   v8::Handle<Value> syntax_error = CompileRun(
   1469       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
   1470   CHECK(syntax_error->IsNativeError());
   1471   v8::Handle<Value> not_error = CompileRun("{a:42}");
   1472   CHECK(!not_error->IsNativeError());
   1473   v8::Handle<Value> not_object = CompileRun("42");
   1474   CHECK(!not_object->IsNativeError());
   1475 }
   1476 
   1477 
   1478 THREADED_TEST(StringObject) {
   1479   LocalContext env;
   1480   v8::HandleScope scope(env->GetIsolate());
   1481   v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
   1482   CHECK(boxed_string->IsStringObject());
   1483   v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
   1484   CHECK(!unboxed_string->IsStringObject());
   1485   v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
   1486   CHECK(!boxed_not_string->IsStringObject());
   1487   v8::Handle<Value> not_object = CompileRun("0");
   1488   CHECK(!not_object->IsStringObject());
   1489   v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
   1490   CHECK(!as_boxed.IsEmpty());
   1491   Local<v8::String> the_string = as_boxed->ValueOf();
   1492   CHECK(!the_string.IsEmpty());
   1493   ExpectObject("\"test\"", the_string);
   1494   v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
   1495   CHECK(new_boxed_string->IsStringObject());
   1496   as_boxed = new_boxed_string.As<v8::StringObject>();
   1497   the_string = as_boxed->ValueOf();
   1498   CHECK(!the_string.IsEmpty());
   1499   ExpectObject("\"test\"", the_string);
   1500 }
   1501 
   1502 
   1503 THREADED_TEST(NumberObject) {
   1504   LocalContext env;
   1505   v8::HandleScope scope(env->GetIsolate());
   1506   v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
   1507   CHECK(boxed_number->IsNumberObject());
   1508   v8::Handle<Value> unboxed_number = CompileRun("42");
   1509   CHECK(!unboxed_number->IsNumberObject());
   1510   v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
   1511   CHECK(!boxed_not_number->IsNumberObject());
   1512   v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
   1513   CHECK(!as_boxed.IsEmpty());
   1514   double the_number = as_boxed->ValueOf();
   1515   CHECK_EQ(42.0, the_number);
   1516   v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
   1517   CHECK(new_boxed_number->IsNumberObject());
   1518   as_boxed = new_boxed_number.As<v8::NumberObject>();
   1519   the_number = as_boxed->ValueOf();
   1520   CHECK_EQ(43.0, the_number);
   1521 }
   1522 
   1523 
   1524 THREADED_TEST(BooleanObject) {
   1525   LocalContext env;
   1526   v8::HandleScope scope(env->GetIsolate());
   1527   v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
   1528   CHECK(boxed_boolean->IsBooleanObject());
   1529   v8::Handle<Value> unboxed_boolean = CompileRun("true");
   1530   CHECK(!unboxed_boolean->IsBooleanObject());
   1531   v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
   1532   CHECK(!boxed_not_boolean->IsBooleanObject());
   1533   v8::Handle<v8::BooleanObject> as_boxed =
   1534       boxed_boolean.As<v8::BooleanObject>();
   1535   CHECK(!as_boxed.IsEmpty());
   1536   bool the_boolean = as_boxed->ValueOf();
   1537   CHECK_EQ(true, the_boolean);
   1538   v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
   1539   v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
   1540   CHECK(boxed_true->IsBooleanObject());
   1541   CHECK(boxed_false->IsBooleanObject());
   1542   as_boxed = boxed_true.As<v8::BooleanObject>();
   1543   CHECK_EQ(true, as_boxed->ValueOf());
   1544   as_boxed = boxed_false.As<v8::BooleanObject>();
   1545   CHECK_EQ(false, as_boxed->ValueOf());
   1546 }
   1547 
   1548 
   1549 THREADED_TEST(PrimitiveAndWrappedBooleans) {
   1550   LocalContext env;
   1551   v8::HandleScope scope(env->GetIsolate());
   1552 
   1553   Local<Value> primitive_false = Boolean::New(false);
   1554   CHECK(primitive_false->IsBoolean());
   1555   CHECK(!primitive_false->IsBooleanObject());
   1556   CHECK(!primitive_false->BooleanValue());
   1557   CHECK(!primitive_false->IsTrue());
   1558   CHECK(primitive_false->IsFalse());
   1559 
   1560   Local<Value> false_value = BooleanObject::New(false);
   1561   CHECK(!false_value->IsBoolean());
   1562   CHECK(false_value->IsBooleanObject());
   1563   CHECK(false_value->BooleanValue());
   1564   CHECK(!false_value->IsTrue());
   1565   CHECK(!false_value->IsFalse());
   1566 
   1567   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
   1568   CHECK(!false_boolean_object->IsBoolean());
   1569   CHECK(false_boolean_object->IsBooleanObject());
   1570   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
   1571   // CHECK(false_boolean_object->BooleanValue());
   1572   CHECK(!false_boolean_object->ValueOf());
   1573   CHECK(!false_boolean_object->IsTrue());
   1574   CHECK(!false_boolean_object->IsFalse());
   1575 
   1576   Local<Value> primitive_true = Boolean::New(true);
   1577   CHECK(primitive_true->IsBoolean());
   1578   CHECK(!primitive_true->IsBooleanObject());
   1579   CHECK(primitive_true->BooleanValue());
   1580   CHECK(primitive_true->IsTrue());
   1581   CHECK(!primitive_true->IsFalse());
   1582 
   1583   Local<Value> true_value = BooleanObject::New(true);
   1584   CHECK(!true_value->IsBoolean());
   1585   CHECK(true_value->IsBooleanObject());
   1586   CHECK(true_value->BooleanValue());
   1587   CHECK(!true_value->IsTrue());
   1588   CHECK(!true_value->IsFalse());
   1589 
   1590   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
   1591   CHECK(!true_boolean_object->IsBoolean());
   1592   CHECK(true_boolean_object->IsBooleanObject());
   1593   // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
   1594   // CHECK(true_boolean_object->BooleanValue());
   1595   CHECK(true_boolean_object->ValueOf());
   1596   CHECK(!true_boolean_object->IsTrue());
   1597   CHECK(!true_boolean_object->IsFalse());
   1598 }
   1599 
   1600 
   1601 THREADED_TEST(Number) {
   1602   LocalContext env;
   1603   v8::HandleScope scope(env->GetIsolate());
   1604   double PI = 3.1415926;
   1605   Local<v8::Number> pi_obj = v8::Number::New(PI);
   1606   CHECK_EQ(PI, pi_obj->NumberValue());
   1607 }
   1608 
   1609 
   1610 THREADED_TEST(ToNumber) {
   1611   LocalContext env;
   1612   v8::HandleScope scope(env->GetIsolate());
   1613   Local<String> str = v8_str("3.1415926");
   1614   CHECK_EQ(3.1415926, str->NumberValue());
   1615   v8::Handle<v8::Boolean> t = v8::True();
   1616   CHECK_EQ(1.0, t->NumberValue());
   1617   v8::Handle<v8::Boolean> f = v8::False();
   1618   CHECK_EQ(0.0, f->NumberValue());
   1619 }
   1620 
   1621 
   1622 THREADED_TEST(Date) {
   1623   LocalContext env;
   1624   v8::HandleScope scope(env->GetIsolate());
   1625   double PI = 3.1415926;
   1626   Local<Value> date = v8::Date::New(PI);
   1627   CHECK_EQ(3.0, date->NumberValue());
   1628   date.As<v8::Date>()->Set(v8_str("property"), v8::Integer::New(42));
   1629   CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
   1630 }
   1631 
   1632 
   1633 THREADED_TEST(Boolean) {
   1634   LocalContext env;
   1635   v8::HandleScope scope(env->GetIsolate());
   1636   v8::Handle<v8::Boolean> t = v8::True();
   1637   CHECK(t->Value());
   1638   v8::Handle<v8::Boolean> f = v8::False();
   1639   CHECK(!f->Value());
   1640   v8::Handle<v8::Primitive> u = v8::Undefined();
   1641   CHECK(!u->BooleanValue());
   1642   v8::Handle<v8::Primitive> n = v8::Null();
   1643   CHECK(!n->BooleanValue());
   1644   v8::Handle<String> str1 = v8_str("");
   1645   CHECK(!str1->BooleanValue());
   1646   v8::Handle<String> str2 = v8_str("x");
   1647   CHECK(str2->BooleanValue());
   1648   CHECK(!v8::Number::New(0)->BooleanValue());
   1649   CHECK(v8::Number::New(-1)->BooleanValue());
   1650   CHECK(v8::Number::New(1)->BooleanValue());
   1651   CHECK(v8::Number::New(42)->BooleanValue());
   1652   CHECK(!v8_compile("NaN")->Run()->BooleanValue());
   1653 }
   1654 
   1655 
   1656 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1657   ApiTestFuzzer::Fuzz();
   1658   args.GetReturnValue().Set(v8_num(13.4));
   1659 }
   1660 
   1661 
   1662 static void GetM(Local<String> name,
   1663                  const v8::PropertyCallbackInfo<v8::Value>& info) {
   1664   ApiTestFuzzer::Fuzz();
   1665   info.GetReturnValue().Set(v8_num(876));
   1666 }
   1667 
   1668 
   1669 THREADED_TEST(GlobalPrototype) {
   1670   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1671   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
   1672   func_templ->PrototypeTemplate()->Set(
   1673       "dummy",
   1674       v8::FunctionTemplate::New(DummyCallHandler));
   1675   v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
   1676   templ->Set("x", v8_num(200));
   1677   templ->SetAccessor(v8_str("m"), GetM);
   1678   LocalContext env(0, templ);
   1679   v8::Handle<Script> script(v8_compile("dummy()"));
   1680   v8::Handle<Value> result(script->Run());
   1681   CHECK_EQ(13.4, result->NumberValue());
   1682   CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
   1683   CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
   1684 }
   1685 
   1686 
   1687 THREADED_TEST(ObjectTemplate) {
   1688   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1689   Local<ObjectTemplate> templ1 = ObjectTemplate::New();
   1690   templ1->Set("x", v8_num(10));
   1691   templ1->Set("y", v8_num(13));
   1692   LocalContext env;
   1693   Local<v8::Object> instance1 = templ1->NewInstance();
   1694   env->Global()->Set(v8_str("p"), instance1);
   1695   CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
   1696   CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
   1697   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
   1698   fun->PrototypeTemplate()->Set("nirk", v8_num(123));
   1699   Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
   1700   templ2->Set("a", v8_num(12));
   1701   templ2->Set("b", templ1);
   1702   Local<v8::Object> instance2 = templ2->NewInstance();
   1703   env->Global()->Set(v8_str("q"), instance2);
   1704   CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
   1705   CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
   1706   CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
   1707   CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
   1708 }
   1709 
   1710 
   1711 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1712   ApiTestFuzzer::Fuzz();
   1713   args.GetReturnValue().Set(v8_num(17.2));
   1714 }
   1715 
   1716 
   1717 static void GetKnurd(Local<String> property,
   1718                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   1719   ApiTestFuzzer::Fuzz();
   1720   info.GetReturnValue().Set(v8_num(15.2));
   1721 }
   1722 
   1723 
   1724 THREADED_TEST(DescriptorInheritance) {
   1725   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1726   v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
   1727   super->PrototypeTemplate()->Set("flabby",
   1728                                   v8::FunctionTemplate::New(GetFlabby));
   1729   super->PrototypeTemplate()->Set("PI", v8_num(3.14));
   1730 
   1731   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
   1732 
   1733   v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
   1734   base1->Inherit(super);
   1735   base1->PrototypeTemplate()->Set("v1", v8_num(20.1));
   1736 
   1737   v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
   1738   base2->Inherit(super);
   1739   base2->PrototypeTemplate()->Set("v2", v8_num(10.1));
   1740 
   1741   LocalContext env;
   1742 
   1743   env->Global()->Set(v8_str("s"), super->GetFunction());
   1744   env->Global()->Set(v8_str("base1"), base1->GetFunction());
   1745   env->Global()->Set(v8_str("base2"), base2->GetFunction());
   1746 
   1747   // Checks right __proto__ chain.
   1748   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
   1749   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
   1750 
   1751   CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
   1752 
   1753   // Instance accessor should not be visible on function object or its prototype
   1754   CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
   1755   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
   1756   CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
   1757 
   1758   env->Global()->Set(v8_str("obj"),
   1759                      base1->GetFunction()->NewInstance());
   1760   CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
   1761   CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
   1762   CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
   1763   CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
   1764   CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
   1765 
   1766   env->Global()->Set(v8_str("obj2"),
   1767                      base2->GetFunction()->NewInstance());
   1768   CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
   1769   CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
   1770   CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
   1771   CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
   1772   CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
   1773 
   1774   // base1 and base2 cannot cross reference to each's prototype
   1775   CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
   1776   CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
   1777 }
   1778 
   1779 
   1780 int echo_named_call_count;
   1781 
   1782 
   1783 static void EchoNamedProperty(Local<String> name,
   1784                               const v8::PropertyCallbackInfo<v8::Value>& info) {
   1785   ApiTestFuzzer::Fuzz();
   1786   CHECK_EQ(v8_str("data"), info.Data());
   1787   echo_named_call_count++;
   1788   info.GetReturnValue().Set(name);
   1789 }
   1790 
   1791 
   1792 // Helper functions for Interceptor/Accessor interaction tests
   1793 
   1794 void SimpleAccessorGetter(Local<String> name,
   1795                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   1796   Handle<Object> self = info.This();
   1797   info.GetReturnValue().Set(
   1798       self->Get(String::Concat(v8_str("accessor_"), name)));
   1799 }
   1800 
   1801 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
   1802                           const v8::PropertyCallbackInfo<void>& info) {
   1803   Handle<Object> self = info.This();
   1804   self->Set(String::Concat(v8_str("accessor_"), name), value);
   1805 }
   1806 
   1807 void EmptyInterceptorGetter(Local<String> name,
   1808                             const v8::PropertyCallbackInfo<v8::Value>& info) {
   1809 }
   1810 
   1811 void EmptyInterceptorSetter(Local<String> name,
   1812                             Local<Value> value,
   1813                             const v8::PropertyCallbackInfo<v8::Value>& info) {
   1814 }
   1815 
   1816 void InterceptorGetter(Local<String> name,
   1817                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   1818   // Intercept names that start with 'interceptor_'.
   1819   String::Utf8Value utf8(name);
   1820   char* name_str = *utf8;
   1821   char prefix[] = "interceptor_";
   1822   int i;
   1823   for (i = 0; name_str[i] && prefix[i]; ++i) {
   1824     if (name_str[i] != prefix[i]) return;
   1825   }
   1826   Handle<Object> self = info.This();
   1827   info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
   1828 }
   1829 
   1830 void InterceptorSetter(Local<String> name,
   1831                        Local<Value> value,
   1832                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   1833   // Intercept accesses that set certain integer values.
   1834   if (value->IsInt32() && value->Int32Value() < 10000) {
   1835     Handle<Object> self = info.This();
   1836     self->SetHiddenValue(name, value);
   1837     info.GetReturnValue().Set(value);
   1838   }
   1839 }
   1840 
   1841 void AddAccessor(Handle<FunctionTemplate> templ,
   1842                  Handle<String> name,
   1843                  v8::AccessorGetterCallback getter,
   1844                  v8::AccessorSetterCallback setter) {
   1845   templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
   1846 }
   1847 
   1848 void AddInterceptor(Handle<FunctionTemplate> templ,
   1849                     v8::NamedPropertyGetterCallback getter,
   1850                     v8::NamedPropertySetterCallback setter) {
   1851   templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
   1852 }
   1853 
   1854 
   1855 THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
   1856   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1857   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1858   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1859   child->Inherit(parent);
   1860   AddAccessor(parent, v8_str("age"),
   1861               SimpleAccessorGetter, SimpleAccessorSetter);
   1862   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   1863   LocalContext env;
   1864   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1865   CompileRun("var child = new Child;"
   1866              "child.age = 10;");
   1867   ExpectBoolean("child.hasOwnProperty('age')", false);
   1868   ExpectInt32("child.age", 10);
   1869   ExpectInt32("child.accessor_age", 10);
   1870 }
   1871 
   1872 
   1873 THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
   1874   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1875   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1876   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1877   child->Inherit(parent);
   1878   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   1879   LocalContext env;
   1880   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1881   CompileRun("var child = new Child;"
   1882              "var parent = child.__proto__;"
   1883              "Object.defineProperty(parent, 'age', "
   1884              "  {get: function(){ return this.accessor_age; }, "
   1885              "   set: function(v){ this.accessor_age = v; }, "
   1886              "   enumerable: true, configurable: true});"
   1887              "child.age = 10;");
   1888   ExpectBoolean("child.hasOwnProperty('age')", false);
   1889   ExpectInt32("child.age", 10);
   1890   ExpectInt32("child.accessor_age", 10);
   1891 }
   1892 
   1893 
   1894 THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
   1895   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1896   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1897   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1898   child->Inherit(parent);
   1899   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
   1900   LocalContext env;
   1901   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1902   CompileRun("var child = new Child;"
   1903              "var parent = child.__proto__;"
   1904              "parent.name = 'Alice';");
   1905   ExpectBoolean("child.hasOwnProperty('name')", false);
   1906   ExpectString("child.name", "Alice");
   1907   CompileRun("child.name = 'Bob';");
   1908   ExpectString("child.name", "Bob");
   1909   ExpectBoolean("child.hasOwnProperty('name')", true);
   1910   ExpectString("parent.name", "Alice");
   1911 }
   1912 
   1913 
   1914 THREADED_TEST(SwitchFromInterceptorToAccessor) {
   1915   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1916   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   1917   AddAccessor(templ, v8_str("age"),
   1918               SimpleAccessorGetter, SimpleAccessorSetter);
   1919   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   1920   LocalContext env;
   1921   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   1922   CompileRun("var obj = new Obj;"
   1923              "function setAge(i){ obj.age = i; };"
   1924              "for(var i = 0; i <= 10000; i++) setAge(i);");
   1925   // All i < 10000 go to the interceptor.
   1926   ExpectInt32("obj.interceptor_age", 9999);
   1927   // The last i goes to the accessor.
   1928   ExpectInt32("obj.accessor_age", 10000);
   1929 }
   1930 
   1931 
   1932 THREADED_TEST(SwitchFromAccessorToInterceptor) {
   1933   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1934   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   1935   AddAccessor(templ, v8_str("age"),
   1936               SimpleAccessorGetter, SimpleAccessorSetter);
   1937   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   1938   LocalContext env;
   1939   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   1940   CompileRun("var obj = new Obj;"
   1941              "function setAge(i){ obj.age = i; };"
   1942              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   1943   // All i >= 10000 go to the accessor.
   1944   ExpectInt32("obj.accessor_age", 10000);
   1945   // The last i goes to the interceptor.
   1946   ExpectInt32("obj.interceptor_age", 9999);
   1947 }
   1948 
   1949 
   1950 THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
   1951   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1952   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1953   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1954   child->Inherit(parent);
   1955   AddAccessor(parent, v8_str("age"),
   1956               SimpleAccessorGetter, SimpleAccessorSetter);
   1957   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   1958   LocalContext env;
   1959   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1960   CompileRun("var child = new Child;"
   1961              "function setAge(i){ child.age = i; };"
   1962              "for(var i = 0; i <= 10000; i++) setAge(i);");
   1963   // All i < 10000 go to the interceptor.
   1964   ExpectInt32("child.interceptor_age", 9999);
   1965   // The last i goes to the accessor.
   1966   ExpectInt32("child.accessor_age", 10000);
   1967 }
   1968 
   1969 
   1970 THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
   1971   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1972   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   1973   Handle<FunctionTemplate> child = FunctionTemplate::New();
   1974   child->Inherit(parent);
   1975   AddAccessor(parent, v8_str("age"),
   1976               SimpleAccessorGetter, SimpleAccessorSetter);
   1977   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   1978   LocalContext env;
   1979   env->Global()->Set(v8_str("Child"), child->GetFunction());
   1980   CompileRun("var child = new Child;"
   1981              "function setAge(i){ child.age = i; };"
   1982              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   1983   // All i >= 10000 go to the accessor.
   1984   ExpectInt32("child.accessor_age", 10000);
   1985   // The last i goes to the interceptor.
   1986   ExpectInt32("child.interceptor_age", 9999);
   1987 }
   1988 
   1989 
   1990 THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
   1991   v8::HandleScope scope(v8::Isolate::GetCurrent());
   1992   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   1993   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   1994   LocalContext env;
   1995   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   1996   CompileRun("var obj = new Obj;"
   1997              "function setter(i) { this.accessor_age = i; };"
   1998              "function getter() { return this.accessor_age; };"
   1999              "function setAge(i) { obj.age = i; };"
   2000              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   2001              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2002   // All i < 10000 go to the interceptor.
   2003   ExpectInt32("obj.interceptor_age", 9999);
   2004   // The last i goes to the JavaScript accessor.
   2005   ExpectInt32("obj.accessor_age", 10000);
   2006   // The installed JavaScript getter is still intact.
   2007   // This last part is a regression test for issue 1651 and relies on the fact
   2008   // that both interceptor and accessor are being installed on the same object.
   2009   ExpectInt32("obj.age", 10000);
   2010   ExpectBoolean("obj.hasOwnProperty('age')", true);
   2011   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
   2012 }
   2013 
   2014 
   2015 THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
   2016   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2017   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   2018   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
   2019   LocalContext env;
   2020   env->Global()->Set(v8_str("Obj"), templ->GetFunction());
   2021   CompileRun("var obj = new Obj;"
   2022              "function setter(i) { this.accessor_age = i; };"
   2023              "function getter() { return this.accessor_age; };"
   2024              "function setAge(i) { obj.age = i; };"
   2025              "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
   2026              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2027   // All i >= 10000 go to the accessor.
   2028   ExpectInt32("obj.accessor_age", 10000);
   2029   // The last i goes to the interceptor.
   2030   ExpectInt32("obj.interceptor_age", 9999);
   2031   // The installed JavaScript getter is still intact.
   2032   // This last part is a regression test for issue 1651 and relies on the fact
   2033   // that both interceptor and accessor are being installed on the same object.
   2034   ExpectInt32("obj.age", 10000);
   2035   ExpectBoolean("obj.hasOwnProperty('age')", true);
   2036   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
   2037 }
   2038 
   2039 
   2040 THREADED_TEST(SwitchFromInterceptorToProperty) {
   2041   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2042   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   2043   Handle<FunctionTemplate> child = FunctionTemplate::New();
   2044   child->Inherit(parent);
   2045   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2046   LocalContext env;
   2047   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2048   CompileRun("var child = new Child;"
   2049              "function setAge(i){ child.age = i; };"
   2050              "for(var i = 0; i <= 10000; i++) setAge(i);");
   2051   // All i < 10000 go to the interceptor.
   2052   ExpectInt32("child.interceptor_age", 9999);
   2053   // The last i goes to child's own property.
   2054   ExpectInt32("child.age", 10000);
   2055 }
   2056 
   2057 
   2058 THREADED_TEST(SwitchFromPropertyToInterceptor) {
   2059   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2060   Handle<FunctionTemplate> parent = FunctionTemplate::New();
   2061   Handle<FunctionTemplate> child = FunctionTemplate::New();
   2062   child->Inherit(parent);
   2063   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
   2064   LocalContext env;
   2065   env->Global()->Set(v8_str("Child"), child->GetFunction());
   2066   CompileRun("var child = new Child;"
   2067              "function setAge(i){ child.age = i; };"
   2068              "for(var i = 20000; i >= 9999; i--) setAge(i);");
   2069   // All i >= 10000 go to child's own property.
   2070   ExpectInt32("child.age", 10000);
   2071   // The last i goes to the interceptor.
   2072   ExpectInt32("child.interceptor_age", 9999);
   2073 }
   2074 
   2075 
   2076 THREADED_TEST(NamedPropertyHandlerGetter) {
   2077   echo_named_call_count = 0;
   2078   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2079   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2080   templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
   2081                                                      0, 0, 0, 0,
   2082                                                      v8_str("data"));
   2083   LocalContext env;
   2084   env->Global()->Set(v8_str("obj"),
   2085                      templ->GetFunction()->NewInstance());
   2086   CHECK_EQ(echo_named_call_count, 0);
   2087   v8_compile("obj.x")->Run();
   2088   CHECK_EQ(echo_named_call_count, 1);
   2089   const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
   2090   v8::Handle<Value> str = CompileRun(code);
   2091   String::Utf8Value value(str);
   2092   CHECK_EQ(*value, "oddlepoddle");
   2093   // Check default behavior
   2094   CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
   2095   CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
   2096   CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
   2097 }
   2098 
   2099 
   2100 int echo_indexed_call_count = 0;
   2101 
   2102 
   2103 static void EchoIndexedProperty(
   2104     uint32_t index,
   2105     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2106   ApiTestFuzzer::Fuzz();
   2107   CHECK_EQ(v8_num(637), info.Data());
   2108   echo_indexed_call_count++;
   2109   info.GetReturnValue().Set(v8_num(index));
   2110 }
   2111 
   2112 
   2113 THREADED_TEST(IndexedPropertyHandlerGetter) {
   2114   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2115   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2116   templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
   2117                                                        0, 0, 0, 0,
   2118                                                        v8_num(637));
   2119   LocalContext env;
   2120   env->Global()->Set(v8_str("obj"),
   2121                      templ->GetFunction()->NewInstance());
   2122   Local<Script> script = v8_compile("obj[900]");
   2123   CHECK_EQ(script->Run()->Int32Value(), 900);
   2124 }
   2125 
   2126 
   2127 v8::Handle<v8::Object> bottom;
   2128 
   2129 static void CheckThisIndexedPropertyHandler(
   2130     uint32_t index,
   2131     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2132   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
   2133   ApiTestFuzzer::Fuzz();
   2134   CHECK(info.This()->Equals(bottom));
   2135 }
   2136 
   2137 static void CheckThisNamedPropertyHandler(
   2138     Local<String> name,
   2139     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2140   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
   2141   ApiTestFuzzer::Fuzz();
   2142   CHECK(info.This()->Equals(bottom));
   2143 }
   2144 
   2145 void CheckThisIndexedPropertySetter(
   2146     uint32_t index,
   2147     Local<Value> value,
   2148     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2149   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
   2150   ApiTestFuzzer::Fuzz();
   2151   CHECK(info.This()->Equals(bottom));
   2152 }
   2153 
   2154 
   2155 void CheckThisNamedPropertySetter(
   2156     Local<String> property,
   2157     Local<Value> value,
   2158     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2159   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
   2160   ApiTestFuzzer::Fuzz();
   2161   CHECK(info.This()->Equals(bottom));
   2162 }
   2163 
   2164 void CheckThisIndexedPropertyQuery(
   2165     uint32_t index,
   2166     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   2167   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
   2168   ApiTestFuzzer::Fuzz();
   2169   CHECK(info.This()->Equals(bottom));
   2170 }
   2171 
   2172 
   2173 void CheckThisNamedPropertyQuery(
   2174     Local<String> property,
   2175     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   2176   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
   2177   ApiTestFuzzer::Fuzz();
   2178   CHECK(info.This()->Equals(bottom));
   2179 }
   2180 
   2181 
   2182 void CheckThisIndexedPropertyDeleter(
   2183     uint32_t index,
   2184     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   2185   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
   2186   ApiTestFuzzer::Fuzz();
   2187   CHECK(info.This()->Equals(bottom));
   2188 }
   2189 
   2190 
   2191 void CheckThisNamedPropertyDeleter(
   2192     Local<String> property,
   2193     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   2194   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
   2195   ApiTestFuzzer::Fuzz();
   2196   CHECK(info.This()->Equals(bottom));
   2197 }
   2198 
   2199 
   2200 void CheckThisIndexedPropertyEnumerator(
   2201     const v8::PropertyCallbackInfo<v8::Array>& info) {
   2202   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
   2203   ApiTestFuzzer::Fuzz();
   2204   CHECK(info.This()->Equals(bottom));
   2205 }
   2206 
   2207 
   2208 void CheckThisNamedPropertyEnumerator(
   2209     const v8::PropertyCallbackInfo<v8::Array>& info) {
   2210   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
   2211   ApiTestFuzzer::Fuzz();
   2212   CHECK(info.This()->Equals(bottom));
   2213 }
   2214 
   2215 
   2216 THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
   2217   LocalContext env;
   2218   v8::HandleScope scope(env->GetIsolate());
   2219 
   2220   // Set up a prototype chain with three interceptors.
   2221   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2222   templ->InstanceTemplate()->SetIndexedPropertyHandler(
   2223       CheckThisIndexedPropertyHandler,
   2224       CheckThisIndexedPropertySetter,
   2225       CheckThisIndexedPropertyQuery,
   2226       CheckThisIndexedPropertyDeleter,
   2227       CheckThisIndexedPropertyEnumerator);
   2228 
   2229   templ->InstanceTemplate()->SetNamedPropertyHandler(
   2230       CheckThisNamedPropertyHandler,
   2231       CheckThisNamedPropertySetter,
   2232       CheckThisNamedPropertyQuery,
   2233       CheckThisNamedPropertyDeleter,
   2234       CheckThisNamedPropertyEnumerator);
   2235 
   2236   bottom = templ->GetFunction()->NewInstance();
   2237   Local<v8::Object> top = templ->GetFunction()->NewInstance();
   2238   Local<v8::Object> middle = templ->GetFunction()->NewInstance();
   2239 
   2240   bottom->SetPrototype(middle);
   2241   middle->SetPrototype(top);
   2242   env->Global()->Set(v8_str("obj"), bottom);
   2243 
   2244   // Indexed and named get.
   2245   Script::Compile(v8_str("obj[0]"))->Run();
   2246   Script::Compile(v8_str("obj.x"))->Run();
   2247 
   2248   // Indexed and named set.
   2249   Script::Compile(v8_str("obj[1] = 42"))->Run();
   2250   Script::Compile(v8_str("obj.y = 42"))->Run();
   2251 
   2252   // Indexed and named query.
   2253   Script::Compile(v8_str("0 in obj"))->Run();
   2254   Script::Compile(v8_str("'x' in obj"))->Run();
   2255 
   2256   // Indexed and named deleter.
   2257   Script::Compile(v8_str("delete obj[0]"))->Run();
   2258   Script::Compile(v8_str("delete obj.x"))->Run();
   2259 
   2260   // Enumerators.
   2261   Script::Compile(v8_str("for (var p in obj) ;"))->Run();
   2262 }
   2263 
   2264 
   2265 static void PrePropertyHandlerGet(
   2266     Local<String> key,
   2267     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2268   ApiTestFuzzer::Fuzz();
   2269   if (v8_str("pre")->Equals(key)) {
   2270     info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
   2271   }
   2272 }
   2273 
   2274 
   2275 static void PrePropertyHandlerQuery(
   2276     Local<String> key,
   2277     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   2278   if (v8_str("pre")->Equals(key)) {
   2279     info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
   2280   }
   2281 }
   2282 
   2283 
   2284 THREADED_TEST(PrePropertyHandler) {
   2285   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2286   v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   2287   desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
   2288                                                     0,
   2289                                                     PrePropertyHandlerQuery);
   2290   LocalContext env(NULL, desc->InstanceTemplate());
   2291   Script::Compile(v8_str(
   2292       "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
   2293   v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
   2294   CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
   2295   v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
   2296   CHECK_EQ(v8_str("Object: on"), result_on);
   2297   v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
   2298   CHECK(result_post.IsEmpty());
   2299 }
   2300 
   2301 
   2302 THREADED_TEST(UndefinedIsNotEnumerable) {
   2303   LocalContext env;
   2304   v8::HandleScope scope(env->GetIsolate());
   2305   v8::Handle<Value> result = Script::Compile(v8_str(
   2306       "this.propertyIsEnumerable(undefined)"))->Run();
   2307   CHECK(result->IsFalse());
   2308 }
   2309 
   2310 
   2311 v8::Handle<Script> call_recursively_script;
   2312 static const int kTargetRecursionDepth = 200;  // near maximum
   2313 
   2314 
   2315 static void CallScriptRecursivelyCall(
   2316     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2317   ApiTestFuzzer::Fuzz();
   2318   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   2319   if (depth == kTargetRecursionDepth) return;
   2320   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
   2321   args.GetReturnValue().Set(call_recursively_script->Run());
   2322 }
   2323 
   2324 
   2325 static void CallFunctionRecursivelyCall(
   2326     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2327   ApiTestFuzzer::Fuzz();
   2328   int depth = args.This()->Get(v8_str("depth"))->Int32Value();
   2329   if (depth == kTargetRecursionDepth) {
   2330     printf("[depth = %d]\n", depth);
   2331     return;
   2332   }
   2333   args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
   2334   v8::Handle<Value> function =
   2335       args.This()->Get(v8_str("callFunctionRecursively"));
   2336   args.GetReturnValue().Set(
   2337       function.As<Function>()->Call(args.This(), 0, NULL));
   2338 }
   2339 
   2340 
   2341 THREADED_TEST(DeepCrossLanguageRecursion) {
   2342   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2343   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
   2344   global->Set(v8_str("callScriptRecursively"),
   2345               v8::FunctionTemplate::New(CallScriptRecursivelyCall));
   2346   global->Set(v8_str("callFunctionRecursively"),
   2347               v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
   2348   LocalContext env(NULL, global);
   2349 
   2350   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
   2351   call_recursively_script = v8_compile("callScriptRecursively()");
   2352   call_recursively_script->Run();
   2353   call_recursively_script = v8::Handle<Script>();
   2354 
   2355   env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
   2356   Script::Compile(v8_str("callFunctionRecursively()"))->Run();
   2357 }
   2358 
   2359 
   2360 static void ThrowingPropertyHandlerGet(
   2361     Local<String> key,
   2362     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2363   ApiTestFuzzer::Fuzz();
   2364   info.GetReturnValue().Set(v8::ThrowException(key));
   2365 }
   2366 
   2367 
   2368 static void ThrowingPropertyHandlerSet(
   2369     Local<String> key,
   2370     Local<Value>,
   2371     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2372   v8::ThrowException(key);
   2373   info.GetReturnValue().SetUndefined();  // not the same as empty handle
   2374 }
   2375 
   2376 
   2377 THREADED_TEST(CallbackExceptionRegression) {
   2378   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2379   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   2380   obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
   2381                                ThrowingPropertyHandlerSet);
   2382   LocalContext env;
   2383   env->Global()->Set(v8_str("obj"), obj->NewInstance());
   2384   v8::Handle<Value> otto = Script::Compile(v8_str(
   2385       "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
   2386   CHECK_EQ(v8_str("otto"), otto);
   2387   v8::Handle<Value> netto = Script::Compile(v8_str(
   2388       "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
   2389   CHECK_EQ(v8_str("netto"), netto);
   2390 }
   2391 
   2392 
   2393 THREADED_TEST(FunctionPrototype) {
   2394   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2395   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
   2396   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
   2397   LocalContext env;
   2398   env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
   2399   Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
   2400   CHECK_EQ(script->Run()->Int32Value(), 321);
   2401 }
   2402 
   2403 
   2404 THREADED_TEST(InternalFields) {
   2405   LocalContext env;
   2406   v8::HandleScope scope(env->GetIsolate());
   2407 
   2408   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2409   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2410   instance_templ->SetInternalFieldCount(1);
   2411   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   2412   CHECK_EQ(1, obj->InternalFieldCount());
   2413   CHECK(obj->GetInternalField(0)->IsUndefined());
   2414   obj->SetInternalField(0, v8_num(17));
   2415   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
   2416 }
   2417 
   2418 
   2419 THREADED_TEST(GlobalObjectInternalFields) {
   2420   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2421   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   2422   global_template->SetInternalFieldCount(1);
   2423   LocalContext env(NULL, global_template);
   2424   v8::Handle<v8::Object> global_proxy = env->Global();
   2425   v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
   2426   CHECK_EQ(1, global->InternalFieldCount());
   2427   CHECK(global->GetInternalField(0)->IsUndefined());
   2428   global->SetInternalField(0, v8_num(17));
   2429   CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
   2430 }
   2431 
   2432 
   2433 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
   2434   LocalContext env;
   2435   v8::HandleScope scope(v8::Isolate::GetCurrent());
   2436 
   2437   v8::Local<v8::Object> global = env->Global();
   2438   global->Set(0, v8::String::New("value"));
   2439   CHECK(global->HasRealIndexedProperty(0));
   2440 }
   2441 
   2442 
   2443 static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
   2444                                                void* value) {
   2445   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2446   obj->SetAlignedPointerInInternalField(0, value);
   2447   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2448   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
   2449 }
   2450 
   2451 
   2452 THREADED_TEST(InternalFieldsAlignedPointers) {
   2453   LocalContext env;
   2454   v8::HandleScope scope(env->GetIsolate());
   2455 
   2456   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   2457   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2458   instance_templ->SetInternalFieldCount(1);
   2459   Local<v8::Object> obj = templ->GetFunction()->NewInstance();
   2460   CHECK_EQ(1, obj->InternalFieldCount());
   2461 
   2462   CheckAlignedPointerInInternalField(obj, NULL);
   2463 
   2464   int* heap_allocated = new int[100];
   2465   CheckAlignedPointerInInternalField(obj, heap_allocated);
   2466   delete[] heap_allocated;
   2467 
   2468   int stack_allocated[100];
   2469   CheckAlignedPointerInInternalField(obj, stack_allocated);
   2470 
   2471   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2472   CheckAlignedPointerInInternalField(obj, huge);
   2473 }
   2474 
   2475 
   2476 static void CheckAlignedPointerInEmbedderData(LocalContext* env,
   2477                                               int index,
   2478                                               void* value) {
   2479   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2480   (*env)->SetAlignedPointerInEmbedderData(index, value);
   2481   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2482   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
   2483 }
   2484 
   2485 
   2486 static void* AlignedTestPointer(int i) {
   2487   return reinterpret_cast<void*>(i * 1234);
   2488 }
   2489 
   2490 
   2491 THREADED_TEST(EmbedderDataAlignedPointers) {
   2492   LocalContext env;
   2493   v8::HandleScope scope(env->GetIsolate());
   2494 
   2495   CheckAlignedPointerInEmbedderData(&env, 0, NULL);
   2496 
   2497   int* heap_allocated = new int[100];
   2498   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
   2499   delete[] heap_allocated;
   2500 
   2501   int stack_allocated[100];
   2502   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
   2503 
   2504   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2505   CheckAlignedPointerInEmbedderData(&env, 3, huge);
   2506 
   2507   // Test growing of the embedder data's backing store.
   2508   for (int i = 0; i < 100; i++) {
   2509     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
   2510   }
   2511   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2512   for (int i = 0; i < 100; i++) {
   2513     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
   2514   }
   2515 }
   2516 
   2517 
   2518 static void CheckEmbedderData(LocalContext* env,
   2519                               int index,
   2520                               v8::Handle<Value> data) {
   2521   (*env)->SetEmbedderData(index, data);
   2522   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
   2523 }
   2524 
   2525 
   2526 THREADED_TEST(EmbedderData) {
   2527   LocalContext env;
   2528   v8::HandleScope scope(env->GetIsolate());
   2529 
   2530   CheckEmbedderData(&env, 3, v8::String::New("The quick brown fox jumps"));
   2531   CheckEmbedderData(&env, 2, v8::String::New("over the lazy dog."));
   2532   CheckEmbedderData(&env, 1, v8::Number::New(1.2345));
   2533   CheckEmbedderData(&env, 0, v8::Boolean::New(true));
   2534 }
   2535 
   2536 
   2537 THREADED_TEST(IdentityHash) {
   2538   LocalContext env;
   2539   v8::HandleScope scope(env->GetIsolate());
   2540 
   2541   // Ensure that the test starts with an fresh heap to test whether the hash
   2542   // code is based on the address.
   2543   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2544   Local<v8::Object> obj = v8::Object::New();
   2545   int hash = obj->GetIdentityHash();
   2546   int hash1 = obj->GetIdentityHash();
   2547   CHECK_EQ(hash, hash1);
   2548   int hash2 = v8::Object::New()->GetIdentityHash();
   2549   // Since the identity hash is essentially a random number two consecutive
   2550   // objects should not be assigned the same hash code. If the test below fails
   2551   // the random number generator should be evaluated.
   2552   CHECK_NE(hash, hash2);
   2553   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2554   int hash3 = v8::Object::New()->GetIdentityHash();
   2555   // Make sure that the identity hash is not based on the initial address of
   2556   // the object alone. If the test below fails the random number generator
   2557   // should be evaluated.
   2558   CHECK_NE(hash, hash3);
   2559   int hash4 = obj->GetIdentityHash();
   2560   CHECK_EQ(hash, hash4);
   2561 
   2562   // Check identity hashes behaviour in the presence of JS accessors.
   2563   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
   2564   {
   2565     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
   2566     Local<v8::Object> o1 = v8::Object::New();
   2567     Local<v8::Object> o2 = v8::Object::New();
   2568     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2569   }
   2570   {
   2571     CompileRun(
   2572         "function cnst() { return 42; };\n"
   2573         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
   2574     Local<v8::Object> o1 = v8::Object::New();
   2575     Local<v8::Object> o2 = v8::Object::New();
   2576     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2577   }
   2578 }
   2579 
   2580 
   2581 THREADED_TEST(SymbolProperties) {
   2582   i::FLAG_harmony_symbols = true;
   2583 
   2584   LocalContext env;
   2585   v8::Isolate* isolate = env->GetIsolate();
   2586   v8::HandleScope scope(isolate);
   2587 
   2588   v8::Local<v8::Object> obj = v8::Object::New();
   2589   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
   2590   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
   2591 
   2592   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2593 
   2594   // Check basic symbol functionality.
   2595   CHECK(sym1->IsSymbol());
   2596   CHECK(sym2->IsSymbol());
   2597   CHECK(!obj->IsSymbol());
   2598 
   2599   CHECK(sym1->Equals(sym1));
   2600   CHECK(sym2->Equals(sym2));
   2601   CHECK(!sym1->Equals(sym2));
   2602   CHECK(!sym2->Equals(sym1));
   2603   CHECK(sym1->StrictEquals(sym1));
   2604   CHECK(sym2->StrictEquals(sym2));
   2605   CHECK(!sym1->StrictEquals(sym2));
   2606   CHECK(!sym2->StrictEquals(sym1));
   2607 
   2608   CHECK(sym2->Name()->Equals(v8::String::New("my-symbol")));
   2609 
   2610   v8::Local<v8::Value> sym_val = sym2;
   2611   CHECK(sym_val->IsSymbol());
   2612   CHECK(sym_val->Equals(sym2));
   2613   CHECK(sym_val->StrictEquals(sym2));
   2614   CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
   2615 
   2616   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
   2617   CHECK(sym_obj->IsSymbolObject());
   2618   CHECK(!sym2->IsSymbolObject());
   2619   CHECK(!obj->IsSymbolObject());
   2620   CHECK(sym_obj->Equals(sym2));
   2621   CHECK(!sym_obj->StrictEquals(sym2));
   2622   CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
   2623   CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
   2624 
   2625   // Make sure delete of a non-existent symbol property works.
   2626   CHECK(obj->Delete(sym1));
   2627   CHECK(!obj->Has(sym1));
   2628 
   2629   CHECK(obj->Set(sym1, v8::Integer::New(1503)));
   2630   CHECK(obj->Has(sym1));
   2631   CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
   2632   CHECK(obj->Set(sym1, v8::Integer::New(2002)));
   2633   CHECK(obj->Has(sym1));
   2634   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2635   CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
   2636 
   2637   CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
   2638   int num_props = obj->GetPropertyNames()->Length();
   2639   CHECK(obj->Set(v8::String::New("bla"), v8::Integer::New(20)));
   2640   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2641   CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
   2642 
   2643   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2644 
   2645   // Add another property and delete it afterwards to force the object in
   2646   // slow case.
   2647   CHECK(obj->Set(sym2, v8::Integer::New(2008)));
   2648   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2649   CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
   2650   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2651   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2652 
   2653   CHECK(obj->Has(sym1));
   2654   CHECK(obj->Has(sym2));
   2655   CHECK(obj->Delete(sym2));
   2656   CHECK(obj->Has(sym1));
   2657   CHECK(!obj->Has(sym2));
   2658   CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
   2659   CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
   2660 }
   2661 
   2662 
   2663 class ScopedArrayBufferContents {
   2664  public:
   2665   explicit ScopedArrayBufferContents(
   2666       const v8::ArrayBuffer::Contents& contents)
   2667     : contents_(contents) {}
   2668   ~ScopedArrayBufferContents() { free(contents_.Data()); }
   2669   void* Data() const { return contents_.Data(); }
   2670   size_t ByteLength() const { return contents_.ByteLength(); }
   2671  private:
   2672   const v8::ArrayBuffer::Contents contents_;
   2673 };
   2674 
   2675 template <typename T>
   2676 static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
   2677   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
   2678   for (int i = 0; i < value->InternalFieldCount(); i++) {
   2679     CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
   2680   }
   2681 }
   2682 
   2683 
   2684 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
   2685   i::FLAG_harmony_array_buffer = true;
   2686   i::FLAG_harmony_typed_arrays = true;
   2687 
   2688   LocalContext env;
   2689   v8::Isolate* isolate = env->GetIsolate();
   2690   v8::HandleScope handle_scope(isolate);
   2691 
   2692   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(1024);
   2693   CheckInternalFieldsAreZero(ab);
   2694   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
   2695   CHECK(!ab->IsExternal());
   2696   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2697 
   2698   ScopedArrayBufferContents ab_contents(ab->Externalize());
   2699   CHECK(ab->IsExternal());
   2700 
   2701   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
   2702   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
   2703   ASSERT(data != NULL);
   2704   env->Global()->Set(v8_str("ab"), ab);
   2705 
   2706   v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
   2707   CHECK_EQ(1024, result->Int32Value());
   2708 
   2709   result = CompileRun("var u8 = new Uint8Array(ab);"
   2710                       "u8[0] = 0xFF;"
   2711                       "u8[1] = 0xAA;"
   2712                       "u8.length");
   2713   CHECK_EQ(1024, result->Int32Value());
   2714   CHECK_EQ(0xFF, data[0]);
   2715   CHECK_EQ(0xAA, data[1]);
   2716   data[0] = 0xCC;
   2717   data[1] = 0x11;
   2718   result = CompileRun("u8[0] + u8[1]");
   2719   CHECK_EQ(0xDD, result->Int32Value());
   2720 }
   2721 
   2722 
   2723 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
   2724   i::FLAG_harmony_array_buffer = true;
   2725   i::FLAG_harmony_typed_arrays = true;
   2726 
   2727   LocalContext env;
   2728   v8::Isolate* isolate = env->GetIsolate();
   2729   v8::HandleScope handle_scope(isolate);
   2730 
   2731 
   2732   v8::Local<v8::Value> result =
   2733       CompileRun("var ab1 = new ArrayBuffer(2);"
   2734                  "var u8_a = new Uint8Array(ab1);"
   2735                  "u8_a[0] = 0xAA;"
   2736                  "u8_a[1] = 0xFF; u8_a.buffer");
   2737   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
   2738   CheckInternalFieldsAreZero(ab1);
   2739   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
   2740   CHECK(!ab1->IsExternal());
   2741   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
   2742   CHECK(ab1->IsExternal());
   2743 
   2744   result = CompileRun("ab1.byteLength");
   2745   CHECK_EQ(2, result->Int32Value());
   2746   result = CompileRun("u8_a[0]");
   2747   CHECK_EQ(0xAA, result->Int32Value());
   2748   result = CompileRun("u8_a[1]");
   2749   CHECK_EQ(0xFF, result->Int32Value());
   2750   result = CompileRun("var u8_b = new Uint8Array(ab1);"
   2751                       "u8_b[0] = 0xBB;"
   2752                       "u8_a[0]");
   2753   CHECK_EQ(0xBB, result->Int32Value());
   2754   result = CompileRun("u8_b[1]");
   2755   CHECK_EQ(0xFF, result->Int32Value());
   2756 
   2757   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
   2758   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
   2759   CHECK_EQ(0xBB, ab1_data[0]);
   2760   CHECK_EQ(0xFF, ab1_data[1]);
   2761   ab1_data[0] = 0xCC;
   2762   ab1_data[1] = 0x11;
   2763   result = CompileRun("u8_a[0] + u8_a[1]");
   2764   CHECK_EQ(0xDD, result->Int32Value());
   2765 }
   2766 
   2767 
   2768 THREADED_TEST(ArrayBuffer_External) {
   2769   i::FLAG_harmony_array_buffer = true;
   2770   i::FLAG_harmony_typed_arrays = true;
   2771 
   2772   LocalContext env;
   2773   v8::Isolate* isolate = env->GetIsolate();
   2774   v8::HandleScope handle_scope(isolate);
   2775 
   2776   i::ScopedVector<uint8_t> my_data(100);
   2777   memset(my_data.start(), 0, 100);
   2778   Local<v8::ArrayBuffer> ab3 = v8::ArrayBuffer::New(my_data.start(), 100);
   2779   CheckInternalFieldsAreZero(ab3);
   2780   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
   2781   CHECK(ab3->IsExternal());
   2782 
   2783   env->Global()->Set(v8_str("ab3"), ab3);
   2784 
   2785   v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
   2786   CHECK_EQ(100, result->Int32Value());
   2787 
   2788   result = CompileRun("var u8_b = new Uint8Array(ab3);"
   2789                       "u8_b[0] = 0xBB;"
   2790                       "u8_b[1] = 0xCC;"
   2791                       "u8_b.length");
   2792   CHECK_EQ(100, result->Int32Value());
   2793   CHECK_EQ(0xBB, my_data[0]);
   2794   CHECK_EQ(0xCC, my_data[1]);
   2795   my_data[0] = 0xCC;
   2796   my_data[1] = 0x11;
   2797   result = CompileRun("u8_b[0] + u8_b[1]");
   2798   CHECK_EQ(0xDD, result->Int32Value());
   2799 }
   2800 
   2801 
   2802 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
   2803   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
   2804   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
   2805 }
   2806 
   2807 
   2808 static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
   2809   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
   2810   CHECK_EQ(0, static_cast<int>(ta->Length()));
   2811   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
   2812 }
   2813 
   2814 
   2815 static void CheckIsTypedArrayVarNeutered(const char* name) {
   2816   i::ScopedVector<char> source(1024);
   2817   i::OS::SNPrintF(source,
   2818       "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
   2819       name, name, name);
   2820   CHECK(CompileRun(source.start())->IsTrue());
   2821   v8::Handle<v8::TypedArray> ta =
   2822     v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
   2823   CheckIsNeutered(ta);
   2824 }
   2825 
   2826 
   2827 template <typename TypedArray, int kElementSize>
   2828 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
   2829                                          int byteOffset,
   2830                                          int length) {
   2831   v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
   2832   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   2833   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
   2834   CHECK_EQ(length, static_cast<int>(ta->Length()));
   2835   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
   2836   return ta;
   2837 }
   2838 
   2839 
   2840 THREADED_TEST(ArrayBuffer_NeuteringApi) {
   2841   LocalContext env;
   2842   v8::Isolate* isolate = env->GetIsolate();
   2843   v8::HandleScope handle_scope(isolate);
   2844 
   2845   v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(1024);
   2846 
   2847   v8::Handle<v8::Uint8Array> u8a =
   2848     CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
   2849   v8::Handle<v8::Uint8ClampedArray> u8c =
   2850     CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
   2851   v8::Handle<v8::Int8Array> i8a =
   2852     CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
   2853 
   2854   v8::Handle<v8::Uint16Array> u16a =
   2855     CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
   2856   v8::Handle<v8::Int16Array> i16a =
   2857     CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
   2858 
   2859   v8::Handle<v8::Uint32Array> u32a =
   2860     CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
   2861   v8::Handle<v8::Int32Array> i32a =
   2862     CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
   2863 
   2864   v8::Handle<v8::Float32Array> f32a =
   2865     CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
   2866   v8::Handle<v8::Float64Array> f64a =
   2867     CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
   2868 
   2869   v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
   2870   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   2871   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
   2872   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
   2873 
   2874   ScopedArrayBufferContents contents(buffer->Externalize());
   2875   buffer->Neuter();
   2876   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
   2877   CheckIsNeutered(u8a);
   2878   CheckIsNeutered(u8c);
   2879   CheckIsNeutered(i8a);
   2880   CheckIsNeutered(u16a);
   2881   CheckIsNeutered(i16a);
   2882   CheckIsNeutered(u32a);
   2883   CheckIsNeutered(i32a);
   2884   CheckIsNeutered(f32a);
   2885   CheckIsNeutered(f64a);
   2886   CheckDataViewIsNeutered(dv);
   2887 }
   2888 
   2889 
   2890 THREADED_TEST(ArrayBuffer_NeuteringScript) {
   2891   LocalContext env;
   2892   v8::Isolate* isolate = env->GetIsolate();
   2893   v8::HandleScope handle_scope(isolate);
   2894 
   2895   CompileRun(
   2896       "var ab = new ArrayBuffer(1024);"
   2897       "var u8a = new Uint8Array(ab, 1, 1023);"
   2898       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
   2899       "var i8a = new Int8Array(ab, 1, 1023);"
   2900       "var u16a = new Uint16Array(ab, 2, 511);"
   2901       "var i16a = new Int16Array(ab, 2, 511);"
   2902       "var u32a = new Uint32Array(ab, 4, 255);"
   2903       "var i32a = new Int32Array(ab, 4, 255);"
   2904       "var f32a = new Float32Array(ab, 4, 255);"
   2905       "var f64a = new Float64Array(ab, 8, 127);"
   2906       "var dv = new DataView(ab, 1, 1023);");
   2907 
   2908   v8::Handle<v8::ArrayBuffer> ab =
   2909       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
   2910 
   2911   v8::Handle<v8::DataView> dv =
   2912     v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
   2913 
   2914   ScopedArrayBufferContents contents(ab->Externalize());
   2915   ab->Neuter();
   2916   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
   2917   CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
   2918 
   2919   CheckIsTypedArrayVarNeutered("u8a");
   2920   CheckIsTypedArrayVarNeutered("u8c");
   2921   CheckIsTypedArrayVarNeutered("i8a");
   2922   CheckIsTypedArrayVarNeutered("u16a");
   2923   CheckIsTypedArrayVarNeutered("i16a");
   2924   CheckIsTypedArrayVarNeutered("u32a");
   2925   CheckIsTypedArrayVarNeutered("i32a");
   2926   CheckIsTypedArrayVarNeutered("f32a");
   2927   CheckIsTypedArrayVarNeutered("f64a");
   2928 
   2929   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
   2930   CheckDataViewIsNeutered(dv);
   2931 }
   2932 
   2933 
   2934 
   2935 THREADED_TEST(HiddenProperties) {
   2936   LocalContext env;
   2937   v8::HandleScope scope(env->GetIsolate());
   2938 
   2939   v8::Local<v8::Object> obj = v8::Object::New();
   2940   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   2941   v8::Local<v8::String> empty = v8_str("");
   2942   v8::Local<v8::String> prop_name = v8_str("prop_name");
   2943 
   2944   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2945 
   2946   // Make sure delete of a non-existent hidden value works
   2947   CHECK(obj->DeleteHiddenValue(key));
   2948 
   2949   CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
   2950   CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
   2951   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
   2952   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2953 
   2954   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2955 
   2956   // Make sure we do not find the hidden property.
   2957   CHECK(!obj->Has(empty));
   2958   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2959   CHECK(obj->Get(empty)->IsUndefined());
   2960   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2961   CHECK(obj->Set(empty, v8::Integer::New(2003)));
   2962   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2963   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
   2964 
   2965   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2966 
   2967   // Add another property and delete it afterwards to force the object in
   2968   // slow case.
   2969   CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
   2970   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2971   CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
   2972   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2973   CHECK(obj->Delete(prop_name));
   2974   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   2975 
   2976   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   2977 
   2978   CHECK(obj->SetHiddenValue(key, Handle<Value>()));
   2979   CHECK(obj->GetHiddenValue(key).IsEmpty());
   2980 
   2981   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
   2982   CHECK(obj->DeleteHiddenValue(key));
   2983   CHECK(obj->GetHiddenValue(key).IsEmpty());
   2984 }
   2985 
   2986 
   2987 THREADED_TEST(Regress97784) {
   2988   // Regression test for crbug.com/97784
   2989   // Messing with the Object.prototype should not have effect on
   2990   // hidden properties.
   2991   LocalContext env;
   2992   v8::HandleScope scope(env->GetIsolate());
   2993 
   2994   v8::Local<v8::Object> obj = v8::Object::New();
   2995   v8::Local<v8::String> key = v8_str("hidden");
   2996 
   2997   CompileRun(
   2998       "set_called = false;"
   2999       "Object.defineProperty("
   3000       "    Object.prototype,"
   3001       "    'hidden',"
   3002       "    {get: function() { return 45; },"
   3003       "     set: function() { set_called = true; }})");
   3004 
   3005   CHECK(obj->GetHiddenValue(key).IsEmpty());
   3006   // Make sure that the getter and setter from Object.prototype is not invoked.
   3007   // If it did we would have full access to the hidden properties in
   3008   // the accessor.
   3009   CHECK(obj->SetHiddenValue(key, v8::Integer::New(42)));
   3010   ExpectFalse("set_called");
   3011   CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
   3012 }
   3013 
   3014 
   3015 static bool interceptor_for_hidden_properties_called;
   3016 static void InterceptorForHiddenProperties(
   3017     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   3018   interceptor_for_hidden_properties_called = true;
   3019 }
   3020 
   3021 
   3022 THREADED_TEST(HiddenPropertiesWithInterceptors) {
   3023   LocalContext context;
   3024   v8::HandleScope scope(context->GetIsolate());
   3025 
   3026   interceptor_for_hidden_properties_called = false;
   3027 
   3028   v8::Local<v8::String> key = v8_str("api-test::hidden-key");
   3029 
   3030   // Associate an interceptor with an object and start setting hidden values.
   3031   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   3032   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   3033   instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
   3034   Local<v8::Function> function = fun_templ->GetFunction();
   3035   Local<v8::Object> obj = function->NewInstance();
   3036   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
   3037   CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
   3038   CHECK(!interceptor_for_hidden_properties_called);
   3039 }
   3040 
   3041 
   3042 THREADED_TEST(External) {
   3043   v8::HandleScope scope(v8::Isolate::GetCurrent());
   3044   int x = 3;
   3045   Local<v8::External> ext = v8::External::New(&x);
   3046   LocalContext env;
   3047   env->Global()->Set(v8_str("ext"), ext);
   3048   Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
   3049   v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
   3050   int* ptr = static_cast<int*>(reext->Value());
   3051   CHECK_EQ(x, 3);
   3052   *ptr = 10;
   3053   CHECK_EQ(x, 10);
   3054 
   3055   // Make sure unaligned pointers are wrapped properly.
   3056   char* data = i::StrDup("0123456789");
   3057   Local<v8::Value> zero = v8::External::New(&data[0]);
   3058   Local<v8::Value> one = v8::External::New(&data[1]);
   3059   Local<v8::Value> two = v8::External::New(&data[2]);
   3060   Local<v8::Value> three = v8::External::New(&data[3]);
   3061 
   3062   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
   3063   CHECK_EQ('0', *char_ptr);
   3064   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
   3065   CHECK_EQ('1', *char_ptr);
   3066   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
   3067   CHECK_EQ('2', *char_ptr);
   3068   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
   3069   CHECK_EQ('3', *char_ptr);
   3070   i::DeleteArray(data);
   3071 }
   3072 
   3073 
   3074 THREADED_TEST(GlobalHandle) {
   3075   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   3076   v8::Persistent<String> global;
   3077   {
   3078     v8::HandleScope scope(isolate);
   3079     global.Reset(isolate, v8_str("str"));
   3080   }
   3081   {
   3082     v8::HandleScope scope(isolate);
   3083     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3084   }
   3085   global.Dispose();
   3086   global.Clear();
   3087   {
   3088     v8::HandleScope scope(isolate);
   3089     global.Reset(isolate, v8_str("str"));
   3090   }
   3091   {
   3092     v8::HandleScope scope(isolate);
   3093     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3094   }
   3095   global.Dispose();
   3096 }
   3097 
   3098 
   3099 THREADED_TEST(ResettingGlobalHandle) {
   3100   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   3101   v8::Persistent<String> global;
   3102   {
   3103     v8::HandleScope scope(isolate);
   3104     global.Reset(isolate, v8_str("str"));
   3105   }
   3106   v8::internal::GlobalHandles* global_handles =
   3107       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3108   int initial_handle_count = global_handles->global_handles_count();
   3109   {
   3110     v8::HandleScope scope(isolate);
   3111     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3112   }
   3113   {
   3114     v8::HandleScope scope(isolate);
   3115     global.Reset(isolate, v8_str("longer"));
   3116   }
   3117   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
   3118   {
   3119     v8::HandleScope scope(isolate);
   3120     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
   3121   }
   3122   global.Dispose(isolate);
   3123   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3124 }
   3125 
   3126 
   3127 THREADED_TEST(ResettingGlobalHandleToEmpty) {
   3128   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   3129   v8::Persistent<String> global;
   3130   {
   3131     v8::HandleScope scope(isolate);
   3132     global.Reset(isolate, v8_str("str"));
   3133   }
   3134   v8::internal::GlobalHandles* global_handles =
   3135       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3136   int initial_handle_count = global_handles->global_handles_count();
   3137   {
   3138     v8::HandleScope scope(isolate);
   3139     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3140   }
   3141   {
   3142     v8::HandleScope scope(isolate);
   3143     Local<String> empty;
   3144     global.Reset(isolate, empty);
   3145   }
   3146   CHECK(global.IsEmpty());
   3147   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3148 }
   3149 
   3150 
   3151 THREADED_TEST(ClearAndLeakGlobal) {
   3152   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   3153   v8::internal::GlobalHandles* global_handles = NULL;
   3154   int initial_handle_count = 0;
   3155   v8::Persistent<String> global;
   3156   {
   3157     v8::HandleScope scope(isolate);
   3158     Local<String> str = v8_str("str");
   3159     global_handles =
   3160         reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3161     initial_handle_count = global_handles->global_handles_count();
   3162     global.Reset(isolate, str);
   3163   }
   3164   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count + 1);
   3165   String* str = global.ClearAndLeak();
   3166   CHECK(global.IsEmpty());
   3167   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count + 1);
   3168   global_handles->Destroy(reinterpret_cast<i::Object**>(str));
   3169   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
   3170 }
   3171 
   3172 
   3173 THREADED_TEST(GlobalHandleUpcast) {
   3174   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   3175   v8::HandleScope scope(isolate);
   3176   v8::Local<String> local = v8::Local<String>::New(v8_str("str"));
   3177   v8::Persistent<String> global_string(isolate, local);
   3178 #ifdef V8_USE_UNSAFE_HANDLES
   3179   v8::Persistent<Value> global_value =
   3180       v8::Persistent<Value>::Cast(global_string);
   3181 #else
   3182   v8::Persistent<Value>& global_value =
   3183       v8::Persistent<Value>::Cast(global_string);
   3184 #endif
   3185   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
   3186   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
   3187   global_string.Dispose();
   3188 }
   3189 
   3190 
   3191 THREADED_TEST(LocalHandle) {
   3192   v8::HandleScope scope(v8::Isolate::GetCurrent());
   3193   v8::Local<String> local = v8::Local<String>::New(v8_str("str"));
   3194   CHECK_EQ(local->Length(), 3);
   3195 
   3196   local = v8::Local<String>::New(v8::Isolate::GetCurrent(), v8_str("str"));
   3197   CHECK_EQ(local->Length(), 3);
   3198 }
   3199 
   3200 
   3201 class WeakCallCounter {
   3202  public:
   3203   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
   3204   int id() { return id_; }
   3205   void increment() { number_of_weak_calls_++; }
   3206   int NumberOfWeakCalls() { return number_of_weak_calls_; }
   3207  private:
   3208   int id_;
   3209   int number_of_weak_calls_;
   3210 };
   3211 
   3212 
   3213 static void WeakPointerCallback(v8::Isolate* isolate,
   3214                                 Persistent<Value>* handle,
   3215                                 WeakCallCounter* counter) {
   3216   CHECK_EQ(1234, counter->id());
   3217   counter->increment();
   3218   handle->Dispose(isolate);
   3219 }
   3220 
   3221 
   3222 static UniqueId MakeUniqueId(const Persistent<Value>& p) {
   3223   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
   3224 }
   3225 
   3226 
   3227 THREADED_TEST(ApiObjectGroups) {
   3228   LocalContext env;
   3229   v8::Isolate* iso = env->GetIsolate();
   3230   HandleScope scope(iso);
   3231 
   3232   Persistent<Value> g1s1;
   3233   Persistent<Value> g1s2;
   3234   Persistent<Value> g1c1;
   3235   Persistent<Value> g2s1;
   3236   Persistent<Value> g2s2;
   3237   Persistent<Value> g2c1;
   3238 
   3239   WeakCallCounter counter(1234);
   3240 
   3241   {
   3242     HandleScope scope(iso);
   3243     g1s1.Reset(iso, Object::New());
   3244     g1s2.Reset(iso, Object::New());
   3245     g1c1.Reset(iso, Object::New());
   3246     g1s1.MakeWeak(&counter, &WeakPointerCallback);
   3247     g1s2.MakeWeak(&counter, &WeakPointerCallback);
   3248     g1c1.MakeWeak(&counter, &WeakPointerCallback);
   3249 
   3250     g2s1.Reset(iso, Object::New());
   3251     g2s2.Reset(iso, Object::New());
   3252     g2c1.Reset(iso, Object::New());
   3253     g2s1.MakeWeak(&counter, &WeakPointerCallback);
   3254     g2s2.MakeWeak(&counter, &WeakPointerCallback);
   3255     g2c1.MakeWeak(&counter, &WeakPointerCallback);
   3256   }
   3257 
   3258   Persistent<Value> root(iso, g1s1);  // make a root.
   3259 
   3260   // Connect group 1 and 2, make a cycle.
   3261   {
   3262     HandleScope scope(iso);
   3263     CHECK(Local<Object>::New(iso, g1s2.As<Object>())->
   3264             Set(0, Local<Value>::New(iso, g2s2)));
   3265     CHECK(Local<Object>::New(iso, g2s1.As<Object>())->
   3266             Set(0, Local<Value>::New(iso, g1s1)));
   3267   }
   3268 
   3269   {
   3270     UniqueId id1 = MakeUniqueId(g1s1);
   3271     UniqueId id2 = MakeUniqueId(g2s2);
   3272     iso->SetObjectGroupId(g1s1, id1);
   3273     iso->SetObjectGroupId(g1s2, id1);
   3274     iso->SetReferenceFromGroup(id1, g1c1);
   3275     iso->SetObjectGroupId(g2s1, id2);
   3276     iso->SetObjectGroupId(g2s2, id2);
   3277     iso->SetReferenceFromGroup(id2, g2c1);
   3278   }
   3279   // Do a single full GC, ensure incremental marking is stopped.
   3280   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   3281       iso)->heap();
   3282   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3283 
   3284   // All object should be alive.
   3285   CHECK_EQ(0, counter.NumberOfWeakCalls());
   3286 
   3287   // Weaken the root.
   3288   root.MakeWeak(&counter, &WeakPointerCallback);
   3289   // But make children strong roots---all the objects (except for children)
   3290   // should be collectable now.
   3291   g1c1.ClearWeak(iso);
   3292   g2c1.ClearWeak(iso);
   3293 
   3294   // Groups are deleted, rebuild groups.
   3295   {
   3296     UniqueId id1 = MakeUniqueId(g1s1);
   3297     UniqueId id2 = MakeUniqueId(g2s2);
   3298     iso->SetObjectGroupId(g1s1, id1);
   3299     iso->SetObjectGroupId(g1s2, id1);
   3300     iso->SetReferenceFromGroup(id1, g1c1);
   3301     iso->SetObjectGroupId(g2s1, id2);
   3302     iso->SetObjectGroupId(g2s2, id2);
   3303     iso->SetReferenceFromGroup(id2, g2c1);
   3304   }
   3305 
   3306   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3307 
   3308   // All objects should be gone. 5 global handles in total.
   3309   CHECK_EQ(5, counter.NumberOfWeakCalls());
   3310 
   3311   // And now make children weak again and collect them.
   3312   g1c1.MakeWeak(&counter, &WeakPointerCallback);
   3313   g2c1.MakeWeak(&counter, &WeakPointerCallback);
   3314 
   3315   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3316   CHECK_EQ(7, counter.NumberOfWeakCalls());
   3317 }
   3318 
   3319 
   3320 THREADED_TEST(ApiObjectGroupsCycle) {
   3321   LocalContext env;
   3322   v8::Isolate* iso = env->GetIsolate();
   3323   HandleScope scope(iso);
   3324 
   3325   WeakCallCounter counter(1234);
   3326 
   3327   Persistent<Value> g1s1;
   3328   Persistent<Value> g1s2;
   3329   Persistent<Value> g2s1;
   3330   Persistent<Value> g2s2;
   3331   Persistent<Value> g3s1;
   3332   Persistent<Value> g3s2;
   3333   Persistent<Value> g4s1;
   3334   Persistent<Value> g4s2;
   3335 
   3336   {
   3337     HandleScope scope(iso);
   3338     g1s1.Reset(iso, Object::New());
   3339     g1s2.Reset(iso, Object::New());
   3340     g1s1.MakeWeak(&counter, &WeakPointerCallback);
   3341     g1s2.MakeWeak(&counter, &WeakPointerCallback);
   3342     CHECK(g1s1.IsWeak(iso));
   3343     CHECK(g1s2.IsWeak(iso));
   3344 
   3345     g2s1.Reset(iso, Object::New());
   3346     g2s2.Reset(iso, Object::New());
   3347     g2s1.MakeWeak(&counter, &WeakPointerCallback);
   3348     g2s2.MakeWeak(&counter, &WeakPointerCallback);
   3349     CHECK(g2s1.IsWeak(iso));
   3350     CHECK(g2s2.IsWeak(iso));
   3351 
   3352     g3s1.Reset(iso, Object::New());
   3353     g3s2.Reset(iso, Object::New());
   3354     g3s1.MakeWeak(&counter, &WeakPointerCallback);
   3355     g3s2.MakeWeak(&counter, &WeakPointerCallback);
   3356     CHECK(g3s1.IsWeak(iso));
   3357     CHECK(g3s2.IsWeak(iso));
   3358 
   3359     g4s1.Reset(iso, Object::New());
   3360     g4s2.Reset(iso, Object::New());
   3361     g4s1.MakeWeak(&counter, &WeakPointerCallback);
   3362     g4s2.MakeWeak(&counter, &WeakPointerCallback);
   3363     CHECK(g4s1.IsWeak(iso));
   3364     CHECK(g4s2.IsWeak(iso));
   3365   }
   3366 
   3367   Persistent<Value> root(iso, g1s1);  // make a root.
   3368 
   3369   // Connect groups.  We're building the following cycle:
   3370   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   3371   // groups.
   3372   {
   3373     UniqueId id1 = MakeUniqueId(g1s1);
   3374     UniqueId id2 = MakeUniqueId(g2s1);
   3375     UniqueId id3 = MakeUniqueId(g3s1);
   3376     UniqueId id4 = MakeUniqueId(g4s1);
   3377     iso->SetObjectGroupId(g1s1, id1);
   3378     iso->SetObjectGroupId(g1s2, id1);
   3379     iso->SetReferenceFromGroup(id1, g2s1);
   3380     iso->SetObjectGroupId(g2s1, id2);
   3381     iso->SetObjectGroupId(g2s2, id2);
   3382     iso->SetReferenceFromGroup(id2, g3s1);
   3383     iso->SetObjectGroupId(g3s1, id3);
   3384     iso->SetObjectGroupId(g3s2, id3);
   3385     iso->SetReferenceFromGroup(id3, g4s1);
   3386     iso->SetObjectGroupId(g4s1, id4);
   3387     iso->SetObjectGroupId(g4s2, id4);
   3388     iso->SetReferenceFromGroup(id4, g1s1);
   3389   }
   3390   // Do a single full GC
   3391   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   3392       iso)->heap();
   3393   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3394 
   3395   // All object should be alive.
   3396   CHECK_EQ(0, counter.NumberOfWeakCalls());
   3397 
   3398   // Weaken the root.
   3399   root.MakeWeak(&counter, &WeakPointerCallback);
   3400 
   3401   // Groups are deleted, rebuild groups.
   3402   {
   3403     UniqueId id1 = MakeUniqueId(g1s1);
   3404     UniqueId id2 = MakeUniqueId(g2s1);
   3405     UniqueId id3 = MakeUniqueId(g3s1);
   3406     UniqueId id4 = MakeUniqueId(g4s1);
   3407     iso->SetObjectGroupId(g1s1, id1);
   3408     iso->SetObjectGroupId(g1s2, id1);
   3409     iso->SetReferenceFromGroup(id1, g2s1);
   3410     iso->SetObjectGroupId(g2s1, id2);
   3411     iso->SetObjectGroupId(g2s2, id2);
   3412     iso->SetReferenceFromGroup(id2, g3s1);
   3413     iso->SetObjectGroupId(g3s1, id3);
   3414     iso->SetObjectGroupId(g3s2, id3);
   3415     iso->SetReferenceFromGroup(id3, g4s1);
   3416     iso->SetObjectGroupId(g4s1, id4);
   3417     iso->SetObjectGroupId(g4s2, id4);
   3418     iso->SetReferenceFromGroup(id4, g1s1);
   3419   }
   3420 
   3421   heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   3422 
   3423   // All objects should be gone. 9 global handles in total.
   3424   CHECK_EQ(9, counter.NumberOfWeakCalls());
   3425 }
   3426 
   3427 
   3428 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
   3429 // on the buildbots, so was made non-threaded for the time being.
   3430 TEST(ApiObjectGroupsCycleForScavenger) {
   3431   i::FLAG_stress_compaction = false;
   3432   i::FLAG_gc_global = false;
   3433   LocalContext env;
   3434   v8::Isolate* iso = env->GetIsolate();
   3435   HandleScope scope(iso);
   3436 
   3437   WeakCallCounter counter(1234);
   3438 
   3439   Persistent<Value> g1s1;
   3440   Persistent<Value> g1s2;
   3441   Persistent<Value> g2s1;
   3442   Persistent<Value> g2s2;
   3443   Persistent<Value> g3s1;
   3444   Persistent<Value> g3s2;
   3445 
   3446   {
   3447     HandleScope scope(iso);
   3448     g1s1.Reset(iso, Object::New());
   3449     g1s2.Reset(iso, Object::New());
   3450     g1s1.MakeWeak(&counter, &WeakPointerCallback);
   3451     g1s2.MakeWeak(&counter, &WeakPointerCallback);
   3452 
   3453     g2s1.Reset(iso, Object::New());
   3454     g2s2.Reset(iso, Object::New());
   3455     g2s1.MakeWeak(&counter, &WeakPointerCallback);
   3456     g2s2.MakeWeak(&counter, &WeakPointerCallback);
   3457 
   3458     g3s1.Reset(iso, Object::New());
   3459     g3s2.Reset(iso, Object::New());
   3460     g3s1.MakeWeak(&counter, &WeakPointerCallback);
   3461     g3s2.MakeWeak(&counter, &WeakPointerCallback);
   3462   }
   3463 
   3464   // Make a root.
   3465   Persistent<Value> root(iso, g1s1);
   3466   root.MarkPartiallyDependent(iso);
   3467 
   3468   // Connect groups.  We're building the following cycle:
   3469   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   3470   // groups.
   3471   {
   3472     HandleScope handle_scope(iso);
   3473     g1s1.MarkPartiallyDependent(iso);
   3474     g1s2.MarkPartiallyDependent(iso);
   3475     g2s1.MarkPartiallyDependent(iso);
   3476     g2s2.MarkPartiallyDependent(iso);
   3477     g3s1.MarkPartiallyDependent(iso);
   3478     g3s2.MarkPartiallyDependent(iso);
   3479     iso->SetObjectGroupId(g1s1, UniqueId(1));
   3480     iso->SetObjectGroupId(g1s2, UniqueId(1));
   3481     Local<Object>::New(iso, g1s1.As<Object>())->Set(
   3482         v8_str("x"), Local<Value>::New(iso, g2s1));
   3483     iso->SetObjectGroupId(g2s1, UniqueId(2));
   3484     iso->SetObjectGroupId(g2s2, UniqueId(2));
   3485     Local<Object>::New(iso, g2s1.As<Object>())->Set(
   3486         v8_str("x"), Local<Value>::New(iso, g3s1));
   3487     iso->SetObjectGroupId(g3s1, UniqueId(3));
   3488     iso->SetObjectGroupId(g3s2, UniqueId(3));
   3489     Local<Object>::New(iso, g3s1.As<Object>())->Set(
   3490         v8_str("x"), Local<Value>::New(iso, g1s1));
   3491   }
   3492 
   3493   v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
   3494       iso)->heap();
   3495   heap->CollectGarbage(i::NEW_SPACE);
   3496 
   3497   // All objects should be alive.
   3498   CHECK_EQ(0, counter.NumberOfWeakCalls());
   3499 
   3500   // Weaken the root.
   3501   root.MakeWeak(&counter, &WeakPointerCallback);
   3502   root.MarkPartiallyDependent(iso);
   3503 
   3504   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   3505   // Groups are deleted, rebuild groups.
   3506   {
   3507     HandleScope handle_scope(iso);
   3508     g1s1.MarkPartiallyDependent(isolate);
   3509     g1s2.MarkPartiallyDependent(isolate);
   3510     g2s1.MarkPartiallyDependent(isolate);
   3511     g2s2.MarkPartiallyDependent(isolate);
   3512     g3s1.MarkPartiallyDependent(isolate);
   3513     g3s2.MarkPartiallyDependent(isolate);
   3514     iso->SetObjectGroupId(g1s1, UniqueId(1));
   3515     iso->SetObjectGroupId(g1s2, UniqueId(1));
   3516     Local<Object>::New(iso, g1s1.As<Object>())->Set(
   3517         v8_str("x"), Local<Value>::New(iso, g2s1));
   3518     iso->SetObjectGroupId(g2s1, UniqueId(2));
   3519     iso->SetObjectGroupId(g2s2, UniqueId(2));
   3520     Local<Object>::New(iso, g2s1.As<Object>())->Set(
   3521         v8_str("x"), Local<Value>::New(iso, g3s1));
   3522     iso->SetObjectGroupId(g3s1, UniqueId(3));
   3523     iso->SetObjectGroupId(g3s2, UniqueId(3));
   3524     Local<Object>::New(iso, g3s1.As<Object>())->Set(
   3525         v8_str("x"), Local<Value>::New(iso, g1s1));
   3526   }
   3527 
   3528   heap->CollectGarbage(i::NEW_SPACE);
   3529 
   3530   // All objects should be gone. 7 global handles in total.
   3531   CHECK_EQ(7, counter.NumberOfWeakCalls());
   3532 }
   3533 
   3534 
   3535 THREADED_TEST(ScriptException) {
   3536   LocalContext env;
   3537   v8::HandleScope scope(env->GetIsolate());
   3538   Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
   3539   v8::TryCatch try_catch;
   3540   Local<Value> result = script->Run();
   3541   CHECK(result.IsEmpty());
   3542   CHECK(try_catch.HasCaught());
   3543   String::Utf8Value exception_value(try_catch.Exception());
   3544   CHECK_EQ(*exception_value, "panama!");
   3545 }
   3546 
   3547 
   3548 TEST(TryCatchCustomException) {
   3549   LocalContext env;
   3550   v8::HandleScope scope(env->GetIsolate());
   3551   v8::TryCatch try_catch;
   3552   CompileRun("function CustomError() { this.a = 'b'; }"
   3553              "(function f() { throw new CustomError(); })();");
   3554   CHECK(try_catch.HasCaught());
   3555   CHECK(try_catch.Exception()->ToObject()->
   3556             Get(v8_str("a"))->Equals(v8_str("b")));
   3557 }
   3558 
   3559 
   3560 bool message_received;
   3561 
   3562 
   3563 static void check_message_0(v8::Handle<v8::Message> message,
   3564                             v8::Handle<Value> data) {
   3565   CHECK_EQ(5.76, data->NumberValue());
   3566   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   3567   CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
   3568   CHECK(!message->IsSharedCrossOrigin());
   3569   message_received = true;
   3570 }
   3571 
   3572 
   3573 THREADED_TEST(MessageHandler0) {
   3574   message_received = false;
   3575   v8::HandleScope scope(v8::Isolate::GetCurrent());
   3576   CHECK(!message_received);
   3577   v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
   3578   LocalContext context;
   3579   v8::ScriptOrigin origin =
   3580       v8::ScriptOrigin(v8_str("6.75"));
   3581   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   3582                                                   &origin);
   3583   script->SetData(v8_str("7.56"));
   3584   script->Run();
   3585   CHECK(message_received);
   3586   // clear out the message listener
   3587   v8::V8::RemoveMessageListeners(check_message_0);
   3588 }
   3589 
   3590 
   3591 static void check_message_1(v8::Handle<v8::Message> message,
   3592                             v8::Handle<Value> data) {
   3593   CHECK(data->IsNumber());
   3594   CHECK_EQ(1337, data->Int32Value());
   3595   CHECK(!message->IsSharedCrossOrigin());
   3596   message_received = true;
   3597 }
   3598 
   3599 
   3600 TEST(MessageHandler1) {
   3601   message_received = false;
   3602   v8::HandleScope scope(v8::Isolate::GetCurrent());
   3603   CHECK(!message_received);
   3604   v8::V8::AddMessageListener(check_message_1);
   3605   LocalContext context;
   3606   CompileRun("throw 1337;");
   3607   CHECK(message_received);
   3608   // clear out the message listener
   3609   v8::V8::RemoveMessageListeners(check_message_1);
   3610 }
   3611 
   3612 
   3613 static void check_message_2(v8::Handle<v8::Message> message,
   3614                             v8::Handle<Value> data) {
   3615   LocalContext context;
   3616   CHECK(data->IsObject());
   3617   v8::Local<v8::Value> hidden_property =
   3618       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
   3619   CHECK(v8_str("hidden value")->Equals(hidden_property));
   3620   CHECK(!message->IsSharedCrossOrigin());
   3621   message_received = true;
   3622 }
   3623 
   3624 
   3625 TEST(MessageHandler2) {
   3626   message_received = false;
   3627   v8::HandleScope scope(v8::Isolate::GetCurrent());
   3628   CHECK(!message_received);
   3629   v8::V8::AddMessageListener(check_message_2);
   3630   LocalContext context;
   3631   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
   3632   v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
   3633                                            v8_str("hidden value"));
   3634   context->Global()->Set(v8_str("error"), error);
   3635   CompileRun("throw error;");
   3636   CHECK(message_received);
   3637   // clear out the message listener
   3638   v8::V8::RemoveMessageListeners(check_message_2);
   3639 }
   3640 
   3641 
   3642 static void check_message_3(v8::Handle<v8::Message> message,
   3643                             v8::Handle<Value> data) {
   3644   CHECK(message->IsSharedCrossOrigin());
   3645   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   3646   message_received = true;
   3647 }
   3648 
   3649 
   3650 TEST(MessageHandler3) {
   3651   message_received = false;
   3652   v8::HandleScope scope(v8::Isolate::GetCurrent());
   3653   CHECK(!message_received);
   3654   v8::V8::AddMessageListener(check_message_3);
   3655   LocalContext context;
   3656   v8::ScriptOrigin origin =
   3657       v8::ScriptOrigin(v8_str("6.75"),
   3658                        v8::Integer::New(1),
   3659                        v8::Integer::New(2),
   3660                        v8::True());
   3661   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   3662                                                   &origin);
   3663   script->Run();
   3664   CHECK(message_received);
   3665   // clear out the message listener
   3666   v8::V8::RemoveMessageListeners(check_message_3);
   3667 }
   3668 
   3669 
   3670 static void check_message_4(v8::Handle<v8::Message> message,
   3671                             v8::Handle<Value> data) {
   3672   CHECK(!message->IsSharedCrossOrigin());
   3673   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   3674   message_received = true;
   3675 }
   3676 
   3677 
   3678 TEST(MessageHandler4) {
   3679   message_received = false;
   3680   v8::HandleScope scope(v8::Isolate::GetCurrent());
   3681   CHECK(!message_received);
   3682   v8::V8::AddMessageListener(check_message_4);
   3683   LocalContext context;
   3684   v8::ScriptOrigin origin =
   3685       v8::ScriptOrigin(v8_str("6.75"),
   3686                        v8::Integer::New(1),
   3687                        v8::Integer::New(2),
   3688                        v8::False());
   3689   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   3690                                                   &origin);
   3691   script->Run();
   3692   CHECK(message_received);
   3693   // clear out the message listener
   3694   v8::V8::RemoveMessageListeners(check_message_4);
   3695 }
   3696 
   3697 
   3698 static void check_message_5a(v8::Handle<v8::Message> message,
   3699                             v8::Handle<Value> data) {
   3700   CHECK(message->IsSharedCrossOrigin());
   3701   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   3702   message_received = true;
   3703 }
   3704 
   3705 
   3706 static void check_message_5b(v8::Handle<v8::Message> message,
   3707                             v8::Handle<Value> data) {
   3708   CHECK(!message->IsSharedCrossOrigin());
   3709   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   3710   message_received = true;
   3711 }
   3712 
   3713 
   3714 TEST(MessageHandler5) {
   3715   message_received = false;
   3716   v8::HandleScope scope(v8::Isolate::GetCurrent());
   3717   CHECK(!message_received);
   3718   v8::V8::AddMessageListener(check_message_5a);
   3719   LocalContext context;
   3720   v8::ScriptOrigin origin =
   3721       v8::ScriptOrigin(v8_str("6.75"),
   3722                        v8::Integer::New(1),
   3723                        v8::Integer::New(2),
   3724                        v8::True());
   3725   v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
   3726                                                   &origin);
   3727   script->Run();
   3728   CHECK(message_received);
   3729   // clear out the message listener
   3730   v8::V8::RemoveMessageListeners(check_message_5a);
   3731 
   3732   message_received = false;
   3733   v8::V8::AddMessageListener(check_message_5b);
   3734   origin =
   3735       v8::ScriptOrigin(v8_str("6.75"),
   3736                        v8::Integer::New(1),
   3737                        v8::Integer::New(2),
   3738                        v8::False());
   3739   script = Script::Compile(v8_str("throw 'error'"),
   3740                            &origin);
   3741   script->Run();
   3742   CHECK(message_received);
   3743   // clear out the message listener
   3744   v8::V8::RemoveMessageListeners(check_message_5b);
   3745 }
   3746 
   3747 
   3748 THREADED_TEST(GetSetProperty) {
   3749   LocalContext context;
   3750   v8::HandleScope scope(context->GetIsolate());
   3751   context->Global()->Set(v8_str("foo"), v8_num(14));
   3752   context->Global()->Set(v8_str("12"), v8_num(92));
   3753   context->Global()->Set(v8::Integer::New(16), v8_num(32));
   3754   context->Global()->Set(v8_num(13), v8_num(56));
   3755   Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
   3756   CHECK_EQ(14, foo->Int32Value());
   3757   Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
   3758   CHECK_EQ(92, twelve->Int32Value());
   3759   Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
   3760   CHECK_EQ(32, sixteen->Int32Value());
   3761   Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
   3762   CHECK_EQ(56, thirteen->Int32Value());
   3763   CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
   3764   CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
   3765   CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
   3766   CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
   3767   CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
   3768   CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
   3769   CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
   3770   CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
   3771   CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
   3772 }
   3773 
   3774 
   3775 THREADED_TEST(PropertyAttributes) {
   3776   LocalContext context;
   3777   v8::HandleScope scope(context->GetIsolate());
   3778   // none
   3779   Local<String> prop = v8_str("none");
   3780   context->Global()->Set(prop, v8_num(7));
   3781   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
   3782   // read-only
   3783   prop = v8_str("read_only");
   3784   context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
   3785   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   3786   CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
   3787   Script::Compile(v8_str("read_only = 9"))->Run();
   3788   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   3789   context->Global()->Set(prop, v8_num(10));
   3790   CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
   3791   // dont-delete
   3792   prop = v8_str("dont_delete");
   3793   context->Global()->Set(prop, v8_num(13), v8::DontDelete);
   3794   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   3795   Script::Compile(v8_str("delete dont_delete"))->Run();
   3796   CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
   3797   CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
   3798   // dont-enum
   3799   prop = v8_str("dont_enum");
   3800   context->Global()->Set(prop, v8_num(28), v8::DontEnum);
   3801   CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
   3802   // absent
   3803   prop = v8_str("absent");
   3804   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
   3805   Local<Value> fake_prop = v8_num(1);
   3806   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
   3807   // exception
   3808   TryCatch try_catch;
   3809   Local<Value> exception =
   3810       CompileRun("({ toString: function() { throw 'exception';} })");
   3811   CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
   3812   CHECK(try_catch.HasCaught());
   3813   String::Utf8Value exception_value(try_catch.Exception());
   3814   CHECK_EQ("exception", *exception_value);
   3815   try_catch.Reset();
   3816 }
   3817 
   3818 
   3819 THREADED_TEST(Array) {
   3820   LocalContext context;
   3821   v8::HandleScope scope(context->GetIsolate());
   3822   Local<v8::Array> array = v8::Array::New();
   3823   CHECK_EQ(0, array->Length());
   3824   CHECK(array->Get(0)->IsUndefined());
   3825   CHECK(!array->Has(0));
   3826   CHECK(array->Get(100)->IsUndefined());
   3827   CHECK(!array->Has(100));
   3828   array->Set(2, v8_num(7));
   3829   CHECK_EQ(3, array->Length());
   3830   CHECK(!array->Has(0));
   3831   CHECK(!array->Has(1));
   3832   CHECK(array->Has(2));
   3833   CHECK_EQ(7, array->Get(2)->Int32Value());
   3834   Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
   3835   Local<v8::Array> arr = obj.As<v8::Array>();
   3836   CHECK_EQ(3, arr->Length());
   3837   CHECK_EQ(1, arr->Get(0)->Int32Value());
   3838   CHECK_EQ(2, arr->Get(1)->Int32Value());
   3839   CHECK_EQ(3, arr->Get(2)->Int32Value());
   3840   array = v8::Array::New(27);
   3841   CHECK_EQ(27, array->Length());
   3842   array = v8::Array::New(-27);
   3843   CHECK_EQ(0, array->Length());
   3844 }
   3845 
   3846 
   3847 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
   3848   v8::HandleScope scope(args.GetIsolate());
   3849   ApiTestFuzzer::Fuzz();
   3850   Local<v8::Array> result = v8::Array::New(args.Length());
   3851   for (int i = 0; i < args.Length(); i++)
   3852     result->Set(i, args[i]);
   3853   args.GetReturnValue().Set(scope.Close(result));
   3854 }
   3855 
   3856 
   3857 THREADED_TEST(Vector) {
   3858   v8::HandleScope scope(v8::Isolate::GetCurrent());
   3859   Local<ObjectTemplate> global = ObjectTemplate::New();
   3860   global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
   3861   LocalContext context(0, global);
   3862 
   3863   const char* fun = "f()";
   3864   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
   3865   CHECK_EQ(0, a0->Length());
   3866 
   3867   const char* fun2 = "f(11)";
   3868   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
   3869   CHECK_EQ(1, a1->Length());
   3870   CHECK_EQ(11, a1->Get(0)->Int32Value());
   3871 
   3872   const char* fun3 = "f(12, 13)";
   3873   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
   3874   CHECK_EQ(2, a2->Length());
   3875   CHECK_EQ(12, a2->Get(0)->Int32Value());
   3876   CHECK_EQ(13, a2->Get(1)->Int32Value());
   3877 
   3878   const char* fun4 = "f(14, 15, 16)";
   3879   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
   3880   CHECK_EQ(3, a3->Length());
   3881   CHECK_EQ(14, a3->Get(0)->Int32Value());
   3882   CHECK_EQ(15, a3->Get(1)->Int32Value());
   3883   CHECK_EQ(16, a3->Get(2)->Int32Value());
   3884 
   3885   const char* fun5 = "f(17, 18, 19, 20)";
   3886   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
   3887   CHECK_EQ(4, a4->Length());
   3888   CHECK_EQ(17, a4->Get(0)->Int32Value());
   3889   CHECK_EQ(18, a4->Get(1)->Int32Value());
   3890   CHECK_EQ(19, a4->Get(2)->Int32Value());
   3891   CHECK_EQ(20, a4->Get(3)->Int32Value());
   3892 }
   3893 
   3894 
   3895 THREADED_TEST(FunctionCall) {
   3896   LocalContext context;
   3897   v8::HandleScope scope(context->GetIsolate());
   3898   CompileRun(
   3899     "function Foo() {"
   3900     "  var result = [];"
   3901     "  for (var i = 0; i < arguments.length; i++) {"
   3902     "    result.push(arguments[i]);"
   3903     "  }"
   3904     "  return result;"
   3905     "}");
   3906   Local<Function> Foo =
   3907       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   3908 
   3909   v8::Handle<Value>* args0 = NULL;
   3910   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
   3911   CHECK_EQ(0, a0->Length());
   3912 
   3913   v8::Handle<Value> args1[] = { v8_num(1.1) };
   3914   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
   3915   CHECK_EQ(1, a1->Length());
   3916   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
   3917 
   3918   v8::Handle<Value> args2[] = { v8_num(2.2),
   3919                                 v8_num(3.3) };
   3920   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
   3921   CHECK_EQ(2, a2->Length());
   3922   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
   3923   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
   3924 
   3925   v8::Handle<Value> args3[] = { v8_num(4.4),
   3926                                 v8_num(5.5),
   3927                                 v8_num(6.6) };
   3928   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
   3929   CHECK_EQ(3, a3->Length());
   3930   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
   3931   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
   3932   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
   3933 
   3934   v8::Handle<Value> args4[] = { v8_num(7.7),
   3935                                 v8_num(8.8),
   3936                                 v8_num(9.9),
   3937                                 v8_num(10.11) };
   3938   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
   3939   CHECK_EQ(4, a4->Length());
   3940   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
   3941   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
   3942   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
   3943   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
   3944 }
   3945 
   3946 
   3947 static const char* js_code_causing_out_of_memory =
   3948     "var a = new Array(); while(true) a.push(a);";
   3949 
   3950 
   3951 // These tests run for a long time and prevent us from running tests
   3952 // that come after them so they cannot run in parallel.
   3953 TEST(OutOfMemory) {
   3954   // It's not possible to read a snapshot into a heap with different dimensions.
   3955   if (i::Snapshot::IsEnabled()) return;
   3956   // Set heap limits.
   3957   static const int K = 1024;
   3958   v8::ResourceConstraints constraints;
   3959   constraints.set_max_young_space_size(256 * K);
   3960   constraints.set_max_old_space_size(5 * K * K);
   3961   v8::SetResourceConstraints(&constraints);
   3962 
   3963   // Execute a script that causes out of memory.
   3964   LocalContext context;
   3965   v8::HandleScope scope(context->GetIsolate());
   3966   v8::V8::IgnoreOutOfMemoryException();
   3967   Local<Script> script =
   3968       Script::Compile(String::New(js_code_causing_out_of_memory));
   3969   Local<Value> result = script->Run();
   3970 
   3971   // Check for out of memory state.
   3972   CHECK(result.IsEmpty());
   3973   CHECK(context->HasOutOfMemoryException());
   3974 }
   3975 
   3976 
   3977 void ProvokeOutOfMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
   3978   ApiTestFuzzer::Fuzz();
   3979 
   3980   LocalContext context;
   3981   v8::HandleScope scope(context->GetIsolate());
   3982   Local<Script> script =
   3983       Script::Compile(String::New(js_code_causing_out_of_memory));
   3984   Local<Value> result = script->Run();
   3985 
   3986   // Check for out of memory state.
   3987   CHECK(result.IsEmpty());
   3988   CHECK(context->HasOutOfMemoryException());
   3989 
   3990   args.GetReturnValue().Set(result);
   3991 }
   3992 
   3993 
   3994 TEST(OutOfMemoryNested) {
   3995   // It's not possible to read a snapshot into a heap with different dimensions.
   3996   if (i::Snapshot::IsEnabled()) return;
   3997   // Set heap limits.
   3998   static const int K = 1024;
   3999   v8::ResourceConstraints constraints;
   4000   constraints.set_max_young_space_size(256 * K);
   4001   constraints.set_max_old_space_size(5 * K * K);
   4002   v8::SetResourceConstraints(&constraints);
   4003 
   4004   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4005   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4006   templ->Set(v8_str("ProvokeOutOfMemory"),
   4007              v8::FunctionTemplate::New(ProvokeOutOfMemory));
   4008   LocalContext context(0, templ);
   4009   v8::V8::IgnoreOutOfMemoryException();
   4010   Local<Value> result = CompileRun(
   4011     "var thrown = false;"
   4012     "try {"
   4013     "  ProvokeOutOfMemory();"
   4014     "} catch (e) {"
   4015     "  thrown = true;"
   4016     "}");
   4017   // Check for out of memory state.
   4018   CHECK(result.IsEmpty());
   4019   CHECK(context->HasOutOfMemoryException());
   4020 }
   4021 
   4022 
   4023 TEST(HugeConsStringOutOfMemory) {
   4024   // It's not possible to read a snapshot into a heap with different dimensions.
   4025   if (i::Snapshot::IsEnabled()) return;
   4026   // Set heap limits.
   4027   static const int K = 1024;
   4028   v8::ResourceConstraints constraints;
   4029   constraints.set_max_young_space_size(256 * K);
   4030   constraints.set_max_old_space_size(4 * K * K);
   4031   v8::SetResourceConstraints(&constraints);
   4032 
   4033   // Execute a script that causes out of memory.
   4034   v8::V8::IgnoreOutOfMemoryException();
   4035 
   4036   LocalContext context;
   4037   v8::HandleScope scope(context->GetIsolate());
   4038 
   4039   // Build huge string. This should fail with out of memory exception.
   4040   Local<Value> result = CompileRun(
   4041     "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
   4042     "for (var i = 0; i < 22; i++) { str = str + str; }");
   4043 
   4044   // Check for out of memory state.
   4045   CHECK(result.IsEmpty());
   4046   CHECK(context->HasOutOfMemoryException());
   4047 }
   4048 
   4049 
   4050 THREADED_TEST(ConstructCall) {
   4051   LocalContext context;
   4052   v8::HandleScope scope(context->GetIsolate());
   4053   CompileRun(
   4054     "function Foo() {"
   4055     "  var result = [];"
   4056     "  for (var i = 0; i < arguments.length; i++) {"
   4057     "    result.push(arguments[i]);"
   4058     "  }"
   4059     "  return result;"
   4060     "}");
   4061   Local<Function> Foo =
   4062       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
   4063 
   4064   v8::Handle<Value>* args0 = NULL;
   4065   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
   4066   CHECK_EQ(0, a0->Length());
   4067 
   4068   v8::Handle<Value> args1[] = { v8_num(1.1) };
   4069   Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
   4070   CHECK_EQ(1, a1->Length());
   4071   CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
   4072 
   4073   v8::Handle<Value> args2[] = { v8_num(2.2),
   4074                                 v8_num(3.3) };
   4075   Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
   4076   CHECK_EQ(2, a2->Length());
   4077   CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
   4078   CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
   4079 
   4080   v8::Handle<Value> args3[] = { v8_num(4.4),
   4081                                 v8_num(5.5),
   4082                                 v8_num(6.6) };
   4083   Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
   4084   CHECK_EQ(3, a3->Length());
   4085   CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
   4086   CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
   4087   CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
   4088 
   4089   v8::Handle<Value> args4[] = { v8_num(7.7),
   4090                                 v8_num(8.8),
   4091                                 v8_num(9.9),
   4092                                 v8_num(10.11) };
   4093   Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
   4094   CHECK_EQ(4, a4->Length());
   4095   CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
   4096   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
   4097   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
   4098   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
   4099 }
   4100 
   4101 
   4102 static void CheckUncle(v8::TryCatch* try_catch) {
   4103   CHECK(try_catch->HasCaught());
   4104   String::Utf8Value str_value(try_catch->Exception());
   4105   CHECK_EQ(*str_value, "uncle?");
   4106   try_catch->Reset();
   4107 }
   4108 
   4109 
   4110 THREADED_TEST(ConversionNumber) {
   4111   LocalContext env;
   4112   v8::HandleScope scope(env->GetIsolate());
   4113   // Very large number.
   4114   CompileRun("var obj = Math.pow(2,32) * 1237;");
   4115   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   4116   CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
   4117   CHECK_EQ(0, obj->ToInt32()->Value());
   4118   CHECK(0u == obj->ToUint32()->Value());  // NOLINT - no CHECK_EQ for unsigned.
   4119   // Large number.
   4120   CompileRun("var obj = -1234567890123;");
   4121   obj = env->Global()->Get(v8_str("obj"));
   4122   CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
   4123   CHECK_EQ(-1912276171, obj->ToInt32()->Value());
   4124   CHECK(2382691125u == obj->ToUint32()->Value());  // NOLINT
   4125   // Small positive integer.
   4126   CompileRun("var obj = 42;");
   4127   obj = env->Global()->Get(v8_str("obj"));
   4128   CHECK_EQ(42.0, obj->ToNumber()->Value());
   4129   CHECK_EQ(42, obj->ToInt32()->Value());
   4130   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   4131   // Negative integer.
   4132   CompileRun("var obj = -37;");
   4133   obj = env->Global()->Get(v8_str("obj"));
   4134   CHECK_EQ(-37.0, obj->ToNumber()->Value());
   4135   CHECK_EQ(-37, obj->ToInt32()->Value());
   4136   CHECK(4294967259u == obj->ToUint32()->Value());  // NOLINT
   4137   // Positive non-int32 integer.
   4138   CompileRun("var obj = 0x81234567;");
   4139   obj = env->Global()->Get(v8_str("obj"));
   4140   CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
   4141   CHECK_EQ(-2128394905, obj->ToInt32()->Value());
   4142   CHECK(2166572391u == obj->ToUint32()->Value());  // NOLINT
   4143   // Fraction.
   4144   CompileRun("var obj = 42.3;");
   4145   obj = env->Global()->Get(v8_str("obj"));
   4146   CHECK_EQ(42.3, obj->ToNumber()->Value());
   4147   CHECK_EQ(42, obj->ToInt32()->Value());
   4148   CHECK(42u == obj->ToUint32()->Value());  // NOLINT
   4149   // Large negative fraction.
   4150   CompileRun("var obj = -5726623061.75;");
   4151   obj = env->Global()->Get(v8_str("obj"));
   4152   CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
   4153   CHECK_EQ(-1431655765, obj->ToInt32()->Value());
   4154   CHECK(2863311531u == obj->ToUint32()->Value());  // NOLINT
   4155 }
   4156 
   4157 
   4158 THREADED_TEST(isNumberType) {
   4159   LocalContext env;
   4160   v8::HandleScope scope(env->GetIsolate());
   4161   // Very large number.
   4162   CompileRun("var obj = Math.pow(2,32) * 1237;");
   4163   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   4164   CHECK(!obj->IsInt32());
   4165   CHECK(!obj->IsUint32());
   4166   // Large negative number.
   4167   CompileRun("var obj = -1234567890123;");
   4168   obj = env->Global()->Get(v8_str("obj"));
   4169   CHECK(!obj->IsInt32());
   4170   CHECK(!obj->IsUint32());
   4171   // Small positive integer.
   4172   CompileRun("var obj = 42;");
   4173   obj = env->Global()->Get(v8_str("obj"));
   4174   CHECK(obj->IsInt32());
   4175   CHECK(obj->IsUint32());
   4176   // Negative integer.
   4177   CompileRun("var obj = -37;");
   4178   obj = env->Global()->Get(v8_str("obj"));
   4179   CHECK(obj->IsInt32());
   4180   CHECK(!obj->IsUint32());
   4181   // Positive non-int32 integer.
   4182   CompileRun("var obj = 0x81234567;");
   4183   obj = env->Global()->Get(v8_str("obj"));
   4184   CHECK(!obj->IsInt32());
   4185   CHECK(obj->IsUint32());
   4186   // Fraction.
   4187   CompileRun("var obj = 42.3;");
   4188   obj = env->Global()->Get(v8_str("obj"));
   4189   CHECK(!obj->IsInt32());
   4190   CHECK(!obj->IsUint32());
   4191   // Large negative fraction.
   4192   CompileRun("var obj = -5726623061.75;");
   4193   obj = env->Global()->Get(v8_str("obj"));
   4194   CHECK(!obj->IsInt32());
   4195   CHECK(!obj->IsUint32());
   4196   // Positive zero
   4197   CompileRun("var obj = 0.0;");
   4198   obj = env->Global()->Get(v8_str("obj"));
   4199   CHECK(obj->IsInt32());
   4200   CHECK(obj->IsUint32());
   4201   // Positive zero
   4202   CompileRun("var obj = -0.0;");
   4203   obj = env->Global()->Get(v8_str("obj"));
   4204   CHECK(!obj->IsInt32());
   4205   CHECK(!obj->IsUint32());
   4206 }
   4207 
   4208 
   4209 THREADED_TEST(ConversionException) {
   4210   LocalContext env;
   4211   v8::HandleScope scope(env->GetIsolate());
   4212   CompileRun(
   4213     "function TestClass() { };"
   4214     "TestClass.prototype.toString = function () { throw 'uncle?'; };"
   4215     "var obj = new TestClass();");
   4216   Local<Value> obj = env->Global()->Get(v8_str("obj"));
   4217 
   4218   v8::TryCatch try_catch;
   4219 
   4220   Local<Value> to_string_result = obj->ToString();
   4221   CHECK(to_string_result.IsEmpty());
   4222   CheckUncle(&try_catch);
   4223 
   4224   Local<Value> to_number_result = obj->ToNumber();
   4225   CHECK(to_number_result.IsEmpty());
   4226   CheckUncle(&try_catch);
   4227 
   4228   Local<Value> to_integer_result = obj->ToInteger();
   4229   CHECK(to_integer_result.IsEmpty());
   4230   CheckUncle(&try_catch);
   4231 
   4232   Local<Value> to_uint32_result = obj->ToUint32();
   4233   CHECK(to_uint32_result.IsEmpty());
   4234   CheckUncle(&try_catch);
   4235 
   4236   Local<Value> to_int32_result = obj->ToInt32();
   4237   CHECK(to_int32_result.IsEmpty());
   4238   CheckUncle(&try_catch);
   4239 
   4240   Local<Value> to_object_result = v8::Undefined()->ToObject();
   4241   CHECK(to_object_result.IsEmpty());
   4242   CHECK(try_catch.HasCaught());
   4243   try_catch.Reset();
   4244 
   4245   int32_t int32_value = obj->Int32Value();
   4246   CHECK_EQ(0, int32_value);
   4247   CheckUncle(&try_catch);
   4248 
   4249   uint32_t uint32_value = obj->Uint32Value();
   4250   CHECK_EQ(0, uint32_value);
   4251   CheckUncle(&try_catch);
   4252 
   4253   double number_value = obj->NumberValue();
   4254   CHECK_NE(0, std::isnan(number_value));
   4255   CheckUncle(&try_catch);
   4256 
   4257   int64_t integer_value = obj->IntegerValue();
   4258   CHECK_EQ(0.0, static_cast<double>(integer_value));
   4259   CheckUncle(&try_catch);
   4260 }
   4261 
   4262 
   4263 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4264   ApiTestFuzzer::Fuzz();
   4265   v8::ThrowException(v8_str("konto"));
   4266 }
   4267 
   4268 
   4269 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4270   if (args.Length() < 1) {
   4271     args.GetReturnValue().Set(false);
   4272     return;
   4273   }
   4274   v8::HandleScope scope(args.GetIsolate());
   4275   v8::TryCatch try_catch;
   4276   Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
   4277   CHECK(!try_catch.HasCaught() || result.IsEmpty());
   4278   args.GetReturnValue().Set(try_catch.HasCaught());
   4279 }
   4280 
   4281 
   4282 THREADED_TEST(APICatch) {
   4283   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4284   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4285   templ->Set(v8_str("ThrowFromC"),
   4286              v8::FunctionTemplate::New(ThrowFromC));
   4287   LocalContext context(0, templ);
   4288   CompileRun(
   4289     "var thrown = false;"
   4290     "try {"
   4291     "  ThrowFromC();"
   4292     "} catch (e) {"
   4293     "  thrown = true;"
   4294     "}");
   4295   Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
   4296   CHECK(thrown->BooleanValue());
   4297 }
   4298 
   4299 
   4300 THREADED_TEST(APIThrowTryCatch) {
   4301   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4302   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4303   templ->Set(v8_str("ThrowFromC"),
   4304              v8::FunctionTemplate::New(ThrowFromC));
   4305   LocalContext context(0, templ);
   4306   v8::TryCatch try_catch;
   4307   CompileRun("ThrowFromC();");
   4308   CHECK(try_catch.HasCaught());
   4309 }
   4310 
   4311 
   4312 // Test that a try-finally block doesn't shadow a try-catch block
   4313 // when setting up an external handler.
   4314 //
   4315 // BUG(271): Some of the exception propagation does not work on the
   4316 // ARM simulator because the simulator separates the C++ stack and the
   4317 // JS stack.  This test therefore fails on the simulator.  The test is
   4318 // not threaded to allow the threading tests to run on the simulator.
   4319 TEST(TryCatchInTryFinally) {
   4320   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4321   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4322   templ->Set(v8_str("CCatcher"),
   4323              v8::FunctionTemplate::New(CCatcher));
   4324   LocalContext context(0, templ);
   4325   Local<Value> result = CompileRun("try {"
   4326                                    "  try {"
   4327                                    "    CCatcher('throw 7;');"
   4328                                    "  } finally {"
   4329                                    "  }"
   4330                                    "} catch (e) {"
   4331                                    "}");
   4332   CHECK(result->IsTrue());
   4333 }
   4334 
   4335 
   4336 static void check_reference_error_message(
   4337     v8::Handle<v8::Message> message,
   4338     v8::Handle<v8::Value> data) {
   4339   const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
   4340   CHECK(message->Get()->Equals(v8_str(reference_error)));
   4341 }
   4342 
   4343 
   4344 static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4345   ApiTestFuzzer::Fuzz();
   4346   CHECK(false);
   4347 }
   4348 
   4349 
   4350 // Test that overwritten methods are not invoked on uncaught exception
   4351 // formatting. However, they are invoked when performing normal error
   4352 // string conversions.
   4353 TEST(APIThrowMessageOverwrittenToString) {
   4354   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4355   v8::V8::AddMessageListener(check_reference_error_message);
   4356   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4357   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
   4358   LocalContext context(NULL, templ);
   4359   CompileRun("asdf;");
   4360   CompileRun("var limit = {};"
   4361              "limit.valueOf = fail;"
   4362              "Error.stackTraceLimit = limit;");
   4363   CompileRun("asdf");
   4364   CompileRun("Array.prototype.pop = fail;");
   4365   CompileRun("Object.prototype.hasOwnProperty = fail;");
   4366   CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
   4367   CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
   4368   CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
   4369   CompileRun("ReferenceError.prototype.toString ="
   4370              "  function() { return 'Whoops' }");
   4371   CompileRun("asdf;");
   4372   CompileRun("ReferenceError.prototype.constructor.name = void 0;");
   4373   CompileRun("asdf;");
   4374   CompileRun("ReferenceError.prototype.constructor = void 0;");
   4375   CompileRun("asdf;");
   4376   CompileRun("ReferenceError.prototype.__proto__ = new Object();");
   4377   CompileRun("asdf;");
   4378   CompileRun("ReferenceError.prototype = new Object();");
   4379   CompileRun("asdf;");
   4380   v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
   4381   CHECK(string->Equals(v8_str("Whoops")));
   4382   CompileRun("ReferenceError.prototype.constructor = new Object();"
   4383              "ReferenceError.prototype.constructor.name = 1;"
   4384              "Number.prototype.toString = function() { return 'Whoops'; };"
   4385              "ReferenceError.prototype.toString = Object.prototype.toString;");
   4386   CompileRun("asdf;");
   4387   v8::V8::RemoveMessageListeners(check_reference_error_message);
   4388 }
   4389 
   4390 
   4391 static void check_custom_error_tostring(
   4392     v8::Handle<v8::Message> message,
   4393     v8::Handle<v8::Value> data) {
   4394   const char* uncaught_error = "Uncaught MyError toString";
   4395   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
   4396 }
   4397 
   4398 
   4399 TEST(CustomErrorToString) {
   4400   LocalContext context;
   4401   v8::HandleScope scope(context->GetIsolate());
   4402   v8::V8::AddMessageListener(check_custom_error_tostring);
   4403   CompileRun(
   4404     "function MyError(name, message) {                   "
   4405     "  this.name = name;                                 "
   4406     "  this.message = message;                           "
   4407     "}                                                   "
   4408     "MyError.prototype = Object.create(Error.prototype); "
   4409     "MyError.prototype.toString = function() {           "
   4410     "  return 'MyError toString';                        "
   4411     "};                                                  "
   4412     "throw new MyError('my name', 'my message');         ");
   4413   v8::V8::RemoveMessageListeners(check_custom_error_tostring);
   4414 }
   4415 
   4416 
   4417 static void check_custom_error_message(
   4418     v8::Handle<v8::Message> message,
   4419     v8::Handle<v8::Value> data) {
   4420   const char* uncaught_error = "Uncaught MyError: my message";
   4421   printf("%s\n", *v8::String::Utf8Value(message->Get()));
   4422   CHECK(message->Get()->Equals(v8_str(uncaught_error)));
   4423 }
   4424 
   4425 
   4426 TEST(CustomErrorMessage) {
   4427   LocalContext context;
   4428   v8::HandleScope scope(context->GetIsolate());
   4429   v8::V8::AddMessageListener(check_custom_error_message);
   4430 
   4431   // Handlebars.
   4432   CompileRun(
   4433     "function MyError(msg) {                             "
   4434     "  this.name = 'MyError';                            "
   4435     "  this.message = msg;                               "
   4436     "}                                                   "
   4437     "MyError.prototype = new Error();                    "
   4438     "throw new MyError('my message');                    ");
   4439 
   4440   // Closure.
   4441   CompileRun(
   4442     "function MyError(msg) {                             "
   4443     "  this.name = 'MyError';                            "
   4444     "  this.message = msg;                               "
   4445     "}                                                   "
   4446     "inherits = function(childCtor, parentCtor) {        "
   4447     "    function tempCtor() {};                         "
   4448     "    tempCtor.prototype = parentCtor.prototype;      "
   4449     "    childCtor.superClass_ = parentCtor.prototype;   "
   4450     "    childCtor.prototype = new tempCtor();           "
   4451     "    childCtor.prototype.constructor = childCtor;    "
   4452     "};                                                  "
   4453     "inherits(MyError, Error);                           "
   4454     "throw new MyError('my message');                    ");
   4455 
   4456   // Object.create.
   4457   CompileRun(
   4458     "function MyError(msg) {                             "
   4459     "  this.name = 'MyError';                            "
   4460     "  this.message = msg;                               "
   4461     "}                                                   "
   4462     "MyError.prototype = Object.create(Error.prototype); "
   4463     "throw new MyError('my message');                    ");
   4464 
   4465   v8::V8::RemoveMessageListeners(check_custom_error_message);
   4466 }
   4467 
   4468 
   4469 static void receive_message(v8::Handle<v8::Message> message,
   4470                             v8::Handle<v8::Value> data) {
   4471   message->Get();
   4472   message_received = true;
   4473 }
   4474 
   4475 
   4476 TEST(APIThrowMessage) {
   4477   message_received = false;
   4478   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4479   v8::V8::AddMessageListener(receive_message);
   4480   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4481   templ->Set(v8_str("ThrowFromC"),
   4482              v8::FunctionTemplate::New(ThrowFromC));
   4483   LocalContext context(0, templ);
   4484   CompileRun("ThrowFromC();");
   4485   CHECK(message_received);
   4486   v8::V8::RemoveMessageListeners(receive_message);
   4487 }
   4488 
   4489 
   4490 TEST(APIThrowMessageAndVerboseTryCatch) {
   4491   message_received = false;
   4492   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4493   v8::V8::AddMessageListener(receive_message);
   4494   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4495   templ->Set(v8_str("ThrowFromC"),
   4496              v8::FunctionTemplate::New(ThrowFromC));
   4497   LocalContext context(0, templ);
   4498   v8::TryCatch try_catch;
   4499   try_catch.SetVerbose(true);
   4500   Local<Value> result = CompileRun("ThrowFromC();");
   4501   CHECK(try_catch.HasCaught());
   4502   CHECK(result.IsEmpty());
   4503   CHECK(message_received);
   4504   v8::V8::RemoveMessageListeners(receive_message);
   4505 }
   4506 
   4507 
   4508 TEST(APIStackOverflowAndVerboseTryCatch) {
   4509   message_received = false;
   4510   LocalContext context;
   4511   v8::HandleScope scope(context->GetIsolate());
   4512   v8::V8::AddMessageListener(receive_message);
   4513   v8::TryCatch try_catch;
   4514   try_catch.SetVerbose(true);
   4515   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
   4516   CHECK(try_catch.HasCaught());
   4517   CHECK(result.IsEmpty());
   4518   CHECK(message_received);
   4519   v8::V8::RemoveMessageListeners(receive_message);
   4520 }
   4521 
   4522 
   4523 THREADED_TEST(ExternalScriptException) {
   4524   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4525   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4526   templ->Set(v8_str("ThrowFromC"),
   4527              v8::FunctionTemplate::New(ThrowFromC));
   4528   LocalContext context(0, templ);
   4529 
   4530   v8::TryCatch try_catch;
   4531   Local<Script> script
   4532       = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
   4533   Local<Value> result = script->Run();
   4534   CHECK(result.IsEmpty());
   4535   CHECK(try_catch.HasCaught());
   4536   String::Utf8Value exception_value(try_catch.Exception());
   4537   CHECK_EQ("konto", *exception_value);
   4538 }
   4539 
   4540 
   4541 
   4542 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4543   ApiTestFuzzer::Fuzz();
   4544   CHECK_EQ(4, args.Length());
   4545   int count = args[0]->Int32Value();
   4546   int cInterval = args[2]->Int32Value();
   4547   if (count == 0) {
   4548     v8::ThrowException(v8_str("FromC"));
   4549     return;
   4550   } else {
   4551     Local<v8::Object> global = Context::GetCurrent()->Global();
   4552     Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
   4553     v8::Handle<Value> argv[] = { v8_num(count - 1),
   4554                                  args[1],
   4555                                  args[2],
   4556                                  args[3] };
   4557     if (count % cInterval == 0) {
   4558       v8::TryCatch try_catch;
   4559       Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
   4560       int expected = args[3]->Int32Value();
   4561       if (try_catch.HasCaught()) {
   4562         CHECK_EQ(expected, count);
   4563         CHECK(result.IsEmpty());
   4564         CHECK(!i::Isolate::Current()->has_scheduled_exception());
   4565       } else {
   4566         CHECK_NE(expected, count);
   4567       }
   4568       args.GetReturnValue().Set(result);
   4569       return;
   4570     } else {
   4571       args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
   4572       return;
   4573     }
   4574   }
   4575 }
   4576 
   4577 
   4578 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4579   ApiTestFuzzer::Fuzz();
   4580   CHECK_EQ(3, args.Length());
   4581   bool equality = args[0]->BooleanValue();
   4582   int count = args[1]->Int32Value();
   4583   int expected = args[2]->Int32Value();
   4584   if (equality) {
   4585     CHECK_EQ(count, expected);
   4586   } else {
   4587     CHECK_NE(count, expected);
   4588   }
   4589 }
   4590 
   4591 
   4592 THREADED_TEST(EvalInTryFinally) {
   4593   LocalContext context;
   4594   v8::HandleScope scope(context->GetIsolate());
   4595   v8::TryCatch try_catch;
   4596   CompileRun("(function() {"
   4597              "  try {"
   4598              "    eval('asldkf (*&^&*^');"
   4599              "  } finally {"
   4600              "    return;"
   4601              "  }"
   4602              "})()");
   4603   CHECK(!try_catch.HasCaught());
   4604 }
   4605 
   4606 
   4607 // This test works by making a stack of alternating JavaScript and C
   4608 // activations.  These activations set up exception handlers with regular
   4609 // intervals, one interval for C activations and another for JavaScript
   4610 // activations.  When enough activations have been created an exception is
   4611 // thrown and we check that the right activation catches the exception and that
   4612 // no other activations do.  The right activation is always the topmost one with
   4613 // a handler, regardless of whether it is in JavaScript or C.
   4614 //
   4615 // The notation used to describe a test case looks like this:
   4616 //
   4617 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
   4618 //
   4619 // Each entry is an activation, either JS or C.  The index is the count at that
   4620 // level.  Stars identify activations with exception handlers, the @ identifies
   4621 // the exception handler that should catch the exception.
   4622 //
   4623 // BUG(271): Some of the exception propagation does not work on the
   4624 // ARM simulator because the simulator separates the C++ stack and the
   4625 // JS stack.  This test therefore fails on the simulator.  The test is
   4626 // not threaded to allow the threading tests to run on the simulator.
   4627 TEST(ExceptionOrder) {
   4628   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4629   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4630   templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
   4631   templ->Set(v8_str("CThrowCountDown"),
   4632              v8::FunctionTemplate::New(CThrowCountDown));
   4633   LocalContext context(0, templ);
   4634   CompileRun(
   4635     "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
   4636     "  if (count == 0) throw 'FromJS';"
   4637     "  if (count % jsInterval == 0) {"
   4638     "    try {"
   4639     "      var value = CThrowCountDown(count - 1,"
   4640     "                                  jsInterval,"
   4641     "                                  cInterval,"
   4642     "                                  expected);"
   4643     "      check(false, count, expected);"
   4644     "      return value;"
   4645     "    } catch (e) {"
   4646     "      check(true, count, expected);"
   4647     "    }"
   4648     "  } else {"
   4649     "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
   4650     "  }"
   4651     "}");
   4652   Local<Function> fun =
   4653       Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
   4654 
   4655   const int argc = 4;
   4656   //                             count      jsInterval cInterval  expected
   4657 
   4658   // *JS[4] *C[3] @JS[2] C[1] JS[0]
   4659   v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
   4660   fun->Call(fun, argc, a0);
   4661 
   4662   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
   4663   v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
   4664   fun->Call(fun, argc, a1);
   4665 
   4666   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
   4667   v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
   4668   fun->Call(fun, argc, a2);
   4669 
   4670   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
   4671   v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
   4672   fun->Call(fun, argc, a3);
   4673 
   4674   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
   4675   v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
   4676   fun->Call(fun, argc, a4);
   4677 
   4678   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
   4679   v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
   4680   fun->Call(fun, argc, a5);
   4681 }
   4682 
   4683 
   4684 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4685   ApiTestFuzzer::Fuzz();
   4686   CHECK_EQ(1, args.Length());
   4687   v8::ThrowException(args[0]);
   4688 }
   4689 
   4690 
   4691 THREADED_TEST(ThrowValues) {
   4692   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4693   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4694   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
   4695   LocalContext context(0, templ);
   4696   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   4697     "function Run(obj) {"
   4698     "  try {"
   4699     "    Throw(obj);"
   4700     "  } catch (e) {"
   4701     "    return e;"
   4702     "  }"
   4703     "  return 'no exception';"
   4704     "}"
   4705     "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
   4706   CHECK_EQ(5, result->Length());
   4707   CHECK(result->Get(v8::Integer::New(0))->IsString());
   4708   CHECK(result->Get(v8::Integer::New(1))->IsNumber());
   4709   CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
   4710   CHECK(result->Get(v8::Integer::New(2))->IsNumber());
   4711   CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
   4712   CHECK(result->Get(v8::Integer::New(3))->IsNull());
   4713   CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
   4714 }
   4715 
   4716 
   4717 THREADED_TEST(CatchZero) {
   4718   LocalContext context;
   4719   v8::HandleScope scope(context->GetIsolate());
   4720   v8::TryCatch try_catch;
   4721   CHECK(!try_catch.HasCaught());
   4722   Script::Compile(v8_str("throw 10"))->Run();
   4723   CHECK(try_catch.HasCaught());
   4724   CHECK_EQ(10, try_catch.Exception()->Int32Value());
   4725   try_catch.Reset();
   4726   CHECK(!try_catch.HasCaught());
   4727   Script::Compile(v8_str("throw 0"))->Run();
   4728   CHECK(try_catch.HasCaught());
   4729   CHECK_EQ(0, try_catch.Exception()->Int32Value());
   4730 }
   4731 
   4732 
   4733 THREADED_TEST(CatchExceptionFromWith) {
   4734   LocalContext context;
   4735   v8::HandleScope scope(context->GetIsolate());
   4736   v8::TryCatch try_catch;
   4737   CHECK(!try_catch.HasCaught());
   4738   Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
   4739   CHECK(try_catch.HasCaught());
   4740 }
   4741 
   4742 
   4743 THREADED_TEST(TryCatchAndFinallyHidingException) {
   4744   LocalContext context;
   4745   v8::HandleScope scope(context->GetIsolate());
   4746   v8::TryCatch try_catch;
   4747   CHECK(!try_catch.HasCaught());
   4748   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
   4749   CompileRun("f({toString: function() { throw 42; }});");
   4750   CHECK(!try_catch.HasCaught());
   4751 }
   4752 
   4753 
   4754 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   4755   v8::TryCatch try_catch;
   4756 }
   4757 
   4758 
   4759 THREADED_TEST(TryCatchAndFinally) {
   4760   LocalContext context;
   4761   v8::HandleScope scope(context->GetIsolate());
   4762   context->Global()->Set(
   4763       v8_str("native_with_try_catch"),
   4764       v8::FunctionTemplate::New(WithTryCatch)->GetFunction());
   4765   v8::TryCatch try_catch;
   4766   CHECK(!try_catch.HasCaught());
   4767   CompileRun(
   4768       "try {\n"
   4769       "  throw new Error('a');\n"
   4770       "} finally {\n"
   4771       "  native_with_try_catch();\n"
   4772       "}\n");
   4773   CHECK(try_catch.HasCaught());
   4774 }
   4775 
   4776 
   4777 static void TryCatchNestedHelper(int depth) {
   4778   if (depth > 0) {
   4779     v8::TryCatch try_catch;
   4780     try_catch.SetVerbose(true);
   4781     TryCatchNestedHelper(depth - 1);
   4782     CHECK(try_catch.HasCaught());
   4783     try_catch.ReThrow();
   4784   } else {
   4785     v8::ThrowException(v8_str("back"));
   4786   }
   4787 }
   4788 
   4789 
   4790 TEST(TryCatchNested) {
   4791   v8::V8::Initialize();
   4792   LocalContext context;
   4793   v8::HandleScope scope(context->GetIsolate());
   4794   v8::TryCatch try_catch;
   4795   TryCatchNestedHelper(5);
   4796   CHECK(try_catch.HasCaught());
   4797   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
   4798 }
   4799 
   4800 
   4801 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
   4802   CHECK(try_catch->HasCaught());
   4803   Handle<Message> message = try_catch->Message();
   4804   Handle<Value> resource = message->GetScriptResourceName();
   4805   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
   4806   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
   4807                      "Uncaught Error: a"));
   4808   CHECK_EQ(1, message->GetLineNumber());
   4809   CHECK_EQ(6, message->GetStartColumn());
   4810 }
   4811 
   4812 
   4813 void TryCatchMixedNestingHelper(
   4814     const v8::FunctionCallbackInfo<v8::Value>& args) {
   4815   ApiTestFuzzer::Fuzz();
   4816   v8::TryCatch try_catch;
   4817   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
   4818   CHECK(try_catch.HasCaught());
   4819   TryCatchMixedNestingCheck(&try_catch);
   4820   try_catch.ReThrow();
   4821 }
   4822 
   4823 
   4824 // This test ensures that an outer TryCatch in the following situation:
   4825 //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
   4826 // does not clobber the Message object generated for the inner TryCatch.
   4827 // This exercises the ability of TryCatch.ReThrow() to restore the
   4828 // inner pending Message before throwing the exception again.
   4829 TEST(TryCatchMixedNesting) {
   4830   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4831   v8::V8::Initialize();
   4832   v8::TryCatch try_catch;
   4833   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4834   templ->Set(v8_str("TryCatchMixedNestingHelper"),
   4835              v8::FunctionTemplate::New(TryCatchMixedNestingHelper));
   4836   LocalContext context(0, templ);
   4837   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
   4838   TryCatchMixedNestingCheck(&try_catch);
   4839 }
   4840 
   4841 
   4842 THREADED_TEST(Equality) {
   4843   LocalContext context;
   4844   v8::Isolate* isolate = context->GetIsolate();
   4845   v8::HandleScope scope(context->GetIsolate());
   4846   // Check that equality works at all before relying on CHECK_EQ
   4847   CHECK(v8_str("a")->Equals(v8_str("a")));
   4848   CHECK(!v8_str("a")->Equals(v8_str("b")));
   4849 
   4850   CHECK_EQ(v8_str("a"), v8_str("a"));
   4851   CHECK_NE(v8_str("a"), v8_str("b"));
   4852   CHECK_EQ(v8_num(1), v8_num(1));
   4853   CHECK_EQ(v8_num(1.00), v8_num(1));
   4854   CHECK_NE(v8_num(1), v8_num(2));
   4855 
   4856   // Assume String is not internalized.
   4857   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
   4858   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
   4859   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
   4860   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   4861   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
   4862   CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
   4863   Local<Value> not_a_number = v8_num(i::OS::nan_value());
   4864   CHECK(!not_a_number->StrictEquals(not_a_number));
   4865   CHECK(v8::False()->StrictEquals(v8::False()));
   4866   CHECK(!v8::False()->StrictEquals(v8::Undefined()));
   4867 
   4868   v8::Handle<v8::Object> obj = v8::Object::New();
   4869   v8::Persistent<v8::Object> alias(isolate, obj);
   4870   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
   4871   alias.Dispose(isolate);
   4872 }
   4873 
   4874 
   4875 THREADED_TEST(MultiRun) {
   4876   LocalContext context;
   4877   v8::HandleScope scope(context->GetIsolate());
   4878   Local<Script> script = Script::Compile(v8_str("x"));
   4879   for (int i = 0; i < 10; i++)
   4880     script->Run();
   4881 }
   4882 
   4883 
   4884 static void GetXValue(Local<String> name,
   4885                       const v8::PropertyCallbackInfo<v8::Value>& info) {
   4886   ApiTestFuzzer::Fuzz();
   4887   CHECK_EQ(info.Data(), v8_str("donut"));
   4888   CHECK_EQ(name, v8_str("x"));
   4889   info.GetReturnValue().Set(name);
   4890 }
   4891 
   4892 
   4893 THREADED_TEST(SimplePropertyRead) {
   4894   LocalContext context;
   4895   v8::HandleScope scope(context->GetIsolate());
   4896   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4897   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   4898   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   4899   Local<Script> script = Script::Compile(v8_str("obj.x"));
   4900   for (int i = 0; i < 10; i++) {
   4901     Local<Value> result = script->Run();
   4902     CHECK_EQ(result, v8_str("x"));
   4903   }
   4904 }
   4905 
   4906 
   4907 THREADED_TEST(DefinePropertyOnAPIAccessor) {
   4908   LocalContext context;
   4909   v8::HandleScope scope(context->GetIsolate());
   4910   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4911   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   4912   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   4913 
   4914   // Uses getOwnPropertyDescriptor to check the configurable status
   4915   Local<Script> script_desc
   4916     = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
   4917                              "obj, 'x');"
   4918                              "prop.configurable;"));
   4919   Local<Value> result = script_desc->Run();
   4920   CHECK_EQ(result->BooleanValue(), true);
   4921 
   4922   // Redefine get - but still configurable
   4923   Local<Script> script_define
   4924     = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
   4925                              "            configurable: true };"
   4926                              "Object.defineProperty(obj, 'x', desc);"
   4927                              "obj.x"));
   4928   result = script_define->Run();
   4929   CHECK_EQ(result, v8_num(42));
   4930 
   4931   // Check that the accessor is still configurable
   4932   result = script_desc->Run();
   4933   CHECK_EQ(result->BooleanValue(), true);
   4934 
   4935   // Redefine to a non-configurable
   4936   script_define
   4937     = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
   4938                              "             configurable: false };"
   4939                              "Object.defineProperty(obj, 'x', desc);"
   4940                              "obj.x"));
   4941   result = script_define->Run();
   4942   CHECK_EQ(result, v8_num(43));
   4943   result = script_desc->Run();
   4944   CHECK_EQ(result->BooleanValue(), false);
   4945 
   4946   // Make sure that it is not possible to redefine again
   4947   v8::TryCatch try_catch;
   4948   result = script_define->Run();
   4949   CHECK(try_catch.HasCaught());
   4950   String::Utf8Value exception_value(try_catch.Exception());
   4951   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   4952 }
   4953 
   4954 
   4955 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
   4956   v8::HandleScope scope(v8::Isolate::GetCurrent());
   4957   Local<ObjectTemplate> templ = ObjectTemplate::New();
   4958   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   4959   LocalContext context;
   4960   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   4961 
   4962   Local<Script> script_desc = Script::Compile(v8_str("var prop ="
   4963                                     "Object.getOwnPropertyDescriptor( "
   4964                                     "obj, 'x');"
   4965                                     "prop.configurable;"));
   4966   Local<Value> result = script_desc->Run();
   4967   CHECK_EQ(result->BooleanValue(), true);
   4968 
   4969   Local<Script> script_define =
   4970     Script::Compile(v8_str("var desc = {get: function(){return 42; },"
   4971                            "            configurable: true };"
   4972                            "Object.defineProperty(obj, 'x', desc);"
   4973                            "obj.x"));
   4974   result = script_define->Run();
   4975   CHECK_EQ(result, v8_num(42));
   4976 
   4977 
   4978   result = script_desc->Run();
   4979   CHECK_EQ(result->BooleanValue(), true);
   4980 
   4981 
   4982   script_define =
   4983     Script::Compile(v8_str("var desc = {get: function(){return 43; },"
   4984                            "            configurable: false };"
   4985                            "Object.defineProperty(obj, 'x', desc);"
   4986                            "obj.x"));
   4987   result = script_define->Run();
   4988   CHECK_EQ(result, v8_num(43));
   4989   result = script_desc->Run();
   4990 
   4991   CHECK_EQ(result->BooleanValue(), false);
   4992 
   4993   v8::TryCatch try_catch;
   4994   result = script_define->Run();
   4995   CHECK(try_catch.HasCaught());
   4996   String::Utf8Value exception_value(try_catch.Exception());
   4997   CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   4998 }
   4999 
   5000 
   5001 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
   5002                                                 char const* name) {
   5003   return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
   5004 }
   5005 
   5006 
   5007 THREADED_TEST(DefineAPIAccessorOnObject) {
   5008   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5009   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5010   LocalContext context;
   5011 
   5012   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   5013   CompileRun("var obj2 = {};");
   5014 
   5015   CHECK(CompileRun("obj1.x")->IsUndefined());
   5016   CHECK(CompileRun("obj2.x")->IsUndefined());
   5017 
   5018   CHECK(GetGlobalProperty(&context, "obj1")->
   5019       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5020 
   5021   ExpectString("obj1.x", "x");
   5022   CHECK(CompileRun("obj2.x")->IsUndefined());
   5023 
   5024   CHECK(GetGlobalProperty(&context, "obj2")->
   5025       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5026 
   5027   ExpectString("obj1.x", "x");
   5028   ExpectString("obj2.x", "x");
   5029 
   5030   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5031   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5032 
   5033   CompileRun("Object.defineProperty(obj1, 'x',"
   5034              "{ get: function() { return 'y'; }, configurable: true })");
   5035 
   5036   ExpectString("obj1.x", "y");
   5037   ExpectString("obj2.x", "x");
   5038 
   5039   CompileRun("Object.defineProperty(obj2, 'x',"
   5040              "{ get: function() { return 'y'; }, configurable: true })");
   5041 
   5042   ExpectString("obj1.x", "y");
   5043   ExpectString("obj2.x", "y");
   5044 
   5045   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5046   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5047 
   5048   CHECK(GetGlobalProperty(&context, "obj1")->
   5049       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5050   CHECK(GetGlobalProperty(&context, "obj2")->
   5051       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5052 
   5053   ExpectString("obj1.x", "x");
   5054   ExpectString("obj2.x", "x");
   5055 
   5056   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5057   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5058 
   5059   // Define getters/setters, but now make them not configurable.
   5060   CompileRun("Object.defineProperty(obj1, 'x',"
   5061              "{ get: function() { return 'z'; }, configurable: false })");
   5062   CompileRun("Object.defineProperty(obj2, 'x',"
   5063              "{ get: function() { return 'z'; }, configurable: false })");
   5064 
   5065   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5066   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5067 
   5068   ExpectString("obj1.x", "z");
   5069   ExpectString("obj2.x", "z");
   5070 
   5071   CHECK(!GetGlobalProperty(&context, "obj1")->
   5072       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5073   CHECK(!GetGlobalProperty(&context, "obj2")->
   5074       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5075 
   5076   ExpectString("obj1.x", "z");
   5077   ExpectString("obj2.x", "z");
   5078 }
   5079 
   5080 
   5081 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
   5082   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5083   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5084   LocalContext context;
   5085 
   5086   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   5087   CompileRun("var obj2 = {};");
   5088 
   5089   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   5090         v8_str("x"),
   5091         GetXValue, NULL,
   5092         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   5093   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   5094         v8_str("x"),
   5095         GetXValue, NULL,
   5096         v8_str("donut"), v8::DEFAULT, v8::DontDelete));
   5097 
   5098   ExpectString("obj1.x", "x");
   5099   ExpectString("obj2.x", "x");
   5100 
   5101   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   5102   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   5103 
   5104   CHECK(!GetGlobalProperty(&context, "obj1")->
   5105       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5106   CHECK(!GetGlobalProperty(&context, "obj2")->
   5107       SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
   5108 
   5109   {
   5110     v8::TryCatch try_catch;
   5111     CompileRun("Object.defineProperty(obj1, 'x',"
   5112         "{get: function() { return 'func'; }})");
   5113     CHECK(try_catch.HasCaught());
   5114     String::Utf8Value exception_value(try_catch.Exception());
   5115     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5116   }
   5117   {
   5118     v8::TryCatch try_catch;
   5119     CompileRun("Object.defineProperty(obj2, 'x',"
   5120         "{get: function() { return 'func'; }})");
   5121     CHECK(try_catch.HasCaught());
   5122     String::Utf8Value exception_value(try_catch.Exception());
   5123     CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
   5124   }
   5125 }
   5126 
   5127 
   5128 static void Get239Value(Local<String> name,
   5129                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   5130   ApiTestFuzzer::Fuzz();
   5131   CHECK_EQ(info.Data(), v8_str("donut"));
   5132   CHECK_EQ(name, v8_str("239"));
   5133   info.GetReturnValue().Set(name);
   5134 }
   5135 
   5136 
   5137 THREADED_TEST(ElementAPIAccessor) {
   5138   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5139   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5140   LocalContext context;
   5141 
   5142   context->Global()->Set(v8_str("obj1"), templ->NewInstance());
   5143   CompileRun("var obj2 = {};");
   5144 
   5145   CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
   5146         v8_str("239"),
   5147         Get239Value, NULL,
   5148         v8_str("donut")));
   5149   CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
   5150         v8_str("239"),
   5151         Get239Value, NULL,
   5152         v8_str("donut")));
   5153 
   5154   ExpectString("obj1[239]", "239");
   5155   ExpectString("obj2[239]", "239");
   5156   ExpectString("obj1['239']", "239");
   5157   ExpectString("obj2['239']", "239");
   5158 }
   5159 
   5160 
   5161 v8::Persistent<Value> xValue;
   5162 
   5163 
   5164 static void SetXValue(Local<String> name,
   5165                       Local<Value> value,
   5166                       const v8::PropertyCallbackInfo<void>& info) {
   5167   CHECK_EQ(value, v8_num(4));
   5168   CHECK_EQ(info.Data(), v8_str("donut"));
   5169   CHECK_EQ(name, v8_str("x"));
   5170   CHECK(xValue.IsEmpty());
   5171   xValue.Reset(info.GetIsolate(), value);
   5172 }
   5173 
   5174 
   5175 THREADED_TEST(SimplePropertyWrite) {
   5176   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5177   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5178   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
   5179   LocalContext context;
   5180   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5181   Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
   5182   for (int i = 0; i < 10; i++) {
   5183     CHECK(xValue.IsEmpty());
   5184     script->Run();
   5185     CHECK_EQ(v8_num(4), Local<Value>::New(v8::Isolate::GetCurrent(), xValue));
   5186     xValue.Dispose(context->GetIsolate());
   5187     xValue.Clear();
   5188   }
   5189 }
   5190 
   5191 
   5192 THREADED_TEST(SetterOnly) {
   5193   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5194   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5195   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
   5196   LocalContext context;
   5197   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5198   Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
   5199   for (int i = 0; i < 10; i++) {
   5200     CHECK(xValue.IsEmpty());
   5201     script->Run();
   5202     CHECK_EQ(v8_num(4), Local<Value>::New(v8::Isolate::GetCurrent(), xValue));
   5203     xValue.Dispose(context->GetIsolate());
   5204     xValue.Clear();
   5205   }
   5206 }
   5207 
   5208 
   5209 THREADED_TEST(NoAccessors) {
   5210   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5211   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5212   templ->SetAccessor(v8_str("x"),
   5213                      static_cast<v8::AccessorGetterCallback>(NULL),
   5214                      NULL,
   5215                      v8_str("donut"));
   5216   LocalContext context;
   5217   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5218   Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
   5219   for (int i = 0; i < 10; i++) {
   5220     script->Run();
   5221   }
   5222 }
   5223 
   5224 
   5225 static void XPropertyGetter(Local<String> property,
   5226                             const v8::PropertyCallbackInfo<v8::Value>& info) {
   5227   ApiTestFuzzer::Fuzz();
   5228   CHECK(info.Data()->IsUndefined());
   5229   info.GetReturnValue().Set(property);
   5230 }
   5231 
   5232 
   5233 THREADED_TEST(NamedInterceptorPropertyRead) {
   5234   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5235   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5236   templ->SetNamedPropertyHandler(XPropertyGetter);
   5237   LocalContext context;
   5238   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5239   Local<Script> script = Script::Compile(v8_str("obj.x"));
   5240   for (int i = 0; i < 10; i++) {
   5241     Local<Value> result = script->Run();
   5242     CHECK_EQ(result, v8_str("x"));
   5243   }
   5244 }
   5245 
   5246 
   5247 THREADED_TEST(NamedInterceptorDictionaryIC) {
   5248   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5249   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5250   templ->SetNamedPropertyHandler(XPropertyGetter);
   5251   LocalContext context;
   5252   // Create an object with a named interceptor.
   5253   context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
   5254   Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
   5255   for (int i = 0; i < 10; i++) {
   5256     Local<Value> result = script->Run();
   5257     CHECK_EQ(result, v8_str("x"));
   5258   }
   5259   // Create a slow case object and a function accessing a property in
   5260   // that slow case object (with dictionary probing in generated
   5261   // code). Then force object with a named interceptor into slow-case,
   5262   // pass it to the function, and check that the interceptor is called
   5263   // instead of accessing the local property.
   5264   Local<Value> result =
   5265       CompileRun("function get_x(o) { return o.x; };"
   5266                  "var obj = { x : 42, y : 0 };"
   5267                  "delete obj.y;"
   5268                  "for (var i = 0; i < 10; i++) get_x(obj);"
   5269                  "interceptor_obj.x = 42;"
   5270                  "interceptor_obj.y = 10;"
   5271                  "delete interceptor_obj.y;"
   5272                  "get_x(interceptor_obj)");
   5273   CHECK_EQ(result, v8_str("x"));
   5274 }
   5275 
   5276 
   5277 THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
   5278   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   5279   v8::HandleScope scope(isolate);
   5280   v8::Local<Context> context1 = Context::New(isolate);
   5281 
   5282   context1->Enter();
   5283   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5284   templ->SetNamedPropertyHandler(XPropertyGetter);
   5285   // Create an object with a named interceptor.
   5286   v8::Local<v8::Object> object = templ->NewInstance();
   5287   context1->Global()->Set(v8_str("interceptor_obj"), object);
   5288 
   5289   // Force the object into the slow case.
   5290   CompileRun("interceptor_obj.y = 0;"
   5291              "delete interceptor_obj.y;");
   5292   context1->Exit();
   5293 
   5294   {
   5295     // Introduce the object into a different context.
   5296     // Repeat named loads to exercise ICs.
   5297     LocalContext context2;
   5298     context2->Global()->Set(v8_str("interceptor_obj"), object);
   5299     Local<Value> result =
   5300       CompileRun("function get_x(o) { return o.x; }"
   5301                  "interceptor_obj.x = 42;"
   5302                  "for (var i=0; i != 10; i++) {"
   5303                  "  get_x(interceptor_obj);"
   5304                  "}"
   5305                  "get_x(interceptor_obj)");
   5306     // Check that the interceptor was actually invoked.
   5307     CHECK_EQ(result, v8_str("x"));
   5308   }
   5309 
   5310   // Return to the original context and force some object to the slow case
   5311   // to cause the NormalizedMapCache to verify.
   5312   context1->Enter();
   5313   CompileRun("var obj = { x : 0 }; delete obj.x;");
   5314   context1->Exit();
   5315 }
   5316 
   5317 
   5318 static void SetXOnPrototypeGetter(
   5319     Local<String> property,
   5320     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5321   // Set x on the prototype object and do not handle the get request.
   5322   v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
   5323   proto.As<v8::Object>()->Set(v8_str("x"), v8::Integer::New(23));
   5324 }
   5325 
   5326 
   5327 // This is a regression test for http://crbug.com/20104. Map
   5328 // transitions should not interfere with post interceptor lookup.
   5329 THREADED_TEST(NamedInterceptorMapTransitionRead) {
   5330   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5331   Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
   5332   Local<v8::ObjectTemplate> instance_template
   5333       = function_template->InstanceTemplate();
   5334   instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
   5335   LocalContext context;
   5336   context->Global()->Set(v8_str("F"), function_template->GetFunction());
   5337   // Create an instance of F and introduce a map transition for x.
   5338   CompileRun("var o = new F(); o.x = 23;");
   5339   // Create an instance of F and invoke the getter. The result should be 23.
   5340   Local<Value> result = CompileRun("o = new F(); o.x");
   5341   CHECK_EQ(result->Int32Value(), 23);
   5342 }
   5343 
   5344 
   5345 static void IndexedPropertyGetter(
   5346     uint32_t index,
   5347     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5348   ApiTestFuzzer::Fuzz();
   5349   if (index == 37) {
   5350     info.GetReturnValue().Set(v8_num(625));
   5351   }
   5352 }
   5353 
   5354 
   5355 static void IndexedPropertySetter(
   5356     uint32_t index,
   5357     Local<Value> value,
   5358     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5359   ApiTestFuzzer::Fuzz();
   5360   if (index == 39) {
   5361     info.GetReturnValue().Set(value);
   5362   }
   5363 }
   5364 
   5365 
   5366 THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
   5367   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5368   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5369   templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
   5370                                    IndexedPropertySetter);
   5371   LocalContext context;
   5372   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5373   Local<Script> getter_script = Script::Compile(v8_str(
   5374       "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
   5375   Local<Script> setter_script = Script::Compile(v8_str(
   5376       "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
   5377       "obj[17] = 23;"
   5378       "obj.foo;"));
   5379   Local<Script> interceptor_setter_script = Script::Compile(v8_str(
   5380       "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
   5381       "obj[39] = 47;"
   5382       "obj.foo;"));  // This setter should not run, due to the interceptor.
   5383   Local<Script> interceptor_getter_script = Script::Compile(v8_str(
   5384       "obj[37];"));
   5385   Local<Value> result = getter_script->Run();
   5386   CHECK_EQ(v8_num(5), result);
   5387   result = setter_script->Run();
   5388   CHECK_EQ(v8_num(23), result);
   5389   result = interceptor_setter_script->Run();
   5390   CHECK_EQ(v8_num(23), result);
   5391   result = interceptor_getter_script->Run();
   5392   CHECK_EQ(v8_num(625), result);
   5393 }
   5394 
   5395 
   5396 static void UnboxedDoubleIndexedPropertyGetter(
   5397     uint32_t index,
   5398     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5399   ApiTestFuzzer::Fuzz();
   5400   if (index < 25) {
   5401     info.GetReturnValue().Set(v8_num(index));
   5402   }
   5403 }
   5404 
   5405 
   5406 static void UnboxedDoubleIndexedPropertySetter(
   5407     uint32_t index,
   5408     Local<Value> value,
   5409     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5410   ApiTestFuzzer::Fuzz();
   5411   if (index < 25) {
   5412     info.GetReturnValue().Set(v8_num(index));
   5413   }
   5414 }
   5415 
   5416 
   5417 void UnboxedDoubleIndexedPropertyEnumerator(
   5418     const v8::PropertyCallbackInfo<v8::Array>& info) {
   5419   // Force the list of returned keys to be stored in a FastDoubleArray.
   5420   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
   5421       "keys = new Array(); keys[125000] = 1;"
   5422       "for(i = 0; i < 80000; i++) { keys[i] = i; };"
   5423       "keys.length = 25; keys;"));
   5424   Local<Value> result = indexed_property_names_script->Run();
   5425   info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
   5426 }
   5427 
   5428 
   5429 // Make sure that the the interceptor code in the runtime properly handles
   5430 // merging property name lists for double-array-backed arrays.
   5431 THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
   5432   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5433   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5434   templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
   5435                                    UnboxedDoubleIndexedPropertySetter,
   5436                                    0,
   5437                                    0,
   5438                                    UnboxedDoubleIndexedPropertyEnumerator);
   5439   LocalContext context;
   5440   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5441   // When obj is created, force it to be Stored in a FastDoubleArray.
   5442   Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
   5443       "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
   5444       "key_count = 0; "
   5445       "for (x in obj) {key_count++;};"
   5446       "obj;"));
   5447   Local<Value> result = create_unboxed_double_script->Run();
   5448   CHECK(result->ToObject()->HasRealIndexedProperty(2000));
   5449   Local<Script> key_count_check = Script::Compile(v8_str(
   5450       "key_count;"));
   5451   result = key_count_check->Run();
   5452   CHECK_EQ(v8_num(40013), result);
   5453 }
   5454 
   5455 
   5456 void NonStrictArgsIndexedPropertyEnumerator(
   5457     const v8::PropertyCallbackInfo<v8::Array>& info) {
   5458   // Force the list of returned keys to be stored in a Arguments object.
   5459   Local<Script> indexed_property_names_script = Script::Compile(v8_str(
   5460       "function f(w,x) {"
   5461       " return arguments;"
   5462       "}"
   5463       "keys = f(0, 1, 2, 3);"
   5464       "keys;"));
   5465   Local<Object> result =
   5466       Local<Object>::Cast(indexed_property_names_script->Run());
   5467   // Have to populate the handle manually, as it's not Cast-able.
   5468   i::Handle<i::JSObject> o =
   5469       v8::Utils::OpenHandle<Object, i::JSObject>(result);
   5470   i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
   5471   info.GetReturnValue().Set(v8::Utils::ToLocal(array));
   5472 }
   5473 
   5474 
   5475 static void NonStrictIndexedPropertyGetter(
   5476     uint32_t index,
   5477     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5478   ApiTestFuzzer::Fuzz();
   5479   if (index < 4) {
   5480     info.GetReturnValue().Set(v8_num(index));
   5481   }
   5482 }
   5483 
   5484 
   5485 // Make sure that the the interceptor code in the runtime properly handles
   5486 // merging property name lists for non-string arguments arrays.
   5487 THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
   5488   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5489   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5490   templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
   5491                                    0,
   5492                                    0,
   5493                                    0,
   5494                                    NonStrictArgsIndexedPropertyEnumerator);
   5495   LocalContext context;
   5496   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5497   Local<Script> create_args_script =
   5498       Script::Compile(v8_str(
   5499           "var key_count = 0;"
   5500           "for (x in obj) {key_count++;} key_count;"));
   5501   Local<Value> result = create_args_script->Run();
   5502   CHECK_EQ(v8_num(4), result);
   5503 }
   5504 
   5505 
   5506 static void IdentityIndexedPropertyGetter(
   5507     uint32_t index,
   5508     const v8::PropertyCallbackInfo<v8::Value>& info) {
   5509   info.GetReturnValue().Set(index);
   5510 }
   5511 
   5512 
   5513 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
   5514   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5515   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5516   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5517 
   5518   LocalContext context;
   5519   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5520 
   5521   // Check fast object case.
   5522   const char* fast_case_code =
   5523       "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
   5524   ExpectString(fast_case_code, "0");
   5525 
   5526   // Check slow case.
   5527   const char* slow_case_code =
   5528       "obj.x = 1; delete obj.x;"
   5529       "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
   5530   ExpectString(slow_case_code, "1");
   5531 }
   5532 
   5533 
   5534 THREADED_TEST(IndexedInterceptorWithNoSetter) {
   5535   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5536   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5537   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5538 
   5539   LocalContext context;
   5540   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   5541 
   5542   const char* code =
   5543       "try {"
   5544       "  obj[0] = 239;"
   5545       "  for (var i = 0; i < 100; i++) {"
   5546       "    var v = obj[0];"
   5547       "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5548       "  }"
   5549       "  'PASSED'"
   5550       "} catch(e) {"
   5551       "  e"
   5552       "}";
   5553   ExpectString(code, "PASSED");
   5554 }
   5555 
   5556 
   5557 THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
   5558   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5559   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5560   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5561 
   5562   LocalContext context;
   5563   Local<v8::Object> obj = templ->NewInstance();
   5564   obj->TurnOnAccessCheck();
   5565   context->Global()->Set(v8_str("obj"), obj);
   5566 
   5567   const char* code =
   5568       "try {"
   5569       "  for (var i = 0; i < 100; i++) {"
   5570       "    var v = obj[0];"
   5571       "    if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5572       "  }"
   5573       "  'PASSED'"
   5574       "} catch(e) {"
   5575       "  e"
   5576       "}";
   5577   ExpectString(code, "PASSED");
   5578 }
   5579 
   5580 
   5581 THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
   5582   i::FLAG_allow_natives_syntax = true;
   5583   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5584   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5585   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5586 
   5587   LocalContext context;
   5588   Local<v8::Object> obj = templ->NewInstance();
   5589   context->Global()->Set(v8_str("obj"), obj);
   5590 
   5591   const char* code =
   5592       "try {"
   5593       "  for (var i = 0; i < 100; i++) {"
   5594       "    var expected = i;"
   5595       "    if (i == 5) {"
   5596       "      %EnableAccessChecks(obj);"
   5597       "      expected = undefined;"
   5598       "    }"
   5599       "    var v = obj[i];"
   5600       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5601       "    if (i == 5) %DisableAccessChecks(obj);"
   5602       "  }"
   5603       "  'PASSED'"
   5604       "} catch(e) {"
   5605       "  e"
   5606       "}";
   5607   ExpectString(code, "PASSED");
   5608 }
   5609 
   5610 
   5611 THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
   5612   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5613   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5614   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5615 
   5616   LocalContext context;
   5617   Local<v8::Object> obj = templ->NewInstance();
   5618   context->Global()->Set(v8_str("obj"), obj);
   5619 
   5620   const char* code =
   5621       "try {"
   5622       "  for (var i = 0; i < 100; i++) {"
   5623       "    var v = obj[i];"
   5624       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5625       "  }"
   5626       "  'PASSED'"
   5627       "} catch(e) {"
   5628       "  e"
   5629       "}";
   5630   ExpectString(code, "PASSED");
   5631 }
   5632 
   5633 
   5634 THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
   5635   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5636   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5637   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5638 
   5639   LocalContext context;
   5640   Local<v8::Object> obj = templ->NewInstance();
   5641   context->Global()->Set(v8_str("obj"), obj);
   5642 
   5643   const char* code =
   5644       "try {"
   5645       "  for (var i = 0; i < 100; i++) {"
   5646       "    var expected = i;"
   5647       "    var key = i;"
   5648       "    if (i == 25) {"
   5649       "       key = -1;"
   5650       "       expected = undefined;"
   5651       "    }"
   5652       "    if (i == 50) {"
   5653       "       /* probe minimal Smi number on 32-bit platforms */"
   5654       "       key = -(1 << 30);"
   5655       "       expected = undefined;"
   5656       "    }"
   5657       "    if (i == 75) {"
   5658       "       /* probe minimal Smi number on 64-bit platforms */"
   5659       "       key = 1 << 31;"
   5660       "       expected = undefined;"
   5661       "    }"
   5662       "    var v = obj[key];"
   5663       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5664       "  }"
   5665       "  'PASSED'"
   5666       "} catch(e) {"
   5667       "  e"
   5668       "}";
   5669   ExpectString(code, "PASSED");
   5670 }
   5671 
   5672 
   5673 THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
   5674   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5675   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5676   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5677 
   5678   LocalContext context;
   5679   Local<v8::Object> obj = templ->NewInstance();
   5680   context->Global()->Set(v8_str("obj"), obj);
   5681 
   5682   const char* code =
   5683       "try {"
   5684       "  for (var i = 0; i < 100; i++) {"
   5685       "    var expected = i;"
   5686       "    var key = i;"
   5687       "    if (i == 50) {"
   5688       "       key = 'foobar';"
   5689       "       expected = undefined;"
   5690       "    }"
   5691       "    var v = obj[key];"
   5692       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5693       "  }"
   5694       "  'PASSED'"
   5695       "} catch(e) {"
   5696       "  e"
   5697       "}";
   5698   ExpectString(code, "PASSED");
   5699 }
   5700 
   5701 
   5702 THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
   5703   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5704   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5705   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5706 
   5707   LocalContext context;
   5708   Local<v8::Object> obj = templ->NewInstance();
   5709   context->Global()->Set(v8_str("obj"), obj);
   5710 
   5711   const char* code =
   5712       "var original = obj;"
   5713       "try {"
   5714       "  for (var i = 0; i < 100; i++) {"
   5715       "    var expected = i;"
   5716       "    if (i == 50) {"
   5717       "       obj = {50: 'foobar'};"
   5718       "       expected = 'foobar';"
   5719       "    }"
   5720       "    var v = obj[i];"
   5721       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5722       "    if (i == 50) obj = original;"
   5723       "  }"
   5724       "  'PASSED'"
   5725       "} catch(e) {"
   5726       "  e"
   5727       "}";
   5728   ExpectString(code, "PASSED");
   5729 }
   5730 
   5731 
   5732 THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
   5733   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5734   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5735   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5736 
   5737   LocalContext context;
   5738   Local<v8::Object> obj = templ->NewInstance();
   5739   context->Global()->Set(v8_str("obj"), obj);
   5740 
   5741   const char* code =
   5742       "var original = obj;"
   5743       "try {"
   5744       "  for (var i = 0; i < 100; i++) {"
   5745       "    var expected = i;"
   5746       "    if (i == 5) {"
   5747       "       obj = 239;"
   5748       "       expected = undefined;"
   5749       "    }"
   5750       "    var v = obj[i];"
   5751       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5752       "    if (i == 5) obj = original;"
   5753       "  }"
   5754       "  'PASSED'"
   5755       "} catch(e) {"
   5756       "  e"
   5757       "}";
   5758   ExpectString(code, "PASSED");
   5759 }
   5760 
   5761 
   5762 THREADED_TEST(IndexedInterceptorOnProto) {
   5763   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5764   Local<ObjectTemplate> templ = ObjectTemplate::New();
   5765   templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
   5766 
   5767   LocalContext context;
   5768   Local<v8::Object> obj = templ->NewInstance();
   5769   context->Global()->Set(v8_str("obj"), obj);
   5770 
   5771   const char* code =
   5772       "var o = {__proto__: obj};"
   5773       "try {"
   5774       "  for (var i = 0; i < 100; i++) {"
   5775       "    var v = o[i];"
   5776       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
   5777       "  }"
   5778       "  'PASSED'"
   5779       "} catch(e) {"
   5780       "  e"
   5781       "}";
   5782   ExpectString(code, "PASSED");
   5783 }
   5784 
   5785 
   5786 THREADED_TEST(MultiContexts) {
   5787   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5788   v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
   5789   templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
   5790 
   5791   Local<String> password = v8_str("Password");
   5792 
   5793   // Create an environment
   5794   LocalContext context0(0, templ);
   5795   context0->SetSecurityToken(password);
   5796   v8::Handle<v8::Object> global0 = context0->Global();
   5797   global0->Set(v8_str("custom"), v8_num(1234));
   5798   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   5799 
   5800   // Create an independent environment
   5801   LocalContext context1(0, templ);
   5802   context1->SetSecurityToken(password);
   5803   v8::Handle<v8::Object> global1 = context1->Global();
   5804   global1->Set(v8_str("custom"), v8_num(1234));
   5805   CHECK_NE(global0, global1);
   5806   CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
   5807   CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
   5808 
   5809   // Now create a new context with the old global
   5810   LocalContext context2(0, templ, global1);
   5811   context2->SetSecurityToken(password);
   5812   v8::Handle<v8::Object> global2 = context2->Global();
   5813   CHECK_EQ(global1, global2);
   5814   CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
   5815   CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
   5816 }
   5817 
   5818 
   5819 THREADED_TEST(FunctionPrototypeAcrossContexts) {
   5820   // Make sure that functions created by cloning boilerplates cannot
   5821   // communicate through their __proto__ field.
   5822 
   5823   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5824 
   5825   LocalContext env0;
   5826   v8::Handle<v8::Object> global0 =
   5827       env0->Global();
   5828   v8::Handle<v8::Object> object0 =
   5829       global0->Get(v8_str("Object")).As<v8::Object>();
   5830   v8::Handle<v8::Object> tostring0 =
   5831       object0->Get(v8_str("toString")).As<v8::Object>();
   5832   v8::Handle<v8::Object> proto0 =
   5833       tostring0->Get(v8_str("__proto__")).As<v8::Object>();
   5834   proto0->Set(v8_str("custom"), v8_num(1234));
   5835 
   5836   LocalContext env1;
   5837   v8::Handle<v8::Object> global1 =
   5838       env1->Global();
   5839   v8::Handle<v8::Object> object1 =
   5840       global1->Get(v8_str("Object")).As<v8::Object>();
   5841   v8::Handle<v8::Object> tostring1 =
   5842       object1->Get(v8_str("toString")).As<v8::Object>();
   5843   v8::Handle<v8::Object> proto1 =
   5844       tostring1->Get(v8_str("__proto__")).As<v8::Object>();
   5845   CHECK(!proto1->Has(v8_str("custom")));
   5846 }
   5847 
   5848 
   5849 THREADED_TEST(Regress892105) {
   5850   // Make sure that object and array literals created by cloning
   5851   // boilerplates cannot communicate through their __proto__
   5852   // field. This is rather difficult to check, but we try to add stuff
   5853   // to Object.prototype and Array.prototype and create a new
   5854   // environment. This should succeed.
   5855 
   5856   v8::HandleScope scope(v8::Isolate::GetCurrent());
   5857 
   5858   Local<String> source = v8_str("Object.prototype.obj = 1234;"
   5859                                 "Array.prototype.arr = 4567;"
   5860                                 "8901");
   5861 
   5862   LocalContext env0;
   5863   Local<Script> script0 = Script::Compile(source);
   5864   CHECK_EQ(8901.0, script0->Run()->NumberValue());
   5865 
   5866   LocalContext env1;
   5867   Local<Script> script1 = Script::Compile(source);
   5868   CHECK_EQ(8901.0, script1->Run()->NumberValue());
   5869 }
   5870 
   5871 
   5872 THREADED_TEST(UndetectableObject) {
   5873   LocalContext env;
   5874   v8::HandleScope scope(env->GetIsolate());
   5875 
   5876   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   5877   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   5878 
   5879   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   5880   env->Global()->Set(v8_str("undetectable"), obj);
   5881 
   5882   ExpectString("undetectable.toString()", "[object Object]");
   5883   ExpectString("typeof undetectable", "undefined");
   5884   ExpectString("typeof(undetectable)", "undefined");
   5885   ExpectBoolean("typeof undetectable == 'undefined'", true);
   5886   ExpectBoolean("typeof undetectable == 'object'", false);
   5887   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   5888   ExpectBoolean("!undetectable", true);
   5889 
   5890   ExpectObject("true&&undetectable", obj);
   5891   ExpectBoolean("false&&undetectable", false);
   5892   ExpectBoolean("true||undetectable", true);
   5893   ExpectObject("false||undetectable", obj);
   5894 
   5895   ExpectObject("undetectable&&true", obj);
   5896   ExpectObject("undetectable&&false", obj);
   5897   ExpectBoolean("undetectable||true", true);
   5898   ExpectBoolean("undetectable||false", false);
   5899 
   5900   ExpectBoolean("undetectable==null", true);
   5901   ExpectBoolean("null==undetectable", true);
   5902   ExpectBoolean("undetectable==undefined", true);
   5903   ExpectBoolean("undefined==undetectable", true);
   5904   ExpectBoolean("undetectable==undetectable", true);
   5905 
   5906 
   5907   ExpectBoolean("undetectable===null", false);
   5908   ExpectBoolean("null===undetectable", false);
   5909   ExpectBoolean("undetectable===undefined", false);
   5910   ExpectBoolean("undefined===undetectable", false);
   5911   ExpectBoolean("undetectable===undetectable", true);
   5912 }
   5913 
   5914 
   5915 THREADED_TEST(VoidLiteral) {
   5916   LocalContext env;
   5917   v8::HandleScope scope(env->GetIsolate());
   5918 
   5919   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   5920   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   5921 
   5922   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   5923   env->Global()->Set(v8_str("undetectable"), obj);
   5924 
   5925   ExpectBoolean("undefined == void 0", true);
   5926   ExpectBoolean("undetectable == void 0", true);
   5927   ExpectBoolean("null == void 0", true);
   5928   ExpectBoolean("undefined === void 0", true);
   5929   ExpectBoolean("undetectable === void 0", false);
   5930   ExpectBoolean("null === void 0", false);
   5931 
   5932   ExpectBoolean("void 0 == undefined", true);
   5933   ExpectBoolean("void 0 == undetectable", true);
   5934   ExpectBoolean("void 0 == null", true);
   5935   ExpectBoolean("void 0 === undefined", true);
   5936   ExpectBoolean("void 0 === undetectable", false);
   5937   ExpectBoolean("void 0 === null", false);
   5938 
   5939   ExpectString("(function() {"
   5940                "  try {"
   5941                "    return x === void 0;"
   5942                "  } catch(e) {"
   5943                "    return e.toString();"
   5944                "  }"
   5945                "})()",
   5946                "ReferenceError: x is not defined");
   5947   ExpectString("(function() {"
   5948                "  try {"
   5949                "    return void 0 === x;"
   5950                "  } catch(e) {"
   5951                "    return e.toString();"
   5952                "  }"
   5953                "})()",
   5954                "ReferenceError: x is not defined");
   5955 }
   5956 
   5957 
   5958 THREADED_TEST(ExtensibleOnUndetectable) {
   5959   LocalContext env;
   5960   v8::HandleScope scope(env->GetIsolate());
   5961 
   5962   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   5963   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   5964 
   5965   Local<v8::Object> obj = desc->GetFunction()->NewInstance();
   5966   env->Global()->Set(v8_str("undetectable"), obj);
   5967 
   5968   Local<String> source = v8_str("undetectable.x = 42;"
   5969                                 "undetectable.x");
   5970 
   5971   Local<Script> script = Script::Compile(source);
   5972 
   5973   CHECK_EQ(v8::Integer::New(42), script->Run());
   5974 
   5975   ExpectBoolean("Object.isExtensible(undetectable)", true);
   5976 
   5977   source = v8_str("Object.preventExtensions(undetectable);");
   5978   script = Script::Compile(source);
   5979   script->Run();
   5980   ExpectBoolean("Object.isExtensible(undetectable)", false);
   5981 
   5982   source = v8_str("undetectable.y = 2000;");
   5983   script = Script::Compile(source);
   5984   script->Run();
   5985   ExpectBoolean("undetectable.y == undefined", true);
   5986 }
   5987 
   5988 
   5989 
   5990 THREADED_TEST(UndetectableString) {
   5991   LocalContext env;
   5992   v8::HandleScope scope(env->GetIsolate());
   5993 
   5994   Local<String> obj = String::NewUndetectable("foo");
   5995   env->Global()->Set(v8_str("undetectable"), obj);
   5996 
   5997   ExpectString("undetectable", "foo");
   5998   ExpectString("typeof undetectable", "undefined");
   5999   ExpectString("typeof(undetectable)", "undefined");
   6000   ExpectBoolean("typeof undetectable == 'undefined'", true);
   6001   ExpectBoolean("typeof undetectable == 'string'", false);
   6002   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   6003   ExpectBoolean("!undetectable", true);
   6004 
   6005   ExpectObject("true&&undetectable", obj);
   6006   ExpectBoolean("false&&undetectable", false);
   6007   ExpectBoolean("true||undetectable", true);
   6008   ExpectObject("false||undetectable", obj);
   6009 
   6010   ExpectObject("undetectable&&true", obj);
   6011   ExpectObject("undetectable&&false", obj);
   6012   ExpectBoolean("undetectable||true", true);
   6013   ExpectBoolean("undetectable||false", false);
   6014 
   6015   ExpectBoolean("undetectable==null", true);
   6016   ExpectBoolean("null==undetectable", true);
   6017   ExpectBoolean("undetectable==undefined", true);
   6018   ExpectBoolean("undefined==undetectable", true);
   6019   ExpectBoolean("undetectable==undetectable", true);
   6020 
   6021 
   6022   ExpectBoolean("undetectable===null", false);
   6023   ExpectBoolean("null===undetectable", false);
   6024   ExpectBoolean("undetectable===undefined", false);
   6025   ExpectBoolean("undefined===undetectable", false);
   6026   ExpectBoolean("undetectable===undetectable", true);
   6027 }
   6028 
   6029 
   6030 TEST(UndetectableOptimized) {
   6031   i::FLAG_allow_natives_syntax = true;
   6032   LocalContext env;
   6033   v8::HandleScope scope(env->GetIsolate());
   6034 
   6035   Local<String> obj = String::NewUndetectable("foo");
   6036   env->Global()->Set(v8_str("undetectable"), obj);
   6037   env->Global()->Set(v8_str("detectable"), v8_str("bar"));
   6038 
   6039   ExpectString(
   6040       "function testBranch() {"
   6041       "  if (!%_IsUndetectableObject(undetectable)) throw 1;"
   6042       "  if (%_IsUndetectableObject(detectable)) throw 2;"
   6043       "}\n"
   6044       "function testBool() {"
   6045       "  var b1 = !%_IsUndetectableObject(undetectable);"
   6046       "  var b2 = %_IsUndetectableObject(detectable);"
   6047       "  if (b1) throw 3;"
   6048       "  if (b2) throw 4;"
   6049       "  return b1 == b2;"
   6050       "}\n"
   6051       "%OptimizeFunctionOnNextCall(testBranch);"
   6052       "%OptimizeFunctionOnNextCall(testBool);"
   6053       "for (var i = 0; i < 10; i++) {"
   6054       "  testBranch();"
   6055       "  testBool();"
   6056       "}\n"
   6057       "\"PASS\"",
   6058       "PASS");
   6059 }
   6060 
   6061 
   6062 template <typename T> static void USE(T) { }
   6063 
   6064 
   6065 // This test is not intended to be run, just type checked.
   6066 static inline void PersistentHandles(v8::Isolate* isolate) {
   6067   USE(PersistentHandles);
   6068   Local<String> str = v8_str("foo");
   6069   v8::Persistent<String> p_str(isolate, str);
   6070   p_str.Dispose();
   6071   Local<Script> scr = Script::Compile(v8_str(""));
   6072   v8::Persistent<Script> p_scr(isolate, scr);
   6073   p_scr.Dispose();
   6074   Local<ObjectTemplate> templ = ObjectTemplate::New();
   6075   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
   6076   p_templ.Dispose();
   6077 }
   6078 
   6079 
   6080 static void HandleLogDelegator(
   6081     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6082   ApiTestFuzzer::Fuzz();
   6083 }
   6084 
   6085 
   6086 THREADED_TEST(GlobalObjectTemplate) {
   6087   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   6088   v8::HandleScope handle_scope(isolate);
   6089   Local<ObjectTemplate> global_template = ObjectTemplate::New();
   6090   global_template->Set(v8_str("JSNI_Log"),
   6091                        v8::FunctionTemplate::New(HandleLogDelegator));
   6092   v8::Local<Context> context = Context::New(isolate, 0, global_template);
   6093   Context::Scope context_scope(context);
   6094   Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
   6095 }
   6096 
   6097 
   6098 static const char* kSimpleExtensionSource =
   6099   "function Foo() {"
   6100   "  return 4;"
   6101   "}";
   6102 
   6103 
   6104 THREADED_TEST(SimpleExtensions) {
   6105   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6106   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
   6107   const char* extension_names[] = { "simpletest" };
   6108   v8::ExtensionConfiguration extensions(1, extension_names);
   6109   v8::Handle<Context> context =
   6110       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6111   Context::Scope lock(context);
   6112   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
   6113   CHECK_EQ(result, v8::Integer::New(4));
   6114 }
   6115 
   6116 
   6117 THREADED_TEST(NullExtensions) {
   6118   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6119   v8::RegisterExtension(new Extension("nulltest", NULL));
   6120   const char* extension_names[] = { "nulltest" };
   6121   v8::ExtensionConfiguration extensions(1, extension_names);
   6122   v8::Handle<Context> context =
   6123       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6124   Context::Scope lock(context);
   6125   v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
   6126   CHECK_EQ(result, v8::Integer::New(4));
   6127 }
   6128 
   6129 
   6130 static const char* kEmbeddedExtensionSource =
   6131     "function Ret54321(){return 54321;}~~@@$"
   6132     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
   6133 static const int kEmbeddedExtensionSourceValidLen = 34;
   6134 
   6135 
   6136 THREADED_TEST(ExtensionMissingSourceLength) {
   6137   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6138   v8::RegisterExtension(new Extension("srclentest_fail",
   6139                                       kEmbeddedExtensionSource));
   6140   const char* extension_names[] = { "srclentest_fail" };
   6141   v8::ExtensionConfiguration extensions(1, extension_names);
   6142   v8::Handle<Context> context =
   6143       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6144   CHECK_EQ(0, *context);
   6145 }
   6146 
   6147 
   6148 THREADED_TEST(ExtensionWithSourceLength) {
   6149   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
   6150        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
   6151     v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6152     i::ScopedVector<char> extension_name(32);
   6153     i::OS::SNPrintF(extension_name, "ext #%d", source_len);
   6154     v8::RegisterExtension(new Extension(extension_name.start(),
   6155                                         kEmbeddedExtensionSource, 0, 0,
   6156                                         source_len));
   6157     const char* extension_names[1] = { extension_name.start() };
   6158     v8::ExtensionConfiguration extensions(1, extension_names);
   6159     v8::Handle<Context> context =
   6160       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6161     if (source_len == kEmbeddedExtensionSourceValidLen) {
   6162       Context::Scope lock(context);
   6163       v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
   6164       CHECK_EQ(v8::Integer::New(54321), result);
   6165     } else {
   6166       // Anything but exactly the right length should fail to compile.
   6167       CHECK_EQ(0, *context);
   6168     }
   6169   }
   6170 }
   6171 
   6172 
   6173 static const char* kEvalExtensionSource1 =
   6174   "function UseEval1() {"
   6175   "  var x = 42;"
   6176   "  return eval('x');"
   6177   "}";
   6178 
   6179 
   6180 static const char* kEvalExtensionSource2 =
   6181   "(function() {"
   6182   "  var x = 42;"
   6183   "  function e() {"
   6184   "    return eval('x');"
   6185   "  }"
   6186   "  this.UseEval2 = e;"
   6187   "})()";
   6188 
   6189 
   6190 THREADED_TEST(UseEvalFromExtension) {
   6191   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6192   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
   6193   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
   6194   const char* extension_names[] = { "evaltest1", "evaltest2" };
   6195   v8::ExtensionConfiguration extensions(2, extension_names);
   6196   v8::Handle<Context> context =
   6197       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6198   Context::Scope lock(context);
   6199   v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
   6200   CHECK_EQ(result, v8::Integer::New(42));
   6201   result = Script::Compile(v8_str("UseEval2()"))->Run();
   6202   CHECK_EQ(result, v8::Integer::New(42));
   6203 }
   6204 
   6205 
   6206 static const char* kWithExtensionSource1 =
   6207   "function UseWith1() {"
   6208   "  var x = 42;"
   6209   "  with({x:87}) { return x; }"
   6210   "}";
   6211 
   6212 
   6213 
   6214 static const char* kWithExtensionSource2 =
   6215   "(function() {"
   6216   "  var x = 42;"
   6217   "  function e() {"
   6218   "    with ({x:87}) { return x; }"
   6219   "  }"
   6220   "  this.UseWith2 = e;"
   6221   "})()";
   6222 
   6223 
   6224 THREADED_TEST(UseWithFromExtension) {
   6225   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6226   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
   6227   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
   6228   const char* extension_names[] = { "withtest1", "withtest2" };
   6229   v8::ExtensionConfiguration extensions(2, extension_names);
   6230   v8::Handle<Context> context =
   6231       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6232   Context::Scope lock(context);
   6233   v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
   6234   CHECK_EQ(result, v8::Integer::New(87));
   6235   result = Script::Compile(v8_str("UseWith2()"))->Run();
   6236   CHECK_EQ(result, v8::Integer::New(87));
   6237 }
   6238 
   6239 
   6240 THREADED_TEST(AutoExtensions) {
   6241   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6242   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
   6243   extension->set_auto_enable(true);
   6244   v8::RegisterExtension(extension);
   6245   v8::Handle<Context> context =
   6246       Context::New(v8::Isolate::GetCurrent());
   6247   Context::Scope lock(context);
   6248   v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
   6249   CHECK_EQ(result, v8::Integer::New(4));
   6250 }
   6251 
   6252 
   6253 static const char* kSyntaxErrorInExtensionSource =
   6254     "[";
   6255 
   6256 
   6257 // Test that a syntax error in an extension does not cause a fatal
   6258 // error but results in an empty context.
   6259 THREADED_TEST(SyntaxErrorExtensions) {
   6260   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6261   v8::RegisterExtension(new Extension("syntaxerror",
   6262                                       kSyntaxErrorInExtensionSource));
   6263   const char* extension_names[] = { "syntaxerror" };
   6264   v8::ExtensionConfiguration extensions(1, extension_names);
   6265   v8::Handle<Context> context =
   6266       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6267   CHECK(context.IsEmpty());
   6268 }
   6269 
   6270 
   6271 static const char* kExceptionInExtensionSource =
   6272     "throw 42";
   6273 
   6274 
   6275 // Test that an exception when installing an extension does not cause
   6276 // a fatal error but results in an empty context.
   6277 THREADED_TEST(ExceptionExtensions) {
   6278   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6279   v8::RegisterExtension(new Extension("exception",
   6280                                       kExceptionInExtensionSource));
   6281   const char* extension_names[] = { "exception" };
   6282   v8::ExtensionConfiguration extensions(1, extension_names);
   6283   v8::Handle<Context> context =
   6284       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6285   CHECK(context.IsEmpty());
   6286 }
   6287 
   6288 
   6289 static const char* kNativeCallInExtensionSource =
   6290     "function call_runtime_last_index_of(x) {"
   6291     "  return %StringLastIndexOf(x, 'bob', 10);"
   6292     "}";
   6293 
   6294 
   6295 static const char* kNativeCallTest =
   6296     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
   6297 
   6298 // Test that a native runtime calls are supported in extensions.
   6299 THREADED_TEST(NativeCallInExtensions) {
   6300   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6301   v8::RegisterExtension(new Extension("nativecall",
   6302                                       kNativeCallInExtensionSource));
   6303   const char* extension_names[] = { "nativecall" };
   6304   v8::ExtensionConfiguration extensions(1, extension_names);
   6305   v8::Handle<Context> context =
   6306       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6307   Context::Scope lock(context);
   6308   v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
   6309   CHECK_EQ(result, v8::Integer::New(3));
   6310 }
   6311 
   6312 
   6313 class NativeFunctionExtension : public Extension {
   6314  public:
   6315   NativeFunctionExtension(const char* name,
   6316                           const char* source,
   6317                           v8::FunctionCallback fun = &Echo)
   6318       : Extension(name, source),
   6319         function_(fun) { }
   6320 
   6321   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
   6322       v8::Handle<v8::String> name) {
   6323     return v8::FunctionTemplate::New(function_);
   6324   }
   6325 
   6326   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6327     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
   6328   }
   6329  private:
   6330   v8::FunctionCallback function_;
   6331 };
   6332 
   6333 
   6334 THREADED_TEST(NativeFunctionDeclaration) {
   6335   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6336   const char* name = "nativedecl";
   6337   v8::RegisterExtension(new NativeFunctionExtension(name,
   6338                                                     "native function foo();"));
   6339   const char* extension_names[] = { name };
   6340   v8::ExtensionConfiguration extensions(1, extension_names);
   6341   v8::Handle<Context> context =
   6342       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6343   Context::Scope lock(context);
   6344   v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
   6345   CHECK_EQ(result, v8::Integer::New(42));
   6346 }
   6347 
   6348 
   6349 THREADED_TEST(NativeFunctionDeclarationError) {
   6350   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6351   const char* name = "nativedeclerr";
   6352   // Syntax error in extension code.
   6353   v8::RegisterExtension(new NativeFunctionExtension(name,
   6354                                                     "native\nfunction foo();"));
   6355   const char* extension_names[] = { name };
   6356   v8::ExtensionConfiguration extensions(1, extension_names);
   6357   v8::Handle<Context> context =
   6358       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6359   CHECK(context.IsEmpty());
   6360 }
   6361 
   6362 
   6363 THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
   6364   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6365   const char* name = "nativedeclerresc";
   6366   // Syntax error in extension code - escape code in "native" means that
   6367   // it's not treated as a keyword.
   6368   v8::RegisterExtension(new NativeFunctionExtension(
   6369       name,
   6370       "nativ\\u0065 function foo();"));
   6371   const char* extension_names[] = { name };
   6372   v8::ExtensionConfiguration extensions(1, extension_names);
   6373   v8::Handle<Context> context =
   6374       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6375   CHECK(context.IsEmpty());
   6376 }
   6377 
   6378 
   6379 static void CheckDependencies(const char* name, const char* expected) {
   6380   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6381   v8::ExtensionConfiguration config(1, &name);
   6382   LocalContext context(&config);
   6383   CHECK_EQ(String::New(expected), context->Global()->Get(v8_str("loaded")));
   6384 }
   6385 
   6386 
   6387 /*
   6388  * Configuration:
   6389  *
   6390  *     /-- B <--\
   6391  * A <-          -- D <-- E
   6392  *     \-- C <--/
   6393  */
   6394 THREADED_TEST(ExtensionDependency) {
   6395   static const char* kEDeps[] = { "D" };
   6396   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
   6397   static const char* kDDeps[] = { "B", "C" };
   6398   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
   6399   static const char* kBCDeps[] = { "A" };
   6400   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
   6401   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
   6402   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
   6403   CheckDependencies("A", "undefinedA");
   6404   CheckDependencies("B", "undefinedAB");
   6405   CheckDependencies("C", "undefinedAC");
   6406   CheckDependencies("D", "undefinedABCD");
   6407   CheckDependencies("E", "undefinedABCDE");
   6408   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6409   static const char* exts[2] = { "C", "E" };
   6410   v8::ExtensionConfiguration config(2, exts);
   6411   LocalContext context(&config);
   6412   CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
   6413 }
   6414 
   6415 
   6416 static const char* kExtensionTestScript =
   6417   "native function A();"
   6418   "native function B();"
   6419   "native function C();"
   6420   "function Foo(i) {"
   6421   "  if (i == 0) return A();"
   6422   "  if (i == 1) return B();"
   6423   "  if (i == 2) return C();"
   6424   "}";
   6425 
   6426 
   6427 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6428   ApiTestFuzzer::Fuzz();
   6429   if (args.IsConstructCall()) {
   6430     args.This()->Set(v8_str("data"), args.Data());
   6431     args.GetReturnValue().SetNull();
   6432     return;
   6433   }
   6434   args.GetReturnValue().Set(args.Data());
   6435 }
   6436 
   6437 
   6438 class FunctionExtension : public Extension {
   6439  public:
   6440   FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
   6441   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
   6442       v8::Handle<String> name);
   6443 };
   6444 
   6445 
   6446 static int lookup_count = 0;
   6447 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunction(
   6448       v8::Handle<String> name) {
   6449   lookup_count++;
   6450   if (name->Equals(v8_str("A"))) {
   6451     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
   6452   } else if (name->Equals(v8_str("B"))) {
   6453     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
   6454   } else if (name->Equals(v8_str("C"))) {
   6455     return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
   6456   } else {
   6457     return v8::Handle<v8::FunctionTemplate>();
   6458   }
   6459 }
   6460 
   6461 
   6462 THREADED_TEST(FunctionLookup) {
   6463   v8::RegisterExtension(new FunctionExtension());
   6464   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6465   static const char* exts[1] = { "functiontest" };
   6466   v8::ExtensionConfiguration config(1, exts);
   6467   LocalContext context(&config);
   6468   CHECK_EQ(3, lookup_count);
   6469   CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
   6470   CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
   6471   CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
   6472 }
   6473 
   6474 
   6475 THREADED_TEST(NativeFunctionConstructCall) {
   6476   v8::RegisterExtension(new FunctionExtension());
   6477   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6478   static const char* exts[1] = { "functiontest" };
   6479   v8::ExtensionConfiguration config(1, exts);
   6480   LocalContext context(&config);
   6481   for (int i = 0; i < 10; i++) {
   6482     // Run a few times to ensure that allocation of objects doesn't
   6483     // change behavior of a constructor function.
   6484     CHECK_EQ(v8::Integer::New(8),
   6485              Script::Compile(v8_str("(new A()).data"))->Run());
   6486     CHECK_EQ(v8::Integer::New(7),
   6487              Script::Compile(v8_str("(new B()).data"))->Run());
   6488     CHECK_EQ(v8::Integer::New(6),
   6489              Script::Compile(v8_str("(new C()).data"))->Run());
   6490   }
   6491 }
   6492 
   6493 
   6494 static const char* last_location;
   6495 static const char* last_message;
   6496 void StoringErrorCallback(const char* location, const char* message) {
   6497   if (last_location == NULL) {
   6498     last_location = location;
   6499     last_message = message;
   6500   }
   6501 }
   6502 
   6503 
   6504 // ErrorReporting creates a circular extensions configuration and
   6505 // tests that the fatal error handler gets called.  This renders V8
   6506 // unusable and therefore this test cannot be run in parallel.
   6507 TEST(ErrorReporting) {
   6508   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   6509   static const char* aDeps[] = { "B" };
   6510   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
   6511   static const char* bDeps[] = { "A" };
   6512   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
   6513   last_location = NULL;
   6514   v8::ExtensionConfiguration config(1, bDeps);
   6515   v8::Handle<Context> context =
   6516       Context::New(v8::Isolate::GetCurrent(), &config);
   6517   CHECK(context.IsEmpty());
   6518   CHECK_NE(last_location, NULL);
   6519 }
   6520 
   6521 
   6522 static const char* js_code_causing_huge_string_flattening =
   6523     "var str = 'X';"
   6524     "for (var i = 0; i < 30; i++) {"
   6525     "  str = str + str;"
   6526     "}"
   6527     "str.match(/X/);";
   6528 
   6529 
   6530 void OOMCallback(const char* location, const char* message) {
   6531   exit(0);
   6532 }
   6533 
   6534 
   6535 TEST(RegexpOutOfMemory) {
   6536   // Execute a script that causes out of memory when flattening a string.
   6537   v8::HandleScope scope(v8::Isolate::GetCurrent());
   6538   v8::V8::SetFatalErrorHandler(OOMCallback);
   6539   LocalContext context;
   6540   Local<Script> script =
   6541       Script::Compile(String::New(js_code_causing_huge_string_flattening));
   6542   last_location = NULL;
   6543   script->Run();
   6544 
   6545   CHECK(false);  // Should not return.
   6546 }
   6547 
   6548 
   6549 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
   6550                                              v8::Handle<Value> data) {
   6551   CHECK(message->GetScriptResourceName()->IsUndefined());
   6552   CHECK_EQ(v8::Undefined(), message->GetScriptResourceName());
   6553   message->GetLineNumber();
   6554   message->GetSourceLine();
   6555 }
   6556 
   6557 
   6558 THREADED_TEST(ErrorWithMissingScriptInfo) {
   6559   LocalContext context;
   6560   v8::HandleScope scope(context->GetIsolate());
   6561   v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
   6562   Script::Compile(v8_str("throw Error()"))->Run();
   6563   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
   6564 }
   6565 
   6566 
   6567 int global_index = 0;
   6568 
   6569 class Snorkel {
   6570  public:
   6571   Snorkel() { index_ = global_index++; }
   6572   int index_;
   6573 };
   6574 
   6575 class Whammy {
   6576  public:
   6577   explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
   6578   ~Whammy() { script_.Dispose(isolate_); }
   6579   v8::Handle<Script> getScript() {
   6580     if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo"));
   6581     return Local<Script>::New(isolate_, script_);
   6582   }
   6583 
   6584  public:
   6585   static const int kObjectCount = 256;
   6586   int cursor_;
   6587   v8::Isolate* isolate_;
   6588   v8::Persistent<v8::Object> objects_[kObjectCount];
   6589   v8::Persistent<Script> script_;
   6590 };
   6591 
   6592 static void HandleWeakReference(v8::Isolate* isolate,
   6593                                 v8::Persistent<v8::Value>* obj,
   6594                                 Snorkel* snorkel) {
   6595   delete snorkel;
   6596   obj->ClearWeak(isolate);
   6597 }
   6598 
   6599 void WhammyPropertyGetter(Local<String> name,
   6600                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   6601   Whammy* whammy =
   6602     static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
   6603 
   6604   v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_];
   6605 
   6606   v8::Handle<v8::Object> obj = v8::Object::New();
   6607   if (!prev.IsEmpty()) {
   6608     v8::Local<v8::Object>::New(info.GetIsolate(), prev)
   6609         ->Set(v8_str("next"), obj);
   6610     prev.MakeWeak<Value, Snorkel>(new Snorkel(), &HandleWeakReference);
   6611     whammy->objects_[whammy->cursor_].Clear();
   6612   }
   6613   whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj);
   6614   whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
   6615   info.GetReturnValue().Set(whammy->getScript()->Run());
   6616 }
   6617 
   6618 
   6619 THREADED_TEST(WeakReference) {
   6620   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   6621   v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
   6622   Whammy* whammy = new Whammy(v8::Isolate::GetCurrent());
   6623   templ->SetNamedPropertyHandler(WhammyPropertyGetter,
   6624                                  0, 0, 0, 0,
   6625                                  v8::External::New(whammy));
   6626   const char* extension_list[] = { "v8/gc" };
   6627   v8::ExtensionConfiguration extensions(1, extension_list);
   6628   v8::Handle<Context> context =
   6629       Context::New(v8::Isolate::GetCurrent(), &extensions);
   6630   Context::Scope context_scope(context);
   6631 
   6632   v8::Handle<v8::Object> interceptor = templ->NewInstance();
   6633   context->Global()->Set(v8_str("whammy"), interceptor);
   6634   const char* code =
   6635       "var last;"
   6636       "for (var i = 0; i < 10000; i++) {"
   6637       "  var obj = whammy.length;"
   6638       "  if (last) last.next = obj;"
   6639       "  last = obj;"
   6640       "}"
   6641       "gc();"
   6642       "4";
   6643   v8::Handle<Value> result = CompileRun(code);
   6644   CHECK_EQ(4.0, result->NumberValue());
   6645   delete whammy;
   6646 }
   6647 
   6648 
   6649 static void DisposeAndSetFlag(v8::Isolate* isolate,
   6650                               v8::Persistent<v8::Object>* obj,
   6651                               bool* data) {
   6652   obj->Dispose(isolate);
   6653   *(data) = true;
   6654 }
   6655 
   6656 
   6657 THREADED_TEST(IndependentWeakHandle) {
   6658   v8::Isolate* iso = v8::Isolate::GetCurrent();
   6659   v8::HandleScope scope(iso);
   6660   v8::Handle<Context> context = Context::New(iso);
   6661   Context::Scope context_scope(context);
   6662 
   6663   v8::Persistent<v8::Object> object_a, object_b;
   6664 
   6665   {
   6666     v8::HandleScope handle_scope(iso);
   6667     object_a.Reset(iso, v8::Object::New());
   6668     object_b.Reset(iso, v8::Object::New());
   6669   }
   6670 
   6671   bool object_a_disposed = false;
   6672   bool object_b_disposed = false;
   6673   object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag);
   6674   object_b.MakeWeak(&object_b_disposed, &DisposeAndSetFlag);
   6675   CHECK(!object_b.IsIndependent(iso));
   6676   object_a.MarkIndependent(iso);
   6677   object_b.MarkIndependent(iso);
   6678   CHECK(object_b.IsIndependent(iso));
   6679   HEAP->PerformScavenge();
   6680   CHECK(object_a_disposed);
   6681   CHECK(object_b_disposed);
   6682 }
   6683 
   6684 
   6685 static void InvokeScavenge() {
   6686   HEAP->PerformScavenge();
   6687 }
   6688 
   6689 
   6690 static void InvokeMarkSweep() {
   6691   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   6692 }
   6693 
   6694 
   6695 static void ForceScavenge(v8::Isolate* isolate,
   6696                           v8::Persistent<v8::Object>* obj,
   6697                           bool* data) {
   6698   obj->Dispose(isolate);
   6699   *(data) = true;
   6700   InvokeScavenge();
   6701 }
   6702 
   6703 
   6704 static void ForceMarkSweep(v8::Isolate* isolate,
   6705                            v8::Persistent<v8::Object>* obj,
   6706                            bool* data) {
   6707   obj->Dispose(isolate);
   6708   *(data) = true;
   6709   InvokeMarkSweep();
   6710 }
   6711 
   6712 
   6713 THREADED_TEST(GCFromWeakCallbacks) {
   6714   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   6715   v8::HandleScope scope(isolate);
   6716   v8::Handle<Context> context = Context::New(isolate);
   6717   Context::Scope context_scope(context);
   6718 
   6719   static const int kNumberOfGCTypes = 2;
   6720   typedef v8::WeakReferenceCallbacks<v8::Object, bool>::Revivable Callback;
   6721   Callback gc_forcing_callback[kNumberOfGCTypes] =
   6722       {&ForceScavenge, &ForceMarkSweep};
   6723 
   6724   typedef void (*GCInvoker)();
   6725   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
   6726 
   6727   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
   6728     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
   6729       v8::Persistent<v8::Object> object;
   6730       {
   6731         v8::HandleScope handle_scope(isolate);
   6732         object.Reset(isolate, v8::Object::New());
   6733       }
   6734       bool disposed = false;
   6735       object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]);
   6736       object.MarkIndependent(isolate);
   6737       invoke_gc[outer_gc]();
   6738       CHECK(disposed);
   6739     }
   6740   }
   6741 }
   6742 
   6743 
   6744 static void RevivingCallback(v8::Isolate* isolate,
   6745                              v8::Persistent<v8::Object>* obj,
   6746                              bool* data) {
   6747   obj->ClearWeak(isolate);
   6748   *(data) = true;
   6749 }
   6750 
   6751 
   6752 THREADED_TEST(IndependentHandleRevival) {
   6753   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   6754   v8::HandleScope scope(isolate);
   6755   v8::Handle<Context> context = Context::New(isolate);
   6756   Context::Scope context_scope(context);
   6757 
   6758   v8::Persistent<v8::Object> object;
   6759   {
   6760     v8::HandleScope handle_scope(isolate);
   6761     v8::Local<v8::Object> o = v8::Object::New();
   6762     object.Reset(isolate, o);
   6763     o->Set(v8_str("x"), v8::Integer::New(1));
   6764     v8::Local<String> y_str = v8_str("y");
   6765     o->Set(y_str, y_str);
   6766   }
   6767   bool revived = false;
   6768   object.MakeWeak(&revived, &RevivingCallback);
   6769   object.MarkIndependent(isolate);
   6770   HEAP->PerformScavenge();
   6771   CHECK(revived);
   6772   HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   6773   {
   6774     v8::HandleScope handle_scope(isolate);
   6775     v8::Local<v8::Object> o = v8::Local<v8::Object>::New(isolate, object);
   6776     v8::Local<String> y_str = v8_str("y");
   6777     CHECK_EQ(v8::Integer::New(1), o->Get(v8_str("x")));
   6778     CHECK(o->Get(y_str)->Equals(y_str));
   6779   }
   6780 }
   6781 
   6782 
   6783 v8::Handle<Function> args_fun;
   6784 
   6785 
   6786 static void ArgumentsTestCallback(
   6787     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6788   ApiTestFuzzer::Fuzz();
   6789   CHECK_EQ(args_fun, args.Callee());
   6790   CHECK_EQ(3, args.Length());
   6791   CHECK_EQ(v8::Integer::New(1), args[0]);
   6792   CHECK_EQ(v8::Integer::New(2), args[1]);
   6793   CHECK_EQ(v8::Integer::New(3), args[2]);
   6794   CHECK_EQ(v8::Undefined(), args[3]);
   6795   v8::HandleScope scope(args.GetIsolate());
   6796   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   6797 }
   6798 
   6799 
   6800 THREADED_TEST(Arguments) {
   6801   v8::HandleScope scope(v8::Isolate::GetCurrent());
   6802   v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
   6803   global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
   6804   LocalContext context(NULL, global);
   6805   args_fun = context->Global()->Get(v8_str("f")).As<Function>();
   6806   v8_compile("f(1, 2, 3)")->Run();
   6807 }
   6808 
   6809 
   6810 static void NoBlockGetterX(Local<String> name,
   6811                            const v8::PropertyCallbackInfo<v8::Value>&) {
   6812 }
   6813 
   6814 
   6815 static void NoBlockGetterI(uint32_t index,
   6816                            const v8::PropertyCallbackInfo<v8::Value>&) {
   6817 }
   6818 
   6819 
   6820 static void PDeleter(Local<String> name,
   6821                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   6822   if (!name->Equals(v8_str("foo"))) {
   6823     return;  // not intercepted
   6824   }
   6825 
   6826   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
   6827 }
   6828 
   6829 
   6830 static void IDeleter(uint32_t index,
   6831                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   6832   if (index != 2) {
   6833     return;  // not intercepted
   6834   }
   6835 
   6836   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
   6837 }
   6838 
   6839 
   6840 THREADED_TEST(Deleter) {
   6841   v8::HandleScope scope(v8::Isolate::GetCurrent());
   6842   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   6843   obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
   6844   obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
   6845   LocalContext context;
   6846   context->Global()->Set(v8_str("k"), obj->NewInstance());
   6847   CompileRun(
   6848     "k.foo = 'foo';"
   6849     "k.bar = 'bar';"
   6850     "k[2] = 2;"
   6851     "k[4] = 4;");
   6852   CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
   6853   CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
   6854 
   6855   CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
   6856   CHECK(v8_compile("k.bar")->Run()->IsUndefined());
   6857 
   6858   CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
   6859   CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
   6860 
   6861   CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
   6862   CHECK(v8_compile("k[4]")->Run()->IsUndefined());
   6863 }
   6864 
   6865 
   6866 static void GetK(Local<String> name,
   6867                  const v8::PropertyCallbackInfo<v8::Value>& info) {
   6868   ApiTestFuzzer::Fuzz();
   6869   if (name->Equals(v8_str("foo")) ||
   6870       name->Equals(v8_str("bar")) ||
   6871       name->Equals(v8_str("baz"))) {
   6872     info.GetReturnValue().SetUndefined();
   6873   }
   6874 }
   6875 
   6876 
   6877 static void IndexedGetK(uint32_t index,
   6878                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   6879   ApiTestFuzzer::Fuzz();
   6880   if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
   6881 }
   6882 
   6883 
   6884 static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
   6885   ApiTestFuzzer::Fuzz();
   6886   v8::Handle<v8::Array> result = v8::Array::New(3);
   6887   result->Set(v8::Integer::New(0), v8_str("foo"));
   6888   result->Set(v8::Integer::New(1), v8_str("bar"));
   6889   result->Set(v8::Integer::New(2), v8_str("baz"));
   6890   info.GetReturnValue().Set(result);
   6891 }
   6892 
   6893 
   6894 static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
   6895   ApiTestFuzzer::Fuzz();
   6896   v8::Handle<v8::Array> result = v8::Array::New(2);
   6897   result->Set(v8::Integer::New(0), v8_str("0"));
   6898   result->Set(v8::Integer::New(1), v8_str("1"));
   6899   info.GetReturnValue().Set(result);
   6900 }
   6901 
   6902 
   6903 THREADED_TEST(Enumerators) {
   6904   v8::HandleScope scope(v8::Isolate::GetCurrent());
   6905   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   6906   obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
   6907   obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
   6908   LocalContext context;
   6909   context->Global()->Set(v8_str("k"), obj->NewInstance());
   6910   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   6911     "k[10] = 0;"
   6912     "k.a = 0;"
   6913     "k[5] = 0;"
   6914     "k.b = 0;"
   6915     "k[4294967295] = 0;"
   6916     "k.c = 0;"
   6917     "k[4294967296] = 0;"
   6918     "k.d = 0;"
   6919     "k[140000] = 0;"
   6920     "k.e = 0;"
   6921     "k[30000000000] = 0;"
   6922     "k.f = 0;"
   6923     "var result = [];"
   6924     "for (var prop in k) {"
   6925     "  result.push(prop);"
   6926     "}"
   6927     "result"));
   6928   // Check that we get all the property names returned including the
   6929   // ones from the enumerators in the right order: indexed properties
   6930   // in numerical order, indexed interceptor properties, named
   6931   // properties in insertion order, named interceptor properties.
   6932   // This order is not mandated by the spec, so this test is just
   6933   // documenting our behavior.
   6934   CHECK_EQ(17, result->Length());
   6935   // Indexed properties in numerical order.
   6936   CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
   6937   CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
   6938   CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
   6939   CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
   6940   // Indexed interceptor properties in the order they are returned
   6941   // from the enumerator interceptor.
   6942   CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
   6943   CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
   6944   // Named properties in insertion order.
   6945   CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
   6946   CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
   6947   CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
   6948   CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
   6949   CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
   6950   CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
   6951   CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
   6952   CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
   6953   // Named interceptor properties.
   6954   CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
   6955   CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
   6956   CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
   6957 }
   6958 
   6959 
   6960 int p_getter_count;
   6961 int p_getter_count2;
   6962 
   6963 
   6964 static void PGetter(Local<String> name,
   6965                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   6966   ApiTestFuzzer::Fuzz();
   6967   p_getter_count++;
   6968   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
   6969   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   6970   if (name->Equals(v8_str("p1"))) {
   6971     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   6972   } else if (name->Equals(v8_str("p2"))) {
   6973     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   6974   } else if (name->Equals(v8_str("p3"))) {
   6975     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   6976   } else if (name->Equals(v8_str("p4"))) {
   6977     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   6978   }
   6979 }
   6980 
   6981 
   6982 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
   6983   ApiTestFuzzer::Fuzz();
   6984   LocalContext context;
   6985   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   6986   CompileRun(
   6987     "o1.__proto__ = { };"
   6988     "var o2 = { __proto__: o1 };"
   6989     "var o3 = { __proto__: o2 };"
   6990     "var o4 = { __proto__: o3 };"
   6991     "for (var i = 0; i < 10; i++) o4.p4;"
   6992     "for (var i = 0; i < 10; i++) o3.p3;"
   6993     "for (var i = 0; i < 10; i++) o2.p2;"
   6994     "for (var i = 0; i < 10; i++) o1.p1;");
   6995 }
   6996 
   6997 
   6998 static void PGetter2(Local<String> name,
   6999                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   7000   ApiTestFuzzer::Fuzz();
   7001   p_getter_count2++;
   7002   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
   7003   CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
   7004   if (name->Equals(v8_str("p1"))) {
   7005     CHECK_EQ(info.This(), global->Get(v8_str("o1")));
   7006   } else if (name->Equals(v8_str("p2"))) {
   7007     CHECK_EQ(info.This(), global->Get(v8_str("o2")));
   7008   } else if (name->Equals(v8_str("p3"))) {
   7009     CHECK_EQ(info.This(), global->Get(v8_str("o3")));
   7010   } else if (name->Equals(v8_str("p4"))) {
   7011     CHECK_EQ(info.This(), global->Get(v8_str("o4")));
   7012   }
   7013 }
   7014 
   7015 
   7016 THREADED_TEST(GetterHolders) {
   7017   v8::HandleScope scope(v8::Isolate::GetCurrent());
   7018   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   7019   obj->SetAccessor(v8_str("p1"), PGetter);
   7020   obj->SetAccessor(v8_str("p2"), PGetter);
   7021   obj->SetAccessor(v8_str("p3"), PGetter);
   7022   obj->SetAccessor(v8_str("p4"), PGetter);
   7023   p_getter_count = 0;
   7024   RunHolderTest(obj);
   7025   CHECK_EQ(40, p_getter_count);
   7026 }
   7027 
   7028 
   7029 THREADED_TEST(PreInterceptorHolders) {
   7030   v8::HandleScope scope(v8::Isolate::GetCurrent());
   7031   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   7032   obj->SetNamedPropertyHandler(PGetter2);
   7033   p_getter_count2 = 0;
   7034   RunHolderTest(obj);
   7035   CHECK_EQ(40, p_getter_count2);
   7036 }
   7037 
   7038 
   7039 THREADED_TEST(ObjectInstantiation) {
   7040   v8::HandleScope scope(v8::Isolate::GetCurrent());
   7041   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   7042   templ->SetAccessor(v8_str("t"), PGetter2);
   7043   LocalContext context;
   7044   context->Global()->Set(v8_str("o"), templ->NewInstance());
   7045   for (int i = 0; i < 100; i++) {
   7046     v8::HandleScope inner_scope(v8::Isolate::GetCurrent());
   7047     v8::Handle<v8::Object> obj = templ->NewInstance();
   7048     CHECK_NE(obj, context->Global()->Get(v8_str("o")));
   7049     context->Global()->Set(v8_str("o2"), obj);
   7050     v8::Handle<Value> value =
   7051         Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
   7052     CHECK_EQ(v8::True(), value);
   7053     context->Global()->Set(v8_str("o"), obj);
   7054   }
   7055 }
   7056 
   7057 
   7058 static int StrCmp16(uint16_t* a, uint16_t* b) {
   7059   while (true) {
   7060     if (*a == 0 && *b == 0) return 0;
   7061     if (*a != *b) return 0 + *a - *b;
   7062     a++;
   7063     b++;
   7064   }
   7065 }
   7066 
   7067 
   7068 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
   7069   while (true) {
   7070     if (n-- == 0) return 0;
   7071     if (*a == 0 && *b == 0) return 0;
   7072     if (*a != *b) return 0 + *a - *b;
   7073     a++;
   7074     b++;
   7075   }
   7076 }
   7077 
   7078 
   7079 int GetUtf8Length(Handle<String> str) {
   7080   int len = str->Utf8Length();
   7081   if (len < 0) {
   7082     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
   7083     i::FlattenString(istr);
   7084     len = str->Utf8Length();
   7085   }
   7086   return len;
   7087 }
   7088 
   7089 
   7090 THREADED_TEST(StringWrite) {
   7091   LocalContext context;
   7092   v8::HandleScope scope(context->GetIsolate());
   7093   v8::Handle<String> str = v8_str("abcde");
   7094   // abc<Icelandic eth><Unicode snowman>.
   7095   v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
   7096   v8::Handle<String> str3 = v8::String::New("abc\0def", 7);
   7097   const int kStride = 4;  // Must match stride in for loops in JS below.
   7098   CompileRun(
   7099       "var left = '';"
   7100       "for (var i = 0; i < 0xd800; i += 4) {"
   7101       "  left = left + String.fromCharCode(i);"
   7102       "}");
   7103   CompileRun(
   7104       "var right = '';"
   7105       "for (var i = 0; i < 0xd800; i += 4) {"
   7106       "  right = String.fromCharCode(i) + right;"
   7107       "}");
   7108   v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
   7109   Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
   7110   Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
   7111 
   7112   CHECK_EQ(5, str2->Length());
   7113   CHECK_EQ(0xd800 / kStride, left_tree->Length());
   7114   CHECK_EQ(0xd800 / kStride, right_tree->Length());
   7115 
   7116   char buf[100];
   7117   char utf8buf[0xd800 * 3];
   7118   uint16_t wbuf[100];
   7119   int len;
   7120   int charlen;
   7121 
   7122   memset(utf8buf, 0x1, 1000);
   7123   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   7124   CHECK_EQ(9, len);
   7125   CHECK_EQ(5, charlen);
   7126   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   7127 
   7128   memset(utf8buf, 0x1, 1000);
   7129   len = str2->WriteUtf8(utf8buf, 8, &charlen);
   7130   CHECK_EQ(8, len);
   7131   CHECK_EQ(5, charlen);
   7132   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
   7133 
   7134   memset(utf8buf, 0x1, 1000);
   7135   len = str2->WriteUtf8(utf8buf, 7, &charlen);
   7136   CHECK_EQ(5, len);
   7137   CHECK_EQ(4, charlen);
   7138   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   7139 
   7140   memset(utf8buf, 0x1, 1000);
   7141   len = str2->WriteUtf8(utf8buf, 6, &charlen);
   7142   CHECK_EQ(5, len);
   7143   CHECK_EQ(4, charlen);
   7144   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   7145 
   7146   memset(utf8buf, 0x1, 1000);
   7147   len = str2->WriteUtf8(utf8buf, 5, &charlen);
   7148   CHECK_EQ(5, len);
   7149   CHECK_EQ(4, charlen);
   7150   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   7151 
   7152   memset(utf8buf, 0x1, 1000);
   7153   len = str2->WriteUtf8(utf8buf, 4, &charlen);
   7154   CHECK_EQ(3, len);
   7155   CHECK_EQ(3, charlen);
   7156   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   7157 
   7158   memset(utf8buf, 0x1, 1000);
   7159   len = str2->WriteUtf8(utf8buf, 3, &charlen);
   7160   CHECK_EQ(3, len);
   7161   CHECK_EQ(3, charlen);
   7162   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   7163 
   7164   memset(utf8buf, 0x1, 1000);
   7165   len = str2->WriteUtf8(utf8buf, 2, &charlen);
   7166   CHECK_EQ(2, len);
   7167   CHECK_EQ(2, charlen);
   7168   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
   7169 
   7170   memset(utf8buf, 0x1, sizeof(utf8buf));
   7171   len = GetUtf8Length(left_tree);
   7172   int utf8_expected =
   7173       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
   7174   CHECK_EQ(utf8_expected, len);
   7175   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   7176   CHECK_EQ(utf8_expected, len);
   7177   CHECK_EQ(0xd800 / kStride, charlen);
   7178   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
   7179   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
   7180   CHECK_EQ(0xc0 - kStride,
   7181            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
   7182   CHECK_EQ(1, utf8buf[utf8_expected]);
   7183 
   7184   memset(utf8buf, 0x1, sizeof(utf8buf));
   7185   len = GetUtf8Length(right_tree);
   7186   CHECK_EQ(utf8_expected, len);
   7187   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   7188   CHECK_EQ(utf8_expected, len);
   7189   CHECK_EQ(0xd800 / kStride, charlen);
   7190   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
   7191   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
   7192   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
   7193   CHECK_EQ(1, utf8buf[utf8_expected]);
   7194 
   7195   memset(buf, 0x1, sizeof(buf));
   7196   memset(wbuf, 0x1, sizeof(wbuf));
   7197   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   7198   CHECK_EQ(5, len);
   7199   len = str->Write(wbuf);
   7200   CHECK_EQ(5, len);
   7201   CHECK_EQ(0, strcmp("abcde", buf));
   7202   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   7203   CHECK_EQ(0, StrCmp16(answer1, wbuf));
   7204 
   7205   memset(buf, 0x1, sizeof(buf));
   7206   memset(wbuf, 0x1, sizeof(wbuf));
   7207   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
   7208   CHECK_EQ(4, len);
   7209   len = str->Write(wbuf, 0, 4);
   7210   CHECK_EQ(4, len);
   7211   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
   7212   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
   7213   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
   7214 
   7215   memset(buf, 0x1, sizeof(buf));
   7216   memset(wbuf, 0x1, sizeof(wbuf));
   7217   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
   7218   CHECK_EQ(5, len);
   7219   len = str->Write(wbuf, 0, 5);
   7220   CHECK_EQ(5, len);
   7221   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
   7222   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
   7223   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
   7224 
   7225   memset(buf, 0x1, sizeof(buf));
   7226   memset(wbuf, 0x1, sizeof(wbuf));
   7227   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
   7228   CHECK_EQ(5, len);
   7229   len = str->Write(wbuf, 0, 6);
   7230   CHECK_EQ(5, len);
   7231   CHECK_EQ(0, strcmp("abcde", buf));
   7232   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   7233   CHECK_EQ(0, StrCmp16(answer4, wbuf));
   7234 
   7235   memset(buf, 0x1, sizeof(buf));
   7236   memset(wbuf, 0x1, sizeof(wbuf));
   7237   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
   7238   CHECK_EQ(1, len);
   7239   len = str->Write(wbuf, 4, -1);
   7240   CHECK_EQ(1, len);
   7241   CHECK_EQ(0, strcmp("e", buf));
   7242   uint16_t answer5[] = {'e', '\0'};
   7243   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   7244 
   7245   memset(buf, 0x1, sizeof(buf));
   7246   memset(wbuf, 0x1, sizeof(wbuf));
   7247   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
   7248   CHECK_EQ(1, len);
   7249   len = str->Write(wbuf, 4, 6);
   7250   CHECK_EQ(1, len);
   7251   CHECK_EQ(0, strcmp("e", buf));
   7252   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   7253 
   7254   memset(buf, 0x1, sizeof(buf));
   7255   memset(wbuf, 0x1, sizeof(wbuf));
   7256   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
   7257   CHECK_EQ(1, len);
   7258   len = str->Write(wbuf, 4, 1);
   7259   CHECK_EQ(1, len);
   7260   CHECK_EQ(0, strncmp("e\1", buf, 2));
   7261   uint16_t answer6[] = {'e', 0x101};
   7262   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
   7263 
   7264   memset(buf, 0x1, sizeof(buf));
   7265   memset(wbuf, 0x1, sizeof(wbuf));
   7266   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
   7267   CHECK_EQ(1, len);
   7268   len = str->Write(wbuf, 3, 1);
   7269   CHECK_EQ(1, len);
   7270   CHECK_EQ(0, strncmp("d\1", buf, 2));
   7271   uint16_t answer7[] = {'d', 0x101};
   7272   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
   7273 
   7274   memset(wbuf, 0x1, sizeof(wbuf));
   7275   wbuf[5] = 'X';
   7276   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
   7277   CHECK_EQ(5, len);
   7278   CHECK_EQ('X', wbuf[5]);
   7279   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
   7280   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   7281   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
   7282   CHECK_NE(0, StrCmp16(answer8b, wbuf));
   7283   wbuf[5] = '\0';
   7284   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
   7285 
   7286   memset(buf, 0x1, sizeof(buf));
   7287   buf[5] = 'X';
   7288   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
   7289                           0,
   7290                           6,
   7291                           String::NO_NULL_TERMINATION);
   7292   CHECK_EQ(5, len);
   7293   CHECK_EQ('X', buf[5]);
   7294   CHECK_EQ(0, strncmp("abcde", buf, 5));
   7295   CHECK_NE(0, strcmp("abcde", buf));
   7296   buf[5] = '\0';
   7297   CHECK_EQ(0, strcmp("abcde", buf));
   7298 
   7299   memset(utf8buf, 0x1, sizeof(utf8buf));
   7300   utf8buf[8] = 'X';
   7301   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   7302                         String::NO_NULL_TERMINATION);
   7303   CHECK_EQ(8, len);
   7304   CHECK_EQ('X', utf8buf[8]);
   7305   CHECK_EQ(5, charlen);
   7306   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
   7307   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   7308   utf8buf[8] = '\0';
   7309   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   7310 
   7311   memset(utf8buf, 0x1, sizeof(utf8buf));
   7312   utf8buf[5] = 'X';
   7313   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   7314                         String::NO_NULL_TERMINATION);
   7315   CHECK_EQ(5, len);
   7316   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
   7317   CHECK_EQ(5, charlen);
   7318   utf8buf[5] = '\0';
   7319   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
   7320 
   7321   memset(buf, 0x1, sizeof(buf));
   7322   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   7323   CHECK_EQ(7, len);
   7324   CHECK_EQ(0, strcmp("abc", buf));
   7325   CHECK_EQ(0, buf[3]);
   7326   CHECK_EQ(0, strcmp("def", buf + 4));
   7327 
   7328   CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
   7329   CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
   7330   CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
   7331 }
   7332 
   7333 
   7334 static void Utf16Helper(
   7335     LocalContext& context,
   7336     const char* name,
   7337     const char* lengths_name,
   7338     int len) {
   7339   Local<v8::Array> a =
   7340       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
   7341   Local<v8::Array> alens =
   7342       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
   7343   for (int i = 0; i < len; i++) {
   7344     Local<v8::String> string =
   7345       Local<v8::String>::Cast(a->Get(i));
   7346     Local<v8::Number> expected_len =
   7347       Local<v8::Number>::Cast(alens->Get(i));
   7348     int length = GetUtf8Length(string);
   7349     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
   7350   }
   7351 }
   7352 
   7353 
   7354 static uint16_t StringGet(Handle<String> str, int index) {
   7355   i::Handle<i::String> istring =
   7356       v8::Utils::OpenHandle(String::Cast(*str));
   7357   return istring->Get(index);
   7358 }
   7359 
   7360 
   7361 static void WriteUtf8Helper(
   7362     LocalContext& context,
   7363     const char* name,
   7364     const char* lengths_name,
   7365     int len) {
   7366   Local<v8::Array> b =
   7367       Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
   7368   Local<v8::Array> alens =
   7369       Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
   7370   char buffer[1000];
   7371   char buffer2[1000];
   7372   for (int i = 0; i < len; i++) {
   7373     Local<v8::String> string =
   7374       Local<v8::String>::Cast(b->Get(i));
   7375     Local<v8::Number> expected_len =
   7376       Local<v8::Number>::Cast(alens->Get(i));
   7377     int utf8_length = static_cast<int>(expected_len->Value());
   7378     for (int j = utf8_length + 1; j >= 0; j--) {
   7379       memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
   7380       memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
   7381       int nchars;
   7382       int utf8_written =
   7383           string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
   7384       int utf8_written2 =
   7385           string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
   7386       CHECK_GE(utf8_length + 1, utf8_written);
   7387       CHECK_GE(utf8_length, utf8_written2);
   7388       for (int k = 0; k < utf8_written2; k++) {
   7389         CHECK_EQ(buffer[k], buffer2[k]);
   7390       }
   7391       CHECK(nchars * 3 >= utf8_written - 1);
   7392       CHECK(nchars <= utf8_written);
   7393       if (j == utf8_length + 1) {
   7394         CHECK_EQ(utf8_written2, utf8_length);
   7395         CHECK_EQ(utf8_written2 + 1, utf8_written);
   7396       }
   7397       CHECK_EQ(buffer[utf8_written], 42);
   7398       if (j > utf8_length) {
   7399         if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
   7400         if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
   7401         Handle<String> roundtrip = v8_str(buffer);
   7402         CHECK(roundtrip->Equals(string));
   7403       } else {
   7404         if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
   7405       }
   7406       if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
   7407       if (nchars >= 2) {
   7408         uint16_t trail = StringGet(string, nchars - 1);
   7409         uint16_t lead = StringGet(string, nchars - 2);
   7410         if (((lead & 0xfc00) == 0xd800) &&
   7411             ((trail & 0xfc00) == 0xdc00)) {
   7412           unsigned char u1 = buffer2[utf8_written2 - 4];
   7413           unsigned char u2 = buffer2[utf8_written2 - 3];
   7414           unsigned char u3 = buffer2[utf8_written2 - 2];
   7415           unsigned char u4 = buffer2[utf8_written2 - 1];
   7416           CHECK_EQ((u1 & 0xf8), 0xf0);
   7417           CHECK_EQ((u2 & 0xc0), 0x80);
   7418           CHECK_EQ((u3 & 0xc0), 0x80);
   7419           CHECK_EQ((u4 & 0xc0), 0x80);
   7420           uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
   7421           CHECK_EQ((u4 & 0x3f), (c & 0x3f));
   7422           CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
   7423           CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
   7424           CHECK_EQ((u1 & 0x3), c >> 18);
   7425         }
   7426       }
   7427     }
   7428   }
   7429 }
   7430 
   7431 
   7432 THREADED_TEST(Utf16) {
   7433   LocalContext context;
   7434   v8::HandleScope scope(context->GetIsolate());
   7435   CompileRun(
   7436       "var pad = '01234567890123456789';"
   7437       "var p = [];"
   7438       "var plens = [20, 3, 3];"
   7439       "p.push('01234567890123456789');"
   7440       "var lead = 0xd800;"
   7441       "var trail = 0xdc00;"
   7442       "p.push(String.fromCharCode(0xd800));"
   7443       "p.push(String.fromCharCode(0xdc00));"
   7444       "var a = [];"
   7445       "var b = [];"
   7446       "var c = [];"
   7447       "var alens = [];"
   7448       "for (var i = 0; i < 3; i++) {"
   7449       "  p[1] = String.fromCharCode(lead++);"
   7450       "  for (var j = 0; j < 3; j++) {"
   7451       "    p[2] = String.fromCharCode(trail++);"
   7452       "    a.push(p[i] + p[j]);"
   7453       "    b.push(p[i] + p[j]);"
   7454       "    c.push(p[i] + p[j]);"
   7455       "    alens.push(plens[i] + plens[j]);"
   7456       "  }"
   7457       "}"
   7458       "alens[5] -= 2;"  // Here the surrogate pairs match up.
   7459       "var a2 = [];"
   7460       "var b2 = [];"
   7461       "var c2 = [];"
   7462       "var a2lens = [];"
   7463       "for (var m = 0; m < 9; m++) {"
   7464       "  for (var n = 0; n < 9; n++) {"
   7465       "    a2.push(a[m] + a[n]);"
   7466       "    b2.push(b[m] + b[n]);"
   7467       "    var newc = 'x' + c[m] + c[n] + 'y';"
   7468       "    c2.push(newc.substring(1, newc.length - 1));"
   7469       "    var utf = alens[m] + alens[n];"  // And here.
   7470            // The 'n's that start with 0xdc.. are 6-8
   7471            // The 'm's that end with 0xd8.. are 1, 4 and 7
   7472       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
   7473       "    a2lens.push(utf);"
   7474       "  }"
   7475       "}");
   7476   Utf16Helper(context, "a", "alens", 9);
   7477   Utf16Helper(context, "a2", "a2lens", 81);
   7478   WriteUtf8Helper(context, "b", "alens", 9);
   7479   WriteUtf8Helper(context, "b2", "a2lens", 81);
   7480   WriteUtf8Helper(context, "c2", "a2lens", 81);
   7481 }
   7482 
   7483 
   7484 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
   7485   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
   7486   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
   7487   return *is1 == *is2;
   7488 }
   7489 
   7490 
   7491 static void SameSymbolHelper(const char* a, const char* b) {
   7492   Handle<String> symbol1 = v8::String::NewSymbol(a);
   7493   Handle<String> symbol2 = v8::String::NewSymbol(b);
   7494   CHECK(SameSymbol(symbol1, symbol2));
   7495 }
   7496 
   7497 
   7498 THREADED_TEST(Utf16Symbol) {
   7499   LocalContext context;
   7500   v8::HandleScope scope(context->GetIsolate());
   7501 
   7502   Handle<String> symbol1 = v8::String::NewSymbol("abc");
   7503   Handle<String> symbol2 = v8::String::NewSymbol("abc");
   7504   CHECK(SameSymbol(symbol1, symbol2));
   7505 
   7506   SameSymbolHelper("\360\220\220\205",  // 4 byte encoding.
   7507                    "\355\240\201\355\260\205");  // 2 3-byte surrogates.
   7508   SameSymbolHelper("\355\240\201\355\260\206",  // 2 3-byte surrogates.
   7509                    "\360\220\220\206");  // 4 byte encoding.
   7510   SameSymbolHelper("x\360\220\220\205",  // 4 byte encoding.
   7511                    "x\355\240\201\355\260\205");  // 2 3-byte surrogates.
   7512   SameSymbolHelper("x\355\240\201\355\260\206",  // 2 3-byte surrogates.
   7513                    "x\360\220\220\206");  // 4 byte encoding.
   7514   CompileRun(
   7515       "var sym0 = 'benedictus';"
   7516       "var sym0b = 'S\303\270ren';"
   7517       "var sym1 = '\355\240\201\355\260\207';"
   7518       "var sym2 = '\360\220\220\210';"
   7519       "var sym3 = 'x\355\240\201\355\260\207';"
   7520       "var sym4 = 'x\360\220\220\210';"
   7521       "if (sym1.length != 2) throw sym1;"
   7522       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
   7523       "if (sym2.length != 2) throw sym2;"
   7524       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
   7525       "if (sym3.length != 3) throw sym3;"
   7526       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
   7527       "if (sym4.length != 3) throw sym4;"
   7528       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
   7529   Handle<String> sym0 = v8::String::NewSymbol("benedictus");
   7530   Handle<String> sym0b = v8::String::NewSymbol("S\303\270ren");
   7531   Handle<String> sym1 = v8::String::NewSymbol("\355\240\201\355\260\207");
   7532   Handle<String> sym2 = v8::String::NewSymbol("\360\220\220\210");
   7533   Handle<String> sym3 = v8::String::NewSymbol("x\355\240\201\355\260\207");
   7534   Handle<String> sym4 = v8::String::NewSymbol("x\360\220\220\210");
   7535   v8::Local<v8::Object> global = context->Global();
   7536   Local<Value> s0 = global->Get(v8_str("sym0"));
   7537   Local<Value> s0b = global->Get(v8_str("sym0b"));
   7538   Local<Value> s1 = global->Get(v8_str("sym1"));
   7539   Local<Value> s2 = global->Get(v8_str("sym2"));
   7540   Local<Value> s3 = global->Get(v8_str("sym3"));
   7541   Local<Value> s4 = global->Get(v8_str("sym4"));
   7542   CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
   7543   CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
   7544   CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
   7545   CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
   7546   CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
   7547   CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
   7548 }
   7549 
   7550 
   7551 THREADED_TEST(ToArrayIndex) {
   7552   LocalContext context;
   7553   v8::HandleScope scope(context->GetIsolate());
   7554 
   7555   v8::Handle<String> str = v8_str("42");
   7556   v8::Handle<v8::Uint32> index = str->ToArrayIndex();
   7557   CHECK(!index.IsEmpty());
   7558   CHECK_EQ(42.0, index->Uint32Value());
   7559   str = v8_str("42asdf");
   7560   index = str->ToArrayIndex();
   7561   CHECK(index.IsEmpty());
   7562   str = v8_str("-42");
   7563   index = str->ToArrayIndex();
   7564   CHECK(index.IsEmpty());
   7565   str = v8_str("4294967295");
   7566   index = str->ToArrayIndex();
   7567   CHECK(!index.IsEmpty());
   7568   CHECK_EQ(4294967295.0, index->Uint32Value());
   7569   v8::Handle<v8::Number> num = v8::Number::New(1);
   7570   index = num->ToArrayIndex();
   7571   CHECK(!index.IsEmpty());
   7572   CHECK_EQ(1.0, index->Uint32Value());
   7573   num = v8::Number::New(-1);
   7574   index = num->ToArrayIndex();
   7575   CHECK(index.IsEmpty());
   7576   v8::Handle<v8::Object> obj = v8::Object::New();
   7577   index = obj->ToArrayIndex();
   7578   CHECK(index.IsEmpty());
   7579 }
   7580 
   7581 
   7582 THREADED_TEST(ErrorConstruction) {
   7583   LocalContext context;
   7584   v8::HandleScope scope(context->GetIsolate());
   7585 
   7586   v8::Handle<String> foo = v8_str("foo");
   7587   v8::Handle<String> message = v8_str("message");
   7588   v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
   7589   CHECK(range_error->IsObject());
   7590   CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
   7591   v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
   7592   CHECK(reference_error->IsObject());
   7593   CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
   7594   v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
   7595   CHECK(syntax_error->IsObject());
   7596   CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
   7597   v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
   7598   CHECK(type_error->IsObject());
   7599   CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
   7600   v8::Handle<Value> error = v8::Exception::Error(foo);
   7601   CHECK(error->IsObject());
   7602   CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
   7603 }
   7604 
   7605 
   7606 static void YGetter(Local<String> name,
   7607                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   7608   ApiTestFuzzer::Fuzz();
   7609   info.GetReturnValue().Set(v8_num(10));
   7610 }
   7611 
   7612 
   7613 static void YSetter(Local<String> name,
   7614                     Local<Value> value,
   7615                     const v8::PropertyCallbackInfo<void>& info) {
   7616   if (info.This()->Has(name)) {
   7617     info.This()->Delete(name);
   7618   }
   7619   info.This()->Set(name, value);
   7620 }
   7621 
   7622 
   7623 THREADED_TEST(DeleteAccessor) {
   7624   v8::HandleScope scope(v8::Isolate::GetCurrent());
   7625   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
   7626   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
   7627   LocalContext context;
   7628   v8::Handle<v8::Object> holder = obj->NewInstance();
   7629   context->Global()->Set(v8_str("holder"), holder);
   7630   v8::Handle<Value> result = CompileRun(
   7631       "holder.y = 11; holder.y = 12; holder.y");
   7632   CHECK_EQ(12, result->Uint32Value());
   7633 }
   7634 
   7635 
   7636 THREADED_TEST(TypeSwitch) {
   7637   v8::HandleScope scope(v8::Isolate::GetCurrent());
   7638   v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
   7639   v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
   7640   v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
   7641   v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
   7642   v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
   7643   LocalContext context;
   7644   v8::Handle<v8::Object> obj0 = v8::Object::New();
   7645   v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
   7646   v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
   7647   v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
   7648   for (int i = 0; i < 10; i++) {
   7649     CHECK_EQ(0, type_switch->match(obj0));
   7650     CHECK_EQ(1, type_switch->match(obj1));
   7651     CHECK_EQ(2, type_switch->match(obj2));
   7652     CHECK_EQ(3, type_switch->match(obj3));
   7653     CHECK_EQ(3, type_switch->match(obj3));
   7654     CHECK_EQ(2, type_switch->match(obj2));
   7655     CHECK_EQ(1, type_switch->match(obj1));
   7656     CHECK_EQ(0, type_switch->match(obj0));
   7657   }
   7658 }
   7659 
   7660 
   7661 // For use within the TestSecurityHandler() test.
   7662 static bool g_security_callback_result = false;
   7663 static bool NamedSecurityTestCallback(Local<v8::Object> global,
   7664                                       Local<Value> name,
   7665                                       v8::AccessType type,
   7666                                       Local<Value> data) {
   7667   // Always allow read access.
   7668   if (type == v8::ACCESS_GET)
   7669     return true;
   7670 
   7671   // Sometimes allow other access.
   7672   return g_security_callback_result;
   7673 }
   7674 
   7675 
   7676 static bool IndexedSecurityTestCallback(Local<v8::Object> global,
   7677                                         uint32_t key,
   7678                                         v8::AccessType type,
   7679                                         Local<Value> data) {
   7680   // Always allow read access.
   7681   if (type == v8::ACCESS_GET)
   7682     return true;
   7683 
   7684   // Sometimes allow other access.
   7685   return g_security_callback_result;
   7686 }
   7687 
   7688 
   7689 static int trouble_nesting = 0;
   7690 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   7691   ApiTestFuzzer::Fuzz();
   7692   trouble_nesting++;
   7693 
   7694   // Call a JS function that throws an uncaught exception.
   7695   Local<v8::Object> arg_this = Context::GetCurrent()->Global();
   7696   Local<Value> trouble_callee = (trouble_nesting == 3) ?
   7697     arg_this->Get(v8_str("trouble_callee")) :
   7698     arg_this->Get(v8_str("trouble_caller"));
   7699   CHECK(trouble_callee->IsFunction());
   7700   args.GetReturnValue().Set(
   7701       Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
   7702 }
   7703 
   7704 
   7705 static int report_count = 0;
   7706 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
   7707                                              v8::Handle<Value>) {
   7708   report_count++;
   7709 }
   7710 
   7711 
   7712 // Counts uncaught exceptions, but other tests running in parallel
   7713 // also have uncaught exceptions.
   7714 TEST(ApiUncaughtException) {
   7715   report_count = 0;
   7716   LocalContext env;
   7717   v8::HandleScope scope(env->GetIsolate());
   7718   v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
   7719 
   7720   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
   7721   v8::Local<v8::Object> global = env->Global();
   7722   global->Set(v8_str("trouble"), fun->GetFunction());
   7723 
   7724   Script::Compile(v8_str("function trouble_callee() {"
   7725                          "  var x = null;"
   7726                          "  return x.foo;"
   7727                          "};"
   7728                          "function trouble_caller() {"
   7729                          "  trouble();"
   7730                          "};"))->Run();
   7731   Local<Value> trouble = global->Get(v8_str("trouble"));
   7732   CHECK(trouble->IsFunction());
   7733   Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
   7734   CHECK(trouble_callee->IsFunction());
   7735   Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
   7736   CHECK(trouble_caller->IsFunction());
   7737   Function::Cast(*trouble_caller)->Call(global, 0, NULL);
   7738   CHECK_EQ(1, report_count);
   7739   v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
   7740 }
   7741 
   7742 static const char* script_resource_name = "ExceptionInNativeScript.js";
   7743 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
   7744                                                 v8::Handle<Value>) {
   7745   v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
   7746   CHECK(!name_val.IsEmpty() && name_val->IsString());
   7747   v8::String::Utf8Value name(message->GetScriptResourceName());
   7748   CHECK_EQ(script_resource_name, *name);
   7749   CHECK_EQ(3, message->GetLineNumber());
   7750   v8::String::Utf8Value source_line(message->GetSourceLine());
   7751   CHECK_EQ("  new o.foo();", *source_line);
   7752 }
   7753 
   7754 
   7755 TEST(ExceptionInNativeScript) {
   7756   LocalContext env;
   7757   v8::HandleScope scope(env->GetIsolate());
   7758   v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
   7759 
   7760   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
   7761   v8::Local<v8::Object> global = env->Global();
   7762   global->Set(v8_str("trouble"), fun->GetFunction());
   7763 
   7764   Script::Compile(v8_str("function trouble() {\n"
   7765                          "  var o = {};\n"
   7766                          "  new o.foo();\n"
   7767                          "};"), v8::String::New(script_resource_name))->Run();
   7768   Local<Value> trouble = global->Get(v8_str("trouble"));
   7769   CHECK(trouble->IsFunction());
   7770   Function::Cast(*trouble)->Call(global, 0, NULL);
   7771   v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
   7772 }
   7773 
   7774 
   7775 TEST(CompilationErrorUsingTryCatchHandler) {
   7776   LocalContext env;
   7777   v8::HandleScope scope(env->GetIsolate());
   7778   v8::TryCatch try_catch;
   7779   Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
   7780   CHECK_NE(NULL, *try_catch.Exception());
   7781   CHECK(try_catch.HasCaught());
   7782 }
   7783 
   7784 
   7785 TEST(TryCatchFinallyUsingTryCatchHandler) {
   7786   LocalContext env;
   7787   v8::HandleScope scope(env->GetIsolate());
   7788   v8::TryCatch try_catch;
   7789   Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
   7790   CHECK(!try_catch.HasCaught());
   7791   Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
   7792   CHECK(try_catch.HasCaught());
   7793   try_catch.Reset();
   7794   Script::Compile(v8_str("(function() {"
   7795                          "try { throw ''; } finally { return; }"
   7796                          "})()"))->Run();
   7797   CHECK(!try_catch.HasCaught());
   7798   Script::Compile(v8_str("(function()"
   7799                          "  { try { throw ''; } finally { throw 0; }"
   7800                          "})()"))->Run();
   7801   CHECK(try_catch.HasCaught());
   7802 }
   7803 
   7804 
   7805 // SecurityHandler can't be run twice
   7806 TEST(SecurityHandler) {
   7807   v8::HandleScope scope0(v8::Isolate::GetCurrent());
   7808   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   7809   global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
   7810                                            IndexedSecurityTestCallback);
   7811   // Create an environment
   7812   v8::Handle<Context> context0 =
   7813     Context::New(v8::Isolate::GetCurrent(), NULL, global_template);
   7814   context0->Enter();
   7815 
   7816   v8::Handle<v8::Object> global0 = context0->Global();
   7817   v8::Handle<Script> script0 = v8_compile("foo = 111");
   7818   script0->Run();
   7819   global0->Set(v8_str("0"), v8_num(999));
   7820   v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
   7821   CHECK_EQ(111, foo0->Int32Value());
   7822   v8::Handle<Value> z0 = global0->Get(v8_str("0"));
   7823   CHECK_EQ(999, z0->Int32Value());
   7824 
   7825   // Create another environment, should fail security checks.
   7826   v8::HandleScope scope1(v8::Isolate::GetCurrent());
   7827 
   7828   v8::Handle<Context> context1 =
   7829     Context::New(v8::Isolate::GetCurrent(), NULL, global_template);
   7830   context1->Enter();
   7831 
   7832   v8::Handle<v8::Object> global1 = context1->Global();
   7833   global1->Set(v8_str("othercontext"), global0);
   7834   // This set will fail the security check.
   7835   v8::Handle<Script> script1 =
   7836     v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
   7837   script1->Run();
   7838   // This read will pass the security check.
   7839   v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
   7840   CHECK_EQ(111, foo1->Int32Value());
   7841   // This read will pass the security check.
   7842   v8::Handle<Value> z1 = global0->Get(v8_str("0"));
   7843   CHECK_EQ(999, z1->Int32Value());
   7844 
   7845   // Create another environment, should pass security checks.
   7846   { g_security_callback_result = true;  // allow security handler to pass.
   7847     v8::HandleScope scope2(v8::Isolate::GetCurrent());
   7848     LocalContext context2;
   7849     v8::Handle<v8::Object> global2 = context2->Global();
   7850     global2->Set(v8_str("othercontext"), global0);
   7851     v8::Handle<Script> script2 =
   7852         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
   7853     script2->Run();
   7854     v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
   7855     CHECK_EQ(333, foo2->Int32Value());
   7856     v8::Handle<Value> z2 = global0->Get(v8_str("0"));
   7857     CHECK_EQ(888, z2->Int32Value());
   7858   }
   7859 
   7860   context1->Exit();
   7861   context0->Exit();
   7862 }
   7863 
   7864 
   7865 THREADED_TEST(SecurityChecks) {
   7866   LocalContext env1;
   7867   v8::HandleScope handle_scope(env1->GetIsolate());
   7868   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   7869 
   7870   Local<Value> foo = v8_str("foo");
   7871   Local<Value> bar = v8_str("bar");
   7872 
   7873   // Set to the same domain.
   7874   env1->SetSecurityToken(foo);
   7875 
   7876   // Create a function in env1.
   7877   Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
   7878   Local<Value> spy = env1->Global()->Get(v8_str("spy"));
   7879   CHECK(spy->IsFunction());
   7880 
   7881   // Create another function accessing global objects.
   7882   Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
   7883   Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
   7884   CHECK(spy2->IsFunction());
   7885 
   7886   // Switch to env2 in the same domain and invoke spy on env2.
   7887   {
   7888     env2->SetSecurityToken(foo);
   7889     // Enter env2
   7890     Context::Scope scope_env2(env2);
   7891     Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
   7892     CHECK(result->IsFunction());
   7893   }
   7894 
   7895   {
   7896     env2->SetSecurityToken(bar);
   7897     Context::Scope scope_env2(env2);
   7898 
   7899     // Call cross_domain_call, it should throw an exception
   7900     v8::TryCatch try_catch;
   7901     Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
   7902     CHECK(try_catch.HasCaught());
   7903   }
   7904 }
   7905 
   7906 
   7907 // Regression test case for issue 1183439.
   7908 THREADED_TEST(SecurityChecksForPrototypeChain) {
   7909   LocalContext current;
   7910   v8::HandleScope scope(current->GetIsolate());
   7911   v8::Handle<Context> other = Context::New(current->GetIsolate());
   7912 
   7913   // Change context to be able to get to the Object function in the
   7914   // other context without hitting the security checks.
   7915   v8::Local<Value> other_object;
   7916   { Context::Scope scope(other);
   7917     other_object = other->Global()->Get(v8_str("Object"));
   7918     other->Global()->Set(v8_num(42), v8_num(87));
   7919   }
   7920 
   7921   current->Global()->Set(v8_str("other"), other->Global());
   7922   CHECK(v8_compile("other")->Run()->Equals(other->Global()));
   7923 
   7924   // Make sure the security check fails here and we get an undefined
   7925   // result instead of getting the Object function. Repeat in a loop
   7926   // to make sure to exercise the IC code.
   7927   v8::Local<Script> access_other0 = v8_compile("other.Object");
   7928   v8::Local<Script> access_other1 = v8_compile("other[42]");
   7929   for (int i = 0; i < 5; i++) {
   7930     CHECK(!access_other0->Run()->Equals(other_object));
   7931     CHECK(access_other0->Run()->IsUndefined());
   7932     CHECK(!access_other1->Run()->Equals(v8_num(87)));
   7933     CHECK(access_other1->Run()->IsUndefined());
   7934   }
   7935 
   7936   // Create an object that has 'other' in its prototype chain and make
   7937   // sure we cannot access the Object function indirectly through
   7938   // that. Repeat in a loop to make sure to exercise the IC code.
   7939   v8_compile("function F() { };"
   7940              "F.prototype = other;"
   7941              "var f = new F();")->Run();
   7942   v8::Local<Script> access_f0 = v8_compile("f.Object");
   7943   v8::Local<Script> access_f1 = v8_compile("f[42]");
   7944   for (int j = 0; j < 5; j++) {
   7945     CHECK(!access_f0->Run()->Equals(other_object));
   7946     CHECK(access_f0->Run()->IsUndefined());
   7947     CHECK(!access_f1->Run()->Equals(v8_num(87)));
   7948     CHECK(access_f1->Run()->IsUndefined());
   7949   }
   7950 
   7951   // Now it gets hairy: Set the prototype for the other global object
   7952   // to be the current global object. The prototype chain for 'f' now
   7953   // goes through 'other' but ends up in the current global object.
   7954   { Context::Scope scope(other);
   7955     other->Global()->Set(v8_str("__proto__"), current->Global());
   7956   }
   7957   // Set a named and an index property on the current global
   7958   // object. To force the lookup to go through the other global object,
   7959   // the properties must not exist in the other global object.
   7960   current->Global()->Set(v8_str("foo"), v8_num(100));
   7961   current->Global()->Set(v8_num(99), v8_num(101));
   7962   // Try to read the properties from f and make sure that the access
   7963   // gets stopped by the security checks on the other global object.
   7964   Local<Script> access_f2 = v8_compile("f.foo");
   7965   Local<Script> access_f3 = v8_compile("f[99]");
   7966   for (int k = 0; k < 5; k++) {
   7967     CHECK(!access_f2->Run()->Equals(v8_num(100)));
   7968     CHECK(access_f2->Run()->IsUndefined());
   7969     CHECK(!access_f3->Run()->Equals(v8_num(101)));
   7970     CHECK(access_f3->Run()->IsUndefined());
   7971   }
   7972 }
   7973 
   7974 
   7975 THREADED_TEST(CrossDomainDelete) {
   7976   LocalContext env1;
   7977   v8::HandleScope handle_scope(env1->GetIsolate());
   7978   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   7979 
   7980   Local<Value> foo = v8_str("foo");
   7981   Local<Value> bar = v8_str("bar");
   7982 
   7983   // Set to the same domain.
   7984   env1->SetSecurityToken(foo);
   7985   env2->SetSecurityToken(foo);
   7986 
   7987   env1->Global()->Set(v8_str("prop"), v8_num(3));
   7988   env2->Global()->Set(v8_str("env1"), env1->Global());
   7989 
   7990   // Change env2 to a different domain and delete env1.prop.
   7991   env2->SetSecurityToken(bar);
   7992   {
   7993     Context::Scope scope_env2(env2);
   7994     Local<Value> result =
   7995         Script::Compile(v8_str("delete env1.prop"))->Run();
   7996     CHECK(result->IsFalse());
   7997   }
   7998 
   7999   // Check that env1.prop still exists.
   8000   Local<Value> v = env1->Global()->Get(v8_str("prop"));
   8001   CHECK(v->IsNumber());
   8002   CHECK_EQ(3, v->Int32Value());
   8003 }
   8004 
   8005 
   8006 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
   8007   LocalContext env1;
   8008   v8::HandleScope handle_scope(env1->GetIsolate());
   8009   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8010 
   8011   Local<Value> foo = v8_str("foo");
   8012   Local<Value> bar = v8_str("bar");
   8013 
   8014   // Set to the same domain.
   8015   env1->SetSecurityToken(foo);
   8016   env2->SetSecurityToken(foo);
   8017 
   8018   env1->Global()->Set(v8_str("prop"), v8_num(3));
   8019   env2->Global()->Set(v8_str("env1"), env1->Global());
   8020 
   8021   // env1.prop is enumerable in env2.
   8022   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
   8023   {
   8024     Context::Scope scope_env2(env2);
   8025     Local<Value> result = Script::Compile(test)->Run();
   8026     CHECK(result->IsTrue());
   8027   }
   8028 
   8029   // Change env2 to a different domain and test again.
   8030   env2->SetSecurityToken(bar);
   8031   {
   8032     Context::Scope scope_env2(env2);
   8033     Local<Value> result = Script::Compile(test)->Run();
   8034     CHECK(result->IsFalse());
   8035   }
   8036 }
   8037 
   8038 
   8039 THREADED_TEST(CrossDomainForIn) {
   8040   LocalContext env1;
   8041   v8::HandleScope handle_scope(env1->GetIsolate());
   8042   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8043 
   8044   Local<Value> foo = v8_str("foo");
   8045   Local<Value> bar = v8_str("bar");
   8046 
   8047   // Set to the same domain.
   8048   env1->SetSecurityToken(foo);
   8049   env2->SetSecurityToken(foo);
   8050 
   8051   env1->Global()->Set(v8_str("prop"), v8_num(3));
   8052   env2->Global()->Set(v8_str("env1"), env1->Global());
   8053 
   8054   // Change env2 to a different domain and set env1's global object
   8055   // as the __proto__ of an object in env2 and enumerate properties
   8056   // in for-in. It shouldn't enumerate properties on env1's global
   8057   // object.
   8058   env2->SetSecurityToken(bar);
   8059   {
   8060     Context::Scope scope_env2(env2);
   8061     Local<Value> result =
   8062         CompileRun("(function(){var obj = {'__proto__':env1};"
   8063                    "for (var p in obj)"
   8064                    "   if (p == 'prop') return false;"
   8065                    "return true;})()");
   8066     CHECK(result->IsTrue());
   8067   }
   8068 }
   8069 
   8070 
   8071 TEST(ContextDetachGlobal) {
   8072   LocalContext env1;
   8073   v8::HandleScope handle_scope(env1->GetIsolate());
   8074   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8075 
   8076   Local<v8::Object> global1 = env1->Global();
   8077 
   8078   Local<Value> foo = v8_str("foo");
   8079 
   8080   // Set to the same domain.
   8081   env1->SetSecurityToken(foo);
   8082   env2->SetSecurityToken(foo);
   8083 
   8084   // Enter env2
   8085   env2->Enter();
   8086 
   8087   // Create a function in env2 and add a reference to it in env1.
   8088   Local<v8::Object> global2 = env2->Global();
   8089   global2->Set(v8_str("prop"), v8::Integer::New(1));
   8090   CompileRun("function getProp() {return prop;}");
   8091 
   8092   env1->Global()->Set(v8_str("getProp"),
   8093                       global2->Get(v8_str("getProp")));
   8094 
   8095   // Detach env2's global, and reuse the global object of env2
   8096   env2->Exit();
   8097   env2->DetachGlobal();
   8098   // env2 has a new global object.
   8099   CHECK(!env2->Global()->Equals(global2));
   8100 
   8101   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
   8102                                           0,
   8103                                           v8::Handle<v8::ObjectTemplate>(),
   8104                                           global2);
   8105   env3->SetSecurityToken(v8_str("bar"));
   8106   env3->Enter();
   8107 
   8108   Local<v8::Object> global3 = env3->Global();
   8109   CHECK_EQ(global2, global3);
   8110   CHECK(global3->Get(v8_str("prop"))->IsUndefined());
   8111   CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
   8112   global3->Set(v8_str("prop"), v8::Integer::New(-1));
   8113   global3->Set(v8_str("prop2"), v8::Integer::New(2));
   8114   env3->Exit();
   8115 
   8116   // Call getProp in env1, and it should return the value 1
   8117   {
   8118     Local<Value> get_prop = global1->Get(v8_str("getProp"));
   8119     CHECK(get_prop->IsFunction());
   8120     v8::TryCatch try_catch;
   8121     Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
   8122     CHECK(!try_catch.HasCaught());
   8123     CHECK_EQ(1, r->Int32Value());
   8124   }
   8125 
   8126   // Check that env3 is not accessible from env1
   8127   {
   8128     Local<Value> r = global3->Get(v8_str("prop2"));
   8129     CHECK(r->IsUndefined());
   8130   }
   8131 }
   8132 
   8133 
   8134 TEST(DetachAndReattachGlobal) {
   8135   LocalContext env1;
   8136   v8::HandleScope scope(env1->GetIsolate());
   8137 
   8138   // Create second environment.
   8139   v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
   8140 
   8141   Local<Value> foo = v8_str("foo");
   8142 
   8143   // Set same security token for env1 and env2.
   8144   env1->SetSecurityToken(foo);
   8145   env2->SetSecurityToken(foo);
   8146 
   8147   // Create a property on the global object in env2.
   8148   {
   8149     v8::Context::Scope scope(env2);
   8150     env2->Global()->Set(v8_str("p"), v8::Integer::New(42));
   8151   }
   8152 
   8153   // Create a reference to env2 global from env1 global.
   8154   env1->Global()->Set(v8_str("other"), env2->Global());
   8155 
   8156   // Check that we have access to other.p in env2 from env1.
   8157   Local<Value> result = CompileRun("other.p");
   8158   CHECK(result->IsInt32());
   8159   CHECK_EQ(42, result->Int32Value());
   8160 
   8161   // Hold on to global from env2 and detach global from env2.
   8162   Local<v8::Object> global2 = env2->Global();
   8163   env2->DetachGlobal();
   8164 
   8165   // Check that the global has been detached. No other.p property can
   8166   // be found.
   8167   result = CompileRun("other.p");
   8168   CHECK(result->IsUndefined());
   8169 
   8170   // Reuse global2 for env3.
   8171   v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
   8172                                           0,
   8173                                           v8::Handle<v8::ObjectTemplate>(),
   8174                                           global2);
   8175   CHECK_EQ(global2, env3->Global());
   8176 
   8177   // Start by using the same security token for env3 as for env1 and env2.
   8178   env3->SetSecurityToken(foo);
   8179 
   8180   // Create a property on the global object in env3.
   8181   {
   8182     v8::Context::Scope scope(env3);
   8183     env3->Global()->Set(v8_str("p"), v8::Integer::New(24));
   8184   }
   8185 
   8186   // Check that other.p is now the property in env3 and that we have access.
   8187   result = CompileRun("other.p");
   8188   CHECK(result->IsInt32());
   8189   CHECK_EQ(24, result->Int32Value());
   8190 
   8191   // Change security token for env3 to something different from env1 and env2.
   8192   env3->SetSecurityToken(v8_str("bar"));
   8193 
   8194   // Check that we do not have access to other.p in env1. |other| is now
   8195   // the global object for env3 which has a different security token,
   8196   // so access should be blocked.
   8197   result = CompileRun("other.p");
   8198   CHECK(result->IsUndefined());
   8199 
   8200   // Detach the global for env3 and reattach it to env2.
   8201   env3->DetachGlobal();
   8202   env2->ReattachGlobal(global2);
   8203 
   8204   // Check that we have access to other.p again in env1.  |other| is now
   8205   // the global object for env2 which has the same security token as env1.
   8206   result = CompileRun("other.p");
   8207   CHECK(result->IsInt32());
   8208   CHECK_EQ(42, result->Int32Value());
   8209 }
   8210 
   8211 
   8212 static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
   8213 static bool NamedAccessBlocker(Local<v8::Object> global,
   8214                                Local<Value> name,
   8215                                v8::AccessType type,
   8216                                Local<Value> data) {
   8217   return Context::GetCurrent()->Global()->Equals(global) ||
   8218       allowed_access_type[type];
   8219 }
   8220 
   8221 
   8222 static bool IndexedAccessBlocker(Local<v8::Object> global,
   8223                                  uint32_t key,
   8224                                  v8::AccessType type,
   8225                                  Local<Value> data) {
   8226   return Context::GetCurrent()->Global()->Equals(global) ||
   8227       allowed_access_type[type];
   8228 }
   8229 
   8230 
   8231 static int g_echo_value = -1;
   8232 static void EchoGetter(
   8233     Local<String> name,
   8234     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8235   info.GetReturnValue().Set(v8_num(g_echo_value));
   8236 }
   8237 
   8238 
   8239 static void EchoSetter(Local<String> name,
   8240                        Local<Value> value,
   8241                        const v8::PropertyCallbackInfo<void>&) {
   8242   if (value->IsNumber())
   8243     g_echo_value = value->Int32Value();
   8244 }
   8245 
   8246 
   8247 static void UnreachableGetter(
   8248     Local<String> name,
   8249     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8250   CHECK(false);  // This function should not be called..
   8251 }
   8252 
   8253 
   8254 static void UnreachableSetter(Local<String>,
   8255                               Local<Value>,
   8256                               const v8::PropertyCallbackInfo<void>&) {
   8257   CHECK(false);  // This function should nto be called.
   8258 }
   8259 
   8260 
   8261 TEST(AccessControl) {
   8262   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   8263   v8::HandleScope handle_scope(isolate);
   8264   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   8265 
   8266   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   8267                                            IndexedAccessBlocker);
   8268 
   8269   // Add an accessor accessible by cross-domain JS code.
   8270   global_template->SetAccessor(
   8271       v8_str("accessible_prop"),
   8272       EchoGetter, EchoSetter,
   8273       v8::Handle<Value>(),
   8274       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   8275 
   8276   // Add an accessor that is not accessible by cross-domain JS code.
   8277   global_template->SetAccessor(v8_str("blocked_prop"),
   8278                                UnreachableGetter, UnreachableSetter,
   8279                                v8::Handle<Value>(),
   8280                                v8::DEFAULT);
   8281 
   8282   // Create an environment
   8283   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   8284   context0->Enter();
   8285 
   8286   v8::Handle<v8::Object> global0 = context0->Global();
   8287 
   8288   // Define a property with JS getter and setter.
   8289   CompileRun(
   8290       "function getter() { return 'getter'; };\n"
   8291       "function setter() { return 'setter'; }\n"
   8292       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   8293 
   8294   Local<Value> getter = global0->Get(v8_str("getter"));
   8295   Local<Value> setter = global0->Get(v8_str("setter"));
   8296 
   8297   // And define normal element.
   8298   global0->Set(239, v8_str("239"));
   8299 
   8300   // Define an element with JS getter and setter.
   8301   CompileRun(
   8302       "function el_getter() { return 'el_getter'; };\n"
   8303       "function el_setter() { return 'el_setter'; };\n"
   8304       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   8305 
   8306   Local<Value> el_getter = global0->Get(v8_str("el_getter"));
   8307   Local<Value> el_setter = global0->Get(v8_str("el_setter"));
   8308 
   8309   v8::HandleScope scope1(isolate);
   8310 
   8311   v8::Local<Context> context1 = Context::New(isolate);
   8312   context1->Enter();
   8313 
   8314   v8::Handle<v8::Object> global1 = context1->Global();
   8315   global1->Set(v8_str("other"), global0);
   8316 
   8317   // Access blocked property.
   8318   CompileRun("other.blocked_prop = 1");
   8319 
   8320   ExpectUndefined("other.blocked_prop");
   8321   ExpectUndefined(
   8322       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
   8323   ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
   8324 
   8325   // Enable ACCESS_HAS
   8326   allowed_access_type[v8::ACCESS_HAS] = true;
   8327   ExpectUndefined("other.blocked_prop");
   8328   // ... and now we can get the descriptor...
   8329   ExpectUndefined(
   8330       "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
   8331   // ... and enumerate the property.
   8332   ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
   8333   allowed_access_type[v8::ACCESS_HAS] = false;
   8334 
   8335   // Access blocked element.
   8336   CompileRun("other[239] = 1");
   8337 
   8338   ExpectUndefined("other[239]");
   8339   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
   8340   ExpectFalse("propertyIsEnumerable.call(other, '239')");
   8341 
   8342   // Enable ACCESS_HAS
   8343   allowed_access_type[v8::ACCESS_HAS] = true;
   8344   ExpectUndefined("other[239]");
   8345   // ... and now we can get the descriptor...
   8346   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
   8347   // ... and enumerate the property.
   8348   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   8349   allowed_access_type[v8::ACCESS_HAS] = false;
   8350 
   8351   // Access a property with JS accessor.
   8352   CompileRun("other.js_accessor_p = 2");
   8353 
   8354   ExpectUndefined("other.js_accessor_p");
   8355   ExpectUndefined(
   8356       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
   8357 
   8358   // Enable ACCESS_HAS.
   8359   allowed_access_type[v8::ACCESS_HAS] = true;
   8360   ExpectUndefined("other.js_accessor_p");
   8361   ExpectUndefined(
   8362       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
   8363   ExpectUndefined(
   8364       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
   8365   ExpectUndefined(
   8366       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   8367   allowed_access_type[v8::ACCESS_HAS] = false;
   8368 
   8369   // Enable both ACCESS_HAS and ACCESS_GET.
   8370   allowed_access_type[v8::ACCESS_HAS] = true;
   8371   allowed_access_type[v8::ACCESS_GET] = true;
   8372 
   8373   ExpectString("other.js_accessor_p", "getter");
   8374   ExpectObject(
   8375       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   8376   ExpectUndefined(
   8377       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
   8378   ExpectUndefined(
   8379       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   8380 
   8381   allowed_access_type[v8::ACCESS_GET] = false;
   8382   allowed_access_type[v8::ACCESS_HAS] = false;
   8383 
   8384   // Enable both ACCESS_HAS and ACCESS_SET.
   8385   allowed_access_type[v8::ACCESS_HAS] = true;
   8386   allowed_access_type[v8::ACCESS_SET] = true;
   8387 
   8388   ExpectUndefined("other.js_accessor_p");
   8389   ExpectUndefined(
   8390       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
   8391   ExpectObject(
   8392       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   8393   ExpectUndefined(
   8394       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   8395 
   8396   allowed_access_type[v8::ACCESS_SET] = false;
   8397   allowed_access_type[v8::ACCESS_HAS] = false;
   8398 
   8399   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
   8400   allowed_access_type[v8::ACCESS_HAS] = true;
   8401   allowed_access_type[v8::ACCESS_GET] = true;
   8402   allowed_access_type[v8::ACCESS_SET] = true;
   8403 
   8404   ExpectString("other.js_accessor_p", "getter");
   8405   ExpectObject(
   8406       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   8407   ExpectObject(
   8408       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   8409   ExpectUndefined(
   8410       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   8411 
   8412   allowed_access_type[v8::ACCESS_SET] = false;
   8413   allowed_access_type[v8::ACCESS_GET] = false;
   8414   allowed_access_type[v8::ACCESS_HAS] = false;
   8415 
   8416   // Access an element with JS accessor.
   8417   CompileRun("other[42] = 2");
   8418 
   8419   ExpectUndefined("other[42]");
   8420   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
   8421 
   8422   // Enable ACCESS_HAS.
   8423   allowed_access_type[v8::ACCESS_HAS] = true;
   8424   ExpectUndefined("other[42]");
   8425   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
   8426   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
   8427   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   8428   allowed_access_type[v8::ACCESS_HAS] = false;
   8429 
   8430   // Enable both ACCESS_HAS and ACCESS_GET.
   8431   allowed_access_type[v8::ACCESS_HAS] = true;
   8432   allowed_access_type[v8::ACCESS_GET] = true;
   8433 
   8434   ExpectString("other[42]", "el_getter");
   8435   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   8436   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
   8437   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   8438 
   8439   allowed_access_type[v8::ACCESS_GET] = false;
   8440   allowed_access_type[v8::ACCESS_HAS] = false;
   8441 
   8442   // Enable both ACCESS_HAS and ACCESS_SET.
   8443   allowed_access_type[v8::ACCESS_HAS] = true;
   8444   allowed_access_type[v8::ACCESS_SET] = true;
   8445 
   8446   ExpectUndefined("other[42]");
   8447   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
   8448   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   8449   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   8450 
   8451   allowed_access_type[v8::ACCESS_SET] = false;
   8452   allowed_access_type[v8::ACCESS_HAS] = false;
   8453 
   8454   // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
   8455   allowed_access_type[v8::ACCESS_HAS] = true;
   8456   allowed_access_type[v8::ACCESS_GET] = true;
   8457   allowed_access_type[v8::ACCESS_SET] = true;
   8458 
   8459   ExpectString("other[42]", "el_getter");
   8460   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   8461   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   8462   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   8463 
   8464   allowed_access_type[v8::ACCESS_SET] = false;
   8465   allowed_access_type[v8::ACCESS_GET] = false;
   8466   allowed_access_type[v8::ACCESS_HAS] = false;
   8467 
   8468   v8::Handle<Value> value;
   8469 
   8470   // Access accessible property
   8471   value = CompileRun("other.accessible_prop = 3");
   8472   CHECK(value->IsNumber());
   8473   CHECK_EQ(3, value->Int32Value());
   8474   CHECK_EQ(3, g_echo_value);
   8475 
   8476   value = CompileRun("other.accessible_prop");
   8477   CHECK(value->IsNumber());
   8478   CHECK_EQ(3, value->Int32Value());
   8479 
   8480   value = CompileRun(
   8481       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   8482   CHECK(value->IsNumber());
   8483   CHECK_EQ(3, value->Int32Value());
   8484 
   8485   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   8486   CHECK(value->IsTrue());
   8487 
   8488   // Enumeration doesn't enumerate accessors from inaccessible objects in
   8489   // the prototype chain even if the accessors are in themselves accessible.
   8490   value =
   8491       CompileRun("(function(){var obj = {'__proto__':other};"
   8492                  "for (var p in obj)"
   8493                  "   if (p == 'accessible_prop' || p == 'blocked_prop') {"
   8494                  "     return false;"
   8495                  "   }"
   8496                  "return true;})()");
   8497   CHECK(value->IsTrue());
   8498 
   8499   context1->Exit();
   8500   context0->Exit();
   8501 }
   8502 
   8503 
   8504 TEST(AccessControlES5) {
   8505   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   8506   v8::HandleScope handle_scope(isolate);
   8507   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   8508 
   8509   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
   8510                                            IndexedAccessBlocker);
   8511 
   8512   // Add accessible accessor.
   8513   global_template->SetAccessor(
   8514       v8_str("accessible_prop"),
   8515       EchoGetter, EchoSetter,
   8516       v8::Handle<Value>(),
   8517       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   8518 
   8519 
   8520   // Add an accessor that is not accessible by cross-domain JS code.
   8521   global_template->SetAccessor(v8_str("blocked_prop"),
   8522                                UnreachableGetter, UnreachableSetter,
   8523                                v8::Handle<Value>(),
   8524                                v8::DEFAULT);
   8525 
   8526   // Create an environment
   8527   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   8528   context0->Enter();
   8529 
   8530   v8::Handle<v8::Object> global0 = context0->Global();
   8531 
   8532   v8::Local<Context> context1 = Context::New(isolate);
   8533   context1->Enter();
   8534   v8::Handle<v8::Object> global1 = context1->Global();
   8535   global1->Set(v8_str("other"), global0);
   8536 
   8537   // Regression test for issue 1154.
   8538   ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
   8539 
   8540   ExpectUndefined("other.blocked_prop");
   8541 
   8542   // Regression test for issue 1027.
   8543   CompileRun("Object.defineProperty(\n"
   8544              "  other, 'blocked_prop', {configurable: false})");
   8545   ExpectUndefined("other.blocked_prop");
   8546   ExpectUndefined(
   8547       "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
   8548 
   8549   // Regression test for issue 1171.
   8550   ExpectTrue("Object.isExtensible(other)");
   8551   CompileRun("Object.preventExtensions(other)");
   8552   ExpectTrue("Object.isExtensible(other)");
   8553 
   8554   // Object.seal and Object.freeze.
   8555   CompileRun("Object.freeze(other)");
   8556   ExpectTrue("Object.isExtensible(other)");
   8557 
   8558   CompileRun("Object.seal(other)");
   8559   ExpectTrue("Object.isExtensible(other)");
   8560 
   8561   // Regression test for issue 1250.
   8562   // Make sure that we can set the accessible accessors value using normal
   8563   // assignment.
   8564   CompileRun("other.accessible_prop = 42");
   8565   CHECK_EQ(42, g_echo_value);
   8566 
   8567   v8::Handle<Value> value;
   8568   // We follow Safari in ignoring assignments to host object accessors.
   8569   CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
   8570   value = CompileRun("other.accessible_prop == 42");
   8571   CHECK(value->IsTrue());
   8572 }
   8573 
   8574 
   8575 static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
   8576                                             Local<Value> name,
   8577                                             v8::AccessType type,
   8578                                             Local<Value> data) {
   8579   return false;
   8580 }
   8581 
   8582 
   8583 static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
   8584                                               uint32_t key,
   8585                                               v8::AccessType type,
   8586                                               Local<Value> data) {
   8587   return false;
   8588 }
   8589 
   8590 
   8591 THREADED_TEST(AccessControlGetOwnPropertyNames) {
   8592   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   8593   v8::HandleScope handle_scope(isolate);
   8594   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
   8595 
   8596   obj_template->Set(v8_str("x"), v8::Integer::New(42));
   8597   obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
   8598                                         GetOwnPropertyNamesIndexedBlocker);
   8599 
   8600   // Create an environment
   8601   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
   8602   context0->Enter();
   8603 
   8604   v8::Handle<v8::Object> global0 = context0->Global();
   8605 
   8606   v8::HandleScope scope1(v8::Isolate::GetCurrent());
   8607 
   8608   v8::Local<Context> context1 = Context::New(isolate);
   8609   context1->Enter();
   8610 
   8611   v8::Handle<v8::Object> global1 = context1->Global();
   8612   global1->Set(v8_str("other"), global0);
   8613   global1->Set(v8_str("object"), obj_template->NewInstance());
   8614 
   8615   v8::Handle<Value> value;
   8616 
   8617   // Attempt to get the property names of the other global object and
   8618   // of an object that requires access checks.  Accessing the other
   8619   // global object should be blocked by access checks on the global
   8620   // proxy object.  Accessing the object that requires access checks
   8621   // is blocked by the access checks on the object itself.
   8622   value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
   8623   CHECK(value->IsTrue());
   8624 
   8625   value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
   8626   CHECK(value->IsTrue());
   8627 
   8628   context1->Exit();
   8629   context0->Exit();
   8630 }
   8631 
   8632 
   8633 static void IndexedPropertyEnumerator(
   8634     const v8::PropertyCallbackInfo<v8::Array>& info) {
   8635   v8::Handle<v8::Array> result = v8::Array::New(2);
   8636   result->Set(0, v8::Integer::New(7));
   8637   result->Set(1, v8::Object::New());
   8638   info.GetReturnValue().Set(result);
   8639 }
   8640 
   8641 
   8642 static void NamedPropertyEnumerator(
   8643     const v8::PropertyCallbackInfo<v8::Array>& info) {
   8644   v8::Handle<v8::Array> result = v8::Array::New(2);
   8645   result->Set(0, v8_str("x"));
   8646   result->Set(1, v8::Object::New());
   8647   info.GetReturnValue().Set(result);
   8648 }
   8649 
   8650 
   8651 THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
   8652   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   8653   v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
   8654 
   8655   obj_template->Set(v8_str("7"), v8::Integer::New(7));
   8656   obj_template->Set(v8_str("x"), v8::Integer::New(42));
   8657   obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
   8658                                           IndexedPropertyEnumerator);
   8659   obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
   8660                                         NamedPropertyEnumerator);
   8661 
   8662   LocalContext context;
   8663   v8::Handle<v8::Object> global = context->Global();
   8664   global->Set(v8_str("object"), obj_template->NewInstance());
   8665 
   8666   v8::Handle<v8::Value> result =
   8667       CompileRun("Object.getOwnPropertyNames(object)");
   8668   CHECK(result->IsArray());
   8669   v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
   8670   CHECK_EQ(3, result_array->Length());
   8671   CHECK(result_array->Get(0)->IsString());
   8672   CHECK(result_array->Get(1)->IsString());
   8673   CHECK(result_array->Get(2)->IsString());
   8674   CHECK_EQ(v8_str("7"), result_array->Get(0));
   8675   CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
   8676   CHECK_EQ(v8_str("x"), result_array->Get(2));
   8677 }
   8678 
   8679 
   8680 static void ConstTenGetter(Local<String> name,
   8681                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   8682   info.GetReturnValue().Set(v8_num(10));
   8683 }
   8684 
   8685 
   8686 THREADED_TEST(CrossDomainAccessors) {
   8687   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   8688   v8::HandleScope handle_scope(isolate);
   8689 
   8690   v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
   8691 
   8692   v8::Handle<v8::ObjectTemplate> global_template =
   8693       func_template->InstanceTemplate();
   8694 
   8695   v8::Handle<v8::ObjectTemplate> proto_template =
   8696       func_template->PrototypeTemplate();
   8697 
   8698   // Add an accessor to proto that's accessible by cross-domain JS code.
   8699   proto_template->SetAccessor(v8_str("accessible"),
   8700                               ConstTenGetter, 0,
   8701                               v8::Handle<Value>(),
   8702                               v8::ALL_CAN_READ);
   8703 
   8704   // Add an accessor that is not accessible by cross-domain JS code.
   8705   global_template->SetAccessor(v8_str("unreachable"),
   8706                                UnreachableGetter, 0,
   8707                                v8::Handle<Value>(),
   8708                                v8::DEFAULT);
   8709 
   8710   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   8711   context0->Enter();
   8712 
   8713   Local<v8::Object> global = context0->Global();
   8714   // Add a normal property that shadows 'accessible'
   8715   global->Set(v8_str("accessible"), v8_num(11));
   8716 
   8717   // Enter a new context.
   8718   v8::HandleScope scope1(v8::Isolate::GetCurrent());
   8719   v8::Local<Context> context1 = Context::New(isolate);
   8720   context1->Enter();
   8721 
   8722   v8::Handle<v8::Object> global1 = context1->Global();
   8723   global1->Set(v8_str("other"), global);
   8724 
   8725   // Should return 10, instead of 11
   8726   v8::Handle<Value> value = v8_compile("other.accessible")->Run();
   8727   CHECK(value->IsNumber());
   8728   CHECK_EQ(10, value->Int32Value());
   8729 
   8730   value = v8_compile("other.unreachable")->Run();
   8731   CHECK(value->IsUndefined());
   8732 
   8733   context1->Exit();
   8734   context0->Exit();
   8735 }
   8736 
   8737 
   8738 static int named_access_count = 0;
   8739 static int indexed_access_count = 0;
   8740 
   8741 static bool NamedAccessCounter(Local<v8::Object> global,
   8742                                Local<Value> name,
   8743                                v8::AccessType type,
   8744                                Local<Value> data) {
   8745   named_access_count++;
   8746   return true;
   8747 }
   8748 
   8749 
   8750 static bool IndexedAccessCounter(Local<v8::Object> global,
   8751                                  uint32_t key,
   8752                                  v8::AccessType type,
   8753                                  Local<Value> data) {
   8754   indexed_access_count++;
   8755   return true;
   8756 }
   8757 
   8758 
   8759 // This one is too easily disturbed by other tests.
   8760 TEST(AccessControlIC) {
   8761   named_access_count = 0;
   8762   indexed_access_count = 0;
   8763 
   8764   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   8765   v8::HandleScope handle_scope(isolate);
   8766 
   8767   // Create an environment.
   8768   v8::Local<Context> context0 = Context::New(isolate);
   8769   context0->Enter();
   8770 
   8771   // Create an object that requires access-check functions to be
   8772   // called for cross-domain access.
   8773   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   8774   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   8775                                            IndexedAccessCounter);
   8776   Local<v8::Object> object = object_template->NewInstance();
   8777 
   8778   v8::HandleScope scope1(isolate);
   8779 
   8780   // Create another environment.
   8781   v8::Local<Context> context1 = Context::New(isolate);
   8782   context1->Enter();
   8783 
   8784   // Make easy access to the object from the other environment.
   8785   v8::Handle<v8::Object> global1 = context1->Global();
   8786   global1->Set(v8_str("obj"), object);
   8787 
   8788   v8::Handle<Value> value;
   8789 
   8790   // Check that the named access-control function is called every time.
   8791   CompileRun("function testProp(obj) {"
   8792              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   8793              "  for (var j = 0; j < 10; j++) obj.prop;"
   8794              "  return obj.prop"
   8795              "}");
   8796   value = CompileRun("testProp(obj)");
   8797   CHECK(value->IsNumber());
   8798   CHECK_EQ(1, value->Int32Value());
   8799   CHECK_EQ(21, named_access_count);
   8800 
   8801   // Check that the named access-control function is called every time.
   8802   CompileRun("var p = 'prop';"
   8803              "function testKeyed(obj) {"
   8804              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   8805              "  for (var j = 0; j < 10; j++) obj[p];"
   8806              "  return obj[p];"
   8807              "}");
   8808   // Use obj which requires access checks.  No inline caching is used
   8809   // in that case.
   8810   value = CompileRun("testKeyed(obj)");
   8811   CHECK(value->IsNumber());
   8812   CHECK_EQ(1, value->Int32Value());
   8813   CHECK_EQ(42, named_access_count);
   8814   // Force the inline caches into generic state and try again.
   8815   CompileRun("testKeyed({ a: 0 })");
   8816   CompileRun("testKeyed({ b: 0 })");
   8817   value = CompileRun("testKeyed(obj)");
   8818   CHECK(value->IsNumber());
   8819   CHECK_EQ(1, value->Int32Value());
   8820   CHECK_EQ(63, named_access_count);
   8821 
   8822   // Check that the indexed access-control function is called every time.
   8823   CompileRun("function testIndexed(obj) {"
   8824              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   8825              "  for (var j = 0; j < 10; j++) obj[0];"
   8826              "  return obj[0]"
   8827              "}");
   8828   value = CompileRun("testIndexed(obj)");
   8829   CHECK(value->IsNumber());
   8830   CHECK_EQ(1, value->Int32Value());
   8831   CHECK_EQ(21, indexed_access_count);
   8832   // Force the inline caches into generic state.
   8833   CompileRun("testIndexed(new Array(1))");
   8834   // Test that the indexed access check is called.
   8835   value = CompileRun("testIndexed(obj)");
   8836   CHECK(value->IsNumber());
   8837   CHECK_EQ(1, value->Int32Value());
   8838   CHECK_EQ(42, indexed_access_count);
   8839 
   8840   // Check that the named access check is called when invoking
   8841   // functions on an object that requires access checks.
   8842   CompileRun("obj.f = function() {}");
   8843   CompileRun("function testCallNormal(obj) {"
   8844              "  for (var i = 0; i < 10; i++) obj.f();"
   8845              "}");
   8846   CompileRun("testCallNormal(obj)");
   8847   CHECK_EQ(74, named_access_count);
   8848 
   8849   // Force obj into slow case.
   8850   value = CompileRun("delete obj.prop");
   8851   CHECK(value->BooleanValue());
   8852   // Force inline caches into dictionary probing mode.
   8853   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   8854   // Test that the named access check is called.
   8855   value = CompileRun("testProp(obj);");
   8856   CHECK(value->IsNumber());
   8857   CHECK_EQ(1, value->Int32Value());
   8858   CHECK_EQ(96, named_access_count);
   8859 
   8860   // Force the call inline cache into dictionary probing mode.
   8861   CompileRun("o.f = function() {}; testCallNormal(o)");
   8862   // Test that the named access check is still called for each
   8863   // invocation of the function.
   8864   value = CompileRun("testCallNormal(obj)");
   8865   CHECK_EQ(106, named_access_count);
   8866 
   8867   context1->Exit();
   8868   context0->Exit();
   8869 }
   8870 
   8871 
   8872 static bool NamedAccessFlatten(Local<v8::Object> global,
   8873                                Local<Value> name,
   8874                                v8::AccessType type,
   8875                                Local<Value> data) {
   8876   char buf[100];
   8877   int len;
   8878 
   8879   CHECK(name->IsString());
   8880 
   8881   memset(buf, 0x1, sizeof(buf));
   8882   len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   8883   CHECK_EQ(4, len);
   8884 
   8885   uint16_t buf2[100];
   8886 
   8887   memset(buf, 0x1, sizeof(buf));
   8888   len = name.As<String>()->Write(buf2);
   8889   CHECK_EQ(4, len);
   8890 
   8891   return true;
   8892 }
   8893 
   8894 
   8895 static bool IndexedAccessFlatten(Local<v8::Object> global,
   8896                                  uint32_t key,
   8897                                  v8::AccessType type,
   8898                                  Local<Value> data) {
   8899   return true;
   8900 }
   8901 
   8902 
   8903 // Regression test.  In access checks, operations that may cause
   8904 // garbage collection are not allowed.  It used to be the case that
   8905 // using the Write operation on a string could cause a garbage
   8906 // collection due to flattening of the string.  This is no longer the
   8907 // case.
   8908 THREADED_TEST(AccessControlFlatten) {
   8909   named_access_count = 0;
   8910   indexed_access_count = 0;
   8911 
   8912   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   8913   v8::HandleScope handle_scope(isolate);
   8914 
   8915   // Create an environment.
   8916   v8::Local<Context> context0 = Context::New(isolate);
   8917   context0->Enter();
   8918 
   8919   // Create an object that requires access-check functions to be
   8920   // called for cross-domain access.
   8921   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   8922   object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
   8923                                            IndexedAccessFlatten);
   8924   Local<v8::Object> object = object_template->NewInstance();
   8925 
   8926   v8::HandleScope scope1(isolate);
   8927 
   8928   // Create another environment.
   8929   v8::Local<Context> context1 = Context::New(isolate);
   8930   context1->Enter();
   8931 
   8932   // Make easy access to the object from the other environment.
   8933   v8::Handle<v8::Object> global1 = context1->Global();
   8934   global1->Set(v8_str("obj"), object);
   8935 
   8936   v8::Handle<Value> value;
   8937 
   8938   value = v8_compile("var p = 'as' + 'df';")->Run();
   8939   value = v8_compile("obj[p];")->Run();
   8940 
   8941   context1->Exit();
   8942   context0->Exit();
   8943 }
   8944 
   8945 
   8946 static void AccessControlNamedGetter(
   8947     Local<String>,
   8948     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8949   info.GetReturnValue().Set(42);
   8950 }
   8951 
   8952 
   8953 static void AccessControlNamedSetter(
   8954     Local<String>,
   8955     Local<Value> value,
   8956     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8957   info.GetReturnValue().Set(value);
   8958 }
   8959 
   8960 
   8961 static void AccessControlIndexedGetter(
   8962       uint32_t index,
   8963       const v8::PropertyCallbackInfo<v8::Value>& info) {
   8964   info.GetReturnValue().Set(v8_num(42));
   8965 }
   8966 
   8967 
   8968 static void AccessControlIndexedSetter(
   8969     uint32_t,
   8970     Local<Value> value,
   8971     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8972   info.GetReturnValue().Set(value);
   8973 }
   8974 
   8975 
   8976 THREADED_TEST(AccessControlInterceptorIC) {
   8977   named_access_count = 0;
   8978   indexed_access_count = 0;
   8979 
   8980   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   8981   v8::HandleScope handle_scope(isolate);
   8982 
   8983   // Create an environment.
   8984   v8::Local<Context> context0 = Context::New(isolate);
   8985   context0->Enter();
   8986 
   8987   // Create an object that requires access-check functions to be
   8988   // called for cross-domain access.  The object also has interceptors
   8989   // interceptor.
   8990   v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
   8991   object_template->SetAccessCheckCallbacks(NamedAccessCounter,
   8992                                            IndexedAccessCounter);
   8993   object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
   8994                                            AccessControlNamedSetter);
   8995   object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
   8996                                              AccessControlIndexedSetter);
   8997   Local<v8::Object> object = object_template->NewInstance();
   8998 
   8999   v8::HandleScope scope1(isolate);
   9000 
   9001   // Create another environment.
   9002   v8::Local<Context> context1 = Context::New(isolate);
   9003   context1->Enter();
   9004 
   9005   // Make easy access to the object from the other environment.
   9006   v8::Handle<v8::Object> global1 = context1->Global();
   9007   global1->Set(v8_str("obj"), object);
   9008 
   9009   v8::Handle<Value> value;
   9010 
   9011   // Check that the named access-control function is called every time
   9012   // eventhough there is an interceptor on the object.
   9013   value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
   9014   value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
   9015                      "obj.x")->Run();
   9016   CHECK(value->IsNumber());
   9017   CHECK_EQ(42, value->Int32Value());
   9018   CHECK_EQ(21, named_access_count);
   9019 
   9020   value = v8_compile("var p = 'x';")->Run();
   9021   value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
   9022   value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
   9023                      "obj[p]")->Run();
   9024   CHECK(value->IsNumber());
   9025   CHECK_EQ(42, value->Int32Value());
   9026   CHECK_EQ(42, named_access_count);
   9027 
   9028   // Check that the indexed access-control function is called every
   9029   // time eventhough there is an interceptor on the object.
   9030   value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
   9031   value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
   9032                      "obj[0]")->Run();
   9033   CHECK(value->IsNumber());
   9034   CHECK_EQ(42, value->Int32Value());
   9035   CHECK_EQ(21, indexed_access_count);
   9036 
   9037   context1->Exit();
   9038   context0->Exit();
   9039 }
   9040 
   9041 
   9042 THREADED_TEST(Version) {
   9043   v8::V8::GetVersion();
   9044 }
   9045 
   9046 
   9047 static void InstanceFunctionCallback(
   9048     const v8::FunctionCallbackInfo<v8::Value>& args) {
   9049   ApiTestFuzzer::Fuzz();
   9050   args.GetReturnValue().Set(v8_num(12));
   9051 }
   9052 
   9053 
   9054 THREADED_TEST(InstanceProperties) {
   9055   LocalContext context;
   9056   v8::HandleScope handle_scope(context->GetIsolate());
   9057 
   9058   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9059   Local<ObjectTemplate> instance = t->InstanceTemplate();
   9060 
   9061   instance->Set(v8_str("x"), v8_num(42));
   9062   instance->Set(v8_str("f"),
   9063                 v8::FunctionTemplate::New(InstanceFunctionCallback));
   9064 
   9065   Local<Value> o = t->GetFunction()->NewInstance();
   9066 
   9067   context->Global()->Set(v8_str("i"), o);
   9068   Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
   9069   CHECK_EQ(42, value->Int32Value());
   9070 
   9071   value = Script::Compile(v8_str("i.f()"))->Run();
   9072   CHECK_EQ(12, value->Int32Value());
   9073 }
   9074 
   9075 
   9076 static void GlobalObjectInstancePropertiesGet(
   9077     Local<String> key,
   9078     const v8::PropertyCallbackInfo<v8::Value>&) {
   9079   ApiTestFuzzer::Fuzz();
   9080 }
   9081 
   9082 
   9083 THREADED_TEST(GlobalObjectInstanceProperties) {
   9084   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   9085 
   9086   Local<Value> global_object;
   9087 
   9088   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9089   t->InstanceTemplate()->SetNamedPropertyHandler(
   9090       GlobalObjectInstancePropertiesGet);
   9091   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   9092   instance_template->Set(v8_str("x"), v8_num(42));
   9093   instance_template->Set(v8_str("f"),
   9094                          v8::FunctionTemplate::New(InstanceFunctionCallback));
   9095 
   9096   // The script to check how Crankshaft compiles missing global function
   9097   // invocations.  function g is not defined and should throw on call.
   9098   const char* script =
   9099       "function wrapper(call) {"
   9100       "  var x = 0, y = 1;"
   9101       "  for (var i = 0; i < 1000; i++) {"
   9102       "    x += i * 100;"
   9103       "    y += i * 100;"
   9104       "  }"
   9105       "  if (call) g();"
   9106       "}"
   9107       "for (var i = 0; i < 17; i++) wrapper(false);"
   9108       "var thrown = 0;"
   9109       "try { wrapper(true); } catch (e) { thrown = 1; };"
   9110       "thrown";
   9111 
   9112   {
   9113     LocalContext env(NULL, instance_template);
   9114     // Hold on to the global object so it can be used again in another
   9115     // environment initialization.
   9116     global_object = env->Global();
   9117 
   9118     Local<Value> value = Script::Compile(v8_str("x"))->Run();
   9119     CHECK_EQ(42, value->Int32Value());
   9120     value = Script::Compile(v8_str("f()"))->Run();
   9121     CHECK_EQ(12, value->Int32Value());
   9122     value = Script::Compile(v8_str(script))->Run();
   9123     CHECK_EQ(1, value->Int32Value());
   9124   }
   9125 
   9126   {
   9127     // Create new environment reusing the global object.
   9128     LocalContext env(NULL, instance_template, global_object);
   9129     Local<Value> value = Script::Compile(v8_str("x"))->Run();
   9130     CHECK_EQ(42, value->Int32Value());
   9131     value = Script::Compile(v8_str("f()"))->Run();
   9132     CHECK_EQ(12, value->Int32Value());
   9133     value = Script::Compile(v8_str(script))->Run();
   9134     CHECK_EQ(1, value->Int32Value());
   9135   }
   9136 }
   9137 
   9138 
   9139 THREADED_TEST(CallKnownGlobalReceiver) {
   9140   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   9141 
   9142   Local<Value> global_object;
   9143 
   9144   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9145   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   9146 
   9147   // The script to check that we leave global object not
   9148   // global object proxy on stack when we deoptimize from inside
   9149   // arguments evaluation.
   9150   // To provoke error we need to both force deoptimization
   9151   // from arguments evaluation and to force CallIC to take
   9152   // CallIC_Miss code path that can't cope with global proxy.
   9153   const char* script =
   9154       "function bar(x, y) { try { } finally { } }"
   9155       "function baz(x) { try { } finally { } }"
   9156       "function bom(x) { try { } finally { } }"
   9157       "function foo(x) { bar([x], bom(2)); }"
   9158       "for (var i = 0; i < 10000; i++) foo(1);"
   9159       "foo";
   9160 
   9161   Local<Value> foo;
   9162   {
   9163     LocalContext env(NULL, instance_template);
   9164     // Hold on to the global object so it can be used again in another
   9165     // environment initialization.
   9166     global_object = env->Global();
   9167     foo = Script::Compile(v8_str(script))->Run();
   9168   }
   9169 
   9170   {
   9171     // Create new environment reusing the global object.
   9172     LocalContext env(NULL, instance_template, global_object);
   9173     env->Global()->Set(v8_str("foo"), foo);
   9174     Script::Compile(v8_str("foo()"))->Run();
   9175   }
   9176 }
   9177 
   9178 
   9179 static void ShadowFunctionCallback(
   9180     const v8::FunctionCallbackInfo<v8::Value>& args) {
   9181   ApiTestFuzzer::Fuzz();
   9182   args.GetReturnValue().Set(v8_num(42));
   9183 }
   9184 
   9185 
   9186 static int shadow_y;
   9187 static int shadow_y_setter_call_count;
   9188 static int shadow_y_getter_call_count;
   9189 
   9190 
   9191 static void ShadowYSetter(Local<String>,
   9192                           Local<Value>,
   9193                           const v8::PropertyCallbackInfo<void>&) {
   9194   shadow_y_setter_call_count++;
   9195   shadow_y = 42;
   9196 }
   9197 
   9198 
   9199 static void ShadowYGetter(Local<String> name,
   9200                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   9201   ApiTestFuzzer::Fuzz();
   9202   shadow_y_getter_call_count++;
   9203   info.GetReturnValue().Set(v8_num(shadow_y));
   9204 }
   9205 
   9206 
   9207 static void ShadowIndexedGet(uint32_t index,
   9208                              const v8::PropertyCallbackInfo<v8::Value>&) {
   9209 }
   9210 
   9211 
   9212 static void ShadowNamedGet(Local<String> key,
   9213                            const v8::PropertyCallbackInfo<v8::Value>&) {
   9214 }
   9215 
   9216 
   9217 THREADED_TEST(ShadowObject) {
   9218   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   9219   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   9220 
   9221   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
   9222   LocalContext context(NULL, global_template);
   9223 
   9224   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9225   t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
   9226   t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
   9227   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   9228   Local<ObjectTemplate> instance = t->InstanceTemplate();
   9229 
   9230   proto->Set(v8_str("f"),
   9231              v8::FunctionTemplate::New(ShadowFunctionCallback, Local<Value>()));
   9232   proto->Set(v8_str("x"), v8_num(12));
   9233 
   9234   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   9235 
   9236   Local<Value> o = t->GetFunction()->NewInstance();
   9237   context->Global()->Set(v8_str("__proto__"), o);
   9238 
   9239   Local<Value> value =
   9240       Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
   9241   CHECK(value->IsBoolean());
   9242   CHECK(!value->BooleanValue());
   9243 
   9244   value = Script::Compile(v8_str("x"))->Run();
   9245   CHECK_EQ(12, value->Int32Value());
   9246 
   9247   value = Script::Compile(v8_str("f()"))->Run();
   9248   CHECK_EQ(42, value->Int32Value());
   9249 
   9250   Script::Compile(v8_str("y = 43"))->Run();
   9251   CHECK_EQ(1, shadow_y_setter_call_count);
   9252   value = Script::Compile(v8_str("y"))->Run();
   9253   CHECK_EQ(1, shadow_y_getter_call_count);
   9254   CHECK_EQ(42, value->Int32Value());
   9255 }
   9256 
   9257 
   9258 THREADED_TEST(HiddenPrototype) {
   9259   LocalContext context;
   9260   v8::HandleScope handle_scope(context->GetIsolate());
   9261 
   9262   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
   9263   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   9264   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   9265   t1->SetHiddenPrototype(true);
   9266   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   9267   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   9268   t2->SetHiddenPrototype(true);
   9269   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   9270   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   9271   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   9272 
   9273   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   9274   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   9275   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   9276   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   9277 
   9278   // Setting the prototype on an object skips hidden prototypes.
   9279   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9280   o0->Set(v8_str("__proto__"), o1);
   9281   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9282   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9283   o0->Set(v8_str("__proto__"), o2);
   9284   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9285   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9286   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   9287   o0->Set(v8_str("__proto__"), o3);
   9288   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9289   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9290   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   9291   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   9292 
   9293   // Getting the prototype of o0 should get the first visible one
   9294   // which is o3.  Therefore, z should not be defined on the prototype
   9295   // object.
   9296   Local<Value> proto = o0->Get(v8_str("__proto__"));
   9297   CHECK(proto->IsObject());
   9298   CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
   9299 }
   9300 
   9301 
   9302 THREADED_TEST(HiddenPrototypeSet) {
   9303   LocalContext context;
   9304   v8::HandleScope handle_scope(context->GetIsolate());
   9305 
   9306   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New();
   9307   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New();
   9308   ht->SetHiddenPrototype(true);
   9309   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New();
   9310   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   9311 
   9312   Local<v8::Object> o = ot->GetFunction()->NewInstance();
   9313   Local<v8::Object> h = ht->GetFunction()->NewInstance();
   9314   Local<v8::Object> p = pt->GetFunction()->NewInstance();
   9315   o->Set(v8_str("__proto__"), h);
   9316   h->Set(v8_str("__proto__"), p);
   9317 
   9318   // Setting a property that exists on the hidden prototype goes there.
   9319   o->Set(v8_str("x"), v8_num(7));
   9320   CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
   9321   CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
   9322   CHECK(p->Get(v8_str("x"))->IsUndefined());
   9323 
   9324   // Setting a new property should not be forwarded to the hidden prototype.
   9325   o->Set(v8_str("y"), v8_num(6));
   9326   CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
   9327   CHECK(h->Get(v8_str("y"))->IsUndefined());
   9328   CHECK(p->Get(v8_str("y"))->IsUndefined());
   9329 
   9330   // Setting a property that only exists on a prototype of the hidden prototype
   9331   // is treated normally again.
   9332   p->Set(v8_str("z"), v8_num(8));
   9333   CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
   9334   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
   9335   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
   9336   o->Set(v8_str("z"), v8_num(9));
   9337   CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
   9338   CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
   9339   CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
   9340 }
   9341 
   9342 
   9343 // Regression test for issue 2457.
   9344 THREADED_TEST(HiddenPrototypeIdentityHash) {
   9345   LocalContext context;
   9346   v8::HandleScope handle_scope(context->GetIsolate());
   9347 
   9348   Handle<FunctionTemplate> t = FunctionTemplate::New();
   9349   t->SetHiddenPrototype(true);
   9350   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
   9351   Handle<Object> p = t->GetFunction()->NewInstance();
   9352   Handle<Object> o = Object::New();
   9353   o->SetPrototype(p);
   9354 
   9355   int hash = o->GetIdentityHash();
   9356   USE(hash);
   9357   o->Set(v8_str("foo"), v8_num(42));
   9358   ASSERT_EQ(hash, o->GetIdentityHash());
   9359 }
   9360 
   9361 
   9362 THREADED_TEST(SetPrototype) {
   9363   LocalContext context;
   9364   v8::HandleScope handle_scope(context->GetIsolate());
   9365 
   9366   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
   9367   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   9368   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   9369   t1->SetHiddenPrototype(true);
   9370   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   9371   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   9372   t2->SetHiddenPrototype(true);
   9373   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   9374   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   9375   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   9376 
   9377   Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
   9378   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   9379   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   9380   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   9381 
   9382   // Setting the prototype on an object does not skip hidden prototypes.
   9383   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9384   CHECK(o0->SetPrototype(o1));
   9385   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9386   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9387   CHECK(o1->SetPrototype(o2));
   9388   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9389   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9390   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   9391   CHECK(o2->SetPrototype(o3));
   9392   CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
   9393   CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
   9394   CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
   9395   CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
   9396 
   9397   // Getting the prototype of o0 should get the first visible one
   9398   // which is o3.  Therefore, z should not be defined on the prototype
   9399   // object.
   9400   Local<Value> proto = o0->Get(v8_str("__proto__"));
   9401   CHECK(proto->IsObject());
   9402   CHECK_EQ(proto.As<v8::Object>(), o3);
   9403 
   9404   // However, Object::GetPrototype ignores hidden prototype.
   9405   Local<Value> proto0 = o0->GetPrototype();
   9406   CHECK(proto0->IsObject());
   9407   CHECK_EQ(proto0.As<v8::Object>(), o1);
   9408 
   9409   Local<Value> proto1 = o1->GetPrototype();
   9410   CHECK(proto1->IsObject());
   9411   CHECK_EQ(proto1.As<v8::Object>(), o2);
   9412 
   9413   Local<Value> proto2 = o2->GetPrototype();
   9414   CHECK(proto2->IsObject());
   9415   CHECK_EQ(proto2.As<v8::Object>(), o3);
   9416 }
   9417 
   9418 
   9419 // Getting property names of an object with a prototype chain that
   9420 // triggers dictionary elements in GetLocalPropertyNames() shouldn't
   9421 // crash the runtime.
   9422 THREADED_TEST(Regress91517) {
   9423   i::FLAG_allow_natives_syntax = true;
   9424   LocalContext context;
   9425   v8::HandleScope handle_scope(context->GetIsolate());
   9426 
   9427   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   9428   t1->SetHiddenPrototype(true);
   9429   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   9430   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   9431   t2->SetHiddenPrototype(true);
   9432   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   9433   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New());
   9434   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   9435   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
   9436   t3->SetHiddenPrototype(true);
   9437   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   9438   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
   9439   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   9440 
   9441   // Force dictionary-based properties.
   9442   i::ScopedVector<char> name_buf(1024);
   9443   for (int i = 1; i <= 1000; i++) {
   9444     i::OS::SNPrintF(name_buf, "sdf%d", i);
   9445     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   9446   }
   9447 
   9448   Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
   9449   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   9450   Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
   9451   Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
   9452 
   9453   // Create prototype chain of hidden prototypes.
   9454   CHECK(o4->SetPrototype(o3));
   9455   CHECK(o3->SetPrototype(o2));
   9456   CHECK(o2->SetPrototype(o1));
   9457 
   9458   // Call the runtime version of GetLocalPropertyNames() on the natively
   9459   // created object through JavaScript.
   9460   context->Global()->Set(v8_str("obj"), o4);
   9461   CompileRun("var names = %GetLocalPropertyNames(obj, true);");
   9462 
   9463   ExpectInt32("names.length", 1006);
   9464   ExpectTrue("names.indexOf(\"baz\") >= 0");
   9465   ExpectTrue("names.indexOf(\"boo\") >= 0");
   9466   ExpectTrue("names.indexOf(\"foo\") >= 0");
   9467   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
   9468   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
   9469   ExpectFalse("names[1005] == undefined");
   9470 }
   9471 
   9472 
   9473 THREADED_TEST(FunctionReadOnlyPrototype) {
   9474   LocalContext context;
   9475   v8::HandleScope handle_scope(context->GetIsolate());
   9476 
   9477   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
   9478   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
   9479   t1->ReadOnlyPrototype();
   9480   context->Global()->Set(v8_str("func1"), t1->GetFunction());
   9481   // Configured value of ReadOnly flag.
   9482   CHECK(CompileRun(
   9483       "(function() {"
   9484       "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   9485       "  return (descriptor['writable'] == false);"
   9486       "})()")->BooleanValue());
   9487   CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
   9488   CHECK_EQ(42,
   9489            CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
   9490 
   9491   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
   9492   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
   9493   context->Global()->Set(v8_str("func2"), t2->GetFunction());
   9494   // Default value of ReadOnly flag.
   9495   CHECK(CompileRun(
   9496       "(function() {"
   9497       "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   9498       "  return (descriptor['writable'] == true);"
   9499       "})()")->BooleanValue());
   9500   CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
   9501 }
   9502 
   9503 
   9504 THREADED_TEST(SetPrototypeThrows) {
   9505   LocalContext context;
   9506   v8::HandleScope handle_scope(context->GetIsolate());
   9507 
   9508   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9509 
   9510   Local<v8::Object> o0 = t->GetFunction()->NewInstance();
   9511   Local<v8::Object> o1 = t->GetFunction()->NewInstance();
   9512 
   9513   CHECK(o0->SetPrototype(o1));
   9514   // If setting the prototype leads to the cycle, SetPrototype should
   9515   // return false and keep VM in sane state.
   9516   v8::TryCatch try_catch;
   9517   CHECK(!o1->SetPrototype(o0));
   9518   CHECK(!try_catch.HasCaught());
   9519   ASSERT(!i::Isolate::Current()->has_pending_exception());
   9520 
   9521   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
   9522 }
   9523 
   9524 
   9525 THREADED_TEST(GetterSetterExceptions) {
   9526   LocalContext context;
   9527   v8::HandleScope handle_scope(context->GetIsolate());
   9528   CompileRun(
   9529     "function Foo() { };"
   9530     "function Throw() { throw 5; };"
   9531     "var x = { };"
   9532     "x.__defineSetter__('set', Throw);"
   9533     "x.__defineGetter__('get', Throw);");
   9534   Local<v8::Object> x =
   9535       Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
   9536   v8::TryCatch try_catch;
   9537   x->Set(v8_str("set"), v8::Integer::New(8));
   9538   x->Get(v8_str("get"));
   9539   x->Set(v8_str("set"), v8::Integer::New(8));
   9540   x->Get(v8_str("get"));
   9541   x->Set(v8_str("set"), v8::Integer::New(8));
   9542   x->Get(v8_str("get"));
   9543   x->Set(v8_str("set"), v8::Integer::New(8));
   9544   x->Get(v8_str("get"));
   9545 }
   9546 
   9547 
   9548 THREADED_TEST(Constructor) {
   9549   LocalContext context;
   9550   v8::HandleScope handle_scope(context->GetIsolate());
   9551   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   9552   templ->SetClassName(v8_str("Fun"));
   9553   Local<Function> cons = templ->GetFunction();
   9554   context->Global()->Set(v8_str("Fun"), cons);
   9555   Local<v8::Object> inst = cons->NewInstance();
   9556   i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
   9557   CHECK(obj->IsJSObject());
   9558   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   9559   CHECK(value->BooleanValue());
   9560 }
   9561 
   9562 
   9563 static void ConstructorCallback(
   9564     const v8::FunctionCallbackInfo<v8::Value>& args) {
   9565   ApiTestFuzzer::Fuzz();
   9566   Local<Object> This;
   9567 
   9568   if (args.IsConstructCall()) {
   9569     Local<Object> Holder = args.Holder();
   9570     This = Object::New();
   9571     Local<Value> proto = Holder->GetPrototype();
   9572     if (proto->IsObject()) {
   9573       This->SetPrototype(proto);
   9574     }
   9575   } else {
   9576     This = args.This();
   9577   }
   9578 
   9579   This->Set(v8_str("a"), args[0]);
   9580   args.GetReturnValue().Set(This);
   9581 }
   9582 
   9583 
   9584 static void FakeConstructorCallback(
   9585     const v8::FunctionCallbackInfo<v8::Value>& args) {
   9586   ApiTestFuzzer::Fuzz();
   9587   args.GetReturnValue().Set(args[0]);
   9588 }
   9589 
   9590 
   9591 THREADED_TEST(ConstructorForObject) {
   9592   LocalContext context;
   9593   v8::HandleScope handle_scope(context->GetIsolate());
   9594 
   9595   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   9596     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
   9597     Local<Object> instance = instance_template->NewInstance();
   9598     context->Global()->Set(v8_str("obj"), instance);
   9599     v8::TryCatch try_catch;
   9600     Local<Value> value;
   9601     CHECK(!try_catch.HasCaught());
   9602 
   9603     // Call the Object's constructor with a 32-bit signed integer.
   9604     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
   9605     CHECK(!try_catch.HasCaught());
   9606     CHECK(value->IsInt32());
   9607     CHECK_EQ(28, value->Int32Value());
   9608 
   9609     Local<Value> args1[] = { v8_num(28) };
   9610     Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
   9611     CHECK(value_obj1->IsObject());
   9612     Local<Object> object1 = Local<Object>::Cast(value_obj1);
   9613     value = object1->Get(v8_str("a"));
   9614     CHECK(value->IsInt32());
   9615     CHECK(!try_catch.HasCaught());
   9616     CHECK_EQ(28, value->Int32Value());
   9617 
   9618     // Call the Object's constructor with a String.
   9619     value = CompileRun(
   9620         "(function() { var o = new obj('tipli'); return o.a; })()");
   9621     CHECK(!try_catch.HasCaught());
   9622     CHECK(value->IsString());
   9623     String::Utf8Value string_value1(value->ToString());
   9624     CHECK_EQ("tipli", *string_value1);
   9625 
   9626     Local<Value> args2[] = { v8_str("tipli") };
   9627     Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
   9628     CHECK(value_obj2->IsObject());
   9629     Local<Object> object2 = Local<Object>::Cast(value_obj2);
   9630     value = object2->Get(v8_str("a"));
   9631     CHECK(!try_catch.HasCaught());
   9632     CHECK(value->IsString());
   9633     String::Utf8Value string_value2(value->ToString());
   9634     CHECK_EQ("tipli", *string_value2);
   9635 
   9636     // Call the Object's constructor with a Boolean.
   9637     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
   9638     CHECK(!try_catch.HasCaught());
   9639     CHECK(value->IsBoolean());
   9640     CHECK_EQ(true, value->BooleanValue());
   9641 
   9642     Handle<Value> args3[] = { v8::True() };
   9643     Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
   9644     CHECK(value_obj3->IsObject());
   9645     Local<Object> object3 = Local<Object>::Cast(value_obj3);
   9646     value = object3->Get(v8_str("a"));
   9647     CHECK(!try_catch.HasCaught());
   9648     CHECK(value->IsBoolean());
   9649     CHECK_EQ(true, value->BooleanValue());
   9650 
   9651     // Call the Object's constructor with undefined.
   9652     Handle<Value> args4[] = { v8::Undefined() };
   9653     Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
   9654     CHECK(value_obj4->IsObject());
   9655     Local<Object> object4 = Local<Object>::Cast(value_obj4);
   9656     value = object4->Get(v8_str("a"));
   9657     CHECK(!try_catch.HasCaught());
   9658     CHECK(value->IsUndefined());
   9659 
   9660     // Call the Object's constructor with null.
   9661     Handle<Value> args5[] = { v8::Null() };
   9662     Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
   9663     CHECK(value_obj5->IsObject());
   9664     Local<Object> object5 = Local<Object>::Cast(value_obj5);
   9665     value = object5->Get(v8_str("a"));
   9666     CHECK(!try_catch.HasCaught());
   9667     CHECK(value->IsNull());
   9668   }
   9669 
   9670   // Check exception handling when there is no constructor set for the Object.
   9671   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   9672     Local<Object> instance = instance_template->NewInstance();
   9673     context->Global()->Set(v8_str("obj2"), instance);
   9674     v8::TryCatch try_catch;
   9675     Local<Value> value;
   9676     CHECK(!try_catch.HasCaught());
   9677 
   9678     value = CompileRun("new obj2(28)");
   9679     CHECK(try_catch.HasCaught());
   9680     String::Utf8Value exception_value1(try_catch.Exception());
   9681     CHECK_EQ("TypeError: object is not a function", *exception_value1);
   9682     try_catch.Reset();
   9683 
   9684     Local<Value> args[] = { v8_num(29) };
   9685     value = instance->CallAsConstructor(1, args);
   9686     CHECK(try_catch.HasCaught());
   9687     String::Utf8Value exception_value2(try_catch.Exception());
   9688     CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
   9689     try_catch.Reset();
   9690   }
   9691 
   9692   // Check the case when constructor throws exception.
   9693   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   9694     instance_template->SetCallAsFunctionHandler(ThrowValue);
   9695     Local<Object> instance = instance_template->NewInstance();
   9696     context->Global()->Set(v8_str("obj3"), instance);
   9697     v8::TryCatch try_catch;
   9698     Local<Value> value;
   9699     CHECK(!try_catch.HasCaught());
   9700 
   9701     value = CompileRun("new obj3(22)");
   9702     CHECK(try_catch.HasCaught());
   9703     String::Utf8Value exception_value1(try_catch.Exception());
   9704     CHECK_EQ("22", *exception_value1);
   9705     try_catch.Reset();
   9706 
   9707     Local<Value> args[] = { v8_num(23) };
   9708     value = instance->CallAsConstructor(1, args);
   9709     CHECK(try_catch.HasCaught());
   9710     String::Utf8Value exception_value2(try_catch.Exception());
   9711     CHECK_EQ("23", *exception_value2);
   9712     try_catch.Reset();
   9713   }
   9714 
   9715   // Check whether constructor returns with an object or non-object.
   9716   { Local<FunctionTemplate> function_template =
   9717         FunctionTemplate::New(FakeConstructorCallback);
   9718     Local<Function> function = function_template->GetFunction();
   9719     Local<Object> instance1 = function;
   9720     context->Global()->Set(v8_str("obj4"), instance1);
   9721     v8::TryCatch try_catch;
   9722     Local<Value> value;
   9723     CHECK(!try_catch.HasCaught());
   9724 
   9725     CHECK(instance1->IsObject());
   9726     CHECK(instance1->IsFunction());
   9727 
   9728     value = CompileRun("new obj4(28)");
   9729     CHECK(!try_catch.HasCaught());
   9730     CHECK(value->IsObject());
   9731 
   9732     Local<Value> args1[] = { v8_num(28) };
   9733     value = instance1->CallAsConstructor(1, args1);
   9734     CHECK(!try_catch.HasCaught());
   9735     CHECK(value->IsObject());
   9736 
   9737     Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   9738     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
   9739     Local<Object> instance2 = instance_template->NewInstance();
   9740     context->Global()->Set(v8_str("obj5"), instance2);
   9741     CHECK(!try_catch.HasCaught());
   9742 
   9743     CHECK(instance2->IsObject());
   9744     CHECK(!instance2->IsFunction());
   9745 
   9746     value = CompileRun("new obj5(28)");
   9747     CHECK(!try_catch.HasCaught());
   9748     CHECK(!value->IsObject());
   9749 
   9750     Local<Value> args2[] = { v8_num(28) };
   9751     value = instance2->CallAsConstructor(1, args2);
   9752     CHECK(!try_catch.HasCaught());
   9753     CHECK(!value->IsObject());
   9754   }
   9755 }
   9756 
   9757 
   9758 THREADED_TEST(FunctionDescriptorException) {
   9759   LocalContext context;
   9760   v8::HandleScope handle_scope(context->GetIsolate());
   9761   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   9762   templ->SetClassName(v8_str("Fun"));
   9763   Local<Function> cons = templ->GetFunction();
   9764   context->Global()->Set(v8_str("Fun"), cons);
   9765   Local<Value> value = CompileRun(
   9766     "function test() {"
   9767     "  try {"
   9768     "    (new Fun()).blah()"
   9769     "  } catch (e) {"
   9770     "    var str = String(e);"
   9771     "    if (str.indexOf('TypeError') == -1) return 1;"
   9772     "    if (str.indexOf('[object Fun]') != -1) return 2;"
   9773     "    if (str.indexOf('#<Fun>') == -1) return 3;"
   9774     "    return 0;"
   9775     "  }"
   9776     "  return 4;"
   9777     "}"
   9778     "test();");
   9779   CHECK_EQ(0, value->Int32Value());
   9780 }
   9781 
   9782 
   9783 THREADED_TEST(EvalAliasedDynamic) {
   9784   LocalContext current;
   9785   v8::HandleScope scope(current->GetIsolate());
   9786 
   9787   // Tests where aliased eval can only be resolved dynamically.
   9788   Local<Script> script =
   9789       Script::Compile(v8_str("function f(x) { "
   9790                              "  var foo = 2;"
   9791                              "  with (x) { return eval('foo'); }"
   9792                              "}"
   9793                              "foo = 0;"
   9794                              "result1 = f(new Object());"
   9795                              "result2 = f(this);"
   9796                              "var x = new Object();"
   9797                              "x.eval = function(x) { return 1; };"
   9798                              "result3 = f(x);"));
   9799   script->Run();
   9800   CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
   9801   CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
   9802   CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
   9803 
   9804   v8::TryCatch try_catch;
   9805   script =
   9806     Script::Compile(v8_str("function f(x) { "
   9807                            "  var bar = 2;"
   9808                            "  with (x) { return eval('bar'); }"
   9809                            "}"
   9810                            "result4 = f(this)"));
   9811   script->Run();
   9812   CHECK(!try_catch.HasCaught());
   9813   CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
   9814 
   9815   try_catch.Reset();
   9816 }
   9817 
   9818 
   9819 THREADED_TEST(CrossEval) {
   9820   v8::HandleScope scope(v8::Isolate::GetCurrent());
   9821   LocalContext other;
   9822   LocalContext current;
   9823 
   9824   Local<String> token = v8_str("<security token>");
   9825   other->SetSecurityToken(token);
   9826   current->SetSecurityToken(token);
   9827 
   9828   // Set up reference from current to other.
   9829   current->Global()->Set(v8_str("other"), other->Global());
   9830 
   9831   // Check that new variables are introduced in other context.
   9832   Local<Script> script =
   9833       Script::Compile(v8_str("other.eval('var foo = 1234')"));
   9834   script->Run();
   9835   Local<Value> foo = other->Global()->Get(v8_str("foo"));
   9836   CHECK_EQ(1234, foo->Int32Value());
   9837   CHECK(!current->Global()->Has(v8_str("foo")));
   9838 
   9839   // Check that writing to non-existing properties introduces them in
   9840   // the other context.
   9841   script =
   9842       Script::Compile(v8_str("other.eval('na = 1234')"));
   9843   script->Run();
   9844   CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
   9845   CHECK(!current->Global()->Has(v8_str("na")));
   9846 
   9847   // Check that global variables in current context are not visible in other
   9848   // context.
   9849   v8::TryCatch try_catch;
   9850   script =
   9851       Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
   9852   Local<Value> result = script->Run();
   9853   CHECK(try_catch.HasCaught());
   9854   try_catch.Reset();
   9855 
   9856   // Check that local variables in current context are not visible in other
   9857   // context.
   9858   script =
   9859       Script::Compile(v8_str("(function() { "
   9860                              "  var baz = 87;"
   9861                              "  return other.eval('baz');"
   9862                              "})();"));
   9863   result = script->Run();
   9864   CHECK(try_catch.HasCaught());
   9865   try_catch.Reset();
   9866 
   9867   // Check that global variables in the other environment are visible
   9868   // when evaluting code.
   9869   other->Global()->Set(v8_str("bis"), v8_num(1234));
   9870   script = Script::Compile(v8_str("other.eval('bis')"));
   9871   CHECK_EQ(1234, script->Run()->Int32Value());
   9872   CHECK(!try_catch.HasCaught());
   9873 
   9874   // Check that the 'this' pointer points to the global object evaluating
   9875   // code.
   9876   other->Global()->Set(v8_str("t"), other->Global());
   9877   script = Script::Compile(v8_str("other.eval('this == t')"));
   9878   result = script->Run();
   9879   CHECK(result->IsTrue());
   9880   CHECK(!try_catch.HasCaught());
   9881 
   9882   // Check that variables introduced in with-statement are not visible in
   9883   // other context.
   9884   script =
   9885       Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
   9886   result = script->Run();
   9887   CHECK(try_catch.HasCaught());
   9888   try_catch.Reset();
   9889 
   9890   // Check that you cannot use 'eval.call' with another object than the
   9891   // current global object.
   9892   script =
   9893       Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
   9894   result = script->Run();
   9895   CHECK(try_catch.HasCaught());
   9896 }
   9897 
   9898 
   9899 // Test that calling eval in a context which has been detached from
   9900 // its global throws an exception.  This behavior is consistent with
   9901 // other JavaScript implementations.
   9902 THREADED_TEST(EvalInDetachedGlobal) {
   9903   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   9904   v8::HandleScope scope(isolate);
   9905 
   9906   v8::Local<Context> context0 = Context::New(isolate);
   9907   v8::Local<Context> context1 = Context::New(isolate);
   9908 
   9909   // Set up function in context0 that uses eval from context0.
   9910   context0->Enter();
   9911   v8::Handle<v8::Value> fun =
   9912       CompileRun("var x = 42;"
   9913                  "(function() {"
   9914                  "  var e = eval;"
   9915                  "  return function(s) { return e(s); }"
   9916                  "})()");
   9917   context0->Exit();
   9918 
   9919   // Put the function into context1 and call it before and after
   9920   // detaching the global.  Before detaching, the call succeeds and
   9921   // after detaching and exception is thrown.
   9922   context1->Enter();
   9923   context1->Global()->Set(v8_str("fun"), fun);
   9924   v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
   9925   CHECK_EQ(42, x_value->Int32Value());
   9926   context0->DetachGlobal();
   9927   v8::TryCatch catcher;
   9928   x_value = CompileRun("fun('x')");
   9929   CHECK(x_value.IsEmpty());
   9930   CHECK(catcher.HasCaught());
   9931   context1->Exit();
   9932 }
   9933 
   9934 
   9935 THREADED_TEST(CrossLazyLoad) {
   9936   v8::HandleScope scope(v8::Isolate::GetCurrent());
   9937   LocalContext other;
   9938   LocalContext current;
   9939 
   9940   Local<String> token = v8_str("<security token>");
   9941   other->SetSecurityToken(token);
   9942   current->SetSecurityToken(token);
   9943 
   9944   // Set up reference from current to other.
   9945   current->Global()->Set(v8_str("other"), other->Global());
   9946 
   9947   // Trigger lazy loading in other context.
   9948   Local<Script> script =
   9949       Script::Compile(v8_str("other.eval('new Date(42)')"));
   9950   Local<Value> value = script->Run();
   9951   CHECK_EQ(42.0, value->NumberValue());
   9952 }
   9953 
   9954 
   9955 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
   9956   ApiTestFuzzer::Fuzz();
   9957   if (args.IsConstructCall()) {
   9958     if (args[0]->IsInt32()) {
   9959       args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
   9960       return;
   9961     }
   9962   }
   9963 
   9964   args.GetReturnValue().Set(args[0]);
   9965 }
   9966 
   9967 
   9968 // Test that a call handler can be set for objects which will allow
   9969 // non-function objects created through the API to be called as
   9970 // functions.
   9971 THREADED_TEST(CallAsFunction) {
   9972   LocalContext context;
   9973   v8::HandleScope scope(context->GetIsolate());
   9974 
   9975   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   9976     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   9977     instance_template->SetCallAsFunctionHandler(call_as_function);
   9978     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   9979     context->Global()->Set(v8_str("obj"), instance);
   9980     v8::TryCatch try_catch;
   9981     Local<Value> value;
   9982     CHECK(!try_catch.HasCaught());
   9983 
   9984     value = CompileRun("obj(42)");
   9985     CHECK(!try_catch.HasCaught());
   9986     CHECK_EQ(42, value->Int32Value());
   9987 
   9988     value = CompileRun("(function(o){return o(49)})(obj)");
   9989     CHECK(!try_catch.HasCaught());
   9990     CHECK_EQ(49, value->Int32Value());
   9991 
   9992     // test special case of call as function
   9993     value = CompileRun("[obj]['0'](45)");
   9994     CHECK(!try_catch.HasCaught());
   9995     CHECK_EQ(45, value->Int32Value());
   9996 
   9997     value = CompileRun("obj.call = Function.prototype.call;"
   9998                        "obj.call(null, 87)");
   9999     CHECK(!try_catch.HasCaught());
   10000     CHECK_EQ(87, value->Int32Value());
   10001 
   10002     // Regression tests for bug #1116356: Calling call through call/apply
   10003     // must work for non-function receivers.
   10004     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   10005     value = CompileRun(apply_99);
   10006     CHECK(!try_catch.HasCaught());
   10007     CHECK_EQ(99, value->Int32Value());
   10008 
   10009     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   10010     value = CompileRun(call_17);
   10011     CHECK(!try_catch.HasCaught());
   10012     CHECK_EQ(17, value->Int32Value());
   10013 
   10014     // Check that the call-as-function handler can be called through
   10015     // new.
   10016     value = CompileRun("new obj(43)");
   10017     CHECK(!try_catch.HasCaught());
   10018     CHECK_EQ(-43, value->Int32Value());
   10019 
   10020     // Check that the call-as-function handler can be called through
   10021     // the API.
   10022     v8::Handle<Value> args[] = { v8_num(28) };
   10023     value = instance->CallAsFunction(instance, 1, args);
   10024     CHECK(!try_catch.HasCaught());
   10025     CHECK_EQ(28, value->Int32Value());
   10026   }
   10027 
   10028   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   10029     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   10030     USE(instance_template);
   10031     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   10032     context->Global()->Set(v8_str("obj2"), instance);
   10033     v8::TryCatch try_catch;
   10034     Local<Value> value;
   10035     CHECK(!try_catch.HasCaught());
   10036 
   10037     // Call an object without call-as-function handler through the JS
   10038     value = CompileRun("obj2(28)");
   10039     CHECK(value.IsEmpty());
   10040     CHECK(try_catch.HasCaught());
   10041     String::Utf8Value exception_value1(try_catch.Exception());
   10042     CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
   10043              *exception_value1);
   10044     try_catch.Reset();
   10045 
   10046     // Call an object without call-as-function handler through the API
   10047     value = CompileRun("obj2(28)");
   10048     v8::Handle<Value> args[] = { v8_num(28) };
   10049     value = instance->CallAsFunction(instance, 1, args);
   10050     CHECK(value.IsEmpty());
   10051     CHECK(try_catch.HasCaught());
   10052     String::Utf8Value exception_value2(try_catch.Exception());
   10053     CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
   10054     try_catch.Reset();
   10055   }
   10056 
   10057   { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   10058     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10059     instance_template->SetCallAsFunctionHandler(ThrowValue);
   10060     Local<v8::Object> instance = t->GetFunction()->NewInstance();
   10061     context->Global()->Set(v8_str("obj3"), instance);
   10062     v8::TryCatch try_catch;
   10063     Local<Value> value;
   10064     CHECK(!try_catch.HasCaught());
   10065 
   10066     // Catch the exception which is thrown by call-as-function handler
   10067     value = CompileRun("obj3(22)");
   10068     CHECK(try_catch.HasCaught());
   10069     String::Utf8Value exception_value1(try_catch.Exception());
   10070     CHECK_EQ("22", *exception_value1);
   10071     try_catch.Reset();
   10072 
   10073     v8::Handle<Value> args[] = { v8_num(23) };
   10074     value = instance->CallAsFunction(instance, 1, args);
   10075     CHECK(try_catch.HasCaught());
   10076     String::Utf8Value exception_value2(try_catch.Exception());
   10077     CHECK_EQ("23", *exception_value2);
   10078     try_catch.Reset();
   10079   }
   10080 }
   10081 
   10082 
   10083 // Check whether a non-function object is callable.
   10084 THREADED_TEST(CallableObject) {
   10085   LocalContext context;
   10086   v8::HandleScope scope(context->GetIsolate());
   10087 
   10088   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   10089     instance_template->SetCallAsFunctionHandler(call_as_function);
   10090     Local<Object> instance = instance_template->NewInstance();
   10091     v8::TryCatch try_catch;
   10092 
   10093     CHECK(instance->IsCallable());
   10094     CHECK(!try_catch.HasCaught());
   10095   }
   10096 
   10097   { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
   10098     Local<Object> instance = instance_template->NewInstance();
   10099     v8::TryCatch try_catch;
   10100 
   10101     CHECK(!instance->IsCallable());
   10102     CHECK(!try_catch.HasCaught());
   10103   }
   10104 
   10105   { Local<FunctionTemplate> function_template =
   10106         FunctionTemplate::New(call_as_function);
   10107     Local<Function> function = function_template->GetFunction();
   10108     Local<Object> instance = function;
   10109     v8::TryCatch try_catch;
   10110 
   10111     CHECK(instance->IsCallable());
   10112     CHECK(!try_catch.HasCaught());
   10113   }
   10114 
   10115   { Local<FunctionTemplate> function_template = FunctionTemplate::New();
   10116     Local<Function> function = function_template->GetFunction();
   10117     Local<Object> instance = function;
   10118     v8::TryCatch try_catch;
   10119 
   10120     CHECK(instance->IsCallable());
   10121     CHECK(!try_catch.HasCaught());
   10122   }
   10123 }
   10124 
   10125 
   10126 static int CountHandles() {
   10127   return v8::HandleScope::NumberOfHandles();
   10128 }
   10129 
   10130 
   10131 static int Recurse(int depth, int iterations) {
   10132   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10133   if (depth == 0) return CountHandles();
   10134   for (int i = 0; i < iterations; i++) {
   10135     Local<v8::Number> n(v8::Integer::New(42));
   10136   }
   10137   return Recurse(depth - 1, iterations);
   10138 }
   10139 
   10140 
   10141 THREADED_TEST(HandleIteration) {
   10142   static const int kIterations = 500;
   10143   static const int kNesting = 200;
   10144   CHECK_EQ(0, CountHandles());
   10145   {
   10146     v8::HandleScope scope1(v8::Isolate::GetCurrent());
   10147     CHECK_EQ(0, CountHandles());
   10148     for (int i = 0; i < kIterations; i++) {
   10149       Local<v8::Number> n(v8::Integer::New(42));
   10150       CHECK_EQ(i + 1, CountHandles());
   10151     }
   10152 
   10153     CHECK_EQ(kIterations, CountHandles());
   10154     {
   10155       v8::HandleScope scope2(v8::Isolate::GetCurrent());
   10156       for (int j = 0; j < kIterations; j++) {
   10157         Local<v8::Number> n(v8::Integer::New(42));
   10158         CHECK_EQ(j + 1 + kIterations, CountHandles());
   10159       }
   10160     }
   10161     CHECK_EQ(kIterations, CountHandles());
   10162   }
   10163   CHECK_EQ(0, CountHandles());
   10164   CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
   10165 }
   10166 
   10167 
   10168 static void InterceptorHasOwnPropertyGetter(
   10169     Local<String> name,
   10170     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10171   ApiTestFuzzer::Fuzz();
   10172 }
   10173 
   10174 
   10175 THREADED_TEST(InterceptorHasOwnProperty) {
   10176   LocalContext context;
   10177   v8::HandleScope scope(context->GetIsolate());
   10178   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   10179   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   10180   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
   10181   Local<Function> function = fun_templ->GetFunction();
   10182   context->Global()->Set(v8_str("constructor"), function);
   10183   v8::Handle<Value> value = CompileRun(
   10184       "var o = new constructor();"
   10185       "o.hasOwnProperty('ostehaps');");
   10186   CHECK_EQ(false, value->BooleanValue());
   10187   value = CompileRun(
   10188       "o.ostehaps = 42;"
   10189       "o.hasOwnProperty('ostehaps');");
   10190   CHECK_EQ(true, value->BooleanValue());
   10191   value = CompileRun(
   10192       "var p = new constructor();"
   10193       "p.hasOwnProperty('ostehaps');");
   10194   CHECK_EQ(false, value->BooleanValue());
   10195 }
   10196 
   10197 
   10198 static void InterceptorHasOwnPropertyGetterGC(
   10199     Local<String> name,
   10200     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10201   ApiTestFuzzer::Fuzz();
   10202   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   10203 }
   10204 
   10205 
   10206 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
   10207   LocalContext context;
   10208   v8::HandleScope scope(context->GetIsolate());
   10209   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   10210   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
   10211   instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
   10212   Local<Function> function = fun_templ->GetFunction();
   10213   context->Global()->Set(v8_str("constructor"), function);
   10214   // Let's first make some stuff so we can be sure to get a good GC.
   10215   CompileRun(
   10216       "function makestr(size) {"
   10217       "  switch (size) {"
   10218       "    case 1: return 'f';"
   10219       "    case 2: return 'fo';"
   10220       "    case 3: return 'foo';"
   10221       "  }"
   10222       "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
   10223       "}"
   10224       "var x = makestr(12345);"
   10225       "x = makestr(31415);"
   10226       "x = makestr(23456);");
   10227   v8::Handle<Value> value = CompileRun(
   10228       "var o = new constructor();"
   10229       "o.__proto__ = new String(x);"
   10230       "o.hasOwnProperty('ostehaps');");
   10231   CHECK_EQ(false, value->BooleanValue());
   10232 }
   10233 
   10234 
   10235 typedef void (*NamedPropertyGetter)(
   10236     Local<String> property,
   10237     const v8::PropertyCallbackInfo<v8::Value>& info);
   10238 
   10239 
   10240 static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
   10241                                    const char* source,
   10242                                    int expected) {
   10243   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10244   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10245   templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
   10246   LocalContext context;
   10247   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10248   v8::Handle<Value> value = CompileRun(source);
   10249   CHECK_EQ(expected, value->Int32Value());
   10250 }
   10251 
   10252 
   10253 static void InterceptorLoadICGetter(
   10254     Local<String> name,
   10255     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10256   ApiTestFuzzer::Fuzz();
   10257   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   10258   CHECK_EQ(isolate, info.GetIsolate());
   10259   CHECK_EQ(v8_str("data"), info.Data());
   10260   CHECK_EQ(v8_str("x"), name);
   10261   info.GetReturnValue().Set(v8::Integer::New(42));
   10262 }
   10263 
   10264 
   10265 // This test should hit the load IC for the interceptor case.
   10266 THREADED_TEST(InterceptorLoadIC) {
   10267   CheckInterceptorLoadIC(InterceptorLoadICGetter,
   10268     "var result = 0;"
   10269     "for (var i = 0; i < 1000; i++) {"
   10270     "  result = o.x;"
   10271     "}",
   10272     42);
   10273 }
   10274 
   10275 
   10276 // Below go several tests which verify that JITing for various
   10277 // configurations of interceptor and explicit fields works fine
   10278 // (those cases are special cased to get better performance).
   10279 
   10280 static void InterceptorLoadXICGetter(
   10281     Local<String> name,
   10282     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10283   ApiTestFuzzer::Fuzz();
   10284   info.GetReturnValue().Set(
   10285       v8_str("x")->Equals(name) ?
   10286           v8::Handle<v8::Value>(v8::Integer::New(42)) :
   10287           v8::Handle<v8::Value>());
   10288 }
   10289 
   10290 
   10291 THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
   10292   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10293     "var result = 0;"
   10294     "o.y = 239;"
   10295     "for (var i = 0; i < 1000; i++) {"
   10296     "  result = o.y;"
   10297     "}",
   10298     239);
   10299 }
   10300 
   10301 
   10302 THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
   10303   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10304     "var result = 0;"
   10305     "o.__proto__ = { 'y': 239 };"
   10306     "for (var i = 0; i < 1000; i++) {"
   10307     "  result = o.y + o.x;"
   10308     "}",
   10309     239 + 42);
   10310 }
   10311 
   10312 
   10313 THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
   10314   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10315     "var result = 0;"
   10316     "o.__proto__.y = 239;"
   10317     "for (var i = 0; i < 1000; i++) {"
   10318     "  result = o.y + o.x;"
   10319     "}",
   10320     239 + 42);
   10321 }
   10322 
   10323 
   10324 THREADED_TEST(InterceptorLoadICUndefined) {
   10325   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10326     "var result = 0;"
   10327     "for (var i = 0; i < 1000; i++) {"
   10328     "  result = (o.y == undefined) ? 239 : 42;"
   10329     "}",
   10330     239);
   10331 }
   10332 
   10333 
   10334 THREADED_TEST(InterceptorLoadICWithOverride) {
   10335   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10336     "fst = new Object();  fst.__proto__ = o;"
   10337     "snd = new Object();  snd.__proto__ = fst;"
   10338     "var result1 = 0;"
   10339     "for (var i = 0; i < 1000;  i++) {"
   10340     "  result1 = snd.x;"
   10341     "}"
   10342     "fst.x = 239;"
   10343     "var result = 0;"
   10344     "for (var i = 0; i < 1000; i++) {"
   10345     "  result = snd.x;"
   10346     "}"
   10347     "result + result1",
   10348     239 + 42);
   10349 }
   10350 
   10351 
   10352 // Test the case when we stored field into
   10353 // a stub, but interceptor produced value on its own.
   10354 THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
   10355   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10356     "proto = new Object();"
   10357     "o.__proto__ = proto;"
   10358     "proto.x = 239;"
   10359     "for (var i = 0; i < 1000; i++) {"
   10360     "  o.x;"
   10361     // Now it should be ICed and keep a reference to x defined on proto
   10362     "}"
   10363     "var result = 0;"
   10364     "for (var i = 0; i < 1000; i++) {"
   10365     "  result += o.x;"
   10366     "}"
   10367     "result;",
   10368     42 * 1000);
   10369 }
   10370 
   10371 
   10372 // Test the case when we stored field into
   10373 // a stub, but it got invalidated later on.
   10374 THREADED_TEST(InterceptorLoadICInvalidatedField) {
   10375   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10376     "proto1 = new Object();"
   10377     "proto2 = new Object();"
   10378     "o.__proto__ = proto1;"
   10379     "proto1.__proto__ = proto2;"
   10380     "proto2.y = 239;"
   10381     "for (var i = 0; i < 1000; i++) {"
   10382     "  o.y;"
   10383     // Now it should be ICed and keep a reference to y defined on proto2
   10384     "}"
   10385     "proto1.y = 42;"
   10386     "var result = 0;"
   10387     "for (var i = 0; i < 1000; i++) {"
   10388     "  result += o.y;"
   10389     "}"
   10390     "result;",
   10391     42 * 1000);
   10392 }
   10393 
   10394 
   10395 static int interceptor_load_not_handled_calls = 0;
   10396 static void InterceptorLoadNotHandled(
   10397     Local<String> name,
   10398     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10399   ++interceptor_load_not_handled_calls;
   10400 }
   10401 
   10402 
   10403 // Test how post-interceptor lookups are done in the non-cacheable
   10404 // case: the interceptor should not be invoked during this lookup.
   10405 THREADED_TEST(InterceptorLoadICPostInterceptor) {
   10406   interceptor_load_not_handled_calls = 0;
   10407   CheckInterceptorLoadIC(InterceptorLoadNotHandled,
   10408     "receiver = new Object();"
   10409     "receiver.__proto__ = o;"
   10410     "proto = new Object();"
   10411     "/* Make proto a slow-case object. */"
   10412     "for (var i = 0; i < 1000; i++) {"
   10413     "  proto[\"xxxxxxxx\" + i] = [];"
   10414     "}"
   10415     "proto.x = 17;"
   10416     "o.__proto__ = proto;"
   10417     "var result = 0;"
   10418     "for (var i = 0; i < 1000; i++) {"
   10419     "  result += receiver.x;"
   10420     "}"
   10421     "result;",
   10422     17 * 1000);
   10423   CHECK_EQ(1000, interceptor_load_not_handled_calls);
   10424 }
   10425 
   10426 
   10427 // Test the case when we stored field into
   10428 // a stub, but it got invalidated later on due to override on
   10429 // global object which is between interceptor and fields' holders.
   10430 THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
   10431   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
   10432     "o.__proto__ = this;"  // set a global to be a proto of o.
   10433     "this.__proto__.y = 239;"
   10434     "for (var i = 0; i < 10; i++) {"
   10435     "  if (o.y != 239) throw 'oops: ' + o.y;"
   10436     // Now it should be ICed and keep a reference to y defined on field_holder.
   10437     "}"
   10438     "this.y = 42;"  // Assign on a global.
   10439     "var result = 0;"
   10440     "for (var i = 0; i < 10; i++) {"
   10441     "  result += o.y;"
   10442     "}"
   10443     "result;",
   10444     42 * 10);
   10445 }
   10446 
   10447 
   10448 static void SetOnThis(Local<String> name,
   10449                       Local<Value> value,
   10450                       const v8::PropertyCallbackInfo<void>& info) {
   10451   info.This()->ForceSet(name, value);
   10452 }
   10453 
   10454 
   10455 THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
   10456   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10457   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10458   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   10459   templ->SetAccessor(v8_str("y"), Return239Callback);
   10460   LocalContext context;
   10461   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10462 
   10463   // Check the case when receiver and interceptor's holder
   10464   // are the same objects.
   10465   v8::Handle<Value> value = CompileRun(
   10466       "var result = 0;"
   10467       "for (var i = 0; i < 7; i++) {"
   10468       "  result = o.y;"
   10469       "}");
   10470   CHECK_EQ(239, value->Int32Value());
   10471 
   10472   // Check the case when interceptor's holder is in proto chain
   10473   // of receiver.
   10474   value = CompileRun(
   10475       "r = { __proto__: o };"
   10476       "var result = 0;"
   10477       "for (var i = 0; i < 7; i++) {"
   10478       "  result = r.y;"
   10479       "}");
   10480   CHECK_EQ(239, value->Int32Value());
   10481 }
   10482 
   10483 
   10484 THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
   10485   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10486   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   10487   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   10488   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   10489   templ_p->SetAccessor(v8_str("y"), Return239Callback);
   10490 
   10491   LocalContext context;
   10492   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   10493   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   10494 
   10495   // Check the case when receiver and interceptor's holder
   10496   // are the same objects.
   10497   v8::Handle<Value> value = CompileRun(
   10498       "o.__proto__ = p;"
   10499       "var result = 0;"
   10500       "for (var i = 0; i < 7; i++) {"
   10501       "  result = o.x + o.y;"
   10502       "}");
   10503   CHECK_EQ(239 + 42, value->Int32Value());
   10504 
   10505   // Check the case when interceptor's holder is in proto chain
   10506   // of receiver.
   10507   value = CompileRun(
   10508       "r = { __proto__: o };"
   10509       "var result = 0;"
   10510       "for (var i = 0; i < 7; i++) {"
   10511       "  result = r.x + r.y;"
   10512       "}");
   10513   CHECK_EQ(239 + 42, value->Int32Value());
   10514 }
   10515 
   10516 
   10517 THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
   10518   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10519   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10520   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   10521   templ->SetAccessor(v8_str("y"), Return239Callback);
   10522 
   10523   LocalContext context;
   10524   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10525 
   10526   v8::Handle<Value> value = CompileRun(
   10527     "fst = new Object();  fst.__proto__ = o;"
   10528     "snd = new Object();  snd.__proto__ = fst;"
   10529     "var result1 = 0;"
   10530     "for (var i = 0; i < 7;  i++) {"
   10531     "  result1 = snd.x;"
   10532     "}"
   10533     "fst.x = 239;"
   10534     "var result = 0;"
   10535     "for (var i = 0; i < 7; i++) {"
   10536     "  result = snd.x;"
   10537     "}"
   10538     "result + result1");
   10539   CHECK_EQ(239 + 42, value->Int32Value());
   10540 }
   10541 
   10542 
   10543 // Test the case when we stored callback into
   10544 // a stub, but interceptor produced value on its own.
   10545 THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
   10546   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10547   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   10548   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   10549   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   10550   templ_p->SetAccessor(v8_str("y"), Return239Callback);
   10551 
   10552   LocalContext context;
   10553   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   10554   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   10555 
   10556   v8::Handle<Value> value = CompileRun(
   10557     "o.__proto__ = p;"
   10558     "for (var i = 0; i < 7; i++) {"
   10559     "  o.x;"
   10560     // Now it should be ICed and keep a reference to x defined on p
   10561     "}"
   10562     "var result = 0;"
   10563     "for (var i = 0; i < 7; i++) {"
   10564     "  result += o.x;"
   10565     "}"
   10566     "result");
   10567   CHECK_EQ(42 * 7, value->Int32Value());
   10568 }
   10569 
   10570 
   10571 // Test the case when we stored callback into
   10572 // a stub, but it got invalidated later on.
   10573 THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
   10574   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10575   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   10576   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   10577   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   10578   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
   10579 
   10580   LocalContext context;
   10581   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   10582   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   10583 
   10584   v8::Handle<Value> value = CompileRun(
   10585     "inbetween = new Object();"
   10586     "o.__proto__ = inbetween;"
   10587     "inbetween.__proto__ = p;"
   10588     "for (var i = 0; i < 10; i++) {"
   10589     "  o.y;"
   10590     // Now it should be ICed and keep a reference to y defined on p
   10591     "}"
   10592     "inbetween.y = 42;"
   10593     "var result = 0;"
   10594     "for (var i = 0; i < 10; i++) {"
   10595     "  result += o.y;"
   10596     "}"
   10597     "result");
   10598   CHECK_EQ(42 * 10, value->Int32Value());
   10599 }
   10600 
   10601 
   10602 // Test the case when we stored callback into
   10603 // a stub, but it got invalidated later on due to override on
   10604 // global object which is between interceptor and callbacks' holders.
   10605 THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
   10606   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10607   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   10608   templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   10609   v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
   10610   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
   10611 
   10612   LocalContext context;
   10613   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   10614   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
   10615 
   10616   v8::Handle<Value> value = CompileRun(
   10617     "o.__proto__ = this;"
   10618     "this.__proto__ = p;"
   10619     "for (var i = 0; i < 10; i++) {"
   10620     "  if (o.y != 239) throw 'oops: ' + o.y;"
   10621     // Now it should be ICed and keep a reference to y defined on p
   10622     "}"
   10623     "this.y = 42;"
   10624     "var result = 0;"
   10625     "for (var i = 0; i < 10; i++) {"
   10626     "  result += o.y;"
   10627     "}"
   10628     "result");
   10629   CHECK_EQ(42 * 10, value->Int32Value());
   10630 }
   10631 
   10632 
   10633 static void InterceptorLoadICGetter0(
   10634     Local<String> name,
   10635     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10636   ApiTestFuzzer::Fuzz();
   10637   CHECK(v8_str("x")->Equals(name));
   10638   info.GetReturnValue().Set(v8::Integer::New(0));
   10639 }
   10640 
   10641 
   10642 THREADED_TEST(InterceptorReturningZero) {
   10643   CheckInterceptorLoadIC(InterceptorLoadICGetter0,
   10644      "o.x == undefined ? 1 : 0",
   10645      0);
   10646 }
   10647 
   10648 
   10649 static void InterceptorStoreICSetter(
   10650     Local<String> key,
   10651     Local<Value> value,
   10652     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10653   CHECK(v8_str("x")->Equals(key));
   10654   CHECK_EQ(42, value->Int32Value());
   10655   info.GetReturnValue().Set(value);
   10656 }
   10657 
   10658 
   10659 // This test should hit the store IC for the interceptor case.
   10660 THREADED_TEST(InterceptorStoreIC) {
   10661   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10662   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10663   templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
   10664                                  InterceptorStoreICSetter,
   10665                                  0, 0, 0, v8_str("data"));
   10666   LocalContext context;
   10667   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10668   CompileRun(
   10669       "for (var i = 0; i < 1000; i++) {"
   10670       "  o.x = 42;"
   10671       "}");
   10672 }
   10673 
   10674 
   10675 THREADED_TEST(InterceptorStoreICWithNoSetter) {
   10676   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10677   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10678   templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   10679   LocalContext context;
   10680   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10681   v8::Handle<Value> value = CompileRun(
   10682     "for (var i = 0; i < 1000; i++) {"
   10683     "  o.y = 239;"
   10684     "}"
   10685     "42 + o.y");
   10686   CHECK_EQ(239 + 42, value->Int32Value());
   10687 }
   10688 
   10689 
   10690 
   10691 
   10692 v8::Handle<Value> call_ic_function;
   10693 v8::Handle<Value> call_ic_function2;
   10694 v8::Handle<Value> call_ic_function3;
   10695 
   10696 static void InterceptorCallICGetter(
   10697     Local<String> name,
   10698     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10699   ApiTestFuzzer::Fuzz();
   10700   CHECK(v8_str("x")->Equals(name));
   10701   info.GetReturnValue().Set(call_ic_function);
   10702 }
   10703 
   10704 
   10705 // This test should hit the call IC for the interceptor case.
   10706 THREADED_TEST(InterceptorCallIC) {
   10707   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10708   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10709   templ->SetNamedPropertyHandler(InterceptorCallICGetter);
   10710   LocalContext context;
   10711   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10712   call_ic_function =
   10713       v8_compile("function f(x) { return x + 1; }; f")->Run();
   10714   v8::Handle<Value> value = CompileRun(
   10715     "var result = 0;"
   10716     "for (var i = 0; i < 1000; i++) {"
   10717     "  result = o.x(41);"
   10718     "}");
   10719   CHECK_EQ(42, value->Int32Value());
   10720 }
   10721 
   10722 
   10723 // This test checks that if interceptor doesn't provide
   10724 // a value, we can fetch regular value.
   10725 THREADED_TEST(InterceptorCallICSeesOthers) {
   10726   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10727   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10728   templ->SetNamedPropertyHandler(NoBlockGetterX);
   10729   LocalContext context;
   10730   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10731   v8::Handle<Value> value = CompileRun(
   10732     "o.x = function f(x) { return x + 1; };"
   10733     "var result = 0;"
   10734     "for (var i = 0; i < 7; i++) {"
   10735     "  result = o.x(41);"
   10736     "}");
   10737   CHECK_EQ(42, value->Int32Value());
   10738 }
   10739 
   10740 
   10741 static v8::Handle<Value> call_ic_function4;
   10742 static void InterceptorCallICGetter4(
   10743     Local<String> name,
   10744     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10745   ApiTestFuzzer::Fuzz();
   10746   CHECK(v8_str("x")->Equals(name));
   10747   info.GetReturnValue().Set(call_ic_function4);
   10748 }
   10749 
   10750 
   10751 // This test checks that if interceptor provides a function,
   10752 // even if we cached shadowed variant, interceptor's function
   10753 // is invoked
   10754 THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
   10755   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10756   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10757   templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
   10758   LocalContext context;
   10759   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10760   call_ic_function4 =
   10761       v8_compile("function f(x) { return x - 1; }; f")->Run();
   10762   v8::Handle<Value> value = CompileRun(
   10763     "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
   10764     "var result = 0;"
   10765     "for (var i = 0; i < 1000; i++) {"
   10766     "  result = o.x(42);"
   10767     "}");
   10768   CHECK_EQ(41, value->Int32Value());
   10769 }
   10770 
   10771 
   10772 // Test the case when we stored cacheable lookup into
   10773 // a stub, but it got invalidated later on
   10774 THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
   10775   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10776   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10777   templ->SetNamedPropertyHandler(NoBlockGetterX);
   10778   LocalContext context;
   10779   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10780   v8::Handle<Value> value = CompileRun(
   10781     "proto1 = new Object();"
   10782     "proto2 = new Object();"
   10783     "o.__proto__ = proto1;"
   10784     "proto1.__proto__ = proto2;"
   10785     "proto2.y = function(x) { return x + 1; };"
   10786     // Invoke it many times to compile a stub
   10787     "for (var i = 0; i < 7; i++) {"
   10788     "  o.y(42);"
   10789     "}"
   10790     "proto1.y = function(x) { return x - 1; };"
   10791     "var result = 0;"
   10792     "for (var i = 0; i < 7; i++) {"
   10793     "  result += o.y(42);"
   10794     "}");
   10795   CHECK_EQ(41 * 7, value->Int32Value());
   10796 }
   10797 
   10798 
   10799 // This test checks that if interceptor doesn't provide a function,
   10800 // cached constant function is used
   10801 THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
   10802   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10803   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10804   templ->SetNamedPropertyHandler(NoBlockGetterX);
   10805   LocalContext context;
   10806   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10807   v8::Handle<Value> value = CompileRun(
   10808     "function inc(x) { return x + 1; };"
   10809     "inc(1);"
   10810     "o.x = inc;"
   10811     "var result = 0;"
   10812     "for (var i = 0; i < 1000; i++) {"
   10813     "  result = o.x(42);"
   10814     "}");
   10815   CHECK_EQ(43, value->Int32Value());
   10816 }
   10817 
   10818 
   10819 static v8::Handle<Value> call_ic_function5;
   10820 static void InterceptorCallICGetter5(
   10821     Local<String> name,
   10822     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10823   ApiTestFuzzer::Fuzz();
   10824   if (v8_str("x")->Equals(name))
   10825     info.GetReturnValue().Set(call_ic_function5);
   10826 }
   10827 
   10828 
   10829 // This test checks that if interceptor provides a function,
   10830 // even if we cached constant function, interceptor's function
   10831 // is invoked
   10832 THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
   10833   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10834   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10835   templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
   10836   LocalContext context;
   10837   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10838   call_ic_function5 =
   10839       v8_compile("function f(x) { return x - 1; }; f")->Run();
   10840   v8::Handle<Value> value = CompileRun(
   10841     "function inc(x) { return x + 1; };"
   10842     "inc(1);"
   10843     "o.x = inc;"
   10844     "var result = 0;"
   10845     "for (var i = 0; i < 1000; i++) {"
   10846     "  result = o.x(42);"
   10847     "}");
   10848   CHECK_EQ(41, value->Int32Value());
   10849 }
   10850 
   10851 
   10852 static v8::Handle<Value> call_ic_function6;
   10853 static void InterceptorCallICGetter6(
   10854     Local<String> name,
   10855     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10856   ApiTestFuzzer::Fuzz();
   10857   if (v8_str("x")->Equals(name))
   10858     info.GetReturnValue().Set(call_ic_function6);
   10859 }
   10860 
   10861 
   10862 // Same test as above, except the code is wrapped in a function
   10863 // to test the optimized compiler.
   10864 THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
   10865   i::FLAG_allow_natives_syntax = true;
   10866   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10867   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10868   templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
   10869   LocalContext context;
   10870   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10871   call_ic_function6 =
   10872       v8_compile("function f(x) { return x - 1; }; f")->Run();
   10873   v8::Handle<Value> value = CompileRun(
   10874     "function inc(x) { return x + 1; };"
   10875     "inc(1);"
   10876     "o.x = inc;"
   10877     "function test() {"
   10878     "  var result = 0;"
   10879     "  for (var i = 0; i < 1000; i++) {"
   10880     "    result = o.x(42);"
   10881     "  }"
   10882     "  return result;"
   10883     "};"
   10884     "test();"
   10885     "test();"
   10886     "test();"
   10887     "%OptimizeFunctionOnNextCall(test);"
   10888     "test()");
   10889   CHECK_EQ(41, value->Int32Value());
   10890 }
   10891 
   10892 
   10893 // Test the case when we stored constant function into
   10894 // a stub, but it got invalidated later on
   10895 THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
   10896   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10897   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10898   templ->SetNamedPropertyHandler(NoBlockGetterX);
   10899   LocalContext context;
   10900   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10901   v8::Handle<Value> value = CompileRun(
   10902     "function inc(x) { return x + 1; };"
   10903     "inc(1);"
   10904     "proto1 = new Object();"
   10905     "proto2 = new Object();"
   10906     "o.__proto__ = proto1;"
   10907     "proto1.__proto__ = proto2;"
   10908     "proto2.y = inc;"
   10909     // Invoke it many times to compile a stub
   10910     "for (var i = 0; i < 7; i++) {"
   10911     "  o.y(42);"
   10912     "}"
   10913     "proto1.y = function(x) { return x - 1; };"
   10914     "var result = 0;"
   10915     "for (var i = 0; i < 7; i++) {"
   10916     "  result += o.y(42);"
   10917     "}");
   10918   CHECK_EQ(41 * 7, value->Int32Value());
   10919 }
   10920 
   10921 
   10922 // Test the case when we stored constant function into
   10923 // a stub, but it got invalidated later on due to override on
   10924 // global object which is between interceptor and constant function' holders.
   10925 THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
   10926   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10927   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   10928   templ->SetNamedPropertyHandler(NoBlockGetterX);
   10929   LocalContext context;
   10930   context->Global()->Set(v8_str("o"), templ->NewInstance());
   10931   v8::Handle<Value> value = CompileRun(
   10932     "function inc(x) { return x + 1; };"
   10933     "inc(1);"
   10934     "o.__proto__ = this;"
   10935     "this.__proto__.y = inc;"
   10936     // Invoke it many times to compile a stub
   10937     "for (var i = 0; i < 7; i++) {"
   10938     "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
   10939     "}"
   10940     "this.y = function(x) { return x - 1; };"
   10941     "var result = 0;"
   10942     "for (var i = 0; i < 7; i++) {"
   10943     "  result += o.y(42);"
   10944     "}");
   10945   CHECK_EQ(41 * 7, value->Int32Value());
   10946 }
   10947 
   10948 
   10949 // Test the case when actual function to call sits on global object.
   10950 THREADED_TEST(InterceptorCallICCachedFromGlobal) {
   10951   v8::HandleScope scope(v8::Isolate::GetCurrent());
   10952   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   10953   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   10954 
   10955   LocalContext context;
   10956   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   10957 
   10958   v8::Handle<Value> value = CompileRun(
   10959     "try {"
   10960     "  o.__proto__ = this;"
   10961     "  for (var i = 0; i < 10; i++) {"
   10962     "    var v = o.parseFloat('239');"
   10963     "    if (v != 239) throw v;"
   10964       // Now it should be ICed and keep a reference to parseFloat.
   10965     "  }"
   10966     "  var result = 0;"
   10967     "  for (var i = 0; i < 10; i++) {"
   10968     "    result += o.parseFloat('239');"
   10969     "  }"
   10970     "  result"
   10971     "} catch(e) {"
   10972     "  e"
   10973     "};");
   10974   CHECK_EQ(239 * 10, value->Int32Value());
   10975 }
   10976 
   10977 static void InterceptorCallICFastApi(
   10978     Local<String> name,
   10979     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10980   ApiTestFuzzer::Fuzz();
   10981   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
   10982   int* call_count =
   10983       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
   10984   ++(*call_count);
   10985   if ((*call_count) % 20 == 0) {
   10986     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   10987   }
   10988 }
   10989 
   10990 static void FastApiCallback_TrivialSignature(
   10991     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10992   ApiTestFuzzer::Fuzz();
   10993   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
   10994   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   10995   CHECK_EQ(isolate, args.GetIsolate());
   10996   CHECK_EQ(args.This(), args.Holder());
   10997   CHECK(args.Data()->Equals(v8_str("method_data")));
   10998   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
   10999 }
   11000 
   11001 static void FastApiCallback_SimpleSignature(
   11002     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11003   ApiTestFuzzer::Fuzz();
   11004   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
   11005   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   11006   CHECK_EQ(isolate, args.GetIsolate());
   11007   CHECK_EQ(args.This()->GetPrototype(), args.Holder());
   11008   CHECK(args.Data()->Equals(v8_str("method_data")));
   11009   // Note, we're using HasRealNamedProperty instead of Has to avoid
   11010   // invoking the interceptor again.
   11011   CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
   11012   args.GetReturnValue().Set(args[0]->Int32Value() + 1);
   11013 }
   11014 
   11015 
   11016 // Helper to maximize the odds of object moving.
   11017 static void GenerateSomeGarbage() {
   11018   CompileRun(
   11019       "var garbage;"
   11020       "for (var i = 0; i < 1000; i++) {"
   11021       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   11022       "}"
   11023       "garbage = undefined;");
   11024 }
   11025 
   11026 
   11027 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11028   static int count = 0;
   11029   if (count++ % 3 == 0) {
   11030     HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   11031         // This should move the stub
   11032     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   11033   }
   11034 }
   11035 
   11036 
   11037 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   11038   LocalContext context;
   11039   v8::HandleScope scope(context->GetIsolate());
   11040   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
   11041   nativeobject_templ->Set("callback",
   11042                           v8::FunctionTemplate::New(DirectApiCallback));
   11043   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   11044   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   11045   // call the api function multiple times to ensure direct call stub creation.
   11046   CompileRun(
   11047         "function f() {"
   11048         "  for (var i = 1; i <= 30; i++) {"
   11049         "    nativeobject.callback();"
   11050         "  }"
   11051         "}"
   11052         "f();");
   11053 }
   11054 
   11055 
   11056 void ThrowingDirectApiCallback(
   11057     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11058   v8::ThrowException(v8_str("g"));
   11059 }
   11060 
   11061 
   11062 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   11063   LocalContext context;
   11064   v8::HandleScope scope(context->GetIsolate());
   11065   v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
   11066   nativeobject_templ->Set("callback",
   11067                           v8::FunctionTemplate::New(ThrowingDirectApiCallback));
   11068   v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
   11069   context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
   11070   // call the api function multiple times to ensure direct call stub creation.
   11071   v8::Handle<Value> result = CompileRun(
   11072       "var result = '';"
   11073       "function f() {"
   11074       "  for (var i = 1; i <= 5; i++) {"
   11075       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   11076       "  }"
   11077       "}"
   11078       "f(); result;");
   11079   CHECK_EQ(v8_str("ggggg"), result);
   11080 }
   11081 
   11082 
   11083 static Handle<Value> DoDirectGetter() {
   11084   if (++p_getter_count % 3 == 0) {
   11085     HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   11086     GenerateSomeGarbage();
   11087   }
   11088   return v8_str("Direct Getter Result");
   11089 }
   11090 
   11091 static void DirectGetterCallback(
   11092     Local<String> name,
   11093     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11094   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
   11095   info.GetReturnValue().Set(DoDirectGetter());
   11096 }
   11097 
   11098 
   11099 template<typename Accessor>
   11100 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
   11101   LocalContext context;
   11102   v8::HandleScope scope(context->GetIsolate());
   11103   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
   11104   obj->SetAccessor(v8_str("p1"), accessor);
   11105   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   11106   p_getter_count = 0;
   11107   v8::Handle<v8::Value> result = CompileRun(
   11108       "function f() {"
   11109       "  for (var i = 0; i < 30; i++) o1.p1;"
   11110       "  return o1.p1"
   11111       "}"
   11112       "f();");
   11113   CHECK_EQ(v8_str("Direct Getter Result"), result);
   11114   CHECK_EQ(31, p_getter_count);
   11115 }
   11116 
   11117 
   11118 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   11119   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
   11120 }
   11121 
   11122 
   11123 void ThrowingDirectGetterCallback(
   11124     Local<String> name,
   11125     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11126   v8::ThrowException(v8_str("g"));
   11127 }
   11128 
   11129 
   11130 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   11131   LocalContext context;
   11132   v8::HandleScope scope(context->GetIsolate());
   11133   v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
   11134   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   11135   context->Global()->Set(v8_str("o1"), obj->NewInstance());
   11136   v8::Handle<Value> result = CompileRun(
   11137       "var result = '';"
   11138       "for (var i = 0; i < 5; i++) {"
   11139       "    try { o1.p1; } catch (e) { result += e; }"
   11140       "}"
   11141       "result;");
   11142   CHECK_EQ(v8_str("ggggg"), result);
   11143 }
   11144 
   11145 
   11146 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   11147   int interceptor_call_count = 0;
   11148   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11149   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11150   v8::Handle<v8::FunctionTemplate> method_templ =
   11151       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
   11152                                 v8_str("method_data"),
   11153                                 v8::Handle<v8::Signature>());
   11154   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11155   proto_templ->Set(v8_str("method"), method_templ);
   11156   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11157   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   11158                                  NULL, NULL, NULL, NULL,
   11159                                  v8::External::New(&interceptor_call_count));
   11160   LocalContext context;
   11161   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11162   GenerateSomeGarbage();
   11163   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11164   CompileRun(
   11165       "var result = 0;"
   11166       "for (var i = 0; i < 100; i++) {"
   11167       "  result = o.method(41);"
   11168       "}");
   11169   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   11170   CHECK_EQ(100, interceptor_call_count);
   11171 }
   11172 
   11173 
   11174 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
   11175   int interceptor_call_count = 0;
   11176   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11177   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11178   v8::Handle<v8::FunctionTemplate> method_templ =
   11179       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   11180                                 v8_str("method_data"),
   11181                                 v8::Signature::New(fun_templ));
   11182   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11183   proto_templ->Set(v8_str("method"), method_templ);
   11184   fun_templ->SetHiddenPrototype(true);
   11185   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11186   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   11187                                  NULL, NULL, NULL, NULL,
   11188                                  v8::External::New(&interceptor_call_count));
   11189   LocalContext context;
   11190   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11191   GenerateSomeGarbage();
   11192   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11193   CompileRun(
   11194       "o.foo = 17;"
   11195       "var receiver = {};"
   11196       "receiver.__proto__ = o;"
   11197       "var result = 0;"
   11198       "for (var i = 0; i < 100; i++) {"
   11199       "  result = receiver.method(41);"
   11200       "}");
   11201   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   11202   CHECK_EQ(100, interceptor_call_count);
   11203 }
   11204 
   11205 
   11206 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
   11207   int interceptor_call_count = 0;
   11208   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11209   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11210   v8::Handle<v8::FunctionTemplate> method_templ =
   11211       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   11212                                 v8_str("method_data"),
   11213                                 v8::Signature::New(fun_templ));
   11214   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11215   proto_templ->Set(v8_str("method"), method_templ);
   11216   fun_templ->SetHiddenPrototype(true);
   11217   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11218   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   11219                                  NULL, NULL, NULL, NULL,
   11220                                  v8::External::New(&interceptor_call_count));
   11221   LocalContext context;
   11222   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11223   GenerateSomeGarbage();
   11224   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11225   CompileRun(
   11226       "o.foo = 17;"
   11227       "var receiver = {};"
   11228       "receiver.__proto__ = o;"
   11229       "var result = 0;"
   11230       "var saved_result = 0;"
   11231       "for (var i = 0; i < 100; i++) {"
   11232       "  result = receiver.method(41);"
   11233       "  if (i == 50) {"
   11234       "    saved_result = result;"
   11235       "    receiver = {method: function(x) { return x - 1 }};"
   11236       "  }"
   11237       "}");
   11238   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   11239   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11240   CHECK_GE(interceptor_call_count, 50);
   11241 }
   11242 
   11243 
   11244 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
   11245   int interceptor_call_count = 0;
   11246   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11247   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11248   v8::Handle<v8::FunctionTemplate> method_templ =
   11249       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   11250                                 v8_str("method_data"),
   11251                                 v8::Signature::New(fun_templ));
   11252   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11253   proto_templ->Set(v8_str("method"), method_templ);
   11254   fun_templ->SetHiddenPrototype(true);
   11255   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11256   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   11257                                  NULL, NULL, NULL, NULL,
   11258                                  v8::External::New(&interceptor_call_count));
   11259   LocalContext context;
   11260   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11261   GenerateSomeGarbage();
   11262   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11263   CompileRun(
   11264       "o.foo = 17;"
   11265       "var receiver = {};"
   11266       "receiver.__proto__ = o;"
   11267       "var result = 0;"
   11268       "var saved_result = 0;"
   11269       "for (var i = 0; i < 100; i++) {"
   11270       "  result = receiver.method(41);"
   11271       "  if (i == 50) {"
   11272       "    saved_result = result;"
   11273       "    o.method = function(x) { return x - 1 };"
   11274       "  }"
   11275       "}");
   11276   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   11277   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11278   CHECK_GE(interceptor_call_count, 50);
   11279 }
   11280 
   11281 
   11282 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
   11283   int interceptor_call_count = 0;
   11284   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11285   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11286   v8::Handle<v8::FunctionTemplate> method_templ =
   11287       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   11288                                 v8_str("method_data"),
   11289                                 v8::Signature::New(fun_templ));
   11290   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11291   proto_templ->Set(v8_str("method"), method_templ);
   11292   fun_templ->SetHiddenPrototype(true);
   11293   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11294   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   11295                                  NULL, NULL, NULL, NULL,
   11296                                  v8::External::New(&interceptor_call_count));
   11297   LocalContext context;
   11298   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11299   GenerateSomeGarbage();
   11300   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11301   v8::TryCatch try_catch;
   11302   CompileRun(
   11303       "o.foo = 17;"
   11304       "var receiver = {};"
   11305       "receiver.__proto__ = o;"
   11306       "var result = 0;"
   11307       "var saved_result = 0;"
   11308       "for (var i = 0; i < 100; i++) {"
   11309       "  result = receiver.method(41);"
   11310       "  if (i == 50) {"
   11311       "    saved_result = result;"
   11312       "    receiver = 333;"
   11313       "  }"
   11314       "}");
   11315   CHECK(try_catch.HasCaught());
   11316   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
   11317            try_catch.Exception()->ToString());
   11318   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11319   CHECK_GE(interceptor_call_count, 50);
   11320 }
   11321 
   11322 
   11323 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
   11324   int interceptor_call_count = 0;
   11325   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11326   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11327   v8::Handle<v8::FunctionTemplate> method_templ =
   11328       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   11329                                 v8_str("method_data"),
   11330                                 v8::Signature::New(fun_templ));
   11331   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11332   proto_templ->Set(v8_str("method"), method_templ);
   11333   fun_templ->SetHiddenPrototype(true);
   11334   v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   11335   templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
   11336                                  NULL, NULL, NULL, NULL,
   11337                                  v8::External::New(&interceptor_call_count));
   11338   LocalContext context;
   11339   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11340   GenerateSomeGarbage();
   11341   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11342   v8::TryCatch try_catch;
   11343   CompileRun(
   11344       "o.foo = 17;"
   11345       "var receiver = {};"
   11346       "receiver.__proto__ = o;"
   11347       "var result = 0;"
   11348       "var saved_result = 0;"
   11349       "for (var i = 0; i < 100; i++) {"
   11350       "  result = receiver.method(41);"
   11351       "  if (i == 50) {"
   11352       "    saved_result = result;"
   11353       "    receiver = {method: receiver.method};"
   11354       "  }"
   11355       "}");
   11356   CHECK(try_catch.HasCaught());
   11357   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
   11358            try_catch.Exception()->ToString());
   11359   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11360   CHECK_GE(interceptor_call_count, 50);
   11361 }
   11362 
   11363 
   11364 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   11365   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11366   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11367   v8::Handle<v8::FunctionTemplate> method_templ =
   11368       v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
   11369                                 v8_str("method_data"),
   11370                                 v8::Handle<v8::Signature>());
   11371   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11372   proto_templ->Set(v8_str("method"), method_templ);
   11373   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   11374   USE(templ);
   11375   LocalContext context;
   11376   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11377   GenerateSomeGarbage();
   11378   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11379   CompileRun(
   11380       "var result = 0;"
   11381       "for (var i = 0; i < 100; i++) {"
   11382       "  result = o.method(41);"
   11383       "}");
   11384 
   11385   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   11386 }
   11387 
   11388 
   11389 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
   11390   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11391   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11392   v8::Handle<v8::FunctionTemplate> method_templ =
   11393       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   11394                                 v8_str("method_data"),
   11395                                 v8::Signature::New(fun_templ));
   11396   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11397   proto_templ->Set(v8_str("method"), method_templ);
   11398   fun_templ->SetHiddenPrototype(true);
   11399   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   11400   CHECK(!templ.IsEmpty());
   11401   LocalContext context;
   11402   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11403   GenerateSomeGarbage();
   11404   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11405   CompileRun(
   11406       "o.foo = 17;"
   11407       "var receiver = {};"
   11408       "receiver.__proto__ = o;"
   11409       "var result = 0;"
   11410       "for (var i = 0; i < 100; i++) {"
   11411       "  result = receiver.method(41);"
   11412       "}");
   11413 
   11414   CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
   11415 }
   11416 
   11417 
   11418 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   11419   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11420   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11421   v8::Handle<v8::FunctionTemplate> method_templ =
   11422       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   11423                                 v8_str("method_data"),
   11424                                 v8::Signature::New(fun_templ));
   11425   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11426   proto_templ->Set(v8_str("method"), method_templ);
   11427   fun_templ->SetHiddenPrototype(true);
   11428   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   11429   CHECK(!templ.IsEmpty());
   11430   LocalContext context;
   11431   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11432   GenerateSomeGarbage();
   11433   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11434   CompileRun(
   11435       "o.foo = 17;"
   11436       "var receiver = {};"
   11437       "receiver.__proto__ = o;"
   11438       "var result = 0;"
   11439       "var saved_result = 0;"
   11440       "for (var i = 0; i < 100; i++) {"
   11441       "  result = receiver.method(41);"
   11442       "  if (i == 50) {"
   11443       "    saved_result = result;"
   11444       "    receiver = {method: function(x) { return x - 1 }};"
   11445       "  }"
   11446       "}");
   11447   CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
   11448   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11449 }
   11450 
   11451 
   11452 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   11453   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11454   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11455   v8::Handle<v8::FunctionTemplate> method_templ =
   11456       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   11457                                 v8_str("method_data"),
   11458                                 v8::Signature::New(fun_templ));
   11459   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11460   proto_templ->Set(v8_str("method"), method_templ);
   11461   fun_templ->SetHiddenPrototype(true);
   11462   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   11463   CHECK(!templ.IsEmpty());
   11464   LocalContext context;
   11465   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11466   GenerateSomeGarbage();
   11467   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11468   v8::TryCatch try_catch;
   11469   CompileRun(
   11470       "o.foo = 17;"
   11471       "var receiver = {};"
   11472       "receiver.__proto__ = o;"
   11473       "var result = 0;"
   11474       "var saved_result = 0;"
   11475       "for (var i = 0; i < 100; i++) {"
   11476       "  result = receiver.method(41);"
   11477       "  if (i == 50) {"
   11478       "    saved_result = result;"
   11479       "    receiver = 333;"
   11480       "  }"
   11481       "}");
   11482   CHECK(try_catch.HasCaught());
   11483   CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
   11484            try_catch.Exception()->ToString());
   11485   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11486 }
   11487 
   11488 
   11489 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
   11490   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11491   v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   11492   v8::Handle<v8::FunctionTemplate> method_templ =
   11493       v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
   11494                                 v8_str("method_data"),
   11495                                 v8::Signature::New(fun_templ));
   11496   v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   11497   proto_templ->Set(v8_str("method"), method_templ);
   11498   fun_templ->SetHiddenPrototype(true);
   11499   v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   11500   CHECK(!templ.IsEmpty());
   11501   LocalContext context;
   11502   v8::Handle<v8::Function> fun = fun_templ->GetFunction();
   11503   GenerateSomeGarbage();
   11504   context->Global()->Set(v8_str("o"), fun->NewInstance());
   11505   v8::TryCatch try_catch;
   11506   CompileRun(
   11507       "o.foo = 17;"
   11508       "var receiver = {};"
   11509       "receiver.__proto__ = o;"
   11510       "var result = 0;"
   11511       "var saved_result = 0;"
   11512       "for (var i = 0; i < 100; i++) {"
   11513       "  result = receiver.method(41);"
   11514       "  if (i == 50) {"
   11515       "    saved_result = result;"
   11516       "    receiver = Object.create(receiver);"
   11517       "  }"
   11518       "}");
   11519   CHECK(try_catch.HasCaught());
   11520   CHECK_EQ(v8_str("TypeError: Illegal invocation"),
   11521            try_catch.Exception()->ToString());
   11522   CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11523 }
   11524 
   11525 
   11526 v8::Handle<Value> keyed_call_ic_function;
   11527 
   11528 static void InterceptorKeyedCallICGetter(
   11529     Local<String> name,
   11530     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11531   ApiTestFuzzer::Fuzz();
   11532   if (v8_str("x")->Equals(name)) {
   11533     info.GetReturnValue().Set(keyed_call_ic_function);
   11534   }
   11535 }
   11536 
   11537 
   11538 // Test the case when we stored cacheable lookup into
   11539 // a stub, but the function name changed (to another cacheable function).
   11540 THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
   11541   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11542   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11543   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11544   LocalContext context;
   11545   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11546   CompileRun(
   11547     "proto = new Object();"
   11548     "proto.y = function(x) { return x + 1; };"
   11549     "proto.z = function(x) { return x - 1; };"
   11550     "o.__proto__ = proto;"
   11551     "var result = 0;"
   11552     "var method = 'y';"
   11553     "for (var i = 0; i < 10; i++) {"
   11554     "  if (i == 5) { method = 'z'; };"
   11555     "  result += o[method](41);"
   11556     "}");
   11557   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   11558 }
   11559 
   11560 
   11561 // Test the case when we stored cacheable lookup into
   11562 // a stub, but the function name changed (and the new function is present
   11563 // both before and after the interceptor in the prototype chain).
   11564 THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
   11565   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11566   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11567   templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
   11568   LocalContext context;
   11569   context->Global()->Set(v8_str("proto1"), templ->NewInstance());
   11570   keyed_call_ic_function =
   11571       v8_compile("function f(x) { return x - 1; }; f")->Run();
   11572   CompileRun(
   11573     "o = new Object();"
   11574     "proto2 = new Object();"
   11575     "o.y = function(x) { return x + 1; };"
   11576     "proto2.y = function(x) { return x + 2; };"
   11577     "o.__proto__ = proto1;"
   11578     "proto1.__proto__ = proto2;"
   11579     "var result = 0;"
   11580     "var method = 'x';"
   11581     "for (var i = 0; i < 10; i++) {"
   11582     "  if (i == 5) { method = 'y'; };"
   11583     "  result += o[method](41);"
   11584     "}");
   11585   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   11586 }
   11587 
   11588 
   11589 // Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
   11590 // on the global object.
   11591 THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
   11592   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11593   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11594   templ->SetNamedPropertyHandler(NoBlockGetterX);
   11595   LocalContext context;
   11596   context->Global()->Set(v8_str("o"), templ->NewInstance());
   11597   CompileRun(
   11598     "function inc(x) { return x + 1; };"
   11599     "inc(1);"
   11600     "function dec(x) { return x - 1; };"
   11601     "dec(1);"
   11602     "o.__proto__ = this;"
   11603     "this.__proto__.x = inc;"
   11604     "this.__proto__.y = dec;"
   11605     "var result = 0;"
   11606     "var method = 'x';"
   11607     "for (var i = 0; i < 10; i++) {"
   11608     "  if (i == 5) { method = 'y'; };"
   11609     "  result += o[method](41);"
   11610     "}");
   11611   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   11612 }
   11613 
   11614 
   11615 // Test the case when actual function to call sits on global object.
   11616 THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
   11617   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11618   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   11619   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   11620   LocalContext context;
   11621   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11622 
   11623   CompileRun(
   11624     "function len(x) { return x.length; };"
   11625     "o.__proto__ = this;"
   11626     "var m = 'parseFloat';"
   11627     "var result = 0;"
   11628     "for (var i = 0; i < 10; i++) {"
   11629     "  if (i == 5) {"
   11630     "    m = 'len';"
   11631     "    saved_result = result;"
   11632     "  };"
   11633     "  result = o[m]('239');"
   11634     "}");
   11635   CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
   11636   CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
   11637 }
   11638 
   11639 
   11640 // Test the map transition before the interceptor.
   11641 THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
   11642   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11643   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   11644   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   11645   LocalContext context;
   11646   context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
   11647 
   11648   CompileRun(
   11649     "var o = new Object();"
   11650     "o.__proto__ = proto;"
   11651     "o.method = function(x) { return x + 1; };"
   11652     "var m = 'method';"
   11653     "var result = 0;"
   11654     "for (var i = 0; i < 10; i++) {"
   11655     "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
   11656     "  result += o[m](41);"
   11657     "}");
   11658   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   11659 }
   11660 
   11661 
   11662 // Test the map transition after the interceptor.
   11663 THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
   11664   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11665   v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
   11666   templ_o->SetNamedPropertyHandler(NoBlockGetterX);
   11667   LocalContext context;
   11668   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   11669 
   11670   CompileRun(
   11671     "var proto = new Object();"
   11672     "o.__proto__ = proto;"
   11673     "proto.method = function(x) { return x + 1; };"
   11674     "var m = 'method';"
   11675     "var result = 0;"
   11676     "for (var i = 0; i < 10; i++) {"
   11677     "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
   11678     "  result += o[m](41);"
   11679     "}");
   11680   CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
   11681 }
   11682 
   11683 
   11684 static int interceptor_call_count = 0;
   11685 
   11686 static void InterceptorICRefErrorGetter(
   11687     Local<String> name,
   11688     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11689   ApiTestFuzzer::Fuzz();
   11690   if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
   11691     info.GetReturnValue().Set(call_ic_function2);
   11692   }
   11693 }
   11694 
   11695 
   11696 // This test should hit load and call ICs for the interceptor case.
   11697 // Once in a while, the interceptor will reply that a property was not
   11698 // found in which case we should get a reference error.
   11699 THREADED_TEST(InterceptorICReferenceErrors) {
   11700   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11701   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11702   templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
   11703   LocalContext context(0, templ, v8::Handle<Value>());
   11704   call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
   11705   v8::Handle<Value> value = CompileRun(
   11706     "function f() {"
   11707     "  for (var i = 0; i < 1000; i++) {"
   11708     "    try { x; } catch(e) { return true; }"
   11709     "  }"
   11710     "  return false;"
   11711     "};"
   11712     "f();");
   11713   CHECK_EQ(true, value->BooleanValue());
   11714   interceptor_call_count = 0;
   11715   value = CompileRun(
   11716     "function g() {"
   11717     "  for (var i = 0; i < 1000; i++) {"
   11718     "    try { x(42); } catch(e) { return true; }"
   11719     "  }"
   11720     "  return false;"
   11721     "};"
   11722     "g();");
   11723   CHECK_EQ(true, value->BooleanValue());
   11724 }
   11725 
   11726 
   11727 static int interceptor_ic_exception_get_count = 0;
   11728 
   11729 static void InterceptorICExceptionGetter(
   11730     Local<String> name,
   11731     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11732   ApiTestFuzzer::Fuzz();
   11733   if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
   11734     info.GetReturnValue().Set(call_ic_function3);
   11735   }
   11736   if (interceptor_ic_exception_get_count == 20) {
   11737     v8::ThrowException(v8_num(42));
   11738     return;
   11739   }
   11740 }
   11741 
   11742 
   11743 // Test interceptor load/call IC where the interceptor throws an
   11744 // exception once in a while.
   11745 THREADED_TEST(InterceptorICGetterExceptions) {
   11746   interceptor_ic_exception_get_count = 0;
   11747   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11748   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11749   templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
   11750   LocalContext context(0, templ, v8::Handle<Value>());
   11751   call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
   11752   v8::Handle<Value> value = CompileRun(
   11753     "function f() {"
   11754     "  for (var i = 0; i < 100; i++) {"
   11755     "    try { x; } catch(e) { return true; }"
   11756     "  }"
   11757     "  return false;"
   11758     "};"
   11759     "f();");
   11760   CHECK_EQ(true, value->BooleanValue());
   11761   interceptor_ic_exception_get_count = 0;
   11762   value = CompileRun(
   11763     "function f() {"
   11764     "  for (var i = 0; i < 100; i++) {"
   11765     "    try { x(42); } catch(e) { return true; }"
   11766     "  }"
   11767     "  return false;"
   11768     "};"
   11769     "f();");
   11770   CHECK_EQ(true, value->BooleanValue());
   11771 }
   11772 
   11773 
   11774 static int interceptor_ic_exception_set_count = 0;
   11775 
   11776 static void InterceptorICExceptionSetter(
   11777       Local<String> key,
   11778       Local<Value> value,
   11779       const v8::PropertyCallbackInfo<v8::Value>& info) {
   11780   ApiTestFuzzer::Fuzz();
   11781   if (++interceptor_ic_exception_set_count > 20) {
   11782     v8::ThrowException(v8_num(42));
   11783   }
   11784 }
   11785 
   11786 
   11787 // Test interceptor store IC where the interceptor throws an exception
   11788 // once in a while.
   11789 THREADED_TEST(InterceptorICSetterExceptions) {
   11790   interceptor_ic_exception_set_count = 0;
   11791   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11792   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11793   templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
   11794   LocalContext context(0, templ, v8::Handle<Value>());
   11795   v8::Handle<Value> value = CompileRun(
   11796     "function f() {"
   11797     "  for (var i = 0; i < 100; i++) {"
   11798     "    try { x = 42; } catch(e) { return true; }"
   11799     "  }"
   11800     "  return false;"
   11801     "};"
   11802     "f();");
   11803   CHECK_EQ(true, value->BooleanValue());
   11804 }
   11805 
   11806 
   11807 // Test that we ignore null interceptors.
   11808 THREADED_TEST(NullNamedInterceptor) {
   11809   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11810   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11811   templ->SetNamedPropertyHandler(
   11812       static_cast<v8::NamedPropertyGetterCallback>(0));
   11813   LocalContext context;
   11814   templ->Set("x", v8_num(42));
   11815   v8::Handle<v8::Object> obj = templ->NewInstance();
   11816   context->Global()->Set(v8_str("obj"), obj);
   11817   v8::Handle<Value> value = CompileRun("obj.x");
   11818   CHECK(value->IsInt32());
   11819   CHECK_EQ(42, value->Int32Value());
   11820 }
   11821 
   11822 
   11823 // Test that we ignore null interceptors.
   11824 THREADED_TEST(NullIndexedInterceptor) {
   11825   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11826   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   11827   templ->SetIndexedPropertyHandler(
   11828       static_cast<v8::IndexedPropertyGetterCallback>(0));
   11829   LocalContext context;
   11830   templ->Set("42", v8_num(42));
   11831   v8::Handle<v8::Object> obj = templ->NewInstance();
   11832   context->Global()->Set(v8_str("obj"), obj);
   11833   v8::Handle<Value> value = CompileRun("obj[42]");
   11834   CHECK(value->IsInt32());
   11835   CHECK_EQ(42, value->Int32Value());
   11836 }
   11837 
   11838 
   11839 THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
   11840   v8::HandleScope scope(v8::Isolate::GetCurrent());
   11841   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   11842   templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
   11843   LocalContext env;
   11844   env->Global()->Set(v8_str("obj"),
   11845                      templ->GetFunction()->NewInstance());
   11846   ExpectTrue("obj.x === 42");
   11847   ExpectTrue("!obj.propertyIsEnumerable('x')");
   11848 }
   11849 
   11850 
   11851 static void ThrowingGetter(Local<String> name,
   11852                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   11853   ApiTestFuzzer::Fuzz();
   11854   ThrowException(Handle<Value>());
   11855   info.GetReturnValue().SetUndefined();
   11856 }
   11857 
   11858 
   11859 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   11860   LocalContext context;
   11861   HandleScope scope(context->GetIsolate());
   11862 
   11863   Local<FunctionTemplate> templ = FunctionTemplate::New();
   11864   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   11865   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   11866 
   11867   Local<Object> instance = templ->GetFunction()->NewInstance();
   11868 
   11869   Local<Object> another = Object::New();
   11870   another->SetPrototype(instance);
   11871 
   11872   Local<Object> with_js_getter = CompileRun(
   11873       "o = {};\n"
   11874       "o.__defineGetter__('f', function() { throw undefined; });\n"
   11875       "o\n").As<Object>();
   11876   CHECK(!with_js_getter.IsEmpty());
   11877 
   11878   TryCatch try_catch;
   11879 
   11880   Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
   11881   CHECK(try_catch.HasCaught());
   11882   try_catch.Reset();
   11883   CHECK(result.IsEmpty());
   11884 
   11885   result = another->GetRealNamedProperty(v8_str("f"));
   11886   CHECK(try_catch.HasCaught());
   11887   try_catch.Reset();
   11888   CHECK(result.IsEmpty());
   11889 
   11890   result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
   11891   CHECK(try_catch.HasCaught());
   11892   try_catch.Reset();
   11893   CHECK(result.IsEmpty());
   11894 
   11895   result = another->Get(v8_str("f"));
   11896   CHECK(try_catch.HasCaught());
   11897   try_catch.Reset();
   11898   CHECK(result.IsEmpty());
   11899 
   11900   result = with_js_getter->GetRealNamedProperty(v8_str("f"));
   11901   CHECK(try_catch.HasCaught());
   11902   try_catch.Reset();
   11903   CHECK(result.IsEmpty());
   11904 
   11905   result = with_js_getter->Get(v8_str("f"));
   11906   CHECK(try_catch.HasCaught());
   11907   try_catch.Reset();
   11908   CHECK(result.IsEmpty());
   11909 }
   11910 
   11911 
   11912 static void ThrowingCallbackWithTryCatch(
   11913     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11914   TryCatch try_catch;
   11915   // Verboseness is important: it triggers message delivery which can call into
   11916   // external code.
   11917   try_catch.SetVerbose(true);
   11918   CompileRun("throw 'from JS';");
   11919   CHECK(try_catch.HasCaught());
   11920   CHECK(!i::Isolate::Current()->has_pending_exception());
   11921   CHECK(!i::Isolate::Current()->has_scheduled_exception());
   11922 }
   11923 
   11924 
   11925 static int call_depth;
   11926 
   11927 
   11928 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
   11929   TryCatch try_catch;
   11930 }
   11931 
   11932 
   11933 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
   11934   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   11935 }
   11936 
   11937 
   11938 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
   11939   if (--call_depth) ThrowException(v8_str("ThrowViaApi"));
   11940 }
   11941 
   11942 
   11943 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
   11944   Handle<String> errorMessageString = message->Get();
   11945   CHECK(!errorMessageString.IsEmpty());
   11946   message->GetStackTrace();
   11947   message->GetScriptResourceName();
   11948 }
   11949 
   11950 
   11951 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   11952   LocalContext context;
   11953   HandleScope scope(context->GetIsolate());
   11954 
   11955   Local<Function> func =
   11956       FunctionTemplate::New(ThrowingCallbackWithTryCatch)->GetFunction();
   11957   context->Global()->Set(v8_str("func"), func);
   11958 
   11959   MessageCallback callbacks[] =
   11960       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
   11961   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   11962     MessageCallback callback = callbacks[i];
   11963     if (callback != NULL) {
   11964       V8::AddMessageListener(callback);
   11965     }
   11966     // Some small number to control number of times message handler should
   11967     // throw an exception.
   11968     call_depth = 5;
   11969     ExpectFalse(
   11970         "var thrown = false;\n"
   11971         "try { func(); } catch(e) { thrown = true; }\n"
   11972         "thrown\n");
   11973     if (callback != NULL) {
   11974       V8::RemoveMessageListeners(callback);
   11975     }
   11976   }
   11977 }
   11978 
   11979 
   11980 static void ParentGetter(Local<String> name,
   11981                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   11982   ApiTestFuzzer::Fuzz();
   11983   info.GetReturnValue().Set(v8_num(1));
   11984 }
   11985 
   11986 
   11987 static void ChildGetter(Local<String> name,
   11988                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   11989   ApiTestFuzzer::Fuzz();
   11990   info.GetReturnValue().Set(v8_num(42));
   11991 }
   11992 
   11993 
   11994 THREADED_TEST(Overriding) {
   11995   i::FLAG_es5_readonly = true;
   11996   LocalContext context;
   11997   v8::HandleScope scope(context->GetIsolate());
   11998 
   11999   // Parent template.
   12000   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
   12001   Local<ObjectTemplate> parent_instance_templ =
   12002       parent_templ->InstanceTemplate();
   12003   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   12004 
   12005   // Template that inherits from the parent template.
   12006   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
   12007   Local<ObjectTemplate> child_instance_templ =
   12008       child_templ->InstanceTemplate();
   12009   child_templ->Inherit(parent_templ);
   12010   // Override 'f'.  The child version of 'f' should get called for child
   12011   // instances.
   12012   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   12013   // Add 'g' twice.  The 'g' added last should get called for instances.
   12014   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   12015   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   12016 
   12017   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   12018   // so 'h' can be shadowed on the instance object.
   12019   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   12020   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
   12021       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   12022 
   12023   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   12024   // but the attribute does not have effect because it is duplicated with
   12025   // NULL setter.
   12026   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
   12027       v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
   12028 
   12029 
   12030 
   12031   // Instantiate the child template.
   12032   Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
   12033 
   12034   // Check that the child function overrides the parent one.
   12035   context->Global()->Set(v8_str("o"), instance);
   12036   Local<Value> value = v8_compile("o.f")->Run();
   12037   // Check that the 'g' that was added last is hit.
   12038   CHECK_EQ(42, value->Int32Value());
   12039   value = v8_compile("o.g")->Run();
   12040   CHECK_EQ(42, value->Int32Value());
   12041 
   12042   // Check that 'h' cannot be shadowed.
   12043   value = v8_compile("o.h = 3; o.h")->Run();
   12044   CHECK_EQ(1, value->Int32Value());
   12045 
   12046   // Check that 'i' cannot be shadowed or changed.
   12047   value = v8_compile("o.i = 3; o.i")->Run();
   12048   CHECK_EQ(42, value->Int32Value());
   12049 }
   12050 
   12051 
   12052 static void IsConstructHandler(
   12053     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12054   ApiTestFuzzer::Fuzz();
   12055   args.GetReturnValue().Set(args.IsConstructCall());
   12056 }
   12057 
   12058 
   12059 THREADED_TEST(IsConstructCall) {
   12060   v8::HandleScope scope(v8::Isolate::GetCurrent());
   12061 
   12062   // Function template with call handler.
   12063   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   12064   templ->SetCallHandler(IsConstructHandler);
   12065 
   12066   LocalContext context;
   12067 
   12068   context->Global()->Set(v8_str("f"), templ->GetFunction());
   12069   Local<Value> value = v8_compile("f()")->Run();
   12070   CHECK(!value->BooleanValue());
   12071   value = v8_compile("new f()")->Run();
   12072   CHECK(value->BooleanValue());
   12073 }
   12074 
   12075 
   12076 THREADED_TEST(ObjectProtoToString) {
   12077   v8::HandleScope scope(v8::Isolate::GetCurrent());
   12078   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
   12079   templ->SetClassName(v8_str("MyClass"));
   12080 
   12081   LocalContext context;
   12082 
   12083   Local<String> customized_tostring = v8_str("customized toString");
   12084 
   12085   // Replace Object.prototype.toString
   12086   v8_compile("Object.prototype.toString = function() {"
   12087                   "  return 'customized toString';"
   12088                   "}")->Run();
   12089 
   12090   // Normal ToString call should call replaced Object.prototype.toString
   12091   Local<v8::Object> instance = templ->GetFunction()->NewInstance();
   12092   Local<String> value = instance->ToString();
   12093   CHECK(value->IsString() && value->Equals(customized_tostring));
   12094 
   12095   // ObjectProtoToString should not call replace toString function.
   12096   value = instance->ObjectProtoToString();
   12097   CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
   12098 
   12099   // Check global
   12100   value = context->Global()->ObjectProtoToString();
   12101   CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
   12102 
   12103   // Check ordinary object
   12104   Local<Value> object = v8_compile("new Object()")->Run();
   12105   value = object.As<v8::Object>()->ObjectProtoToString();
   12106   CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
   12107 }
   12108 
   12109 
   12110 THREADED_TEST(ObjectGetConstructorName) {
   12111   LocalContext context;
   12112   v8::HandleScope scope(context->GetIsolate());
   12113   v8_compile("function Parent() {};"
   12114              "function Child() {};"
   12115              "Child.prototype = new Parent();"
   12116              "var outer = { inner: function() { } };"
   12117              "var p = new Parent();"
   12118              "var c = new Child();"
   12119              "var x = new outer.inner();")->Run();
   12120 
   12121   Local<v8::Value> p = context->Global()->Get(v8_str("p"));
   12122   CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
   12123       v8_str("Parent")));
   12124 
   12125   Local<v8::Value> c = context->Global()->Get(v8_str("c"));
   12126   CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
   12127       v8_str("Child")));
   12128 
   12129   Local<v8::Value> x = context->Global()->Get(v8_str("x"));
   12130   CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
   12131       v8_str("outer.inner")));
   12132 }
   12133 
   12134 
   12135 bool ApiTestFuzzer::fuzzing_ = false;
   12136 i::Semaphore* ApiTestFuzzer::all_tests_done_=
   12137   i::OS::CreateSemaphore(0);
   12138 int ApiTestFuzzer::active_tests_;
   12139 int ApiTestFuzzer::tests_being_run_;
   12140 int ApiTestFuzzer::current_;
   12141 
   12142 
   12143 // We are in a callback and want to switch to another thread (if we
   12144 // are currently running the thread fuzzing test).
   12145 void ApiTestFuzzer::Fuzz() {
   12146   if (!fuzzing_) return;
   12147   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   12148   test->ContextSwitch();
   12149 }
   12150 
   12151 
   12152 // Let the next thread go.  Since it is also waiting on the V8 lock it may
   12153 // not start immediately.
   12154 bool ApiTestFuzzer::NextThread() {
   12155   int test_position = GetNextTestNumber();
   12156   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   12157   if (test_position == current_) {
   12158     if (kLogThreading)
   12159       printf("Stay with %s\n", test_name);
   12160     return false;
   12161   }
   12162   if (kLogThreading) {
   12163     printf("Switch from %s to %s\n",
   12164            test_name,
   12165            RegisterThreadedTest::nth(test_position)->name());
   12166   }
   12167   current_ = test_position;
   12168   RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
   12169   return true;
   12170 }
   12171 
   12172 
   12173 void ApiTestFuzzer::Run() {
   12174   // When it is our turn...
   12175   gate_->Wait();
   12176   {
   12177     // ... get the V8 lock and start running the test.
   12178     v8::Locker locker(CcTest::default_isolate());
   12179     CallTest();
   12180   }
   12181   // This test finished.
   12182   active_ = false;
   12183   active_tests_--;
   12184   // If it was the last then signal that fact.
   12185   if (active_tests_ == 0) {
   12186     all_tests_done_->Signal();
   12187   } else {
   12188     // Otherwise select a new test and start that.
   12189     NextThread();
   12190   }
   12191 }
   12192 
   12193 
   12194 static unsigned linear_congruential_generator;
   12195 
   12196 
   12197 void ApiTestFuzzer::SetUp(PartOfTest part) {
   12198   linear_congruential_generator = i::FLAG_testing_prng_seed;
   12199   fuzzing_ = true;
   12200   int count = RegisterThreadedTest::count();
   12201   int start =  count * part / (LAST_PART + 1);
   12202   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   12203   active_tests_ = tests_being_run_ = end - start + 1;
   12204   for (int i = 0; i < tests_being_run_; i++) {
   12205     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   12206   }
   12207   for (int i = 0; i < active_tests_; i++) {
   12208     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   12209   }
   12210 }
   12211 
   12212 
   12213 static void CallTestNumber(int test_number) {
   12214   (RegisterThreadedTest::nth(test_number)->callback())();
   12215 }
   12216 
   12217 
   12218 void ApiTestFuzzer::RunAllTests() {
   12219   // Set off the first test.
   12220   current_ = -1;
   12221   NextThread();
   12222   // Wait till they are all done.
   12223   all_tests_done_->Wait();
   12224 }
   12225 
   12226 
   12227 int ApiTestFuzzer::GetNextTestNumber() {
   12228   int next_test;
   12229   do {
   12230     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   12231     linear_congruential_generator *= 1664525u;
   12232     linear_congruential_generator += 1013904223u;
   12233   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   12234   return next_test;
   12235 }
   12236 
   12237 
   12238 void ApiTestFuzzer::ContextSwitch() {
   12239   // If the new thread is the same as the current thread there is nothing to do.
   12240   if (NextThread()) {
   12241     // Now it can start.
   12242     v8::Unlocker unlocker(CcTest::default_isolate());
   12243     // Wait till someone starts us again.
   12244     gate_->Wait();
   12245     // And we're off.
   12246   }
   12247 }
   12248 
   12249 
   12250 void ApiTestFuzzer::TearDown() {
   12251   fuzzing_ = false;
   12252   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   12253     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   12254     if (fuzzer != NULL) fuzzer->Join();
   12255   }
   12256 }
   12257 
   12258 
   12259 // Lets not be needlessly self-referential.
   12260 TEST(Threading1) {
   12261   // TODO(mstarzinger): Disabled in GC stress mode for now, we should find the
   12262   // correct timeout for this an re-enable this test again
   12263   if (i::FLAG_stress_compaction) return;
   12264   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
   12265   ApiTestFuzzer::RunAllTests();
   12266   ApiTestFuzzer::TearDown();
   12267 }
   12268 
   12269 
   12270 TEST(Threading2) {
   12271   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
   12272   ApiTestFuzzer::RunAllTests();
   12273   ApiTestFuzzer::TearDown();
   12274 }
   12275 
   12276 
   12277 TEST(Threading3) {
   12278   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
   12279   ApiTestFuzzer::RunAllTests();
   12280   ApiTestFuzzer::TearDown();
   12281 }
   12282 
   12283 
   12284 TEST(Threading4) {
   12285   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
   12286   ApiTestFuzzer::RunAllTests();
   12287   ApiTestFuzzer::TearDown();
   12288 }
   12289 
   12290 
   12291 void ApiTestFuzzer::CallTest() {
   12292   if (kLogThreading)
   12293     printf("Start test %d\n", test_number_);
   12294   CallTestNumber(test_number_);
   12295   if (kLogThreading)
   12296     printf("End test %d\n", test_number_);
   12297 }
   12298 
   12299 
   12300 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12301   CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
   12302   ApiTestFuzzer::Fuzz();
   12303   v8::Unlocker unlocker(CcTest::default_isolate());
   12304   const char* code = "throw 7;";
   12305   {
   12306     v8::Locker nested_locker(CcTest::default_isolate());
   12307     v8::HandleScope scope(args.GetIsolate());
   12308     v8::Handle<Value> exception;
   12309     { v8::TryCatch try_catch;
   12310       v8::Handle<Value> value = CompileRun(code);
   12311       CHECK(value.IsEmpty());
   12312       CHECK(try_catch.HasCaught());
   12313       // Make sure to wrap the exception in a new handle because
   12314       // the handle returned from the TryCatch is destroyed
   12315       // when the TryCatch is destroyed.
   12316       exception = Local<Value>::New(try_catch.Exception());
   12317     }
   12318     v8::ThrowException(exception);
   12319   }
   12320 }
   12321 
   12322 
   12323 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12324   CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
   12325   ApiTestFuzzer::Fuzz();
   12326   v8::Unlocker unlocker(CcTest::default_isolate());
   12327   const char* code = "throw 7;";
   12328   {
   12329     v8::Locker nested_locker(CcTest::default_isolate());
   12330     v8::HandleScope scope(args.GetIsolate());
   12331     v8::Handle<Value> value = CompileRun(code);
   12332     CHECK(value.IsEmpty());
   12333     args.GetReturnValue().Set(v8_str("foo"));
   12334   }
   12335 }
   12336 
   12337 
   12338 // These are locking tests that don't need to be run again
   12339 // as part of the locking aggregation tests.
   12340 TEST(NestedLockers) {
   12341   v8::Locker locker(CcTest::default_isolate());
   12342   CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
   12343   LocalContext env;
   12344   v8::HandleScope scope(env->GetIsolate());
   12345   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
   12346   Local<Function> fun = fun_templ->GetFunction();
   12347   env->Global()->Set(v8_str("throw_in_js"), fun);
   12348   Local<Script> script = v8_compile("(function () {"
   12349                                     "  try {"
   12350                                     "    throw_in_js();"
   12351                                     "    return 42;"
   12352                                     "  } catch (e) {"
   12353                                     "    return e * 13;"
   12354                                     "  }"
   12355                                     "})();");
   12356   CHECK_EQ(91, script->Run()->Int32Value());
   12357 }
   12358 
   12359 
   12360 // These are locking tests that don't need to be run again
   12361 // as part of the locking aggregation tests.
   12362 TEST(NestedLockersNoTryCatch) {
   12363   v8::Locker locker(CcTest::default_isolate());
   12364   LocalContext env;
   12365   v8::HandleScope scope(env->GetIsolate());
   12366   Local<v8::FunctionTemplate> fun_templ =
   12367       v8::FunctionTemplate::New(ThrowInJSNoCatch);
   12368   Local<Function> fun = fun_templ->GetFunction();
   12369   env->Global()->Set(v8_str("throw_in_js"), fun);
   12370   Local<Script> script = v8_compile("(function () {"
   12371                                     "  try {"
   12372                                     "    throw_in_js();"
   12373                                     "    return 42;"
   12374                                     "  } catch (e) {"
   12375                                     "    return e * 13;"
   12376                                     "  }"
   12377                                     "})();");
   12378   CHECK_EQ(91, script->Run()->Int32Value());
   12379 }
   12380 
   12381 
   12382 THREADED_TEST(RecursiveLocking) {
   12383   v8::Locker locker(CcTest::default_isolate());
   12384   {
   12385     v8::Locker locker2(CcTest::default_isolate());
   12386     CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
   12387   }
   12388 }
   12389 
   12390 
   12391 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12392   ApiTestFuzzer::Fuzz();
   12393   v8::Unlocker unlocker(CcTest::default_isolate());
   12394 }
   12395 
   12396 
   12397 THREADED_TEST(LockUnlockLock) {
   12398   {
   12399     v8::Locker locker(CcTest::default_isolate());
   12400     v8::HandleScope scope(CcTest::default_isolate());
   12401     LocalContext env;
   12402     Local<v8::FunctionTemplate> fun_templ =
   12403         v8::FunctionTemplate::New(UnlockForAMoment);
   12404     Local<Function> fun = fun_templ->GetFunction();
   12405     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   12406     Local<Script> script = v8_compile("(function () {"
   12407                                       "  unlock_for_a_moment();"
   12408                                       "  return 42;"
   12409                                       "})();");
   12410     CHECK_EQ(42, script->Run()->Int32Value());
   12411   }
   12412   {
   12413     v8::Locker locker(CcTest::default_isolate());
   12414     v8::HandleScope scope(CcTest::default_isolate());
   12415     LocalContext env;
   12416     Local<v8::FunctionTemplate> fun_templ =
   12417         v8::FunctionTemplate::New(UnlockForAMoment);
   12418     Local<Function> fun = fun_templ->GetFunction();
   12419     env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
   12420     Local<Script> script = v8_compile("(function () {"
   12421                                       "  unlock_for_a_moment();"
   12422                                       "  return 42;"
   12423                                       "})();");
   12424     CHECK_EQ(42, script->Run()->Int32Value());
   12425   }
   12426 }
   12427 
   12428 
   12429 static int GetGlobalObjectsCount() {
   12430   i::Isolate::Current()->heap()->EnsureHeapIsIterable();
   12431   int count = 0;
   12432   i::HeapIterator it(HEAP);
   12433   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
   12434     if (object->IsJSGlobalObject()) count++;
   12435   return count;
   12436 }
   12437 
   12438 
   12439 static void CheckSurvivingGlobalObjectsCount(int expected) {
   12440   // We need to collect all garbage twice to be sure that everything
   12441   // has been collected.  This is because inline caches are cleared in
   12442   // the first garbage collection but some of the maps have already
   12443   // been marked at that point.  Therefore some of the maps are not
   12444   // collected until the second garbage collection.
   12445   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   12446   HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
   12447   int count = GetGlobalObjectsCount();
   12448 #ifdef DEBUG
   12449   if (count != expected) HEAP->TracePathToGlobal();
   12450 #endif
   12451   CHECK_EQ(expected, count);
   12452 }
   12453 
   12454 
   12455 TEST(DontLeakGlobalObjects) {
   12456   // Regression test for issues 1139850 and 1174891.
   12457 
   12458   v8::V8::Initialize();
   12459 
   12460   for (int i = 0; i < 5; i++) {
   12461     { v8::HandleScope scope(v8::Isolate::GetCurrent());
   12462       LocalContext context;
   12463     }
   12464     v8::V8::ContextDisposedNotification();
   12465     CheckSurvivingGlobalObjectsCount(0);
   12466 
   12467     { v8::HandleScope scope(v8::Isolate::GetCurrent());
   12468       LocalContext context;
   12469       v8_compile("Date")->Run();
   12470     }
   12471     v8::V8::ContextDisposedNotification();
   12472     CheckSurvivingGlobalObjectsCount(0);
   12473 
   12474     { v8::HandleScope scope(v8::Isolate::GetCurrent());
   12475       LocalContext context;
   12476       v8_compile("/aaa/")->Run();
   12477     }
   12478     v8::V8::ContextDisposedNotification();
   12479     CheckSurvivingGlobalObjectsCount(0);
   12480 
   12481     { v8::HandleScope scope(v8::Isolate::GetCurrent());
   12482       const char* extension_list[] = { "v8/gc" };
   12483       v8::ExtensionConfiguration extensions(1, extension_list);
   12484       LocalContext context(&extensions);
   12485       v8_compile("gc();")->Run();
   12486     }
   12487     v8::V8::ContextDisposedNotification();
   12488     CheckSurvivingGlobalObjectsCount(0);
   12489   }
   12490 }
   12491 
   12492 
   12493 v8::Persistent<v8::Object> some_object;
   12494 v8::Persistent<v8::Object> bad_handle;
   12495 
   12496 void NewPersistentHandleCallback(v8::Isolate* isolate,
   12497                                  v8::Persistent<v8::Value>* handle,
   12498                                  void*) {
   12499   v8::HandleScope scope(isolate);
   12500   bad_handle.Reset(isolate, some_object);
   12501   handle->Dispose(isolate);
   12502 }
   12503 
   12504 
   12505 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   12506   LocalContext context;
   12507   v8::Isolate* isolate = context->GetIsolate();
   12508 
   12509   v8::Persistent<v8::Object> handle1, handle2;
   12510   {
   12511     v8::HandleScope scope(isolate);
   12512     some_object.Reset(isolate, v8::Object::New());
   12513     handle1.Reset(isolate, v8::Object::New());
   12514     handle2.Reset(isolate, v8::Object::New());
   12515   }
   12516   // Note: order is implementation dependent alas: currently
   12517   // global handle nodes are processed by PostGarbageCollectionProcessing
   12518   // in reverse allocation order, so if second allocated handle is deleted,
   12519   // weak callback of the first handle would be able to 'reallocate' it.
   12520   handle1.MakeWeak<v8::Value, void>(NULL, NewPersistentHandleCallback);
   12521   handle2.Dispose(isolate);
   12522   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   12523 }
   12524 
   12525 
   12526 v8::Persistent<v8::Object> to_be_disposed;
   12527 
   12528 void DisposeAndForceGcCallback(v8::Isolate* isolate,
   12529                                v8::Persistent<v8::Value>* handle,
   12530                                void*) {
   12531   to_be_disposed.Dispose(isolate);
   12532   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   12533   handle->Dispose(isolate);
   12534 }
   12535 
   12536 
   12537 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   12538   LocalContext context;
   12539   v8::Isolate* isolate = context->GetIsolate();
   12540 
   12541   v8::Persistent<v8::Object> handle1, handle2;
   12542   {
   12543     v8::HandleScope scope(isolate);
   12544     handle1.Reset(isolate, v8::Object::New());
   12545     handle2.Reset(isolate, v8::Object::New());
   12546   }
   12547   handle1.MakeWeak<v8::Value, void>(NULL, DisposeAndForceGcCallback);
   12548   to_be_disposed.Reset(isolate, handle2);
   12549   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   12550 }
   12551 
   12552 void DisposingCallback(v8::Isolate* isolate,
   12553                        v8::Persistent<v8::Value>* handle,
   12554                        void*) {
   12555   handle->Dispose(isolate);
   12556 }
   12557 
   12558 void HandleCreatingCallback(v8::Isolate* isolate,
   12559                             v8::Persistent<v8::Value>* handle,
   12560                             void*) {
   12561   v8::HandleScope scope(isolate);
   12562   v8::Persistent<v8::Object>(isolate, v8::Object::New());
   12563   handle->Dispose(isolate);
   12564 }
   12565 
   12566 
   12567 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   12568   LocalContext context;
   12569   v8::Isolate* isolate = context->GetIsolate();
   12570 
   12571   v8::Persistent<v8::Object> handle1, handle2, handle3;
   12572   {
   12573     v8::HandleScope scope(isolate);
   12574     handle3.Reset(isolate, v8::Object::New());
   12575     handle2.Reset(isolate, v8::Object::New());
   12576     handle1.Reset(isolate, v8::Object::New());
   12577   }
   12578   handle2.MakeWeak<v8::Value, void>(NULL, DisposingCallback);
   12579   handle3.MakeWeak<v8::Value, void>(NULL, HandleCreatingCallback);
   12580   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   12581 }
   12582 
   12583 
   12584 THREADED_TEST(CheckForCrossContextObjectLiterals) {
   12585   v8::V8::Initialize();
   12586 
   12587   const int nof = 2;
   12588   const char* sources[nof] = {
   12589     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   12590     "Object()"
   12591   };
   12592 
   12593   for (int i = 0; i < nof; i++) {
   12594     const char* source = sources[i];
   12595     { v8::HandleScope scope(v8::Isolate::GetCurrent());
   12596       LocalContext context;
   12597       CompileRun(source);
   12598     }
   12599     { v8::HandleScope scope(v8::Isolate::GetCurrent());
   12600       LocalContext context;
   12601       CompileRun(source);
   12602     }
   12603   }
   12604 }
   12605 
   12606 
   12607 static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
   12608   v8::HandleScope inner(env->GetIsolate());
   12609   env->Enter();
   12610   v8::Handle<Value> three = v8_num(3);
   12611   v8::Handle<Value> value = inner.Close(three);
   12612   env->Exit();
   12613   return value;
   12614 }
   12615 
   12616 
   12617 THREADED_TEST(NestedHandleScopeAndContexts) {
   12618   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   12619   v8::HandleScope outer(isolate);
   12620   v8::Local<Context> env = Context::New(isolate);
   12621   env->Enter();
   12622   v8::Handle<Value> value = NestedScope(env);
   12623   v8::Handle<String> str(value->ToString());
   12624   CHECK(!str.IsEmpty());
   12625   env->Exit();
   12626 }
   12627 
   12628 
   12629 static bool MatchPointers(void* key1, void* key2) {
   12630   return key1 == key2;
   12631 }
   12632 
   12633 
   12634 struct SymbolInfo {
   12635   size_t id;
   12636   size_t size;
   12637   std::string name;
   12638 };
   12639 
   12640 
   12641 class SetFunctionEntryHookTest {
   12642  public:
   12643   SetFunctionEntryHookTest() {
   12644     CHECK(instance_ == NULL);
   12645     instance_ = this;
   12646   }
   12647   ~SetFunctionEntryHookTest() {
   12648     CHECK(instance_ == this);
   12649     instance_ = NULL;
   12650   }
   12651   void Reset() {
   12652     symbols_.clear();
   12653     symbol_locations_.clear();
   12654     invocations_.clear();
   12655   }
   12656   void RunTest();
   12657   void OnJitEvent(const v8::JitCodeEvent* event);
   12658   static void JitEvent(const v8::JitCodeEvent* event) {
   12659     CHECK(instance_ != NULL);
   12660     instance_->OnJitEvent(event);
   12661   }
   12662 
   12663   void OnEntryHook(uintptr_t function,
   12664                    uintptr_t return_addr_location);
   12665   static void EntryHook(uintptr_t function,
   12666                         uintptr_t return_addr_location) {
   12667     CHECK(instance_ != NULL);
   12668     instance_->OnEntryHook(function, return_addr_location);
   12669   }
   12670 
   12671   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12672     CHECK(instance_ != NULL);
   12673     args.GetReturnValue().Set(v8_num(42));
   12674   }
   12675   void RunLoopInNewEnv(v8::Isolate* isolate);
   12676 
   12677   // Records addr as location of symbol.
   12678   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
   12679 
   12680   // Finds the symbol containing addr
   12681   SymbolInfo* FindSymbolForAddr(i::Address addr);
   12682   // Returns the number of invocations where the caller name contains
   12683   // \p caller_name and the function name contains \p function_name.
   12684   int CountInvocations(const char* caller_name,
   12685                        const char* function_name);
   12686 
   12687   i::Handle<i::JSFunction> foo_func_;
   12688   i::Handle<i::JSFunction> bar_func_;
   12689 
   12690   typedef std::map<size_t, SymbolInfo> SymbolMap;
   12691   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
   12692   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
   12693   SymbolMap symbols_;
   12694   SymbolLocationMap symbol_locations_;
   12695   InvocationMap invocations_;
   12696 
   12697   static SetFunctionEntryHookTest* instance_;
   12698 };
   12699 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
   12700 
   12701 
   12702 // Returns true if addr is in the range [start, start+len).
   12703 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
   12704   if (start <= addr && start + len > addr)
   12705     return true;
   12706 
   12707   return false;
   12708 }
   12709 
   12710 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
   12711                                               SymbolInfo* symbol) {
   12712   // Insert the symbol at the new location.
   12713   SymbolLocationMap::iterator it =
   12714       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
   12715   // Now erase symbols to the left and right that overlap this one.
   12716   while (it != symbol_locations_.begin()) {
   12717     SymbolLocationMap::iterator left = it;
   12718     --left;
   12719     if (!Overlaps(left->first, left->second->size, addr))
   12720       break;
   12721     symbol_locations_.erase(left);
   12722   }
   12723 
   12724   // Now erase symbols to the left and right that overlap this one.
   12725   while (true) {
   12726     SymbolLocationMap::iterator right = it;
   12727     ++right;
   12728     if (right == symbol_locations_.end())
   12729         break;
   12730     if (!Overlaps(addr, symbol->size, right->first))
   12731       break;
   12732     symbol_locations_.erase(right);
   12733   }
   12734 }
   12735 
   12736 
   12737 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
   12738   switch (event->type) {
   12739     case v8::JitCodeEvent::CODE_ADDED: {
   12740         CHECK(event->code_start != NULL);
   12741         CHECK_NE(0, static_cast<int>(event->code_len));
   12742         CHECK(event->name.str != NULL);
   12743         size_t symbol_id = symbols_.size();
   12744 
   12745         // Record the new symbol.
   12746         SymbolInfo& info = symbols_[symbol_id];
   12747         info.id = symbol_id;
   12748         info.size = event->code_len;
   12749         info.name.assign(event->name.str, event->name.str + event->name.len);
   12750 
   12751         // And record it's location.
   12752         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
   12753       }
   12754       break;
   12755 
   12756     case v8::JitCodeEvent::CODE_MOVED: {
   12757         // We would like to never see code move that we haven't seen before,
   12758         // but the code creation event does not happen until the line endings
   12759         // have been calculated (this is so that we can report the line in the
   12760         // script at which the function source is found, see
   12761         // Compiler::RecordFunctionCompilation) and the line endings
   12762         // calculations can cause a GC, which can move the newly created code
   12763         // before its existence can be logged.
   12764         SymbolLocationMap::iterator it(
   12765             symbol_locations_.find(
   12766                 reinterpret_cast<i::Address>(event->code_start)));
   12767         if (it != symbol_locations_.end()) {
   12768           // Found a symbol at this location, move it.
   12769           SymbolInfo* info = it->second;
   12770           symbol_locations_.erase(it);
   12771           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
   12772                          info);
   12773         }
   12774       }
   12775     default:
   12776       break;
   12777   }
   12778 }
   12779 
   12780 void SetFunctionEntryHookTest::OnEntryHook(
   12781     uintptr_t function, uintptr_t return_addr_location) {
   12782   // Get the function's code object.
   12783   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
   12784       reinterpret_cast<i::Address>(function));
   12785   CHECK(function_code != NULL);
   12786 
   12787   // Then try and look up the caller's code object.
   12788   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
   12789 
   12790   // Count the invocation.
   12791   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
   12792   SymbolInfo* function_symbol =
   12793       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
   12794   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
   12795 
   12796   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
   12797     // Check that we have a symbol for the "bar" function at the right location.
   12798     SymbolLocationMap::iterator it(
   12799         symbol_locations_.find(function_code->instruction_start()));
   12800     CHECK(it != symbol_locations_.end());
   12801   }
   12802 
   12803   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
   12804     // Check that we have a symbol for "foo" at the right location.
   12805     SymbolLocationMap::iterator it(
   12806         symbol_locations_.find(function_code->instruction_start()));
   12807     CHECK(it != symbol_locations_.end());
   12808   }
   12809 }
   12810 
   12811 
   12812 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
   12813   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
   12814   // Do we have a direct hit on a symbol?
   12815   if (it != symbol_locations_.end()) {
   12816     if (it->first == addr)
   12817       return it->second;
   12818   }
   12819 
   12820   // If not a direct hit, it'll have to be the previous symbol.
   12821   if (it == symbol_locations_.begin())
   12822     return NULL;
   12823 
   12824   --it;
   12825   size_t offs = addr - it->first;
   12826   if (offs < it->second->size)
   12827     return it->second;
   12828 
   12829   return NULL;
   12830 }
   12831 
   12832 
   12833 int SetFunctionEntryHookTest::CountInvocations(
   12834     const char* caller_name, const char* function_name) {
   12835   InvocationMap::iterator it(invocations_.begin());
   12836   int invocations = 0;
   12837   for (; it != invocations_.end(); ++it) {
   12838     SymbolInfo* caller = it->first.first;
   12839     SymbolInfo* function = it->first.second;
   12840 
   12841     // Filter out non-matching functions.
   12842     if (function_name != NULL) {
   12843       if (function->name.find(function_name) == std::string::npos)
   12844         continue;
   12845     }
   12846 
   12847     // Filter out non-matching callers.
   12848     if (caller_name != NULL) {
   12849       if (caller == NULL)
   12850         continue;
   12851       if (caller->name.find(caller_name) == std::string::npos)
   12852         continue;
   12853     }
   12854 
   12855     // It matches add the invocation count to the tally.
   12856     invocations += it->second;
   12857   }
   12858 
   12859   return invocations;
   12860 }
   12861 
   12862 
   12863 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
   12864   v8::HandleScope outer(isolate);
   12865   v8::Local<Context> env = Context::New(isolate);
   12866   env->Enter();
   12867 
   12868   Local<ObjectTemplate> t = ObjectTemplate::New();
   12869   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(RuntimeCallback));
   12870   env->Global()->Set(v8_str("obj"), t->NewInstance());
   12871 
   12872   const char* script =
   12873       "function bar() {\n"
   12874       "  var sum = 0;\n"
   12875       "  for (i = 0; i < 100; ++i)\n"
   12876       "    sum = foo(i);\n"
   12877       "  return sum;\n"
   12878       "}\n"
   12879       "function foo(i) { return i * i; }\n"
   12880       "// Invoke on the runtime function.\n"
   12881       "obj.asdf()";
   12882   CompileRun(script);
   12883   bar_func_ = i::Handle<i::JSFunction>::cast(
   12884           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
   12885   ASSERT(!bar_func_.is_null());
   12886 
   12887   foo_func_ =
   12888       i::Handle<i::JSFunction>::cast(
   12889            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
   12890   ASSERT(!foo_func_.is_null());
   12891 
   12892   v8::Handle<v8::Value> value = CompileRun("bar();");
   12893   CHECK(value->IsNumber());
   12894   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   12895 
   12896   // Test the optimized codegen path.
   12897   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
   12898                      "bar();");
   12899   CHECK(value->IsNumber());
   12900   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   12901 
   12902   env->Exit();
   12903 }
   12904 
   12905 
   12906 void SetFunctionEntryHookTest::RunTest() {
   12907   // Work in a new isolate throughout.
   12908   v8::Isolate* isolate = v8::Isolate::New();
   12909 
   12910   // Test setting the entry hook on the new isolate.
   12911   CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
   12912 
   12913   // Replacing the hook, once set should fail.
   12914   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
   12915 
   12916   {
   12917     v8::Isolate::Scope scope(isolate);
   12918 
   12919     v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
   12920 
   12921     RunLoopInNewEnv(isolate);
   12922 
   12923     // Check the exepected invocation counts.
   12924     CHECK_EQ(2, CountInvocations(NULL, "bar"));
   12925     CHECK_EQ(200, CountInvocations("bar", "foo"));
   12926     CHECK_EQ(200, CountInvocations(NULL, "foo"));
   12927 
   12928     // Verify that we have an entry hook on some specific stubs.
   12929     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
   12930     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
   12931     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
   12932   }
   12933   isolate->Dispose();
   12934 
   12935   Reset();
   12936 
   12937   // Make sure a second isolate is unaffected by the previous entry hook.
   12938   isolate = v8::Isolate::New();
   12939   {
   12940     v8::Isolate::Scope scope(isolate);
   12941 
   12942     // Reset the entry count to zero and set the entry hook.
   12943     RunLoopInNewEnv(isolate);
   12944 
   12945     // We should record no invocations in this isolate.
   12946     CHECK_EQ(0, static_cast<int>(invocations_.size()));
   12947   }
   12948   // Since the isolate has been used, we shouldn't be able to set an entry
   12949   // hook anymore.
   12950   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
   12951 
   12952   isolate->Dispose();
   12953 }
   12954 
   12955 
   12956 TEST(SetFunctionEntryHook) {
   12957   // FunctionEntryHook does not work well with experimental natives.
   12958   // Experimental natives are compiled during snapshot deserialization.
   12959   // This test breaks because InstallGetter (function from snapshot that
   12960   // only gets called from experimental natives) is compiled with entry hooks.
   12961   i::FLAG_harmony_typed_arrays = false;
   12962   i::FLAG_harmony_array_buffer = false;
   12963 
   12964   i::FLAG_allow_natives_syntax = true;
   12965   i::FLAG_use_inlining = false;
   12966 
   12967   SetFunctionEntryHookTest test;
   12968   test.RunTest();
   12969 }
   12970 
   12971 
   12972 static i::HashMap* code_map = NULL;
   12973 static i::HashMap* jitcode_line_info = NULL;
   12974 static int saw_bar = 0;
   12975 static int move_events = 0;
   12976 
   12977 
   12978 static bool FunctionNameIs(const char* expected,
   12979                            const v8::JitCodeEvent* event) {
   12980   // Log lines for functions are of the general form:
   12981   // "LazyCompile:<type><function_name>", where the type is one of
   12982   // "*", "~" or "".
   12983   static const char kPreamble[] = "LazyCompile:";
   12984   static size_t kPreambleLen = sizeof(kPreamble) - 1;
   12985 
   12986   if (event->name.len < sizeof(kPreamble) - 1 ||
   12987       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
   12988     return false;
   12989   }
   12990 
   12991   const char* tail = event->name.str + kPreambleLen;
   12992   size_t tail_len = event->name.len - kPreambleLen;
   12993   size_t expected_len = strlen(expected);
   12994   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
   12995     --tail_len;
   12996     ++tail;
   12997   }
   12998 
   12999   // Check for tails like 'bar :1'.
   13000   if (tail_len > expected_len + 2 &&
   13001       tail[expected_len] == ' ' &&
   13002       tail[expected_len + 1] == ':' &&
   13003       tail[expected_len + 2] &&
   13004       !strncmp(tail, expected, expected_len)) {
   13005     return true;
   13006   }
   13007 
   13008   if (tail_len != expected_len)
   13009     return false;
   13010 
   13011   return strncmp(tail, expected, expected_len) == 0;
   13012 }
   13013 
   13014 
   13015 static void event_handler(const v8::JitCodeEvent* event) {
   13016   CHECK(event != NULL);
   13017   CHECK(code_map != NULL);
   13018   CHECK(jitcode_line_info != NULL);
   13019 
   13020   class DummyJitCodeLineInfo {
   13021   };
   13022 
   13023   switch (event->type) {
   13024     case v8::JitCodeEvent::CODE_ADDED: {
   13025         CHECK(event->code_start != NULL);
   13026         CHECK_NE(0, static_cast<int>(event->code_len));
   13027         CHECK(event->name.str != NULL);
   13028         i::HashMap::Entry* entry =
   13029             code_map->Lookup(event->code_start,
   13030                              i::ComputePointerHash(event->code_start),
   13031                              true);
   13032         entry->value = reinterpret_cast<void*>(event->code_len);
   13033 
   13034         if (FunctionNameIs("bar", event)) {
   13035           ++saw_bar;
   13036         }
   13037       }
   13038       break;
   13039 
   13040     case v8::JitCodeEvent::CODE_MOVED: {
   13041         uint32_t hash = i::ComputePointerHash(event->code_start);
   13042         // We would like to never see code move that we haven't seen before,
   13043         // but the code creation event does not happen until the line endings
   13044         // have been calculated (this is so that we can report the line in the
   13045         // script at which the function source is found, see
   13046         // Compiler::RecordFunctionCompilation) and the line endings
   13047         // calculations can cause a GC, which can move the newly created code
   13048         // before its existence can be logged.
   13049         i::HashMap::Entry* entry =
   13050             code_map->Lookup(event->code_start, hash, false);
   13051         if (entry != NULL) {
   13052           ++move_events;
   13053 
   13054           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
   13055           code_map->Remove(event->code_start, hash);
   13056 
   13057           entry = code_map->Lookup(event->new_code_start,
   13058                                    i::ComputePointerHash(event->new_code_start),
   13059                                    true);
   13060           CHECK(entry != NULL);
   13061           entry->value = reinterpret_cast<void*>(event->code_len);
   13062         }
   13063       }
   13064       break;
   13065 
   13066     case v8::JitCodeEvent::CODE_REMOVED:
   13067       // Object/code removal events are currently not dispatched from the GC.
   13068       CHECK(false);
   13069       break;
   13070 
   13071     // For CODE_START_LINE_INFO_RECORDING event, we will create one
   13072     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
   13073     // record it in jitcode_line_info.
   13074     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
   13075         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
   13076         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
   13077         temp_event->user_data = line_info;
   13078         i::HashMap::Entry* entry =
   13079             jitcode_line_info->Lookup(line_info,
   13080                                       i::ComputePointerHash(line_info),
   13081                                       true);
   13082         entry->value = reinterpret_cast<void*>(line_info);
   13083       }
   13084       break;
   13085     // For these two events, we will check whether the event->user_data
   13086     // data structure is created before during CODE_START_LINE_INFO_RECORDING
   13087     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
   13088     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
   13089         CHECK(event->user_data != NULL);
   13090         uint32_t hash = i::ComputePointerHash(event->user_data);
   13091         i::HashMap::Entry* entry =
   13092             jitcode_line_info->Lookup(event->user_data, hash, false);
   13093         CHECK(entry != NULL);
   13094         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
   13095       }
   13096       break;
   13097 
   13098     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
   13099         CHECK(event->user_data != NULL);
   13100         uint32_t hash = i::ComputePointerHash(event->user_data);
   13101         i::HashMap::Entry* entry =
   13102             jitcode_line_info->Lookup(event->user_data, hash, false);
   13103         CHECK(entry != NULL);
   13104       }
   13105       break;
   13106 
   13107     default:
   13108       // Impossible event.
   13109       CHECK(false);
   13110       break;
   13111   }
   13112 }
   13113 
   13114 
   13115 TEST(SetJitCodeEventHandler) {
   13116   i::FLAG_stress_compaction = true;
   13117   i::FLAG_incremental_marking = false;
   13118   const char* script =
   13119     "function bar() {"
   13120     "  var sum = 0;"
   13121     "  for (i = 0; i < 100; ++i)"
   13122     "    sum = foo(i);"
   13123     "  return sum;"
   13124     "}"
   13125     "function foo(i) { return i * i; };"
   13126     "bar();";
   13127 
   13128   // Run this test in a new isolate to make sure we don't
   13129   // have remnants of state from other code.
   13130   v8::Isolate* isolate = v8::Isolate::New();
   13131   isolate->Enter();
   13132 
   13133   {
   13134     v8::HandleScope scope(isolate);
   13135     i::HashMap code(MatchPointers);
   13136     code_map = &code;
   13137 
   13138     i::HashMap lineinfo(MatchPointers);
   13139     jitcode_line_info = &lineinfo;
   13140 
   13141     saw_bar = 0;
   13142     move_events = 0;
   13143 
   13144     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
   13145 
   13146     // Generate new code objects sparsely distributed across several
   13147     // different fragmented code-space pages.
   13148     const int kIterations = 10;
   13149     for (int i = 0; i < kIterations; ++i) {
   13150       LocalContext env;
   13151       i::AlwaysAllocateScope always_allocate;
   13152       SimulateFullSpace(HEAP->code_space());
   13153       CompileRun(script);
   13154 
   13155       // Keep a strong reference to the code object in the handle scope.
   13156       i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
   13157           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
   13158       i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
   13159           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
   13160 
   13161       // Clear the compilation cache to get more wastage.
   13162       ISOLATE->compilation_cache()->Clear();
   13163     }
   13164 
   13165     // Force code movement.
   13166     HEAP->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
   13167 
   13168     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   13169 
   13170     CHECK_LE(kIterations, saw_bar);
   13171     CHECK_LT(0, move_events);
   13172 
   13173     code_map = NULL;
   13174     jitcode_line_info = NULL;
   13175   }
   13176 
   13177   isolate->Exit();
   13178   isolate->Dispose();
   13179 
   13180   // Do this in a new isolate.
   13181   isolate = v8::Isolate::New();
   13182   isolate->Enter();
   13183 
   13184   // Verify that we get callbacks for existing code objects when we
   13185   // request enumeration of existing code.
   13186   {
   13187     v8::HandleScope scope(isolate);
   13188     LocalContext env;
   13189     CompileRun(script);
   13190 
   13191     // Now get code through initial iteration.
   13192     i::HashMap code(MatchPointers);
   13193     code_map = &code;
   13194 
   13195     i::HashMap lineinfo(MatchPointers);
   13196     jitcode_line_info = &lineinfo;
   13197 
   13198     V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
   13199     V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   13200 
   13201     jitcode_line_info = NULL;
   13202     // We expect that we got some events. Note that if we could get code removal
   13203     // notifications, we could compare two collections, one created by listening
   13204     // from the time of creation of an isolate, and the other by subscribing
   13205     // with EnumExisting.
   13206     CHECK_LT(0, code.occupancy());
   13207 
   13208     code_map = NULL;
   13209   }
   13210 
   13211   isolate->Exit();
   13212   isolate->Dispose();
   13213 }
   13214 
   13215 
   13216 static int64_t cast(intptr_t x) { return static_cast<int64_t>(x); }
   13217 
   13218 
   13219 THREADED_TEST(ExternalAllocatedMemory) {
   13220   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   13221   v8::HandleScope outer(isolate);
   13222   v8::Local<Context> env(Context::New(isolate));
   13223   CHECK(!env.IsEmpty());
   13224   const intptr_t kSize = 1024*1024;
   13225   int64_t baseline = cast(isolate->AdjustAmountOfExternalAllocatedMemory(0));
   13226   CHECK_EQ(baseline + cast(kSize),
   13227            cast(isolate->AdjustAmountOfExternalAllocatedMemory(kSize)));
   13228   CHECK_EQ(baseline,
   13229            cast(isolate->AdjustAmountOfExternalAllocatedMemory(-kSize)));
   13230 }
   13231 
   13232 
   13233 THREADED_TEST(DisposeEnteredContext) {
   13234   LocalContext outer;
   13235   v8::Isolate* isolate = outer->GetIsolate();
   13236   v8::Persistent<v8::Context> inner;
   13237   {
   13238     v8::HandleScope scope(isolate);
   13239     inner.Reset(isolate, v8::Context::New(isolate));
   13240   }
   13241   v8::HandleScope scope(isolate);
   13242   {
   13243     // Don't want a handle here, so do this unsafely
   13244     v8::Handle<v8::Context> inner_local =
   13245         v8::Utils::Convert<i::Object, v8::Context>(
   13246             v8::Utils::OpenPersistent(inner));
   13247     inner_local->Enter();
   13248     inner.Dispose();
   13249     inner.Clear();
   13250     inner_local->Exit();
   13251   }
   13252 }
   13253 
   13254 
   13255 // Regression test for issue 54, object templates with internal fields
   13256 // but no accessors or interceptors did not get their internal field
   13257 // count set on instances.
   13258 THREADED_TEST(Regress54) {
   13259   LocalContext context;
   13260   v8::Isolate* isolate = context->GetIsolate();
   13261   v8::HandleScope outer(isolate);
   13262   static v8::Persistent<v8::ObjectTemplate> templ;
   13263   if (templ.IsEmpty()) {
   13264     v8::HandleScope inner(isolate);
   13265     v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
   13266     local->SetInternalFieldCount(1);
   13267     templ.Reset(isolate, inner.Close(local));
   13268   }
   13269   v8::Handle<v8::Object> result =
   13270       v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
   13271   CHECK_EQ(1, result->InternalFieldCount());
   13272 }
   13273 
   13274 
   13275 // If part of the threaded tests, this test makes ThreadingTest fail
   13276 // on mac.
   13277 TEST(CatchStackOverflow) {
   13278   LocalContext context;
   13279   v8::HandleScope scope(context->GetIsolate());
   13280   v8::TryCatch try_catch;
   13281   v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
   13282     "function f() {"
   13283     "  return f();"
   13284     "}"
   13285     ""
   13286     "f();"));
   13287   v8::Handle<v8::Value> result = script->Run();
   13288   CHECK(result.IsEmpty());
   13289 }
   13290 
   13291 
   13292 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
   13293                                     const char* resource_name,
   13294                                     int line_offset) {
   13295   v8::HandleScope scope(v8::Isolate::GetCurrent());
   13296   v8::TryCatch try_catch;
   13297   v8::Handle<v8::Value> result = script->Run();
   13298   CHECK(result.IsEmpty());
   13299   CHECK(try_catch.HasCaught());
   13300   v8::Handle<v8::Message> message = try_catch.Message();
   13301   CHECK(!message.IsEmpty());
   13302   CHECK_EQ(10 + line_offset, message->GetLineNumber());
   13303   CHECK_EQ(91, message->GetStartPosition());
   13304   CHECK_EQ(92, message->GetEndPosition());
   13305   CHECK_EQ(2, message->GetStartColumn());
   13306   CHECK_EQ(3, message->GetEndColumn());
   13307   v8::String::Utf8Value line(message->GetSourceLine());
   13308   CHECK_EQ("  throw 'nirk';", *line);
   13309   v8::String::Utf8Value name(message->GetScriptResourceName());
   13310   CHECK_EQ(resource_name, *name);
   13311 }
   13312 
   13313 
   13314 THREADED_TEST(TryCatchSourceInfo) {
   13315   LocalContext context;
   13316   v8::HandleScope scope(context->GetIsolate());
   13317   v8::Handle<v8::String> source = v8::String::New(
   13318       "function Foo() {\n"
   13319       "  return Bar();\n"
   13320       "}\n"
   13321       "\n"
   13322       "function Bar() {\n"
   13323       "  return Baz();\n"
   13324       "}\n"
   13325       "\n"
   13326       "function Baz() {\n"
   13327       "  throw 'nirk';\n"
   13328       "}\n"
   13329       "\n"
   13330       "Foo();\n");
   13331 
   13332   const char* resource_name;
   13333   v8::Handle<v8::Script> script;
   13334   resource_name = "test.js";
   13335   script = v8::Script::Compile(source, v8::String::New(resource_name));
   13336   CheckTryCatchSourceInfo(script, resource_name, 0);
   13337 
   13338   resource_name = "test1.js";
   13339   v8::ScriptOrigin origin1(v8::String::New(resource_name));
   13340   script = v8::Script::Compile(source, &origin1);
   13341   CheckTryCatchSourceInfo(script, resource_name, 0);
   13342 
   13343   resource_name = "test2.js";
   13344   v8::ScriptOrigin origin2(v8::String::New(resource_name), v8::Integer::New(7));
   13345   script = v8::Script::Compile(source, &origin2);
   13346   CheckTryCatchSourceInfo(script, resource_name, 7);
   13347 }
   13348 
   13349 
   13350 THREADED_TEST(CompilationCache) {
   13351   LocalContext context;
   13352   v8::HandleScope scope(context->GetIsolate());
   13353   v8::Handle<v8::String> source0 = v8::String::New("1234");
   13354   v8::Handle<v8::String> source1 = v8::String::New("1234");
   13355   v8::Handle<v8::Script> script0 =
   13356       v8::Script::Compile(source0, v8::String::New("test.js"));
   13357   v8::Handle<v8::Script> script1 =
   13358       v8::Script::Compile(source1, v8::String::New("test.js"));
   13359   v8::Handle<v8::Script> script2 =
   13360       v8::Script::Compile(source0);  // different origin
   13361   CHECK_EQ(1234, script0->Run()->Int32Value());
   13362   CHECK_EQ(1234, script1->Run()->Int32Value());
   13363   CHECK_EQ(1234, script2->Run()->Int32Value());
   13364 }
   13365 
   13366 
   13367 static void FunctionNameCallback(
   13368     const v8::FunctionCallbackInfo<v8::Value>& args) {
   13369   ApiTestFuzzer::Fuzz();
   13370   args.GetReturnValue().Set(v8_num(42));
   13371 }
   13372 
   13373 
   13374 THREADED_TEST(CallbackFunctionName) {
   13375   LocalContext context;
   13376   v8::HandleScope scope(context->GetIsolate());
   13377   Local<ObjectTemplate> t = ObjectTemplate::New();
   13378   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
   13379   context->Global()->Set(v8_str("obj"), t->NewInstance());
   13380   v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
   13381   CHECK(value->IsString());
   13382   v8::String::Utf8Value name(value);
   13383   CHECK_EQ("asdf", *name);
   13384 }
   13385 
   13386 
   13387 THREADED_TEST(DateAccess) {
   13388   LocalContext context;
   13389   v8::HandleScope scope(context->GetIsolate());
   13390   v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
   13391   CHECK(date->IsDate());
   13392   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
   13393 }
   13394 
   13395 
   13396 void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
   13397   v8::Handle<v8::Object> obj = val.As<v8::Object>();
   13398   v8::Handle<v8::Array> props = obj->GetPropertyNames();
   13399   CHECK_EQ(elmc, props->Length());
   13400   for (int i = 0; i < elmc; i++) {
   13401     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
   13402     CHECK_EQ(elmv[i], *elm);
   13403   }
   13404 }
   13405 
   13406 
   13407 void CheckOwnProperties(v8::Handle<v8::Value> val,
   13408                         int elmc,
   13409                         const char* elmv[]) {
   13410   v8::Handle<v8::Object> obj = val.As<v8::Object>();
   13411   v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
   13412   CHECK_EQ(elmc, props->Length());
   13413   for (int i = 0; i < elmc; i++) {
   13414     v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
   13415     CHECK_EQ(elmv[i], *elm);
   13416   }
   13417 }
   13418 
   13419 
   13420 THREADED_TEST(PropertyEnumeration) {
   13421   LocalContext context;
   13422   v8::HandleScope scope(context->GetIsolate());
   13423   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
   13424       "var result = [];"
   13425       "result[0] = {};"
   13426       "result[1] = {a: 1, b: 2};"
   13427       "result[2] = [1, 2, 3];"
   13428       "var proto = {x: 1, y: 2, z: 3};"
   13429       "var x = { __proto__: proto, w: 0, z: 1 };"
   13430       "result[3] = x;"
   13431       "result;"))->Run();
   13432   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   13433   CHECK_EQ(4, elms->Length());
   13434   int elmc0 = 0;
   13435   const char** elmv0 = NULL;
   13436   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   13437   CheckOwnProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   13438   int elmc1 = 2;
   13439   const char* elmv1[] = {"a", "b"};
   13440   CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
   13441   CheckOwnProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
   13442   int elmc2 = 3;
   13443   const char* elmv2[] = {"0", "1", "2"};
   13444   CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
   13445   CheckOwnProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
   13446   int elmc3 = 4;
   13447   const char* elmv3[] = {"w", "z", "x", "y"};
   13448   CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
   13449   int elmc4 = 2;
   13450   const char* elmv4[] = {"w", "z"};
   13451   CheckOwnProperties(elms->Get(v8::Integer::New(3)), elmc4, elmv4);
   13452 }
   13453 
   13454 
   13455 THREADED_TEST(PropertyEnumeration2) {
   13456   LocalContext context;
   13457   v8::HandleScope scope(context->GetIsolate());
   13458   v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
   13459       "var result = [];"
   13460       "result[0] = {};"
   13461       "result[1] = {a: 1, b: 2};"
   13462       "result[2] = [1, 2, 3];"
   13463       "var proto = {x: 1, y: 2, z: 3};"
   13464       "var x = { __proto__: proto, w: 0, z: 1 };"
   13465       "result[3] = x;"
   13466       "result;"))->Run();
   13467   v8::Handle<v8::Array> elms = obj.As<v8::Array>();
   13468   CHECK_EQ(4, elms->Length());
   13469   int elmc0 = 0;
   13470   const char** elmv0 = NULL;
   13471   CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
   13472 
   13473   v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0));
   13474   v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
   13475   CHECK_EQ(0, props->Length());
   13476   for (uint32_t i = 0; i < props->Length(); i++) {
   13477     printf("p[%d]\n", i);
   13478   }
   13479 }
   13480 
   13481 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
   13482                                   Local<Value> name,
   13483                                   v8::AccessType type,
   13484                                   Local<Value> data) {
   13485   return type != v8::ACCESS_SET;
   13486 }
   13487 
   13488 
   13489 static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
   13490                                     uint32_t key,
   13491                                     v8::AccessType type,
   13492                                     Local<Value> data) {
   13493   return type != v8::ACCESS_SET;
   13494 }
   13495 
   13496 
   13497 THREADED_TEST(DisableAccessChecksWhileConfiguring) {
   13498   LocalContext context;
   13499   v8::HandleScope scope(context->GetIsolate());
   13500   Local<ObjectTemplate> templ = ObjectTemplate::New();
   13501   templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   13502                                  IndexedSetAccessBlocker);
   13503   templ->Set(v8_str("x"), v8::True());
   13504   Local<v8::Object> instance = templ->NewInstance();
   13505   context->Global()->Set(v8_str("obj"), instance);
   13506   Local<Value> value = CompileRun("obj.x");
   13507   CHECK(value->BooleanValue());
   13508 }
   13509 
   13510 
   13511 static bool NamedGetAccessBlocker(Local<v8::Object> obj,
   13512                                   Local<Value> name,
   13513                                   v8::AccessType type,
   13514                                   Local<Value> data) {
   13515   return false;
   13516 }
   13517 
   13518 
   13519 static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
   13520                                     uint32_t key,
   13521                                     v8::AccessType type,
   13522                                     Local<Value> data) {
   13523   return false;
   13524 }
   13525 
   13526 
   13527 
   13528 THREADED_TEST(AccessChecksReenabledCorrectly) {
   13529   LocalContext context;
   13530   v8::HandleScope scope(context->GetIsolate());
   13531   Local<ObjectTemplate> templ = ObjectTemplate::New();
   13532   templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   13533                                  IndexedGetAccessBlocker);
   13534   templ->Set(v8_str("a"), v8_str("a"));
   13535   // Add more than 8 (see kMaxFastProperties) properties
   13536   // so that the constructor will force copying map.
   13537   // Cannot sprintf, gcc complains unsafety.
   13538   char buf[4];
   13539   for (char i = '0'; i <= '9' ; i++) {
   13540     buf[0] = i;
   13541     for (char j = '0'; j <= '9'; j++) {
   13542       buf[1] = j;
   13543       for (char k = '0'; k <= '9'; k++) {
   13544         buf[2] = k;
   13545         buf[3] = 0;
   13546         templ->Set(v8_str(buf), v8::Number::New(k));
   13547       }
   13548     }
   13549   }
   13550 
   13551   Local<v8::Object> instance_1 = templ->NewInstance();
   13552   context->Global()->Set(v8_str("obj_1"), instance_1);
   13553 
   13554   Local<Value> value_1 = CompileRun("obj_1.a");
   13555   CHECK(value_1->IsUndefined());
   13556 
   13557   Local<v8::Object> instance_2 = templ->NewInstance();
   13558   context->Global()->Set(v8_str("obj_2"), instance_2);
   13559 
   13560   Local<Value> value_2 = CompileRun("obj_2.a");
   13561   CHECK(value_2->IsUndefined());
   13562 }
   13563 
   13564 
   13565 // This tests that access check information remains on the global
   13566 // object template when creating contexts.
   13567 THREADED_TEST(AccessControlRepeatedContextCreation) {
   13568   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   13569   v8::HandleScope handle_scope(isolate);
   13570   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   13571   global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
   13572                                            IndexedSetAccessBlocker);
   13573   i::Handle<i::ObjectTemplateInfo> internal_template =
   13574       v8::Utils::OpenHandle(*global_template);
   13575   CHECK(!internal_template->constructor()->IsUndefined());
   13576   i::Handle<i::FunctionTemplateInfo> constructor(
   13577       i::FunctionTemplateInfo::cast(internal_template->constructor()));
   13578   CHECK(!constructor->access_check_info()->IsUndefined());
   13579   v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
   13580   CHECK(!context0.IsEmpty());
   13581   CHECK(!constructor->access_check_info()->IsUndefined());
   13582 }
   13583 
   13584 
   13585 THREADED_TEST(TurnOnAccessCheck) {
   13586   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   13587   v8::HandleScope handle_scope(isolate);
   13588 
   13589   // Create an environment with access check to the global object disabled by
   13590   // default.
   13591   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   13592   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   13593                                            IndexedGetAccessBlocker,
   13594                                            v8::Handle<v8::Value>(),
   13595                                            false);
   13596   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
   13597   Context::Scope context_scope(context);
   13598 
   13599   // Set up a property and a number of functions.
   13600   context->Global()->Set(v8_str("a"), v8_num(1));
   13601   CompileRun("function f1() {return a;}"
   13602              "function f2() {return a;}"
   13603              "function g1() {return h();}"
   13604              "function g2() {return h();}"
   13605              "function h() {return 1;}");
   13606   Local<Function> f1 =
   13607       Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   13608   Local<Function> f2 =
   13609       Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   13610   Local<Function> g1 =
   13611       Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   13612   Local<Function> g2 =
   13613       Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   13614   Local<Function> h =
   13615       Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   13616 
   13617   // Get the global object.
   13618   v8::Handle<v8::Object> global = context->Global();
   13619 
   13620   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   13621   // uses the runtime system to retreive property a whereas f2 uses global load
   13622   // inline cache.
   13623   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   13624   for (int i = 0; i < 4; i++) {
   13625     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   13626   }
   13627 
   13628   // Same for g1 and g2.
   13629   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   13630   for (int i = 0; i < 4; i++) {
   13631     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   13632   }
   13633 
   13634   // Detach the global and turn on access check.
   13635   context->DetachGlobal();
   13636   context->Global()->TurnOnAccessCheck();
   13637 
   13638   // Failing access check to property get results in undefined.
   13639   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   13640   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   13641 
   13642   // Failing access check to function call results in exception.
   13643   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   13644   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   13645 
   13646   // No failing access check when just returning a constant.
   13647   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   13648 }
   13649 
   13650 
   13651 static const char* kPropertyA = "a";
   13652 static const char* kPropertyH = "h";
   13653 
   13654 static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
   13655                                        Local<Value> name,
   13656                                        v8::AccessType type,
   13657                                        Local<Value> data) {
   13658   if (!name->IsString()) return false;
   13659   i::Handle<i::String> name_handle =
   13660       v8::Utils::OpenHandle(String::Cast(*name));
   13661   return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
   13662       && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
   13663 }
   13664 
   13665 
   13666 THREADED_TEST(TurnOnAccessCheckAndRecompile) {
   13667   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   13668   v8::HandleScope handle_scope(isolate);
   13669 
   13670   // Create an environment with access check to the global object disabled by
   13671   // default. When the registered access checker will block access to properties
   13672   // a and h.
   13673   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   13674   global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
   13675                                            IndexedGetAccessBlocker,
   13676                                            v8::Handle<v8::Value>(),
   13677                                            false);
   13678   v8::Local<Context> context = Context::New(isolate, NULL, global_template);
   13679   Context::Scope context_scope(context);
   13680 
   13681   // Set up a property and a number of functions.
   13682   context->Global()->Set(v8_str("a"), v8_num(1));
   13683   static const char* source = "function f1() {return a;}"
   13684                               "function f2() {return a;}"
   13685                               "function g1() {return h();}"
   13686                               "function g2() {return h();}"
   13687                               "function h() {return 1;}";
   13688 
   13689   CompileRun(source);
   13690   Local<Function> f1;
   13691   Local<Function> f2;
   13692   Local<Function> g1;
   13693   Local<Function> g2;
   13694   Local<Function> h;
   13695   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   13696   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   13697   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   13698   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   13699   h =  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
   13700 
   13701   // Get the global object.
   13702   v8::Handle<v8::Object> global = context->Global();
   13703 
   13704   // Call f1 one time and f2 a number of times. This will ensure that f1 still
   13705   // uses the runtime system to retreive property a whereas f2 uses global load
   13706   // inline cache.
   13707   CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
   13708   for (int i = 0; i < 4; i++) {
   13709     CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
   13710   }
   13711 
   13712   // Same for g1 and g2.
   13713   CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
   13714   for (int i = 0; i < 4; i++) {
   13715     CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
   13716   }
   13717 
   13718   // Detach the global and turn on access check now blocking access to property
   13719   // a and function h.
   13720   context->DetachGlobal();
   13721   context->Global()->TurnOnAccessCheck();
   13722 
   13723   // Failing access check to property get results in undefined.
   13724   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   13725   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   13726 
   13727   // Failing access check to function call results in exception.
   13728   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   13729   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   13730 
   13731   // No failing access check when just returning a constant.
   13732   CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
   13733 
   13734   // Now compile the source again. And get the newly compiled functions, except
   13735   // for h for which access is blocked.
   13736   CompileRun(source);
   13737   f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
   13738   f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
   13739   g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
   13740   g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
   13741   CHECK(context->Global()->Get(v8_str("h"))->IsUndefined());
   13742 
   13743   // Failing access check to property get results in undefined.
   13744   CHECK(f1->Call(global, 0, NULL)->IsUndefined());
   13745   CHECK(f2->Call(global, 0, NULL)->IsUndefined());
   13746 
   13747   // Failing access check to function call results in exception.
   13748   CHECK(g1->Call(global, 0, NULL).IsEmpty());
   13749   CHECK(g2->Call(global, 0, NULL).IsEmpty());
   13750 }
   13751 
   13752 
   13753 // This test verifies that pre-compilation (aka preparsing) can be called
   13754 // without initializing the whole VM. Thus we cannot run this test in a
   13755 // multi-threaded setup.
   13756 TEST(PreCompile) {
   13757   // TODO(155): This test would break without the initialization of V8. This is
   13758   // a workaround for now to make this test not fail.
   13759   v8::V8::Initialize();
   13760   const char* script = "function foo(a) { return a+1; }";
   13761   v8::ScriptData* sd =
   13762       v8::ScriptData::PreCompile(script, i::StrLength(script));
   13763   CHECK_NE(sd->Length(), 0);
   13764   CHECK_NE(sd->Data(), NULL);
   13765   CHECK(!sd->HasError());
   13766   delete sd;
   13767 }
   13768 
   13769 
   13770 TEST(PreCompileWithError) {
   13771   v8::V8::Initialize();
   13772   const char* script = "function foo(a) { return 1 * * 2; }";
   13773   v8::ScriptData* sd =
   13774       v8::ScriptData::PreCompile(script, i::StrLength(script));
   13775   CHECK(sd->HasError());
   13776   delete sd;
   13777 }
   13778 
   13779 
   13780 TEST(Regress31661) {
   13781   v8::V8::Initialize();
   13782   const char* script = " The Definintive Guide";
   13783   v8::ScriptData* sd =
   13784       v8::ScriptData::PreCompile(script, i::StrLength(script));
   13785   CHECK(sd->HasError());
   13786   delete sd;
   13787 }
   13788 
   13789 
   13790 // Tests that ScriptData can be serialized and deserialized.
   13791 TEST(PreCompileSerialization) {
   13792   v8::V8::Initialize();
   13793   const char* script = "function foo(a) { return a+1; }";
   13794   v8::ScriptData* sd =
   13795       v8::ScriptData::PreCompile(script, i::StrLength(script));
   13796 
   13797   // Serialize.
   13798   int serialized_data_length = sd->Length();
   13799   char* serialized_data = i::NewArray<char>(serialized_data_length);
   13800   i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
   13801 
   13802   // Deserialize.
   13803   v8::ScriptData* deserialized_sd =
   13804       v8::ScriptData::New(serialized_data, serialized_data_length);
   13805 
   13806   // Verify that the original is the same as the deserialized.
   13807   CHECK_EQ(sd->Length(), deserialized_sd->Length());
   13808   CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
   13809   CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
   13810 
   13811   delete sd;
   13812   delete deserialized_sd;
   13813 }
   13814 
   13815 
   13816 // Attempts to deserialize bad data.
   13817 TEST(PreCompileDeserializationError) {
   13818   v8::V8::Initialize();
   13819   const char* data = "DONT CARE";
   13820   int invalid_size = 3;
   13821   v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
   13822 
   13823   CHECK_EQ(0, sd->Length());
   13824 
   13825   delete sd;
   13826 }
   13827 
   13828 
   13829 // Attempts to deserialize bad data.
   13830 TEST(PreCompileInvalidPreparseDataError) {
   13831   v8::V8::Initialize();
   13832   LocalContext context;
   13833   v8::HandleScope scope(context->GetIsolate());
   13834 
   13835   const char* script = "function foo(){ return 5;}\n"
   13836       "function bar(){ return 6 + 7;}  foo();";
   13837   v8::ScriptData* sd =
   13838       v8::ScriptData::PreCompile(script, i::StrLength(script));
   13839   CHECK(!sd->HasError());
   13840   // ScriptDataImpl private implementation details
   13841   const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
   13842   const int kFunctionEntrySize = i::FunctionEntry::kSize;
   13843   const int kFunctionEntryStartOffset = 0;
   13844   const int kFunctionEntryEndOffset = 1;
   13845   unsigned* sd_data =
   13846       reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
   13847 
   13848   // Overwrite function bar's end position with 0.
   13849   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
   13850   v8::TryCatch try_catch;
   13851 
   13852   Local<String> source = String::New(script);
   13853   Local<Script> compiled_script = Script::New(source, NULL, sd);
   13854   CHECK(try_catch.HasCaught());
   13855   String::Utf8Value exception_value(try_catch.Message()->Get());
   13856   CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
   13857            *exception_value);
   13858 
   13859   try_catch.Reset();
   13860 
   13861   // Overwrite function bar's start position with 200.  The function entry
   13862   // will not be found when searching for it by position and we should fall
   13863   // back on eager compilation.
   13864   sd = v8::ScriptData::PreCompile(script, i::StrLength(script));
   13865   sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
   13866   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
   13867       200;
   13868   compiled_script = Script::New(source, NULL, sd);
   13869   CHECK(!try_catch.HasCaught());
   13870 
   13871   delete sd;
   13872 }
   13873 
   13874 
   13875 // Verifies that the Handle<String> and const char* versions of the API produce
   13876 // the same results (at least for one trivial case).
   13877 TEST(PreCompileAPIVariationsAreSame) {
   13878   v8::V8::Initialize();
   13879   v8::HandleScope scope(v8::Isolate::GetCurrent());
   13880 
   13881   const char* cstring = "function foo(a) { return a+1; }";
   13882 
   13883   v8::ScriptData* sd_from_cstring =
   13884       v8::ScriptData::PreCompile(cstring, i::StrLength(cstring));
   13885 
   13886   TestAsciiResource* resource = new TestAsciiResource(cstring);
   13887   v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
   13888       v8::String::NewExternal(resource));
   13889 
   13890   v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
   13891       v8::String::New(cstring));
   13892 
   13893   CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
   13894   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
   13895                      sd_from_external_string->Data(),
   13896                      sd_from_cstring->Length()));
   13897 
   13898   CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
   13899   CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
   13900                      sd_from_string->Data(),
   13901                      sd_from_cstring->Length()));
   13902 
   13903 
   13904   delete sd_from_cstring;
   13905   delete sd_from_external_string;
   13906   delete sd_from_string;
   13907 }
   13908 
   13909 
   13910 // This tests that we do not allow dictionary load/call inline caches
   13911 // to use functions that have not yet been compiled.  The potential
   13912 // problem of loading a function that has not yet been compiled can
   13913 // arise because we share code between contexts via the compilation
   13914 // cache.
   13915 THREADED_TEST(DictionaryICLoadedFunction) {
   13916   v8::HandleScope scope(v8::Isolate::GetCurrent());
   13917   // Test LoadIC.
   13918   for (int i = 0; i < 2; i++) {
   13919     LocalContext context;
   13920     context->Global()->Set(v8_str("tmp"), v8::True());
   13921     context->Global()->Delete(v8_str("tmp"));
   13922     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   13923   }
   13924   // Test CallIC.
   13925   for (int i = 0; i < 2; i++) {
   13926     LocalContext context;
   13927     context->Global()->Set(v8_str("tmp"), v8::True());
   13928     context->Global()->Delete(v8_str("tmp"));
   13929     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   13930   }
   13931 }
   13932 
   13933 
   13934 // Test that cross-context new calls use the context of the callee to
   13935 // create the new JavaScript object.
   13936 THREADED_TEST(CrossContextNew) {
   13937   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   13938   v8::HandleScope scope(isolate);
   13939   v8::Local<Context> context0 = Context::New(isolate);
   13940   v8::Local<Context> context1 = Context::New(isolate);
   13941 
   13942   // Allow cross-domain access.
   13943   Local<String> token = v8_str("<security token>");
   13944   context0->SetSecurityToken(token);
   13945   context1->SetSecurityToken(token);
   13946 
   13947   // Set an 'x' property on the Object prototype and define a
   13948   // constructor function in context0.
   13949   context0->Enter();
   13950   CompileRun("Object.prototype.x = 42; function C() {};");
   13951   context0->Exit();
   13952 
   13953   // Call the constructor function from context0 and check that the
   13954   // result has the 'x' property.
   13955   context1->Enter();
   13956   context1->Global()->Set(v8_str("other"), context0->Global());
   13957   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   13958   CHECK(value->IsInt32());
   13959   CHECK_EQ(42, value->Int32Value());
   13960   context1->Exit();
   13961 }
   13962 
   13963 
   13964 class RegExpInterruptTest {
   13965  public:
   13966   RegExpInterruptTest() : block_(NULL) {}
   13967   ~RegExpInterruptTest() { delete block_; }
   13968   void RunTest() {
   13969     block_ = i::OS::CreateSemaphore(0);
   13970     gc_count_ = 0;
   13971     gc_during_regexp_ = 0;
   13972     regexp_success_ = false;
   13973     gc_success_ = false;
   13974     GCThread gc_thread(this);
   13975     gc_thread.Start();
   13976     v8::Locker::StartPreemption(1);
   13977 
   13978     LongRunningRegExp();
   13979     {
   13980       v8::Unlocker unlock(CcTest::default_isolate());
   13981       gc_thread.Join();
   13982     }
   13983     v8::Locker::StopPreemption();
   13984     CHECK(regexp_success_);
   13985     CHECK(gc_success_);
   13986   }
   13987 
   13988  private:
   13989   // Number of garbage collections required.
   13990   static const int kRequiredGCs = 5;
   13991 
   13992   class GCThread : public i::Thread {
   13993    public:
   13994     explicit GCThread(RegExpInterruptTest* test)
   13995         : Thread("GCThread"), test_(test) {}
   13996     virtual void Run() {
   13997       test_->CollectGarbage();
   13998     }
   13999    private:
   14000      RegExpInterruptTest* test_;
   14001   };
   14002 
   14003   void CollectGarbage() {
   14004     block_->Wait();
   14005     while (gc_during_regexp_ < kRequiredGCs) {
   14006       {
   14007         v8::Locker lock(CcTest::default_isolate());
   14008         // TODO(lrn): Perhaps create some garbage before collecting.
   14009         HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14010         gc_count_++;
   14011       }
   14012       i::OS::Sleep(1);
   14013     }
   14014     gc_success_ = true;
   14015   }
   14016 
   14017   void LongRunningRegExp() {
   14018     block_->Signal();  // Enable garbage collection thread on next preemption.
   14019     int rounds = 0;
   14020     while (gc_during_regexp_ < kRequiredGCs) {
   14021       int gc_before = gc_count_;
   14022       {
   14023         // Match 15-30 "a"'s against 14 and a "b".
   14024         const char* c_source =
   14025             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
   14026             ".exec('aaaaaaaaaaaaaaab') === null";
   14027         Local<String> source = String::New(c_source);
   14028         Local<Script> script = Script::Compile(source);
   14029         Local<Value> result = script->Run();
   14030         if (!result->BooleanValue()) {
   14031           gc_during_regexp_ = kRequiredGCs;  // Allow gc thread to exit.
   14032           return;
   14033         }
   14034       }
   14035       {
   14036         // Match 15-30 "a"'s against 15 and a "b".
   14037         const char* c_source =
   14038             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
   14039             ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
   14040         Local<String> source = String::New(c_source);
   14041         Local<Script> script = Script::Compile(source);
   14042         Local<Value> result = script->Run();
   14043         if (!result->BooleanValue()) {
   14044           gc_during_regexp_ = kRequiredGCs;
   14045           return;
   14046         }
   14047       }
   14048       int gc_after = gc_count_;
   14049       gc_during_regexp_ += gc_after - gc_before;
   14050       rounds++;
   14051       i::OS::Sleep(1);
   14052     }
   14053     regexp_success_ = true;
   14054   }
   14055 
   14056   i::Semaphore* block_;
   14057   int gc_count_;
   14058   int gc_during_regexp_;
   14059   bool regexp_success_;
   14060   bool gc_success_;
   14061 };
   14062 
   14063 
   14064 // Test that a regular expression execution can be interrupted and
   14065 // survive a garbage collection.
   14066 TEST(RegExpInterruption) {
   14067   v8::Locker lock(CcTest::default_isolate());
   14068   v8::V8::Initialize();
   14069   v8::HandleScope scope(CcTest::default_isolate());
   14070   Local<Context> local_env;
   14071   {
   14072     LocalContext env;
   14073     local_env = env.local();
   14074   }
   14075 
   14076   // Local context should still be live.
   14077   CHECK(!local_env.IsEmpty());
   14078   local_env->Enter();
   14079 
   14080   // Should complete without problems.
   14081   RegExpInterruptTest().RunTest();
   14082 
   14083   local_env->Exit();
   14084 }
   14085 
   14086 
   14087 class ApplyInterruptTest {
   14088  public:
   14089   ApplyInterruptTest() : block_(NULL) {}
   14090   ~ApplyInterruptTest() { delete block_; }
   14091   void RunTest() {
   14092     block_ = i::OS::CreateSemaphore(0);
   14093     gc_count_ = 0;
   14094     gc_during_apply_ = 0;
   14095     apply_success_ = false;
   14096     gc_success_ = false;
   14097     GCThread gc_thread(this);
   14098     gc_thread.Start();
   14099     v8::Locker::StartPreemption(1);
   14100 
   14101     LongRunningApply();
   14102     {
   14103       v8::Unlocker unlock(CcTest::default_isolate());
   14104       gc_thread.Join();
   14105     }
   14106     v8::Locker::StopPreemption();
   14107     CHECK(apply_success_);
   14108     CHECK(gc_success_);
   14109   }
   14110 
   14111  private:
   14112   // Number of garbage collections required.
   14113   static const int kRequiredGCs = 2;
   14114 
   14115   class GCThread : public i::Thread {
   14116    public:
   14117     explicit GCThread(ApplyInterruptTest* test)
   14118         : Thread("GCThread"), test_(test) {}
   14119     virtual void Run() {
   14120       test_->CollectGarbage();
   14121     }
   14122    private:
   14123      ApplyInterruptTest* test_;
   14124   };
   14125 
   14126   void CollectGarbage() {
   14127     block_->Wait();
   14128     while (gc_during_apply_ < kRequiredGCs) {
   14129       {
   14130         v8::Locker lock(CcTest::default_isolate());
   14131         HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14132         gc_count_++;
   14133       }
   14134       i::OS::Sleep(1);
   14135     }
   14136     gc_success_ = true;
   14137   }
   14138 
   14139   void LongRunningApply() {
   14140     block_->Signal();
   14141     int rounds = 0;
   14142     while (gc_during_apply_ < kRequiredGCs) {
   14143       int gc_before = gc_count_;
   14144       {
   14145         const char* c_source =
   14146             "function do_very_little(bar) {"
   14147             "  this.foo = bar;"
   14148             "}"
   14149             "for (var i = 0; i < 100000; i++) {"
   14150             "  do_very_little.apply(this, ['bar']);"
   14151             "}";
   14152         Local<String> source = String::New(c_source);
   14153         Local<Script> script = Script::Compile(source);
   14154         Local<Value> result = script->Run();
   14155         // Check that no exception was thrown.
   14156         CHECK(!result.IsEmpty());
   14157       }
   14158       int gc_after = gc_count_;
   14159       gc_during_apply_ += gc_after - gc_before;
   14160       rounds++;
   14161     }
   14162     apply_success_ = true;
   14163   }
   14164 
   14165   i::Semaphore* block_;
   14166   int gc_count_;
   14167   int gc_during_apply_;
   14168   bool apply_success_;
   14169   bool gc_success_;
   14170 };
   14171 
   14172 
   14173 // Test that nothing bad happens if we get a preemption just when we were
   14174 // about to do an apply().
   14175 TEST(ApplyInterruption) {
   14176   v8::Locker lock(CcTest::default_isolate());
   14177   v8::V8::Initialize();
   14178   v8::HandleScope scope(CcTest::default_isolate());
   14179   Local<Context> local_env;
   14180   {
   14181     LocalContext env;
   14182     local_env = env.local();
   14183   }
   14184 
   14185   // Local context should still be live.
   14186   CHECK(!local_env.IsEmpty());
   14187   local_env->Enter();
   14188 
   14189   // Should complete without problems.
   14190   ApplyInterruptTest().RunTest();
   14191 
   14192   local_env->Exit();
   14193 }
   14194 
   14195 
   14196 // Verify that we can clone an object
   14197 TEST(ObjectClone) {
   14198   LocalContext env;
   14199   v8::HandleScope scope(env->GetIsolate());
   14200 
   14201   const char* sample =
   14202     "var rv = {};"      \
   14203     "rv.alpha = 'hello';" \
   14204     "rv.beta = 123;"     \
   14205     "rv;";
   14206 
   14207   // Create an object, verify basics.
   14208   Local<Value> val = CompileRun(sample);
   14209   CHECK(val->IsObject());
   14210   Local<v8::Object> obj = val.As<v8::Object>();
   14211   obj->Set(v8_str("gamma"), v8_str("cloneme"));
   14212 
   14213   CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
   14214   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
   14215   CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
   14216 
   14217   // Clone it.
   14218   Local<v8::Object> clone = obj->Clone();
   14219   CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
   14220   CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
   14221   CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
   14222 
   14223   // Set a property on the clone, verify each object.
   14224   clone->Set(v8_str("beta"), v8::Integer::New(456));
   14225   CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
   14226   CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
   14227 }
   14228 
   14229 
   14230 class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
   14231  public:
   14232   explicit AsciiVectorResource(i::Vector<const char> vector)
   14233       : data_(vector) {}
   14234   virtual ~AsciiVectorResource() {}
   14235   virtual size_t length() const { return data_.length(); }
   14236   virtual const char* data() const { return data_.start(); }
   14237  private:
   14238   i::Vector<const char> data_;
   14239 };
   14240 
   14241 
   14242 class UC16VectorResource : public v8::String::ExternalStringResource {
   14243  public:
   14244   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   14245       : data_(vector) {}
   14246   virtual ~UC16VectorResource() {}
   14247   virtual size_t length() const { return data_.length(); }
   14248   virtual const i::uc16* data() const { return data_.start(); }
   14249  private:
   14250   i::Vector<const i::uc16> data_;
   14251 };
   14252 
   14253 
   14254 static void MorphAString(i::String* string,
   14255                          AsciiVectorResource* ascii_resource,
   14256                          UC16VectorResource* uc16_resource) {
   14257   CHECK(i::StringShape(string).IsExternal());
   14258   if (string->IsOneByteRepresentation()) {
   14259     // Check old map is not internalized or long.
   14260     CHECK(string->map() == HEAP->external_ascii_string_map());
   14261     // Morph external string to be TwoByte string.
   14262     string->set_map(HEAP->external_string_map());
   14263     i::ExternalTwoByteString* morphed =
   14264          i::ExternalTwoByteString::cast(string);
   14265     morphed->set_resource(uc16_resource);
   14266   } else {
   14267     // Check old map is not internalized or long.
   14268     CHECK(string->map() == HEAP->external_string_map());
   14269     // Morph external string to be ASCII string.
   14270     string->set_map(HEAP->external_ascii_string_map());
   14271     i::ExternalAsciiString* morphed =
   14272          i::ExternalAsciiString::cast(string);
   14273     morphed->set_resource(ascii_resource);
   14274   }
   14275 }
   14276 
   14277 
   14278 // Test that we can still flatten a string if the components it is built up
   14279 // from have been turned into 16 bit strings in the mean time.
   14280 THREADED_TEST(MorphCompositeStringTest) {
   14281   char utf_buffer[129];
   14282   const char* c_string = "Now is the time for all good men"
   14283                          " to come to the aid of the party";
   14284   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   14285   {
   14286     LocalContext env;
   14287     i::Factory* factory = i::Isolate::Current()->factory();
   14288     v8::HandleScope scope(env->GetIsolate());
   14289     AsciiVectorResource ascii_resource(
   14290         i::Vector<const char>(c_string, i::StrLength(c_string)));
   14291     UC16VectorResource uc16_resource(
   14292         i::Vector<const uint16_t>(two_byte_string,
   14293                                   i::StrLength(c_string)));
   14294 
   14295     Local<String> lhs(v8::Utils::ToLocal(
   14296         factory->NewExternalStringFromAscii(&ascii_resource)));
   14297     Local<String> rhs(v8::Utils::ToLocal(
   14298         factory->NewExternalStringFromAscii(&ascii_resource)));
   14299 
   14300     env->Global()->Set(v8_str("lhs"), lhs);
   14301     env->Global()->Set(v8_str("rhs"), rhs);
   14302 
   14303     CompileRun(
   14304         "var cons = lhs + rhs;"
   14305         "var slice = lhs.substring(1, lhs.length - 1);"
   14306         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   14307 
   14308     CHECK(lhs->IsOneByte());
   14309     CHECK(rhs->IsOneByte());
   14310 
   14311     MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
   14312     MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
   14313 
   14314     // This should UTF-8 without flattening, since everything is ASCII.
   14315     Handle<String> cons = v8_compile("cons")->Run().As<String>();
   14316     CHECK_EQ(128, cons->Utf8Length());
   14317     int nchars = -1;
   14318     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
   14319     CHECK_EQ(128, nchars);
   14320     CHECK_EQ(0, strcmp(
   14321         utf_buffer,
   14322         "Now is the time for all good men to come to the aid of the party"
   14323         "Now is the time for all good men to come to the aid of the party"));
   14324 
   14325     // Now do some stuff to make sure the strings are flattened, etc.
   14326     CompileRun(
   14327         "/[^a-z]/.test(cons);"
   14328         "/[^a-z]/.test(slice);"
   14329         "/[^a-z]/.test(slice_on_cons);");
   14330     const char* expected_cons =
   14331         "Now is the time for all good men to come to the aid of the party"
   14332         "Now is the time for all good men to come to the aid of the party";
   14333     const char* expected_slice =
   14334         "ow is the time for all good men to come to the aid of the part";
   14335     const char* expected_slice_on_cons =
   14336         "ow is the time for all good men to come to the aid of the party"
   14337         "Now is the time for all good men to come to the aid of the part";
   14338     CHECK_EQ(String::New(expected_cons),
   14339              env->Global()->Get(v8_str("cons")));
   14340     CHECK_EQ(String::New(expected_slice),
   14341              env->Global()->Get(v8_str("slice")));
   14342     CHECK_EQ(String::New(expected_slice_on_cons),
   14343              env->Global()->Get(v8_str("slice_on_cons")));
   14344   }
   14345   i::DeleteArray(two_byte_string);
   14346 }
   14347 
   14348 
   14349 TEST(CompileExternalTwoByteSource) {
   14350   LocalContext context;
   14351   v8::HandleScope scope(context->GetIsolate());
   14352 
   14353   // This is a very short list of sources, which currently is to check for a
   14354   // regression caused by r2703.
   14355   const char* ascii_sources[] = {
   14356     "0.5",
   14357     "-0.5",   // This mainly testes PushBack in the Scanner.
   14358     "--0.5",  // This mainly testes PushBack in the Scanner.
   14359     NULL
   14360   };
   14361 
   14362   // Compile the sources as external two byte strings.
   14363   for (int i = 0; ascii_sources[i] != NULL; i++) {
   14364     uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
   14365     UC16VectorResource uc16_resource(
   14366         i::Vector<const uint16_t>(two_byte_string,
   14367                                   i::StrLength(ascii_sources[i])));
   14368     v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
   14369     v8::Script::Compile(source);
   14370     i::DeleteArray(two_byte_string);
   14371   }
   14372 }
   14373 
   14374 
   14375 class RegExpStringModificationTest {
   14376  public:
   14377   RegExpStringModificationTest()
   14378       : block_(i::OS::CreateSemaphore(0)),
   14379         morphs_(0),
   14380         morphs_during_regexp_(0),
   14381         ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
   14382         uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
   14383   ~RegExpStringModificationTest() { delete block_; }
   14384   void RunTest() {
   14385     i::Factory* factory = i::Isolate::Current()->factory();
   14386 
   14387     regexp_success_ = false;
   14388     morph_success_ = false;
   14389 
   14390     // Initialize the contents of two_byte_content_ to be a uc16 representation
   14391     // of "aaaaaaaaaaaaaab".
   14392     for (int i = 0; i < 14; i++) {
   14393       two_byte_content_[i] = 'a';
   14394     }
   14395     two_byte_content_[14] = 'b';
   14396 
   14397     // Create the input string for the regexp - the one we are going to change
   14398     // properties of.
   14399     input_ = factory->NewExternalStringFromAscii(&ascii_resource_);
   14400 
   14401     // Inject the input as a global variable.
   14402     i::Handle<i::String> input_name =
   14403         factory->NewStringFromAscii(i::Vector<const char>("input", 5));
   14404     i::Isolate::Current()->native_context()->global_object()->SetProperty(
   14405         *input_name,
   14406         *input_,
   14407         NONE,
   14408         i::kNonStrictMode)->ToObjectChecked();
   14409 
   14410     MorphThread morph_thread(this);
   14411     morph_thread.Start();
   14412     v8::Locker::StartPreemption(1);
   14413     LongRunningRegExp();
   14414     {
   14415       v8::Unlocker unlock(CcTest::default_isolate());
   14416       morph_thread.Join();
   14417     }
   14418     v8::Locker::StopPreemption();
   14419     CHECK(regexp_success_);
   14420     CHECK(morph_success_);
   14421   }
   14422 
   14423  private:
   14424   // Number of string modifications required.
   14425   static const int kRequiredModifications = 5;
   14426   static const int kMaxModifications = 100;
   14427 
   14428   class MorphThread : public i::Thread {
   14429    public:
   14430     explicit MorphThread(RegExpStringModificationTest* test)
   14431         : Thread("MorphThread"), test_(test) {}
   14432     virtual void Run() {
   14433       test_->MorphString();
   14434     }
   14435    private:
   14436      RegExpStringModificationTest* test_;
   14437   };
   14438 
   14439   void MorphString() {
   14440     block_->Wait();
   14441     while (morphs_during_regexp_ < kRequiredModifications &&
   14442            morphs_ < kMaxModifications) {
   14443       {
   14444         v8::Locker lock(CcTest::default_isolate());
   14445         // Swap string between ascii and two-byte representation.
   14446         i::String* string = *input_;
   14447         MorphAString(string, &ascii_resource_, &uc16_resource_);
   14448         morphs_++;
   14449       }
   14450       i::OS::Sleep(1);
   14451     }
   14452     morph_success_ = true;
   14453   }
   14454 
   14455   void LongRunningRegExp() {
   14456     block_->Signal();  // Enable morphing thread on next preemption.
   14457     while (morphs_during_regexp_ < kRequiredModifications &&
   14458            morphs_ < kMaxModifications) {
   14459       int morphs_before = morphs_;
   14460       {
   14461         v8::HandleScope scope(v8::Isolate::GetCurrent());
   14462         // Match 15-30 "a"'s against 14 and a "b".
   14463         const char* c_source =
   14464             "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
   14465             ".exec(input) === null";
   14466         Local<String> source = String::New(c_source);
   14467         Local<Script> script = Script::Compile(source);
   14468         Local<Value> result = script->Run();
   14469         CHECK(result->IsTrue());
   14470       }
   14471       int morphs_after = morphs_;
   14472       morphs_during_regexp_ += morphs_after - morphs_before;
   14473     }
   14474     regexp_success_ = true;
   14475   }
   14476 
   14477   i::uc16 two_byte_content_[15];
   14478   i::Semaphore* block_;
   14479   int morphs_;
   14480   int morphs_during_regexp_;
   14481   bool regexp_success_;
   14482   bool morph_success_;
   14483   i::Handle<i::String> input_;
   14484   AsciiVectorResource ascii_resource_;
   14485   UC16VectorResource uc16_resource_;
   14486 };
   14487 
   14488 
   14489 // Test that a regular expression execution can be interrupted and
   14490 // the string changed without failing.
   14491 TEST(RegExpStringModification) {
   14492   v8::Locker lock(CcTest::default_isolate());
   14493   v8::V8::Initialize();
   14494   v8::HandleScope scope(CcTest::default_isolate());
   14495   Local<Context> local_env;
   14496   {
   14497     LocalContext env;
   14498     local_env = env.local();
   14499   }
   14500 
   14501   // Local context should still be live.
   14502   CHECK(!local_env.IsEmpty());
   14503   local_env->Enter();
   14504 
   14505   // Should complete without problems.
   14506   RegExpStringModificationTest().RunTest();
   14507 
   14508   local_env->Exit();
   14509 }
   14510 
   14511 
   14512 // Test that we cannot set a property on the global object if there
   14513 // is a read-only property in the prototype chain.
   14514 TEST(ReadOnlyPropertyInGlobalProto) {
   14515   i::FLAG_es5_readonly = true;
   14516   v8::HandleScope scope(v8::Isolate::GetCurrent());
   14517   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   14518   LocalContext context(0, templ);
   14519   v8::Handle<v8::Object> global = context->Global();
   14520   v8::Handle<v8::Object> global_proto =
   14521       v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
   14522   global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
   14523   global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
   14524   // Check without 'eval' or 'with'.
   14525   v8::Handle<v8::Value> res =
   14526       CompileRun("function f() { x = 42; return x; }; f()");
   14527   CHECK_EQ(v8::Integer::New(0), res);
   14528   // Check with 'eval'.
   14529   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
   14530   CHECK_EQ(v8::Integer::New(0), res);
   14531   // Check with 'with'.
   14532   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
   14533   CHECK_EQ(v8::Integer::New(0), res);
   14534 }
   14535 
   14536 static int force_set_set_count = 0;
   14537 static int force_set_get_count = 0;
   14538 bool pass_on_get = false;
   14539 
   14540 static void ForceSetGetter(v8::Local<v8::String> name,
   14541                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   14542   force_set_get_count++;
   14543   if (pass_on_get) {
   14544     return;
   14545   }
   14546   info.GetReturnValue().Set(3);
   14547 }
   14548 
   14549 static void ForceSetSetter(v8::Local<v8::String> name,
   14550                            v8::Local<v8::Value> value,
   14551                            const v8::PropertyCallbackInfo<void>& info) {
   14552   force_set_set_count++;
   14553 }
   14554 
   14555 static void ForceSetInterceptSetter(
   14556     v8::Local<v8::String> name,
   14557     v8::Local<v8::Value> value,
   14558     const v8::PropertyCallbackInfo<v8::Value>& info) {
   14559   force_set_set_count++;
   14560   info.GetReturnValue().SetUndefined();
   14561 }
   14562 
   14563 
   14564 TEST(ForceSet) {
   14565   force_set_get_count = 0;
   14566   force_set_set_count = 0;
   14567   pass_on_get = false;
   14568 
   14569   v8::HandleScope scope(v8::Isolate::GetCurrent());
   14570   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   14571   v8::Handle<v8::String> access_property = v8::String::New("a");
   14572   templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
   14573   LocalContext context(NULL, templ);
   14574   v8::Handle<v8::Object> global = context->Global();
   14575 
   14576   // Ordinary properties
   14577   v8::Handle<v8::String> simple_property = v8::String::New("p");
   14578   global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
   14579   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   14580   // This should fail because the property is read-only
   14581   global->Set(simple_property, v8::Int32::New(5));
   14582   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   14583   // This should succeed even though the property is read-only
   14584   global->ForceSet(simple_property, v8::Int32::New(6));
   14585   CHECK_EQ(6, global->Get(simple_property)->Int32Value());
   14586 
   14587   // Accessors
   14588   CHECK_EQ(0, force_set_set_count);
   14589   CHECK_EQ(0, force_set_get_count);
   14590   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   14591   // CHECK_EQ the property shouldn't override it, just call the setter
   14592   // which in this case does nothing.
   14593   global->Set(access_property, v8::Int32::New(7));
   14594   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   14595   CHECK_EQ(1, force_set_set_count);
   14596   CHECK_EQ(2, force_set_get_count);
   14597   // Forcing the property to be set should override the accessor without
   14598   // calling it
   14599   global->ForceSet(access_property, v8::Int32::New(8));
   14600   CHECK_EQ(8, global->Get(access_property)->Int32Value());
   14601   CHECK_EQ(1, force_set_set_count);
   14602   CHECK_EQ(2, force_set_get_count);
   14603 }
   14604 
   14605 
   14606 TEST(ForceSetWithInterceptor) {
   14607   force_set_get_count = 0;
   14608   force_set_set_count = 0;
   14609   pass_on_get = false;
   14610 
   14611   v8::HandleScope scope(v8::Isolate::GetCurrent());
   14612   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   14613   templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
   14614   LocalContext context(NULL, templ);
   14615   v8::Handle<v8::Object> global = context->Global();
   14616 
   14617   v8::Handle<v8::String> some_property = v8::String::New("a");
   14618   CHECK_EQ(0, force_set_set_count);
   14619   CHECK_EQ(0, force_set_get_count);
   14620   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   14621   // Setting the property shouldn't override it, just call the setter
   14622   // which in this case does nothing.
   14623   global->Set(some_property, v8::Int32::New(7));
   14624   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   14625   CHECK_EQ(1, force_set_set_count);
   14626   CHECK_EQ(2, force_set_get_count);
   14627   // Getting the property when the interceptor returns an empty handle
   14628   // should yield undefined, since the property isn't present on the
   14629   // object itself yet.
   14630   pass_on_get = true;
   14631   CHECK(global->Get(some_property)->IsUndefined());
   14632   CHECK_EQ(1, force_set_set_count);
   14633   CHECK_EQ(3, force_set_get_count);
   14634   // Forcing the property to be set should cause the value to be
   14635   // set locally without calling the interceptor.
   14636   global->ForceSet(some_property, v8::Int32::New(8));
   14637   CHECK_EQ(8, global->Get(some_property)->Int32Value());
   14638   CHECK_EQ(1, force_set_set_count);
   14639   CHECK_EQ(4, force_set_get_count);
   14640   // Reenabling the interceptor should cause it to take precedence over
   14641   // the property
   14642   pass_on_get = false;
   14643   CHECK_EQ(3, global->Get(some_property)->Int32Value());
   14644   CHECK_EQ(1, force_set_set_count);
   14645   CHECK_EQ(5, force_set_get_count);
   14646   // The interceptor should also work for other properties
   14647   CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
   14648   CHECK_EQ(1, force_set_set_count);
   14649   CHECK_EQ(6, force_set_get_count);
   14650 }
   14651 
   14652 
   14653 THREADED_TEST(ForceDelete) {
   14654   v8::HandleScope scope(v8::Isolate::GetCurrent());
   14655   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   14656   LocalContext context(NULL, templ);
   14657   v8::Handle<v8::Object> global = context->Global();
   14658 
   14659   // Ordinary properties
   14660   v8::Handle<v8::String> simple_property = v8::String::New("p");
   14661   global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
   14662   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   14663   // This should fail because the property is dont-delete.
   14664   CHECK(!global->Delete(simple_property));
   14665   CHECK_EQ(4, global->Get(simple_property)->Int32Value());
   14666   // This should succeed even though the property is dont-delete.
   14667   CHECK(global->ForceDelete(simple_property));
   14668   CHECK(global->Get(simple_property)->IsUndefined());
   14669 }
   14670 
   14671 
   14672 static int force_delete_interceptor_count = 0;
   14673 static bool pass_on_delete = false;
   14674 
   14675 
   14676 static void ForceDeleteDeleter(
   14677     v8::Local<v8::String> name,
   14678     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   14679   force_delete_interceptor_count++;
   14680   if (pass_on_delete) return;
   14681   info.GetReturnValue().Set(true);
   14682 }
   14683 
   14684 
   14685 THREADED_TEST(ForceDeleteWithInterceptor) {
   14686   force_delete_interceptor_count = 0;
   14687   pass_on_delete = false;
   14688 
   14689   v8::HandleScope scope(v8::Isolate::GetCurrent());
   14690   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   14691   templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
   14692   LocalContext context(NULL, templ);
   14693   v8::Handle<v8::Object> global = context->Global();
   14694 
   14695   v8::Handle<v8::String> some_property = v8::String::New("a");
   14696   global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
   14697 
   14698   // Deleting a property should get intercepted and nothing should
   14699   // happen.
   14700   CHECK_EQ(0, force_delete_interceptor_count);
   14701   CHECK(global->Delete(some_property));
   14702   CHECK_EQ(1, force_delete_interceptor_count);
   14703   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   14704   // Deleting the property when the interceptor returns an empty
   14705   // handle should not delete the property since it is DontDelete.
   14706   pass_on_delete = true;
   14707   CHECK(!global->Delete(some_property));
   14708   CHECK_EQ(2, force_delete_interceptor_count);
   14709   CHECK_EQ(42, global->Get(some_property)->Int32Value());
   14710   // Forcing the property to be deleted should delete the value
   14711   // without calling the interceptor.
   14712   CHECK(global->ForceDelete(some_property));
   14713   CHECK(global->Get(some_property)->IsUndefined());
   14714   CHECK_EQ(2, force_delete_interceptor_count);
   14715 }
   14716 
   14717 
   14718 // Make sure that forcing a delete invalidates any IC stubs, so we
   14719 // don't read the hole value.
   14720 THREADED_TEST(ForceDeleteIC) {
   14721   LocalContext context;
   14722   v8::HandleScope scope(context->GetIsolate());
   14723   // Create a DontDelete variable on the global object.
   14724   CompileRun("this.__proto__ = { foo: 'horse' };"
   14725              "var foo = 'fish';"
   14726              "function f() { return foo.length; }");
   14727   // Initialize the IC for foo in f.
   14728   CompileRun("for (var i = 0; i < 4; i++) f();");
   14729   // Make sure the value of foo is correct before the deletion.
   14730   CHECK_EQ(4, CompileRun("f()")->Int32Value());
   14731   // Force the deletion of foo.
   14732   CHECK(context->Global()->ForceDelete(v8_str("foo")));
   14733   // Make sure the value for foo is read from the prototype, and that
   14734   // we don't get in trouble with reading the deleted cell value
   14735   // sentinel.
   14736   CHECK_EQ(5, CompileRun("f()")->Int32Value());
   14737 }
   14738 
   14739 
   14740 TEST(InlinedFunctionAcrossContexts) {
   14741   i::FLAG_allow_natives_syntax = true;
   14742   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   14743   v8::HandleScope outer_scope(isolate);
   14744   v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
   14745   v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
   14746   ctx1->Enter();
   14747 
   14748   {
   14749     v8::HandleScope inner_scope(v8::Isolate::GetCurrent());
   14750     CompileRun("var G = 42; function foo() { return G; }");
   14751     v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
   14752     ctx2->Enter();
   14753     ctx2->Global()->Set(v8_str("o"), foo);
   14754     v8::Local<v8::Value> res = CompileRun(
   14755         "function f() { return o(); }"
   14756         "for (var i = 0; i < 10; ++i) f();"
   14757         "%OptimizeFunctionOnNextCall(f);"
   14758         "f();");
   14759     CHECK_EQ(42, res->Int32Value());
   14760     ctx2->Exit();
   14761     v8::Handle<v8::String> G_property = v8::String::New("G");
   14762     CHECK(ctx1->Global()->ForceDelete(G_property));
   14763     ctx2->Enter();
   14764     ExpectString(
   14765         "(function() {"
   14766         "  try {"
   14767         "    return f();"
   14768         "  } catch(e) {"
   14769         "    return e.toString();"
   14770         "  }"
   14771         " })()",
   14772         "ReferenceError: G is not defined");
   14773     ctx2->Exit();
   14774     ctx1->Exit();
   14775   }
   14776 }
   14777 
   14778 
   14779 static v8::Local<Context> calling_context0;
   14780 static v8::Local<Context> calling_context1;
   14781 static v8::Local<Context> calling_context2;
   14782 
   14783 
   14784 // Check that the call to the callback is initiated in
   14785 // calling_context2, the directly calling context is calling_context1
   14786 // and the callback itself is in calling_context0.
   14787 static void GetCallingContextCallback(
   14788     const v8::FunctionCallbackInfo<v8::Value>& args) {
   14789   ApiTestFuzzer::Fuzz();
   14790   CHECK(Context::GetCurrent() == calling_context0);
   14791   CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
   14792   CHECK(Context::GetCalling() == calling_context1);
   14793   CHECK(Context::GetEntered() == calling_context2);
   14794   args.GetReturnValue().Set(42);
   14795 }
   14796 
   14797 
   14798 THREADED_TEST(GetCurrentContextWhenNotInContext) {
   14799   i::Isolate* isolate = i::Isolate::Current();
   14800   CHECK(isolate != NULL);
   14801   CHECK(isolate->context() == NULL);
   14802   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   14803   v8::HandleScope scope(v8_isolate);
   14804   // The following should not crash, but return an empty handle.
   14805   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
   14806   CHECK(current.IsEmpty());
   14807 }
   14808 
   14809 
   14810 THREADED_TEST(GetCallingContext) {
   14811   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   14812   v8::HandleScope scope(isolate);
   14813 
   14814   Local<Context> calling_context0(Context::New(isolate));
   14815   Local<Context> calling_context1(Context::New(isolate));
   14816   Local<Context> calling_context2(Context::New(isolate));
   14817   ::calling_context0 = calling_context0;
   14818   ::calling_context1 = calling_context1;
   14819   ::calling_context2 = calling_context2;
   14820 
   14821   // Allow cross-domain access.
   14822   Local<String> token = v8_str("<security token>");
   14823   calling_context0->SetSecurityToken(token);
   14824   calling_context1->SetSecurityToken(token);
   14825   calling_context2->SetSecurityToken(token);
   14826 
   14827   // Create an object with a C++ callback in context0.
   14828   calling_context0->Enter();
   14829   Local<v8::FunctionTemplate> callback_templ =
   14830       v8::FunctionTemplate::New(GetCallingContextCallback);
   14831   calling_context0->Global()->Set(v8_str("callback"),
   14832                                   callback_templ->GetFunction());
   14833   calling_context0->Exit();
   14834 
   14835   // Expose context0 in context1 and set up a function that calls the
   14836   // callback function.
   14837   calling_context1->Enter();
   14838   calling_context1->Global()->Set(v8_str("context0"),
   14839                                   calling_context0->Global());
   14840   CompileRun("function f() { context0.callback() }");
   14841   calling_context1->Exit();
   14842 
   14843   // Expose context1 in context2 and call the callback function in
   14844   // context0 indirectly through f in context1.
   14845   calling_context2->Enter();
   14846   calling_context2->Global()->Set(v8_str("context1"),
   14847                                   calling_context1->Global());
   14848   CompileRun("context1.f()");
   14849   calling_context2->Exit();
   14850   ::calling_context0.Clear();
   14851   ::calling_context1.Clear();
   14852   ::calling_context2.Clear();
   14853 }
   14854 
   14855 
   14856 // Check that a variable declaration with no explicit initialization
   14857 // value does shadow an existing property in the prototype chain.
   14858 THREADED_TEST(InitGlobalVarInProtoChain) {
   14859   i::FLAG_es52_globals = true;
   14860   LocalContext context;
   14861   v8::HandleScope scope(context->GetIsolate());
   14862   // Introduce a variable in the prototype chain.
   14863   CompileRun("__proto__.x = 42");
   14864   v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
   14865   CHECK(!result->IsUndefined());
   14866   CHECK_EQ(43, result->Int32Value());
   14867 }
   14868 
   14869 
   14870 // Regression test for issue 398.
   14871 // If a function is added to an object, creating a constant function
   14872 // field, and the result is cloned, replacing the constant function on the
   14873 // original should not affect the clone.
   14874 // See http://code.google.com/p/v8/issues/detail?id=398
   14875 THREADED_TEST(ReplaceConstantFunction) {
   14876   LocalContext context;
   14877   v8::HandleScope scope(context->GetIsolate());
   14878   v8::Handle<v8::Object> obj = v8::Object::New();
   14879   v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
   14880   v8::Handle<v8::String> foo_string = v8::String::New("foo");
   14881   obj->Set(foo_string, func_templ->GetFunction());
   14882   v8::Handle<v8::Object> obj_clone = obj->Clone();
   14883   obj_clone->Set(foo_string, v8::String::New("Hello"));
   14884   CHECK(!obj->Get(foo_string)->IsUndefined());
   14885 }
   14886 
   14887 
   14888 // Regression test for http://crbug.com/16276.
   14889 THREADED_TEST(Regress16276) {
   14890   LocalContext context;
   14891   v8::HandleScope scope(context->GetIsolate());
   14892   // Force the IC in f to be a dictionary load IC.
   14893   CompileRun("function f(obj) { return obj.x; }\n"
   14894              "var obj = { x: { foo: 42 }, y: 87 };\n"
   14895              "var x = obj.x;\n"
   14896              "delete obj.y;\n"
   14897              "for (var i = 0; i < 5; i++) f(obj);");
   14898   // Detach the global object to make 'this' refer directly to the
   14899   // global object (not the proxy), and make sure that the dictionary
   14900   // load IC doesn't mess up loading directly from the global object.
   14901   context->DetachGlobal();
   14902   CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
   14903 }
   14904 
   14905 
   14906 THREADED_TEST(PixelArray) {
   14907   LocalContext context;
   14908   i::Factory* factory = i::Isolate::Current()->factory();
   14909   v8::HandleScope scope(context->GetIsolate());
   14910   const int kElementCount = 260;
   14911   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   14912   i::Handle<i::ExternalPixelArray> pixels =
   14913       i::Handle<i::ExternalPixelArray>::cast(
   14914           factory->NewExternalArray(kElementCount,
   14915                                     v8::kExternalPixelArray,
   14916                                     pixel_data));
   14917   // Force GC to trigger verification.
   14918   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14919   for (int i = 0; i < kElementCount; i++) {
   14920     pixels->set(i, i % 256);
   14921   }
   14922   // Force GC to trigger verification.
   14923   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   14924   for (int i = 0; i < kElementCount; i++) {
   14925     CHECK_EQ(i % 256, pixels->get_scalar(i));
   14926     CHECK_EQ(i % 256, pixel_data[i]);
   14927   }
   14928 
   14929   v8::Handle<v8::Object> obj = v8::Object::New();
   14930   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   14931   // Set the elements to be the pixels.
   14932   // jsobj->set_elements(*pixels);
   14933   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   14934   CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   14935   obj->Set(v8_str("field"), v8::Int32::New(1503));
   14936   context->Global()->Set(v8_str("pixels"), obj);
   14937   v8::Handle<v8::Value> result = CompileRun("pixels.field");
   14938   CHECK_EQ(1503, result->Int32Value());
   14939   result = CompileRun("pixels[1]");
   14940   CHECK_EQ(1, result->Int32Value());
   14941 
   14942   result = CompileRun("var sum = 0;"
   14943                       "for (var i = 0; i < 8; i++) {"
   14944                       "  sum += pixels[i] = pixels[i] = -i;"
   14945                       "}"
   14946                       "sum;");
   14947   CHECK_EQ(-28, result->Int32Value());
   14948 
   14949   result = CompileRun("var sum = 0;"
   14950                       "for (var i = 0; i < 8; i++) {"
   14951                       "  sum += pixels[i] = pixels[i] = 0;"
   14952                       "}"
   14953                       "sum;");
   14954   CHECK_EQ(0, result->Int32Value());
   14955 
   14956   result = CompileRun("var sum = 0;"
   14957                       "for (var i = 0; i < 8; i++) {"
   14958                       "  sum += pixels[i] = pixels[i] = 255;"
   14959                       "}"
   14960                       "sum;");
   14961   CHECK_EQ(8 * 255, result->Int32Value());
   14962 
   14963   result = CompileRun("var sum = 0;"
   14964                       "for (var i = 0; i < 8; i++) {"
   14965                       "  sum += pixels[i] = pixels[i] = 256 + i;"
   14966                       "}"
   14967                       "sum;");
   14968   CHECK_EQ(2076, result->Int32Value());
   14969 
   14970   result = CompileRun("var sum = 0;"
   14971                       "for (var i = 0; i < 8; i++) {"
   14972                       "  sum += pixels[i] = pixels[i] = i;"
   14973                       "}"
   14974                       "sum;");
   14975   CHECK_EQ(28, result->Int32Value());
   14976 
   14977   result = CompileRun("var sum = 0;"
   14978                       "for (var i = 0; i < 8; i++) {"
   14979                       "  sum += pixels[i];"
   14980                       "}"
   14981                       "sum;");
   14982   CHECK_EQ(28, result->Int32Value());
   14983 
   14984   i::Handle<i::Smi> value(i::Smi::FromInt(2),
   14985                           reinterpret_cast<i::Isolate*>(context->GetIsolate()));
   14986   i::Handle<i::Object> no_failure;
   14987   no_failure =
   14988       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
   14989   ASSERT(!no_failure.is_null());
   14990   i::USE(no_failure);
   14991   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   14992   *value.location() = i::Smi::FromInt(256);
   14993   no_failure =
   14994       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
   14995   ASSERT(!no_failure.is_null());
   14996   i::USE(no_failure);
   14997   CHECK_EQ(255,
   14998            i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   14999   *value.location() = i::Smi::FromInt(-1);
   15000   no_failure =
   15001       i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
   15002   ASSERT(!no_failure.is_null());
   15003   i::USE(no_failure);
   15004   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   15005 
   15006   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15007                       "  pixels[i] = (i * 65) - 109;"
   15008                       "}"
   15009                       "pixels[1] + pixels[6];");
   15010   CHECK_EQ(255, result->Int32Value());
   15011   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
   15012   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   15013   CHECK_EQ(21,
   15014            i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
   15015   CHECK_EQ(86,
   15016            i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
   15017   CHECK_EQ(151,
   15018            i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
   15019   CHECK_EQ(216,
   15020            i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   15021   CHECK_EQ(255,
   15022            i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
   15023   CHECK_EQ(255,
   15024            i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
   15025   result = CompileRun("var sum = 0;"
   15026                       "for (var i = 0; i < 8; i++) {"
   15027                       "  sum += pixels[i];"
   15028                       "}"
   15029                       "sum;");
   15030   CHECK_EQ(984, result->Int32Value());
   15031 
   15032   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15033                       "  pixels[i] = (i * 1.1);"
   15034                       "}"
   15035                       "pixels[1] + pixels[6];");
   15036   CHECK_EQ(8, result->Int32Value());
   15037   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
   15038   CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   15039   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
   15040   CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
   15041   CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
   15042   CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   15043   CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
   15044   CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
   15045 
   15046   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15047                       "  pixels[7] = undefined;"
   15048                       "}"
   15049                       "pixels[7];");
   15050   CHECK_EQ(0, result->Int32Value());
   15051   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
   15052 
   15053   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15054                       "  pixels[6] = '2.3';"
   15055                       "}"
   15056                       "pixels[6];");
   15057   CHECK_EQ(2, result->Int32Value());
   15058   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
   15059 
   15060   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15061                       "  pixels[5] = NaN;"
   15062                       "}"
   15063                       "pixels[5];");
   15064   CHECK_EQ(0, result->Int32Value());
   15065   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   15066 
   15067   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15068                       "  pixels[8] = Infinity;"
   15069                       "}"
   15070                       "pixels[8];");
   15071   CHECK_EQ(255, result->Int32Value());
   15072   CHECK_EQ(255,
   15073            i::Smi::cast(jsobj->GetElement(8)->ToObjectChecked())->value());
   15074 
   15075   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15076                       "  pixels[9] = -Infinity;"
   15077                       "}"
   15078                       "pixels[9];");
   15079   CHECK_EQ(0, result->Int32Value());
   15080   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9)->ToObjectChecked())->value());
   15081 
   15082   result = CompileRun("pixels[3] = 33;"
   15083                       "delete pixels[3];"
   15084                       "pixels[3];");
   15085   CHECK_EQ(33, result->Int32Value());
   15086 
   15087   result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
   15088                       "pixels[2] = 12; pixels[3] = 13;"
   15089                       "pixels.__defineGetter__('2',"
   15090                       "function() { return 120; });"
   15091                       "pixels[2];");
   15092   CHECK_EQ(12, result->Int32Value());
   15093 
   15094   result = CompileRun("var js_array = new Array(40);"
   15095                       "js_array[0] = 77;"
   15096                       "js_array;");
   15097   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   15098 
   15099   result = CompileRun("pixels[1] = 23;"
   15100                       "pixels.__proto__ = [];"
   15101                       "js_array.__proto__ = pixels;"
   15102                       "js_array.concat(pixels);");
   15103   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   15104   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   15105 
   15106   result = CompileRun("pixels[1] = 23;");
   15107   CHECK_EQ(23, result->Int32Value());
   15108 
   15109   // Test for index greater than 255.  Regression test for:
   15110   // http://code.google.com/p/chromium/issues/detail?id=26337.
   15111   result = CompileRun("pixels[256] = 255;");
   15112   CHECK_EQ(255, result->Int32Value());
   15113   result = CompileRun("var i = 0;"
   15114                       "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
   15115                       "i");
   15116   CHECK_EQ(255, result->Int32Value());
   15117 
   15118   // Make sure that pixel array ICs recognize when a non-pixel array
   15119   // is passed to it.
   15120   result = CompileRun("function pa_load(p) {"
   15121                       "  var sum = 0;"
   15122                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   15123                       "  return sum;"
   15124                       "}"
   15125                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15126                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   15127                       "just_ints = new Object();"
   15128                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15129                       "for (var i = 0; i < 10; ++i) {"
   15130                       "  result = pa_load(just_ints);"
   15131                       "}"
   15132                       "result");
   15133   CHECK_EQ(32640, result->Int32Value());
   15134 
   15135   // Make sure that pixel array ICs recognize out-of-bound accesses.
   15136   result = CompileRun("function pa_load(p, start) {"
   15137                       "  var sum = 0;"
   15138                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   15139                       "  return sum;"
   15140                       "}"
   15141                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15142                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   15143                       "for (var i = 0; i < 10; ++i) {"
   15144                       "  result = pa_load(pixels,-10);"
   15145                       "}"
   15146                       "result");
   15147   CHECK_EQ(0, result->Int32Value());
   15148 
   15149   // Make sure that generic ICs properly handles a pixel array.
   15150   result = CompileRun("function pa_load(p) {"
   15151                       "  var sum = 0;"
   15152                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   15153                       "  return sum;"
   15154                       "}"
   15155                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15156                       "just_ints = new Object();"
   15157                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15158                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   15159                       "for (var i = 0; i < 10; ++i) {"
   15160                       "  result = pa_load(pixels);"
   15161                       "}"
   15162                       "result");
   15163   CHECK_EQ(32640, result->Int32Value());
   15164 
   15165   // Make sure that generic load ICs recognize out-of-bound accesses in
   15166   // pixel arrays.
   15167   result = CompileRun("function pa_load(p, start) {"
   15168                       "  var sum = 0;"
   15169                       "  for (var j = start; j < 256; j++) { sum += p[j]; }"
   15170                       "  return sum;"
   15171                       "}"
   15172                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15173                       "just_ints = new Object();"
   15174                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15175                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
   15176                       "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
   15177                       "for (var i = 0; i < 10; ++i) {"
   15178                       "  result = pa_load(pixels,-10);"
   15179                       "}"
   15180                       "result");
   15181   CHECK_EQ(0, result->Int32Value());
   15182 
   15183   // Make sure that generic ICs properly handles other types than pixel
   15184   // arrays (that the inlined fast pixel array test leaves the right information
   15185   // in the right registers).
   15186   result = CompileRun("function pa_load(p) {"
   15187                       "  var sum = 0;"
   15188                       "  for (var j = 0; j < 256; j++) { sum += p[j]; }"
   15189                       "  return sum;"
   15190                       "}"
   15191                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15192                       "just_ints = new Object();"
   15193                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15194                       "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
   15195                       "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
   15196                       "sparse_array = new Object();"
   15197                       "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
   15198                       "sparse_array[1000000] = 3;"
   15199                       "for (var i = 0; i < 10; ++i) {"
   15200                       "  result = pa_load(sparse_array);"
   15201                       "}"
   15202                       "result");
   15203   CHECK_EQ(32640, result->Int32Value());
   15204 
   15205   // Make sure that pixel array store ICs clamp values correctly.
   15206   result = CompileRun("function pa_store(p) {"
   15207                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   15208                       "}"
   15209                       "pa_store(pixels);"
   15210                       "var sum = 0;"
   15211                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   15212                       "sum");
   15213   CHECK_EQ(48896, result->Int32Value());
   15214 
   15215   // Make sure that pixel array stores correctly handle accesses outside
   15216   // of the pixel array..
   15217   result = CompileRun("function pa_store(p,start) {"
   15218                       "  for (var j = 0; j < 256; j++) {"
   15219                       "    p[j+start] = j * 2;"
   15220                       "  }"
   15221                       "}"
   15222                       "pa_store(pixels,0);"
   15223                       "pa_store(pixels,-128);"
   15224                       "var sum = 0;"
   15225                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   15226                       "sum");
   15227   CHECK_EQ(65280, result->Int32Value());
   15228 
   15229   // Make sure that the generic store stub correctly handle accesses outside
   15230   // of the pixel array..
   15231   result = CompileRun("function pa_store(p,start) {"
   15232                       "  for (var j = 0; j < 256; j++) {"
   15233                       "    p[j+start] = j * 2;"
   15234                       "  }"
   15235                       "}"
   15236                       "pa_store(pixels,0);"
   15237                       "just_ints = new Object();"
   15238                       "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
   15239                       "pa_store(just_ints, 0);"
   15240                       "pa_store(pixels,-128);"
   15241                       "var sum = 0;"
   15242                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   15243                       "sum");
   15244   CHECK_EQ(65280, result->Int32Value());
   15245 
   15246   // Make sure that the generic keyed store stub clamps pixel array values
   15247   // correctly.
   15248   result = CompileRun("function pa_store(p) {"
   15249                       "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
   15250                       "}"
   15251                       "pa_store(pixels);"
   15252                       "just_ints = new Object();"
   15253                       "pa_store(just_ints);"
   15254                       "pa_store(pixels);"
   15255                       "var sum = 0;"
   15256                       "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
   15257                       "sum");
   15258   CHECK_EQ(48896, result->Int32Value());
   15259 
   15260   // Make sure that pixel array loads are optimized by crankshaft.
   15261   result = CompileRun("function pa_load(p) {"
   15262                       "  var sum = 0;"
   15263                       "  for (var i=0; i<256; ++i) {"
   15264                       "    sum += p[i];"
   15265                       "  }"
   15266                       "  return sum; "
   15267                       "}"
   15268                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
   15269                       "for (var i = 0; i < 5000; ++i) {"
   15270                       "  result = pa_load(pixels);"
   15271                       "}"
   15272                       "result");
   15273   CHECK_EQ(32640, result->Int32Value());
   15274 
   15275   // Make sure that pixel array stores are optimized by crankshaft.
   15276   result = CompileRun("function pa_init(p) {"
   15277                       "for (var i = 0; i < 256; ++i) { p[i] = i; }"
   15278                       "}"
   15279                       "function pa_load(p) {"
   15280                       "  var sum = 0;"
   15281                       "  for (var i=0; i<256; ++i) {"
   15282                       "    sum += p[i];"
   15283                       "  }"
   15284                       "  return sum; "
   15285                       "}"
   15286                       "for (var i = 0; i < 5000; ++i) {"
   15287                       "  pa_init(pixels);"
   15288                       "}"
   15289                       "result = pa_load(pixels);"
   15290                       "result");
   15291   CHECK_EQ(32640, result->Int32Value());
   15292 
   15293   free(pixel_data);
   15294 }
   15295 
   15296 
   15297 THREADED_TEST(PixelArrayInfo) {
   15298   LocalContext context;
   15299   v8::HandleScope scope(context->GetIsolate());
   15300   for (int size = 0; size < 100; size += 10) {
   15301     uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
   15302     v8::Handle<v8::Object> obj = v8::Object::New();
   15303     obj->SetIndexedPropertiesToPixelData(pixel_data, size);
   15304     CHECK(obj->HasIndexedPropertiesInPixelData());
   15305     CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
   15306     CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
   15307     free(pixel_data);
   15308   }
   15309 }
   15310 
   15311 
   15312 static void NotHandledIndexedPropertyGetter(
   15313     uint32_t index,
   15314     const v8::PropertyCallbackInfo<v8::Value>& info) {
   15315   ApiTestFuzzer::Fuzz();
   15316 }
   15317 
   15318 
   15319 static void NotHandledIndexedPropertySetter(
   15320     uint32_t index,
   15321     Local<Value> value,
   15322     const v8::PropertyCallbackInfo<v8::Value>& info) {
   15323   ApiTestFuzzer::Fuzz();
   15324 }
   15325 
   15326 
   15327 THREADED_TEST(PixelArrayWithInterceptor) {
   15328   LocalContext context;
   15329   i::Factory* factory = i::Isolate::Current()->factory();
   15330   v8::HandleScope scope(context->GetIsolate());
   15331   const int kElementCount = 260;
   15332   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
   15333   i::Handle<i::ExternalPixelArray> pixels =
   15334       i::Handle<i::ExternalPixelArray>::cast(
   15335           factory->NewExternalArray(kElementCount,
   15336                                     v8::kExternalPixelArray,
   15337                                     pixel_data));
   15338   for (int i = 0; i < kElementCount; i++) {
   15339     pixels->set(i, i % 256);
   15340   }
   15341   v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   15342   templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
   15343                                    NotHandledIndexedPropertySetter);
   15344   v8::Handle<v8::Object> obj = templ->NewInstance();
   15345   obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
   15346   context->Global()->Set(v8_str("pixels"), obj);
   15347   v8::Handle<v8::Value> result = CompileRun("pixels[1]");
   15348   CHECK_EQ(1, result->Int32Value());
   15349   result = CompileRun("var sum = 0;"
   15350                       "for (var i = 0; i < 8; i++) {"
   15351                       "  sum += pixels[i] = pixels[i] = -i;"
   15352                       "}"
   15353                       "sum;");
   15354   CHECK_EQ(-28, result->Int32Value());
   15355   result = CompileRun("pixels.hasOwnProperty('1')");
   15356   CHECK(result->BooleanValue());
   15357   free(pixel_data);
   15358 }
   15359 
   15360 
   15361 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
   15362   switch (array_type) {
   15363     case v8::kExternalByteArray:
   15364     case v8::kExternalUnsignedByteArray:
   15365     case v8::kExternalPixelArray:
   15366       return 1;
   15367       break;
   15368     case v8::kExternalShortArray:
   15369     case v8::kExternalUnsignedShortArray:
   15370       return 2;
   15371       break;
   15372     case v8::kExternalIntArray:
   15373     case v8::kExternalUnsignedIntArray:
   15374     case v8::kExternalFloatArray:
   15375       return 4;
   15376       break;
   15377     case v8::kExternalDoubleArray:
   15378       return 8;
   15379       break;
   15380     default:
   15381       UNREACHABLE();
   15382       return -1;
   15383   }
   15384   UNREACHABLE();
   15385   return -1;
   15386 }
   15387 
   15388 
   15389 template <class ExternalArrayClass, class ElementType>
   15390 static void ObjectWithExternalArrayTestHelper(
   15391     Handle<Context> context,
   15392     v8::Handle<Object> obj,
   15393     int element_count,
   15394     v8::ExternalArrayType array_type,
   15395     int64_t low, int64_t high) {
   15396   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   15397   obj->Set(v8_str("field"), v8::Int32::New(1503));
   15398   context->Global()->Set(v8_str("ext_array"), obj);
   15399   v8::Handle<v8::Value> result = CompileRun("ext_array.field");
   15400   CHECK_EQ(1503, result->Int32Value());
   15401   result = CompileRun("ext_array[1]");
   15402   CHECK_EQ(1, result->Int32Value());
   15403 
   15404   // Check pass through of assigned smis
   15405   result = CompileRun("var sum = 0;"
   15406                       "for (var i = 0; i < 8; i++) {"
   15407                       "  sum += ext_array[i] = ext_array[i] = -i;"
   15408                       "}"
   15409                       "sum;");
   15410   CHECK_EQ(-28, result->Int32Value());
   15411 
   15412   // Check assigned smis
   15413   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15414                       "  ext_array[i] = i;"
   15415                       "}"
   15416                       "var sum = 0;"
   15417                       "for (var i = 0; i < 8; i++) {"
   15418                       "  sum += ext_array[i];"
   15419                       "}"
   15420                       "sum;");
   15421   CHECK_EQ(28, result->Int32Value());
   15422 
   15423   // Check assigned smis in reverse order
   15424   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   15425                       "  ext_array[i] = i;"
   15426                       "}"
   15427                       "var sum = 0;"
   15428                       "for (var i = 0; i < 8; i++) {"
   15429                       "  sum += ext_array[i];"
   15430                       "}"
   15431                       "sum;");
   15432   CHECK_EQ(28, result->Int32Value());
   15433 
   15434   // Check pass through of assigned HeapNumbers
   15435   result = CompileRun("var sum = 0;"
   15436                       "for (var i = 0; i < 16; i+=2) {"
   15437                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   15438                       "}"
   15439                       "sum;");
   15440   CHECK_EQ(-28, result->Int32Value());
   15441 
   15442   // Check assigned HeapNumbers
   15443   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   15444                       "  ext_array[i] = (i * 0.5);"
   15445                       "}"
   15446                       "var sum = 0;"
   15447                       "for (var i = 0; i < 16; i+=2) {"
   15448                       "  sum += ext_array[i];"
   15449                       "}"
   15450                       "sum;");
   15451   CHECK_EQ(28, result->Int32Value());
   15452 
   15453   // Check assigned HeapNumbers in reverse order
   15454   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   15455                       "  ext_array[i] = (i * 0.5);"
   15456                       "}"
   15457                       "var sum = 0;"
   15458                       "for (var i = 0; i < 16; i+=2) {"
   15459                       "  sum += ext_array[i];"
   15460                       "}"
   15461                       "sum;");
   15462   CHECK_EQ(28, result->Int32Value());
   15463 
   15464   i::ScopedVector<char> test_buf(1024);
   15465 
   15466   // Check legal boundary conditions.
   15467   // The repeated loads and stores ensure the ICs are exercised.
   15468   const char* boundary_program =
   15469       "var res = 0;"
   15470       "for (var i = 0; i < 16; i++) {"
   15471       "  ext_array[i] = %lld;"
   15472       "  if (i > 8) {"
   15473       "    res = ext_array[i];"
   15474       "  }"
   15475       "}"
   15476       "res;";
   15477   i::OS::SNPrintF(test_buf,
   15478                   boundary_program,
   15479                   low);
   15480   result = CompileRun(test_buf.start());
   15481   CHECK_EQ(low, result->IntegerValue());
   15482 
   15483   i::OS::SNPrintF(test_buf,
   15484                   boundary_program,
   15485                   high);
   15486   result = CompileRun(test_buf.start());
   15487   CHECK_EQ(high, result->IntegerValue());
   15488 
   15489   // Check misprediction of type in IC.
   15490   result = CompileRun("var tmp_array = ext_array;"
   15491                       "var sum = 0;"
   15492                       "for (var i = 0; i < 8; i++) {"
   15493                       "  tmp_array[i] = i;"
   15494                       "  sum += tmp_array[i];"
   15495                       "  if (i == 4) {"
   15496                       "    tmp_array = {};"
   15497                       "  }"
   15498                       "}"
   15499                       "sum;");
   15500   // Force GC to trigger verification.
   15501   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   15502   CHECK_EQ(28, result->Int32Value());
   15503 
   15504   // Make sure out-of-range loads do not throw.
   15505   i::OS::SNPrintF(test_buf,
   15506                   "var caught_exception = false;"
   15507                   "try {"
   15508                   "  ext_array[%d];"
   15509                   "} catch (e) {"
   15510                   "  caught_exception = true;"
   15511                   "}"
   15512                   "caught_exception;",
   15513                   element_count);
   15514   result = CompileRun(test_buf.start());
   15515   CHECK_EQ(false, result->BooleanValue());
   15516 
   15517   // Make sure out-of-range stores do not throw.
   15518   i::OS::SNPrintF(test_buf,
   15519                   "var caught_exception = false;"
   15520                   "try {"
   15521                   "  ext_array[%d] = 1;"
   15522                   "} catch (e) {"
   15523                   "  caught_exception = true;"
   15524                   "}"
   15525                   "caught_exception;",
   15526                   element_count);
   15527   result = CompileRun(test_buf.start());
   15528   CHECK_EQ(false, result->BooleanValue());
   15529 
   15530   // Check other boundary conditions, values and operations.
   15531   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15532                       "  ext_array[7] = undefined;"
   15533                       "}"
   15534                       "ext_array[7];");
   15535   CHECK_EQ(0, result->Int32Value());
   15536   if (array_type == v8::kExternalDoubleArray ||
   15537       array_type == v8::kExternalFloatArray) {
   15538     CHECK_EQ(
   15539         static_cast<int>(i::OS::nan_value()),
   15540         static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number()));
   15541   } else {
   15542     CHECK_EQ(0, static_cast<int>(
   15543         jsobj->GetElement(7)->ToObjectChecked()->Number()));
   15544   }
   15545 
   15546   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15547                       "  ext_array[6] = '2.3';"
   15548                       "}"
   15549                       "ext_array[6];");
   15550   CHECK_EQ(2, result->Int32Value());
   15551   CHECK_EQ(
   15552       2, static_cast<int>(jsobj->GetElement(6)->ToObjectChecked()->Number()));
   15553 
   15554   if (array_type != v8::kExternalFloatArray &&
   15555       array_type != v8::kExternalDoubleArray) {
   15556     // Though the specification doesn't state it, be explicit about
   15557     // converting NaNs and +/-Infinity to zero.
   15558     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15559                         "  ext_array[i] = 5;"
   15560                         "}"
   15561                         "for (var i = 0; i < 8; i++) {"
   15562                         "  ext_array[i] = NaN;"
   15563                         "}"
   15564                         "ext_array[5];");
   15565     CHECK_EQ(0, result->Int32Value());
   15566     CHECK_EQ(0,
   15567              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   15568 
   15569     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15570                         "  ext_array[i] = 5;"
   15571                         "}"
   15572                         "for (var i = 0; i < 8; i++) {"
   15573                         "  ext_array[i] = Infinity;"
   15574                         "}"
   15575                         "ext_array[5];");
   15576     int expected_value =
   15577         (array_type == v8::kExternalPixelArray) ? 255 : 0;
   15578     CHECK_EQ(expected_value, result->Int32Value());
   15579     CHECK_EQ(expected_value,
   15580              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   15581 
   15582     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15583                         "  ext_array[i] = 5;"
   15584                         "}"
   15585                         "for (var i = 0; i < 8; i++) {"
   15586                         "  ext_array[i] = -Infinity;"
   15587                         "}"
   15588                         "ext_array[5];");
   15589     CHECK_EQ(0, result->Int32Value());
   15590     CHECK_EQ(0,
   15591              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
   15592 
   15593     // Check truncation behavior of integral arrays.
   15594     const char* unsigned_data =
   15595         "var source_data = [0.6, 10.6];"
   15596         "var expected_results = [0, 10];";
   15597     const char* signed_data =
   15598         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   15599         "var expected_results = [0, 10, 0, -10];";
   15600     const char* pixel_data =
   15601         "var source_data = [0.6, 10.6];"
   15602         "var expected_results = [1, 11];";
   15603     bool is_unsigned =
   15604         (array_type == v8::kExternalUnsignedByteArray ||
   15605          array_type == v8::kExternalUnsignedShortArray ||
   15606          array_type == v8::kExternalUnsignedIntArray);
   15607     bool is_pixel_data = array_type == v8::kExternalPixelArray;
   15608 
   15609     i::OS::SNPrintF(test_buf,
   15610                     "%s"
   15611                     "var all_passed = true;"
   15612                     "for (var i = 0; i < source_data.length; i++) {"
   15613                     "  for (var j = 0; j < 8; j++) {"
   15614                     "    ext_array[j] = source_data[i];"
   15615                     "  }"
   15616                     "  all_passed = all_passed &&"
   15617                     "               (ext_array[5] == expected_results[i]);"
   15618                     "}"
   15619                     "all_passed;",
   15620                     (is_unsigned ?
   15621                          unsigned_data :
   15622                          (is_pixel_data ? pixel_data : signed_data)));
   15623     result = CompileRun(test_buf.start());
   15624     CHECK_EQ(true, result->BooleanValue());
   15625   }
   15626 
   15627   i::Handle<ExternalArrayClass> array(
   15628       ExternalArrayClass::cast(jsobj->elements()));
   15629   for (int i = 0; i < element_count; i++) {
   15630     array->set(i, static_cast<ElementType>(i));
   15631   }
   15632 
   15633   // Test complex assignments
   15634   result = CompileRun("function ee_op_test_complex_func(sum) {"
   15635                       " for (var i = 0; i < 40; ++i) {"
   15636                       "   sum += (ext_array[i] += 1);"
   15637                       "   sum += (ext_array[i] -= 1);"
   15638                       " } "
   15639                       " return sum;"
   15640                       "}"
   15641                       "sum=0;"
   15642                       "for (var i=0;i<10000;++i) {"
   15643                       "  sum=ee_op_test_complex_func(sum);"
   15644                       "}"
   15645                       "sum;");
   15646   CHECK_EQ(16000000, result->Int32Value());
   15647 
   15648   // Test count operations
   15649   result = CompileRun("function ee_op_test_count_func(sum) {"
   15650                       " for (var i = 0; i < 40; ++i) {"
   15651                       "   sum += (++ext_array[i]);"
   15652                       "   sum += (--ext_array[i]);"
   15653                       " } "
   15654                       " return sum;"
   15655                       "}"
   15656                       "sum=0;"
   15657                       "for (var i=0;i<10000;++i) {"
   15658                       "  sum=ee_op_test_count_func(sum);"
   15659                       "}"
   15660                       "sum;");
   15661   CHECK_EQ(16000000, result->Int32Value());
   15662 
   15663   result = CompileRun("ext_array[3] = 33;"
   15664                       "delete ext_array[3];"
   15665                       "ext_array[3];");
   15666   CHECK_EQ(33, result->Int32Value());
   15667 
   15668   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
   15669                       "ext_array[2] = 12; ext_array[3] = 13;"
   15670                       "ext_array.__defineGetter__('2',"
   15671                       "function() { return 120; });"
   15672                       "ext_array[2];");
   15673   CHECK_EQ(12, result->Int32Value());
   15674 
   15675   result = CompileRun("var js_array = new Array(40);"
   15676                       "js_array[0] = 77;"
   15677                       "js_array;");
   15678   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   15679 
   15680   result = CompileRun("ext_array[1] = 23;"
   15681                       "ext_array.__proto__ = [];"
   15682                       "js_array.__proto__ = ext_array;"
   15683                       "js_array.concat(ext_array);");
   15684   CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
   15685   CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
   15686 
   15687   result = CompileRun("ext_array[1] = 23;");
   15688   CHECK_EQ(23, result->Int32Value());
   15689 }
   15690 
   15691 
   15692 template <class ExternalArrayClass, class ElementType>
   15693 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
   15694                                     int64_t low,
   15695                                     int64_t high) {
   15696   LocalContext context;
   15697   i::Factory* factory = i::Isolate::Current()->factory();
   15698   v8::HandleScope scope(context->GetIsolate());
   15699   const int kElementCount = 40;
   15700   int element_size = ExternalArrayElementSize(array_type);
   15701   ElementType* array_data =
   15702       static_cast<ElementType*>(malloc(kElementCount * element_size));
   15703   i::Handle<ExternalArrayClass> array =
   15704       i::Handle<ExternalArrayClass>::cast(
   15705           factory->NewExternalArray(kElementCount, array_type, array_data));
   15706   // Force GC to trigger verification.
   15707   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   15708   for (int i = 0; i < kElementCount; i++) {
   15709     array->set(i, static_cast<ElementType>(i));
   15710   }
   15711   // Force GC to trigger verification.
   15712   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   15713   for (int i = 0; i < kElementCount; i++) {
   15714     CHECK_EQ(static_cast<int64_t>(i),
   15715              static_cast<int64_t>(array->get_scalar(i)));
   15716     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
   15717   }
   15718 
   15719   v8::Handle<v8::Object> obj = v8::Object::New();
   15720   i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
   15721   // Set the elements to be the external array.
   15722   obj->SetIndexedPropertiesToExternalArrayData(array_data,
   15723                                                array_type,
   15724                                                kElementCount);
   15725   CHECK_EQ(
   15726       1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number()));
   15727 
   15728   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   15729       context.local(), obj, kElementCount, array_type, low, high);
   15730 
   15731   v8::Handle<v8::Value> result;
   15732 
   15733   // Test more complex manipulations which cause eax to contain values
   15734   // that won't be completely overwritten by loads from the arrays.
   15735   // This catches bugs in the instructions used for the KeyedLoadIC
   15736   // for byte and word types.
   15737   {
   15738     const int kXSize = 300;
   15739     const int kYSize = 300;
   15740     const int kLargeElementCount = kXSize * kYSize * 4;
   15741     ElementType* large_array_data =
   15742         static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
   15743     v8::Handle<v8::Object> large_obj = v8::Object::New();
   15744     // Set the elements to be the external array.
   15745     large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
   15746                                                        array_type,
   15747                                                        kLargeElementCount);
   15748     context->Global()->Set(v8_str("large_array"), large_obj);
   15749     // Initialize contents of a few rows.
   15750     for (int x = 0; x < 300; x++) {
   15751       int row = 0;
   15752       int offset = row * 300 * 4;
   15753       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   15754       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   15755       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   15756       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   15757       row = 150;
   15758       offset = row * 300 * 4;
   15759       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   15760       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   15761       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   15762       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   15763       row = 298;
   15764       offset = row * 300 * 4;
   15765       large_array_data[offset + 4 * x + 0] = (ElementType) 127;
   15766       large_array_data[offset + 4 * x + 1] = (ElementType) 0;
   15767       large_array_data[offset + 4 * x + 2] = (ElementType) 0;
   15768       large_array_data[offset + 4 * x + 3] = (ElementType) 127;
   15769     }
   15770     // The goal of the code below is to make "offset" large enough
   15771     // that the computation of the index (which goes into eax) has
   15772     // high bits set which will not be overwritten by a byte or short
   15773     // load.
   15774     result = CompileRun("var failed = false;"
   15775                         "var offset = 0;"
   15776                         "for (var i = 0; i < 300; i++) {"
   15777                         "  if (large_array[4 * i] != 127 ||"
   15778                         "      large_array[4 * i + 1] != 0 ||"
   15779                         "      large_array[4 * i + 2] != 0 ||"
   15780                         "      large_array[4 * i + 3] != 127) {"
   15781                         "    failed = true;"
   15782                         "  }"
   15783                         "}"
   15784                         "offset = 150 * 300 * 4;"
   15785                         "for (var i = 0; i < 300; i++) {"
   15786                         "  if (large_array[offset + 4 * i] != 127 ||"
   15787                         "      large_array[offset + 4 * i + 1] != 0 ||"
   15788                         "      large_array[offset + 4 * i + 2] != 0 ||"
   15789                         "      large_array[offset + 4 * i + 3] != 127) {"
   15790                         "    failed = true;"
   15791                         "  }"
   15792                         "}"
   15793                         "offset = 298 * 300 * 4;"
   15794                         "for (var i = 0; i < 300; i++) {"
   15795                         "  if (large_array[offset + 4 * i] != 127 ||"
   15796                         "      large_array[offset + 4 * i + 1] != 0 ||"
   15797                         "      large_array[offset + 4 * i + 2] != 0 ||"
   15798                         "      large_array[offset + 4 * i + 3] != 127) {"
   15799                         "    failed = true;"
   15800                         "  }"
   15801                         "}"
   15802                         "!failed;");
   15803     CHECK_EQ(true, result->BooleanValue());
   15804     free(large_array_data);
   15805   }
   15806 
   15807   // The "" property descriptor is overloaded to store information about
   15808   // the external array. Ensure that setting and accessing the "" property
   15809   // works (it should overwrite the information cached about the external
   15810   // array in the DescriptorArray) in various situations.
   15811   result = CompileRun("ext_array[''] = 23; ext_array['']");
   15812   CHECK_EQ(23, result->Int32Value());
   15813 
   15814   // Property "" set after the external array is associated with the object.
   15815   {
   15816     v8::Handle<v8::Object> obj2 = v8::Object::New();
   15817     obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256));
   15818     obj2->Set(v8_str(""), v8::Int32::New(1503));
   15819     // Set the elements to be the external array.
   15820     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   15821                                                   array_type,
   15822                                                   kElementCount);
   15823     context->Global()->Set(v8_str("ext_array"), obj2);
   15824     result = CompileRun("ext_array['']");
   15825     CHECK_EQ(1503, result->Int32Value());
   15826   }
   15827 
   15828   // Property "" set after the external array is associated with the object.
   15829   {
   15830     v8::Handle<v8::Object> obj2 = v8::Object::New();
   15831     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
   15832     // Set the elements to be the external array.
   15833     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   15834                                                   array_type,
   15835                                                   kElementCount);
   15836     obj2->Set(v8_str(""), v8::Int32::New(1503));
   15837     context->Global()->Set(v8_str("ext_array"), obj2);
   15838     result = CompileRun("ext_array['']");
   15839     CHECK_EQ(1503, result->Int32Value());
   15840   }
   15841 
   15842   // Should reuse the map from previous test.
   15843   {
   15844     v8::Handle<v8::Object> obj2 = v8::Object::New();
   15845     obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
   15846     // Set the elements to be the external array. Should re-use the map
   15847     // from previous test.
   15848     obj2->SetIndexedPropertiesToExternalArrayData(array_data,
   15849                                                   array_type,
   15850                                                   kElementCount);
   15851     context->Global()->Set(v8_str("ext_array"), obj2);
   15852     result = CompileRun("ext_array['']");
   15853   }
   15854 
   15855   // Property "" is a constant function that shouldn't not be interfered with
   15856   // when an external array is set.
   15857   {
   15858     v8::Handle<v8::Object> obj2 = v8::Object::New();
   15859     // Start
   15860     obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
   15861 
   15862     // Add a constant function to an object.
   15863     context->Global()->Set(v8_str("ext_array"), obj2);
   15864     result = CompileRun("ext_array[''] = function() {return 1503;};"
   15865                         "ext_array['']();");
   15866 
   15867     // Add an external array transition to the same map that
   15868     // has the constant transition.
   15869     v8::Handle<v8::Object> obj3 = v8::Object::New();
   15870     obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
   15871     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   15872                                                   array_type,
   15873                                                   kElementCount);
   15874     context->Global()->Set(v8_str("ext_array"), obj3);
   15875   }
   15876 
   15877   // If a external array transition is in the map, it should get clobbered
   15878   // by a constant function.
   15879   {
   15880     // Add an external array transition.
   15881     v8::Handle<v8::Object> obj3 = v8::Object::New();
   15882     obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
   15883     obj3->SetIndexedPropertiesToExternalArrayData(array_data,
   15884                                                   array_type,
   15885                                                   kElementCount);
   15886 
   15887     // Add a constant function to the same map that just got an external array
   15888     // transition.
   15889     v8::Handle<v8::Object> obj2 = v8::Object::New();
   15890     obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
   15891     context->Global()->Set(v8_str("ext_array"), obj2);
   15892     result = CompileRun("ext_array[''] = function() {return 1503;};"
   15893                         "ext_array['']();");
   15894   }
   15895 
   15896   free(array_data);
   15897 }
   15898 
   15899 
   15900 THREADED_TEST(ExternalByteArray) {
   15901   ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
   15902       v8::kExternalByteArray,
   15903       -128,
   15904       127);
   15905 }
   15906 
   15907 
   15908 THREADED_TEST(ExternalUnsignedByteArray) {
   15909   ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
   15910       v8::kExternalUnsignedByteArray,
   15911       0,
   15912       255);
   15913 }
   15914 
   15915 
   15916 THREADED_TEST(ExternalPixelArray) {
   15917   ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
   15918       v8::kExternalPixelArray,
   15919       0,
   15920       255);
   15921 }
   15922 
   15923 
   15924 THREADED_TEST(ExternalShortArray) {
   15925   ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
   15926       v8::kExternalShortArray,
   15927       -32768,
   15928       32767);
   15929 }
   15930 
   15931 
   15932 THREADED_TEST(ExternalUnsignedShortArray) {
   15933   ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
   15934       v8::kExternalUnsignedShortArray,
   15935       0,
   15936       65535);
   15937 }
   15938 
   15939 
   15940 THREADED_TEST(ExternalIntArray) {
   15941   ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
   15942       v8::kExternalIntArray,
   15943       INT_MIN,   // -2147483648
   15944       INT_MAX);  //  2147483647
   15945 }
   15946 
   15947 
   15948 THREADED_TEST(ExternalUnsignedIntArray) {
   15949   ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
   15950       v8::kExternalUnsignedIntArray,
   15951       0,
   15952       UINT_MAX);  // 4294967295
   15953 }
   15954 
   15955 
   15956 THREADED_TEST(ExternalFloatArray) {
   15957   ExternalArrayTestHelper<i::ExternalFloatArray, float>(
   15958       v8::kExternalFloatArray,
   15959       -500,
   15960       500);
   15961 }
   15962 
   15963 
   15964 THREADED_TEST(ExternalDoubleArray) {
   15965   ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
   15966       v8::kExternalDoubleArray,
   15967       -500,
   15968       500);
   15969 }
   15970 
   15971 
   15972 THREADED_TEST(ExternalArrays) {
   15973   TestExternalByteArray();
   15974   TestExternalUnsignedByteArray();
   15975   TestExternalShortArray();
   15976   TestExternalUnsignedShortArray();
   15977   TestExternalIntArray();
   15978   TestExternalUnsignedIntArray();
   15979   TestExternalFloatArray();
   15980 }
   15981 
   15982 
   15983 void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
   15984   LocalContext context;
   15985   v8::HandleScope scope(context->GetIsolate());
   15986   for (int size = 0; size < 100; size += 10) {
   15987     int element_size = ExternalArrayElementSize(array_type);
   15988     void* external_data = malloc(size * element_size);
   15989     v8::Handle<v8::Object> obj = v8::Object::New();
   15990     obj->SetIndexedPropertiesToExternalArrayData(
   15991         external_data, array_type, size);
   15992     CHECK(obj->HasIndexedPropertiesInExternalArrayData());
   15993     CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
   15994     CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
   15995     CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
   15996     free(external_data);
   15997   }
   15998 }
   15999 
   16000 
   16001 THREADED_TEST(ExternalArrayInfo) {
   16002   ExternalArrayInfoTestHelper(v8::kExternalByteArray);
   16003   ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
   16004   ExternalArrayInfoTestHelper(v8::kExternalShortArray);
   16005   ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
   16006   ExternalArrayInfoTestHelper(v8::kExternalIntArray);
   16007   ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
   16008   ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
   16009   ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
   16010   ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
   16011 }
   16012 
   16013 
   16014 void ExternalArrayLimitTestHelper(v8::ExternalArrayType array_type, int size) {
   16015   v8::Handle<v8::Object> obj = v8::Object::New();
   16016   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   16017   last_location = last_message = NULL;
   16018   obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
   16019   CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
   16020   CHECK_NE(NULL, last_location);
   16021   CHECK_NE(NULL, last_message);
   16022 }
   16023 
   16024 
   16025 TEST(ExternalArrayLimits) {
   16026   LocalContext context;
   16027   v8::HandleScope scope(context->GetIsolate());
   16028   ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0x40000000);
   16029   ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0xffffffff);
   16030   ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0x40000000);
   16031   ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0xffffffff);
   16032   ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0x40000000);
   16033   ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0xffffffff);
   16034   ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0x40000000);
   16035   ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0xffffffff);
   16036   ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0x40000000);
   16037   ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0xffffffff);
   16038   ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0x40000000);
   16039   ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0xffffffff);
   16040   ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0x40000000);
   16041   ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0xffffffff);
   16042   ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0x40000000);
   16043   ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0xffffffff);
   16044   ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0x40000000);
   16045   ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0xffffffff);
   16046 }
   16047 
   16048 
   16049 template <typename ElementType, typename TypedArray,
   16050           class ExternalArrayClass>
   16051 void TypedArrayTestHelper(v8::ExternalArrayType array_type,
   16052                           int64_t low, int64_t high) {
   16053   const int kElementCount = 50;
   16054 
   16055   i::ScopedVector<ElementType> backing_store(kElementCount+2);
   16056 
   16057   LocalContext env;
   16058   v8::Isolate* isolate = env->GetIsolate();
   16059   v8::HandleScope handle_scope(isolate);
   16060 
   16061   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
   16062       backing_store.start(), (kElementCount+2)*sizeof(ElementType));
   16063   Local<TypedArray> ta =
   16064       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
   16065   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   16066   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
   16067   CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
   16068   CHECK_EQ(kElementCount*sizeof(ElementType),
   16069            static_cast<int>(ta->ByteLength()));
   16070   CHECK_EQ(ab, ta->Buffer());
   16071 
   16072   ElementType* data = backing_store.start() + 2;
   16073   for (int i = 0; i < kElementCount; i++) {
   16074     data[i] = static_cast<ElementType>(i);
   16075   }
   16076 
   16077   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   16078       env.local(), ta, kElementCount, array_type, low, high);
   16079 }
   16080 
   16081 
   16082 THREADED_TEST(Uint8Array) {
   16083   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUnsignedByteArray>(
   16084       v8::kExternalUnsignedByteArray, 0, 0xFF);
   16085 }
   16086 
   16087 
   16088 THREADED_TEST(Int8Array) {
   16089   TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalByteArray>(
   16090       v8::kExternalByteArray, -0x80, 0x7F);
   16091 }
   16092 
   16093 
   16094 THREADED_TEST(Uint16Array) {
   16095   TypedArrayTestHelper<uint16_t,
   16096                        v8::Uint16Array,
   16097                        i::ExternalUnsignedShortArray>(
   16098       v8::kExternalUnsignedShortArray, 0, 0xFFFF);
   16099 }
   16100 
   16101 
   16102 THREADED_TEST(Int16Array) {
   16103   TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalShortArray>(
   16104       v8::kExternalShortArray, -0x8000, 0x7FFF);
   16105 }
   16106 
   16107 
   16108 THREADED_TEST(Uint32Array) {
   16109   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUnsignedIntArray>(
   16110       v8::kExternalUnsignedIntArray, 0, UINT_MAX);
   16111 }
   16112 
   16113 
   16114 THREADED_TEST(Int32Array) {
   16115   TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalIntArray>(
   16116       v8::kExternalIntArray, INT_MIN, INT_MAX);
   16117 }
   16118 
   16119 
   16120 THREADED_TEST(Float32Array) {
   16121   TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloatArray>(
   16122       v8::kExternalFloatArray, -500, 500);
   16123 }
   16124 
   16125 
   16126 THREADED_TEST(Float64Array) {
   16127   TypedArrayTestHelper<double, v8::Float64Array, i::ExternalDoubleArray>(
   16128       v8::kExternalDoubleArray, -500, 500);
   16129 }
   16130 
   16131 
   16132 THREADED_TEST(Uint8ClampedArray) {
   16133   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, i::ExternalPixelArray>(
   16134       v8::kExternalPixelArray, 0, 0xFF);
   16135 }
   16136 
   16137 
   16138 THREADED_TEST(DataView) {
   16139   const int kSize = 50;
   16140 
   16141   i::ScopedVector<uint8_t> backing_store(kSize+2);
   16142 
   16143   LocalContext env;
   16144   v8::Isolate* isolate = env->GetIsolate();
   16145   v8::HandleScope handle_scope(isolate);
   16146 
   16147   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
   16148       backing_store.start(), 2 + kSize);
   16149   Local<v8::DataView> dv =
   16150       v8::DataView::New(ab, 2, kSize);
   16151   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16152   CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
   16153   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16154   CHECK_EQ(ab, dv->Buffer());
   16155 }
   16156 
   16157 
   16158 #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                       \
   16159   THREADED_TEST(Is##View) {                                                   \
   16160     i::FLAG_harmony_array_buffer = true;                                      \
   16161     i::FLAG_harmony_typed_arrays = true;                                      \
   16162     LocalContext env;                                                         \
   16163     v8::Isolate* isolate = env->GetIsolate();                                 \
   16164     v8::HandleScope handle_scope(isolate);                                    \
   16165                                                                               \
   16166     Handle<Value> result = CompileRun(                                        \
   16167         "var ab = new ArrayBuffer(128);"                                      \
   16168         "new " #View "(ab)");                                                 \
   16169     CHECK(result->IsArrayBufferView());                                       \
   16170     CHECK(result->Is##View());                                                \
   16171     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>());   \
   16172   }
   16173 
   16174 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
   16175 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
   16176 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
   16177 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
   16178 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
   16179 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
   16180 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
   16181 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
   16182 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
   16183 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
   16184 
   16185 #undef IS_ARRAY_BUFFER_VIEW_TEST
   16186 
   16187 
   16188 
   16189 THREADED_TEST(ScriptContextDependence) {
   16190   LocalContext c1;
   16191   v8::HandleScope scope(c1->GetIsolate());
   16192   const char *source = "foo";
   16193   v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
   16194   v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
   16195   c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
   16196   CHECK_EQ(dep->Run()->Int32Value(), 100);
   16197   CHECK_EQ(indep->Run()->Int32Value(), 100);
   16198   LocalContext c2;
   16199   c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
   16200   CHECK_EQ(dep->Run()->Int32Value(), 100);
   16201   CHECK_EQ(indep->Run()->Int32Value(), 101);
   16202 }
   16203 
   16204 
   16205 THREADED_TEST(StackTrace) {
   16206   LocalContext context;
   16207   v8::HandleScope scope(context->GetIsolate());
   16208   v8::TryCatch try_catch;
   16209   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   16210   v8::Handle<v8::String> src = v8::String::New(source);
   16211   v8::Handle<v8::String> origin = v8::String::New("stack-trace-test");
   16212   v8::Script::New(src, origin)->Run();
   16213   CHECK(try_catch.HasCaught());
   16214   v8::String::Utf8Value stack(try_catch.StackTrace());
   16215   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
   16216 }
   16217 
   16218 
   16219 // Checks that a StackFrame has certain expected values.
   16220 void checkStackFrame(const char* expected_script_name,
   16221     const char* expected_func_name, int expected_line_number,
   16222     int expected_column, bool is_eval, bool is_constructor,
   16223     v8::Handle<v8::StackFrame> frame) {
   16224   v8::HandleScope scope(v8::Isolate::GetCurrent());
   16225   v8::String::Utf8Value func_name(frame->GetFunctionName());
   16226   v8::String::Utf8Value script_name(frame->GetScriptName());
   16227   if (*script_name == NULL) {
   16228     // The situation where there is no associated script, like for evals.
   16229     CHECK(expected_script_name == NULL);
   16230   } else {
   16231     CHECK(strstr(*script_name, expected_script_name) != NULL);
   16232   }
   16233   CHECK(strstr(*func_name, expected_func_name) != NULL);
   16234   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   16235   CHECK_EQ(expected_column, frame->GetColumn());
   16236   CHECK_EQ(is_eval, frame->IsEval());
   16237   CHECK_EQ(is_constructor, frame->IsConstructor());
   16238 }
   16239 
   16240 
   16241 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
   16242   v8::HandleScope scope(args.GetIsolate());
   16243   const char* origin = "capture-stack-trace-test";
   16244   const int kOverviewTest = 1;
   16245   const int kDetailedTest = 2;
   16246 
   16247   ASSERT(args.Length() == 1);
   16248 
   16249   int testGroup = args[0]->Int32Value();
   16250   if (testGroup == kOverviewTest) {
   16251     v8::Handle<v8::StackTrace> stackTrace =
   16252         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
   16253     CHECK_EQ(4, stackTrace->GetFrameCount());
   16254     checkStackFrame(origin, "bar", 2, 10, false, false,
   16255                     stackTrace->GetFrame(0));
   16256     checkStackFrame(origin, "foo", 6, 3, false, false,
   16257                     stackTrace->GetFrame(1));
   16258     // This is the source string inside the eval which has the call to foo.
   16259     checkStackFrame(NULL, "", 1, 5, false, false,
   16260                     stackTrace->GetFrame(2));
   16261     // The last frame is an anonymous function which has the initial eval call.
   16262     checkStackFrame(origin, "", 8, 7, false, false,
   16263                     stackTrace->GetFrame(3));
   16264 
   16265     CHECK(stackTrace->AsArray()->IsArray());
   16266   } else if (testGroup == kDetailedTest) {
   16267     v8::Handle<v8::StackTrace> stackTrace =
   16268         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
   16269     CHECK_EQ(4, stackTrace->GetFrameCount());
   16270     checkStackFrame(origin, "bat", 4, 22, false, false,
   16271                     stackTrace->GetFrame(0));
   16272     checkStackFrame(origin, "baz", 8, 3, false, true,
   16273                     stackTrace->GetFrame(1));
   16274 #ifdef ENABLE_DEBUGGER_SUPPORT
   16275     bool is_eval = true;
   16276 #else  // ENABLE_DEBUGGER_SUPPORT
   16277     bool is_eval = false;
   16278 #endif  // ENABLE_DEBUGGER_SUPPORT
   16279 
   16280     // This is the source string inside the eval which has the call to baz.
   16281     checkStackFrame(NULL, "", 1, 5, is_eval, false,
   16282                     stackTrace->GetFrame(2));
   16283     // The last frame is an anonymous function which has the initial eval call.
   16284     checkStackFrame(origin, "", 10, 1, false, false,
   16285                     stackTrace->GetFrame(3));
   16286 
   16287     CHECK(stackTrace->AsArray()->IsArray());
   16288   }
   16289 }
   16290 
   16291 
   16292 // Tests the C++ StackTrace API.
   16293 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   16294 // THREADED_TEST(CaptureStackTrace) {
   16295 TEST(CaptureStackTrace) {
   16296   v8::HandleScope scope(v8::Isolate::GetCurrent());
   16297   v8::Handle<v8::String> origin = v8::String::New("capture-stack-trace-test");
   16298   Local<ObjectTemplate> templ = ObjectTemplate::New();
   16299   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   16300              v8::FunctionTemplate::New(AnalyzeStackInNativeCode));
   16301   LocalContext context(0, templ);
   16302 
   16303   // Test getting OVERVIEW information. Should ignore information that is not
   16304   // script name, function name, line number, and column offset.
   16305   const char *overview_source =
   16306     "function bar() {\n"
   16307     "  var y; AnalyzeStackInNativeCode(1);\n"
   16308     "}\n"
   16309     "function foo() {\n"
   16310     "\n"
   16311     "  bar();\n"
   16312     "}\n"
   16313     "var x;eval('new foo();');";
   16314   v8::Handle<v8::String> overview_src = v8::String::New(overview_source);
   16315   v8::Handle<Value> overview_result(
   16316       v8::Script::New(overview_src, origin)->Run());
   16317   CHECK(!overview_result.IsEmpty());
   16318   CHECK(overview_result->IsObject());
   16319 
   16320   // Test getting DETAILED information.
   16321   const char *detailed_source =
   16322     "function bat() {AnalyzeStackInNativeCode(2);\n"
   16323     "}\n"
   16324     "\n"
   16325     "function baz() {\n"
   16326     "  bat();\n"
   16327     "}\n"
   16328     "eval('new baz();');";
   16329   v8::Handle<v8::String> detailed_src = v8::String::New(detailed_source);
   16330   // Make the script using a non-zero line and column offset.
   16331   v8::Handle<v8::Integer> line_offset = v8::Integer::New(3);
   16332   v8::Handle<v8::Integer> column_offset = v8::Integer::New(5);
   16333   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   16334   v8::Handle<v8::Script> detailed_script(
   16335       v8::Script::New(detailed_src, &detailed_origin));
   16336   v8::Handle<Value> detailed_result(detailed_script->Run());
   16337   CHECK(!detailed_result.IsEmpty());
   16338   CHECK(detailed_result->IsObject());
   16339 }
   16340 
   16341 
   16342 static void StackTraceForUncaughtExceptionListener(
   16343     v8::Handle<v8::Message> message,
   16344     v8::Handle<Value>) {
   16345   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16346   CHECK_EQ(2, stack_trace->GetFrameCount());
   16347   checkStackFrame("origin", "foo", 2, 3, false, false,
   16348                   stack_trace->GetFrame(0));
   16349   checkStackFrame("origin", "bar", 5, 3, false, false,
   16350                   stack_trace->GetFrame(1));
   16351 }
   16352 
   16353 
   16354 TEST(CaptureStackTraceForUncaughtException) {
   16355   report_count = 0;
   16356   LocalContext env;
   16357   v8::HandleScope scope(env->GetIsolate());
   16358   v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
   16359   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16360 
   16361   Script::Compile(v8_str("function foo() {\n"
   16362                          "  throw 1;\n"
   16363                          "};\n"
   16364                          "function bar() {\n"
   16365                          "  foo();\n"
   16366                          "};"),
   16367                   v8_str("origin"))->Run();
   16368   v8::Local<v8::Object> global = env->Global();
   16369   Local<Value> trouble = global->Get(v8_str("bar"));
   16370   CHECK(trouble->IsFunction());
   16371   Function::Cast(*trouble)->Call(global, 0, NULL);
   16372   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16373   v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   16374 }
   16375 
   16376 
   16377 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   16378   LocalContext env;
   16379   v8::HandleScope scope(env->GetIsolate());
   16380   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
   16381                                                     1024,
   16382                                                     v8::StackTrace::kDetailed);
   16383 
   16384   CompileRun(
   16385       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   16386       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   16387       "    'isConstructor'];\n"
   16388       "for (var i = 0; i < setters.length; i++) {\n"
   16389       "  var prop = setters[i];\n"
   16390       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   16391       "}\n");
   16392   CompileRun("throw 'exception';");
   16393   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16394 }
   16395 
   16396 
   16397 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
   16398                                      v8::Handle<v8::Value> data) {
   16399   // Use the frame where JavaScript is called from.
   16400   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16401   CHECK(!stack_trace.IsEmpty());
   16402   int frame_count = stack_trace->GetFrameCount();
   16403   CHECK_EQ(3, frame_count);
   16404   int line_number[] = {1, 2, 5};
   16405   for (int i = 0; i < frame_count; i++) {
   16406     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   16407   }
   16408 }
   16409 
   16410 
   16411 // Test that we only return the stack trace at the site where the exception
   16412 // is first thrown (not where it is rethrown).
   16413 TEST(RethrowStackTrace) {
   16414   LocalContext env;
   16415   v8::HandleScope scope(env->GetIsolate());
   16416   // We make sure that
   16417   // - the stack trace of the ReferenceError in g() is reported.
   16418   // - the stack trace is not overwritten when e1 is rethrown by t().
   16419   // - the stack trace of e2 does not overwrite that of e1.
   16420   const char* source =
   16421       "function g() { error; }          \n"
   16422       "function f() { g(); }            \n"
   16423       "function t(e) { throw e; }       \n"
   16424       "try {                            \n"
   16425       "  f();                           \n"
   16426       "} catch (e1) {                   \n"
   16427       "  try {                          \n"
   16428       "    error;                       \n"
   16429       "  } catch (e2) {                 \n"
   16430       "    t(e1);                       \n"
   16431       "  }                              \n"
   16432       "}                                \n";
   16433   v8::V8::AddMessageListener(RethrowStackTraceHandler);
   16434   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16435   CompileRun(source);
   16436   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16437   v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
   16438 }
   16439 
   16440 
   16441 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
   16442                                               v8::Handle<v8::Value> data) {
   16443   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16444   CHECK(!stack_trace.IsEmpty());
   16445   int frame_count = stack_trace->GetFrameCount();
   16446   CHECK_EQ(2, frame_count);
   16447   int line_number[] = {3, 7};
   16448   for (int i = 0; i < frame_count; i++) {
   16449     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   16450   }
   16451 }
   16452 
   16453 
   16454 // Test that we do not recognize identity for primitive exceptions.
   16455 TEST(RethrowPrimitiveStackTrace) {
   16456   LocalContext env;
   16457   v8::HandleScope scope(env->GetIsolate());
   16458   // We do not capture stack trace for non Error objects on creation time.
   16459   // Instead, we capture the stack trace on last throw.
   16460   const char* source =
   16461       "function g() { throw 404; }      \n"
   16462       "function f() { g(); }            \n"
   16463       "function t(e) { throw e; }       \n"
   16464       "try {                            \n"
   16465       "  f();                           \n"
   16466       "} catch (e1) {                   \n"
   16467       "  t(e1)                          \n"
   16468       "}                                \n";
   16469   v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
   16470   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16471   CompileRun(source);
   16472   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16473   v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   16474 }
   16475 
   16476 
   16477 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
   16478                                               v8::Handle<v8::Value> data) {
   16479   // Use the frame where JavaScript is called from.
   16480   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16481   CHECK(!stack_trace.IsEmpty());
   16482   CHECK_EQ(1, stack_trace->GetFrameCount());
   16483   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
   16484 }
   16485 
   16486 
   16487 // Test that the stack trace is captured when the error object is created and
   16488 // not where it is thrown.
   16489 TEST(RethrowExistingStackTrace) {
   16490   LocalContext env;
   16491   v8::HandleScope scope(env->GetIsolate());
   16492   const char* source =
   16493       "var e = new Error();           \n"
   16494       "throw e;                       \n";
   16495   v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
   16496   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16497   CompileRun(source);
   16498   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16499   v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
   16500 }
   16501 
   16502 
   16503 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
   16504                                                v8::Handle<v8::Value> data) {
   16505   // Use the frame where JavaScript is called from.
   16506   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   16507   CHECK(!stack_trace.IsEmpty());
   16508   CHECK_EQ(1, stack_trace->GetFrameCount());
   16509   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
   16510 }
   16511 
   16512 
   16513 // Test that the stack trace is captured where the bogus Error object is thrown.
   16514 TEST(RethrowBogusErrorStackTrace) {
   16515   LocalContext env;
   16516   v8::HandleScope scope(env->GetIsolate());
   16517   const char* source =
   16518       "var e = {__proto__: new Error()} \n"
   16519       "throw e;                         \n";
   16520   v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
   16521   v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
   16522   CompileRun(source);
   16523   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
   16524   v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   16525 }
   16526 
   16527 
   16528 void AnalyzeStackOfEvalWithSourceURL(
   16529     const v8::FunctionCallbackInfo<v8::Value>& args) {
   16530   v8::HandleScope scope(args.GetIsolate());
   16531   v8::Handle<v8::StackTrace> stackTrace =
   16532       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
   16533   CHECK_EQ(5, stackTrace->GetFrameCount());
   16534   v8::Handle<v8::String> url = v8_str("eval_url");
   16535   for (int i = 0; i < 3; i++) {
   16536     v8::Handle<v8::String> name =
   16537         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   16538     CHECK(!name.IsEmpty());
   16539     CHECK_EQ(url, name);
   16540   }
   16541 }
   16542 
   16543 
   16544 TEST(SourceURLInStackTrace) {
   16545   v8::HandleScope scope(v8::Isolate::GetCurrent());
   16546   Local<ObjectTemplate> templ = ObjectTemplate::New();
   16547   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   16548              v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
   16549   LocalContext context(0, templ);
   16550 
   16551   const char *source =
   16552     "function outer() {\n"
   16553     "function bar() {\n"
   16554     "  AnalyzeStackOfEvalWithSourceURL();\n"
   16555     "}\n"
   16556     "function foo() {\n"
   16557     "\n"
   16558     "  bar();\n"
   16559     "}\n"
   16560     "foo();\n"
   16561     "}\n"
   16562     "eval('(' + outer +')()%s');";
   16563 
   16564   i::ScopedVector<char> code(1024);
   16565   i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
   16566   CHECK(CompileRun(code.start())->IsUndefined());
   16567   i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
   16568   CHECK(CompileRun(code.start())->IsUndefined());
   16569 }
   16570 
   16571 
   16572 void AnalyzeStackOfInlineScriptWithSourceURL(
   16573     const v8::FunctionCallbackInfo<v8::Value>& args) {
   16574   v8::HandleScope scope(args.GetIsolate());
   16575   v8::Handle<v8::StackTrace> stackTrace =
   16576       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
   16577   CHECK_EQ(4, stackTrace->GetFrameCount());
   16578   v8::Handle<v8::String> url = v8_str("url");
   16579   for (int i = 0; i < 3; i++) {
   16580     v8::Handle<v8::String> name =
   16581         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   16582     CHECK(!name.IsEmpty());
   16583     CHECK_EQ(url, name);
   16584   }
   16585 }
   16586 
   16587 
   16588 TEST(InlineScriptWithSourceURLInStackTrace) {
   16589   v8::HandleScope scope(v8::Isolate::GetCurrent());
   16590   Local<ObjectTemplate> templ = ObjectTemplate::New();
   16591   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
   16592              v8::FunctionTemplate::New(
   16593                  AnalyzeStackOfInlineScriptWithSourceURL));
   16594   LocalContext context(0, templ);
   16595 
   16596   const char *source =
   16597     "function outer() {\n"
   16598     "function bar() {\n"
   16599     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
   16600     "}\n"
   16601     "function foo() {\n"
   16602     "\n"
   16603     "  bar();\n"
   16604     "}\n"
   16605     "foo();\n"
   16606     "}\n"
   16607     "outer()\n%s";
   16608 
   16609   i::ScopedVector<char> code(1024);
   16610   i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
   16611   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   16612   i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
   16613   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   16614 }
   16615 
   16616 
   16617 void AnalyzeStackOfDynamicScriptWithSourceURL(
   16618     const v8::FunctionCallbackInfo<v8::Value>& args) {
   16619   v8::HandleScope scope(args.GetIsolate());
   16620   v8::Handle<v8::StackTrace> stackTrace =
   16621       v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
   16622   CHECK_EQ(4, stackTrace->GetFrameCount());
   16623   v8::Handle<v8::String> url = v8_str("source_url");
   16624   for (int i = 0; i < 3; i++) {
   16625     v8::Handle<v8::String> name =
   16626         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   16627     CHECK(!name.IsEmpty());
   16628     CHECK_EQ(url, name);
   16629   }
   16630 }
   16631 
   16632 
   16633 TEST(DynamicWithSourceURLInStackTrace) {
   16634   v8::HandleScope scope(v8::Isolate::GetCurrent());
   16635   Local<ObjectTemplate> templ = ObjectTemplate::New();
   16636   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
   16637              v8::FunctionTemplate::New(
   16638                  AnalyzeStackOfDynamicScriptWithSourceURL));
   16639   LocalContext context(0, templ);
   16640 
   16641   const char *source =
   16642     "function outer() {\n"
   16643     "function bar() {\n"
   16644     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
   16645     "}\n"
   16646     "function foo() {\n"
   16647     "\n"
   16648     "  bar();\n"
   16649     "}\n"
   16650     "foo();\n"
   16651     "}\n"
   16652     "outer()\n%s";
   16653 
   16654   i::ScopedVector<char> code(1024);
   16655   i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
   16656   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   16657   i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
   16658   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   16659 }
   16660 
   16661 
   16662 static void CreateGarbageInOldSpace() {
   16663   i::Factory* factory = i::Isolate::Current()->factory();
   16664   v8::HandleScope scope(v8::Isolate::GetCurrent());
   16665   i::AlwaysAllocateScope always_allocate;
   16666   for (int i = 0; i < 1000; i++) {
   16667     factory->NewFixedArray(1000, i::TENURED);
   16668   }
   16669 }
   16670 
   16671 
   16672 // Test that idle notification can be handled and eventually returns true.
   16673 TEST(IdleNotification) {
   16674   const intptr_t MB = 1024 * 1024;
   16675   LocalContext env;
   16676   v8::HandleScope scope(env->GetIsolate());
   16677   intptr_t initial_size = HEAP->SizeOfObjects();
   16678   CreateGarbageInOldSpace();
   16679   intptr_t size_with_garbage = HEAP->SizeOfObjects();
   16680   CHECK_GT(size_with_garbage, initial_size + MB);
   16681   bool finished = false;
   16682   for (int i = 0; i < 200 && !finished; i++) {
   16683     finished = v8::V8::IdleNotification();
   16684   }
   16685   intptr_t final_size = HEAP->SizeOfObjects();
   16686   CHECK(finished);
   16687   CHECK_LT(final_size, initial_size + 1);
   16688 }
   16689 
   16690 
   16691 // Test that idle notification can be handled and eventually collects garbage.
   16692 TEST(IdleNotificationWithSmallHint) {
   16693   const intptr_t MB = 1024 * 1024;
   16694   const int IdlePauseInMs = 900;
   16695   LocalContext env;
   16696   v8::HandleScope scope(env->GetIsolate());
   16697   intptr_t initial_size = HEAP->SizeOfObjects();
   16698   CreateGarbageInOldSpace();
   16699   intptr_t size_with_garbage = HEAP->SizeOfObjects();
   16700   CHECK_GT(size_with_garbage, initial_size + MB);
   16701   bool finished = false;
   16702   for (int i = 0; i < 200 && !finished; i++) {
   16703     finished = v8::V8::IdleNotification(IdlePauseInMs);
   16704   }
   16705   intptr_t final_size = HEAP->SizeOfObjects();
   16706   CHECK(finished);
   16707   CHECK_LT(final_size, initial_size + 1);
   16708 }
   16709 
   16710 
   16711 // Test that idle notification can be handled and eventually collects garbage.
   16712 TEST(IdleNotificationWithLargeHint) {
   16713   const intptr_t MB = 1024 * 1024;
   16714   const int IdlePauseInMs = 900;
   16715   LocalContext env;
   16716   v8::HandleScope scope(env->GetIsolate());
   16717   intptr_t initial_size = HEAP->SizeOfObjects();
   16718   CreateGarbageInOldSpace();
   16719   intptr_t size_with_garbage = HEAP->SizeOfObjects();
   16720   CHECK_GT(size_with_garbage, initial_size + MB);
   16721   bool finished = false;
   16722   for (int i = 0; i < 200 && !finished; i++) {
   16723     finished = v8::V8::IdleNotification(IdlePauseInMs);
   16724   }
   16725   intptr_t final_size = HEAP->SizeOfObjects();
   16726   CHECK(finished);
   16727   CHECK_LT(final_size, initial_size + 1);
   16728 }
   16729 
   16730 
   16731 TEST(Regress2107) {
   16732   const intptr_t MB = 1024 * 1024;
   16733   const int kShortIdlePauseInMs = 100;
   16734   const int kLongIdlePauseInMs = 1000;
   16735   LocalContext env;
   16736   v8::Isolate* isolate = env->GetIsolate();
   16737   v8::HandleScope scope(env->GetIsolate());
   16738   intptr_t initial_size = HEAP->SizeOfObjects();
   16739   // Send idle notification to start a round of incremental GCs.
   16740   v8::V8::IdleNotification(kShortIdlePauseInMs);
   16741   // Emulate 7 page reloads.
   16742   for (int i = 0; i < 7; i++) {
   16743     {
   16744       v8::HandleScope inner_scope(env->GetIsolate());
   16745       v8::Local<v8::Context> ctx = v8::Context::New(isolate);
   16746       ctx->Enter();
   16747       CreateGarbageInOldSpace();
   16748       ctx->Exit();
   16749     }
   16750     v8::V8::ContextDisposedNotification();
   16751     v8::V8::IdleNotification(kLongIdlePauseInMs);
   16752   }
   16753   // Create garbage and check that idle notification still collects it.
   16754   CreateGarbageInOldSpace();
   16755   intptr_t size_with_garbage = HEAP->SizeOfObjects();
   16756   CHECK_GT(size_with_garbage, initial_size + MB);
   16757   bool finished = false;
   16758   for (int i = 0; i < 200 && !finished; i++) {
   16759     finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
   16760   }
   16761   intptr_t final_size = HEAP->SizeOfObjects();
   16762   CHECK_LT(final_size, initial_size + 1);
   16763 }
   16764 
   16765 static uint32_t* stack_limit;
   16766 
   16767 static void GetStackLimitCallback(
   16768     const v8::FunctionCallbackInfo<v8::Value>& args) {
   16769   stack_limit = reinterpret_cast<uint32_t*>(
   16770       i::Isolate::Current()->stack_guard()->real_climit());
   16771 }
   16772 
   16773 
   16774 // Uses the address of a local variable to determine the stack top now.
   16775 // Given a size, returns an address that is that far from the current
   16776 // top of stack.
   16777 static uint32_t* ComputeStackLimit(uint32_t size) {
   16778   uint32_t* answer = &size - (size / sizeof(size));
   16779   // If the size is very large and the stack is very near the bottom of
   16780   // memory then the calculation above may wrap around and give an address
   16781   // that is above the (downwards-growing) stack.  In that case we return
   16782   // a very low address.
   16783   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   16784   return answer;
   16785 }
   16786 
   16787 
   16788 // We need at least 165kB for an x64 debug build with clang and ASAN.
   16789 static const int stack_breathing_room = 256 * i::KB;
   16790 
   16791 
   16792 TEST(SetResourceConstraints) {
   16793   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
   16794 
   16795   // Set stack limit.
   16796   v8::ResourceConstraints constraints;
   16797   constraints.set_stack_limit(set_limit);
   16798   CHECK(v8::SetResourceConstraints(&constraints));
   16799 
   16800   // Execute a script.
   16801   LocalContext env;
   16802   v8::HandleScope scope(env->GetIsolate());
   16803   Local<v8::FunctionTemplate> fun_templ =
   16804       v8::FunctionTemplate::New(GetStackLimitCallback);
   16805   Local<Function> fun = fun_templ->GetFunction();
   16806   env->Global()->Set(v8_str("get_stack_limit"), fun);
   16807   CompileRun("get_stack_limit();");
   16808 
   16809   CHECK(stack_limit == set_limit);
   16810 }
   16811 
   16812 
   16813 TEST(SetResourceConstraintsInThread) {
   16814   uint32_t* set_limit;
   16815   {
   16816     v8::Locker locker(CcTest::default_isolate());
   16817     set_limit = ComputeStackLimit(stack_breathing_room);
   16818 
   16819     // Set stack limit.
   16820     v8::ResourceConstraints constraints;
   16821     constraints.set_stack_limit(set_limit);
   16822     CHECK(v8::SetResourceConstraints(&constraints));
   16823 
   16824     // Execute a script.
   16825     v8::HandleScope scope(CcTest::default_isolate());
   16826     LocalContext env;
   16827     Local<v8::FunctionTemplate> fun_templ =
   16828         v8::FunctionTemplate::New(GetStackLimitCallback);
   16829     Local<Function> fun = fun_templ->GetFunction();
   16830     env->Global()->Set(v8_str("get_stack_limit"), fun);
   16831     CompileRun("get_stack_limit();");
   16832 
   16833     CHECK(stack_limit == set_limit);
   16834   }
   16835   {
   16836     v8::Locker locker(CcTest::default_isolate());
   16837     CHECK(stack_limit == set_limit);
   16838   }
   16839 }
   16840 
   16841 
   16842 THREADED_TEST(GetHeapStatistics) {
   16843   LocalContext c1;
   16844   v8::HandleScope scope(c1->GetIsolate());
   16845   v8::HeapStatistics heap_statistics;
   16846   CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
   16847   CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
   16848   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
   16849   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   16850   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   16851 }
   16852 
   16853 
   16854 class VisitorImpl : public v8::ExternalResourceVisitor {
   16855  public:
   16856   explicit VisitorImpl(TestResource** resource) {
   16857     for (int i = 0; i < 4; i++) {
   16858       resource_[i] = resource[i];
   16859       found_resource_[i] = false;
   16860     }
   16861   }
   16862   virtual ~VisitorImpl() {}
   16863   virtual void VisitExternalString(v8::Handle<v8::String> string) {
   16864     if (!string->IsExternal()) {
   16865       CHECK(string->IsExternalAscii());
   16866       return;
   16867     }
   16868     v8::String::ExternalStringResource* resource =
   16869         string->GetExternalStringResource();
   16870     CHECK(resource);
   16871     for (int i = 0; i < 4; i++) {
   16872       if (resource_[i] == resource) {
   16873         CHECK(!found_resource_[i]);
   16874         found_resource_[i] = true;
   16875       }
   16876     }
   16877   }
   16878   void CheckVisitedResources() {
   16879     for (int i = 0; i < 4; i++) {
   16880       CHECK(found_resource_[i]);
   16881     }
   16882   }
   16883 
   16884  private:
   16885   v8::String::ExternalStringResource* resource_[4];
   16886   bool found_resource_[4];
   16887 };
   16888 
   16889 
   16890 TEST(VisitExternalStrings) {
   16891   LocalContext env;
   16892   v8::HandleScope scope(env->GetIsolate());
   16893   const char* string = "Some string";
   16894   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   16895   TestResource* resource[4];
   16896   resource[0] = new TestResource(two_byte_string);
   16897   v8::Local<v8::String> string0 = v8::String::NewExternal(resource[0]);
   16898   resource[1] = new TestResource(two_byte_string);
   16899   v8::Local<v8::String> string1 = v8::String::NewExternal(resource[1]);
   16900 
   16901   // Externalized symbol.
   16902   resource[2] = new TestResource(two_byte_string);
   16903   v8::Local<v8::String> string2 = v8::String::NewSymbol(string);
   16904   CHECK(string2->MakeExternal(resource[2]));
   16905 
   16906   // Symbolized External.
   16907   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
   16908   v8::Local<v8::String> string3 = v8::String::NewExternal(resource[3]);
   16909   HEAP->CollectAllAvailableGarbage();  // Tenure string.
   16910   // Turn into a symbol.
   16911   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
   16912   CHECK(!HEAP->InternalizeString(*string3_i)->IsFailure());
   16913   CHECK(string3_i->IsInternalizedString());
   16914 
   16915   // We need to add usages for string* to avoid warnings in GCC 4.7
   16916   CHECK(string0->IsExternal());
   16917   CHECK(string1->IsExternal());
   16918   CHECK(string2->IsExternal());
   16919   CHECK(string3->IsExternal());
   16920 
   16921   VisitorImpl visitor(resource);
   16922   v8::V8::VisitExternalResources(&visitor);
   16923   visitor.CheckVisitedResources();
   16924 }
   16925 
   16926 
   16927 static double DoubleFromBits(uint64_t value) {
   16928   double target;
   16929   i::OS::MemCopy(&target, &value, sizeof(target));
   16930   return target;
   16931 }
   16932 
   16933 
   16934 static uint64_t DoubleToBits(double value) {
   16935   uint64_t target;
   16936   i::OS::MemCopy(&target, &value, sizeof(target));
   16937   return target;
   16938 }
   16939 
   16940 
   16941 static double DoubleToDateTime(double input) {
   16942   double date_limit = 864e13;
   16943   if (std::isnan(input) || input < -date_limit || input > date_limit) {
   16944     return i::OS::nan_value();
   16945   }
   16946   return (input < 0) ? -(floor(-input)) : floor(input);
   16947 }
   16948 
   16949 
   16950 // We don't have a consistent way to write 64-bit constants syntactically, so we
   16951 // split them into two 32-bit constants and combine them programmatically.
   16952 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   16953   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   16954 }
   16955 
   16956 
   16957 THREADED_TEST(QuietSignalingNaNs) {
   16958   LocalContext context;
   16959   v8::HandleScope scope(context->GetIsolate());
   16960   v8::TryCatch try_catch;
   16961 
   16962   // Special double values.
   16963   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
   16964   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
   16965   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
   16966   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
   16967   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   16968   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
   16969   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   16970 
   16971   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   16972   // on either side of the epoch.
   16973   double date_limit = 864e13;
   16974 
   16975   double test_values[] = {
   16976       snan,
   16977       qnan,
   16978       infinity,
   16979       max_normal,
   16980       date_limit + 1,
   16981       date_limit,
   16982       min_normal,
   16983       max_denormal,
   16984       min_denormal,
   16985       0,
   16986       -0,
   16987       -min_denormal,
   16988       -max_denormal,
   16989       -min_normal,
   16990       -date_limit,
   16991       -date_limit - 1,
   16992       -max_normal,
   16993       -infinity,
   16994       -qnan,
   16995       -snan
   16996   };
   16997   int num_test_values = 20;
   16998 
   16999   for (int i = 0; i < num_test_values; i++) {
   17000     double test_value = test_values[i];
   17001 
   17002     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   17003     v8::Handle<v8::Value> number = v8::Number::New(test_value);
   17004     double stored_number = number->NumberValue();
   17005     if (!std::isnan(test_value)) {
   17006       CHECK_EQ(test_value, stored_number);
   17007     } else {
   17008       uint64_t stored_bits = DoubleToBits(stored_number);
   17009       // Check if quiet nan (bits 51..62 all set).
   17010 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
   17011       // Most significant fraction bit for quiet nan is set to 0
   17012       // on MIPS architecture. Allowed by IEEE-754.
   17013       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   17014 #else
   17015       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   17016 #endif
   17017     }
   17018 
   17019     // Check that Date::New preserves non-NaNs in the date range and
   17020     // quiets SNaNs.
   17021     v8::Handle<v8::Value> date = v8::Date::New(test_value);
   17022     double expected_stored_date = DoubleToDateTime(test_value);
   17023     double stored_date = date->NumberValue();
   17024     if (!std::isnan(expected_stored_date)) {
   17025       CHECK_EQ(expected_stored_date, stored_date);
   17026     } else {
   17027       uint64_t stored_bits = DoubleToBits(stored_date);
   17028       // Check if quiet nan (bits 51..62 all set).
   17029 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
   17030       // Most significant fraction bit for quiet nan is set to 0
   17031       // on MIPS architecture. Allowed by IEEE-754.
   17032       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   17033 #else
   17034       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   17035 #endif
   17036     }
   17037   }
   17038 }
   17039 
   17040 
   17041 static void SpaghettiIncident(
   17042     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17043   v8::HandleScope scope(args.GetIsolate());
   17044   v8::TryCatch tc;
   17045   v8::Handle<v8::String> str(args[0]->ToString());
   17046   USE(str);
   17047   if (tc.HasCaught())
   17048     tc.ReThrow();
   17049 }
   17050 
   17051 
   17052 // Test that an exception can be propagated down through a spaghetti
   17053 // stack using ReThrow.
   17054 THREADED_TEST(SpaghettiStackReThrow) {
   17055   v8::HandleScope scope(v8::Isolate::GetCurrent());
   17056   LocalContext context;
   17057   context->Global()->Set(
   17058       v8::String::New("s"),
   17059       v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction());
   17060   v8::TryCatch try_catch;
   17061   CompileRun(
   17062       "var i = 0;"
   17063       "var o = {"
   17064       "  toString: function () {"
   17065       "    if (i == 10) {"
   17066       "      throw 'Hey!';"
   17067       "    } else {"
   17068       "      i++;"
   17069       "      return s(o);"
   17070       "    }"
   17071       "  }"
   17072       "};"
   17073       "s(o);");
   17074   CHECK(try_catch.HasCaught());
   17075   v8::String::Utf8Value value(try_catch.Exception());
   17076   CHECK_EQ(0, strcmp(*value, "Hey!"));
   17077 }
   17078 
   17079 
   17080 TEST(Regress528) {
   17081   v8::V8::Initialize();
   17082   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   17083   v8::HandleScope scope(isolate);
   17084   v8::Local<Context> other_context;
   17085   int gc_count;
   17086 
   17087   // Create a context used to keep the code from aging in the compilation
   17088   // cache.
   17089   other_context = Context::New(isolate);
   17090 
   17091   // Context-dependent context data creates reference from the compilation
   17092   // cache to the global object.
   17093   const char* source_simple = "1";
   17094   {
   17095     v8::HandleScope scope(isolate);
   17096     v8::Local<Context> context = Context::New(isolate);
   17097 
   17098     context->Enter();
   17099     Local<v8::String> obj = v8::String::New("");
   17100     context->SetEmbedderData(0, obj);
   17101     CompileRun(source_simple);
   17102     context->Exit();
   17103   }
   17104   v8::V8::ContextDisposedNotification();
   17105   for (gc_count = 1; gc_count < 10; gc_count++) {
   17106     other_context->Enter();
   17107     CompileRun(source_simple);
   17108     other_context->Exit();
   17109     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   17110     if (GetGlobalObjectsCount() == 1) break;
   17111   }
   17112   CHECK_GE(2, gc_count);
   17113   CHECK_EQ(1, GetGlobalObjectsCount());
   17114 
   17115   // Eval in a function creates reference from the compilation cache to the
   17116   // global object.
   17117   const char* source_eval = "function f(){eval('1')}; f()";
   17118   {
   17119     v8::HandleScope scope(isolate);
   17120     v8::Local<Context> context = Context::New(isolate);
   17121 
   17122     context->Enter();
   17123     CompileRun(source_eval);
   17124     context->Exit();
   17125   }
   17126   v8::V8::ContextDisposedNotification();
   17127   for (gc_count = 1; gc_count < 10; gc_count++) {
   17128     other_context->Enter();
   17129     CompileRun(source_eval);
   17130     other_context->Exit();
   17131     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   17132     if (GetGlobalObjectsCount() == 1) break;
   17133   }
   17134   CHECK_GE(2, gc_count);
   17135   CHECK_EQ(1, GetGlobalObjectsCount());
   17136 
   17137   // Looking up the line number for an exception creates reference from the
   17138   // compilation cache to the global object.
   17139   const char* source_exception = "function f(){throw 1;} f()";
   17140   {
   17141     v8::HandleScope scope(isolate);
   17142     v8::Local<Context> context = Context::New(isolate);
   17143 
   17144     context->Enter();
   17145     v8::TryCatch try_catch;
   17146     CompileRun(source_exception);
   17147     CHECK(try_catch.HasCaught());
   17148     v8::Handle<v8::Message> message = try_catch.Message();
   17149     CHECK(!message.IsEmpty());
   17150     CHECK_EQ(1, message->GetLineNumber());
   17151     context->Exit();
   17152   }
   17153   v8::V8::ContextDisposedNotification();
   17154   for (gc_count = 1; gc_count < 10; gc_count++) {
   17155     other_context->Enter();
   17156     CompileRun(source_exception);
   17157     other_context->Exit();
   17158     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   17159     if (GetGlobalObjectsCount() == 1) break;
   17160   }
   17161   CHECK_GE(2, gc_count);
   17162   CHECK_EQ(1, GetGlobalObjectsCount());
   17163 
   17164   v8::V8::ContextDisposedNotification();
   17165 }
   17166 
   17167 
   17168 THREADED_TEST(ScriptOrigin) {
   17169   LocalContext env;
   17170   v8::HandleScope scope(env->GetIsolate());
   17171   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
   17172   v8::Handle<v8::String> script = v8::String::New(
   17173       "function f() {}\n\nfunction g() {}");
   17174   v8::Script::Compile(script, &origin)->Run();
   17175   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17176       env->Global()->Get(v8::String::New("f")));
   17177   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   17178       env->Global()->Get(v8::String::New("g")));
   17179 
   17180   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   17181   CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
   17182   CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
   17183 
   17184   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   17185   CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
   17186   CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
   17187 }
   17188 
   17189 
   17190 THREADED_TEST(FunctionGetInferredName) {
   17191   LocalContext env;
   17192   v8::HandleScope scope(env->GetIsolate());
   17193   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
   17194   v8::Handle<v8::String> script = v8::String::New(
   17195       "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   17196   v8::Script::Compile(script, &origin)->Run();
   17197   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17198       env->Global()->Get(v8::String::New("f")));
   17199   CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
   17200 }
   17201 
   17202 
   17203 THREADED_TEST(ScriptLineNumber) {
   17204   LocalContext env;
   17205   v8::HandleScope scope(env->GetIsolate());
   17206   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
   17207   v8::Handle<v8::String> script = v8::String::New(
   17208       "function f() {}\n\nfunction g() {}");
   17209   v8::Script::Compile(script, &origin)->Run();
   17210   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17211       env->Global()->Get(v8::String::New("f")));
   17212   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   17213       env->Global()->Get(v8::String::New("g")));
   17214   CHECK_EQ(0, f->GetScriptLineNumber());
   17215   CHECK_EQ(2, g->GetScriptLineNumber());
   17216 }
   17217 
   17218 
   17219 THREADED_TEST(ScriptColumnNumber) {
   17220   LocalContext env;
   17221   v8::HandleScope scope(env->GetIsolate());
   17222   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
   17223       v8::Integer::New(3), v8::Integer::New(2));
   17224   v8::Handle<v8::String> script = v8::String::New(
   17225       "function foo() {}\n\n     function bar() {}");
   17226   v8::Script::Compile(script, &origin)->Run();
   17227   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   17228       env->Global()->Get(v8::String::New("foo")));
   17229   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   17230       env->Global()->Get(v8::String::New("bar")));
   17231   CHECK_EQ(14, foo->GetScriptColumnNumber());
   17232   CHECK_EQ(17, bar->GetScriptColumnNumber());
   17233 }
   17234 
   17235 
   17236 THREADED_TEST(FunctionGetScriptId) {
   17237   LocalContext env;
   17238   v8::HandleScope scope(env->GetIsolate());
   17239   v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
   17240       v8::Integer::New(3), v8::Integer::New(2));
   17241   v8::Handle<v8::String> scriptSource = v8::String::New(
   17242       "function foo() {}\n\n     function bar() {}");
   17243   v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
   17244   script->Run();
   17245   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   17246       env->Global()->Get(v8::String::New("foo")));
   17247   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   17248       env->Global()->Get(v8::String::New("bar")));
   17249   CHECK_EQ(script->Id(), foo->GetScriptId());
   17250   CHECK_EQ(script->Id(), bar->GetScriptId());
   17251 }
   17252 
   17253 
   17254 static void GetterWhichReturns42(
   17255     Local<String> name,
   17256     const v8::PropertyCallbackInfo<v8::Value>& info) {
   17257   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   17258   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   17259   info.GetReturnValue().Set(v8_num(42));
   17260 }
   17261 
   17262 
   17263 static void SetterWhichSetsYOnThisTo23(
   17264     Local<String> name,
   17265     Local<Value> value,
   17266     const v8::PropertyCallbackInfo<void>& info) {
   17267   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   17268   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   17269   info.This()->Set(v8_str("y"), v8_num(23));
   17270 }
   17271 
   17272 
   17273 void FooGetInterceptor(Local<String> name,
   17274                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   17275   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   17276   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   17277   if (!name->Equals(v8_str("foo"))) return;
   17278   info.GetReturnValue().Set(v8_num(42));
   17279 }
   17280 
   17281 
   17282 void FooSetInterceptor(Local<String> name,
   17283                        Local<Value> value,
   17284                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   17285   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   17286   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   17287   if (!name->Equals(v8_str("foo"))) return;
   17288   info.This()->Set(v8_str("y"), v8_num(23));
   17289   info.GetReturnValue().Set(v8_num(23));
   17290 }
   17291 
   17292 
   17293 TEST(SetterOnConstructorPrototype) {
   17294   v8::HandleScope scope(v8::Isolate::GetCurrent());
   17295   Local<ObjectTemplate> templ = ObjectTemplate::New();
   17296   templ->SetAccessor(v8_str("x"),
   17297                      GetterWhichReturns42,
   17298                      SetterWhichSetsYOnThisTo23);
   17299   LocalContext context;
   17300   context->Global()->Set(v8_str("P"), templ->NewInstance());
   17301   CompileRun("function C1() {"
   17302              "  this.x = 23;"
   17303              "};"
   17304              "C1.prototype = P;"
   17305              "function C2() {"
   17306              "  this.x = 23"
   17307              "};"
   17308              "C2.prototype = { };"
   17309              "C2.prototype.__proto__ = P;");
   17310 
   17311   v8::Local<v8::Script> script;
   17312   script = v8::Script::Compile(v8_str("new C1();"));
   17313   for (int i = 0; i < 10; i++) {
   17314     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   17315     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   17316     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   17317   }
   17318 
   17319   script = v8::Script::Compile(v8_str("new C2();"));
   17320   for (int i = 0; i < 10; i++) {
   17321     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   17322     CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
   17323     CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
   17324   }
   17325 }
   17326 
   17327 
   17328 static void NamedPropertyGetterWhichReturns42(
   17329     Local<String> name,
   17330     const v8::PropertyCallbackInfo<v8::Value>& info) {
   17331   info.GetReturnValue().Set(v8_num(42));
   17332 }
   17333 
   17334 
   17335 static void NamedPropertySetterWhichSetsYOnThisTo23(
   17336     Local<String> name,
   17337     Local<Value> value,
   17338     const v8::PropertyCallbackInfo<v8::Value>& info) {
   17339   if (name->Equals(v8_str("x"))) {
   17340     info.This()->Set(v8_str("y"), v8_num(23));
   17341   }
   17342 }
   17343 
   17344 
   17345 THREADED_TEST(InterceptorOnConstructorPrototype) {
   17346   v8::HandleScope scope(v8::Isolate::GetCurrent());
   17347   Local<ObjectTemplate> templ = ObjectTemplate::New();
   17348   templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
   17349                                  NamedPropertySetterWhichSetsYOnThisTo23);
   17350   LocalContext context;
   17351   context->Global()->Set(v8_str("P"), templ->NewInstance());
   17352   CompileRun("function C1() {"
   17353              "  this.x = 23;"
   17354              "};"
   17355              "C1.prototype = P;"
   17356              "function C2() {"
   17357              "  this.x = 23"
   17358              "};"
   17359              "C2.prototype = { };"
   17360              "C2.prototype.__proto__ = P;");
   17361 
   17362   v8::Local<v8::Script> script;
   17363   script = v8::Script::Compile(v8_str("new C1();"));
   17364   for (int i = 0; i < 10; i++) {
   17365     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   17366     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   17367     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   17368   }
   17369 
   17370   script = v8::Script::Compile(v8_str("new C2();"));
   17371   for (int i = 0; i < 10; i++) {
   17372     v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
   17373     CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
   17374     CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
   17375   }
   17376 }
   17377 
   17378 
   17379 TEST(Regress618) {
   17380   const char* source = "function C1() {"
   17381                        "  this.x = 23;"
   17382                        "};"
   17383                        "C1.prototype = P;";
   17384 
   17385   LocalContext context;
   17386   v8::HandleScope scope(context->GetIsolate());
   17387   v8::Local<v8::Script> script;
   17388 
   17389   // Use a simple object as prototype.
   17390   v8::Local<v8::Object> prototype = v8::Object::New();
   17391   prototype->Set(v8_str("y"), v8_num(42));
   17392   context->Global()->Set(v8_str("P"), prototype);
   17393 
   17394   // This compile will add the code to the compilation cache.
   17395   CompileRun(source);
   17396 
   17397   script = v8::Script::Compile(v8_str("new C1();"));
   17398   // Allow enough iterations for the inobject slack tracking logic
   17399   // to finalize instance size and install the fast construct stub.
   17400   for (int i = 0; i < 256; i++) {
   17401     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   17402     CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
   17403     CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
   17404   }
   17405 
   17406   // Use an API object with accessors as prototype.
   17407   Local<ObjectTemplate> templ = ObjectTemplate::New();
   17408   templ->SetAccessor(v8_str("x"),
   17409                      GetterWhichReturns42,
   17410                      SetterWhichSetsYOnThisTo23);
   17411   context->Global()->Set(v8_str("P"), templ->NewInstance());
   17412 
   17413   // This compile will get the code from the compilation cache.
   17414   CompileRun(source);
   17415 
   17416   script = v8::Script::Compile(v8_str("new C1();"));
   17417   for (int i = 0; i < 10; i++) {
   17418     v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
   17419     CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
   17420     CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
   17421   }
   17422 }
   17423 
   17424 int prologue_call_count = 0;
   17425 int epilogue_call_count = 0;
   17426 int prologue_call_count_second = 0;
   17427 int epilogue_call_count_second = 0;
   17428 
   17429 void PrologueCallback(v8::GCType, v8::GCCallbackFlags) {
   17430   ++prologue_call_count;
   17431 }
   17432 
   17433 
   17434 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags) {
   17435   ++epilogue_call_count;
   17436 }
   17437 
   17438 
   17439 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
   17440   ++prologue_call_count_second;
   17441 }
   17442 
   17443 
   17444 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
   17445   ++epilogue_call_count_second;
   17446 }
   17447 
   17448 
   17449 TEST(GCCallbacks) {
   17450   LocalContext context;
   17451 
   17452   v8::V8::AddGCPrologueCallback(PrologueCallback);
   17453   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
   17454   CHECK_EQ(0, prologue_call_count);
   17455   CHECK_EQ(0, epilogue_call_count);
   17456   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   17457   CHECK_EQ(1, prologue_call_count);
   17458   CHECK_EQ(1, epilogue_call_count);
   17459   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
   17460   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
   17461   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   17462   CHECK_EQ(2, prologue_call_count);
   17463   CHECK_EQ(2, epilogue_call_count);
   17464   CHECK_EQ(1, prologue_call_count_second);
   17465   CHECK_EQ(1, epilogue_call_count_second);
   17466   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
   17467   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
   17468   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   17469   CHECK_EQ(2, prologue_call_count);
   17470   CHECK_EQ(2, epilogue_call_count);
   17471   CHECK_EQ(2, prologue_call_count_second);
   17472   CHECK_EQ(2, epilogue_call_count_second);
   17473   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
   17474   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   17475   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   17476   CHECK_EQ(2, prologue_call_count);
   17477   CHECK_EQ(2, epilogue_call_count);
   17478   CHECK_EQ(2, prologue_call_count_second);
   17479   CHECK_EQ(2, epilogue_call_count_second);
   17480 }
   17481 
   17482 
   17483 THREADED_TEST(AddToJSFunctionResultCache) {
   17484   i::FLAG_stress_compaction = false;
   17485   i::FLAG_allow_natives_syntax = true;
   17486   v8::HandleScope scope(v8::Isolate::GetCurrent());
   17487 
   17488   LocalContext context;
   17489 
   17490   const char* code =
   17491       "(function() {"
   17492       "  var key0 = 'a';"
   17493       "  var key1 = 'b';"
   17494       "  var r0 = %_GetFromCache(0, key0);"
   17495       "  var r1 = %_GetFromCache(0, key1);"
   17496       "  var r0_ = %_GetFromCache(0, key0);"
   17497       "  if (r0 !== r0_)"
   17498       "    return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
   17499       "  var r1_ = %_GetFromCache(0, key1);"
   17500       "  if (r1 !== r1_)"
   17501       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
   17502       "  return 'PASSED';"
   17503       "})()";
   17504   HEAP->ClearJSFunctionResultCaches();
   17505   ExpectString(code, "PASSED");
   17506 }
   17507 
   17508 
   17509 static const int k0CacheSize = 16;
   17510 
   17511 THREADED_TEST(FillJSFunctionResultCache) {
   17512   i::FLAG_allow_natives_syntax = true;
   17513   LocalContext context;
   17514   v8::HandleScope scope(context->GetIsolate());
   17515 
   17516   const char* code =
   17517       "(function() {"
   17518       "  var k = 'a';"
   17519       "  var r = %_GetFromCache(0, k);"
   17520       "  for (var i = 0; i < 16; i++) {"
   17521       "    %_GetFromCache(0, 'a' + i);"
   17522       "  };"
   17523       "  if (r === %_GetFromCache(0, k))"
   17524       "    return 'FAILED: k0CacheSize is too small';"
   17525       "  return 'PASSED';"
   17526       "})()";
   17527   HEAP->ClearJSFunctionResultCaches();
   17528   ExpectString(code, "PASSED");
   17529 }
   17530 
   17531 
   17532 THREADED_TEST(RoundRobinGetFromCache) {
   17533   i::FLAG_allow_natives_syntax = true;
   17534   LocalContext context;
   17535   v8::HandleScope scope(context->GetIsolate());
   17536 
   17537   const char* code =
   17538       "(function() {"
   17539       "  var keys = [];"
   17540       "  for (var i = 0; i < 16; i++) keys.push(i);"
   17541       "  var values = [];"
   17542       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   17543       "  for (var i = 0; i < 16; i++) {"
   17544       "    var v = %_GetFromCache(0, keys[i]);"
   17545       "    if (v.toString() !== values[i].toString())"
   17546       "      return 'Wrong value for ' + "
   17547       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   17548       "  };"
   17549       "  return 'PASSED';"
   17550       "})()";
   17551   HEAP->ClearJSFunctionResultCaches();
   17552   ExpectString(code, "PASSED");
   17553 }
   17554 
   17555 
   17556 THREADED_TEST(ReverseGetFromCache) {
   17557   i::FLAG_allow_natives_syntax = true;
   17558   LocalContext context;
   17559   v8::HandleScope scope(context->GetIsolate());
   17560 
   17561   const char* code =
   17562       "(function() {"
   17563       "  var keys = [];"
   17564       "  for (var i = 0; i < 16; i++) keys.push(i);"
   17565       "  var values = [];"
   17566       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
   17567       "  for (var i = 15; i >= 16; i--) {"
   17568       "    var v = %_GetFromCache(0, keys[i]);"
   17569       "    if (v !== values[i])"
   17570       "      return 'Wrong value for ' + "
   17571       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
   17572       "  };"
   17573       "  return 'PASSED';"
   17574       "})()";
   17575   HEAP->ClearJSFunctionResultCaches();
   17576   ExpectString(code, "PASSED");
   17577 }
   17578 
   17579 
   17580 THREADED_TEST(TestEviction) {
   17581   i::FLAG_allow_natives_syntax = true;
   17582   LocalContext context;
   17583   v8::HandleScope scope(context->GetIsolate());
   17584 
   17585   const char* code =
   17586       "(function() {"
   17587       "  for (var i = 0; i < 2*16; i++) {"
   17588       "    %_GetFromCache(0, 'a' + i);"
   17589       "  };"
   17590       "  return 'PASSED';"
   17591       "})()";
   17592   HEAP->ClearJSFunctionResultCaches();
   17593   ExpectString(code, "PASSED");
   17594 }
   17595 
   17596 
   17597 THREADED_TEST(TwoByteStringInAsciiCons) {
   17598   // See Chromium issue 47824.
   17599   LocalContext context;
   17600   v8::HandleScope scope(context->GetIsolate());
   17601 
   17602   const char* init_code =
   17603       "var str1 = 'abelspendabel';"
   17604       "var str2 = str1 + str1 + str1;"
   17605       "str2;";
   17606   Local<Value> result = CompileRun(init_code);
   17607 
   17608   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   17609   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   17610 
   17611   CHECK(result->IsString());
   17612   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   17613   int length = string->length();
   17614   CHECK(string->IsOneByteRepresentation());
   17615 
   17616   FlattenString(string);
   17617   i::Handle<i::String> flat_string = FlattenGetString(string);
   17618 
   17619   CHECK(string->IsOneByteRepresentation());
   17620   CHECK(flat_string->IsOneByteRepresentation());
   17621 
   17622   // Create external resource.
   17623   uint16_t* uc16_buffer = new uint16_t[length + 1];
   17624 
   17625   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   17626   uc16_buffer[length] = 0;
   17627 
   17628   TestResource resource(uc16_buffer);
   17629 
   17630   flat_string->MakeExternal(&resource);
   17631 
   17632   CHECK(flat_string->IsTwoByteRepresentation());
   17633 
   17634   // If the cons string has been short-circuited, skip the following checks.
   17635   if (!string.is_identical_to(flat_string)) {
   17636     // At this point, we should have a Cons string which is flat and ASCII,
   17637     // with a first half that is a two-byte string (although it only contains
   17638     // ASCII characters). This is a valid sequence of steps, and it can happen
   17639     // in real pages.
   17640     CHECK(string->IsOneByteRepresentation());
   17641     i::ConsString* cons = i::ConsString::cast(*string);
   17642     CHECK_EQ(0, cons->second()->length());
   17643     CHECK(cons->first()->IsTwoByteRepresentation());
   17644   }
   17645 
   17646   // Check that some string operations work.
   17647 
   17648   // Atom RegExp.
   17649   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   17650   CHECK_EQ(6, reresult->Int32Value());
   17651 
   17652   // Nonatom RegExp.
   17653   reresult = CompileRun("str2.match(/abe./g).length;");
   17654   CHECK_EQ(6, reresult->Int32Value());
   17655 
   17656   reresult = CompileRun("str2.search(/bel/g);");
   17657   CHECK_EQ(1, reresult->Int32Value());
   17658 
   17659   reresult = CompileRun("str2.search(/be./g);");
   17660   CHECK_EQ(1, reresult->Int32Value());
   17661 
   17662   ExpectTrue("/bel/g.test(str2);");
   17663 
   17664   ExpectTrue("/be./g.test(str2);");
   17665 
   17666   reresult = CompileRun("/bel/g.exec(str2);");
   17667   CHECK(!reresult->IsNull());
   17668 
   17669   reresult = CompileRun("/be./g.exec(str2);");
   17670   CHECK(!reresult->IsNull());
   17671 
   17672   ExpectString("str2.substring(2, 10);", "elspenda");
   17673 
   17674   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   17675 
   17676   ExpectString("str2.charAt(2);", "e");
   17677 
   17678   ExpectObject("str2.indexOf('els');", indexof);
   17679 
   17680   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   17681 
   17682   reresult = CompileRun("str2.charCodeAt(2);");
   17683   CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
   17684 }
   17685 
   17686 
   17687 TEST(ContainsOnlyOneByte) {
   17688   v8::V8::Initialize();
   17689   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   17690   v8::HandleScope scope(isolate);
   17691   // Make a buffer long enough that it won't automatically be converted.
   17692   const int length = 512;
   17693   // Ensure word aligned assignment.
   17694   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
   17695   i::SmartArrayPointer<uintptr_t>
   17696   aligned_contents(new uintptr_t[aligned_length]);
   17697   uint16_t* string_contents = reinterpret_cast<uint16_t*>(*aligned_contents);
   17698   // Set to contain only one byte.
   17699   for (int i = 0; i < length-1; i++) {
   17700     string_contents[i] = 0x41;
   17701   }
   17702   string_contents[length-1] = 0;
   17703   // Simple case.
   17704   Handle<String> string;
   17705   string = String::NewExternal(new TestResource(string_contents));
   17706   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   17707   // Counter example.
   17708   string = String::NewFromTwoByte(isolate, string_contents);
   17709   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   17710   // Test left right and balanced cons strings.
   17711   Handle<String> base = String::NewFromUtf8(isolate, "a");
   17712   Handle<String> left = base;
   17713   Handle<String> right = base;
   17714   for (int i = 0; i < 1000; i++) {
   17715     left = String::Concat(base, left);
   17716     right = String::Concat(right, base);
   17717   }
   17718   Handle<String> balanced = String::Concat(left, base);
   17719   balanced = String::Concat(balanced, right);
   17720   Handle<String> cons_strings[] = {left, balanced, right};
   17721   Handle<String> two_byte =
   17722       String::NewExternal(new TestResource(string_contents));
   17723   for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
   17724     // Base assumptions.
   17725     string = cons_strings[i];
   17726     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   17727     // Test left and right concatentation.
   17728     string = String::Concat(two_byte, cons_strings[i]);
   17729     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   17730     string = String::Concat(cons_strings[i], two_byte);
   17731     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   17732   }
   17733   // Set bits in different positions
   17734   // for strings of different lengths and alignments.
   17735   for (int alignment = 0; alignment < 7; alignment++) {
   17736     for (int size = 2; alignment + size < length; size *= 2) {
   17737       int zero_offset = size + alignment;
   17738       string_contents[zero_offset] = 0;
   17739       for (int i = 0; i < size; i++) {
   17740         int shift = 8 + (i % 7);
   17741         string_contents[alignment + i] = 1 << shift;
   17742         string =
   17743             String::NewExternal(new TestResource(string_contents + alignment));
   17744         CHECK_EQ(size, string->Length());
   17745         CHECK(!string->ContainsOnlyOneByte());
   17746         string_contents[alignment + i] = 0x41;
   17747       }
   17748       string_contents[zero_offset] = 0x41;
   17749     }
   17750   }
   17751 }
   17752 
   17753 
   17754 // Failed access check callback that performs a GC on each invocation.
   17755 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   17756                                  v8::AccessType type,
   17757                                  Local<v8::Value> data) {
   17758   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   17759 }
   17760 
   17761 
   17762 TEST(GCInFailedAccessCheckCallback) {
   17763   // Install a failed access check callback that performs a GC on each
   17764   // invocation. Then force the callback to be called from va
   17765 
   17766   v8::V8::Initialize();
   17767   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   17768 
   17769   v8::HandleScope scope(v8::Isolate::GetCurrent());
   17770 
   17771   // Create an ObjectTemplate for global objects and install access
   17772   // check callbacks that will block access.
   17773   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   17774   global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
   17775                                            IndexedGetAccessBlocker,
   17776                                            v8::Handle<v8::Value>(),
   17777                                            false);
   17778 
   17779   // Create a context and set an x property on it's global object.
   17780   LocalContext context0(NULL, global_template);
   17781   context0->Global()->Set(v8_str("x"), v8_num(42));
   17782   v8::Handle<v8::Object> global0 = context0->Global();
   17783 
   17784   // Create a context with a different security token so that the
   17785   // failed access check callback will be called on each access.
   17786   LocalContext context1(NULL, global_template);
   17787   context1->Global()->Set(v8_str("other"), global0);
   17788 
   17789   // Get property with failed access check.
   17790   ExpectUndefined("other.x");
   17791 
   17792   // Get element with failed access check.
   17793   ExpectUndefined("other[0]");
   17794 
   17795   // Set property with failed access check.
   17796   v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
   17797   CHECK(result->IsObject());
   17798 
   17799   // Set element with failed access check.
   17800   result = CompileRun("other[0] = new Object()");
   17801   CHECK(result->IsObject());
   17802 
   17803   // Get property attribute with failed access check.
   17804   ExpectFalse("\'x\' in other");
   17805 
   17806   // Get property attribute for element with failed access check.
   17807   ExpectFalse("0 in other");
   17808 
   17809   // Delete property.
   17810   ExpectFalse("delete other.x");
   17811 
   17812   // Delete element.
   17813   CHECK_EQ(false, global0->Delete(0));
   17814 
   17815   // DefineAccessor.
   17816   CHECK_EQ(false,
   17817            global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
   17818 
   17819   // Define JavaScript accessor.
   17820   ExpectUndefined("Object.prototype.__defineGetter__.call("
   17821                   "    other, \'x\', function() { return 42; })");
   17822 
   17823   // LookupAccessor.
   17824   ExpectUndefined("Object.prototype.__lookupGetter__.call("
   17825                   "    other, \'x\')");
   17826 
   17827   // HasLocalElement.
   17828   ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
   17829 
   17830   CHECK_EQ(false, global0->HasRealIndexedProperty(0));
   17831   CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
   17832   CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
   17833 
   17834   // Reset the failed access check callback so it does not influence
   17835   // the other tests.
   17836   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
   17837 }
   17838 
   17839 
   17840 TEST(DefaultIsolateGetCurrent) {
   17841   CHECK(v8::Isolate::GetCurrent() != NULL);
   17842   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   17843   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   17844   printf("*** %s\n", "DefaultIsolateGetCurrent success");
   17845 }
   17846 
   17847 
   17848 TEST(IsolateNewDispose) {
   17849   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
   17850   v8::Isolate* isolate = v8::Isolate::New();
   17851   CHECK(isolate != NULL);
   17852   CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   17853   CHECK(current_isolate != isolate);
   17854   CHECK(current_isolate == v8::Isolate::GetCurrent());
   17855 
   17856   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   17857   last_location = last_message = NULL;
   17858   isolate->Dispose();
   17859   CHECK_EQ(last_location, NULL);
   17860   CHECK_EQ(last_message, NULL);
   17861 }
   17862 
   17863 
   17864 TEST(IsolateEnterExitDefault) {
   17865   v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
   17866   CHECK(current_isolate != NULL);  // Default isolate.
   17867   v8::HandleScope scope(current_isolate);
   17868   LocalContext context;
   17869   ExpectString("'hello'", "hello");
   17870   current_isolate->Enter();
   17871   ExpectString("'still working'", "still working");
   17872   current_isolate->Exit();
   17873   ExpectString("'still working 2'", "still working 2");
   17874   current_isolate->Exit();
   17875   // Default isolate is always, well, 'default current'.
   17876   CHECK_EQ(v8::Isolate::GetCurrent(), current_isolate);
   17877   // Still working since default isolate is auto-entering any thread
   17878   // that has no isolate and attempts to execute V8 APIs.
   17879   ExpectString("'still working 3'", "still working 3");
   17880 }
   17881 
   17882 
   17883 TEST(DisposeDefaultIsolate) {
   17884   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   17885 
   17886   // Run some V8 code to trigger default isolate to become 'current'.
   17887   v8::HandleScope scope(v8::Isolate::GetCurrent());
   17888   LocalContext context;
   17889   ExpectString("'run some V8'", "run some V8");
   17890 
   17891   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   17892   CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
   17893   last_location = last_message = NULL;
   17894   isolate->Dispose();
   17895   // It is not possible to dispose default isolate via Isolate API.
   17896   CHECK_NE(last_location, NULL);
   17897   CHECK_NE(last_message, NULL);
   17898 }
   17899 
   17900 
   17901 TEST(RunDefaultAndAnotherIsolate) {
   17902   v8::HandleScope scope(v8::Isolate::GetCurrent());
   17903   LocalContext context;
   17904 
   17905   // Enter new isolate.
   17906   v8::Isolate* isolate = v8::Isolate::New();
   17907   CHECK(isolate);
   17908   isolate->Enter();
   17909   { // Need this block because subsequent Exit() will deallocate Heap,
   17910     // so we need all scope objects to be deconstructed when it happens.
   17911     v8::HandleScope scope_new(isolate);
   17912     LocalContext context_new;
   17913 
   17914     // Run something in new isolate.
   17915     CompileRun("var foo = 153;");
   17916     ExpectTrue("function f() { return foo == 153; }; f()");
   17917   }
   17918   isolate->Exit();
   17919 
   17920   // This runs automatically in default isolate.
   17921   // Variables in another isolate should be not available.
   17922   ExpectTrue("function f() {"
   17923              "  try {"
   17924              "    foo;"
   17925              "    return false;"
   17926              "  } catch(e) {"
   17927              "    return true;"
   17928              "  }"
   17929              "};"
   17930              "var bar = 371;"
   17931              "f()");
   17932 
   17933   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   17934   last_location = last_message = NULL;
   17935   isolate->Dispose();
   17936   CHECK_EQ(last_location, NULL);
   17937   CHECK_EQ(last_message, NULL);
   17938 
   17939   // Check that default isolate still runs.
   17940   ExpectTrue("function f() { return bar == 371; }; f()");
   17941 }
   17942 
   17943 
   17944 TEST(DisposeIsolateWhenInUse) {
   17945   v8::Isolate* isolate = v8::Isolate::New();
   17946   CHECK(isolate);
   17947   isolate->Enter();
   17948   v8::HandleScope scope(isolate);
   17949   LocalContext context;
   17950   // Run something in this isolate.
   17951   ExpectTrue("true");
   17952   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   17953   last_location = last_message = NULL;
   17954   // Still entered, should fail.
   17955   isolate->Dispose();
   17956   CHECK_NE(last_location, NULL);
   17957   CHECK_NE(last_message, NULL);
   17958 }
   17959 
   17960 
   17961 TEST(RunTwoIsolatesOnSingleThread) {
   17962   // Run isolate 1.
   17963   v8::Isolate* isolate1 = v8::Isolate::New();
   17964   isolate1->Enter();
   17965   v8::Persistent<v8::Context> context1;
   17966   {
   17967     v8::HandleScope scope(isolate1);
   17968     context1.Reset(isolate1, Context::New(isolate1));
   17969   }
   17970 
   17971   {
   17972     v8::HandleScope scope(isolate1);
   17973     v8::Local<v8::Context> context =
   17974         v8::Local<v8::Context>::New(isolate1, context1);
   17975     v8::Context::Scope context_scope(context);
   17976     // Run something in new isolate.
   17977     CompileRun("var foo = 'isolate 1';");
   17978     ExpectString("function f() { return foo; }; f()", "isolate 1");
   17979   }
   17980 
   17981   // Run isolate 2.
   17982   v8::Isolate* isolate2 = v8::Isolate::New();
   17983   v8::Persistent<v8::Context> context2;
   17984 
   17985   {
   17986     v8::Isolate::Scope iscope(isolate2);
   17987     v8::HandleScope scope(isolate2);
   17988     context2.Reset(isolate2, Context::New(isolate2));
   17989     v8::Local<v8::Context> context =
   17990         v8::Local<v8::Context>::New(isolate2, context2);
   17991     v8::Context::Scope context_scope(context);
   17992 
   17993     // Run something in new isolate.
   17994     CompileRun("var foo = 'isolate 2';");
   17995     ExpectString("function f() { return foo; }; f()", "isolate 2");
   17996   }
   17997 
   17998   {
   17999     v8::HandleScope scope(isolate1);
   18000     v8::Local<v8::Context> context =
   18001         v8::Local<v8::Context>::New(isolate1, context1);
   18002     v8::Context::Scope context_scope(context);
   18003     // Now again in isolate 1
   18004     ExpectString("function f() { return foo; }; f()", "isolate 1");
   18005   }
   18006 
   18007   isolate1->Exit();
   18008 
   18009   // Run some stuff in default isolate.
   18010   v8::Persistent<v8::Context> context_default;
   18011   {
   18012     v8::Isolate* isolate = v8::Isolate::GetCurrent();
   18013     v8::Isolate::Scope iscope(isolate);
   18014     v8::HandleScope scope(isolate);
   18015     context_default.Reset(isolate, Context::New(isolate));
   18016   }
   18017 
   18018   {
   18019     v8::HandleScope scope(v8::Isolate::GetCurrent());
   18020     v8::Local<v8::Context> context =
   18021         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context_default);
   18022     v8::Context::Scope context_scope(context);
   18023     // Variables in other isolates should be not available, verify there
   18024     // is an exception.
   18025     ExpectTrue("function f() {"
   18026                "  try {"
   18027                "    foo;"
   18028                "    return false;"
   18029                "  } catch(e) {"
   18030                "    return true;"
   18031                "  }"
   18032                "};"
   18033                "var isDefaultIsolate = true;"
   18034                "f()");
   18035   }
   18036 
   18037   isolate1->Enter();
   18038 
   18039   {
   18040     v8::Isolate::Scope iscope(isolate2);
   18041     v8::HandleScope scope(v8::Isolate::GetCurrent());
   18042     v8::Local<v8::Context> context =
   18043         v8::Local<v8::Context>::New(isolate2, context2);
   18044     v8::Context::Scope context_scope(context);
   18045     ExpectString("function f() { return foo; }; f()", "isolate 2");
   18046   }
   18047 
   18048   {
   18049     v8::HandleScope scope(v8::Isolate::GetCurrent());
   18050     v8::Local<v8::Context> context =
   18051         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
   18052     v8::Context::Scope context_scope(context);
   18053     ExpectString("function f() { return foo; }; f()", "isolate 1");
   18054   }
   18055 
   18056   {
   18057     v8::Isolate::Scope iscope(isolate2);
   18058     context2.Dispose();
   18059   }
   18060 
   18061   context1.Dispose();
   18062   isolate1->Exit();
   18063 
   18064   v8::V8::SetFatalErrorHandler(StoringErrorCallback);
   18065   last_location = last_message = NULL;
   18066 
   18067   isolate1->Dispose();
   18068   CHECK_EQ(last_location, NULL);
   18069   CHECK_EQ(last_message, NULL);
   18070 
   18071   isolate2->Dispose();
   18072   CHECK_EQ(last_location, NULL);
   18073   CHECK_EQ(last_message, NULL);
   18074 
   18075   // Check that default isolate still runs.
   18076   {
   18077     v8::HandleScope scope(v8::Isolate::GetCurrent());
   18078     v8::Local<v8::Context> context =
   18079         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context_default);
   18080     v8::Context::Scope context_scope(context);
   18081     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   18082   }
   18083 }
   18084 
   18085 
   18086 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   18087   v8::Isolate::Scope isolate_scope(isolate);
   18088   v8::HandleScope scope(isolate);
   18089   LocalContext context;
   18090   i::ScopedVector<char> code(1024);
   18091   i::OS::SNPrintF(code, "function fib(n) {"
   18092                         "  if (n <= 2) return 1;"
   18093                         "  return fib(n-1) + fib(n-2);"
   18094                         "}"
   18095                         "fib(%d)", limit);
   18096   Local<Value> value = CompileRun(code.start());
   18097   CHECK(value->IsNumber());
   18098   return static_cast<int>(value->NumberValue());
   18099 }
   18100 
   18101 class IsolateThread : public v8::internal::Thread {
   18102  public:
   18103   IsolateThread(v8::Isolate* isolate, int fib_limit)
   18104       : Thread("IsolateThread"),
   18105         isolate_(isolate),
   18106         fib_limit_(fib_limit),
   18107         result_(0) { }
   18108 
   18109   void Run() {
   18110     result_ = CalcFibonacci(isolate_, fib_limit_);
   18111   }
   18112 
   18113   int result() { return result_; }
   18114 
   18115  private:
   18116   v8::Isolate* isolate_;
   18117   int fib_limit_;
   18118   int result_;
   18119 };
   18120 
   18121 
   18122 TEST(MultipleIsolatesOnIndividualThreads) {
   18123   v8::Isolate* isolate1 = v8::Isolate::New();
   18124   v8::Isolate* isolate2 = v8::Isolate::New();
   18125 
   18126   IsolateThread thread1(isolate1, 21);
   18127   IsolateThread thread2(isolate2, 12);
   18128 
   18129   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   18130   thread1.Start();
   18131   thread2.Start();
   18132 
   18133   int result1 = CalcFibonacci(v8::Isolate::GetCurrent(), 21);
   18134   int result2 = CalcFibonacci(v8::Isolate::GetCurrent(), 12);
   18135 
   18136   thread1.Join();
   18137   thread2.Join();
   18138 
   18139   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   18140   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   18141   CHECK_EQ(result1, 10946);
   18142   CHECK_EQ(result2, 144);
   18143   CHECK_EQ(result1, thread1.result());
   18144   CHECK_EQ(result2, thread2.result());
   18145 
   18146   isolate1->Dispose();
   18147   isolate2->Dispose();
   18148 }
   18149 
   18150 
   18151 TEST(IsolateDifferentContexts) {
   18152   v8::Isolate* isolate = v8::Isolate::New();
   18153   Local<v8::Context> context;
   18154   {
   18155     v8::Isolate::Scope isolate_scope(isolate);
   18156     v8::HandleScope handle_scope(isolate);
   18157     context = v8::Context::New(isolate);
   18158     v8::Context::Scope context_scope(context);
   18159     Local<Value> v = CompileRun("2");
   18160     CHECK(v->IsNumber());
   18161     CHECK_EQ(2, static_cast<int>(v->NumberValue()));
   18162   }
   18163   {
   18164     v8::Isolate::Scope isolate_scope(isolate);
   18165     v8::HandleScope handle_scope(isolate);
   18166     context = v8::Context::New(isolate);
   18167     v8::Context::Scope context_scope(context);
   18168     Local<Value> v = CompileRun("22");
   18169     CHECK(v->IsNumber());
   18170     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
   18171   }
   18172 }
   18173 
   18174 class InitDefaultIsolateThread : public v8::internal::Thread {
   18175  public:
   18176   enum TestCase {
   18177     IgnoreOOM,
   18178     SetResourceConstraints,
   18179     SetFatalHandler,
   18180     SetCounterFunction,
   18181     SetCreateHistogramFunction,
   18182     SetAddHistogramSampleFunction
   18183   };
   18184 
   18185   explicit InitDefaultIsolateThread(TestCase testCase)
   18186       : Thread("InitDefaultIsolateThread"),
   18187         testCase_(testCase),
   18188         result_(false) { }
   18189 
   18190   void Run() {
   18191     switch (testCase_) {
   18192     case IgnoreOOM:
   18193       v8::V8::IgnoreOutOfMemoryException();
   18194       break;
   18195 
   18196     case SetResourceConstraints: {
   18197       static const int K = 1024;
   18198       v8::ResourceConstraints constraints;
   18199       constraints.set_max_young_space_size(256 * K);
   18200       constraints.set_max_old_space_size(4 * K * K);
   18201       v8::SetResourceConstraints(&constraints);
   18202       break;
   18203     }
   18204 
   18205     case SetFatalHandler:
   18206       v8::V8::SetFatalErrorHandler(NULL);
   18207       break;
   18208 
   18209     case SetCounterFunction:
   18210       v8::V8::SetCounterFunction(NULL);
   18211       break;
   18212 
   18213     case SetCreateHistogramFunction:
   18214       v8::V8::SetCreateHistogramFunction(NULL);
   18215       break;
   18216 
   18217     case SetAddHistogramSampleFunction:
   18218       v8::V8::SetAddHistogramSampleFunction(NULL);
   18219       break;
   18220     }
   18221     result_ = true;
   18222   }
   18223 
   18224   bool result() { return result_; }
   18225 
   18226  private:
   18227   TestCase testCase_;
   18228   bool result_;
   18229 };
   18230 
   18231 
   18232 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   18233   InitDefaultIsolateThread thread(testCase);
   18234   thread.Start();
   18235   thread.Join();
   18236   CHECK_EQ(thread.result(), true);
   18237 }
   18238 
   18239 
   18240 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
   18241   InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
   18242 }
   18243 
   18244 
   18245 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
   18246   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
   18247 }
   18248 
   18249 
   18250 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
   18251   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   18252 }
   18253 
   18254 
   18255 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
   18256   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   18257 }
   18258 
   18259 
   18260 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
   18261   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   18262 }
   18263 
   18264 
   18265 TEST(InitializeDefaultIsolateOnSecondaryThread6) {
   18266   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   18267 }
   18268 
   18269 
   18270 TEST(StringCheckMultipleContexts) {
   18271   const char* code =
   18272       "(function() { return \"a\".charAt(0); })()";
   18273 
   18274   {
   18275     // Run the code twice in the first context to initialize the call IC.
   18276     LocalContext context1;
   18277     v8::HandleScope scope(context1->GetIsolate());
   18278     ExpectString(code, "a");
   18279     ExpectString(code, "a");
   18280   }
   18281 
   18282   {
   18283     // Change the String.prototype in the second context and check
   18284     // that the right function gets called.
   18285     LocalContext context2;
   18286     v8::HandleScope scope(context2->GetIsolate());
   18287     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   18288     ExpectString(code, "not a");
   18289   }
   18290 }
   18291 
   18292 
   18293 TEST(NumberCheckMultipleContexts) {
   18294   const char* code =
   18295       "(function() { return (42).toString(); })()";
   18296 
   18297   {
   18298     // Run the code twice in the first context to initialize the call IC.
   18299     LocalContext context1;
   18300     v8::HandleScope scope(context1->GetIsolate());
   18301     ExpectString(code, "42");
   18302     ExpectString(code, "42");
   18303   }
   18304 
   18305   {
   18306     // Change the Number.prototype in the second context and check
   18307     // that the right function gets called.
   18308     LocalContext context2;
   18309     v8::HandleScope scope(context2->GetIsolate());
   18310     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   18311     ExpectString(code, "not 42");
   18312   }
   18313 }
   18314 
   18315 
   18316 TEST(BooleanCheckMultipleContexts) {
   18317   const char* code =
   18318       "(function() { return true.toString(); })()";
   18319 
   18320   {
   18321     // Run the code twice in the first context to initialize the call IC.
   18322     LocalContext context1;
   18323     v8::HandleScope scope(context1->GetIsolate());
   18324     ExpectString(code, "true");
   18325     ExpectString(code, "true");
   18326   }
   18327 
   18328   {
   18329     // Change the Boolean.prototype in the second context and check
   18330     // that the right function gets called.
   18331     LocalContext context2;
   18332     v8::HandleScope scope(context2->GetIsolate());
   18333     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   18334     ExpectString(code, "");
   18335   }
   18336 }
   18337 
   18338 
   18339 TEST(DontDeleteCellLoadIC) {
   18340   const char* function_code =
   18341       "function readCell() { while (true) { return cell; } }";
   18342 
   18343   {
   18344     // Run the code twice in the first context to initialize the load
   18345     // IC for a don't delete cell.
   18346     LocalContext context1;
   18347     v8::HandleScope scope(context1->GetIsolate());
   18348     CompileRun("var cell = \"first\";");
   18349     ExpectBoolean("delete cell", false);
   18350     CompileRun(function_code);
   18351     ExpectString("readCell()", "first");
   18352     ExpectString("readCell()", "first");
   18353   }
   18354 
   18355   {
   18356     // Use a deletable cell in the second context.
   18357     LocalContext context2;
   18358     v8::HandleScope scope(context2->GetIsolate());
   18359     CompileRun("cell = \"second\";");
   18360     CompileRun(function_code);
   18361     ExpectString("readCell()", "second");
   18362     ExpectBoolean("delete cell", true);
   18363     ExpectString("(function() {"
   18364                  "  try {"
   18365                  "    return readCell();"
   18366                  "  } catch(e) {"
   18367                  "    return e.toString();"
   18368                  "  }"
   18369                  "})()",
   18370                  "ReferenceError: cell is not defined");
   18371     CompileRun("cell = \"new_second\";");
   18372     HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   18373     ExpectString("readCell()", "new_second");
   18374     ExpectString("readCell()", "new_second");
   18375   }
   18376 }
   18377 
   18378 
   18379 TEST(DontDeleteCellLoadICForceDelete) {
   18380   const char* function_code =
   18381       "function readCell() { while (true) { return cell; } }";
   18382 
   18383   // Run the code twice to initialize the load IC for a don't delete
   18384   // cell.
   18385   LocalContext context;
   18386   v8::HandleScope scope(context->GetIsolate());
   18387   CompileRun("var cell = \"value\";");
   18388   ExpectBoolean("delete cell", false);
   18389   CompileRun(function_code);
   18390   ExpectString("readCell()", "value");
   18391   ExpectString("readCell()", "value");
   18392 
   18393   // Delete the cell using the API and check the inlined code works
   18394   // correctly.
   18395   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   18396   ExpectString("(function() {"
   18397                "  try {"
   18398                "    return readCell();"
   18399                "  } catch(e) {"
   18400                "    return e.toString();"
   18401                "  }"
   18402                "})()",
   18403                "ReferenceError: cell is not defined");
   18404 }
   18405 
   18406 
   18407 TEST(DontDeleteCellLoadICAPI) {
   18408   const char* function_code =
   18409       "function readCell() { while (true) { return cell; } }";
   18410 
   18411   // Run the code twice to initialize the load IC for a don't delete
   18412   // cell created using the API.
   18413   LocalContext context;
   18414   v8::HandleScope scope(context->GetIsolate());
   18415   context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
   18416   ExpectBoolean("delete cell", false);
   18417   CompileRun(function_code);
   18418   ExpectString("readCell()", "value");
   18419   ExpectString("readCell()", "value");
   18420 
   18421   // Delete the cell using the API and check the inlined code works
   18422   // correctly.
   18423   CHECK(context->Global()->ForceDelete(v8_str("cell")));
   18424   ExpectString("(function() {"
   18425                "  try {"
   18426                "    return readCell();"
   18427                "  } catch(e) {"
   18428                "    return e.toString();"
   18429                "  }"
   18430                "})()",
   18431                "ReferenceError: cell is not defined");
   18432 }
   18433 
   18434 
   18435 class Visitor42 : public v8::PersistentHandleVisitor {
   18436  public:
   18437   explicit Visitor42(v8::Persistent<v8::Object>* object)
   18438       : counter_(0), object_(object) { }
   18439 
   18440   virtual void VisitPersistentHandle(Persistent<Value>* value,
   18441                                      uint16_t class_id) {
   18442     if (class_id != 42) return;
   18443     CHECK_EQ(42, value->WrapperClassId());
   18444     v8::Isolate* isolate = v8::Isolate::GetCurrent();
   18445     v8::HandleScope handle_scope(isolate);
   18446     v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
   18447     v8::Handle<v8::Value> object =
   18448         v8::Local<v8::Object>::New(isolate, *object_);
   18449     CHECK(handle->IsObject());
   18450     CHECK_EQ(Handle<Object>::Cast(handle), object);
   18451     ++counter_;
   18452   }
   18453 
   18454   int counter_;
   18455   v8::Persistent<v8::Object>* object_;
   18456 };
   18457 
   18458 
   18459 TEST(PersistentHandleVisitor) {
   18460   LocalContext context;
   18461   v8::Isolate* isolate = context->GetIsolate();
   18462   v8::HandleScope scope(isolate);
   18463   v8::Persistent<v8::Object> object(isolate, v8::Object::New());
   18464   CHECK_EQ(0, object.WrapperClassId(isolate));
   18465   object.SetWrapperClassId(isolate, 42);
   18466   CHECK_EQ(42, object.WrapperClassId(isolate));
   18467 
   18468   Visitor42 visitor(&object);
   18469   v8::V8::VisitHandlesWithClassIds(&visitor);
   18470   CHECK_EQ(1, visitor.counter_);
   18471 
   18472   object.Dispose(isolate);
   18473 }
   18474 
   18475 
   18476 TEST(WrapperClassId) {
   18477   LocalContext context;
   18478   v8::Isolate* isolate = context->GetIsolate();
   18479   v8::HandleScope scope(isolate);
   18480   v8::Persistent<v8::Object> object(isolate, v8::Object::New());
   18481   CHECK_EQ(0, object.WrapperClassId(isolate));
   18482   object.SetWrapperClassId(isolate, 65535);
   18483   CHECK_EQ(65535, object.WrapperClassId(isolate));
   18484   object.Dispose(isolate);
   18485 }
   18486 
   18487 
   18488 TEST(PersistentHandleInNewSpaceVisitor) {
   18489   LocalContext context;
   18490   v8::Isolate* isolate = context->GetIsolate();
   18491   v8::HandleScope scope(isolate);
   18492   v8::Persistent<v8::Object> object1(isolate, v8::Object::New());
   18493   CHECK_EQ(0, object1.WrapperClassId(isolate));
   18494   object1.SetWrapperClassId(isolate, 42);
   18495   CHECK_EQ(42, object1.WrapperClassId(isolate));
   18496 
   18497   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   18498 
   18499   v8::Persistent<v8::Object> object2(isolate, v8::Object::New());
   18500   CHECK_EQ(0, object2.WrapperClassId(isolate));
   18501   object2.SetWrapperClassId(isolate, 42);
   18502   CHECK_EQ(42, object2.WrapperClassId(isolate));
   18503 
   18504   Visitor42 visitor(&object2);
   18505   v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
   18506   CHECK_EQ(1, visitor.counter_);
   18507 
   18508   object1.Dispose(isolate);
   18509   object2.Dispose(isolate);
   18510 }
   18511 
   18512 
   18513 TEST(RegExp) {
   18514   LocalContext context;
   18515   v8::HandleScope scope(context->GetIsolate());
   18516 
   18517   v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
   18518   CHECK(re->IsRegExp());
   18519   CHECK(re->GetSource()->Equals(v8_str("foo")));
   18520   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   18521 
   18522   re = v8::RegExp::New(v8_str("bar"),
   18523                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   18524                                                       v8::RegExp::kGlobal));
   18525   CHECK(re->IsRegExp());
   18526   CHECK(re->GetSource()->Equals(v8_str("bar")));
   18527   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   18528            static_cast<int>(re->GetFlags()));
   18529 
   18530   re = v8::RegExp::New(v8_str("baz"),
   18531                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   18532                                                       v8::RegExp::kMultiline));
   18533   CHECK(re->IsRegExp());
   18534   CHECK(re->GetSource()->Equals(v8_str("baz")));
   18535   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   18536            static_cast<int>(re->GetFlags()));
   18537 
   18538   re = CompileRun("/quux/").As<v8::RegExp>();
   18539   CHECK(re->IsRegExp());
   18540   CHECK(re->GetSource()->Equals(v8_str("quux")));
   18541   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   18542 
   18543   re = CompileRun("/quux/gm").As<v8::RegExp>();
   18544   CHECK(re->IsRegExp());
   18545   CHECK(re->GetSource()->Equals(v8_str("quux")));
   18546   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   18547            static_cast<int>(re->GetFlags()));
   18548 
   18549   // Override the RegExp constructor and check the API constructor
   18550   // still works.
   18551   CompileRun("RegExp = function() {}");
   18552 
   18553   re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
   18554   CHECK(re->IsRegExp());
   18555   CHECK(re->GetSource()->Equals(v8_str("foobar")));
   18556   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   18557 
   18558   re = v8::RegExp::New(v8_str("foobarbaz"),
   18559                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   18560                                                       v8::RegExp::kMultiline));
   18561   CHECK(re->IsRegExp());
   18562   CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
   18563   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   18564            static_cast<int>(re->GetFlags()));
   18565 
   18566   context->Global()->Set(v8_str("re"), re);
   18567   ExpectTrue("re.test('FoobarbaZ')");
   18568 
   18569   // RegExps are objects on which you can set properties.
   18570   re->Set(v8_str("property"), v8::Integer::New(32));
   18571   v8::Handle<v8::Value> value(CompileRun("re.property"));
   18572   CHECK_EQ(32, value->Int32Value());
   18573 
   18574   v8::TryCatch try_catch;
   18575   re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
   18576   CHECK(re.IsEmpty());
   18577   CHECK(try_catch.HasCaught());
   18578   context->Global()->Set(v8_str("ex"), try_catch.Exception());
   18579   ExpectTrue("ex instanceof SyntaxError");
   18580 }
   18581 
   18582 
   18583 THREADED_TEST(Equals) {
   18584   LocalContext localContext;
   18585   v8::HandleScope handleScope(localContext->GetIsolate());
   18586 
   18587   v8::Handle<v8::Object> globalProxy = localContext->Global();
   18588   v8::Handle<Value> global = globalProxy->GetPrototype();
   18589 
   18590   CHECK(global->StrictEquals(global));
   18591   CHECK(!global->StrictEquals(globalProxy));
   18592   CHECK(!globalProxy->StrictEquals(global));
   18593   CHECK(globalProxy->StrictEquals(globalProxy));
   18594 
   18595   CHECK(global->Equals(global));
   18596   CHECK(!global->Equals(globalProxy));
   18597   CHECK(!globalProxy->Equals(global));
   18598   CHECK(globalProxy->Equals(globalProxy));
   18599 }
   18600 
   18601 
   18602 static void Getter(v8::Local<v8::String> property,
   18603                    const v8::PropertyCallbackInfo<v8::Value>& info ) {
   18604   info.GetReturnValue().Set(v8_str("42!"));
   18605 }
   18606 
   18607 
   18608 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
   18609   v8::Handle<v8::Array> result = v8::Array::New();
   18610   result->Set(0, v8_str("universalAnswer"));
   18611   info.GetReturnValue().Set(result);
   18612 }
   18613 
   18614 
   18615 TEST(NamedEnumeratorAndForIn) {
   18616   LocalContext context;
   18617   v8::HandleScope handle_scope(context->GetIsolate());
   18618   v8::Context::Scope context_scope(context.local());
   18619 
   18620   v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New();
   18621   tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
   18622   context->Global()->Set(v8_str("o"), tmpl->NewInstance());
   18623   v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
   18624         "var result = []; for (var k in o) result.push(k); result"));
   18625   CHECK_EQ(1, result->Length());
   18626   CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
   18627 }
   18628 
   18629 
   18630 TEST(DefinePropertyPostDetach) {
   18631   LocalContext context;
   18632   v8::HandleScope scope(context->GetIsolate());
   18633   v8::Handle<v8::Object> proxy = context->Global();
   18634   v8::Handle<v8::Function> define_property =
   18635       CompileRun("(function() {"
   18636                  "  Object.defineProperty("
   18637                  "    this,"
   18638                  "    1,"
   18639                  "    { configurable: true, enumerable: true, value: 3 });"
   18640                  "})").As<Function>();
   18641   context->DetachGlobal();
   18642   define_property->Call(proxy, 0, NULL);
   18643 }
   18644 
   18645 
   18646 static void InstallContextId(v8::Handle<Context> context, int id) {
   18647   Context::Scope scope(context);
   18648   CompileRun("Object.prototype").As<Object>()->
   18649       Set(v8_str("context_id"), v8::Integer::New(id));
   18650 }
   18651 
   18652 
   18653 static void CheckContextId(v8::Handle<Object> object, int expected) {
   18654   CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
   18655 }
   18656 
   18657 
   18658 THREADED_TEST(CreationContext) {
   18659   HandleScope handle_scope(v8::Isolate::GetCurrent());
   18660   Handle<Context> context1 = Context::New(v8::Isolate::GetCurrent());
   18661   InstallContextId(context1, 1);
   18662   Handle<Context> context2 = Context::New(v8::Isolate::GetCurrent());
   18663   InstallContextId(context2, 2);
   18664   Handle<Context> context3 = Context::New(v8::Isolate::GetCurrent());
   18665   InstallContextId(context3, 3);
   18666 
   18667   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
   18668 
   18669   Local<Object> object1;
   18670   Local<Function> func1;
   18671   {
   18672     Context::Scope scope(context1);
   18673     object1 = Object::New();
   18674     func1 = tmpl->GetFunction();
   18675   }
   18676 
   18677   Local<Object> object2;
   18678   Local<Function> func2;
   18679   {
   18680     Context::Scope scope(context2);
   18681     object2 = Object::New();
   18682     func2 = tmpl->GetFunction();
   18683   }
   18684 
   18685   Local<Object> instance1;
   18686   Local<Object> instance2;
   18687 
   18688   {
   18689     Context::Scope scope(context3);
   18690     instance1 = func1->NewInstance();
   18691     instance2 = func2->NewInstance();
   18692   }
   18693 
   18694   CHECK(object1->CreationContext() == context1);
   18695   CheckContextId(object1, 1);
   18696   CHECK(func1->CreationContext() == context1);
   18697   CheckContextId(func1, 1);
   18698   CHECK(instance1->CreationContext() == context1);
   18699   CheckContextId(instance1, 1);
   18700   CHECK(object2->CreationContext() == context2);
   18701   CheckContextId(object2, 2);
   18702   CHECK(func2->CreationContext() == context2);
   18703   CheckContextId(func2, 2);
   18704   CHECK(instance2->CreationContext() == context2);
   18705   CheckContextId(instance2, 2);
   18706 
   18707   {
   18708     Context::Scope scope(context1);
   18709     CHECK(object1->CreationContext() == context1);
   18710     CheckContextId(object1, 1);
   18711     CHECK(func1->CreationContext() == context1);
   18712     CheckContextId(func1, 1);
   18713     CHECK(instance1->CreationContext() == context1);
   18714     CheckContextId(instance1, 1);
   18715     CHECK(object2->CreationContext() == context2);
   18716     CheckContextId(object2, 2);
   18717     CHECK(func2->CreationContext() == context2);
   18718     CheckContextId(func2, 2);
   18719     CHECK(instance2->CreationContext() == context2);
   18720     CheckContextId(instance2, 2);
   18721   }
   18722 
   18723   {
   18724     Context::Scope scope(context2);
   18725     CHECK(object1->CreationContext() == context1);
   18726     CheckContextId(object1, 1);
   18727     CHECK(func1->CreationContext() == context1);
   18728     CheckContextId(func1, 1);
   18729     CHECK(instance1->CreationContext() == context1);
   18730     CheckContextId(instance1, 1);
   18731     CHECK(object2->CreationContext() == context2);
   18732     CheckContextId(object2, 2);
   18733     CHECK(func2->CreationContext() == context2);
   18734     CheckContextId(func2, 2);
   18735     CHECK(instance2->CreationContext() == context2);
   18736     CheckContextId(instance2, 2);
   18737   }
   18738 }
   18739 
   18740 
   18741 THREADED_TEST(CreationContextOfJsFunction) {
   18742   HandleScope handle_scope(v8::Isolate::GetCurrent());
   18743   Handle<Context> context = Context::New(v8::Isolate::GetCurrent());
   18744   InstallContextId(context, 1);
   18745 
   18746   Local<Object> function;
   18747   {
   18748     Context::Scope scope(context);
   18749     function = CompileRun("function foo() {}; foo").As<Object>();
   18750   }
   18751 
   18752   CHECK(function->CreationContext() == context);
   18753   CheckContextId(function, 1);
   18754 }
   18755 
   18756 
   18757 void HasOwnPropertyIndexedPropertyGetter(
   18758     uint32_t index,
   18759     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18760   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
   18761 }
   18762 
   18763 
   18764 void HasOwnPropertyNamedPropertyGetter(
   18765     Local<String> property,
   18766     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18767   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
   18768 }
   18769 
   18770 
   18771 void HasOwnPropertyIndexedPropertyQuery(
   18772     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   18773   if (index == 42) info.GetReturnValue().Set(1);
   18774 }
   18775 
   18776 
   18777 void HasOwnPropertyNamedPropertyQuery(
   18778     Local<String> property,
   18779     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   18780   if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
   18781 }
   18782 
   18783 
   18784 void HasOwnPropertyNamedPropertyQuery2(
   18785     Local<String> property,
   18786     const v8::PropertyCallbackInfo<v8::Integer>& info) {
   18787   if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
   18788 }
   18789 
   18790 
   18791 void HasOwnPropertyAccessorGetter(
   18792     Local<String> property,
   18793     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18794   info.GetReturnValue().Set(v8_str("yes"));
   18795 }
   18796 
   18797 
   18798 TEST(HasOwnProperty) {
   18799   LocalContext env;
   18800   v8::HandleScope scope(env->GetIsolate());
   18801   { // Check normal properties and defined getters.
   18802     Handle<Value> value = CompileRun(
   18803         "function Foo() {"
   18804         "    this.foo = 11;"
   18805         "    this.__defineGetter__('baz', function() { return 1; });"
   18806         "};"
   18807         "function Bar() { "
   18808         "    this.bar = 13;"
   18809         "    this.__defineGetter__('bla', function() { return 2; });"
   18810         "};"
   18811         "Bar.prototype = new Foo();"
   18812         "new Bar();");
   18813     CHECK(value->IsObject());
   18814     Handle<Object> object = value->ToObject();
   18815     CHECK(object->Has(v8_str("foo")));
   18816     CHECK(!object->HasOwnProperty(v8_str("foo")));
   18817     CHECK(object->HasOwnProperty(v8_str("bar")));
   18818     CHECK(object->Has(v8_str("baz")));
   18819     CHECK(!object->HasOwnProperty(v8_str("baz")));
   18820     CHECK(object->HasOwnProperty(v8_str("bla")));
   18821   }
   18822   { // Check named getter interceptors.
   18823     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   18824     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
   18825     Handle<Object> instance = templ->NewInstance();
   18826     CHECK(!instance->HasOwnProperty(v8_str("42")));
   18827     CHECK(instance->HasOwnProperty(v8_str("foo")));
   18828     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   18829   }
   18830   { // Check indexed getter interceptors.
   18831     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   18832     templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
   18833     Handle<Object> instance = templ->NewInstance();
   18834     CHECK(instance->HasOwnProperty(v8_str("42")));
   18835     CHECK(!instance->HasOwnProperty(v8_str("43")));
   18836     CHECK(!instance->HasOwnProperty(v8_str("foo")));
   18837   }
   18838   { // Check named query interceptors.
   18839     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   18840     templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
   18841     Handle<Object> instance = templ->NewInstance();
   18842     CHECK(instance->HasOwnProperty(v8_str("foo")));
   18843     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   18844   }
   18845   { // Check indexed query interceptors.
   18846     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   18847     templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
   18848     Handle<Object> instance = templ->NewInstance();
   18849     CHECK(instance->HasOwnProperty(v8_str("42")));
   18850     CHECK(!instance->HasOwnProperty(v8_str("41")));
   18851   }
   18852   { // Check callbacks.
   18853     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   18854     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   18855     Handle<Object> instance = templ->NewInstance();
   18856     CHECK(instance->HasOwnProperty(v8_str("foo")));
   18857     CHECK(!instance->HasOwnProperty(v8_str("bar")));
   18858   }
   18859   { // Check that query wins on disagreement.
   18860     Handle<ObjectTemplate> templ = ObjectTemplate::New();
   18861     templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
   18862                                    0,
   18863                                    HasOwnPropertyNamedPropertyQuery2);
   18864     Handle<Object> instance = templ->NewInstance();
   18865     CHECK(!instance->HasOwnProperty(v8_str("foo")));
   18866     CHECK(instance->HasOwnProperty(v8_str("bar")));
   18867   }
   18868 }
   18869 
   18870 
   18871 TEST(IndexedInterceptorWithStringProto) {
   18872   v8::HandleScope scope(v8::Isolate::GetCurrent());
   18873   Handle<ObjectTemplate> templ = ObjectTemplate::New();
   18874   templ->SetIndexedPropertyHandler(NULL,
   18875                                    NULL,
   18876                                    HasOwnPropertyIndexedPropertyQuery);
   18877   LocalContext context;
   18878   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   18879   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
   18880   // These should be intercepted.
   18881   CHECK(CompileRun("42 in obj")->BooleanValue());
   18882   CHECK(CompileRun("'42' in obj")->BooleanValue());
   18883   // These should fall through to the String prototype.
   18884   CHECK(CompileRun("0 in obj")->BooleanValue());
   18885   CHECK(CompileRun("'0' in obj")->BooleanValue());
   18886   // And these should both fail.
   18887   CHECK(!CompileRun("32 in obj")->BooleanValue());
   18888   CHECK(!CompileRun("'32' in obj")->BooleanValue());
   18889 }
   18890 
   18891 
   18892 void CheckCodeGenerationAllowed() {
   18893   Handle<Value> result = CompileRun("eval('42')");
   18894   CHECK_EQ(42, result->Int32Value());
   18895   result = CompileRun("(function(e) { return e('42'); })(eval)");
   18896   CHECK_EQ(42, result->Int32Value());
   18897   result = CompileRun("var f = new Function('return 42'); f()");
   18898   CHECK_EQ(42, result->Int32Value());
   18899 }
   18900 
   18901 
   18902 void CheckCodeGenerationDisallowed() {
   18903   TryCatch try_catch;
   18904 
   18905   Handle<Value> result = CompileRun("eval('42')");
   18906   CHECK(result.IsEmpty());
   18907   CHECK(try_catch.HasCaught());
   18908   try_catch.Reset();
   18909 
   18910   result = CompileRun("(function(e) { return e('42'); })(eval)");
   18911   CHECK(result.IsEmpty());
   18912   CHECK(try_catch.HasCaught());
   18913   try_catch.Reset();
   18914 
   18915   result = CompileRun("var f = new Function('return 42'); f()");
   18916   CHECK(result.IsEmpty());
   18917   CHECK(try_catch.HasCaught());
   18918 }
   18919 
   18920 
   18921 bool CodeGenerationAllowed(Local<Context> context) {
   18922   ApiTestFuzzer::Fuzz();
   18923   return true;
   18924 }
   18925 
   18926 
   18927 bool CodeGenerationDisallowed(Local<Context> context) {
   18928   ApiTestFuzzer::Fuzz();
   18929   return false;
   18930 }
   18931 
   18932 
   18933 THREADED_TEST(AllowCodeGenFromStrings) {
   18934   LocalContext context;
   18935   v8::HandleScope scope(context->GetIsolate());
   18936 
   18937   // eval and the Function constructor allowed by default.
   18938   CHECK(context->IsCodeGenerationFromStringsAllowed());
   18939   CheckCodeGenerationAllowed();
   18940 
   18941   // Disallow eval and the Function constructor.
   18942   context->AllowCodeGenerationFromStrings(false);
   18943   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   18944   CheckCodeGenerationDisallowed();
   18945 
   18946   // Allow again.
   18947   context->AllowCodeGenerationFromStrings(true);
   18948   CheckCodeGenerationAllowed();
   18949 
   18950   // Disallow but setting a global callback that will allow the calls.
   18951   context->AllowCodeGenerationFromStrings(false);
   18952   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
   18953   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   18954   CheckCodeGenerationAllowed();
   18955 
   18956   // Set a callback that disallows the code generation.
   18957   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
   18958   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   18959   CheckCodeGenerationDisallowed();
   18960 }
   18961 
   18962 
   18963 TEST(SetErrorMessageForCodeGenFromStrings) {
   18964   LocalContext context;
   18965   v8::HandleScope scope(context->GetIsolate());
   18966   TryCatch try_catch;
   18967 
   18968   Handle<String> message = v8_str("Message") ;
   18969   Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
   18970   V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
   18971   context->AllowCodeGenerationFromStrings(false);
   18972   context->SetErrorMessageForCodeGenerationFromStrings(message);
   18973   Handle<Value> result = CompileRun("eval('42')");
   18974   CHECK(result.IsEmpty());
   18975   CHECK(try_catch.HasCaught());
   18976   Handle<String> actual_message = try_catch.Message()->Get();
   18977   CHECK(expected_message->Equals(actual_message));
   18978 }
   18979 
   18980 
   18981 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   18982 }
   18983 
   18984 
   18985 THREADED_TEST(CallAPIFunctionOnNonObject) {
   18986   LocalContext context;
   18987   v8::HandleScope scope(context->GetIsolate());
   18988   Handle<FunctionTemplate> templ = v8::FunctionTemplate::New(NonObjectThis);
   18989   Handle<Function> function = templ->GetFunction();
   18990   context->Global()->Set(v8_str("f"), function);
   18991   TryCatch try_catch;
   18992   CompileRun("f.call(2)");
   18993 }
   18994 
   18995 
   18996 // Regression test for issue 1470.
   18997 THREADED_TEST(ReadOnlyIndexedProperties) {
   18998   v8::HandleScope scope(v8::Isolate::GetCurrent());
   18999   Local<ObjectTemplate> templ = ObjectTemplate::New();
   19000 
   19001   LocalContext context;
   19002   Local<v8::Object> obj = templ->NewInstance();
   19003   context->Global()->Set(v8_str("obj"), obj);
   19004   obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
   19005   obj->Set(v8_str("1"), v8_str("foobar"));
   19006   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
   19007   obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
   19008   obj->Set(v8_num(2), v8_str("foobar"));
   19009   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
   19010 
   19011   // Test non-smi case.
   19012   obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
   19013   obj->Set(v8_str("2000000000"), v8_str("foobar"));
   19014   CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
   19015 }
   19016 
   19017 
   19018 THREADED_TEST(Regress1516) {
   19019   LocalContext context;
   19020   v8::HandleScope scope(context->GetIsolate());
   19021 
   19022   { v8::HandleScope temp_scope(context->GetIsolate());
   19023     CompileRun("({'a': 0})");
   19024   }
   19025 
   19026   int elements;
   19027   { i::MapCache* map_cache =
   19028         i::MapCache::cast(i::Isolate::Current()->context()->map_cache());
   19029     elements = map_cache->NumberOfElements();
   19030     CHECK_LE(1, elements);
   19031   }
   19032 
   19033   i::Isolate::Current()->heap()->CollectAllGarbage(
   19034       i::Heap::kAbortIncrementalMarkingMask);
   19035   { i::Object* raw_map_cache = i::Isolate::Current()->context()->map_cache();
   19036     if (raw_map_cache != i::Isolate::Current()->heap()->undefined_value()) {
   19037       i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
   19038       CHECK_GT(elements, map_cache->NumberOfElements());
   19039     }
   19040   }
   19041 }
   19042 
   19043 
   19044 static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
   19045                                                 Local<Value> name,
   19046                                                 v8::AccessType type,
   19047                                                 Local<Value> data) {
   19048   // Only block read access to __proto__.
   19049   if (type == v8::ACCESS_GET &&
   19050       name->IsString() &&
   19051       name->ToString()->Length() == 9 &&
   19052       name->ToString()->Utf8Length() == 9) {
   19053     char buffer[10];
   19054     CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
   19055     return strncmp(buffer, "__proto__", 9) != 0;
   19056   }
   19057 
   19058   return true;
   19059 }
   19060 
   19061 
   19062 THREADED_TEST(Regress93759) {
   19063   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   19064   HandleScope scope(isolate);
   19065 
   19066   // Template for object with security check.
   19067   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New();
   19068   // We don't do indexing, so any callback can be used for that.
   19069   no_proto_template->SetAccessCheckCallbacks(
   19070       BlockProtoNamedSecurityTestCallback,
   19071       IndexedSecurityTestCallback);
   19072 
   19073   // Templates for objects with hidden prototypes and possibly security check.
   19074   Local<FunctionTemplate> hidden_proto_template = v8::FunctionTemplate::New();
   19075   hidden_proto_template->SetHiddenPrototype(true);
   19076 
   19077   Local<FunctionTemplate> protected_hidden_proto_template =
   19078       v8::FunctionTemplate::New();
   19079   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
   19080       BlockProtoNamedSecurityTestCallback,
   19081       IndexedSecurityTestCallback);
   19082   protected_hidden_proto_template->SetHiddenPrototype(true);
   19083 
   19084   // Context for "foreign" objects used in test.
   19085   Local<Context> context = v8::Context::New(isolate);
   19086   context->Enter();
   19087 
   19088   // Plain object, no security check.
   19089   Local<Object> simple_object = Object::New();
   19090 
   19091   // Object with explicit security check.
   19092   Local<Object> protected_object =
   19093       no_proto_template->NewInstance();
   19094 
   19095   // JSGlobalProxy object, always have security check.
   19096   Local<Object> proxy_object =
   19097       context->Global();
   19098 
   19099   // Global object, the  prototype of proxy_object. No security checks.
   19100   Local<Object> global_object =
   19101       proxy_object->GetPrototype()->ToObject();
   19102 
   19103   // Hidden prototype without security check.
   19104   Local<Object> hidden_prototype =
   19105       hidden_proto_template->GetFunction()->NewInstance();
   19106   Local<Object> object_with_hidden =
   19107     Object::New();
   19108   object_with_hidden->SetPrototype(hidden_prototype);
   19109 
   19110   // Hidden prototype with security check on the hidden prototype.
   19111   Local<Object> protected_hidden_prototype =
   19112       protected_hidden_proto_template->GetFunction()->NewInstance();
   19113   Local<Object> object_with_protected_hidden =
   19114     Object::New();
   19115   object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
   19116 
   19117   context->Exit();
   19118 
   19119   // Template for object for second context. Values to test are put on it as
   19120   // properties.
   19121   Local<ObjectTemplate> global_template = ObjectTemplate::New();
   19122   global_template->Set(v8_str("simple"), simple_object);
   19123   global_template->Set(v8_str("protected"), protected_object);
   19124   global_template->Set(v8_str("global"), global_object);
   19125   global_template->Set(v8_str("proxy"), proxy_object);
   19126   global_template->Set(v8_str("hidden"), object_with_hidden);
   19127   global_template->Set(v8_str("phidden"), object_with_protected_hidden);
   19128 
   19129   LocalContext context2(NULL, global_template);
   19130 
   19131   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
   19132   CHECK(result1->Equals(simple_object->GetPrototype()));
   19133 
   19134   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
   19135   CHECK(result2->Equals(Undefined()));
   19136 
   19137   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
   19138   CHECK(result3->Equals(global_object->GetPrototype()));
   19139 
   19140   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
   19141   CHECK(result4->Equals(Undefined()));
   19142 
   19143   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
   19144   CHECK(result5->Equals(
   19145       object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
   19146 
   19147   Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
   19148   CHECK(result6->Equals(Undefined()));
   19149 }
   19150 
   19151 
   19152 THREADED_TEST(Regress125988) {
   19153   v8::HandleScope scope(v8::Isolate::GetCurrent());
   19154   Handle<FunctionTemplate> intercept = FunctionTemplate::New();
   19155   AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
   19156   LocalContext env;
   19157   env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
   19158   CompileRun("var a = new Object();"
   19159              "var b = new Intercept();"
   19160              "var c = new Object();"
   19161              "c.__proto__ = b;"
   19162              "b.__proto__ = a;"
   19163              "a.x = 23;"
   19164              "for (var i = 0; i < 3; i++) c.x;");
   19165   ExpectBoolean("c.hasOwnProperty('x')", false);
   19166   ExpectInt32("c.x", 23);
   19167   CompileRun("a.y = 42;"
   19168              "for (var i = 0; i < 3; i++) c.x;");
   19169   ExpectBoolean("c.hasOwnProperty('x')", false);
   19170   ExpectInt32("c.x", 23);
   19171   ExpectBoolean("c.hasOwnProperty('y')", false);
   19172   ExpectInt32("c.y", 42);
   19173 }
   19174 
   19175 
   19176 static void TestReceiver(Local<Value> expected_result,
   19177                          Local<Value> expected_receiver,
   19178                          const char* code) {
   19179   Local<Value> result = CompileRun(code);
   19180   CHECK(result->IsObject());
   19181   CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
   19182   CHECK(expected_result->Equals(result->ToObject()->Get(0)));
   19183 }
   19184 
   19185 
   19186 THREADED_TEST(ForeignFunctionReceiver) {
   19187   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   19188   HandleScope scope(isolate);
   19189 
   19190   // Create two contexts with different "id" properties ('i' and 'o').
   19191   // Call a function both from its own context and from a the foreign
   19192   // context, and see what "this" is bound to (returning both "this"
   19193   // and "this.id" for comparison).
   19194 
   19195   Local<Context> foreign_context = v8::Context::New(isolate);
   19196   foreign_context->Enter();
   19197   Local<Value> foreign_function =
   19198     CompileRun("function func() { return { 0: this.id, "
   19199                "                           1: this, "
   19200                "                           toString: function() { "
   19201                "                               return this[0];"
   19202                "                           }"
   19203                "                         };"
   19204                "}"
   19205                "var id = 'i';"
   19206                "func;");
   19207   CHECK(foreign_function->IsFunction());
   19208   foreign_context->Exit();
   19209 
   19210   LocalContext context;
   19211 
   19212   Local<String> password = v8_str("Password");
   19213   // Don't get hit by security checks when accessing foreign_context's
   19214   // global receiver (aka. global proxy).
   19215   context->SetSecurityToken(password);
   19216   foreign_context->SetSecurityToken(password);
   19217 
   19218   Local<String> i = v8_str("i");
   19219   Local<String> o = v8_str("o");
   19220   Local<String> id = v8_str("id");
   19221 
   19222   CompileRun("function ownfunc() { return { 0: this.id, "
   19223              "                              1: this, "
   19224              "                              toString: function() { "
   19225              "                                  return this[0];"
   19226              "                              }"
   19227              "                             };"
   19228              "}"
   19229              "var id = 'o';"
   19230              "ownfunc");
   19231   context->Global()->Set(v8_str("func"), foreign_function);
   19232 
   19233   // Sanity check the contexts.
   19234   CHECK(i->Equals(foreign_context->Global()->Get(id)));
   19235   CHECK(o->Equals(context->Global()->Get(id)));
   19236 
   19237   // Checking local function's receiver.
   19238   // Calling function using its call/apply methods.
   19239   TestReceiver(o, context->Global(), "ownfunc.call()");
   19240   TestReceiver(o, context->Global(), "ownfunc.apply()");
   19241   // Making calls through built-in functions.
   19242   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   19243   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
   19244   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
   19245   CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
   19246   // Calling with environment record as base.
   19247   TestReceiver(o, context->Global(), "ownfunc()");
   19248   // Calling with no base.
   19249   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   19250 
   19251   // Checking foreign function return value.
   19252   // Calling function using its call/apply methods.
   19253   TestReceiver(i, foreign_context->Global(), "func.call()");
   19254   TestReceiver(i, foreign_context->Global(), "func.apply()");
   19255   // Calling function using another context's call/apply methods.
   19256   TestReceiver(i, foreign_context->Global(),
   19257                "Function.prototype.call.call(func)");
   19258   TestReceiver(i, foreign_context->Global(),
   19259                "Function.prototype.call.apply(func)");
   19260   TestReceiver(i, foreign_context->Global(),
   19261                "Function.prototype.apply.call(func)");
   19262   TestReceiver(i, foreign_context->Global(),
   19263                "Function.prototype.apply.apply(func)");
   19264   // Making calls through built-in functions.
   19265   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   19266   // ToString(func()) is func()[0], i.e., the returned this.id.
   19267   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
   19268   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
   19269   CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
   19270 
   19271   // TODO(1547): Make the following also return "i".
   19272   // Calling with environment record as base.
   19273   TestReceiver(o, context->Global(), "func()");
   19274   // Calling with no base.
   19275   TestReceiver(o, context->Global(), "(1,func)()");
   19276 }
   19277 
   19278 
   19279 uint8_t callback_fired = 0;
   19280 
   19281 
   19282 void CallCompletedCallback1() {
   19283   i::OS::Print("Firing callback 1.\n");
   19284   callback_fired ^= 1;  // Toggle first bit.
   19285 }
   19286 
   19287 
   19288 void CallCompletedCallback2() {
   19289   i::OS::Print("Firing callback 2.\n");
   19290   callback_fired ^= 2;  // Toggle second bit.
   19291 }
   19292 
   19293 
   19294 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   19295   int32_t level = args[0]->Int32Value();
   19296   if (level < 3) {
   19297     level++;
   19298     i::OS::Print("Entering recursion level %d.\n", level);
   19299     char script[64];
   19300     i::Vector<char> script_vector(script, sizeof(script));
   19301     i::OS::SNPrintF(script_vector, "recursion(%d)", level);
   19302     CompileRun(script_vector.start());
   19303     i::OS::Print("Leaving recursion level %d.\n", level);
   19304     CHECK_EQ(0, callback_fired);
   19305   } else {
   19306     i::OS::Print("Recursion ends.\n");
   19307     CHECK_EQ(0, callback_fired);
   19308   }
   19309 }
   19310 
   19311 
   19312 TEST(CallCompletedCallback) {
   19313   LocalContext env;
   19314   v8::HandleScope scope(env->GetIsolate());
   19315   v8::Handle<v8::FunctionTemplate> recursive_runtime =
   19316       v8::FunctionTemplate::New(RecursiveCall);
   19317   env->Global()->Set(v8_str("recursion"),
   19318                      recursive_runtime->GetFunction());
   19319   // Adding the same callback a second time has no effect.
   19320   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
   19321   v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
   19322   v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
   19323   i::OS::Print("--- Script (1) ---\n");
   19324   Local<Script> script =
   19325       v8::Script::Compile(v8::String::New("recursion(0)"));
   19326   script->Run();
   19327   CHECK_EQ(3, callback_fired);
   19328 
   19329   i::OS::Print("\n--- Script (2) ---\n");
   19330   callback_fired = 0;
   19331   v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
   19332   script->Run();
   19333   CHECK_EQ(2, callback_fired);
   19334 
   19335   i::OS::Print("\n--- Function ---\n");
   19336   callback_fired = 0;
   19337   Local<Function> recursive_function =
   19338       Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
   19339   v8::Handle<Value> args[] = { v8_num(0) };
   19340   recursive_function->Call(env->Global(), 1, args);
   19341   CHECK_EQ(2, callback_fired);
   19342 }
   19343 
   19344 
   19345 void CallCompletedCallbackNoException() {
   19346   v8::HandleScope scope(v8::Isolate::GetCurrent());
   19347   CompileRun("1+1;");
   19348 }
   19349 
   19350 
   19351 void CallCompletedCallbackException() {
   19352   v8::HandleScope scope(v8::Isolate::GetCurrent());
   19353   CompileRun("throw 'second exception';");
   19354 }
   19355 
   19356 
   19357 TEST(CallCompletedCallbackOneException) {
   19358   LocalContext env;
   19359   v8::HandleScope scope(env->GetIsolate());
   19360   v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
   19361   CompileRun("throw 'exception';");
   19362 }
   19363 
   19364 
   19365 TEST(CallCompletedCallbackTwoExceptions) {
   19366   LocalContext env;
   19367   v8::HandleScope scope(env->GetIsolate());
   19368   v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
   19369   CompileRun("throw 'first exception';");
   19370 }
   19371 
   19372 
   19373 static int probes_counter = 0;
   19374 static int misses_counter = 0;
   19375 static int updates_counter = 0;
   19376 
   19377 
   19378 static int* LookupCounter(const char* name) {
   19379   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
   19380     return &probes_counter;
   19381   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
   19382     return &misses_counter;
   19383   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
   19384     return &updates_counter;
   19385   }
   19386   return NULL;
   19387 }
   19388 
   19389 
   19390 static const char* kMegamorphicTestProgram =
   19391     "function ClassA() { };"
   19392     "function ClassB() { };"
   19393     "ClassA.prototype.foo = function() { };"
   19394     "ClassB.prototype.foo = function() { };"
   19395     "function fooify(obj) { obj.foo(); };"
   19396     "var a = new ClassA();"
   19397     "var b = new ClassB();"
   19398     "for (var i = 0; i < 10000; i++) {"
   19399     "  fooify(a);"
   19400     "  fooify(b);"
   19401     "}";
   19402 
   19403 
   19404 static void StubCacheHelper(bool primary) {
   19405   V8::SetCounterFunction(LookupCounter);
   19406   USE(kMegamorphicTestProgram);
   19407 #ifdef DEBUG
   19408   i::FLAG_native_code_counters = true;
   19409   if (primary) {
   19410     i::FLAG_test_primary_stub_cache = true;
   19411   } else {
   19412     i::FLAG_test_secondary_stub_cache = true;
   19413   }
   19414   i::FLAG_crankshaft = false;
   19415   LocalContext env;
   19416   v8::HandleScope scope(env->GetIsolate());
   19417   int initial_probes = probes_counter;
   19418   int initial_misses = misses_counter;
   19419   int initial_updates = updates_counter;
   19420   CompileRun(kMegamorphicTestProgram);
   19421   int probes = probes_counter - initial_probes;
   19422   int misses = misses_counter - initial_misses;
   19423   int updates = updates_counter - initial_updates;
   19424   CHECK_LT(updates, 10);
   19425   CHECK_LT(misses, 10);
   19426   CHECK_GE(probes, 10000);
   19427 #endif
   19428 }
   19429 
   19430 
   19431 TEST(SecondaryStubCache) {
   19432   StubCacheHelper(true);
   19433 }
   19434 
   19435 
   19436 TEST(PrimaryStubCache) {
   19437   StubCacheHelper(false);
   19438 }
   19439 
   19440 
   19441 TEST(StaticGetters) {
   19442   LocalContext context;
   19443   i::Factory* factory = i::Isolate::Current()->factory();
   19444   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   19445   v8::HandleScope scope(isolate);
   19446   i::Handle<i::Object> undefined_value = factory->undefined_value();
   19447   CHECK(*v8::Utils::OpenHandle(*v8::Undefined()) == *undefined_value);
   19448   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
   19449   i::Handle<i::Object> null_value = factory->null_value();
   19450   CHECK(*v8::Utils::OpenHandle(*v8::Null()) == *null_value);
   19451   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
   19452   i::Handle<i::Object> true_value = factory->true_value();
   19453   CHECK(*v8::Utils::OpenHandle(*v8::True()) == *true_value);
   19454   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
   19455   i::Handle<i::Object> false_value = factory->false_value();
   19456   CHECK(*v8::Utils::OpenHandle(*v8::False()) == *false_value);
   19457   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
   19458 }
   19459 
   19460 
   19461 TEST(IsolateEmbedderData) {
   19462   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   19463   CHECK_EQ(NULL, isolate->GetData());
   19464   CHECK_EQ(NULL, ISOLATE->GetData());
   19465   static void* data1 = reinterpret_cast<void*>(0xacce55ed);
   19466   isolate->SetData(data1);
   19467   CHECK_EQ(data1, isolate->GetData());
   19468   CHECK_EQ(data1, ISOLATE->GetData());
   19469   static void* data2 = reinterpret_cast<void*>(0xdecea5ed);
   19470   ISOLATE->SetData(data2);
   19471   CHECK_EQ(data2, isolate->GetData());
   19472   CHECK_EQ(data2, ISOLATE->GetData());
   19473   ISOLATE->TearDown();
   19474   CHECK_EQ(data2, isolate->GetData());
   19475   CHECK_EQ(data2, ISOLATE->GetData());
   19476 }
   19477 
   19478 
   19479 TEST(StringEmpty) {
   19480   LocalContext context;
   19481   i::Factory* factory = i::Isolate::Current()->factory();
   19482   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   19483   v8::HandleScope scope(isolate);
   19484   i::Handle<i::Object> empty_string = factory->empty_string();
   19485   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty()) == *empty_string);
   19486   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
   19487 }
   19488 
   19489 
   19490 static int instance_checked_getter_count = 0;
   19491 static void InstanceCheckedGetter(
   19492     Local<String> name,
   19493     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19494   CHECK_EQ(name, v8_str("foo"));
   19495   instance_checked_getter_count++;
   19496   info.GetReturnValue().Set(v8_num(11));
   19497 }
   19498 
   19499 
   19500 static int instance_checked_setter_count = 0;
   19501 static void InstanceCheckedSetter(Local<String> name,
   19502                       Local<Value> value,
   19503                       const v8::PropertyCallbackInfo<void>& info) {
   19504   CHECK_EQ(name, v8_str("foo"));
   19505   CHECK_EQ(value, v8_num(23));
   19506   instance_checked_setter_count++;
   19507 }
   19508 
   19509 
   19510 static void CheckInstanceCheckedResult(int getters,
   19511                                        int setters,
   19512                                        bool expects_callbacks,
   19513                                        TryCatch* try_catch) {
   19514   if (expects_callbacks) {
   19515     CHECK(!try_catch->HasCaught());
   19516     CHECK_EQ(getters, instance_checked_getter_count);
   19517     CHECK_EQ(setters, instance_checked_setter_count);
   19518   } else {
   19519     CHECK(try_catch->HasCaught());
   19520     CHECK_EQ(0, instance_checked_getter_count);
   19521     CHECK_EQ(0, instance_checked_setter_count);
   19522   }
   19523   try_catch->Reset();
   19524 }
   19525 
   19526 
   19527 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
   19528   instance_checked_getter_count = 0;
   19529   instance_checked_setter_count = 0;
   19530   TryCatch try_catch;
   19531 
   19532   // Test path through generic runtime code.
   19533   CompileRun("obj.foo");
   19534   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
   19535   CompileRun("obj.foo = 23");
   19536   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
   19537 
   19538   // Test path through generated LoadIC and StoredIC.
   19539   CompileRun("function test_get(o) { o.foo; }"
   19540              "test_get(obj);");
   19541   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
   19542   CompileRun("test_get(obj);");
   19543   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
   19544   CompileRun("test_get(obj);");
   19545   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
   19546   CompileRun("function test_set(o) { o.foo = 23; }"
   19547              "test_set(obj);");
   19548   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
   19549   CompileRun("test_set(obj);");
   19550   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
   19551   CompileRun("test_set(obj);");
   19552   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
   19553 
   19554   // Test path through optimized code.
   19555   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
   19556              "test_get(obj);");
   19557   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
   19558   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
   19559              "test_set(obj);");
   19560   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
   19561 
   19562   // Cleanup so that closures start out fresh in next check.
   19563   CompileRun("%DeoptimizeFunction(test_get);"
   19564              "%ClearFunctionTypeFeedback(test_get);"
   19565              "%DeoptimizeFunction(test_set);"
   19566              "%ClearFunctionTypeFeedback(test_set);");
   19567 }
   19568 
   19569 
   19570 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
   19571   v8::internal::FLAG_allow_natives_syntax = true;
   19572   LocalContext context;
   19573   v8::HandleScope scope(context->GetIsolate());
   19574 
   19575   Local<FunctionTemplate> templ = FunctionTemplate::New();
   19576   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   19577   inst->SetAccessor(v8_str("foo"),
   19578                     InstanceCheckedGetter, InstanceCheckedSetter,
   19579                     Handle<Value>(),
   19580                     v8::DEFAULT,
   19581                     v8::None,
   19582                     v8::AccessorSignature::New(templ));
   19583   context->Global()->Set(v8_str("f"), templ->GetFunction());
   19584 
   19585   printf("Testing positive ...\n");
   19586   CompileRun("var obj = new f();");
   19587   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   19588   CheckInstanceCheckedAccessors(true);
   19589 
   19590   printf("Testing negative ...\n");
   19591   CompileRun("var obj = {};"
   19592              "obj.__proto__ = new f();");
   19593   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   19594   CheckInstanceCheckedAccessors(false);
   19595 }
   19596 
   19597 
   19598 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
   19599   v8::internal::FLAG_allow_natives_syntax = true;
   19600   LocalContext context;
   19601   v8::HandleScope scope(context->GetIsolate());
   19602 
   19603   Local<FunctionTemplate> templ = FunctionTemplate::New();
   19604   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   19605   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   19606   inst->SetAccessor(v8_str("foo"),
   19607                     InstanceCheckedGetter, InstanceCheckedSetter,
   19608                     Handle<Value>(),
   19609                     v8::DEFAULT,
   19610                     v8::None,
   19611                     v8::AccessorSignature::New(templ));
   19612   context->Global()->Set(v8_str("f"), templ->GetFunction());
   19613 
   19614   printf("Testing positive ...\n");
   19615   CompileRun("var obj = new f();");
   19616   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   19617   CheckInstanceCheckedAccessors(true);
   19618 
   19619   printf("Testing negative ...\n");
   19620   CompileRun("var obj = {};"
   19621              "obj.__proto__ = new f();");
   19622   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   19623   CheckInstanceCheckedAccessors(false);
   19624 }
   19625 
   19626 
   19627 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
   19628   v8::internal::FLAG_allow_natives_syntax = true;
   19629   LocalContext context;
   19630   v8::HandleScope scope(context->GetIsolate());
   19631 
   19632   Local<FunctionTemplate> templ = FunctionTemplate::New();
   19633   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
   19634   proto->SetAccessor(v8_str("foo"),
   19635                      InstanceCheckedGetter, InstanceCheckedSetter,
   19636                      Handle<Value>(),
   19637                      v8::DEFAULT,
   19638                      v8::None,
   19639                      v8::AccessorSignature::New(templ));
   19640   context->Global()->Set(v8_str("f"), templ->GetFunction());
   19641 
   19642   printf("Testing positive ...\n");
   19643   CompileRun("var obj = new f();");
   19644   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   19645   CheckInstanceCheckedAccessors(true);
   19646 
   19647   printf("Testing negative ...\n");
   19648   CompileRun("var obj = {};"
   19649              "obj.__proto__ = new f();");
   19650   CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   19651   CheckInstanceCheckedAccessors(false);
   19652 
   19653   printf("Testing positive with modified prototype chain ...\n");
   19654   CompileRun("var obj = new f();"
   19655              "var pro = {};"
   19656              "pro.__proto__ = obj.__proto__;"
   19657              "obj.__proto__ = pro;");
   19658   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   19659   CheckInstanceCheckedAccessors(true);
   19660 }
   19661 
   19662 
   19663 TEST(TryFinallyMessage) {
   19664   LocalContext context;
   19665   v8::HandleScope scope(context->GetIsolate());
   19666   {
   19667     // Test that the original error message is not lost if there is a
   19668     // recursive call into Javascript is done in the finally block, e.g. to
   19669     // initialize an IC. (crbug.com/129171)
   19670     TryCatch try_catch;
   19671     const char* trigger_ic =
   19672         "try {                      \n"
   19673         "  throw new Error('test'); \n"
   19674         "} finally {                \n"
   19675         "  var x = 0;               \n"
   19676         "  x++;                     \n"  // Trigger an IC initialization here.
   19677         "}                          \n";
   19678     CompileRun(trigger_ic);
   19679     CHECK(try_catch.HasCaught());
   19680     Local<Message> message = try_catch.Message();
   19681     CHECK(!message.IsEmpty());
   19682     CHECK_EQ(2, message->GetLineNumber());
   19683   }
   19684 
   19685   {
   19686     // Test that the original exception message is indeed overwritten if
   19687     // a new error is thrown in the finally block.
   19688     TryCatch try_catch;
   19689     const char* throw_again =
   19690         "try {                       \n"
   19691         "  throw new Error('test');  \n"
   19692         "} finally {                 \n"
   19693         "  var x = 0;                \n"
   19694         "  x++;                      \n"
   19695         "  throw new Error('again'); \n"  // This is the new uncaught error.
   19696         "}                           \n";
   19697     CompileRun(throw_again);
   19698     CHECK(try_catch.HasCaught());
   19699     Local<Message> message = try_catch.Message();
   19700     CHECK(!message.IsEmpty());
   19701     CHECK_EQ(6, message->GetLineNumber());
   19702   }
   19703 }
   19704 
   19705 
   19706 static void Helper137002(bool do_store,
   19707                          bool polymorphic,
   19708                          bool remove_accessor,
   19709                          bool interceptor) {
   19710   LocalContext context;
   19711   Local<ObjectTemplate> templ = ObjectTemplate::New();
   19712   if (interceptor) {
   19713     templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
   19714   } else {
   19715     templ->SetAccessor(v8_str("foo"),
   19716                        GetterWhichReturns42,
   19717                        SetterWhichSetsYOnThisTo23);
   19718   }
   19719   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   19720 
   19721   // Turn monomorphic on slow object with native accessor, then turn
   19722   // polymorphic, finally optimize to create negative lookup and fail.
   19723   CompileRun(do_store ?
   19724              "function f(x) { x.foo = void 0; }" :
   19725              "function f(x) { return x.foo; }");
   19726   CompileRun("obj.y = void 0;");
   19727   if (!interceptor) {
   19728     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
   19729   }
   19730   CompileRun("obj.__proto__ = null;"
   19731              "f(obj); f(obj); f(obj);");
   19732   if (polymorphic) {
   19733     CompileRun("f({});");
   19734   }
   19735   CompileRun("obj.y = void 0;"
   19736              "%OptimizeFunctionOnNextCall(f);");
   19737   if (remove_accessor) {
   19738     CompileRun("delete obj.foo;");
   19739   }
   19740   CompileRun("var result = f(obj);");
   19741   if (do_store) {
   19742     CompileRun("result = obj.y;");
   19743   }
   19744   if (remove_accessor && !interceptor) {
   19745     CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
   19746   } else {
   19747     CHECK_EQ(do_store ? 23 : 42,
   19748              context->Global()->Get(v8_str("result"))->Int32Value());
   19749   }
   19750 }
   19751 
   19752 
   19753 THREADED_TEST(Regress137002a) {
   19754   i::FLAG_allow_natives_syntax = true;
   19755   i::FLAG_compilation_cache = false;
   19756   v8::HandleScope scope(v8::Isolate::GetCurrent());
   19757   for (int i = 0; i < 16; i++) {
   19758     Helper137002(i & 8, i & 4, i & 2, i & 1);
   19759   }
   19760 }
   19761 
   19762 
   19763 THREADED_TEST(Regress137002b) {
   19764   i::FLAG_allow_natives_syntax = true;
   19765   LocalContext context;
   19766   v8::HandleScope scope(context->GetIsolate());
   19767   Local<ObjectTemplate> templ = ObjectTemplate::New();
   19768   templ->SetAccessor(v8_str("foo"),
   19769                      GetterWhichReturns42,
   19770                      SetterWhichSetsYOnThisTo23);
   19771   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   19772 
   19773   // Turn monomorphic on slow object with native accessor, then just
   19774   // delete the property and fail.
   19775   CompileRun("function load(x) { return x.foo; }"
   19776              "function store(x) { x.foo = void 0; }"
   19777              "function keyed_load(x, key) { return x[key]; }"
   19778              // Second version of function has a different source (add void 0)
   19779              // so that it does not share code with the first version.  This
   19780              // ensures that the ICs are monomorphic.
   19781              "function load2(x) { void 0; return x.foo; }"
   19782              "function store2(x) { void 0; x.foo = void 0; }"
   19783              "function keyed_load2(x, key) { void 0; return x[key]; }"
   19784 
   19785              "obj.y = void 0;"
   19786              "obj.__proto__ = null;"
   19787              "var subobj = {};"
   19788              "subobj.y = void 0;"
   19789              "subobj.__proto__ = obj;"
   19790              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   19791 
   19792              // Make the ICs monomorphic.
   19793              "load(obj); load(obj);"
   19794              "load2(subobj); load2(subobj);"
   19795              "store(obj); store(obj);"
   19796              "store2(subobj); store2(subobj);"
   19797              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
   19798              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
   19799 
   19800              // Actually test the shiny new ICs and better not crash. This
   19801              // serves as a regression test for issue 142088 as well.
   19802              "load(obj);"
   19803              "load2(subobj);"
   19804              "store(obj);"
   19805              "store2(subobj);"
   19806              "keyed_load(obj, 'foo');"
   19807              "keyed_load2(subobj, 'foo');"
   19808 
   19809              // Delete the accessor.  It better not be called any more now.
   19810              "delete obj.foo;"
   19811              "obj.y = void 0;"
   19812              "subobj.y = void 0;"
   19813 
   19814              "var load_result = load(obj);"
   19815              "var load_result2 = load2(subobj);"
   19816              "var keyed_load_result = keyed_load(obj, 'foo');"
   19817              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
   19818              "store(obj);"
   19819              "store2(subobj);"
   19820              "var y_from_obj = obj.y;"
   19821              "var y_from_subobj = subobj.y;");
   19822   CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
   19823   CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
   19824   CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
   19825   CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
   19826   CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
   19827   CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
   19828 }
   19829 
   19830 
   19831 THREADED_TEST(Regress142088) {
   19832   i::FLAG_allow_natives_syntax = true;
   19833   LocalContext context;
   19834   v8::HandleScope scope(context->GetIsolate());
   19835   Local<ObjectTemplate> templ = ObjectTemplate::New();
   19836   templ->SetAccessor(v8_str("foo"),
   19837                      GetterWhichReturns42,
   19838                      SetterWhichSetsYOnThisTo23);
   19839   context->Global()->Set(v8_str("obj"), templ->NewInstance());
   19840 
   19841   CompileRun("function load(x) { return x.foo; }"
   19842              "var o = Object.create(obj);"
   19843              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   19844              "load(o); load(o); load(o); load(o);");
   19845 }
   19846 
   19847 
   19848 THREADED_TEST(Regress137496) {
   19849   i::FLAG_expose_gc = true;
   19850   LocalContext context;
   19851   v8::HandleScope scope(context->GetIsolate());
   19852 
   19853   // Compile a try-finally clause where the finally block causes a GC
   19854   // while there still is a message pending for external reporting.
   19855   TryCatch try_catch;
   19856   try_catch.SetVerbose(true);
   19857   CompileRun("try { throw new Error(); } finally { gc(); }");
   19858   CHECK(try_catch.HasCaught());
   19859 }
   19860 
   19861 
   19862 THREADED_TEST(Regress149912) {
   19863   LocalContext context;
   19864   v8::HandleScope scope(context->GetIsolate());
   19865   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   19866   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   19867   context->Global()->Set(v8_str("Bug"), templ->GetFunction());
   19868   CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
   19869 }
   19870 
   19871 
   19872 THREADED_TEST(Regress157124) {
   19873   LocalContext context;
   19874   v8::HandleScope scope(context->GetIsolate());
   19875   Local<ObjectTemplate> templ = ObjectTemplate::New();
   19876   Local<Object> obj = templ->NewInstance();
   19877   obj->GetIdentityHash();
   19878   obj->DeleteHiddenValue(v8_str("Bug"));
   19879 }
   19880 
   19881 
   19882 THREADED_TEST(Regress2535) {
   19883   i::FLAG_harmony_collections = true;
   19884   LocalContext context;
   19885   v8::HandleScope scope(context->GetIsolate());
   19886   Local<Value> set_value = CompileRun("new Set();");
   19887   Local<Object> set_object(Local<Object>::Cast(set_value));
   19888   CHECK_EQ(0, set_object->InternalFieldCount());
   19889   Local<Value> map_value = CompileRun("new Map();");
   19890   Local<Object> map_object(Local<Object>::Cast(map_value));
   19891   CHECK_EQ(0, map_object->InternalFieldCount());
   19892 }
   19893 
   19894 
   19895 THREADED_TEST(Regress2746) {
   19896   LocalContext context;
   19897   v8::HandleScope scope(context->GetIsolate());
   19898   Local<Object> obj = Object::New();
   19899   Local<String> key = String::New("key");
   19900   obj->SetHiddenValue(key, v8::Undefined());
   19901   Local<Value> value = obj->GetHiddenValue(key);
   19902   CHECK(!value.IsEmpty());
   19903   CHECK(value->IsUndefined());
   19904 }
   19905 
   19906 
   19907 THREADED_TEST(Regress260106) {
   19908   LocalContext context;
   19909   v8::HandleScope scope(context->GetIsolate());
   19910   Local<FunctionTemplate> templ = FunctionTemplate::New(DummyCallHandler);
   19911   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
   19912   Local<Function> function = templ->GetFunction();
   19913   CHECK(!function.IsEmpty());
   19914   CHECK(function->IsFunction());
   19915 }
   19916 
   19917 
   19918 THREADED_TEST(JSONParseObject) {
   19919   LocalContext context;
   19920   HandleScope scope(context->GetIsolate());
   19921   Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
   19922   Handle<Object> global = context->Global();
   19923   global->Set(v8_str("obj"), obj);
   19924   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
   19925 }
   19926 
   19927 
   19928 THREADED_TEST(JSONParseNumber) {
   19929   LocalContext context;
   19930   HandleScope scope(context->GetIsolate());
   19931   Local<Value> obj = v8::JSON::Parse(v8_str("42"));
   19932   Handle<Object> global = context->Global();
   19933   global->Set(v8_str("obj"), obj);
   19934   ExpectString("JSON.stringify(obj)", "42");
   19935 }
   19936 
   19937 
   19938 #ifndef WIN32
   19939 class ThreadInterruptTest {
   19940  public:
   19941   ThreadInterruptTest() : sem_(NULL), sem_value_(0) { }
   19942   ~ThreadInterruptTest() { delete sem_; }
   19943 
   19944   void RunTest() {
   19945     sem_ = i::OS::CreateSemaphore(0);
   19946 
   19947     InterruptThread i_thread(this);
   19948     i_thread.Start();
   19949 
   19950     sem_->Wait();
   19951     CHECK_EQ(kExpectedValue, sem_value_);
   19952   }
   19953 
   19954  private:
   19955   static const int kExpectedValue = 1;
   19956 
   19957   class InterruptThread : public i::Thread {
   19958    public:
   19959     explicit InterruptThread(ThreadInterruptTest* test)
   19960         : Thread("InterruptThread"), test_(test) {}
   19961 
   19962     virtual void Run() {
   19963       struct sigaction action;
   19964 
   19965       // Ensure that we'll enter waiting condition
   19966       i::OS::Sleep(100);
   19967 
   19968       // Setup signal handler
   19969       memset(&action, 0, sizeof(action));
   19970       action.sa_handler = SignalHandler;
   19971       sigaction(SIGCHLD, &action, NULL);
   19972 
   19973       // Send signal
   19974       kill(getpid(), SIGCHLD);
   19975 
   19976       // Ensure that if wait has returned because of error
   19977       i::OS::Sleep(100);
   19978 
   19979       // Set value and signal semaphore
   19980       test_->sem_value_ = 1;
   19981       test_->sem_->Signal();
   19982     }
   19983 
   19984     static void SignalHandler(int signal) {
   19985     }
   19986 
   19987    private:
   19988      ThreadInterruptTest* test_;
   19989   };
   19990 
   19991   i::Semaphore* sem_;
   19992   volatile int sem_value_;
   19993 };
   19994 
   19995 
   19996 THREADED_TEST(SemaphoreInterruption) {
   19997   ThreadInterruptTest().RunTest();
   19998 }
   19999 
   20000 
   20001 static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
   20002                                      Local<Value> name,
   20003                                      v8::AccessType type,
   20004                                      Local<Value> data) {
   20005   i::PrintF("Named access blocked.\n");
   20006   return false;
   20007 }
   20008 
   20009 
   20010 static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
   20011                                      uint32_t key,
   20012                                      v8::AccessType type,
   20013                                      Local<Value> data) {
   20014   i::PrintF("Indexed access blocked.\n");
   20015   return false;
   20016 }
   20017 
   20018 
   20019 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20020   CHECK(false);
   20021 }
   20022 
   20023 
   20024 TEST(JSONStringifyAccessCheck) {
   20025   v8::V8::Initialize();
   20026   v8::HandleScope scope(v8::Isolate::GetCurrent());
   20027 
   20028   // Create an ObjectTemplate for global objects and install access
   20029   // check callbacks that will block access.
   20030   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   20031   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
   20032                                            IndexAccessAlwaysBlocked);
   20033 
   20034   // Create a context and set an x property on it's global object.
   20035   LocalContext context0(NULL, global_template);
   20036   v8::Handle<v8::Object> global0 = context0->Global();
   20037   global0->Set(v8_str("x"), v8_num(42));
   20038   ExpectString("JSON.stringify(this)", "{\"x\":42}");
   20039 
   20040   for (int i = 0; i < 2; i++) {
   20041     if (i == 1) {
   20042       // Install a toJSON function on the second run.
   20043       v8::Handle<v8::FunctionTemplate> toJSON =
   20044           v8::FunctionTemplate::New(UnreachableCallback);
   20045 
   20046       global0->Set(v8_str("toJSON"), toJSON->GetFunction());
   20047     }
   20048     // Create a context with a different security token so that the
   20049     // failed access check callback will be called on each access.
   20050     LocalContext context1(NULL, global_template);
   20051     context1->Global()->Set(v8_str("other"), global0);
   20052 
   20053     ExpectString("JSON.stringify(other)", "{}");
   20054     ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
   20055                  "{\"a\":{},\"b\":[\"c\"]}");
   20056     ExpectString("JSON.stringify([other, 'b', 'c'])",
   20057                  "[{},\"b\",\"c\"]");
   20058 
   20059     v8::Handle<v8::Array> array = v8::Array::New(2);
   20060     array->Set(0, v8_str("a"));
   20061     array->Set(1, v8_str("b"));
   20062     context1->Global()->Set(v8_str("array"), array);
   20063     ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
   20064     array->TurnOnAccessCheck();
   20065     ExpectString("JSON.stringify(array)", "[]");
   20066     ExpectString("JSON.stringify([array])", "[[]]");
   20067     ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
   20068   }
   20069 }
   20070 
   20071 
   20072 bool access_check_fail_thrown = false;
   20073 bool catch_callback_called = false;
   20074 
   20075 
   20076 // Failed access check callback that performs a GC on each invocation.
   20077 void FailedAccessCheckThrows(Local<v8::Object> target,
   20078                              v8::AccessType type,
   20079                              Local<v8::Value> data) {
   20080   access_check_fail_thrown = true;
   20081   i::PrintF("Access check failed. Error thrown.\n");
   20082   v8::ThrowException(v8::Exception::Error(v8_str("cross context")));
   20083 }
   20084 
   20085 
   20086 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20087   for (int i = 0; i < args.Length(); i++) {
   20088     i::PrintF("%s\n", *String::Utf8Value(args[i]));
   20089   }
   20090   catch_callback_called = true;
   20091 }
   20092 
   20093 
   20094 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20095   args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
   20096 }
   20097 
   20098 
   20099 void CheckCorrectThrow(const char* script) {
   20100   // Test that the script, when wrapped into a try-catch, triggers the catch
   20101   // clause due to failed access check throwing an exception.
   20102   // The subsequent try-catch should run without any exception.
   20103   access_check_fail_thrown = false;
   20104   catch_callback_called = false;
   20105   i::ScopedVector<char> source(1024);
   20106   i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
   20107   CompileRun(source.start());
   20108   CHECK(access_check_fail_thrown);
   20109   CHECK(catch_callback_called);
   20110 
   20111   access_check_fail_thrown = false;
   20112   catch_callback_called = false;
   20113   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
   20114   CHECK(!access_check_fail_thrown);
   20115   CHECK(!catch_callback_called);
   20116 }
   20117 
   20118 
   20119 TEST(AccessCheckThrows) {
   20120   i::FLAG_allow_natives_syntax = true;
   20121   v8::V8::Initialize();
   20122   v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   20123   v8::HandleScope scope(v8::Isolate::GetCurrent());
   20124 
   20125   // Create an ObjectTemplate for global objects and install access
   20126   // check callbacks that will block access.
   20127   v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
   20128   global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
   20129                                            IndexAccessAlwaysBlocked);
   20130 
   20131   // Create a context and set an x property on it's global object.
   20132   LocalContext context0(NULL, global_template);
   20133   context0->Global()->Set(v8_str("x"), v8_num(42));
   20134   v8::Handle<v8::Object> global0 = context0->Global();
   20135 
   20136   // Create a context with a different security token so that the
   20137   // failed access check callback will be called on each access.
   20138   LocalContext context1(NULL, global_template);
   20139   context1->Global()->Set(v8_str("other"), global0);
   20140 
   20141   v8::Handle<v8::FunctionTemplate> catcher_fun =
   20142       v8::FunctionTemplate::New(CatcherCallback);
   20143   context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
   20144 
   20145   v8::Handle<v8::FunctionTemplate> has_own_property_fun =
   20146       v8::FunctionTemplate::New(HasOwnPropertyCallback);
   20147   context1->Global()->Set(v8_str("has_own_property"),
   20148                           has_own_property_fun->GetFunction());
   20149 
   20150   { v8::TryCatch try_catch;
   20151     access_check_fail_thrown = false;
   20152     CompileRun("other.x;");
   20153     CHECK(access_check_fail_thrown);
   20154     CHECK(try_catch.HasCaught());
   20155   }
   20156 
   20157   CheckCorrectThrow("other.x");
   20158   CheckCorrectThrow("other[1]");
   20159   CheckCorrectThrow("JSON.stringify(other)");
   20160   CheckCorrectThrow("has_own_property(other, 'x')");
   20161   CheckCorrectThrow("%GetProperty(other, 'x')");
   20162   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
   20163   CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
   20164   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
   20165   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
   20166   CheckCorrectThrow("%HasLocalProperty(other, 'x')");
   20167   CheckCorrectThrow("%HasProperty(other, 'x')");
   20168   CheckCorrectThrow("%HasElement(other, 1)");
   20169   CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
   20170   CheckCorrectThrow("%GetPropertyNames(other)");
   20171   CheckCorrectThrow("%GetLocalPropertyNames(other, true)");
   20172   CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
   20173                         "other, 'x', null, null, 1)");
   20174 }
   20175 
   20176 
   20177 THREADED_TEST(Regress256330) {
   20178   i::FLAG_allow_natives_syntax = true;
   20179   LocalContext context;
   20180   v8::HandleScope scope(context->GetIsolate());
   20181   Handle<FunctionTemplate> templ = FunctionTemplate::New();
   20182   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
   20183   context->Global()->Set(v8_str("Bug"), templ->GetFunction());
   20184   CompileRun("\"use strict\"; var o = new Bug;"
   20185              "function f(o) { o.x = 10; };"
   20186              "f(o); f(o); f(o);"
   20187              "%OptimizeFunctionOnNextCall(f);"
   20188              "f(o);");
   20189   ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
   20190 }
   20191 
   20192 
   20193 #endif  // WIN32
   20194