Home | History | Annotate | Download | only in src
      1 // Copyright 2011 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 "runtime-profiler.h"
     37 #include "simulator.h"
     38 #include "v8threads.h"
     39 #include "vm-state-inl.h"
     40 
     41 namespace v8 {
     42 namespace internal {
     43 
     44 
     45 StackGuard::StackGuard()
     46     : isolate_(NULL) {
     47 }
     48 
     49 
     50 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
     51   ASSERT(isolate_ != NULL);
     52   // Ignore attempts to interrupt when interrupts are postponed.
     53   if (should_postpone_interrupts(lock)) return;
     54   thread_local_.jslimit_ = kInterruptLimit;
     55   thread_local_.climit_ = kInterruptLimit;
     56   isolate_->heap()->SetStackLimits();
     57 }
     58 
     59 
     60 void StackGuard::reset_limits(const ExecutionAccess& lock) {
     61   ASSERT(isolate_ != NULL);
     62   thread_local_.jslimit_ = thread_local_.real_jslimit_;
     63   thread_local_.climit_ = thread_local_.real_climit_;
     64   isolate_->heap()->SetStackLimits();
     65 }
     66 
     67 
     68 static Handle<Object> Invoke(bool construct,
     69                              Handle<JSFunction> func,
     70                              Handle<Object> receiver,
     71                              int argc,
     72                              Object*** args,
     73                              bool* has_pending_exception) {
     74   Isolate* isolate = func->GetIsolate();
     75 
     76   // Entering JavaScript.
     77   VMState state(isolate, JS);
     78 
     79   // Placeholder for return value.
     80   MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
     81 
     82   typedef Object* (*JSEntryFunction)(
     83     byte* entry,
     84     Object* function,
     85     Object* receiver,
     86     int argc,
     87     Object*** args);
     88 
     89   Handle<Code> code;
     90   if (construct) {
     91     JSConstructEntryStub stub;
     92     code = stub.GetCode();
     93   } else {
     94     JSEntryStub stub;
     95     code = stub.GetCode();
     96   }
     97 
     98   // Convert calls on global objects to be calls on the global
     99   // receiver instead to avoid having a 'this' pointer which refers
    100   // directly to a global object.
    101   if (receiver->IsGlobalObject()) {
    102     Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
    103     receiver = Handle<JSObject>(global->global_receiver());
    104   }
    105 
    106   // Make sure that the global object of the context we're about to
    107   // make the current one is indeed a global object.
    108   ASSERT(func->context()->global()->IsGlobalObject());
    109 
    110   {
    111     // Save and restore context around invocation and block the
    112     // allocation of handles without explicit handle scopes.
    113     SaveContext save(isolate);
    114     NoHandleAllocation na;
    115     JSEntryFunction entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
    116 
    117     // Call the function through the right JS entry stub.
    118     byte* entry_address = func->code()->entry();
    119     JSFunction* function = *func;
    120     Object* receiver_pointer = *receiver;
    121     value = CALL_GENERATED_CODE(entry, entry_address, function,
    122                                 receiver_pointer, argc, args);
    123   }
    124 
    125 #ifdef DEBUG
    126   value->Verify();
    127 #endif
    128 
    129   // Update the pending exception flag and return the value.
    130   *has_pending_exception = value->IsException();
    131   ASSERT(*has_pending_exception == Isolate::Current()->has_pending_exception());
    132   if (*has_pending_exception) {
    133     isolate->ReportPendingMessages();
    134     if (isolate->pending_exception() == Failure::OutOfMemoryException()) {
    135       if (!isolate->ignore_out_of_memory()) {
    136         V8::FatalProcessOutOfMemory("JS", true);
    137       }
    138     }
    139     return Handle<Object>();
    140   } else {
    141     isolate->clear_pending_message();
    142   }
    143 
    144   return Handle<Object>(value->ToObjectUnchecked(), isolate);
    145 }
    146 
    147 
    148 Handle<Object> Execution::Call(Handle<JSFunction> func,
    149                                Handle<Object> receiver,
    150                                int argc,
    151                                Object*** args,
    152                                bool* pending_exception) {
    153   return Invoke(false, func, receiver, argc, args, pending_exception);
    154 }
    155 
    156 
    157 Handle<Object> Execution::New(Handle<JSFunction> func, int argc,
    158                               Object*** args, bool* pending_exception) {
    159   return Invoke(true, func, Isolate::Current()->global(), argc, args,
    160                 pending_exception);
    161 }
    162 
    163 
    164 Handle<Object> Execution::TryCall(Handle<JSFunction> func,
    165                                   Handle<Object> receiver,
    166                                   int argc,
    167                                   Object*** args,
    168                                   bool* caught_exception) {
    169   // Enter a try-block while executing the JavaScript code. To avoid
    170   // duplicate error printing it must be non-verbose.  Also, to avoid
    171   // creating message objects during stack overflow we shouldn't
    172   // capture messages.
    173   v8::TryCatch catcher;
    174   catcher.SetVerbose(false);
    175   catcher.SetCaptureMessage(false);
    176 
    177   Handle<Object> result = Invoke(false, func, receiver, argc, args,
    178                                  caught_exception);
    179 
    180   if (*caught_exception) {
    181     ASSERT(catcher.HasCaught());
    182     Isolate* isolate = Isolate::Current();
    183     ASSERT(isolate->has_pending_exception());
    184     ASSERT(isolate->external_caught_exception());
    185     if (isolate->pending_exception() ==
    186         isolate->heap()->termination_exception()) {
    187       result = isolate->factory()->termination_exception();
    188     } else {
    189       result = v8::Utils::OpenHandle(*catcher.Exception());
    190     }
    191     isolate->OptionalRescheduleException(true);
    192   }
    193 
    194   ASSERT(!Isolate::Current()->has_pending_exception());
    195   ASSERT(!Isolate::Current()->external_caught_exception());
    196   return result;
    197 }
    198 
    199 
    200 Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
    201   ASSERT(!object->IsJSFunction());
    202   Isolate* isolate = Isolate::Current();
    203   Factory* factory = isolate->factory();
    204 
    205   // If you return a function from here, it will be called when an
    206   // attempt is made to call the given object as a function.
    207 
    208   // Regular expressions can be called as functions in both Firefox
    209   // and Safari so we allow it too.
    210   if (object->IsJSRegExp()) {
    211     Handle<String> exec = factory->exec_symbol();
    212     // TODO(lrn): Bug 617.  We should use the default function here, not the
    213     // one on the RegExp object.
    214     Object* exec_function;
    215     { MaybeObject* maybe_exec_function = object->GetProperty(*exec);
    216       // This can lose an exception, but the alternative is to put a failure
    217       // object in a handle, which is not GC safe.
    218       if (!maybe_exec_function->ToObject(&exec_function)) {
    219         return factory->undefined_value();
    220       }
    221     }
    222     return Handle<Object>(exec_function);
    223   }
    224 
    225   // Objects created through the API can have an instance-call handler
    226   // that should be used when calling the object as a function.
    227   if (object->IsHeapObject() &&
    228       HeapObject::cast(*object)->map()->has_instance_call_handler()) {
    229     return Handle<JSFunction>(
    230         isolate->global_context()->call_as_function_delegate());
    231   }
    232 
    233   return factory->undefined_value();
    234 }
    235 
    236 
    237 Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
    238   ASSERT(!object->IsJSFunction());
    239   Isolate* isolate = Isolate::Current();
    240 
    241   // If you return a function from here, it will be called when an
    242   // attempt is made to call the given object as a constructor.
    243 
    244   // Objects created through the API can have an instance-call handler
    245   // that should be used when calling the object as a function.
    246   if (object->IsHeapObject() &&
    247       HeapObject::cast(*object)->map()->has_instance_call_handler()) {
    248     return Handle<JSFunction>(
    249         isolate->global_context()->call_as_constructor_delegate());
    250   }
    251 
    252   return isolate->factory()->undefined_value();
    253 }
    254 
    255 
    256 bool StackGuard::IsStackOverflow() {
    257   ExecutionAccess access(isolate_);
    258   return (thread_local_.jslimit_ != kInterruptLimit &&
    259           thread_local_.climit_ != kInterruptLimit);
    260 }
    261 
    262 
    263 void StackGuard::EnableInterrupts() {
    264   ExecutionAccess access(isolate_);
    265   if (has_pending_interrupts(access)) {
    266     set_interrupt_limits(access);
    267   }
    268 }
    269 
    270 
    271 void StackGuard::SetStackLimit(uintptr_t limit) {
    272   ExecutionAccess access(isolate_);
    273   // If the current limits are special (eg due to a pending interrupt) then
    274   // leave them alone.
    275   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(limit);
    276   if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
    277     thread_local_.jslimit_ = jslimit;
    278   }
    279   if (thread_local_.climit_ == thread_local_.real_climit_) {
    280     thread_local_.climit_ = limit;
    281   }
    282   thread_local_.real_climit_ = limit;
    283   thread_local_.real_jslimit_ = jslimit;
    284 }
    285 
    286 
    287 void StackGuard::DisableInterrupts() {
    288   ExecutionAccess access(isolate_);
    289   reset_limits(access);
    290 }
    291 
    292 
    293 bool StackGuard::IsInterrupted() {
    294   ExecutionAccess access(isolate_);
    295   return thread_local_.interrupt_flags_ & INTERRUPT;
    296 }
    297 
    298 
    299 void StackGuard::Interrupt() {
    300   ExecutionAccess access(isolate_);
    301   thread_local_.interrupt_flags_ |= INTERRUPT;
    302   set_interrupt_limits(access);
    303 }
    304 
    305 
    306 bool StackGuard::IsPreempted() {
    307   ExecutionAccess access(isolate_);
    308   return thread_local_.interrupt_flags_ & PREEMPT;
    309 }
    310 
    311 
    312 void StackGuard::Preempt() {
    313   ExecutionAccess access(isolate_);
    314   thread_local_.interrupt_flags_ |= PREEMPT;
    315   set_interrupt_limits(access);
    316 }
    317 
    318 
    319 bool StackGuard::IsTerminateExecution() {
    320   ExecutionAccess access(isolate_);
    321   return thread_local_.interrupt_flags_ & TERMINATE;
    322 }
    323 
    324 
    325 void StackGuard::TerminateExecution() {
    326   ExecutionAccess access(isolate_);
    327   thread_local_.interrupt_flags_ |= TERMINATE;
    328   set_interrupt_limits(access);
    329 }
    330 
    331 
    332 bool StackGuard::IsRuntimeProfilerTick() {
    333   ExecutionAccess access(isolate_);
    334   return thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK;
    335 }
    336 
    337 
    338 void StackGuard::RequestRuntimeProfilerTick() {
    339   // Ignore calls if we're not optimizing or if we can't get the lock.
    340   if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) {
    341     thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK;
    342     if (thread_local_.postpone_interrupts_nesting_ == 0) {
    343       thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
    344       isolate_->heap()->SetStackLimits();
    345     }
    346     ExecutionAccess::Unlock(isolate_);
    347   }
    348 }
    349 
    350 
    351 #ifdef ENABLE_DEBUGGER_SUPPORT
    352 bool StackGuard::IsDebugBreak() {
    353   ExecutionAccess access(isolate_);
    354   return thread_local_.interrupt_flags_ & DEBUGBREAK;
    355 }
    356 
    357 
    358 void StackGuard::DebugBreak() {
    359   ExecutionAccess access(isolate_);
    360   thread_local_.interrupt_flags_ |= DEBUGBREAK;
    361   set_interrupt_limits(access);
    362 }
    363 
    364 
    365 bool StackGuard::IsDebugCommand() {
    366   ExecutionAccess access(isolate_);
    367   return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
    368 }
    369 
    370 
    371 void StackGuard::DebugCommand() {
    372   if (FLAG_debugger_auto_break) {
    373     ExecutionAccess access(isolate_);
    374     thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
    375     set_interrupt_limits(access);
    376   }
    377 }
    378 #endif
    379 
    380 void StackGuard::Continue(InterruptFlag after_what) {
    381   ExecutionAccess access(isolate_);
    382   thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
    383   if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
    384     reset_limits(access);
    385   }
    386 }
    387 
    388 
    389 char* StackGuard::ArchiveStackGuard(char* to) {
    390   ExecutionAccess access(isolate_);
    391   memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
    392   ThreadLocal blank;
    393 
    394   // Set the stack limits using the old thread_local_.
    395   // TODO(isolates): This was the old semantics of constructing a ThreadLocal
    396   //                 (as the ctor called SetStackLimits, which looked at the
    397   //                 current thread_local_ from StackGuard)-- but is this
    398   //                 really what was intended?
    399   isolate_->heap()->SetStackLimits();
    400   thread_local_ = blank;
    401 
    402   return to + sizeof(ThreadLocal);
    403 }
    404 
    405 
    406 char* StackGuard::RestoreStackGuard(char* from) {
    407   ExecutionAccess access(isolate_);
    408   memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
    409   isolate_->heap()->SetStackLimits();
    410   return from + sizeof(ThreadLocal);
    411 }
    412 
    413 
    414 void StackGuard::FreeThreadResources() {
    415   Isolate::CurrentPerIsolateThreadData()->set_stack_limit(
    416       thread_local_.real_climit_);
    417 }
    418 
    419 
    420 void StackGuard::ThreadLocal::Clear() {
    421   real_jslimit_ = kIllegalLimit;
    422   jslimit_ = kIllegalLimit;
    423   real_climit_ = kIllegalLimit;
    424   climit_ = kIllegalLimit;
    425   nesting_ = 0;
    426   postpone_interrupts_nesting_ = 0;
    427   interrupt_flags_ = 0;
    428 }
    429 
    430 
    431 bool StackGuard::ThreadLocal::Initialize() {
    432   bool should_set_stack_limits = false;
    433   if (real_climit_ == kIllegalLimit) {
    434     // Takes the address of the limit variable in order to find out where
    435     // the top of stack is right now.
    436     const uintptr_t kLimitSize = FLAG_stack_size * KB;
    437     uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
    438     ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
    439     real_jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
    440     jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
    441     real_climit_ = limit;
    442     climit_ = limit;
    443     should_set_stack_limits = true;
    444   }
    445   nesting_ = 0;
    446   postpone_interrupts_nesting_ = 0;
    447   interrupt_flags_ = 0;
    448   return should_set_stack_limits;
    449 }
    450 
    451 
    452 void StackGuard::ClearThread(const ExecutionAccess& lock) {
    453   thread_local_.Clear();
    454   isolate_->heap()->SetStackLimits();
    455 }
    456 
    457 
    458 void StackGuard::InitThread(const ExecutionAccess& lock) {
    459   if (thread_local_.Initialize()) isolate_->heap()->SetStackLimits();
    460   uintptr_t stored_limit =
    461       Isolate::CurrentPerIsolateThreadData()->stack_limit();
    462   // You should hold the ExecutionAccess lock when you call this.
    463   if (stored_limit != 0) {
    464     StackGuard::SetStackLimit(stored_limit);
    465   }
    466 }
    467 
    468 
    469 // --- C a l l s   t o   n a t i v e s ---
    470 
    471 #define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception)            \
    472   do {                                                                         \
    473     Isolate* isolate = Isolate::Current();                                     \
    474     Object** args[argc] = argv;                                                \
    475     ASSERT(has_pending_exception != NULL);                                     \
    476     return Call(isolate->name##_fun(),                                         \
    477                 isolate->js_builtins_object(), argc, args,                     \
    478                 has_pending_exception);                                        \
    479   } while (false)
    480 
    481 
    482 Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
    483   // See the similar code in runtime.js:ToBoolean.
    484   if (obj->IsBoolean()) return obj;
    485   bool result = true;
    486   if (obj->IsString()) {
    487     result = Handle<String>::cast(obj)->length() != 0;
    488   } else if (obj->IsNull() || obj->IsUndefined()) {
    489     result = false;
    490   } else if (obj->IsNumber()) {
    491     double value = obj->Number();
    492     result = !((value == 0) || isnan(value));
    493   }
    494   return Handle<Object>(HEAP->ToBoolean(result));
    495 }
    496 
    497 
    498 Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
    499   RETURN_NATIVE_CALL(to_number, 1, { obj.location() }, exc);
    500 }
    501 
    502 
    503 Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
    504   RETURN_NATIVE_CALL(to_string, 1, { obj.location() }, exc);
    505 }
    506 
    507 
    508 Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
    509   RETURN_NATIVE_CALL(to_detail_string, 1, { obj.location() }, exc);
    510 }
    511 
    512 
    513 Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
    514   if (obj->IsJSObject()) return obj;
    515   RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc);
    516 }
    517 
    518 
    519 Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
    520   RETURN_NATIVE_CALL(to_integer, 1, { obj.location() }, exc);
    521 }
    522 
    523 
    524 Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
    525   RETURN_NATIVE_CALL(to_uint32, 1, { obj.location() }, exc);
    526 }
    527 
    528 
    529 Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
    530   RETURN_NATIVE_CALL(to_int32, 1, { obj.location() }, exc);
    531 }
    532 
    533 
    534 Handle<Object> Execution::NewDate(double time, bool* exc) {
    535   Handle<Object> time_obj = FACTORY->NewNumber(time);
    536   RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
    537 }
    538 
    539 
    540 #undef RETURN_NATIVE_CALL
    541 
    542 
    543 Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
    544                                         Handle<String> flags,
    545                                         bool* exc) {
    546   Handle<JSFunction> function = Handle<JSFunction>(
    547       pattern->GetIsolate()->global_context()->regexp_function());
    548   Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
    549       function, pattern, flags, exc);
    550   if (*exc) return Handle<JSRegExp>();
    551   return Handle<JSRegExp>::cast(re_obj);
    552 }
    553 
    554 
    555 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
    556   Isolate* isolate = string->GetIsolate();
    557   Factory* factory = isolate->factory();
    558 
    559   int int_index = static_cast<int>(index);
    560   if (int_index < 0 || int_index >= string->length()) {
    561     return factory->undefined_value();
    562   }
    563 
    564   Handle<Object> char_at =
    565       GetProperty(isolate->js_builtins_object(),
    566                   factory->char_at_symbol());
    567   if (!char_at->IsJSFunction()) {
    568     return factory->undefined_value();
    569   }
    570 
    571   bool caught_exception;
    572   Handle<Object> index_object = factory->NewNumberFromInt(int_index);
    573   Object** index_arg[] = { index_object.location() };
    574   Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
    575                                   string,
    576                                   ARRAY_SIZE(index_arg),
    577                                   index_arg,
    578                                   &caught_exception);
    579   if (caught_exception) {
    580     return factory->undefined_value();
    581   }
    582   return result;
    583 }
    584 
    585 
    586 Handle<JSFunction> Execution::InstantiateFunction(
    587     Handle<FunctionTemplateInfo> data, bool* exc) {
    588   Isolate* isolate = data->GetIsolate();
    589   // Fast case: see if the function has already been instantiated
    590   int serial_number = Smi::cast(data->serial_number())->value();
    591   Object* elm =
    592       isolate->global_context()->function_cache()->
    593           GetElementNoExceptionThrown(serial_number);
    594   if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
    595   // The function has not yet been instantiated in this context; do it.
    596   Object** args[1] = { Handle<Object>::cast(data).location() };
    597   Handle<Object> result =
    598       Call(isolate->instantiate_fun(),
    599            isolate->js_builtins_object(), 1, args, exc);
    600   if (*exc) return Handle<JSFunction>::null();
    601   return Handle<JSFunction>::cast(result);
    602 }
    603 
    604 
    605 Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
    606                                               bool* exc) {
    607   Isolate* isolate = data->GetIsolate();
    608   if (data->property_list()->IsUndefined() &&
    609       !data->constructor()->IsUndefined()) {
    610     // Initialization to make gcc happy.
    611     Object* result = NULL;
    612     {
    613       HandleScope scope(isolate);
    614       Handle<FunctionTemplateInfo> cons_template =
    615           Handle<FunctionTemplateInfo>(
    616               FunctionTemplateInfo::cast(data->constructor()));
    617       Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
    618       if (*exc) return Handle<JSObject>::null();
    619       Handle<Object> value = New(cons, 0, NULL, exc);
    620       if (*exc) return Handle<JSObject>::null();
    621       result = *value;
    622     }
    623     ASSERT(!*exc);
    624     return Handle<JSObject>(JSObject::cast(result));
    625   } else {
    626     Object** args[1] = { Handle<Object>::cast(data).location() };
    627     Handle<Object> result =
    628         Call(isolate->instantiate_fun(),
    629              isolate->js_builtins_object(), 1, args, exc);
    630     if (*exc) return Handle<JSObject>::null();
    631     return Handle<JSObject>::cast(result);
    632   }
    633 }
    634 
    635 
    636 void Execution::ConfigureInstance(Handle<Object> instance,
    637                                   Handle<Object> instance_template,
    638                                   bool* exc) {
    639   Isolate* isolate = Isolate::Current();
    640   Object** args[2] = { instance.location(), instance_template.location() };
    641   Execution::Call(isolate->configure_instance_fun(),
    642                   isolate->js_builtins_object(), 2, args, exc);
    643 }
    644 
    645 
    646 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
    647                                             Handle<JSFunction> fun,
    648                                             Handle<Object> pos,
    649                                             Handle<Object> is_global) {
    650   Isolate* isolate = fun->GetIsolate();
    651   const int argc = 4;
    652   Object** args[argc] = { recv.location(),
    653                           Handle<Object>::cast(fun).location(),
    654                           pos.location(),
    655                           is_global.location() };
    656   bool caught_exception = false;
    657   Handle<Object> result =
    658       TryCall(isolate->get_stack_trace_line_fun(),
    659               isolate->js_builtins_object(), argc, args,
    660               &caught_exception);
    661   if (caught_exception || !result->IsString()) {
    662       return isolate->factory()->empty_symbol();
    663   }
    664 
    665   return Handle<String>::cast(result);
    666 }
    667 
    668 
    669 static Object* RuntimePreempt() {
    670   Isolate* isolate = Isolate::Current();
    671 
    672   // Clear the preempt request flag.
    673   isolate->stack_guard()->Continue(PREEMPT);
    674 
    675   ContextSwitcher::PreemptionReceived();
    676 
    677 #ifdef ENABLE_DEBUGGER_SUPPORT
    678   if (isolate->debug()->InDebugger()) {
    679     // If currently in the debugger don't do any actual preemption but record
    680     // that preemption occoured while in the debugger.
    681     isolate->debug()->PreemptionWhileInDebugger();
    682   } else {
    683     // Perform preemption.
    684     v8::Unlocker unlocker;
    685     Thread::YieldCPU();
    686   }
    687 #else
    688   { // NOLINT
    689     // Perform preemption.
    690     v8::Unlocker unlocker;
    691     Thread::YieldCPU();
    692   }
    693 #endif
    694 
    695   return isolate->heap()->undefined_value();
    696 }
    697 
    698 
    699 #ifdef ENABLE_DEBUGGER_SUPPORT
    700 Object* Execution::DebugBreakHelper() {
    701   Isolate* isolate = Isolate::Current();
    702 
    703   // Just continue if breaks are disabled.
    704   if (isolate->debug()->disable_break()) {
    705     return isolate->heap()->undefined_value();
    706   }
    707 
    708   // Ignore debug break during bootstrapping.
    709   if (isolate->bootstrapper()->IsActive()) {
    710     return isolate->heap()->undefined_value();
    711   }
    712 
    713   {
    714     JavaScriptFrameIterator it(isolate);
    715     ASSERT(!it.done());
    716     Object* fun = it.frame()->function();
    717     if (fun && fun->IsJSFunction()) {
    718       // Don't stop in builtin functions.
    719       if (JSFunction::cast(fun)->IsBuiltin()) {
    720         return isolate->heap()->undefined_value();
    721       }
    722       GlobalObject* global = JSFunction::cast(fun)->context()->global();
    723       // Don't stop in debugger functions.
    724       if (isolate->debug()->IsDebugGlobal(global)) {
    725         return isolate->heap()->undefined_value();
    726       }
    727     }
    728   }
    729 
    730   // Collect the break state before clearing the flags.
    731   bool debug_command_only =
    732       isolate->stack_guard()->IsDebugCommand() &&
    733       !isolate->stack_guard()->IsDebugBreak();
    734 
    735   // Clear the debug break request flag.
    736   isolate->stack_guard()->Continue(DEBUGBREAK);
    737 
    738   ProcessDebugMesssages(debug_command_only);
    739 
    740   // Return to continue execution.
    741   return isolate->heap()->undefined_value();
    742 }
    743 
    744 void Execution::ProcessDebugMesssages(bool debug_command_only) {
    745   Isolate* isolate = Isolate::Current();
    746   // Clear the debug command request flag.
    747   isolate->stack_guard()->Continue(DEBUGCOMMAND);
    748 
    749   HandleScope scope(isolate);
    750   // Enter the debugger. Just continue if we fail to enter the debugger.
    751   EnterDebugger debugger;
    752   if (debugger.FailedToEnter()) {
    753     return;
    754   }
    755 
    756   // Notify the debug event listeners. Indicate auto continue if the break was
    757   // a debug command break.
    758   isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(),
    759                                     debug_command_only);
    760 }
    761 
    762 
    763 #endif
    764 
    765 MaybeObject* Execution::HandleStackGuardInterrupt() {
    766   Isolate* isolate = Isolate::Current();
    767   StackGuard* stack_guard = isolate->stack_guard();
    768   isolate->counters()->stack_interrupts()->Increment();
    769   if (stack_guard->IsRuntimeProfilerTick()) {
    770     isolate->counters()->runtime_profiler_ticks()->Increment();
    771     stack_guard->Continue(RUNTIME_PROFILER_TICK);
    772     isolate->runtime_profiler()->OptimizeNow();
    773   }
    774 #ifdef ENABLE_DEBUGGER_SUPPORT
    775   if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
    776     DebugBreakHelper();
    777   }
    778 #endif
    779   if (stack_guard->IsPreempted()) RuntimePreempt();
    780   if (stack_guard->IsTerminateExecution()) {
    781     stack_guard->Continue(TERMINATE);
    782     return isolate->TerminateExecution();
    783   }
    784   if (stack_guard->IsInterrupted()) {
    785     stack_guard->Continue(INTERRUPT);
    786     return isolate->StackOverflow();
    787   }
    788   return isolate->heap()->undefined_value();
    789 }
    790 
    791 } }  // namespace v8::internal
    792