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