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