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