Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <stdlib.h>
     29 
     30 #include "v8.h"
     31 
     32 #include "api.h"
     33 #include "bootstrapper.h"
     34 #include "codegen.h"
     35 #include "debug.h"
     36 #include "deoptimizer.h"
     37 #include "isolate-inl.h"
     38 #include "runtime-profiler.h"
     39 #include "simulator.h"
     40 #include "v8threads.h"
     41 #include "vm-state-inl.h"
     42 
     43 namespace v8 {
     44 namespace internal {
     45 
     46 
     47 StackGuard::StackGuard()
     48     : isolate_(NULL) {
     49 }
     50 
     51 
     52 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
     53   ASSERT(isolate_ != NULL);
     54   // Ignore attempts to interrupt when interrupts are postponed.
     55   if (should_postpone_interrupts(lock)) return;
     56   thread_local_.jslimit_ = kInterruptLimit;
     57   thread_local_.climit_ = kInterruptLimit;
     58   isolate_->heap()->SetStackLimits();
     59 }
     60 
     61 
     62 void StackGuard::reset_limits(const ExecutionAccess& lock) {
     63   ASSERT(isolate_ != NULL);
     64   thread_local_.jslimit_ = thread_local_.real_jslimit_;
     65   thread_local_.climit_ = thread_local_.real_climit_;
     66   isolate_->heap()->SetStackLimits();
     67 }
     68 
     69 
     70 static Handle<Object> Invoke(bool is_construct,
     71                              Handle<JSFunction> function,
     72                              Handle<Object> receiver,
     73                              int argc,
     74                              Handle<Object> args[],
     75                              bool* has_pending_exception) {
     76   Isolate* isolate = function->GetIsolate();
     77 
     78   // Entering JavaScript.
     79   VMState<JS> state(isolate);
     80 
     81   // Placeholder for return value.
     82   MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
     83 
     84   typedef Object* (*JSEntryFunction)(byte* entry,
     85                                      Object* function,
     86                                      Object* receiver,
     87                                      int argc,
     88                                      Object*** args);
     89 
     90   Handle<Code> code = is_construct
     91       ? isolate->factory()->js_construct_entry_code()
     92       : isolate->factory()->js_entry_code();
     93 
     94   // Convert calls on global objects to be calls on the global
     95   // receiver instead to avoid having a 'this' pointer which refers
     96   // directly to a global object.
     97   if (receiver->IsGlobalObject()) {
     98     Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
     99     receiver = Handle<JSObject>(global->global_receiver());
    100   }
    101 
    102   // Make sure that the global object of the context we're about to
    103   // make the current one is indeed a global object.
    104   ASSERT(function->context()->global_object()->IsGlobalObject());
    105 
    106   {
    107     // Save and restore context around invocation and block the
    108     // allocation of handles without explicit handle scopes.
    109     SaveContext save(isolate);
    110     SealHandleScope shs(isolate);
    111     JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
    112 
    113     // Call the function through the right JS entry stub.
    114     byte* function_entry = function->code()->entry();
    115     JSFunction* func = *function;
    116     Object* recv = *receiver;
    117     Object*** argv = reinterpret_cast<Object***>(args);
    118     value =
    119         CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
    120   }
    121 
    122 #ifdef VERIFY_HEAP
    123   value->Verify();
    124 #endif
    125 
    126   // Update the pending exception flag and return the value.
    127   *has_pending_exception = value->IsException();
    128   ASSERT(*has_pending_exception == isolate->has_pending_exception());
    129   if (*has_pending_exception) {
    130     isolate->ReportPendingMessages();
    131     if (isolate->pending_exception()->IsOutOfMemory()) {
    132       if (!isolate->ignore_out_of_memory()) {
    133         V8::FatalProcessOutOfMemory("JS", true);
    134       }
    135     }
    136 #ifdef ENABLE_DEBUGGER_SUPPORT
    137     // Reset stepping state when script exits with uncaught exception.
    138     if (isolate->debugger()->IsDebuggerActive()) {
    139       isolate->debug()->ClearStepping();
    140     }
    141 #endif  // ENABLE_DEBUGGER_SUPPORT
    142     return Handle<Object>();
    143   } else {
    144     isolate->clear_pending_message();
    145   }
    146 
    147   return Handle<Object>(value->ToObjectUnchecked(), isolate);
    148 }
    149 
    150 
    151 Handle<Object> Execution::Call(Handle<Object> callable,
    152                                Handle<Object> receiver,
    153                                int argc,
    154                                Handle<Object> argv[],
    155                                bool* pending_exception,
    156                                bool convert_receiver) {
    157   *pending_exception = false;
    158 
    159   if (!callable->IsJSFunction()) {
    160     callable = TryGetFunctionDelegate(callable, pending_exception);
    161     if (*pending_exception) return callable;
    162   }
    163   Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
    164 
    165   // In non-strict mode, convert receiver.
    166   if (convert_receiver && !receiver->IsJSReceiver() &&
    167       !func->shared()->native() && func->shared()->is_classic_mode()) {
    168     if (receiver->IsUndefined() || receiver->IsNull()) {
    169       Object* global = func->context()->global_object()->global_receiver();
    170       // Under some circumstances, 'global' can be the JSBuiltinsObject
    171       // In that case, don't rewrite.  (FWIW, the same holds for
    172       // GetIsolate()->global_object()->global_receiver().)
    173       if (!global->IsJSBuiltinsObject()) {
    174         receiver = Handle<Object>(global, func->GetIsolate());
    175       }
    176     } else {
    177       receiver = ToObject(receiver, pending_exception);
    178     }
    179     if (*pending_exception) return callable;
    180   }
    181 
    182   return Invoke(false, func, receiver, argc, argv, pending_exception);
    183 }
    184 
    185 
    186 Handle<Object> Execution::New(Handle<JSFunction> func,
    187                               int argc,
    188                               Handle<Object> argv[],
    189                               bool* pending_exception) {
    190   return Invoke(true, func, func->GetIsolate()->global_object(), argc, argv,
    191                 pending_exception);
    192 }
    193 
    194 
    195 Handle<Object> Execution::TryCall(Handle<JSFunction> func,
    196                                   Handle<Object> receiver,
    197                                   int argc,
    198                                   Handle<Object> args[],
    199                                   bool* caught_exception) {
    200   // Enter a try-block while executing the JavaScript code. To avoid
    201   // duplicate error printing it must be non-verbose.  Also, to avoid
    202   // creating message objects during stack overflow we shouldn't
    203   // capture messages.
    204   v8::TryCatch catcher;
    205   catcher.SetVerbose(false);
    206   catcher.SetCaptureMessage(false);
    207   *caught_exception = false;
    208 
    209   // Get isolate now, because handle might be persistent
    210   // and get destroyed in the next call.
    211   Isolate* isolate = func->GetIsolate();
    212   Handle<Object> result = Invoke(false, func, receiver, argc, args,
    213                                  caught_exception);
    214 
    215   if (*caught_exception) {
    216     ASSERT(catcher.HasCaught());
    217     ASSERT(isolate->has_pending_exception());
    218     ASSERT(isolate->external_caught_exception());
    219     if (isolate->is_out_of_memory() && !isolate->ignore_out_of_memory()) {
    220       V8::FatalProcessOutOfMemory("OOM during Execution::TryCall");
    221     }
    222     if (isolate->pending_exception() ==
    223         isolate->heap()->termination_exception()) {
    224       result = isolate->factory()->termination_exception();
    225     } else {
    226       result = v8::Utils::OpenHandle(*catcher.Exception());
    227     }
    228     isolate->OptionalRescheduleException(true);
    229   }
    230 
    231   ASSERT(!isolate->has_pending_exception());
    232   ASSERT(!isolate->external_caught_exception());
    233   return result;
    234 }
    235 
    236 
    237 Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
    238   ASSERT(!object->IsJSFunction());
    239   Isolate* isolate = Isolate::Current();
    240   Factory* factory = isolate->factory();
    241 
    242   // If you return a function from here, it will be called when an
    243   // attempt is made to call the given object as a function.
    244 
    245   // If object is a function proxy, get its handler. Iterate if necessary.
    246   Object* fun = *object;
    247   while (fun->IsJSFunctionProxy()) {
    248     fun = JSFunctionProxy::cast(fun)->call_trap();
    249   }
    250   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
    251 
    252   // Objects created through the API can have an instance-call handler
    253   // that should be used when calling the object as a function.
    254   if (fun->IsHeapObject() &&
    255       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
    256     return Handle<JSFunction>(
    257         isolate->native_context()->call_as_function_delegate());
    258   }
    259 
    260   return factory->undefined_value();
    261 }
    262 
    263 
    264 Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object,
    265                                                  bool* has_pending_exception) {
    266   ASSERT(!object->IsJSFunction());
    267   Isolate* isolate = Isolate::Current();
    268 
    269   // If object is a function proxy, get its handler. Iterate if necessary.
    270   Object* fun = *object;
    271   while (fun->IsJSFunctionProxy()) {
    272     fun = JSFunctionProxy::cast(fun)->call_trap();
    273   }
    274   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
    275 
    276   // Objects created through the API can have an instance-call handler
    277   // that should be used when calling the object as a function.
    278   if (fun->IsHeapObject() &&
    279       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
    280     return Handle<JSFunction>(
    281         isolate->native_context()->call_as_function_delegate());
    282   }
    283 
    284   // If the Object doesn't have an instance-call handler we should
    285   // throw a non-callable exception.
    286   i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
    287       "called_non_callable", i::HandleVector<i::Object>(&object, 1));
    288   isolate->Throw(*error_obj);
    289   *has_pending_exception = true;
    290 
    291   return isolate->factory()->undefined_value();
    292 }
    293 
    294 
    295 Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
    296   ASSERT(!object->IsJSFunction());
    297   Isolate* isolate = Isolate::Current();
    298 
    299   // If you return a function from here, it will be called when an
    300   // attempt is made to call the given object as a constructor.
    301 
    302   // If object is a function proxies, get its handler. Iterate if necessary.
    303   Object* fun = *object;
    304   while (fun->IsJSFunctionProxy()) {
    305     fun = JSFunctionProxy::cast(fun)->call_trap();
    306   }
    307   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
    308 
    309   // Objects created through the API can have an instance-call handler
    310   // that should be used when calling the object as a function.
    311   if (fun->IsHeapObject() &&
    312       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
    313     return Handle<JSFunction>(
    314         isolate->native_context()->call_as_constructor_delegate());
    315   }
    316 
    317   return isolate->factory()->undefined_value();
    318 }
    319 
    320 
    321 Handle<Object> Execution::TryGetConstructorDelegate(
    322     Handle<Object> object,
    323     bool* has_pending_exception) {
    324   ASSERT(!object->IsJSFunction());
    325   Isolate* isolate = Isolate::Current();
    326 
    327   // If you return a function from here, it will be called when an
    328   // attempt is made to call the given object as a constructor.
    329 
    330   // If object is a function proxies, get its handler. Iterate if necessary.
    331   Object* fun = *object;
    332   while (fun->IsJSFunctionProxy()) {
    333     fun = JSFunctionProxy::cast(fun)->call_trap();
    334   }
    335   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
    336 
    337   // Objects created through the API can have an instance-call handler
    338   // that should be used when calling the object as a function.
    339   if (fun->IsHeapObject() &&
    340       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
    341     return Handle<JSFunction>(
    342         isolate->native_context()->call_as_constructor_delegate());
    343   }
    344 
    345   // If the Object doesn't have an instance-call handler we should
    346   // throw a non-callable exception.
    347   i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
    348       "called_non_callable", i::HandleVector<i::Object>(&object, 1));
    349   isolate->Throw(*error_obj);
    350   *has_pending_exception = true;
    351 
    352   return isolate->factory()->undefined_value();
    353 }
    354 
    355 
    356 bool StackGuard::IsStackOverflow() {
    357   ExecutionAccess access(isolate_);
    358   return (thread_local_.jslimit_ != kInterruptLimit &&
    359           thread_local_.climit_ != kInterruptLimit);
    360 }
    361 
    362 
    363 void StackGuard::EnableInterrupts() {
    364   ExecutionAccess access(isolate_);
    365   if (has_pending_interrupts(access)) {
    366     set_interrupt_limits(access);
    367   }
    368 }
    369 
    370 
    371 void StackGuard::SetStackLimit(uintptr_t limit) {
    372   ExecutionAccess access(isolate_);
    373   // If the current limits are special (e.g. due to a pending interrupt) then
    374   // leave them alone.
    375   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
    376   if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
    377     thread_local_.jslimit_ = jslimit;
    378   }
    379   if (thread_local_.climit_ == thread_local_.real_climit_) {
    380     thread_local_.climit_ = limit;
    381   }
    382   thread_local_.real_climit_ = limit;
    383   thread_local_.real_jslimit_ = jslimit;
    384 }
    385 
    386 
    387 void StackGuard::DisableInterrupts() {
    388   ExecutionAccess access(isolate_);
    389   reset_limits(access);
    390 }
    391 
    392 
    393 bool StackGuard::ShouldPostponeInterrupts() {
    394   ExecutionAccess access(isolate_);
    395   return should_postpone_interrupts(access);
    396 }
    397 
    398 
    399 bool StackGuard::IsInterrupted() {
    400   ExecutionAccess access(isolate_);
    401   return (thread_local_.interrupt_flags_ & INTERRUPT) != 0;
    402 }
    403 
    404 
    405 void StackGuard::Interrupt() {
    406   ExecutionAccess access(isolate_);
    407   thread_local_.interrupt_flags_ |= INTERRUPT;
    408   set_interrupt_limits(access);
    409 }
    410 
    411 
    412 bool StackGuard::IsPreempted() {
    413   ExecutionAccess access(isolate_);
    414   return thread_local_.interrupt_flags_ & PREEMPT;
    415 }
    416 
    417 
    418 void StackGuard::Preempt() {
    419   ExecutionAccess access(isolate_);
    420   thread_local_.interrupt_flags_ |= PREEMPT;
    421   set_interrupt_limits(access);
    422 }
    423 
    424 
    425 bool StackGuard::IsTerminateExecution() {
    426   ExecutionAccess access(isolate_);
    427   return (thread_local_.interrupt_flags_ & TERMINATE) != 0;
    428 }
    429 
    430 
    431 void StackGuard::CancelTerminateExecution() {
    432   ExecutionAccess access(isolate_);
    433   Continue(TERMINATE);
    434   isolate_->CancelTerminateExecution();
    435 }
    436 
    437 
    438 void StackGuard::TerminateExecution() {
    439   ExecutionAccess access(isolate_);
    440   thread_local_.interrupt_flags_ |= TERMINATE;
    441   set_interrupt_limits(access);
    442 }
    443 
    444 
    445 bool StackGuard::IsGCRequest() {
    446   ExecutionAccess access(isolate_);
    447   return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0;
    448 }
    449 
    450 
    451 void StackGuard::RequestGC() {
    452   ExecutionAccess access(isolate_);
    453   thread_local_.interrupt_flags_ |= GC_REQUEST;
    454   if (thread_local_.postpone_interrupts_nesting_ == 0) {
    455     thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
    456     isolate_->heap()->SetStackLimits();
    457   }
    458 }
    459 
    460 
    461 bool StackGuard::IsFullDeopt() {
    462   ExecutionAccess access(isolate_);
    463   return (thread_local_.interrupt_flags_ & FULL_DEOPT) != 0;
    464 }
    465 
    466 
    467 void StackGuard::FullDeopt() {
    468   ExecutionAccess access(isolate_);
    469   thread_local_.interrupt_flags_ |= FULL_DEOPT;
    470   set_interrupt_limits(access);
    471 }
    472 
    473 
    474 #ifdef ENABLE_DEBUGGER_SUPPORT
    475 bool StackGuard::IsDebugBreak() {
    476   ExecutionAccess access(isolate_);
    477   return thread_local_.interrupt_flags_ & DEBUGBREAK;
    478 }
    479 
    480 
    481 void StackGuard::DebugBreak() {
    482   ExecutionAccess access(isolate_);
    483   thread_local_.interrupt_flags_ |= DEBUGBREAK;
    484   set_interrupt_limits(access);
    485 }
    486 
    487 
    488 bool StackGuard::IsDebugCommand() {
    489   ExecutionAccess access(isolate_);
    490   return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
    491 }
    492 
    493 
    494 void StackGuard::DebugCommand() {
    495   if (FLAG_debugger_auto_break) {
    496     ExecutionAccess access(isolate_);
    497     thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
    498     set_interrupt_limits(access);
    499   }
    500 }
    501 #endif
    502 
    503 void StackGuard::Continue(InterruptFlag after_what) {
    504   ExecutionAccess access(isolate_);
    505   thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
    506   if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
    507     reset_limits(access);
    508   }
    509 }
    510 
    511 
    512 char* StackGuard::ArchiveStackGuard(char* to) {
    513   ExecutionAccess access(isolate_);
    514   OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
    515   ThreadLocal blank;
    516 
    517   // Set the stack limits using the old thread_local_.
    518   // TODO(isolates): This was the old semantics of constructing a ThreadLocal
    519   //                 (as the ctor called SetStackLimits, which looked at the
    520   //                 current thread_local_ from StackGuard)-- but is this
    521   //                 really what was intended?
    522   isolate_->heap()->SetStackLimits();
    523   thread_local_ = blank;
    524 
    525   return to + sizeof(ThreadLocal);
    526 }
    527 
    528 
    529 char* StackGuard::RestoreStackGuard(char* from) {
    530   ExecutionAccess access(isolate_);
    531   OS::MemCopy(
    532       reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
    533   isolate_->heap()->SetStackLimits();
    534   return from + sizeof(ThreadLocal);
    535 }
    536 
    537 
    538 void StackGuard::FreeThreadResources() {
    539   Isolate::PerIsolateThreadData* per_thread =
    540       isolate_->FindOrAllocatePerThreadDataForThisThread();
    541   per_thread->set_stack_limit(thread_local_.real_climit_);
    542 }
    543 
    544 
    545 void StackGuard::ThreadLocal::Clear() {
    546   real_jslimit_ = kIllegalLimit;
    547   jslimit_ = kIllegalLimit;
    548   real_climit_ = kIllegalLimit;
    549   climit_ = kIllegalLimit;
    550   nesting_ = 0;
    551   postpone_interrupts_nesting_ = 0;
    552   interrupt_flags_ = 0;
    553 }
    554 
    555 
    556 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
    557   bool should_set_stack_limits = false;
    558   if (real_climit_ == kIllegalLimit) {
    559     // Takes the address of the limit variable in order to find out where
    560     // the top of stack is right now.
    561     const uintptr_t kLimitSize = FLAG_stack_size * KB;
    562     uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
    563     ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
    564     real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
    565     jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
    566     real_climit_ = limit;
    567     climit_ = limit;
    568     should_set_stack_limits = true;
    569   }
    570   nesting_ = 0;
    571   postpone_interrupts_nesting_ = 0;
    572   interrupt_flags_ = 0;
    573   return should_set_stack_limits;
    574 }
    575 
    576 
    577 void StackGuard::ClearThread(const ExecutionAccess& lock) {
    578   thread_local_.Clear();
    579   isolate_->heap()->SetStackLimits();
    580 }
    581 
    582 
    583 void StackGuard::InitThread(const ExecutionAccess& lock) {
    584   if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
    585   Isolate::PerIsolateThreadData* per_thread =
    586       isolate_->FindOrAllocatePerThreadDataForThisThread();
    587   uintptr_t stored_limit = per_thread->stack_limit();
    588   // You should hold the ExecutionAccess lock when you call this.
    589   if (stored_limit != 0) {
    590     SetStackLimit(stored_limit);
    591   }
    592 }
    593 
    594 
    595 // --- C a l l s   t o   n a t i v e s ---
    596 
    597 #define RETURN_NATIVE_CALL(name, args, has_pending_exception)           \
    598   do {                                                                  \
    599     Isolate* isolate = Isolate::Current();                              \
    600     Handle<Object> argv[] = args;                                       \
    601     ASSERT(has_pending_exception != NULL);                              \
    602     return Call(isolate->name##_fun(),                                  \
    603                 isolate->js_builtins_object(),                          \
    604                 ARRAY_SIZE(argv), argv,                                 \
    605                 has_pending_exception);                                 \
    606   } while (false)
    607 
    608 
    609 Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
    610   RETURN_NATIVE_CALL(to_number, { obj }, exc);
    611 }
    612 
    613 
    614 Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
    615   RETURN_NATIVE_CALL(to_string, { obj }, exc);
    616 }
    617 
    618 
    619 Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
    620   RETURN_NATIVE_CALL(to_detail_string, { obj }, exc);
    621 }
    622 
    623 
    624 Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
    625   if (obj->IsSpecObject()) return obj;
    626   RETURN_NATIVE_CALL(to_object, { obj }, exc);
    627 }
    628 
    629 
    630 Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
    631   RETURN_NATIVE_CALL(to_integer, { obj }, exc);
    632 }
    633 
    634 
    635 Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
    636   RETURN_NATIVE_CALL(to_uint32, { obj }, exc);
    637 }
    638 
    639 
    640 Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
    641   RETURN_NATIVE_CALL(to_int32, { obj }, exc);
    642 }
    643 
    644 
    645 Handle<Object> Execution::NewDate(double time, bool* exc) {
    646   Isolate* isolate = Isolate::Current();
    647   Handle<Object> time_obj = isolate->factory()->NewNumber(time);
    648   RETURN_NATIVE_CALL(create_date, { time_obj }, exc);
    649 }
    650 
    651 
    652 #undef RETURN_NATIVE_CALL
    653 
    654 
    655 Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
    656                                         Handle<String> flags,
    657                                         bool* exc) {
    658   Handle<JSFunction> function = Handle<JSFunction>(
    659       pattern->GetIsolate()->native_context()->regexp_function());
    660   Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
    661       function, pattern, flags, exc);
    662   if (*exc) return Handle<JSRegExp>();
    663   return Handle<JSRegExp>::cast(re_obj);
    664 }
    665 
    666 
    667 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
    668   Isolate* isolate = string->GetIsolate();
    669   Factory* factory = isolate->factory();
    670 
    671   int int_index = static_cast<int>(index);
    672   if (int_index < 0 || int_index >= string->length()) {
    673     return factory->undefined_value();
    674   }
    675 
    676   Handle<Object> char_at = GetProperty(
    677       isolate, isolate->js_builtins_object(), factory->char_at_string());
    678   if (!char_at->IsJSFunction()) {
    679     return factory->undefined_value();
    680   }
    681 
    682   bool caught_exception;
    683   Handle<Object> index_object = factory->NewNumberFromInt(int_index);
    684   Handle<Object> index_arg[] = { index_object };
    685   Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
    686                                   string,
    687                                   ARRAY_SIZE(index_arg),
    688                                   index_arg,
    689                                   &caught_exception);
    690   if (caught_exception) {
    691     return factory->undefined_value();
    692   }
    693   return result;
    694 }
    695 
    696 
    697 Handle<JSFunction> Execution::InstantiateFunction(
    698     Handle<FunctionTemplateInfo> data,
    699     bool* exc) {
    700   Isolate* isolate = data->GetIsolate();
    701   // Fast case: see if the function has already been instantiated
    702   int serial_number = Smi::cast(data->serial_number())->value();
    703   Object* elm =
    704       isolate->native_context()->function_cache()->
    705           GetElementNoExceptionThrown(serial_number);
    706   if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
    707   // The function has not yet been instantiated in this context; do it.
    708   Handle<Object> args[] = { data };
    709   Handle<Object> result = Call(isolate->instantiate_fun(),
    710                                isolate->js_builtins_object(),
    711                                ARRAY_SIZE(args),
    712                                args,
    713                                exc);
    714   if (*exc) return Handle<JSFunction>::null();
    715   return Handle<JSFunction>::cast(result);
    716 }
    717 
    718 
    719 Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
    720                                               bool* exc) {
    721   Isolate* isolate = data->GetIsolate();
    722   if (data->property_list()->IsUndefined() &&
    723       !data->constructor()->IsUndefined()) {
    724     // Initialization to make gcc happy.
    725     Object* result = NULL;
    726     {
    727       HandleScope scope(isolate);
    728       Handle<FunctionTemplateInfo> cons_template =
    729           Handle<FunctionTemplateInfo>(
    730               FunctionTemplateInfo::cast(data->constructor()));
    731       Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
    732       if (*exc) return Handle<JSObject>::null();
    733       Handle<Object> value = New(cons, 0, NULL, exc);
    734       if (*exc) return Handle<JSObject>::null();
    735       result = *value;
    736     }
    737     ASSERT(!*exc);
    738     return Handle<JSObject>(JSObject::cast(result));
    739   } else {
    740     Handle<Object> args[] = { data };
    741     Handle<Object> result = Call(isolate->instantiate_fun(),
    742                                  isolate->js_builtins_object(),
    743                                  ARRAY_SIZE(args),
    744                                  args,
    745                                  exc);
    746     if (*exc) return Handle<JSObject>::null();
    747     return Handle<JSObject>::cast(result);
    748   }
    749 }
    750 
    751 
    752 void Execution::ConfigureInstance(Handle<Object> instance,
    753                                   Handle<Object> instance_template,
    754                                   bool* exc) {
    755   Isolate* isolate = Isolate::Current();
    756   Handle<Object> args[] = { instance, instance_template };
    757   Execution::Call(isolate->configure_instance_fun(),
    758                   isolate->js_builtins_object(),
    759                   ARRAY_SIZE(args),
    760                   args,
    761                   exc);
    762 }
    763 
    764 
    765 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
    766                                             Handle<JSFunction> fun,
    767                                             Handle<Object> pos,
    768                                             Handle<Object> is_global) {
    769   Isolate* isolate = fun->GetIsolate();
    770   Handle<Object> args[] = { recv, fun, pos, is_global };
    771   bool caught_exception;
    772   Handle<Object> result = TryCall(isolate->get_stack_trace_line_fun(),
    773                                   isolate->js_builtins_object(),
    774                                   ARRAY_SIZE(args),
    775                                   args,
    776                                   &caught_exception);
    777   if (caught_exception || !result->IsString()) {
    778       return isolate->factory()->empty_string();
    779   }
    780 
    781   return Handle<String>::cast(result);
    782 }
    783 
    784 
    785 static Object* RuntimePreempt() {
    786   Isolate* isolate = Isolate::Current();
    787 
    788   // Clear the preempt request flag.
    789   isolate->stack_guard()->Continue(PREEMPT);
    790 
    791   ContextSwitcher::PreemptionReceived();
    792 
    793 #ifdef ENABLE_DEBUGGER_SUPPORT
    794   if (isolate->debug()->InDebugger()) {
    795     // If currently in the debugger don't do any actual preemption but record
    796     // that preemption occoured while in the debugger.
    797     isolate->debug()->PreemptionWhileInDebugger();
    798   } else {
    799     // Perform preemption.
    800     v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
    801     Thread::YieldCPU();
    802   }
    803 #else
    804   { // NOLINT
    805     // Perform preemption.
    806     v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
    807     Thread::YieldCPU();
    808   }
    809 #endif
    810 
    811   return isolate->heap()->undefined_value();
    812 }
    813 
    814 
    815 #ifdef ENABLE_DEBUGGER_SUPPORT
    816 Object* Execution::DebugBreakHelper() {
    817   Isolate* isolate = Isolate::Current();
    818 
    819   // Just continue if breaks are disabled.
    820   if (isolate->debug()->disable_break()) {
    821     return isolate->heap()->undefined_value();
    822   }
    823 
    824   // Ignore debug break during bootstrapping.
    825   if (isolate->bootstrapper()->IsActive()) {
    826     return isolate->heap()->undefined_value();
    827   }
    828 
    829   // Ignore debug break if debugger is not active.
    830   if (!isolate->debugger()->IsDebuggerActive()) {
    831     return isolate->heap()->undefined_value();
    832   }
    833 
    834   StackLimitCheck check(isolate);
    835   if (check.HasOverflowed()) {
    836     return isolate->heap()->undefined_value();
    837   }
    838 
    839   {
    840     JavaScriptFrameIterator it(isolate);
    841     ASSERT(!it.done());
    842     Object* fun = it.frame()->function();
    843     if (fun && fun->IsJSFunction()) {
    844       // Don't stop in builtin functions.
    845       if (JSFunction::cast(fun)->IsBuiltin()) {
    846         return isolate->heap()->undefined_value();
    847       }
    848       GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
    849       // Don't stop in debugger functions.
    850       if (isolate->debug()->IsDebugGlobal(global)) {
    851         return isolate->heap()->undefined_value();
    852       }
    853     }
    854   }
    855 
    856   // Collect the break state before clearing the flags.
    857   bool debug_command_only =
    858       isolate->stack_guard()->IsDebugCommand() &&
    859       !isolate->stack_guard()->IsDebugBreak();
    860 
    861   // Clear the debug break request flag.
    862   isolate->stack_guard()->Continue(DEBUGBREAK);
    863 
    864   ProcessDebugMessages(debug_command_only);
    865 
    866   // Return to continue execution.
    867   return isolate->heap()->undefined_value();
    868 }
    869 
    870 
    871 void Execution::ProcessDebugMessages(bool debug_command_only) {
    872   Isolate* isolate = Isolate::Current();
    873   // Clear the debug command request flag.
    874   isolate->stack_guard()->Continue(DEBUGCOMMAND);
    875 
    876   StackLimitCheck check(isolate);
    877   if (check.HasOverflowed()) {
    878     return;
    879   }
    880 
    881   HandleScope scope(isolate);
    882   // Enter the debugger. Just continue if we fail to enter the debugger.
    883   EnterDebugger debugger;
    884   if (debugger.FailedToEnter()) {
    885     return;
    886   }
    887 
    888   // Notify the debug event listeners. Indicate auto continue if the break was
    889   // a debug command break.
    890   isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(),
    891                                     debug_command_only);
    892 }
    893 
    894 
    895 #endif
    896 
    897 MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
    898   StackGuard* stack_guard = isolate->stack_guard();
    899   if (stack_guard->ShouldPostponeInterrupts()) {
    900     return isolate->heap()->undefined_value();
    901   }
    902 
    903   if (stack_guard->IsGCRequest()) {
    904     isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
    905                                        "StackGuard GC request");
    906     stack_guard->Continue(GC_REQUEST);
    907   }
    908 
    909   isolate->counters()->stack_interrupts()->Increment();
    910   isolate->counters()->runtime_profiler_ticks()->Increment();
    911   isolate->runtime_profiler()->OptimizeNow();
    912 #ifdef ENABLE_DEBUGGER_SUPPORT
    913   if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
    914     DebugBreakHelper();
    915   }
    916 #endif
    917   if (stack_guard->IsPreempted()) RuntimePreempt();
    918   if (stack_guard->IsTerminateExecution()) {
    919     stack_guard->Continue(TERMINATE);
    920     return isolate->TerminateExecution();
    921   }
    922   if (stack_guard->IsInterrupted()) {
    923     stack_guard->Continue(INTERRUPT);
    924     return isolate->StackOverflow();
    925   }
    926   if (stack_guard->IsFullDeopt()) {
    927     stack_guard->Continue(FULL_DEOPT);
    928     Deoptimizer::DeoptimizeAll(isolate);
    929   }
    930   return isolate->heap()->undefined_value();
    931 }
    932 
    933 
    934 } }  // namespace v8::internal
    935