Home | History | Annotate | Download | only in src
      1 // Copyright 2009 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 "v8.h"
     29 
     30 #include "api.h"
     31 #include "arguments.h"
     32 #include "bootstrapper.h"
     33 #include "compiler.h"
     34 #include "debug.h"
     35 #include "execution.h"
     36 #include "global-handles.h"
     37 #include "globals.h"
     38 #include "platform.h"
     39 #include "serialize.h"
     40 #include "snapshot.h"
     41 #include "utils.h"
     42 #include "v8threads.h"
     43 #include "version.h"
     44 
     45 
     46 #define LOG_API(expr) LOG(ApiEntryCall(expr))
     47 
     48 #ifdef ENABLE_HEAP_PROTECTION
     49 #define ENTER_V8 i::VMState __state__(i::OTHER)
     50 #define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
     51 #else
     52 #define ENTER_V8 ((void) 0)
     53 #define LEAVE_V8 ((void) 0)
     54 #endif
     55 
     56 namespace v8 {
     57 
     58 
     59 #define ON_BAILOUT(location, code)              \
     60   if (IsDeadCheck(location)) {                  \
     61     code;                                       \
     62     UNREACHABLE();                              \
     63   }
     64 
     65 
     66 #define EXCEPTION_PREAMBLE()                                      \
     67   thread_local.IncrementCallDepth();                              \
     68   ASSERT(!i::Top::external_caught_exception());                   \
     69   bool has_pending_exception = false
     70 
     71 
     72 #define EXCEPTION_BAILOUT_CHECK(value)                                         \
     73   do {                                                                         \
     74     thread_local.DecrementCallDepth();                                         \
     75     if (has_pending_exception) {                                               \
     76       if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) {      \
     77         if (!thread_local.ignore_out_of_memory())                              \
     78           i::V8::FatalProcessOutOfMemory(NULL);                                \
     79       }                                                                        \
     80       bool call_depth_is_zero = thread_local.CallDepthIsZero();                \
     81       i::Top::OptionalRescheduleException(call_depth_is_zero);                 \
     82       return value;                                                            \
     83     }                                                                          \
     84   } while (false)
     85 
     86 
     87 #define API_ENTRY_CHECK(msg)                                                   \
     88   do {                                                                         \
     89     if (v8::Locker::IsActive()) {                                              \
     90       ApiCheck(i::ThreadManager::IsLockedByCurrentThread(),                    \
     91                msg,                                                            \
     92                "Entering the V8 API without proper locking in place");         \
     93     }                                                                          \
     94   } while (false)
     95 
     96 // --- D a t a   t h a t   i s   s p e c i f i c   t o   a   t h r e a d ---
     97 
     98 
     99 static i::HandleScopeImplementer thread_local;
    100 
    101 
    102 // --- E x c e p t i o n   B e h a v i o r ---
    103 
    104 
    105 static FatalErrorCallback exception_behavior = NULL;
    106 int i::Internals::kJSObjectType = JS_OBJECT_TYPE;
    107 int i::Internals::kFirstNonstringType = FIRST_NONSTRING_TYPE;
    108 int i::Internals::kProxyType = PROXY_TYPE;
    109 
    110 static void DefaultFatalErrorHandler(const char* location,
    111                                      const char* message) {
    112   ENTER_V8;
    113   API_Fatal(location, message);
    114 }
    115 
    116 
    117 
    118 static FatalErrorCallback& GetFatalErrorHandler() {
    119   if (exception_behavior == NULL) {
    120     exception_behavior = DefaultFatalErrorHandler;
    121   }
    122   return exception_behavior;
    123 }
    124 
    125 
    126 
    127 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
    128 // The default fatal error handler is called and execution is stopped.
    129 void i::V8::FatalProcessOutOfMemory(const char* location) {
    130   i::HeapStats heap_stats;
    131   int start_marker;
    132   heap_stats.start_marker = &start_marker;
    133   int new_space_size;
    134   heap_stats.new_space_size = &new_space_size;
    135   int new_space_capacity;
    136   heap_stats.new_space_capacity = &new_space_capacity;
    137   int old_pointer_space_size;
    138   heap_stats.old_pointer_space_size = &old_pointer_space_size;
    139   int old_pointer_space_capacity;
    140   heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
    141   int old_data_space_size;
    142   heap_stats.old_data_space_size = &old_data_space_size;
    143   int old_data_space_capacity;
    144   heap_stats.old_data_space_capacity = &old_data_space_capacity;
    145   int code_space_size;
    146   heap_stats.code_space_size = &code_space_size;
    147   int code_space_capacity;
    148   heap_stats.code_space_capacity = &code_space_capacity;
    149   int map_space_size;
    150   heap_stats.map_space_size = &map_space_size;
    151   int map_space_capacity;
    152   heap_stats.map_space_capacity = &map_space_capacity;
    153   int cell_space_size;
    154   heap_stats.cell_space_size = &cell_space_size;
    155   int cell_space_capacity;
    156   heap_stats.cell_space_capacity = &cell_space_capacity;
    157   int lo_space_size;
    158   heap_stats.lo_space_size = &lo_space_size;
    159   int global_handle_count;
    160   heap_stats.global_handle_count = &global_handle_count;
    161   int weak_global_handle_count;
    162   heap_stats.weak_global_handle_count = &weak_global_handle_count;
    163   int pending_global_handle_count;
    164   heap_stats.pending_global_handle_count = &pending_global_handle_count;
    165   int near_death_global_handle_count;
    166   heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
    167   int destroyed_global_handle_count;
    168   heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
    169   int end_marker;
    170   heap_stats.end_marker = &end_marker;
    171   i::Heap::RecordStats(&heap_stats);
    172   i::V8::SetFatalError();
    173   FatalErrorCallback callback = GetFatalErrorHandler();
    174   {
    175     LEAVE_V8;
    176     callback(location, "Allocation failed - process out of memory");
    177   }
    178   // If the callback returns, we stop execution.
    179   UNREACHABLE();
    180 }
    181 
    182 
    183 void V8::SetFatalErrorHandler(FatalErrorCallback that) {
    184   exception_behavior = that;
    185 }
    186 
    187 
    188 bool Utils::ReportApiFailure(const char* location, const char* message) {
    189   FatalErrorCallback callback = GetFatalErrorHandler();
    190   callback(location, message);
    191   i::V8::SetFatalError();
    192   return false;
    193 }
    194 
    195 
    196 bool V8::IsDead() {
    197   return i::V8::IsDead();
    198 }
    199 
    200 
    201 static inline bool ApiCheck(bool condition,
    202                             const char* location,
    203                             const char* message) {
    204   return condition ? true : Utils::ReportApiFailure(location, message);
    205 }
    206 
    207 
    208 static bool ReportV8Dead(const char* location) {
    209   FatalErrorCallback callback = GetFatalErrorHandler();
    210   callback(location, "V8 is no longer usable");
    211   return true;
    212 }
    213 
    214 
    215 static bool ReportEmptyHandle(const char* location) {
    216   FatalErrorCallback callback = GetFatalErrorHandler();
    217   callback(location, "Reading from empty handle");
    218   return true;
    219 }
    220 
    221 
    222 /**
    223  * IsDeadCheck checks that the vm is usable.  If, for instance, the vm has been
    224  * out of memory at some point this check will fail.  It should be called on
    225  * entry to all methods that touch anything in the heap, except destructors
    226  * which you sometimes can't avoid calling after the vm has crashed.  Functions
    227  * that call EnsureInitialized or ON_BAILOUT don't have to also call
    228  * IsDeadCheck.  ON_BAILOUT has the advantage over EnsureInitialized that you
    229  * can arrange to return if the VM is dead.  This is needed to ensure that no VM
    230  * heap allocations are attempted on a dead VM.  EnsureInitialized has the
    231  * advantage over ON_BAILOUT that it actually initializes the VM if this has not
    232  * yet been done.
    233  */
    234 static inline bool IsDeadCheck(const char* location) {
    235   return !i::V8::IsRunning()
    236       && i::V8::IsDead() ? ReportV8Dead(location) : false;
    237 }
    238 
    239 
    240 static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
    241   return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
    242 }
    243 
    244 
    245 static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
    246   return (obj == 0) ? ReportEmptyHandle(location) : false;
    247 }
    248 
    249 // --- S t a t i c s ---
    250 
    251 
    252 static i::StringInputBuffer write_input_buffer;
    253 
    254 
    255 static inline bool EnsureInitialized(const char* location) {
    256   if (i::V8::IsRunning()) {
    257     return true;
    258   }
    259   if (IsDeadCheck(location)) {
    260     return false;
    261   }
    262   return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
    263 }
    264 
    265 
    266 ImplementationUtilities::HandleScopeData*
    267     ImplementationUtilities::CurrentHandleScope() {
    268   return &i::HandleScope::current_;
    269 }
    270 
    271 
    272 #ifdef DEBUG
    273 void ImplementationUtilities::ZapHandleRange(i::Object** begin,
    274                                              i::Object** end) {
    275   i::HandleScope::ZapRange(begin, end);
    276 }
    277 #endif
    278 
    279 
    280 v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
    281   if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
    282   return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
    283 }
    284 
    285 
    286 v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
    287   if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
    288   return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
    289 }
    290 
    291 
    292 v8::Handle<v8::Boolean> ImplementationUtilities::True() {
    293   if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
    294   return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
    295 }
    296 
    297 
    298 v8::Handle<v8::Boolean> ImplementationUtilities::False() {
    299   if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
    300   return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
    301 }
    302 
    303 
    304 void V8::SetFlagsFromString(const char* str, int length) {
    305   i::FlagList::SetFlagsFromString(str, length);
    306 }
    307 
    308 
    309 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
    310   i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
    311 }
    312 
    313 
    314 v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
    315   if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
    316   ENTER_V8;
    317   // If we're passed an empty handle, we throw an undefined exception
    318   // to deal more gracefully with out of memory situations.
    319   if (value.IsEmpty()) {
    320     i::Top::ScheduleThrow(i::Heap::undefined_value());
    321   } else {
    322     i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
    323   }
    324   return v8::Undefined();
    325 }
    326 
    327 
    328 RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
    329 
    330 
    331 RegisteredExtension::RegisteredExtension(Extension* extension)
    332     : extension_(extension), state_(UNVISITED) { }
    333 
    334 
    335 void RegisteredExtension::Register(RegisteredExtension* that) {
    336   that->next_ = RegisteredExtension::first_extension_;
    337   RegisteredExtension::first_extension_ = that;
    338 }
    339 
    340 
    341 void RegisterExtension(Extension* that) {
    342   RegisteredExtension* extension = new RegisteredExtension(that);
    343   RegisteredExtension::Register(extension);
    344 }
    345 
    346 
    347 Extension::Extension(const char* name,
    348                      const char* source,
    349                      int dep_count,
    350                      const char** deps)
    351     : name_(name),
    352       source_(source),
    353       dep_count_(dep_count),
    354       deps_(deps),
    355       auto_enable_(false) { }
    356 
    357 
    358 v8::Handle<Primitive> Undefined() {
    359   LOG_API("Undefined");
    360   return ImplementationUtilities::Undefined();
    361 }
    362 
    363 
    364 v8::Handle<Primitive> Null() {
    365   LOG_API("Null");
    366   return ImplementationUtilities::Null();
    367 }
    368 
    369 
    370 v8::Handle<Boolean> True() {
    371   LOG_API("True");
    372   return ImplementationUtilities::True();
    373 }
    374 
    375 
    376 v8::Handle<Boolean> False() {
    377   LOG_API("False");
    378   return ImplementationUtilities::False();
    379 }
    380 
    381 
    382 ResourceConstraints::ResourceConstraints()
    383   : max_young_space_size_(0),
    384     max_old_space_size_(0),
    385     stack_limit_(NULL) { }
    386 
    387 
    388 bool SetResourceConstraints(ResourceConstraints* constraints) {
    389   int young_space_size = constraints->max_young_space_size();
    390   int old_gen_size = constraints->max_old_space_size();
    391   if (young_space_size != 0 || old_gen_size != 0) {
    392     bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size);
    393     if (!result) return false;
    394   }
    395   if (constraints->stack_limit() != NULL) {
    396     uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
    397     i::StackGuard::SetStackLimit(limit);
    398   }
    399   return true;
    400 }
    401 
    402 
    403 i::Object** V8::GlobalizeReference(i::Object** obj) {
    404   if (IsDeadCheck("V8::Persistent::New")) return NULL;
    405   LOG_API("Persistent::New");
    406   i::Handle<i::Object> result =
    407       i::GlobalHandles::Create(*obj);
    408   return result.location();
    409 }
    410 
    411 
    412 void V8::MakeWeak(i::Object** object, void* parameters,
    413                   WeakReferenceCallback callback) {
    414   LOG_API("MakeWeak");
    415   i::GlobalHandles::MakeWeak(object, parameters, callback);
    416 }
    417 
    418 
    419 void V8::ClearWeak(i::Object** obj) {
    420   LOG_API("ClearWeak");
    421   i::GlobalHandles::ClearWeakness(obj);
    422 }
    423 
    424 
    425 bool V8::IsGlobalNearDeath(i::Object** obj) {
    426   LOG_API("IsGlobalNearDeath");
    427   if (!i::V8::IsRunning()) return false;
    428   return i::GlobalHandles::IsNearDeath(obj);
    429 }
    430 
    431 
    432 bool V8::IsGlobalWeak(i::Object** obj) {
    433   LOG_API("IsGlobalWeak");
    434   if (!i::V8::IsRunning()) return false;
    435   return i::GlobalHandles::IsWeak(obj);
    436 }
    437 
    438 
    439 void V8::DisposeGlobal(i::Object** obj) {
    440   LOG_API("DisposeGlobal");
    441   if (!i::V8::IsRunning()) return;
    442   if ((*obj)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
    443   i::GlobalHandles::Destroy(obj);
    444 }
    445 
    446 // --- H a n d l e s ---
    447 
    448 
    449 HandleScope::HandleScope() : is_closed_(false) {
    450   API_ENTRY_CHECK("HandleScope::HandleScope");
    451   i::HandleScope::Enter(&previous_);
    452 }
    453 
    454 
    455 HandleScope::~HandleScope() {
    456   if (!is_closed_) {
    457     i::HandleScope::Leave(&previous_);
    458   }
    459 }
    460 
    461 
    462 int HandleScope::NumberOfHandles() {
    463   return i::HandleScope::NumberOfHandles();
    464 }
    465 
    466 
    467 i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
    468   return i::HandleScope::CreateHandle(value);
    469 }
    470 
    471 
    472 void Context::Enter() {
    473   if (IsDeadCheck("v8::Context::Enter()")) return;
    474   ENTER_V8;
    475   i::Handle<i::Context> env = Utils::OpenHandle(this);
    476   thread_local.EnterContext(env);
    477 
    478   thread_local.SaveContext(i::Top::context());
    479   i::Top::set_context(*env);
    480 }
    481 
    482 
    483 void Context::Exit() {
    484   if (!i::V8::IsRunning()) return;
    485   if (!ApiCheck(thread_local.LeaveLastContext(),
    486                 "v8::Context::Exit()",
    487                 "Cannot exit non-entered context")) {
    488     return;
    489   }
    490 
    491   // Content of 'last_context' could be NULL.
    492   i::Context* last_context = thread_local.RestoreContext();
    493   i::Top::set_context(last_context);
    494 }
    495 
    496 
    497 void Context::SetData(v8::Handle<String> data) {
    498   if (IsDeadCheck("v8::Context::SetData()")) return;
    499   ENTER_V8;
    500   {
    501     HandleScope scope;
    502     i::Handle<i::Context> env = Utils::OpenHandle(this);
    503     i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
    504     ASSERT(env->IsGlobalContext());
    505     if (env->IsGlobalContext()) {
    506       env->set_data(*raw_data);
    507     }
    508   }
    509 }
    510 
    511 
    512 v8::Local<v8::Value> Context::GetData() {
    513   if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
    514   ENTER_V8;
    515   i::Object* raw_result = NULL;
    516   {
    517     HandleScope scope;
    518     i::Handle<i::Context> env = Utils::OpenHandle(this);
    519     ASSERT(env->IsGlobalContext());
    520     if (env->IsGlobalContext()) {
    521       raw_result = env->data();
    522     } else {
    523       return Local<Value>();
    524     }
    525   }
    526   i::Handle<i::Object> result(raw_result);
    527   return Utils::ToLocal(result);
    528 }
    529 
    530 
    531 i::Object** v8::HandleScope::RawClose(i::Object** value) {
    532   if (!ApiCheck(!is_closed_,
    533                 "v8::HandleScope::Close()",
    534                 "Local scope has already been closed")) {
    535     return 0;
    536   }
    537   LOG_API("CloseHandleScope");
    538 
    539   // Read the result before popping the handle block.
    540   i::Object* result = *value;
    541   is_closed_ = true;
    542   i::HandleScope::Leave(&previous_);
    543 
    544   // Allocate a new handle on the previous handle block.
    545   i::Handle<i::Object> handle(result);
    546   return handle.location();
    547 }
    548 
    549 
    550 // --- N e a n d e r ---
    551 
    552 
    553 // A constructor cannot easily return an error value, therefore it is necessary
    554 // to check for a dead VM with ON_BAILOUT before constructing any Neander
    555 // objects.  To remind you about this there is no HandleScope in the
    556 // NeanderObject constructor.  When you add one to the site calling the
    557 // constructor you should check that you ensured the VM was not dead first.
    558 NeanderObject::NeanderObject(int size) {
    559   EnsureInitialized("v8::Nowhere");
    560   ENTER_V8;
    561   value_ = i::Factory::NewNeanderObject();
    562   i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
    563   value_->set_elements(*elements);
    564 }
    565 
    566 
    567 int NeanderObject::size() {
    568   return i::FixedArray::cast(value_->elements())->length();
    569 }
    570 
    571 
    572 NeanderArray::NeanderArray() : obj_(2) {
    573   obj_.set(0, i::Smi::FromInt(0));
    574 }
    575 
    576 
    577 int NeanderArray::length() {
    578   return i::Smi::cast(obj_.get(0))->value();
    579 }
    580 
    581 
    582 i::Object* NeanderArray::get(int offset) {
    583   ASSERT(0 <= offset);
    584   ASSERT(offset < length());
    585   return obj_.get(offset + 1);
    586 }
    587 
    588 
    589 // This method cannot easily return an error value, therefore it is necessary
    590 // to check for a dead VM with ON_BAILOUT before calling it.  To remind you
    591 // about this there is no HandleScope in this method.  When you add one to the
    592 // site calling this method you should check that you ensured the VM was not
    593 // dead first.
    594 void NeanderArray::add(i::Handle<i::Object> value) {
    595   int length = this->length();
    596   int size = obj_.size();
    597   if (length == size - 1) {
    598     i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
    599     for (int i = 0; i < length; i++)
    600       new_elms->set(i + 1, get(i));
    601     obj_.value()->set_elements(*new_elms);
    602   }
    603   obj_.set(length + 1, *value);
    604   obj_.set(0, i::Smi::FromInt(length + 1));
    605 }
    606 
    607 
    608 void NeanderArray::set(int index, i::Object* value) {
    609   if (index < 0 || index >= this->length()) return;
    610   obj_.set(index + 1, value);
    611 }
    612 
    613 
    614 // --- T e m p l a t e ---
    615 
    616 
    617 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
    618   that->set_tag(i::Smi::FromInt(type));
    619 }
    620 
    621 
    622 void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
    623                    v8::PropertyAttribute attribute) {
    624   if (IsDeadCheck("v8::Template::SetProperty()")) return;
    625   ENTER_V8;
    626   HandleScope scope;
    627   i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
    628   if (list->IsUndefined()) {
    629     list = NeanderArray().value();
    630     Utils::OpenHandle(this)->set_property_list(*list);
    631   }
    632   NeanderArray array(list);
    633   array.add(Utils::OpenHandle(*name));
    634   array.add(Utils::OpenHandle(*value));
    635   array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
    636 }
    637 
    638 
    639 // --- F u n c t i o n   T e m p l a t e ---
    640 static void InitializeFunctionTemplate(
    641       i::Handle<i::FunctionTemplateInfo> info) {
    642   info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
    643   info->set_flag(0);
    644 }
    645 
    646 
    647 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
    648   if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
    649     return Local<ObjectTemplate>();
    650   }
    651   ENTER_V8;
    652   i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
    653   if (result->IsUndefined()) {
    654     result = Utils::OpenHandle(*ObjectTemplate::New());
    655     Utils::OpenHandle(this)->set_prototype_template(*result);
    656   }
    657   return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
    658 }
    659 
    660 
    661 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
    662   if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
    663   ENTER_V8;
    664   Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
    665 }
    666 
    667 
    668 // To distinguish the function templates, so that we can find them in the
    669 // function cache of the global context.
    670 static int next_serial_number = 0;
    671 
    672 
    673 Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
    674     v8::Handle<Value> data, v8::Handle<Signature> signature) {
    675   EnsureInitialized("v8::FunctionTemplate::New()");
    676   LOG_API("FunctionTemplate::New");
    677   ENTER_V8;
    678   i::Handle<i::Struct> struct_obj =
    679       i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
    680   i::Handle<i::FunctionTemplateInfo> obj =
    681       i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
    682   InitializeFunctionTemplate(obj);
    683   obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
    684   if (callback != 0) {
    685     if (data.IsEmpty()) data = v8::Undefined();
    686     Utils::ToLocal(obj)->SetCallHandler(callback, data);
    687   }
    688   obj->set_undetectable(false);
    689   obj->set_needs_access_check(false);
    690 
    691   if (!signature.IsEmpty())
    692     obj->set_signature(*Utils::OpenHandle(*signature));
    693   return Utils::ToLocal(obj);
    694 }
    695 
    696 
    697 Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
    698       int argc, Handle<FunctionTemplate> argv[]) {
    699   EnsureInitialized("v8::Signature::New()");
    700   LOG_API("Signature::New");
    701   ENTER_V8;
    702   i::Handle<i::Struct> struct_obj =
    703       i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
    704   i::Handle<i::SignatureInfo> obj =
    705       i::Handle<i::SignatureInfo>::cast(struct_obj);
    706   if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
    707   if (argc > 0) {
    708     i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
    709     for (int i = 0; i < argc; i++) {
    710       if (!argv[i].IsEmpty())
    711         args->set(i, *Utils::OpenHandle(*argv[i]));
    712     }
    713     obj->set_args(*args);
    714   }
    715   return Utils::ToLocal(obj);
    716 }
    717 
    718 
    719 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
    720   Handle<FunctionTemplate> types[1] = { type };
    721   return TypeSwitch::New(1, types);
    722 }
    723 
    724 
    725 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
    726   EnsureInitialized("v8::TypeSwitch::New()");
    727   LOG_API("TypeSwitch::New");
    728   ENTER_V8;
    729   i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
    730   for (int i = 0; i < argc; i++)
    731     vector->set(i, *Utils::OpenHandle(*types[i]));
    732   i::Handle<i::Struct> struct_obj =
    733       i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
    734   i::Handle<i::TypeSwitchInfo> obj =
    735       i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
    736   obj->set_types(*vector);
    737   return Utils::ToLocal(obj);
    738 }
    739 
    740 
    741 int TypeSwitch::match(v8::Handle<Value> value) {
    742   LOG_API("TypeSwitch::match");
    743   i::Handle<i::Object> obj = Utils::OpenHandle(*value);
    744   i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
    745   i::FixedArray* types = i::FixedArray::cast(info->types());
    746   for (int i = 0; i < types->length(); i++) {
    747     if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
    748       return i + 1;
    749   }
    750   return 0;
    751 }
    752 
    753 
    754 void FunctionTemplate::SetCallHandler(InvocationCallback callback,
    755                                       v8::Handle<Value> data) {
    756   if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
    757   ENTER_V8;
    758   HandleScope scope;
    759   i::Handle<i::Struct> struct_obj =
    760       i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
    761   i::Handle<i::CallHandlerInfo> obj =
    762       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
    763   obj->set_callback(*FromCData(callback));
    764   if (data.IsEmpty()) data = v8::Undefined();
    765   obj->set_data(*Utils::OpenHandle(*data));
    766   Utils::OpenHandle(this)->set_call_code(*obj);
    767 }
    768 
    769 
    770 void FunctionTemplate::AddInstancePropertyAccessor(
    771       v8::Handle<String> name,
    772       AccessorGetter getter,
    773       AccessorSetter setter,
    774       v8::Handle<Value> data,
    775       v8::AccessControl settings,
    776       v8::PropertyAttribute attributes) {
    777   if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
    778     return;
    779   }
    780   ENTER_V8;
    781   HandleScope scope;
    782   i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
    783   ASSERT(getter != NULL);
    784   obj->set_getter(*FromCData(getter));
    785   obj->set_setter(*FromCData(setter));
    786   if (data.IsEmpty()) data = v8::Undefined();
    787   obj->set_data(*Utils::OpenHandle(*data));
    788   obj->set_name(*Utils::OpenHandle(*name));
    789   if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
    790   if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
    791   if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
    792   obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
    793 
    794   i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
    795   if (list->IsUndefined()) {
    796     list = NeanderArray().value();
    797     Utils::OpenHandle(this)->set_property_accessors(*list);
    798   }
    799   NeanderArray array(list);
    800   array.add(obj);
    801 }
    802 
    803 
    804 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
    805   if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
    806       || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
    807     return Local<ObjectTemplate>();
    808   ENTER_V8;
    809   if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
    810     Local<ObjectTemplate> templ =
    811         ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
    812     Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
    813   }
    814   i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
    815         Utils::OpenHandle(this)->instance_template()));
    816   return Utils::ToLocal(result);
    817 }
    818 
    819 
    820 void FunctionTemplate::SetClassName(Handle<String> name) {
    821   if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
    822   ENTER_V8;
    823   Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
    824 }
    825 
    826 
    827 void FunctionTemplate::SetHiddenPrototype(bool value) {
    828   if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
    829   ENTER_V8;
    830   Utils::OpenHandle(this)->set_hidden_prototype(value);
    831 }
    832 
    833 
    834 void FunctionTemplate::SetNamedInstancePropertyHandler(
    835       NamedPropertyGetter getter,
    836       NamedPropertySetter setter,
    837       NamedPropertyQuery query,
    838       NamedPropertyDeleter remover,
    839       NamedPropertyEnumerator enumerator,
    840       Handle<Value> data) {
    841   if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
    842     return;
    843   }
    844   ENTER_V8;
    845   HandleScope scope;
    846   i::Handle<i::Struct> struct_obj =
    847       i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
    848   i::Handle<i::InterceptorInfo> obj =
    849       i::Handle<i::InterceptorInfo>::cast(struct_obj);
    850   if (getter != 0) obj->set_getter(*FromCData(getter));
    851   if (setter != 0) obj->set_setter(*FromCData(setter));
    852   if (query != 0) obj->set_query(*FromCData(query));
    853   if (remover != 0) obj->set_deleter(*FromCData(remover));
    854   if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
    855   if (data.IsEmpty()) data = v8::Undefined();
    856   obj->set_data(*Utils::OpenHandle(*data));
    857   Utils::OpenHandle(this)->set_named_property_handler(*obj);
    858 }
    859 
    860 
    861 void FunctionTemplate::SetIndexedInstancePropertyHandler(
    862       IndexedPropertyGetter getter,
    863       IndexedPropertySetter setter,
    864       IndexedPropertyQuery query,
    865       IndexedPropertyDeleter remover,
    866       IndexedPropertyEnumerator enumerator,
    867       Handle<Value> data) {
    868   if (IsDeadCheck(
    869         "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
    870     return;
    871   }
    872   ENTER_V8;
    873   HandleScope scope;
    874   i::Handle<i::Struct> struct_obj =
    875       i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
    876   i::Handle<i::InterceptorInfo> obj =
    877       i::Handle<i::InterceptorInfo>::cast(struct_obj);
    878   if (getter != 0) obj->set_getter(*FromCData(getter));
    879   if (setter != 0) obj->set_setter(*FromCData(setter));
    880   if (query != 0) obj->set_query(*FromCData(query));
    881   if (remover != 0) obj->set_deleter(*FromCData(remover));
    882   if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
    883   if (data.IsEmpty()) data = v8::Undefined();
    884   obj->set_data(*Utils::OpenHandle(*data));
    885   Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
    886 }
    887 
    888 
    889 void FunctionTemplate::SetInstanceCallAsFunctionHandler(
    890       InvocationCallback callback,
    891       Handle<Value> data) {
    892   if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
    893     return;
    894   }
    895   ENTER_V8;
    896   HandleScope scope;
    897   i::Handle<i::Struct> struct_obj =
    898       i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
    899   i::Handle<i::CallHandlerInfo> obj =
    900       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
    901   obj->set_callback(*FromCData(callback));
    902   if (data.IsEmpty()) data = v8::Undefined();
    903   obj->set_data(*Utils::OpenHandle(*data));
    904   Utils::OpenHandle(this)->set_instance_call_handler(*obj);
    905 }
    906 
    907 
    908 // --- O b j e c t T e m p l a t e ---
    909 
    910 
    911 Local<ObjectTemplate> ObjectTemplate::New() {
    912   return New(Local<FunctionTemplate>());
    913 }
    914 
    915 
    916 Local<ObjectTemplate> ObjectTemplate::New(
    917       v8::Handle<FunctionTemplate> constructor) {
    918   if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
    919   EnsureInitialized("v8::ObjectTemplate::New()");
    920   LOG_API("ObjectTemplate::New");
    921   ENTER_V8;
    922   i::Handle<i::Struct> struct_obj =
    923       i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
    924   i::Handle<i::ObjectTemplateInfo> obj =
    925       i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
    926   InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
    927   if (!constructor.IsEmpty())
    928     obj->set_constructor(*Utils::OpenHandle(*constructor));
    929   obj->set_internal_field_count(i::Smi::FromInt(0));
    930   return Utils::ToLocal(obj);
    931 }
    932 
    933 
    934 // Ensure that the object template has a constructor.  If no
    935 // constructor is available we create one.
    936 static void EnsureConstructor(ObjectTemplate* object_template) {
    937   if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
    938     Local<FunctionTemplate> templ = FunctionTemplate::New();
    939     i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
    940     constructor->set_instance_template(*Utils::OpenHandle(object_template));
    941     Utils::OpenHandle(object_template)->set_constructor(*constructor);
    942   }
    943 }
    944 
    945 
    946 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
    947                                  AccessorGetter getter,
    948                                  AccessorSetter setter,
    949                                  v8::Handle<Value> data,
    950                                  AccessControl settings,
    951                                  PropertyAttribute attribute) {
    952   if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
    953   ENTER_V8;
    954   HandleScope scope;
    955   EnsureConstructor(this);
    956   i::FunctionTemplateInfo* constructor =
    957       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
    958   i::Handle<i::FunctionTemplateInfo> cons(constructor);
    959   Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
    960                                                     getter,
    961                                                     setter,
    962                                                     data,
    963                                                     settings,
    964                                                     attribute);
    965 }
    966 
    967 
    968 void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
    969                                              NamedPropertySetter setter,
    970                                              NamedPropertyQuery query,
    971                                              NamedPropertyDeleter remover,
    972                                              NamedPropertyEnumerator enumerator,
    973                                              Handle<Value> data) {
    974   if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
    975   ENTER_V8;
    976   HandleScope scope;
    977   EnsureConstructor(this);
    978   i::FunctionTemplateInfo* constructor =
    979       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
    980   i::Handle<i::FunctionTemplateInfo> cons(constructor);
    981   Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
    982                                                         setter,
    983                                                         query,
    984                                                         remover,
    985                                                         enumerator,
    986                                                         data);
    987 }
    988 
    989 
    990 void ObjectTemplate::MarkAsUndetectable() {
    991   if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
    992   ENTER_V8;
    993   HandleScope scope;
    994   EnsureConstructor(this);
    995   i::FunctionTemplateInfo* constructor =
    996       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
    997   i::Handle<i::FunctionTemplateInfo> cons(constructor);
    998   cons->set_undetectable(true);
    999 }
   1000 
   1001 
   1002 void ObjectTemplate::SetAccessCheckCallbacks(
   1003       NamedSecurityCallback named_callback,
   1004       IndexedSecurityCallback indexed_callback,
   1005       Handle<Value> data,
   1006       bool turned_on_by_default) {
   1007   if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
   1008   ENTER_V8;
   1009   HandleScope scope;
   1010   EnsureConstructor(this);
   1011 
   1012   i::Handle<i::Struct> struct_info =
   1013       i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
   1014   i::Handle<i::AccessCheckInfo> info =
   1015       i::Handle<i::AccessCheckInfo>::cast(struct_info);
   1016   info->set_named_callback(*FromCData(named_callback));
   1017   info->set_indexed_callback(*FromCData(indexed_callback));
   1018   if (data.IsEmpty()) data = v8::Undefined();
   1019   info->set_data(*Utils::OpenHandle(*data));
   1020 
   1021   i::FunctionTemplateInfo* constructor =
   1022       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
   1023   i::Handle<i::FunctionTemplateInfo> cons(constructor);
   1024   cons->set_access_check_info(*info);
   1025   cons->set_needs_access_check(turned_on_by_default);
   1026 }
   1027 
   1028 
   1029 void ObjectTemplate::SetIndexedPropertyHandler(
   1030       IndexedPropertyGetter getter,
   1031       IndexedPropertySetter setter,
   1032       IndexedPropertyQuery query,
   1033       IndexedPropertyDeleter remover,
   1034       IndexedPropertyEnumerator enumerator,
   1035       Handle<Value> data) {
   1036   if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
   1037   ENTER_V8;
   1038   HandleScope scope;
   1039   EnsureConstructor(this);
   1040   i::FunctionTemplateInfo* constructor =
   1041       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
   1042   i::Handle<i::FunctionTemplateInfo> cons(constructor);
   1043   Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
   1044                                                           setter,
   1045                                                           query,
   1046                                                           remover,
   1047                                                           enumerator,
   1048                                                           data);
   1049 }
   1050 
   1051 
   1052 void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
   1053                                               Handle<Value> data) {
   1054   if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
   1055   ENTER_V8;
   1056   HandleScope scope;
   1057   EnsureConstructor(this);
   1058   i::FunctionTemplateInfo* constructor =
   1059       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
   1060   i::Handle<i::FunctionTemplateInfo> cons(constructor);
   1061   Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
   1062 }
   1063 
   1064 
   1065 int ObjectTemplate::InternalFieldCount() {
   1066   if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
   1067     return 0;
   1068   }
   1069   return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
   1070 }
   1071 
   1072 
   1073 void ObjectTemplate::SetInternalFieldCount(int value) {
   1074   if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
   1075   if (!ApiCheck(i::Smi::IsValid(value),
   1076                 "v8::ObjectTemplate::SetInternalFieldCount()",
   1077                 "Invalid internal field count")) {
   1078     return;
   1079   }
   1080   ENTER_V8;
   1081   if (value > 0) {
   1082     // The internal field count is set by the constructor function's
   1083     // construct code, so we ensure that there is a constructor
   1084     // function to do the setting.
   1085     EnsureConstructor(this);
   1086   }
   1087   Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
   1088 }
   1089 
   1090 
   1091 // --- S c r i p t D a t a ---
   1092 
   1093 
   1094 ScriptData* ScriptData::PreCompile(const char* input, int length) {
   1095   unibrow::Utf8InputBuffer<> buf(input, length);
   1096   return i::PreParse(i::Handle<i::String>(), &buf, NULL);
   1097 }
   1098 
   1099 
   1100 ScriptData* ScriptData::New(unsigned* data, int length) {
   1101   return new i::ScriptDataImpl(i::Vector<unsigned>(data, length));
   1102 }
   1103 
   1104 
   1105 // --- S c r i p t ---
   1106 
   1107 
   1108 Local<Script> Script::New(v8::Handle<String> source,
   1109                           v8::ScriptOrigin* origin,
   1110                           v8::ScriptData* pre_data,
   1111                           v8::Handle<String> script_data) {
   1112   ON_BAILOUT("v8::Script::New()", return Local<Script>());
   1113   LOG_API("Script::New");
   1114   ENTER_V8;
   1115   i::Handle<i::String> str = Utils::OpenHandle(*source);
   1116   i::Handle<i::Object> name_obj;
   1117   int line_offset = 0;
   1118   int column_offset = 0;
   1119   if (origin != NULL) {
   1120     if (!origin->ResourceName().IsEmpty()) {
   1121       name_obj = Utils::OpenHandle(*origin->ResourceName());
   1122     }
   1123     if (!origin->ResourceLineOffset().IsEmpty()) {
   1124       line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
   1125     }
   1126     if (!origin->ResourceColumnOffset().IsEmpty()) {
   1127       column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
   1128     }
   1129   }
   1130   EXCEPTION_PREAMBLE();
   1131   i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
   1132   // We assert that the pre-data is sane, even though we can actually
   1133   // handle it if it turns out not to be in release mode.
   1134   ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
   1135   // If the pre-data isn't sane we simply ignore it
   1136   if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
   1137     pre_data_impl = NULL;
   1138   }
   1139   i::Handle<i::JSFunction> boilerplate =
   1140       i::Compiler::Compile(str,
   1141                            name_obj,
   1142                            line_offset,
   1143                            column_offset,
   1144                            NULL,
   1145                            pre_data_impl,
   1146                            Utils::OpenHandle(*script_data),
   1147                            i::NOT_NATIVES_CODE);
   1148   has_pending_exception = boilerplate.is_null();
   1149   EXCEPTION_BAILOUT_CHECK(Local<Script>());
   1150   return Local<Script>(ToApi<Script>(boilerplate));
   1151 }
   1152 
   1153 
   1154 Local<Script> Script::New(v8::Handle<String> source,
   1155                           v8::Handle<Value> file_name) {
   1156   ScriptOrigin origin(file_name);
   1157   return New(source, &origin);
   1158 }
   1159 
   1160 
   1161 Local<Script> Script::Compile(v8::Handle<String> source,
   1162                               v8::ScriptOrigin* origin,
   1163                               v8::ScriptData* pre_data,
   1164                               v8::Handle<String> script_data) {
   1165   ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
   1166   LOG_API("Script::Compile");
   1167   ENTER_V8;
   1168   Local<Script> generic = New(source, origin, pre_data, script_data);
   1169   if (generic.IsEmpty())
   1170     return generic;
   1171   i::Handle<i::JSFunction> boilerplate = Utils::OpenHandle(*generic);
   1172   i::Handle<i::JSFunction> result =
   1173       i::Factory::NewFunctionFromBoilerplate(boilerplate,
   1174                                              i::Top::global_context());
   1175   return Local<Script>(ToApi<Script>(result));
   1176 }
   1177 
   1178 
   1179 Local<Script> Script::Compile(v8::Handle<String> source,
   1180                               v8::Handle<Value> file_name,
   1181                               v8::Handle<String> script_data) {
   1182   ScriptOrigin origin(file_name);
   1183   return Compile(source, &origin, 0, script_data);
   1184 }
   1185 
   1186 
   1187 Local<Value> Script::Run() {
   1188   ON_BAILOUT("v8::Script::Run()", return Local<Value>());
   1189   LOG_API("Script::Run");
   1190   ENTER_V8;
   1191   i::Object* raw_result = NULL;
   1192   {
   1193     HandleScope scope;
   1194     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
   1195     if (fun->IsBoilerplate()) {
   1196       fun = i::Factory::NewFunctionFromBoilerplate(fun,
   1197                                                    i::Top::global_context());
   1198     }
   1199     EXCEPTION_PREAMBLE();
   1200     i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
   1201     i::Handle<i::Object> result =
   1202         i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
   1203     EXCEPTION_BAILOUT_CHECK(Local<Value>());
   1204     raw_result = *result;
   1205   }
   1206   i::Handle<i::Object> result(raw_result);
   1207   return Utils::ToLocal(result);
   1208 }
   1209 
   1210 
   1211 Local<Value> Script::Id() {
   1212   ON_BAILOUT("v8::Script::Id()", return Local<Value>());
   1213   LOG_API("Script::Id");
   1214   i::Object* raw_id = NULL;
   1215   {
   1216     HandleScope scope;
   1217     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
   1218     i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
   1219     i::Handle<i::Object> id(script->id());
   1220     raw_id = *id;
   1221   }
   1222   i::Handle<i::Object> id(raw_id);
   1223   return Utils::ToLocal(id);
   1224 }
   1225 
   1226 
   1227 void Script::SetData(v8::Handle<String> data) {
   1228   ON_BAILOUT("v8::Script::SetData()", return);
   1229   LOG_API("Script::SetData");
   1230   {
   1231     HandleScope scope;
   1232     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
   1233     i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
   1234     i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
   1235     script->set_data(*raw_data);
   1236   }
   1237 }
   1238 
   1239 
   1240 // --- E x c e p t i o n s ---
   1241 
   1242 
   1243 v8::TryCatch::TryCatch()
   1244     : next_(i::Top::try_catch_handler_address()),
   1245       exception_(i::Heap::the_hole_value()),
   1246       message_(i::Smi::FromInt(0)),
   1247       is_verbose_(false),
   1248       can_continue_(true),
   1249       capture_message_(true),
   1250       rethrow_(false) {
   1251   i::Top::RegisterTryCatchHandler(this);
   1252 }
   1253 
   1254 
   1255 v8::TryCatch::~TryCatch() {
   1256   if (rethrow_) {
   1257     v8::HandleScope scope;
   1258     v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
   1259     i::Top::UnregisterTryCatchHandler(this);
   1260     v8::ThrowException(exc);
   1261   } else {
   1262     i::Top::UnregisterTryCatchHandler(this);
   1263   }
   1264 }
   1265 
   1266 
   1267 bool v8::TryCatch::HasCaught() const {
   1268   return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
   1269 }
   1270 
   1271 
   1272 bool v8::TryCatch::CanContinue() const {
   1273   return can_continue_;
   1274 }
   1275 
   1276 
   1277 v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
   1278   if (!HasCaught()) return v8::Local<v8::Value>();
   1279   rethrow_ = true;
   1280   return v8::Undefined();
   1281 }
   1282 
   1283 
   1284 v8::Local<Value> v8::TryCatch::Exception() const {
   1285   if (HasCaught()) {
   1286     // Check for out of memory exception.
   1287     i::Object* exception = reinterpret_cast<i::Object*>(exception_);
   1288     return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
   1289   } else {
   1290     return v8::Local<Value>();
   1291   }
   1292 }
   1293 
   1294 
   1295 v8::Local<Value> v8::TryCatch::StackTrace() const {
   1296   if (HasCaught()) {
   1297     i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
   1298     if (!raw_obj->IsJSObject()) return v8::Local<Value>();
   1299     v8::HandleScope scope;
   1300     i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
   1301     i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
   1302     if (!obj->HasProperty(*name))
   1303       return v8::Local<Value>();
   1304     return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
   1305   } else {
   1306     return v8::Local<Value>();
   1307   }
   1308 }
   1309 
   1310 
   1311 v8::Local<v8::Message> v8::TryCatch::Message() const {
   1312   if (HasCaught() && message_ != i::Smi::FromInt(0)) {
   1313     i::Object* message = reinterpret_cast<i::Object*>(message_);
   1314     return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
   1315   } else {
   1316     return v8::Local<v8::Message>();
   1317   }
   1318 }
   1319 
   1320 
   1321 void v8::TryCatch::Reset() {
   1322   exception_ = i::Heap::the_hole_value();
   1323   message_ = i::Smi::FromInt(0);
   1324 }
   1325 
   1326 
   1327 void v8::TryCatch::SetVerbose(bool value) {
   1328   is_verbose_ = value;
   1329 }
   1330 
   1331 
   1332 void v8::TryCatch::SetCaptureMessage(bool value) {
   1333   capture_message_ = value;
   1334 }
   1335 
   1336 
   1337 // --- M e s s a g e ---
   1338 
   1339 
   1340 Local<String> Message::Get() const {
   1341   ON_BAILOUT("v8::Message::Get()", return Local<String>());
   1342   ENTER_V8;
   1343   HandleScope scope;
   1344   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1345   i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
   1346   Local<String> result = Utils::ToLocal(raw_result);
   1347   return scope.Close(result);
   1348 }
   1349 
   1350 
   1351 v8::Handle<Value> Message::GetScriptResourceName() const {
   1352   if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
   1353     return Local<String>();
   1354   }
   1355   ENTER_V8;
   1356   HandleScope scope;
   1357   i::Handle<i::JSObject> obj =
   1358       i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
   1359   // Return this.script.name.
   1360   i::Handle<i::JSValue> script =
   1361       i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
   1362   i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
   1363   return scope.Close(Utils::ToLocal(resource_name));
   1364 }
   1365 
   1366 
   1367 v8::Handle<Value> Message::GetScriptData() const {
   1368   if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
   1369     return Local<Value>();
   1370   }
   1371   ENTER_V8;
   1372   HandleScope scope;
   1373   i::Handle<i::JSObject> obj =
   1374       i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
   1375   // Return this.script.data.
   1376   i::Handle<i::JSValue> script =
   1377       i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
   1378   i::Handle<i::Object> data(i::Script::cast(script->value())->data());
   1379   return scope.Close(Utils::ToLocal(data));
   1380 }
   1381 
   1382 
   1383 static i::Handle<i::Object> CallV8HeapFunction(const char* name,
   1384                                                i::Handle<i::Object> recv,
   1385                                                int argc,
   1386                                                i::Object** argv[],
   1387                                                bool* has_pending_exception) {
   1388   i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
   1389   i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
   1390   i::Handle<i::JSFunction> fun =
   1391       i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
   1392   i::Handle<i::Object> value =
   1393       i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
   1394   return value;
   1395 }
   1396 
   1397 
   1398 static i::Handle<i::Object> CallV8HeapFunction(const char* name,
   1399                                                i::Handle<i::Object> data,
   1400                                                bool* has_pending_exception) {
   1401   i::Object** argv[1] = { data.location() };
   1402   return CallV8HeapFunction(name,
   1403                             i::Top::builtins(),
   1404                             1,
   1405                             argv,
   1406                             has_pending_exception);
   1407 }
   1408 
   1409 
   1410 int Message::GetLineNumber() const {
   1411   ON_BAILOUT("v8::Message::GetLineNumber()", return -1);
   1412   ENTER_V8;
   1413   HandleScope scope;
   1414   EXCEPTION_PREAMBLE();
   1415   i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
   1416                                                    Utils::OpenHandle(this),
   1417                                                    &has_pending_exception);
   1418   EXCEPTION_BAILOUT_CHECK(0);
   1419   return static_cast<int>(result->Number());
   1420 }
   1421 
   1422 
   1423 int Message::GetStartPosition() const {
   1424   if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
   1425   ENTER_V8;
   1426   HandleScope scope;
   1427 
   1428   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
   1429   return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
   1430 }
   1431 
   1432 
   1433 int Message::GetEndPosition() const {
   1434   if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
   1435   ENTER_V8;
   1436   HandleScope scope;
   1437   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
   1438   return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
   1439 }
   1440 
   1441 
   1442 int Message::GetStartColumn() const {
   1443   if (IsDeadCheck("v8::Message::GetStartColumn()")) return 0;
   1444   ENTER_V8;
   1445   HandleScope scope;
   1446   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
   1447   EXCEPTION_PREAMBLE();
   1448   i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
   1449       "GetPositionInLine",
   1450       data_obj,
   1451       &has_pending_exception);
   1452   EXCEPTION_BAILOUT_CHECK(0);
   1453   return static_cast<int>(start_col_obj->Number());
   1454 }
   1455 
   1456 
   1457 int Message::GetEndColumn() const {
   1458   if (IsDeadCheck("v8::Message::GetEndColumn()")) return 0;
   1459   ENTER_V8;
   1460   HandleScope scope;
   1461   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
   1462   EXCEPTION_PREAMBLE();
   1463   i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
   1464       "GetPositionInLine",
   1465       data_obj,
   1466       &has_pending_exception);
   1467   EXCEPTION_BAILOUT_CHECK(0);
   1468   int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
   1469   int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
   1470   return static_cast<int>(start_col_obj->Number()) + (end - start);
   1471 }
   1472 
   1473 
   1474 Local<String> Message::GetSourceLine() const {
   1475   ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
   1476   ENTER_V8;
   1477   HandleScope scope;
   1478   EXCEPTION_PREAMBLE();
   1479   i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
   1480                                                    Utils::OpenHandle(this),
   1481                                                    &has_pending_exception);
   1482   EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
   1483   if (result->IsString()) {
   1484     return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
   1485   } else {
   1486     return Local<String>();
   1487   }
   1488 }
   1489 
   1490 
   1491 void Message::PrintCurrentStackTrace(FILE* out) {
   1492   if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
   1493   ENTER_V8;
   1494   i::Top::PrintCurrentStackTrace(out);
   1495 }
   1496 
   1497 
   1498 // --- D a t a ---
   1499 
   1500 bool Value::IsUndefined() const {
   1501   if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
   1502   return Utils::OpenHandle(this)->IsUndefined();
   1503 }
   1504 
   1505 
   1506 bool Value::IsNull() const {
   1507   if (IsDeadCheck("v8::Value::IsNull()")) return false;
   1508   return Utils::OpenHandle(this)->IsNull();
   1509 }
   1510 
   1511 
   1512 bool Value::IsTrue() const {
   1513   if (IsDeadCheck("v8::Value::IsTrue()")) return false;
   1514   return Utils::OpenHandle(this)->IsTrue();
   1515 }
   1516 
   1517 
   1518 bool Value::IsFalse() const {
   1519   if (IsDeadCheck("v8::Value::IsFalse()")) return false;
   1520   return Utils::OpenHandle(this)->IsFalse();
   1521 }
   1522 
   1523 
   1524 bool Value::IsFunction() const {
   1525   if (IsDeadCheck("v8::Value::IsFunction()")) return false;
   1526   return Utils::OpenHandle(this)->IsJSFunction();
   1527 }
   1528 
   1529 
   1530 bool Value::FullIsString() const {
   1531   if (IsDeadCheck("v8::Value::IsString()")) return false;
   1532   bool result = Utils::OpenHandle(this)->IsString();
   1533   ASSERT_EQ(result, QuickIsString());
   1534   return result;
   1535 }
   1536 
   1537 
   1538 bool Value::IsArray() const {
   1539   if (IsDeadCheck("v8::Value::IsArray()")) return false;
   1540   return Utils::OpenHandle(this)->IsJSArray();
   1541 }
   1542 
   1543 
   1544 bool Value::IsObject() const {
   1545   if (IsDeadCheck("v8::Value::IsObject()")) return false;
   1546   return Utils::OpenHandle(this)->IsJSObject();
   1547 }
   1548 
   1549 
   1550 bool Value::IsNumber() const {
   1551   if (IsDeadCheck("v8::Value::IsNumber()")) return false;
   1552   return Utils::OpenHandle(this)->IsNumber();
   1553 }
   1554 
   1555 
   1556 bool Value::IsBoolean() const {
   1557   if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
   1558   return Utils::OpenHandle(this)->IsBoolean();
   1559 }
   1560 
   1561 
   1562 bool Value::IsExternal() const {
   1563   if (IsDeadCheck("v8::Value::IsExternal()")) return false;
   1564   return Utils::OpenHandle(this)->IsProxy();
   1565 }
   1566 
   1567 
   1568 bool Value::IsInt32() const {
   1569   if (IsDeadCheck("v8::Value::IsInt32()")) return false;
   1570   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1571   if (obj->IsSmi()) return true;
   1572   if (obj->IsNumber()) {
   1573     double value = obj->Number();
   1574     return i::FastI2D(i::FastD2I(value)) == value;
   1575   }
   1576   return false;
   1577 }
   1578 
   1579 
   1580 bool Value::IsDate() const {
   1581   if (IsDeadCheck("v8::Value::IsDate()")) return false;
   1582   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1583   return obj->HasSpecificClassOf(i::Heap::Date_symbol());
   1584 }
   1585 
   1586 
   1587 Local<String> Value::ToString() const {
   1588   if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
   1589   LOG_API("ToString");
   1590   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1591   i::Handle<i::Object> str;
   1592   if (obj->IsString()) {
   1593     str = obj;
   1594   } else {
   1595     ENTER_V8;
   1596     EXCEPTION_PREAMBLE();
   1597     str = i::Execution::ToString(obj, &has_pending_exception);
   1598     EXCEPTION_BAILOUT_CHECK(Local<String>());
   1599   }
   1600   return Local<String>(ToApi<String>(str));
   1601 }
   1602 
   1603 
   1604 Local<String> Value::ToDetailString() const {
   1605   if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
   1606   LOG_API("ToDetailString");
   1607   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1608   i::Handle<i::Object> str;
   1609   if (obj->IsString()) {
   1610     str = obj;
   1611   } else {
   1612     ENTER_V8;
   1613     EXCEPTION_PREAMBLE();
   1614     str = i::Execution::ToDetailString(obj, &has_pending_exception);
   1615     EXCEPTION_BAILOUT_CHECK(Local<String>());
   1616   }
   1617   return Local<String>(ToApi<String>(str));
   1618 }
   1619 
   1620 
   1621 Local<v8::Object> Value::ToObject() const {
   1622   if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
   1623   LOG_API("ToObject");
   1624   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1625   i::Handle<i::Object> val;
   1626   if (obj->IsJSObject()) {
   1627     val = obj;
   1628   } else {
   1629     ENTER_V8;
   1630     EXCEPTION_PREAMBLE();
   1631     val = i::Execution::ToObject(obj, &has_pending_exception);
   1632     EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
   1633   }
   1634   return Local<v8::Object>(ToApi<Object>(val));
   1635 }
   1636 
   1637 
   1638 Local<Boolean> Value::ToBoolean() const {
   1639   if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
   1640   LOG_API("ToBoolean");
   1641   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1642   if (obj->IsBoolean()) {
   1643     return Local<Boolean>(ToApi<Boolean>(obj));
   1644   } else {
   1645     ENTER_V8;
   1646     i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
   1647     return Local<Boolean>(ToApi<Boolean>(val));
   1648   }
   1649 }
   1650 
   1651 
   1652 Local<Number> Value::ToNumber() const {
   1653   if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
   1654   LOG_API("ToNumber");
   1655   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1656   i::Handle<i::Object> num;
   1657   if (obj->IsNumber()) {
   1658     num = obj;
   1659   } else {
   1660     ENTER_V8;
   1661     EXCEPTION_PREAMBLE();
   1662     num = i::Execution::ToNumber(obj, &has_pending_exception);
   1663     EXCEPTION_BAILOUT_CHECK(Local<Number>());
   1664   }
   1665   return Local<Number>(ToApi<Number>(num));
   1666 }
   1667 
   1668 
   1669 Local<Integer> Value::ToInteger() const {
   1670   if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
   1671   LOG_API("ToInteger");
   1672   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1673   i::Handle<i::Object> num;
   1674   if (obj->IsSmi()) {
   1675     num = obj;
   1676   } else {
   1677     ENTER_V8;
   1678     EXCEPTION_PREAMBLE();
   1679     num = i::Execution::ToInteger(obj, &has_pending_exception);
   1680     EXCEPTION_BAILOUT_CHECK(Local<Integer>());
   1681   }
   1682   return Local<Integer>(ToApi<Integer>(num));
   1683 }
   1684 
   1685 
   1686 void External::CheckCast(v8::Value* that) {
   1687   if (IsDeadCheck("v8::External::Cast()")) return;
   1688   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   1689   ApiCheck(obj->IsProxy(),
   1690            "v8::External::Cast()",
   1691            "Could not convert to external");
   1692 }
   1693 
   1694 
   1695 void v8::Object::CheckCast(Value* that) {
   1696   if (IsDeadCheck("v8::Object::Cast()")) return;
   1697   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   1698   ApiCheck(obj->IsJSObject(),
   1699            "v8::Object::Cast()",
   1700            "Could not convert to object");
   1701 }
   1702 
   1703 
   1704 void v8::Function::CheckCast(Value* that) {
   1705   if (IsDeadCheck("v8::Function::Cast()")) return;
   1706   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   1707   ApiCheck(obj->IsJSFunction(),
   1708            "v8::Function::Cast()",
   1709            "Could not convert to function");
   1710 }
   1711 
   1712 
   1713 void v8::String::CheckCast(v8::Value* that) {
   1714   if (IsDeadCheck("v8::String::Cast()")) return;
   1715   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   1716   ApiCheck(obj->IsString(),
   1717            "v8::String::Cast()",
   1718            "Could not convert to string");
   1719 }
   1720 
   1721 
   1722 void v8::Number::CheckCast(v8::Value* that) {
   1723   if (IsDeadCheck("v8::Number::Cast()")) return;
   1724   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   1725   ApiCheck(obj->IsNumber(),
   1726            "v8::Number::Cast()",
   1727            "Could not convert to number");
   1728 }
   1729 
   1730 
   1731 void v8::Integer::CheckCast(v8::Value* that) {
   1732   if (IsDeadCheck("v8::Integer::Cast()")) return;
   1733   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   1734   ApiCheck(obj->IsNumber(),
   1735            "v8::Integer::Cast()",
   1736            "Could not convert to number");
   1737 }
   1738 
   1739 
   1740 void v8::Array::CheckCast(Value* that) {
   1741   if (IsDeadCheck("v8::Array::Cast()")) return;
   1742   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   1743   ApiCheck(obj->IsJSArray(),
   1744            "v8::Array::Cast()",
   1745            "Could not convert to array");
   1746 }
   1747 
   1748 
   1749 void v8::Date::CheckCast(v8::Value* that) {
   1750   if (IsDeadCheck("v8::Date::Cast()")) return;
   1751   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   1752   ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
   1753            "v8::Date::Cast()",
   1754            "Could not convert to date");
   1755 }
   1756 
   1757 
   1758 bool Value::BooleanValue() const {
   1759   if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
   1760   LOG_API("BooleanValue");
   1761   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1762   if (obj->IsBoolean()) {
   1763     return obj->IsTrue();
   1764   } else {
   1765     ENTER_V8;
   1766     i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
   1767     return value->IsTrue();
   1768   }
   1769 }
   1770 
   1771 
   1772 double Value::NumberValue() const {
   1773   if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
   1774   LOG_API("NumberValue");
   1775   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1776   i::Handle<i::Object> num;
   1777   if (obj->IsNumber()) {
   1778     num = obj;
   1779   } else {
   1780     ENTER_V8;
   1781     EXCEPTION_PREAMBLE();
   1782     num = i::Execution::ToNumber(obj, &has_pending_exception);
   1783     EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
   1784   }
   1785   return num->Number();
   1786 }
   1787 
   1788 
   1789 int64_t Value::IntegerValue() const {
   1790   if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
   1791   LOG_API("IntegerValue");
   1792   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1793   i::Handle<i::Object> num;
   1794   if (obj->IsNumber()) {
   1795     num = obj;
   1796   } else {
   1797     ENTER_V8;
   1798     EXCEPTION_PREAMBLE();
   1799     num = i::Execution::ToInteger(obj, &has_pending_exception);
   1800     EXCEPTION_BAILOUT_CHECK(0);
   1801   }
   1802   if (num->IsSmi()) {
   1803     return i::Smi::cast(*num)->value();
   1804   } else {
   1805     return static_cast<int64_t>(num->Number());
   1806   }
   1807 }
   1808 
   1809 
   1810 Local<Int32> Value::ToInt32() const {
   1811   if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
   1812   LOG_API("ToInt32");
   1813   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1814   i::Handle<i::Object> num;
   1815   if (obj->IsSmi()) {
   1816     num = obj;
   1817   } else {
   1818     ENTER_V8;
   1819     EXCEPTION_PREAMBLE();
   1820     num = i::Execution::ToInt32(obj, &has_pending_exception);
   1821     EXCEPTION_BAILOUT_CHECK(Local<Int32>());
   1822   }
   1823   return Local<Int32>(ToApi<Int32>(num));
   1824 }
   1825 
   1826 
   1827 Local<Uint32> Value::ToUint32() const {
   1828   if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
   1829   LOG_API("ToUInt32");
   1830   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1831   i::Handle<i::Object> num;
   1832   if (obj->IsSmi()) {
   1833     num = obj;
   1834   } else {
   1835     ENTER_V8;
   1836     EXCEPTION_PREAMBLE();
   1837     num = i::Execution::ToUint32(obj, &has_pending_exception);
   1838     EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
   1839   }
   1840   return Local<Uint32>(ToApi<Uint32>(num));
   1841 }
   1842 
   1843 
   1844 Local<Uint32> Value::ToArrayIndex() const {
   1845   if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
   1846   LOG_API("ToArrayIndex");
   1847   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1848   if (obj->IsSmi()) {
   1849     if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
   1850     return Local<Uint32>();
   1851   }
   1852   ENTER_V8;
   1853   EXCEPTION_PREAMBLE();
   1854   i::Handle<i::Object> string_obj =
   1855       i::Execution::ToString(obj, &has_pending_exception);
   1856   EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
   1857   i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
   1858   uint32_t index;
   1859   if (str->AsArrayIndex(&index)) {
   1860     i::Handle<i::Object> value;
   1861     if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
   1862       value = i::Handle<i::Object>(i::Smi::FromInt(index));
   1863     } else {
   1864       value = i::Factory::NewNumber(index);
   1865     }
   1866     return Utils::Uint32ToLocal(value);
   1867   }
   1868   return Local<Uint32>();
   1869 }
   1870 
   1871 
   1872 int32_t Value::Int32Value() const {
   1873   if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
   1874   LOG_API("Int32Value");
   1875   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1876   if (obj->IsSmi()) {
   1877     return i::Smi::cast(*obj)->value();
   1878   } else {
   1879     LOG_API("Int32Value (slow)");
   1880     ENTER_V8;
   1881     EXCEPTION_PREAMBLE();
   1882     i::Handle<i::Object> num =
   1883         i::Execution::ToInt32(obj, &has_pending_exception);
   1884     EXCEPTION_BAILOUT_CHECK(0);
   1885     if (num->IsSmi()) {
   1886       return i::Smi::cast(*num)->value();
   1887     } else {
   1888       return static_cast<int32_t>(num->Number());
   1889     }
   1890   }
   1891 }
   1892 
   1893 
   1894 bool Value::Equals(Handle<Value> that) const {
   1895   if (IsDeadCheck("v8::Value::Equals()")
   1896       || EmptyCheck("v8::Value::Equals()", this)
   1897       || EmptyCheck("v8::Value::Equals()", that)) {
   1898     return false;
   1899   }
   1900   LOG_API("Equals");
   1901   ENTER_V8;
   1902   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1903   i::Handle<i::Object> other = Utils::OpenHandle(*that);
   1904   i::Object** args[1] = { other.location() };
   1905   EXCEPTION_PREAMBLE();
   1906   i::Handle<i::Object> result =
   1907       CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
   1908   EXCEPTION_BAILOUT_CHECK(false);
   1909   return *result == i::Smi::FromInt(i::EQUAL);
   1910 }
   1911 
   1912 
   1913 bool Value::StrictEquals(Handle<Value> that) const {
   1914   if (IsDeadCheck("v8::Value::StrictEquals()")
   1915       || EmptyCheck("v8::Value::StrictEquals()", this)
   1916       || EmptyCheck("v8::Value::StrictEquals()", that)) {
   1917     return false;
   1918   }
   1919   LOG_API("StrictEquals");
   1920   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1921   i::Handle<i::Object> other = Utils::OpenHandle(*that);
   1922   // Must check HeapNumber first, since NaN !== NaN.
   1923   if (obj->IsHeapNumber()) {
   1924     if (!other->IsNumber()) return false;
   1925     double x = obj->Number();
   1926     double y = other->Number();
   1927     // Must check explicitly for NaN:s on Windows, but -0 works fine.
   1928     return x == y && !isnan(x) && !isnan(y);
   1929   } else if (*obj == *other) {  // Also covers Booleans.
   1930     return true;
   1931   } else if (obj->IsSmi()) {
   1932     return other->IsNumber() && obj->Number() == other->Number();
   1933   } else if (obj->IsString()) {
   1934     return other->IsString() &&
   1935       i::String::cast(*obj)->Equals(i::String::cast(*other));
   1936   } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
   1937     return other->IsUndefined() || other->IsUndetectableObject();
   1938   } else {
   1939     return false;
   1940   }
   1941 }
   1942 
   1943 
   1944 uint32_t Value::Uint32Value() const {
   1945   if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
   1946   LOG_API("Uint32Value");
   1947   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   1948   if (obj->IsSmi()) {
   1949     return i::Smi::cast(*obj)->value();
   1950   } else {
   1951     ENTER_V8;
   1952     EXCEPTION_PREAMBLE();
   1953     i::Handle<i::Object> num =
   1954         i::Execution::ToUint32(obj, &has_pending_exception);
   1955     EXCEPTION_BAILOUT_CHECK(0);
   1956     if (num->IsSmi()) {
   1957       return i::Smi::cast(*num)->value();
   1958     } else {
   1959       return static_cast<uint32_t>(num->Number());
   1960     }
   1961   }
   1962 }
   1963 
   1964 
   1965 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
   1966                      v8::PropertyAttribute attribs) {
   1967   ON_BAILOUT("v8::Object::Set()", return false);
   1968   ENTER_V8;
   1969   HandleScope scope;
   1970   i::Handle<i::Object> self = Utils::OpenHandle(this);
   1971   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
   1972   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
   1973   EXCEPTION_PREAMBLE();
   1974   i::Handle<i::Object> obj = i::SetProperty(
   1975       self,
   1976       key_obj,
   1977       value_obj,
   1978       static_cast<PropertyAttributes>(attribs));
   1979   has_pending_exception = obj.is_null();
   1980   EXCEPTION_BAILOUT_CHECK(false);
   1981   return true;
   1982 }
   1983 
   1984 
   1985 bool v8::Object::ForceSet(v8::Handle<Value> key,
   1986                           v8::Handle<Value> value,
   1987                           v8::PropertyAttribute attribs) {
   1988   ON_BAILOUT("v8::Object::ForceSet()", return false);
   1989   ENTER_V8;
   1990   HandleScope scope;
   1991   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   1992   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
   1993   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
   1994   EXCEPTION_PREAMBLE();
   1995   i::Handle<i::Object> obj = i::ForceSetProperty(
   1996       self,
   1997       key_obj,
   1998       value_obj,
   1999       static_cast<PropertyAttributes>(attribs));
   2000   has_pending_exception = obj.is_null();
   2001   EXCEPTION_BAILOUT_CHECK(false);
   2002   return true;
   2003 }
   2004 
   2005 
   2006 bool v8::Object::ForceDelete(v8::Handle<Value> key) {
   2007   ON_BAILOUT("v8::Object::ForceDelete()", return false);
   2008   ENTER_V8;
   2009   HandleScope scope;
   2010   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2011   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
   2012   EXCEPTION_PREAMBLE();
   2013   i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
   2014   has_pending_exception = obj.is_null();
   2015   EXCEPTION_BAILOUT_CHECK(false);
   2016   return obj->IsTrue();
   2017 }
   2018 
   2019 
   2020 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
   2021   ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
   2022   ENTER_V8;
   2023   i::Handle<i::Object> self = Utils::OpenHandle(this);
   2024   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
   2025   EXCEPTION_PREAMBLE();
   2026   i::Handle<i::Object> result = i::GetProperty(self, key_obj);
   2027   has_pending_exception = result.is_null();
   2028   EXCEPTION_BAILOUT_CHECK(Local<Value>());
   2029   return Utils::ToLocal(result);
   2030 }
   2031 
   2032 
   2033 Local<Value> v8::Object::GetPrototype() {
   2034   ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
   2035   ENTER_V8;
   2036   i::Handle<i::Object> self = Utils::OpenHandle(this);
   2037   i::Handle<i::Object> result = i::GetPrototype(self);
   2038   return Utils::ToLocal(result);
   2039 }
   2040 
   2041 
   2042 bool v8::Object::SetPrototype(Handle<Value> value) {
   2043   ON_BAILOUT("v8::Object::SetPrototype()", return false);
   2044   ENTER_V8;
   2045   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2046   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
   2047   EXCEPTION_PREAMBLE();
   2048   i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
   2049   has_pending_exception = result.is_null();
   2050   EXCEPTION_BAILOUT_CHECK(false);
   2051   return true;
   2052 }
   2053 
   2054 
   2055 Local<Object> v8::Object::FindInstanceInPrototypeChain(
   2056     v8::Handle<FunctionTemplate> tmpl) {
   2057   ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
   2058              return Local<v8::Object>());
   2059   ENTER_V8;
   2060   i::JSObject* object = *Utils::OpenHandle(this);
   2061   i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
   2062   while (!object->IsInstanceOf(tmpl_info)) {
   2063     i::Object* prototype = object->GetPrototype();
   2064     if (!prototype->IsJSObject()) return Local<Object>();
   2065     object = i::JSObject::cast(prototype);
   2066   }
   2067   return Utils::ToLocal(i::Handle<i::JSObject>(object));
   2068 }
   2069 
   2070 
   2071 Local<Array> v8::Object::GetPropertyNames() {
   2072   ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
   2073   ENTER_V8;
   2074   v8::HandleScope scope;
   2075   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2076   i::Handle<i::FixedArray> value =
   2077       i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
   2078   // Because we use caching to speed up enumeration it is important
   2079   // to never change the result of the basic enumeration function so
   2080   // we clone the result.
   2081   i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
   2082   i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
   2083   return scope.Close(Utils::ToLocal(result));
   2084 }
   2085 
   2086 
   2087 Local<String> v8::Object::ObjectProtoToString() {
   2088   ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
   2089   ENTER_V8;
   2090   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2091 
   2092   i::Handle<i::Object> name(self->class_name());
   2093 
   2094   // Native implementation of Object.prototype.toString (v8natives.js):
   2095   //   var c = %ClassOf(this);
   2096   //   if (c === 'Arguments') c  = 'Object';
   2097   //   return "[object " + c + "]";
   2098 
   2099   if (!name->IsString()) {
   2100     return v8::String::New("[object ]");
   2101 
   2102   } else {
   2103     i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
   2104     if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
   2105       return v8::String::New("[object Object]");
   2106 
   2107     } else {
   2108       const char* prefix = "[object ";
   2109       Local<String> str = Utils::ToLocal(class_name);
   2110       const char* postfix = "]";
   2111 
   2112       int prefix_len = i::StrLength(prefix);
   2113       int str_len = str->Length();
   2114       int postfix_len = i::StrLength(postfix);
   2115 
   2116       int buf_len = prefix_len + str_len + postfix_len;
   2117       char* buf = i::NewArray<char>(buf_len);
   2118 
   2119       // Write prefix.
   2120       char* ptr = buf;
   2121       memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
   2122       ptr += prefix_len;
   2123 
   2124       // Write real content.
   2125       str->WriteAscii(ptr, 0, str_len);
   2126       ptr += str_len;
   2127 
   2128       // Write postfix.
   2129       memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
   2130 
   2131       // Copy the buffer into a heap-allocated string and return it.
   2132       Local<String> result = v8::String::New(buf, buf_len);
   2133       i::DeleteArray(buf);
   2134       return result;
   2135     }
   2136   }
   2137 }
   2138 
   2139 
   2140 bool v8::Object::Delete(v8::Handle<String> key) {
   2141   ON_BAILOUT("v8::Object::Delete()", return false);
   2142   ENTER_V8;
   2143   HandleScope scope;
   2144   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2145   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   2146   return i::DeleteProperty(self, key_obj)->IsTrue();
   2147 }
   2148 
   2149 
   2150 bool v8::Object::Has(v8::Handle<String> key) {
   2151   ON_BAILOUT("v8::Object::Has()", return false);
   2152   ENTER_V8;
   2153   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2154   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   2155   return self->HasProperty(*key_obj);
   2156 }
   2157 
   2158 
   2159 bool v8::Object::Delete(uint32_t index) {
   2160   ON_BAILOUT("v8::Object::DeleteProperty()", return false);
   2161   ENTER_V8;
   2162   HandleScope scope;
   2163   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2164   return i::DeleteElement(self, index)->IsTrue();
   2165 }
   2166 
   2167 
   2168 bool v8::Object::Has(uint32_t index) {
   2169   ON_BAILOUT("v8::Object::HasProperty()", return false);
   2170   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2171   return self->HasElement(index);
   2172 }
   2173 
   2174 
   2175 bool v8::Object::HasRealNamedProperty(Handle<String> key) {
   2176   ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
   2177   return Utils::OpenHandle(this)->HasRealNamedProperty(
   2178       *Utils::OpenHandle(*key));
   2179 }
   2180 
   2181 
   2182 bool v8::Object::HasRealIndexedProperty(uint32_t index) {
   2183   ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
   2184   return Utils::OpenHandle(this)->HasRealElementProperty(index);
   2185 }
   2186 
   2187 
   2188 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
   2189   ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
   2190   ENTER_V8;
   2191   return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
   2192       *Utils::OpenHandle(*key));
   2193 }
   2194 
   2195 
   2196 bool v8::Object::HasNamedLookupInterceptor() {
   2197   ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
   2198   return Utils::OpenHandle(this)->HasNamedInterceptor();
   2199 }
   2200 
   2201 
   2202 bool v8::Object::HasIndexedLookupInterceptor() {
   2203   ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
   2204   return Utils::OpenHandle(this)->HasIndexedInterceptor();
   2205 }
   2206 
   2207 
   2208 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
   2209       Handle<String> key) {
   2210   ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
   2211              return Local<Value>());
   2212   ENTER_V8;
   2213   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
   2214   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   2215   i::LookupResult lookup;
   2216   self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
   2217   if (lookup.IsProperty()) {
   2218     PropertyAttributes attributes;
   2219     i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
   2220                                                       &lookup,
   2221                                                       *key_obj,
   2222                                                       &attributes));
   2223     return Utils::ToLocal(result);
   2224   }
   2225   return Local<Value>();  // No real property was found in prototype chain.
   2226 }
   2227 
   2228 
   2229 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
   2230   ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
   2231   ENTER_V8;
   2232   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
   2233   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   2234   i::LookupResult lookup;
   2235   self_obj->LookupRealNamedProperty(*key_obj, &lookup);
   2236   if (lookup.IsProperty()) {
   2237     PropertyAttributes attributes;
   2238     i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
   2239                                                       &lookup,
   2240                                                       *key_obj,
   2241                                                       &attributes));
   2242     return Utils::ToLocal(result);
   2243   }
   2244   return Local<Value>();  // No real property was found in prototype chain.
   2245 }
   2246 
   2247 
   2248 // Turns on access checks by copying the map and setting the check flag.
   2249 // Because the object gets a new map, existing inline cache caching
   2250 // the old map of this object will fail.
   2251 void v8::Object::TurnOnAccessCheck() {
   2252   ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
   2253   ENTER_V8;
   2254   HandleScope scope;
   2255   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
   2256 
   2257   i::Handle<i::Map> new_map =
   2258     i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
   2259   new_map->set_is_access_check_needed(true);
   2260   obj->set_map(*new_map);
   2261 }
   2262 
   2263 
   2264 bool v8::Object::IsDirty() {
   2265   return Utils::OpenHandle(this)->IsDirty();
   2266 }
   2267 
   2268 
   2269 Local<v8::Object> v8::Object::Clone() {
   2270   ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
   2271   ENTER_V8;
   2272   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2273   EXCEPTION_PREAMBLE();
   2274   i::Handle<i::JSObject> result = i::Copy(self);
   2275   has_pending_exception = result.is_null();
   2276   EXCEPTION_BAILOUT_CHECK(Local<Object>());
   2277   return Utils::ToLocal(result);
   2278 }
   2279 
   2280 
   2281 int v8::Object::GetIdentityHash() {
   2282   ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
   2283   ENTER_V8;
   2284   HandleScope scope;
   2285   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2286   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
   2287   i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
   2288   i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
   2289   int hash_value;
   2290   if (hash->IsSmi()) {
   2291     hash_value = i::Smi::cast(*hash)->value();
   2292   } else {
   2293     int attempts = 0;
   2294     do {
   2295       // Generate a random 32-bit hash value but limit range to fit
   2296       // within a smi.
   2297       hash_value = i::V8::Random() & i::Smi::kMaxValue;
   2298       attempts++;
   2299     } while (hash_value == 0 && attempts < 30);
   2300     hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
   2301     i::SetProperty(hidden_props,
   2302                    hash_symbol,
   2303                    i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
   2304                    static_cast<PropertyAttributes>(None));
   2305   }
   2306   return hash_value;
   2307 }
   2308 
   2309 
   2310 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
   2311                                 v8::Handle<v8::Value> value) {
   2312   ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
   2313   ENTER_V8;
   2314   HandleScope scope;
   2315   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2316   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
   2317   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
   2318   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
   2319   EXCEPTION_PREAMBLE();
   2320   i::Handle<i::Object> obj = i::SetProperty(
   2321       hidden_props,
   2322       key_obj,
   2323       value_obj,
   2324       static_cast<PropertyAttributes>(None));
   2325   has_pending_exception = obj.is_null();
   2326   EXCEPTION_BAILOUT_CHECK(false);
   2327   return true;
   2328 }
   2329 
   2330 
   2331 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
   2332   ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
   2333   ENTER_V8;
   2334   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2335   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
   2336   if (hidden_props->IsUndefined()) {
   2337     return v8::Local<v8::Value>();
   2338   }
   2339   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   2340   EXCEPTION_PREAMBLE();
   2341   i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
   2342   has_pending_exception = result.is_null();
   2343   EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
   2344   if (result->IsUndefined()) {
   2345     return v8::Local<v8::Value>();
   2346   }
   2347   return Utils::ToLocal(result);
   2348 }
   2349 
   2350 
   2351 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
   2352   ON_BAILOUT("v8::DeleteHiddenValue()", return false);
   2353   ENTER_V8;
   2354   HandleScope scope;
   2355   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2356   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
   2357   if (hidden_props->IsUndefined()) {
   2358     return true;
   2359   }
   2360   i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
   2361   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   2362   return i::DeleteProperty(js_obj, key_obj)->IsTrue();
   2363 }
   2364 
   2365 
   2366 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
   2367   ON_BAILOUT("v8::SetElementsToPixelData()", return);
   2368   ENTER_V8;
   2369   HandleScope scope;
   2370   if (!ApiCheck(length <= i::PixelArray::kMaxLength,
   2371                 "v8::Object::SetIndexedPropertiesToPixelData()",
   2372                 "length exceeds max acceptable value")) {
   2373     return;
   2374   }
   2375   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2376   if (!ApiCheck(!self->IsJSArray(),
   2377                 "v8::Object::SetIndexedPropertiesToPixelData()",
   2378                 "JSArray is not supported")) {
   2379     return;
   2380   }
   2381   i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
   2382   self->set_elements(*pixels);
   2383 }
   2384 
   2385 
   2386 void v8::Object::SetIndexedPropertiesToExternalArrayData(
   2387     void* data,
   2388     ExternalArrayType array_type,
   2389     int length) {
   2390   ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
   2391   ENTER_V8;
   2392   HandleScope scope;
   2393   if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
   2394                 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
   2395                 "length exceeds max acceptable value")) {
   2396     return;
   2397   }
   2398   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   2399   if (!ApiCheck(!self->IsJSArray(),
   2400                 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
   2401                 "JSArray is not supported")) {
   2402     return;
   2403   }
   2404   i::Handle<i::ExternalArray> array =
   2405       i::Factory::NewExternalArray(length, array_type, data);
   2406   self->set_elements(*array);
   2407 }
   2408 
   2409 
   2410 Local<v8::Object> Function::NewInstance() const {
   2411   return NewInstance(0, NULL);
   2412 }
   2413 
   2414 
   2415 Local<v8::Object> Function::NewInstance(int argc,
   2416                                         v8::Handle<v8::Value> argv[]) const {
   2417   ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
   2418   LOG_API("Function::NewInstance");
   2419   ENTER_V8;
   2420   HandleScope scope;
   2421   i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
   2422   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
   2423   i::Object*** args = reinterpret_cast<i::Object***>(argv);
   2424   EXCEPTION_PREAMBLE();
   2425   i::Handle<i::Object> returned =
   2426       i::Execution::New(function, argc, args, &has_pending_exception);
   2427   EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
   2428   return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
   2429 }
   2430 
   2431 
   2432 Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
   2433                                 v8::Handle<v8::Value> argv[]) {
   2434   ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
   2435   LOG_API("Function::Call");
   2436   ENTER_V8;
   2437   i::Object* raw_result = NULL;
   2438   {
   2439     HandleScope scope;
   2440     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
   2441     i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
   2442     STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
   2443     i::Object*** args = reinterpret_cast<i::Object***>(argv);
   2444     EXCEPTION_PREAMBLE();
   2445     i::Handle<i::Object> returned =
   2446         i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
   2447     EXCEPTION_BAILOUT_CHECK(Local<Object>());
   2448     raw_result = *returned;
   2449   }
   2450   i::Handle<i::Object> result(raw_result);
   2451   return Utils::ToLocal(result);
   2452 }
   2453 
   2454 
   2455 void Function::SetName(v8::Handle<v8::String> name) {
   2456   ENTER_V8;
   2457   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
   2458   func->shared()->set_name(*Utils::OpenHandle(*name));
   2459 }
   2460 
   2461 
   2462 Handle<Value> Function::GetName() const {
   2463   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
   2464   return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
   2465 }
   2466 
   2467 
   2468 ScriptOrigin Function::GetScriptOrigin() const {
   2469   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
   2470   if (func->shared()->script()->IsScript()) {
   2471     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
   2472     v8::ScriptOrigin origin(
   2473       Utils::ToLocal(i::Handle<i::Object>(script->name())),
   2474       v8::Integer::New(script->line_offset()->value()),
   2475       v8::Integer::New(script->column_offset()->value()));
   2476     return origin;
   2477   }
   2478   return v8::ScriptOrigin(Handle<Value>());
   2479 }
   2480 
   2481 
   2482 const int Function::kLineOffsetNotFound = -1;
   2483 
   2484 
   2485 int Function::GetScriptLineNumber() const {
   2486   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
   2487   if (func->shared()->script()->IsScript()) {
   2488     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
   2489     return i::GetScriptLineNumber(script, func->shared()->start_position());
   2490   }
   2491   return kLineOffsetNotFound;
   2492 }
   2493 
   2494 
   2495 namespace {
   2496 
   2497 // Tracks string usage to help make better decisions when
   2498 // externalizing strings.
   2499 //
   2500 // Implementation note: internally this class only tracks fresh
   2501 // strings and keeps a single use counter for them.
   2502 class StringTracker {
   2503  public:
   2504   // Records that the given string's characters were copied to some
   2505   // external buffer. If this happens often we should honor
   2506   // externalization requests for the string.
   2507   static void RecordWrite(i::Handle<i::String> string) {
   2508     i::Address address = reinterpret_cast<i::Address>(*string);
   2509     i::Address top = i::Heap::NewSpaceTop();
   2510     if (IsFreshString(address, top)) {
   2511       IncrementUseCount(top);
   2512     }
   2513   }
   2514 
   2515   // Estimates freshness and use frequency of the given string based
   2516   // on how close it is to the new space top and the recorded usage
   2517   // history.
   2518   static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
   2519     i::Address address = reinterpret_cast<i::Address>(*string);
   2520     i::Address top = i::Heap::NewSpaceTop();
   2521     return IsFreshString(address, top) && IsUseCountLow(top);
   2522   }
   2523 
   2524  private:
   2525   static inline bool IsFreshString(i::Address string, i::Address top) {
   2526     return top - kFreshnessLimit <= string && string <= top;
   2527   }
   2528 
   2529   static inline bool IsUseCountLow(i::Address top) {
   2530     if (last_top_ != top) return true;
   2531     return use_count_ < kUseLimit;
   2532   }
   2533 
   2534   static inline void IncrementUseCount(i::Address top) {
   2535     if (last_top_ != top) {
   2536       use_count_ = 0;
   2537       last_top_ = top;
   2538     }
   2539     ++use_count_;
   2540   }
   2541 
   2542   // How close to the new space top a fresh string has to be.
   2543   static const int kFreshnessLimit = 1024;
   2544 
   2545   // The number of uses required to consider a string useful.
   2546   static const int kUseLimit = 32;
   2547 
   2548   // Single use counter shared by all fresh strings.
   2549   static int use_count_;
   2550 
   2551   // Last new space top when the use count above was valid.
   2552   static i::Address last_top_;
   2553 };
   2554 
   2555 int StringTracker::use_count_ = 0;
   2556 i::Address StringTracker::last_top_ = NULL;
   2557 
   2558 }  // namespace
   2559 
   2560 
   2561 int String::Length() const {
   2562   if (IsDeadCheck("v8::String::Length()")) return 0;
   2563   return Utils::OpenHandle(this)->length();
   2564 }
   2565 
   2566 
   2567 int String::Utf8Length() const {
   2568   if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
   2569   return Utils::OpenHandle(this)->Utf8Length();
   2570 }
   2571 
   2572 
   2573 int String::WriteUtf8(char* buffer, int capacity) const {
   2574   if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
   2575   LOG_API("String::WriteUtf8");
   2576   ENTER_V8;
   2577   i::Handle<i::String> str = Utils::OpenHandle(this);
   2578   StringTracker::RecordWrite(str);
   2579   write_input_buffer.Reset(0, *str);
   2580   int len = str->length();
   2581   // Encode the first K - 3 bytes directly into the buffer since we
   2582   // know there's room for them.  If no capacity is given we copy all
   2583   // of them here.
   2584   int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
   2585   int i;
   2586   int pos = 0;
   2587   for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
   2588     i::uc32 c = write_input_buffer.GetNext();
   2589     int written = unibrow::Utf8::Encode(buffer + pos, c);
   2590     pos += written;
   2591   }
   2592   if (i < len) {
   2593     // For the last characters we need to check the length for each one
   2594     // because they may be longer than the remaining space in the
   2595     // buffer.
   2596     char intermediate[unibrow::Utf8::kMaxEncodedSize];
   2597     for (; i < len && pos < capacity; i++) {
   2598       i::uc32 c = write_input_buffer.GetNext();
   2599       int written = unibrow::Utf8::Encode(intermediate, c);
   2600       if (pos + written <= capacity) {
   2601         for (int j = 0; j < written; j++)
   2602           buffer[pos + j] = intermediate[j];
   2603         pos += written;
   2604       } else {
   2605         // We've reached the end of the buffer
   2606         break;
   2607       }
   2608     }
   2609   }
   2610   if (i == len && (capacity == -1 || pos < capacity))
   2611     buffer[pos++] = '\0';
   2612   return pos;
   2613 }
   2614 
   2615 
   2616 int String::WriteAscii(char* buffer, int start, int length) const {
   2617   if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
   2618   LOG_API("String::WriteAscii");
   2619   ENTER_V8;
   2620   ASSERT(start >= 0 && length >= -1);
   2621   i::Handle<i::String> str = Utils::OpenHandle(this);
   2622   StringTracker::RecordWrite(str);
   2623   // Flatten the string for efficiency.  This applies whether we are
   2624   // using StringInputBuffer or Get(i) to access the characters.
   2625   str->TryFlattenIfNotFlat();
   2626   int end = length;
   2627   if ( (length == -1) || (length > str->length() - start) )
   2628     end = str->length() - start;
   2629   if (end < 0) return 0;
   2630   write_input_buffer.Reset(start, *str);
   2631   int i;
   2632   for (i = 0; i < end; i++) {
   2633     char c = static_cast<char>(write_input_buffer.GetNext());
   2634     if (c == '\0') c = ' ';
   2635     buffer[i] = c;
   2636   }
   2637   if (length == -1 || i < length)
   2638     buffer[i] = '\0';
   2639   return i;
   2640 }
   2641 
   2642 
   2643 int String::Write(uint16_t* buffer, int start, int length) const {
   2644   if (IsDeadCheck("v8::String::Write()")) return 0;
   2645   LOG_API("String::Write");
   2646   ENTER_V8;
   2647   ASSERT(start >= 0 && length >= -1);
   2648   i::Handle<i::String> str = Utils::OpenHandle(this);
   2649   StringTracker::RecordWrite(str);
   2650   int end = length;
   2651   if ( (length == -1) || (length > str->length() - start) )
   2652     end = str->length() - start;
   2653   if (end < 0) return 0;
   2654   i::String::WriteToFlat(*str, buffer, start, end);
   2655   if (length == -1 || end < length)
   2656     buffer[end] = '\0';
   2657   return end;
   2658 }
   2659 
   2660 
   2661 bool v8::String::IsExternal() const {
   2662   EnsureInitialized("v8::String::IsExternal()");
   2663   i::Handle<i::String> str = Utils::OpenHandle(this);
   2664   return i::StringShape(*str).IsExternalTwoByte();
   2665 }
   2666 
   2667 
   2668 bool v8::String::IsExternalAscii() const {
   2669   EnsureInitialized("v8::String::IsExternalAscii()");
   2670   i::Handle<i::String> str = Utils::OpenHandle(this);
   2671   return i::StringShape(*str).IsExternalAscii();
   2672 }
   2673 
   2674 
   2675 void v8::String::VerifyExternalStringResource(
   2676     v8::String::ExternalStringResource* value) const {
   2677   i::Handle<i::String> str = Utils::OpenHandle(this);
   2678   v8::String::ExternalStringResource* expected;
   2679   if (i::StringShape(*str).IsExternalTwoByte()) {
   2680     void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
   2681     expected = reinterpret_cast<ExternalStringResource*>(resource);
   2682   } else {
   2683     expected = NULL;
   2684   }
   2685   CHECK_EQ(expected, value);
   2686 }
   2687 
   2688 
   2689 v8::String::ExternalAsciiStringResource*
   2690       v8::String::GetExternalAsciiStringResource() const {
   2691   EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
   2692   i::Handle<i::String> str = Utils::OpenHandle(this);
   2693   if (i::StringShape(*str).IsExternalAscii()) {
   2694     void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
   2695     return reinterpret_cast<ExternalAsciiStringResource*>(resource);
   2696   } else {
   2697     return NULL;
   2698   }
   2699 }
   2700 
   2701 
   2702 double Number::Value() const {
   2703   if (IsDeadCheck("v8::Number::Value()")) return 0;
   2704   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   2705   return obj->Number();
   2706 }
   2707 
   2708 
   2709 bool Boolean::Value() const {
   2710   if (IsDeadCheck("v8::Boolean::Value()")) return false;
   2711   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   2712   return obj->IsTrue();
   2713 }
   2714 
   2715 
   2716 int64_t Integer::Value() const {
   2717   if (IsDeadCheck("v8::Integer::Value()")) return 0;
   2718   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   2719   if (obj->IsSmi()) {
   2720     return i::Smi::cast(*obj)->value();
   2721   } else {
   2722     return static_cast<int64_t>(obj->Number());
   2723   }
   2724 }
   2725 
   2726 
   2727 int32_t Int32::Value() const {
   2728   if (IsDeadCheck("v8::Int32::Value()")) return 0;
   2729   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   2730   if (obj->IsSmi()) {
   2731     return i::Smi::cast(*obj)->value();
   2732   } else {
   2733     return static_cast<int32_t>(obj->Number());
   2734   }
   2735 }
   2736 
   2737 
   2738 int v8::Object::InternalFieldCount() {
   2739   if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
   2740   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
   2741   return obj->GetInternalFieldCount();
   2742 }
   2743 
   2744 
   2745 Local<Value> v8::Object::CheckedGetInternalField(int index) {
   2746   if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
   2747   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
   2748   if (!ApiCheck(index < obj->GetInternalFieldCount(),
   2749                 "v8::Object::GetInternalField()",
   2750                 "Reading internal field out of bounds")) {
   2751     return Local<Value>();
   2752   }
   2753   i::Handle<i::Object> value(obj->GetInternalField(index));
   2754   Local<Value> result = Utils::ToLocal(value);
   2755 #ifdef DEBUG
   2756   Local<Value> unchecked = UncheckedGetInternalField(index);
   2757   ASSERT(unchecked.IsEmpty() || (unchecked == result));
   2758 #endif
   2759   return result;
   2760 }
   2761 
   2762 
   2763 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
   2764   if (IsDeadCheck("v8::Object::SetInternalField()")) return;
   2765   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
   2766   if (!ApiCheck(index < obj->GetInternalFieldCount(),
   2767                 "v8::Object::SetInternalField()",
   2768                 "Writing internal field out of bounds")) {
   2769     return;
   2770   }
   2771   ENTER_V8;
   2772   i::Handle<i::Object> val = Utils::OpenHandle(*value);
   2773   obj->SetInternalField(index, *val);
   2774 }
   2775 
   2776 
   2777 void v8::Object::SetPointerInInternalField(int index, void* value) {
   2778   i::Object* as_object = reinterpret_cast<i::Object*>(value);
   2779   if (as_object->IsSmi()) {
   2780     Utils::OpenHandle(this)->SetInternalField(index, as_object);
   2781     return;
   2782   }
   2783   HandleScope scope;
   2784   i::Handle<i::Proxy> proxy =
   2785       i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
   2786   if (!proxy.is_null())
   2787       Utils::OpenHandle(this)->SetInternalField(index, *proxy);
   2788 }
   2789 
   2790 
   2791 // --- E n v i r o n m e n t ---
   2792 
   2793 bool v8::V8::Initialize() {
   2794   if (i::V8::IsRunning()) return true;
   2795   ENTER_V8;
   2796   HandleScope scope;
   2797   if (i::Snapshot::Initialize()) return true;
   2798   return i::V8::Initialize(NULL);
   2799 }
   2800 
   2801 
   2802 bool v8::V8::Dispose() {
   2803   i::V8::TearDown();
   2804   return true;
   2805 }
   2806 
   2807 
   2808 HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
   2809 
   2810 
   2811 void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
   2812   heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
   2813   heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
   2814 }
   2815 
   2816 
   2817 bool v8::V8::IdleNotification() {
   2818   // Returning true tells the caller that it need not
   2819   // continue to call IdleNotification.
   2820   if (!i::V8::IsRunning()) return true;
   2821   return i::V8::IdleNotification();
   2822 }
   2823 
   2824 
   2825 void v8::V8::LowMemoryNotification() {
   2826   if (!i::V8::IsRunning()) return;
   2827   i::Heap::CollectAllGarbage(true);
   2828 }
   2829 
   2830 
   2831 const char* v8::V8::GetVersion() {
   2832   static v8::internal::EmbeddedVector<char, 128> buffer;
   2833   v8::internal::Version::GetString(buffer);
   2834   return buffer.start();
   2835 }
   2836 
   2837 
   2838 static i::Handle<i::FunctionTemplateInfo>
   2839     EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
   2840   if (templ->constructor()->IsUndefined()) {
   2841     Local<FunctionTemplate> constructor = FunctionTemplate::New();
   2842     Utils::OpenHandle(*constructor)->set_instance_template(*templ);
   2843     templ->set_constructor(*Utils::OpenHandle(*constructor));
   2844   }
   2845   return i::Handle<i::FunctionTemplateInfo>(
   2846     i::FunctionTemplateInfo::cast(templ->constructor()));
   2847 }
   2848 
   2849 
   2850 Persistent<Context> v8::Context::New(
   2851     v8::ExtensionConfiguration* extensions,
   2852     v8::Handle<ObjectTemplate> global_template,
   2853     v8::Handle<Value> global_object) {
   2854   EnsureInitialized("v8::Context::New()");
   2855   LOG_API("Context::New");
   2856   ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
   2857 
   2858 #if defined(ANDROID)
   2859   // On mobile device, full GC is expensive, leave it to the system to
   2860   // decide when should make a full GC.
   2861 #else
   2862   // Give the heap a chance to cleanup if we've disposed contexts.
   2863   i::Heap::CollectAllGarbageIfContextDisposed();
   2864 #endif
   2865 
   2866   // Enter V8 via an ENTER_V8 scope.
   2867   i::Handle<i::Context> env;
   2868   {
   2869     ENTER_V8;
   2870     v8::Handle<ObjectTemplate> proxy_template = global_template;
   2871     i::Handle<i::FunctionTemplateInfo> proxy_constructor;
   2872     i::Handle<i::FunctionTemplateInfo> global_constructor;
   2873 
   2874     if (!global_template.IsEmpty()) {
   2875       // Make sure that the global_template has a constructor.
   2876       global_constructor =
   2877           EnsureConstructor(Utils::OpenHandle(*global_template));
   2878 
   2879       // Create a fresh template for the global proxy object.
   2880       proxy_template = ObjectTemplate::New();
   2881       proxy_constructor =
   2882           EnsureConstructor(Utils::OpenHandle(*proxy_template));
   2883 
   2884       // Set the global template to be the prototype template of
   2885       // global proxy template.
   2886       proxy_constructor->set_prototype_template(
   2887           *Utils::OpenHandle(*global_template));
   2888 
   2889       // Migrate security handlers from global_template to
   2890       // proxy_template.  Temporarily removing access check
   2891       // information from the global template.
   2892       if (!global_constructor->access_check_info()->IsUndefined()) {
   2893         proxy_constructor->set_access_check_info(
   2894             global_constructor->access_check_info());
   2895         proxy_constructor->set_needs_access_check(
   2896             global_constructor->needs_access_check());
   2897         global_constructor->set_needs_access_check(false);
   2898         global_constructor->set_access_check_info(i::Heap::undefined_value());
   2899       }
   2900     }
   2901 
   2902     // Create the environment.
   2903     env = i::Bootstrapper::CreateEnvironment(
   2904         Utils::OpenHandle(*global_object),
   2905         proxy_template,
   2906         extensions);
   2907 
   2908     // Restore the access check info on the global template.
   2909     if (!global_template.IsEmpty()) {
   2910       ASSERT(!global_constructor.is_null());
   2911       ASSERT(!proxy_constructor.is_null());
   2912       global_constructor->set_access_check_info(
   2913           proxy_constructor->access_check_info());
   2914       global_constructor->set_needs_access_check(
   2915           proxy_constructor->needs_access_check());
   2916     }
   2917   }
   2918   // Leave V8.
   2919 
   2920   if (env.is_null())
   2921     return Persistent<Context>();
   2922   return Persistent<Context>(Utils::ToLocal(env));
   2923 }
   2924 
   2925 
   2926 void v8::Context::SetSecurityToken(Handle<Value> token) {
   2927   if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
   2928   ENTER_V8;
   2929   i::Handle<i::Context> env = Utils::OpenHandle(this);
   2930   i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
   2931   env->set_security_token(*token_handle);
   2932 }
   2933 
   2934 
   2935 void v8::Context::UseDefaultSecurityToken() {
   2936   if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
   2937   ENTER_V8;
   2938   i::Handle<i::Context> env = Utils::OpenHandle(this);
   2939   env->set_security_token(env->global());
   2940 }
   2941 
   2942 
   2943 Handle<Value> v8::Context::GetSecurityToken() {
   2944   if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
   2945   i::Handle<i::Context> env = Utils::OpenHandle(this);
   2946   i::Object* security_token = env->security_token();
   2947   i::Handle<i::Object> token_handle(security_token);
   2948   return Utils::ToLocal(token_handle);
   2949 }
   2950 
   2951 
   2952 bool Context::HasOutOfMemoryException() {
   2953   i::Handle<i::Context> env = Utils::OpenHandle(this);
   2954   return env->has_out_of_memory();
   2955 }
   2956 
   2957 
   2958 bool Context::InContext() {
   2959   return i::Top::context() != NULL;
   2960 }
   2961 
   2962 
   2963 v8::Local<v8::Context> Context::GetEntered() {
   2964   if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
   2965   i::Handle<i::Object> last = thread_local.LastEnteredContext();
   2966   if (last.is_null()) return Local<Context>();
   2967   i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
   2968   return Utils::ToLocal(context);
   2969 }
   2970 
   2971 
   2972 v8::Local<v8::Context> Context::GetCurrent() {
   2973   if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
   2974   i::Handle<i::Object> current = i::Top::global_context();
   2975   if (current.is_null()) return Local<Context>();
   2976   i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
   2977   return Utils::ToLocal(context);
   2978 }
   2979 
   2980 
   2981 v8::Local<v8::Context> Context::GetCalling() {
   2982   if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
   2983   i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
   2984   if (calling.is_null()) return Local<Context>();
   2985   i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
   2986   return Utils::ToLocal(context);
   2987 }
   2988 
   2989 
   2990 v8::Local<v8::Object> Context::Global() {
   2991   if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
   2992   i::Object** ctx = reinterpret_cast<i::Object**>(this);
   2993   i::Handle<i::Context> context =
   2994       i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
   2995   i::Handle<i::Object> global(context->global_proxy());
   2996   return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
   2997 }
   2998 
   2999 
   3000 void Context::DetachGlobal() {
   3001   if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
   3002   ENTER_V8;
   3003   i::Object** ctx = reinterpret_cast<i::Object**>(this);
   3004   i::Handle<i::Context> context =
   3005       i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
   3006   i::Bootstrapper::DetachGlobal(context);
   3007 }
   3008 
   3009 
   3010 void Context::ReattachGlobal(Handle<Object> global_object) {
   3011   if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
   3012   ENTER_V8;
   3013   i::Object** ctx = reinterpret_cast<i::Object**>(this);
   3014   i::Handle<i::Context> context =
   3015       i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
   3016   i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
   3017 }
   3018 
   3019 
   3020 Local<v8::Object> ObjectTemplate::NewInstance() {
   3021   ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
   3022   LOG_API("ObjectTemplate::NewInstance");
   3023   ENTER_V8;
   3024   EXCEPTION_PREAMBLE();
   3025   i::Handle<i::Object> obj =
   3026       i::Execution::InstantiateObject(Utils::OpenHandle(this),
   3027                                       &has_pending_exception);
   3028   EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
   3029   return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
   3030 }
   3031 
   3032 
   3033 Local<v8::Function> FunctionTemplate::GetFunction() {
   3034   ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
   3035              return Local<v8::Function>());
   3036   LOG_API("FunctionTemplate::GetFunction");
   3037   ENTER_V8;
   3038   EXCEPTION_PREAMBLE();
   3039   i::Handle<i::Object> obj =
   3040       i::Execution::InstantiateFunction(Utils::OpenHandle(this),
   3041                                         &has_pending_exception);
   3042   EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
   3043   return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
   3044 }
   3045 
   3046 
   3047 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
   3048   ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
   3049   i::Object* obj = *Utils::OpenHandle(*value);
   3050   return obj->IsInstanceOf(*Utils::OpenHandle(this));
   3051 }
   3052 
   3053 
   3054 static Local<External> ExternalNewImpl(void* data) {
   3055   return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
   3056 }
   3057 
   3058 static void* ExternalValueImpl(i::Handle<i::Object> obj) {
   3059   return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
   3060 }
   3061 
   3062 
   3063 Local<Value> v8::External::Wrap(void* data) {
   3064   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
   3065   LOG_API("External::Wrap");
   3066   EnsureInitialized("v8::External::Wrap()");
   3067   ENTER_V8;
   3068   i::Object* as_object = reinterpret_cast<i::Object*>(data);
   3069   if (as_object->IsSmi()) {
   3070     return Utils::ToLocal(i::Handle<i::Object>(as_object));
   3071   }
   3072   return ExternalNewImpl(data);
   3073 }
   3074 
   3075 
   3076 void* v8::Object::SlowGetPointerFromInternalField(int index) {
   3077   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
   3078   i::Object* value = obj->GetInternalField(index);
   3079   if (value->IsSmi()) {
   3080     return value;
   3081   } else if (value->IsProxy()) {
   3082     return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
   3083   } else {
   3084     return NULL;
   3085   }
   3086 }
   3087 
   3088 
   3089 void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
   3090   if (IsDeadCheck("v8::External::Unwrap()")) return 0;
   3091   i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
   3092   void* result;
   3093   if (obj->IsSmi()) {
   3094     // The external value was an aligned pointer.
   3095     result = *obj;
   3096   } else if (obj->IsProxy()) {
   3097     result = ExternalValueImpl(obj);
   3098   } else {
   3099     result = NULL;
   3100   }
   3101   ASSERT_EQ(result, QuickUnwrap(wrapper));
   3102   return result;
   3103 }
   3104 
   3105 
   3106 Local<External> v8::External::New(void* data) {
   3107   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
   3108   LOG_API("External::New");
   3109   EnsureInitialized("v8::External::New()");
   3110   ENTER_V8;
   3111   return ExternalNewImpl(data);
   3112 }
   3113 
   3114 
   3115 void* External::Value() const {
   3116   if (IsDeadCheck("v8::External::Value()")) return 0;
   3117   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   3118   return ExternalValueImpl(obj);
   3119 }
   3120 
   3121 
   3122 Local<String> v8::String::Empty() {
   3123   EnsureInitialized("v8::String::Empty()");
   3124   LOG_API("String::Empty()");
   3125   return Utils::ToLocal(i::Factory::empty_symbol());
   3126 }
   3127 
   3128 
   3129 Local<String> v8::String::New(const char* data, int length) {
   3130   EnsureInitialized("v8::String::New()");
   3131   LOG_API("String::New(char)");
   3132   if (length == 0) return Empty();
   3133   ENTER_V8;
   3134   if (length == -1) length = i::StrLength(data);
   3135   i::Handle<i::String> result =
   3136       i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
   3137   return Utils::ToLocal(result);
   3138 }
   3139 
   3140 
   3141 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
   3142   EnsureInitialized("v8::String::New()");
   3143   LOG_API("String::New(char)");
   3144   ENTER_V8;
   3145   i::Handle<i::String> left_string = Utils::OpenHandle(*left);
   3146   i::Handle<i::String> right_string = Utils::OpenHandle(*right);
   3147   i::Handle<i::String> result = i::Factory::NewConsString(left_string,
   3148                                                           right_string);
   3149   return Utils::ToLocal(result);
   3150 }
   3151 
   3152 
   3153 Local<String> v8::String::NewUndetectable(const char* data, int length) {
   3154   EnsureInitialized("v8::String::NewUndetectable()");
   3155   LOG_API("String::NewUndetectable(char)");
   3156   ENTER_V8;
   3157   if (length == -1) length = i::StrLength(data);
   3158   i::Handle<i::String> result =
   3159       i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
   3160   result->MarkAsUndetectable();
   3161   return Utils::ToLocal(result);
   3162 }
   3163 
   3164 
   3165 static int TwoByteStringLength(const uint16_t* data) {
   3166   int length = 0;
   3167   while (data[length] != '\0') length++;
   3168   return length;
   3169 }
   3170 
   3171 
   3172 Local<String> v8::String::New(const uint16_t* data, int length) {
   3173   EnsureInitialized("v8::String::New()");
   3174   LOG_API("String::New(uint16_)");
   3175   if (length == 0) return Empty();
   3176   ENTER_V8;
   3177   if (length == -1) length = TwoByteStringLength(data);
   3178   i::Handle<i::String> result =
   3179       i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
   3180   return Utils::ToLocal(result);
   3181 }
   3182 
   3183 
   3184 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
   3185   EnsureInitialized("v8::String::NewUndetectable()");
   3186   LOG_API("String::NewUndetectable(uint16_)");
   3187   ENTER_V8;
   3188   if (length == -1) length = TwoByteStringLength(data);
   3189   i::Handle<i::String> result =
   3190       i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
   3191   result->MarkAsUndetectable();
   3192   return Utils::ToLocal(result);
   3193 }
   3194 
   3195 
   3196 i::Handle<i::String> NewExternalStringHandle(
   3197       v8::String::ExternalStringResource* resource) {
   3198   i::Handle<i::String> result =
   3199       i::Factory::NewExternalStringFromTwoByte(resource);
   3200   return result;
   3201 }
   3202 
   3203 
   3204 i::Handle<i::String> NewExternalAsciiStringHandle(
   3205       v8::String::ExternalAsciiStringResource* resource) {
   3206   i::Handle<i::String> result =
   3207       i::Factory::NewExternalStringFromAscii(resource);
   3208   return result;
   3209 }
   3210 
   3211 
   3212 Local<String> v8::String::NewExternal(
   3213       v8::String::ExternalStringResource* resource) {
   3214   EnsureInitialized("v8::String::NewExternal()");
   3215   LOG_API("String::NewExternal");
   3216   ENTER_V8;
   3217   i::Handle<i::String> result = NewExternalStringHandle(resource);
   3218   i::ExternalStringTable::AddString(*result);
   3219   return Utils::ToLocal(result);
   3220 }
   3221 
   3222 
   3223 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
   3224   if (IsDeadCheck("v8::String::MakeExternal()")) return false;
   3225   if (this->IsExternal()) return false;  // Already an external string.
   3226   ENTER_V8;
   3227   i::Handle<i::String> obj = Utils::OpenHandle(this);
   3228   if (StringTracker::IsFreshUnusedString(obj)) return false;
   3229   bool result = obj->MakeExternal(resource);
   3230   if (result && !obj->IsSymbol()) {
   3231     i::ExternalStringTable::AddString(*obj);
   3232   }
   3233   return result;
   3234 }
   3235 
   3236 
   3237 Local<String> v8::String::NewExternal(
   3238       v8::String::ExternalAsciiStringResource* resource) {
   3239   EnsureInitialized("v8::String::NewExternal()");
   3240   LOG_API("String::NewExternal");
   3241   ENTER_V8;
   3242   i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
   3243   i::ExternalStringTable::AddString(*result);
   3244   return Utils::ToLocal(result);
   3245 }
   3246 
   3247 
   3248 bool v8::String::MakeExternal(
   3249     v8::String::ExternalAsciiStringResource* resource) {
   3250   if (IsDeadCheck("v8::String::MakeExternal()")) return false;
   3251   if (this->IsExternal()) return false;  // Already an external string.
   3252   ENTER_V8;
   3253   i::Handle<i::String> obj = Utils::OpenHandle(this);
   3254   if (StringTracker::IsFreshUnusedString(obj)) return false;
   3255   bool result = obj->MakeExternal(resource);
   3256   if (result && !obj->IsSymbol()) {
   3257     i::ExternalStringTable::AddString(*obj);
   3258   }
   3259   return result;
   3260 }
   3261 
   3262 
   3263 bool v8::String::CanMakeExternal() {
   3264   if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
   3265   i::Handle<i::String> obj = Utils::OpenHandle(this);
   3266   if (StringTracker::IsFreshUnusedString(obj)) return false;
   3267   int size = obj->Size();  // Byte size of the original string.
   3268   if (size < i::ExternalString::kSize)
   3269     return false;
   3270   i::StringShape shape(*obj);
   3271   return !shape.IsExternal();
   3272 }
   3273 
   3274 
   3275 Local<v8::Object> v8::Object::New() {
   3276   EnsureInitialized("v8::Object::New()");
   3277   LOG_API("Object::New");
   3278   ENTER_V8;
   3279   i::Handle<i::JSObject> obj =
   3280       i::Factory::NewJSObject(i::Top::object_function());
   3281   return Utils::ToLocal(obj);
   3282 }
   3283 
   3284 
   3285 Local<v8::Value> v8::Date::New(double time) {
   3286   EnsureInitialized("v8::Date::New()");
   3287   LOG_API("Date::New");
   3288   if (isnan(time)) {
   3289     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
   3290     time = i::OS::nan_value();
   3291   }
   3292   ENTER_V8;
   3293   EXCEPTION_PREAMBLE();
   3294   i::Handle<i::Object> obj =
   3295       i::Execution::NewDate(time, &has_pending_exception);
   3296   EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
   3297   return Utils::ToLocal(obj);
   3298 }
   3299 
   3300 
   3301 double v8::Date::NumberValue() const {
   3302   if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
   3303   LOG_API("Date::NumberValue");
   3304   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   3305   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
   3306   return jsvalue->value()->Number();
   3307 }
   3308 
   3309 
   3310 Local<v8::Array> v8::Array::New(int length) {
   3311   EnsureInitialized("v8::Array::New()");
   3312   LOG_API("Array::New");
   3313   ENTER_V8;
   3314   i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
   3315   return Utils::ToLocal(obj);
   3316 }
   3317 
   3318 
   3319 uint32_t v8::Array::Length() const {
   3320   if (IsDeadCheck("v8::Array::Length()")) return 0;
   3321   i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
   3322   i::Object* length = obj->length();
   3323   if (length->IsSmi()) {
   3324     return i::Smi::cast(length)->value();
   3325   } else {
   3326     return static_cast<uint32_t>(length->Number());
   3327   }
   3328 }
   3329 
   3330 
   3331 Local<Object> Array::CloneElementAt(uint32_t index) {
   3332   ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
   3333   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   3334   if (!self->HasFastElements()) {
   3335     return Local<Object>();
   3336   }
   3337   i::FixedArray* elms = i::FixedArray::cast(self->elements());
   3338   i::Object* paragon = elms->get(index);
   3339   if (!paragon->IsJSObject()) {
   3340     return Local<Object>();
   3341   }
   3342   i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
   3343   EXCEPTION_PREAMBLE();
   3344   i::Handle<i::JSObject> result = i::Copy(paragon_handle);
   3345   has_pending_exception = result.is_null();
   3346   EXCEPTION_BAILOUT_CHECK(Local<Object>());
   3347   return Utils::ToLocal(result);
   3348 }
   3349 
   3350 
   3351 Local<String> v8::String::NewSymbol(const char* data, int length) {
   3352   EnsureInitialized("v8::String::NewSymbol()");
   3353   LOG_API("String::NewSymbol(char)");
   3354   ENTER_V8;
   3355   if (length == -1) length = i::StrLength(data);
   3356   i::Handle<i::String> result =
   3357       i::Factory::LookupSymbol(i::Vector<const char>(data, length));
   3358   return Utils::ToLocal(result);
   3359 }
   3360 
   3361 
   3362 Local<Number> v8::Number::New(double value) {
   3363   EnsureInitialized("v8::Number::New()");
   3364   if (isnan(value)) {
   3365     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
   3366     value = i::OS::nan_value();
   3367   }
   3368   ENTER_V8;
   3369   i::Handle<i::Object> result = i::Factory::NewNumber(value);
   3370   return Utils::NumberToLocal(result);
   3371 }
   3372 
   3373 
   3374 Local<Integer> v8::Integer::New(int32_t value) {
   3375   EnsureInitialized("v8::Integer::New()");
   3376   if (i::Smi::IsValid(value)) {
   3377     return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
   3378   }
   3379   ENTER_V8;
   3380   i::Handle<i::Object> result = i::Factory::NewNumber(value);
   3381   return Utils::IntegerToLocal(result);
   3382 }
   3383 
   3384 
   3385 Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
   3386   bool fits_into_int32_t = (value & (1 << 31)) == 0;
   3387   if (fits_into_int32_t) {
   3388     return Integer::New(static_cast<int32_t>(value));
   3389   }
   3390   ENTER_V8;
   3391   i::Handle<i::Object> result = i::Factory::NewNumber(value);
   3392   return Utils::IntegerToLocal(result);
   3393 }
   3394 
   3395 
   3396 void V8::IgnoreOutOfMemoryException() {
   3397   thread_local.set_ignore_out_of_memory(true);
   3398 }
   3399 
   3400 
   3401 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
   3402   EnsureInitialized("v8::V8::AddMessageListener()");
   3403   ON_BAILOUT("v8::V8::AddMessageListener()", return false);
   3404   ENTER_V8;
   3405   HandleScope scope;
   3406   NeanderArray listeners(i::Factory::message_listeners());
   3407   NeanderObject obj(2);
   3408   obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
   3409   obj.set(1, data.IsEmpty() ?
   3410              i::Heap::undefined_value() :
   3411              *Utils::OpenHandle(*data));
   3412   listeners.add(obj.value());
   3413   return true;
   3414 }
   3415 
   3416 
   3417 void V8::RemoveMessageListeners(MessageCallback that) {
   3418   EnsureInitialized("v8::V8::RemoveMessageListener()");
   3419   ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
   3420   ENTER_V8;
   3421   HandleScope scope;
   3422   NeanderArray listeners(i::Factory::message_listeners());
   3423   for (int i = 0; i < listeners.length(); i++) {
   3424     if (listeners.get(i)->IsUndefined()) continue;  // skip deleted ones
   3425 
   3426     NeanderObject listener(i::JSObject::cast(listeners.get(i)));
   3427     i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
   3428     if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
   3429       listeners.set(i, i::Heap::undefined_value());
   3430     }
   3431   }
   3432 }
   3433 
   3434 
   3435 void V8::SetCounterFunction(CounterLookupCallback callback) {
   3436   if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
   3437   i::StatsTable::SetCounterFunction(callback);
   3438 }
   3439 
   3440 void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
   3441   if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
   3442   i::StatsTable::SetCreateHistogramFunction(callback);
   3443 }
   3444 
   3445 void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
   3446   if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
   3447   i::StatsTable::SetAddHistogramSampleFunction(callback);
   3448 }
   3449 
   3450 void V8::EnableSlidingStateWindow() {
   3451   if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
   3452   i::Logger::EnableSlidingStateWindow();
   3453 }
   3454 
   3455 
   3456 void V8::SetFailedAccessCheckCallbackFunction(
   3457       FailedAccessCheckCallback callback) {
   3458   if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
   3459   i::Top::SetFailedAccessCheckCallback(callback);
   3460 }
   3461 
   3462 
   3463 void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
   3464   if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
   3465   STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
   3466   i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
   3467 }
   3468 
   3469 
   3470 int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
   3471   if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
   3472   return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
   3473 }
   3474 
   3475 
   3476 void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
   3477   if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
   3478   i::Heap::SetGlobalGCPrologueCallback(callback);
   3479 }
   3480 
   3481 
   3482 void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
   3483   if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
   3484   i::Heap::SetGlobalGCEpilogueCallback(callback);
   3485 }
   3486 
   3487 
   3488 void V8::PauseProfiler() {
   3489 #ifdef ENABLE_LOGGING_AND_PROFILING
   3490   PauseProfilerEx(PROFILER_MODULE_CPU);
   3491 #endif
   3492 }
   3493 
   3494 
   3495 void V8::ResumeProfiler() {
   3496 #ifdef ENABLE_LOGGING_AND_PROFILING
   3497   ResumeProfilerEx(PROFILER_MODULE_CPU);
   3498 #endif
   3499 }
   3500 
   3501 
   3502 bool V8::IsProfilerPaused() {
   3503 #ifdef ENABLE_LOGGING_AND_PROFILING
   3504   return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
   3505 #else
   3506   return true;
   3507 #endif
   3508 }
   3509 
   3510 
   3511 void V8::ResumeProfilerEx(int flags, int tag) {
   3512 #ifdef ENABLE_LOGGING_AND_PROFILING
   3513   if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
   3514     // Snapshot mode: resume modules, perform GC, then pause only
   3515     // those modules which haven't been started prior to making a
   3516     // snapshot.
   3517 
   3518     // Reset snapshot flag and CPU module flags.
   3519     flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
   3520     const int current_flags = i::Logger::GetActiveProfilerModules();
   3521     i::Logger::ResumeProfiler(flags, tag);
   3522     i::Heap::CollectAllGarbage(false);
   3523     i::Logger::PauseProfiler(~current_flags & flags, tag);
   3524   } else {
   3525     i::Logger::ResumeProfiler(flags, tag);
   3526   }
   3527 #endif
   3528 }
   3529 
   3530 
   3531 void V8::PauseProfilerEx(int flags, int tag) {
   3532 #ifdef ENABLE_LOGGING_AND_PROFILING
   3533   i::Logger::PauseProfiler(flags, tag);
   3534 #endif
   3535 }
   3536 
   3537 
   3538 int V8::GetActiveProfilerModules() {
   3539 #ifdef ENABLE_LOGGING_AND_PROFILING
   3540   return i::Logger::GetActiveProfilerModules();
   3541 #else
   3542   return PROFILER_MODULE_NONE;
   3543 #endif
   3544 }
   3545 
   3546 
   3547 int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
   3548 #ifdef ENABLE_LOGGING_AND_PROFILING
   3549   return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
   3550 #endif
   3551   return 0;
   3552 }
   3553 
   3554 
   3555 int V8::GetCurrentThreadId() {
   3556   API_ENTRY_CHECK("V8::GetCurrentThreadId()");
   3557   EnsureInitialized("V8::GetCurrentThreadId()");
   3558   return i::Top::thread_id();
   3559 }
   3560 
   3561 
   3562 void V8::TerminateExecution(int thread_id) {
   3563   if (!i::V8::IsRunning()) return;
   3564   API_ENTRY_CHECK("V8::GetCurrentThreadId()");
   3565   // If the thread_id identifies the current thread just terminate
   3566   // execution right away.  Otherwise, ask the thread manager to
   3567   // terminate the thread with the given id if any.
   3568   if (thread_id == i::Top::thread_id()) {
   3569     i::StackGuard::TerminateExecution();
   3570   } else {
   3571     i::ThreadManager::TerminateExecution(thread_id);
   3572   }
   3573 }
   3574 
   3575 
   3576 void V8::TerminateExecution() {
   3577   if (!i::V8::IsRunning()) return;
   3578   i::StackGuard::TerminateExecution();
   3579 }
   3580 
   3581 
   3582 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
   3583   EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
   3584   if (obj.IsEmpty()) {
   3585     str_ = NULL;
   3586     length_ = 0;
   3587     return;
   3588   }
   3589   ENTER_V8;
   3590   HandleScope scope;
   3591   TryCatch try_catch;
   3592   Handle<String> str = obj->ToString();
   3593   if (str.IsEmpty()) {
   3594     str_ = NULL;
   3595     length_ = 0;
   3596   } else {
   3597     length_ = str->Utf8Length();
   3598     str_ = i::NewArray<char>(length_ + 1);
   3599     str->WriteUtf8(str_);
   3600   }
   3601 }
   3602 
   3603 
   3604 String::Utf8Value::~Utf8Value() {
   3605   i::DeleteArray(str_);
   3606 }
   3607 
   3608 
   3609 String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
   3610   EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
   3611   if (obj.IsEmpty()) {
   3612     str_ = NULL;
   3613     length_ = 0;
   3614     return;
   3615   }
   3616   ENTER_V8;
   3617   HandleScope scope;
   3618   TryCatch try_catch;
   3619   Handle<String> str = obj->ToString();
   3620   if (str.IsEmpty()) {
   3621     str_ = NULL;
   3622     length_ = 0;
   3623   } else {
   3624     length_ = str->Length();
   3625     str_ = i::NewArray<char>(length_ + 1);
   3626     str->WriteAscii(str_);
   3627   }
   3628 }
   3629 
   3630 
   3631 String::AsciiValue::~AsciiValue() {
   3632   i::DeleteArray(str_);
   3633 }
   3634 
   3635 
   3636 String::Value::Value(v8::Handle<v8::Value> obj) {
   3637   EnsureInitialized("v8::String::Value::Value()");
   3638   if (obj.IsEmpty()) {
   3639     str_ = NULL;
   3640     length_ = 0;
   3641     return;
   3642   }
   3643   ENTER_V8;
   3644   HandleScope scope;
   3645   TryCatch try_catch;
   3646   Handle<String> str = obj->ToString();
   3647   if (str.IsEmpty()) {
   3648     str_ = NULL;
   3649     length_ = 0;
   3650   } else {
   3651     length_ = str->Length();
   3652     str_ = i::NewArray<uint16_t>(length_ + 1);
   3653     str->Write(str_);
   3654   }
   3655 }
   3656 
   3657 
   3658 String::Value::~Value() {
   3659   i::DeleteArray(str_);
   3660 }
   3661 
   3662 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
   3663   LOG_API("RangeError");
   3664   ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
   3665   ENTER_V8;
   3666   i::Object* error;
   3667   {
   3668     HandleScope scope;
   3669     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
   3670     i::Handle<i::Object> result = i::Factory::NewRangeError(message);
   3671     error = *result;
   3672   }
   3673   i::Handle<i::Object> result(error);
   3674   return Utils::ToLocal(result);
   3675 }
   3676 
   3677 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
   3678   LOG_API("ReferenceError");
   3679   ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
   3680   ENTER_V8;
   3681   i::Object* error;
   3682   {
   3683     HandleScope scope;
   3684     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
   3685     i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
   3686     error = *result;
   3687   }
   3688   i::Handle<i::Object> result(error);
   3689   return Utils::ToLocal(result);
   3690 }
   3691 
   3692 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
   3693   LOG_API("SyntaxError");
   3694   ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
   3695   ENTER_V8;
   3696   i::Object* error;
   3697   {
   3698     HandleScope scope;
   3699     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
   3700     i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
   3701     error = *result;
   3702   }
   3703   i::Handle<i::Object> result(error);
   3704   return Utils::ToLocal(result);
   3705 }
   3706 
   3707 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
   3708   LOG_API("TypeError");
   3709   ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
   3710   ENTER_V8;
   3711   i::Object* error;
   3712   {
   3713     HandleScope scope;
   3714     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
   3715     i::Handle<i::Object> result = i::Factory::NewTypeError(message);
   3716     error = *result;
   3717   }
   3718   i::Handle<i::Object> result(error);
   3719   return Utils::ToLocal(result);
   3720 }
   3721 
   3722 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
   3723   LOG_API("Error");
   3724   ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
   3725   ENTER_V8;
   3726   i::Object* error;
   3727   {
   3728     HandleScope scope;
   3729     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
   3730     i::Handle<i::Object> result = i::Factory::NewError(message);
   3731     error = *result;
   3732   }
   3733   i::Handle<i::Object> result(error);
   3734   return Utils::ToLocal(result);
   3735 }
   3736 
   3737 
   3738 // --- D e b u g   S u p p o r t ---
   3739 
   3740 #ifdef ENABLE_DEBUGGER_SUPPORT
   3741 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
   3742   EnsureInitialized("v8::Debug::SetDebugEventListener()");
   3743   ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
   3744   ENTER_V8;
   3745   HandleScope scope;
   3746   i::Handle<i::Object> proxy = i::Factory::undefined_value();
   3747   if (that != NULL) {
   3748     proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
   3749   }
   3750   i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
   3751   return true;
   3752 }
   3753 
   3754 
   3755 bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
   3756                                   Handle<Value> data) {
   3757   ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
   3758   ENTER_V8;
   3759   i::Debugger::SetEventListener(Utils::OpenHandle(*that),
   3760                                 Utils::OpenHandle(*data));
   3761   return true;
   3762 }
   3763 
   3764 
   3765 void Debug::DebugBreak() {
   3766   if (!i::V8::IsRunning()) return;
   3767   i::StackGuard::DebugBreak();
   3768 }
   3769 
   3770 
   3771 static v8::Debug::MessageHandler message_handler = NULL;
   3772 
   3773 static void MessageHandlerWrapper(const v8::Debug::Message& message) {
   3774   if (message_handler) {
   3775     v8::String::Value json(message.GetJSON());
   3776     message_handler(*json, json.length(), message.GetClientData());
   3777   }
   3778 }
   3779 
   3780 
   3781 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
   3782                               bool message_handler_thread) {
   3783   EnsureInitialized("v8::Debug::SetMessageHandler");
   3784   ENTER_V8;
   3785   // Message handler thread not supported any more. Parameter temporally left in
   3786   // the API for client compatability reasons.
   3787   CHECK(!message_handler_thread);
   3788 
   3789   // TODO(sgjesse) support the old message handler API through a simple wrapper.
   3790   message_handler = handler;
   3791   if (message_handler != NULL) {
   3792     i::Debugger::SetMessageHandler(MessageHandlerWrapper);
   3793   } else {
   3794     i::Debugger::SetMessageHandler(NULL);
   3795   }
   3796 }
   3797 
   3798 
   3799 void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
   3800   EnsureInitialized("v8::Debug::SetMessageHandler");
   3801   ENTER_V8;
   3802   i::Debugger::SetMessageHandler(handler);
   3803 }
   3804 
   3805 
   3806 void Debug::SendCommand(const uint16_t* command, int length,
   3807                         ClientData* client_data) {
   3808   if (!i::V8::IsRunning()) return;
   3809   i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
   3810                               client_data);
   3811 }
   3812 
   3813 
   3814 void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
   3815                                    int period) {
   3816   EnsureInitialized("v8::Debug::SetHostDispatchHandler");
   3817   ENTER_V8;
   3818   i::Debugger::SetHostDispatchHandler(handler, period);
   3819 }
   3820 
   3821 
   3822 void Debug::SetDebugMessageDispatchHandler(
   3823     DebugMessageDispatchHandler handler, bool provide_locker) {
   3824   EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
   3825   ENTER_V8;
   3826   i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
   3827 }
   3828 
   3829 
   3830 Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
   3831                          v8::Handle<v8::Value> data) {
   3832   if (!i::V8::IsRunning()) return Local<Value>();
   3833   ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
   3834   ENTER_V8;
   3835   i::Handle<i::Object> result;
   3836   EXCEPTION_PREAMBLE();
   3837   if (data.IsEmpty()) {
   3838     result = i::Debugger::Call(Utils::OpenHandle(*fun),
   3839                                i::Factory::undefined_value(),
   3840                                &has_pending_exception);
   3841   } else {
   3842     result = i::Debugger::Call(Utils::OpenHandle(*fun),
   3843                                Utils::OpenHandle(*data),
   3844                                &has_pending_exception);
   3845   }
   3846   EXCEPTION_BAILOUT_CHECK(Local<Value>());
   3847   return Utils::ToLocal(result);
   3848 }
   3849 
   3850 
   3851 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
   3852   if (!i::V8::IsRunning()) return Local<Value>();
   3853   ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
   3854   ENTER_V8;
   3855   v8::HandleScope scope;
   3856   i::Debug::Load();
   3857   i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
   3858   i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
   3859   i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
   3860   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
   3861   v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
   3862   const int kArgc = 1;
   3863   v8::Handle<v8::Value> argv[kArgc] = { obj };
   3864   EXCEPTION_PREAMBLE();
   3865   v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
   3866                                               kArgc,
   3867                                               argv);
   3868   EXCEPTION_BAILOUT_CHECK(Local<Value>());
   3869   return scope.Close(result);
   3870 }
   3871 
   3872 
   3873 bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
   3874   return i::Debugger::StartAgent(name, port, wait_for_connection);
   3875 }
   3876 
   3877 void Debug::ProcessDebugMessages() {
   3878   i::Execution::ProcessDebugMesssages(true);
   3879 }
   3880 
   3881 #endif  // ENABLE_DEBUGGER_SUPPORT
   3882 
   3883 namespace internal {
   3884 
   3885 
   3886 HandleScopeImplementer* HandleScopeImplementer::instance() {
   3887   return &thread_local;
   3888 }
   3889 
   3890 
   3891 void HandleScopeImplementer::FreeThreadResources() {
   3892   thread_local.Free();
   3893 }
   3894 
   3895 
   3896 char* HandleScopeImplementer::ArchiveThread(char* storage) {
   3897   return thread_local.ArchiveThreadHelper(storage);
   3898 }
   3899 
   3900 
   3901 char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
   3902   v8::ImplementationUtilities::HandleScopeData* current =
   3903       v8::ImplementationUtilities::CurrentHandleScope();
   3904   handle_scope_data_ = *current;
   3905   memcpy(storage, this, sizeof(*this));
   3906 
   3907   ResetAfterArchive();
   3908   current->Initialize();
   3909 
   3910   return storage + ArchiveSpacePerThread();
   3911 }
   3912 
   3913 
   3914 int HandleScopeImplementer::ArchiveSpacePerThread() {
   3915   return sizeof(thread_local);
   3916 }
   3917 
   3918 
   3919 char* HandleScopeImplementer::RestoreThread(char* storage) {
   3920   return thread_local.RestoreThreadHelper(storage);
   3921 }
   3922 
   3923 
   3924 char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
   3925   memcpy(this, storage, sizeof(*this));
   3926   *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
   3927   return storage + ArchiveSpacePerThread();
   3928 }
   3929 
   3930 
   3931 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
   3932   // Iterate over all handles in the blocks except for the last.
   3933   for (int i = blocks()->length() - 2; i >= 0; --i) {
   3934     Object** block = blocks()->at(i);
   3935     v->VisitPointers(block, &block[kHandleBlockSize]);
   3936   }
   3937 
   3938   // Iterate over live handles in the last block (if any).
   3939   if (!blocks()->is_empty()) {
   3940     v->VisitPointers(blocks()->last(), handle_scope_data_.next);
   3941   }
   3942 
   3943   if (!saved_contexts_.is_empty()) {
   3944     Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
   3945     v->VisitPointers(start, start + saved_contexts_.length());
   3946   }
   3947 }
   3948 
   3949 
   3950 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
   3951   v8::ImplementationUtilities::HandleScopeData* current =
   3952       v8::ImplementationUtilities::CurrentHandleScope();
   3953   thread_local.handle_scope_data_ = *current;
   3954   thread_local.IterateThis(v);
   3955 }
   3956 
   3957 
   3958 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
   3959   HandleScopeImplementer* thread_local =
   3960       reinterpret_cast<HandleScopeImplementer*>(storage);
   3961   thread_local->IterateThis(v);
   3962   return storage + ArchiveSpacePerThread();
   3963 }
   3964 
   3965 } }  // namespace v8::internal
   3966