blob: 8fa059abf8562ea7373b27b7b51609fe5e8e8db4 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
ager@chromium.orga74f0da2008-12-03 16:05:52 +000035#ifdef ARM
ager@chromium.org3a37e9b2009-04-27 09:26:21 +000036#include "arm/simulator-arm.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037#else // ia32
ager@chromium.org3a37e9b2009-04-27 09:26:21 +000038#include "ia32/simulator-ia32.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039#endif
40
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000041#include "debug.h"
42#include "v8threads.h"
43
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000044namespace v8 { namespace internal {
45
46
47static Handle<Object> Invoke(bool construct,
48 Handle<JSFunction> func,
49 Handle<Object> receiver,
50 int argc,
51 Object*** args,
52 bool* has_pending_exception) {
53 // Make sure we have a real function, not a boilerplate function.
54 ASSERT(!func->IsBoilerplate());
55
56 // Entering JavaScript.
57 VMState state(JS);
58
59 // Guard the stack against too much recursion.
60 StackGuard guard;
61
62 // Placeholder for return value.
63 Object* value = reinterpret_cast<Object*>(kZapValue);
64
65 typedef Object* (*JSEntryFunction)(
66 byte* entry,
67 Object* function,
68 Object* receiver,
69 int argc,
70 Object*** args);
71
72 Handle<Code> code;
73 if (construct) {
74 JSConstructEntryStub stub;
75 code = stub.GetCode();
76 } else {
77 JSEntryStub stub;
78 code = stub.GetCode();
79 }
80
kasper.lund44510672008-07-25 07:37:58 +000081 {
82 // Save and restore context around invocation and block the
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000083 // allocation of handles without explicit handle scopes.
84 SaveContext save;
85 NoHandleAllocation na;
86 JSEntryFunction entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
87
88 // Call the function through the right JS entry stub.
89 value = CALL_GENERATED_CODE(entry, func->code()->entry(), *func,
90 *receiver, argc, args);
91 }
92
93#ifdef DEBUG
94 value->Verify();
95#endif
96
97 // Update the pending exception flag and return the value.
98 *has_pending_exception = value->IsException();
99 ASSERT(*has_pending_exception == Top::has_pending_exception());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000100 if (*has_pending_exception) {
ager@chromium.org8bb60582008-12-11 12:02:20 +0000101 Top::ReportPendingMessages();
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000102 return Handle<Object>();
ager@chromium.org8bb60582008-12-11 12:02:20 +0000103 } else {
104 Top::clear_pending_message();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000105 }
106
107 return Handle<Object>(value);
108}
109
110
111Handle<Object> Execution::Call(Handle<JSFunction> func,
112 Handle<Object> receiver,
113 int argc,
114 Object*** args,
115 bool* pending_exception) {
116 return Invoke(false, func, receiver, argc, args, pending_exception);
117}
118
119
120Handle<Object> Execution::New(Handle<JSFunction> func, int argc,
121 Object*** args, bool* pending_exception) {
122 return Invoke(true, func, Top::global(), argc, args, pending_exception);
123}
124
125
126Handle<Object> Execution::TryCall(Handle<JSFunction> func,
127 Handle<Object> receiver,
128 int argc,
129 Object*** args,
130 bool* caught_exception) {
131 // Enter a try-block while executing the JavaScript code. To avoid
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000132 // duplicate error printing it must be non-verbose. Also, to avoid
133 // creating message objects during stack overflow we shouldn't
134 // capture messages.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000135 v8::TryCatch catcher;
136 catcher.SetVerbose(false);
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000137 catcher.SetCaptureMessage(false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000138
139 Handle<Object> result = Invoke(false, func, receiver, argc, args,
140 caught_exception);
141
142 if (*caught_exception) {
143 ASSERT(catcher.HasCaught());
144 ASSERT(Top::has_pending_exception());
145 ASSERT(Top::external_caught_exception());
146 Top::optional_reschedule_exception(true);
147 result = v8::Utils::OpenHandle(*catcher.Exception());
148 }
149
150 ASSERT(!Top::has_pending_exception());
151 ASSERT(!Top::external_caught_exception());
152 return result;
153}
154
155
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000156Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
157 ASSERT(!object->IsJSFunction());
158
159 // If you return a function from here, it will be called when an
160 // attempt is made to call the given object as a function.
161
162 // The regular expression code here is really meant more as an
163 // example than anything else. KJS does not support calling regular
164 // expressions as functions, but SpiderMonkey does.
165 if (FLAG_call_regexp) {
166 bool is_regexp =
167 object->IsHeapObject() &&
168 (HeapObject::cast(*object)->map()->constructor() ==
169 *Top::regexp_function());
170
171 if (is_regexp) {
172 Handle<String> exec = Factory::exec_symbol();
173 return Handle<Object>(object->GetProperty(*exec));
174 }
175 }
176
177 // Objects created through the API can have an instance-call handler
178 // that should be used when calling the object as a function.
179 if (object->IsHeapObject() &&
180 HeapObject::cast(*object)->map()->has_instance_call_handler()) {
181 return Handle<JSFunction>(
182 Top::global_context()->call_as_function_delegate());
183 }
184
185 return Factory::undefined_value();
186}
187
188
189// Static state for stack guards.
190StackGuard::ThreadLocal StackGuard::thread_local_;
191
192
193StackGuard::StackGuard() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000194 // NOTE: Overall the StackGuard code assumes that the stack grows towards
195 // lower addresses.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196 ExecutionAccess access;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000197 if (thread_local_.nesting_++ == 0) {
198 // Initial StackGuard is being set. We will set the stack limits based on
199 // the current stack pointer allowing the stack to grow kLimitSize from
200 // here.
201
202 // Ensure that either the stack limits are unset (kIllegalLimit) or that
203 // they indicate a pending interruption. The interrupt limit will be
204 // temporarily reset through the code below and reestablished if the
205 // interrupt flags indicate that an interrupt is pending.
206 ASSERT(thread_local_.jslimit_ == kIllegalLimit ||
207 (thread_local_.jslimit_ == kInterruptLimit &&
208 thread_local_.interrupt_flags_ != 0));
209 ASSERT(thread_local_.climit_ == kIllegalLimit ||
210 (thread_local_.climit_ == kInterruptLimit &&
211 thread_local_.interrupt_flags_ != 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212
213 thread_local_.initial_jslimit_ = thread_local_.jslimit_ =
kasper.lund7276f142008-07-30 08:49:36 +0000214 GENERATED_CODE_STACK_LIMIT(kLimitSize);
v8.team.kasperl727e9952008-09-02 14:56:44 +0000215 // NOTE: The check for overflow is not safe as there is no guarantee that
kasper.lund7276f142008-07-30 08:49:36 +0000216 // the running thread has its stack in all memory up to address 0x00000000.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000217 thread_local_.initial_climit_ = thread_local_.climit_ =
kasper.lund7276f142008-07-30 08:49:36 +0000218 reinterpret_cast<uintptr_t>(this) >= kLimitSize ?
219 reinterpret_cast<uintptr_t>(this) - kLimitSize : 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220
221 if (thread_local_.interrupt_flags_ != 0) {
222 set_limits(kInterruptLimit, access);
223 }
224 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000225 // Ensure that proper limits have been set.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000226 ASSERT(thread_local_.jslimit_ != kIllegalLimit &&
227 thread_local_.climit_ != kIllegalLimit);
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000228 ASSERT(thread_local_.initial_jslimit_ != kIllegalLimit &&
229 thread_local_.initial_climit_ != kIllegalLimit);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000230}
231
232
233StackGuard::~StackGuard() {
234 ExecutionAccess access;
235 if (--thread_local_.nesting_ == 0) {
236 set_limits(kIllegalLimit, access);
237 }
238}
239
240
241bool StackGuard::IsStackOverflow() {
242 ExecutionAccess access;
243 return (thread_local_.jslimit_ != kInterruptLimit &&
244 thread_local_.climit_ != kInterruptLimit);
245}
246
247
248void StackGuard::EnableInterrupts() {
249 ExecutionAccess access;
250 if (IsSet(access)) {
251 set_limits(kInterruptLimit, access);
252 }
253}
254
255
256void StackGuard::SetStackLimit(uintptr_t limit) {
257 ExecutionAccess access;
258 // If the current limits are special (eg due to a pending interrupt) then
259 // leave them alone.
260 if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) {
261 thread_local_.jslimit_ = limit;
262 }
263 if (thread_local_.climit_ == thread_local_.initial_climit_) {
264 thread_local_.climit_ = limit;
265 }
266 thread_local_.initial_climit_ = limit;
267 thread_local_.initial_jslimit_ = limit;
268}
269
270
271void StackGuard::DisableInterrupts() {
272 ExecutionAccess access;
273 reset_limits(access);
274}
275
276
277bool StackGuard::IsSet(const ExecutionAccess& lock) {
278 return thread_local_.interrupt_flags_ != 0;
279}
280
281
282bool StackGuard::IsInterrupted() {
283 ExecutionAccess access;
284 return thread_local_.interrupt_flags_ & INTERRUPT;
285}
286
287
288void StackGuard::Interrupt() {
289 ExecutionAccess access;
290 thread_local_.interrupt_flags_ |= INTERRUPT;
kasper.lund7276f142008-07-30 08:49:36 +0000291 set_limits(kInterruptLimit, access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000292}
293
294
295bool StackGuard::IsPreempted() {
296 ExecutionAccess access;
297 return thread_local_.interrupt_flags_ & PREEMPT;
298}
299
300
301void StackGuard::Preempt() {
302 ExecutionAccess access;
303 thread_local_.interrupt_flags_ |= PREEMPT;
kasper.lund7276f142008-07-30 08:49:36 +0000304 set_limits(kInterruptLimit, access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305}
306
307
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000308#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000309bool StackGuard::IsDebugBreak() {
310 ExecutionAccess access;
311 return thread_local_.interrupt_flags_ & DEBUGBREAK;
312}
313
kasper.lund44510672008-07-25 07:37:58 +0000314
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315void StackGuard::DebugBreak() {
316 ExecutionAccess access;
kasper.lund7276f142008-07-30 08:49:36 +0000317 thread_local_.interrupt_flags_ |= DEBUGBREAK;
318 set_limits(kInterruptLimit, access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000319}
320
321
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000322bool StackGuard::IsDebugCommand() {
323 ExecutionAccess access;
324 return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
325}
326
327
328void StackGuard::DebugCommand() {
329 if (FLAG_debugger_auto_break) {
330 ExecutionAccess access;
331 thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
332 set_limits(kInterruptLimit, access);
333 }
334}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000335#endif
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000336
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337void StackGuard::Continue(InterruptFlag after_what) {
338 ExecutionAccess access;
339 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
340 if (thread_local_.interrupt_flags_ == 0) {
341 reset_limits(access);
342 }
343}
344
345
346int StackGuard::ArchiveSpacePerThread() {
347 return sizeof(ThreadLocal);
348}
349
350
351char* StackGuard::ArchiveStackGuard(char* to) {
352 ExecutionAccess access;
353 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
354 ThreadLocal blank;
355 thread_local_ = blank;
356 return to + sizeof(ThreadLocal);
357}
358
359
360char* StackGuard::RestoreStackGuard(char* from) {
361 ExecutionAccess access;
362 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
363 return from + sizeof(ThreadLocal);
364}
365
366
367// --- C a l l s t o n a t i v e s ---
368
369#define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \
370 do { \
371 Object** args[argc] = argv; \
372 ASSERT(has_pending_exception != NULL); \
373 return Call(Top::name##_fun(), Top::builtins(), argc, args, \
374 has_pending_exception); \
375 } while (false)
376
377
378Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
379 // See the similar code in runtime.js:ToBoolean.
380 if (obj->IsBoolean()) return obj;
381 bool result = true;
382 if (obj->IsString()) {
383 result = Handle<String>::cast(obj)->length() != 0;
384 } else if (obj->IsNull() || obj->IsUndefined()) {
385 result = false;
386 } else if (obj->IsNumber()) {
387 double value = obj->Number();
388 result = !((value == 0) || isnan(value));
389 }
390 return Handle<Object>(Heap::ToBoolean(result));
391}
392
393
394Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
395 RETURN_NATIVE_CALL(to_number, 1, { obj.location() }, exc);
396}
397
398
399Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
400 RETURN_NATIVE_CALL(to_string, 1, { obj.location() }, exc);
401}
402
403
404Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
405 RETURN_NATIVE_CALL(to_detail_string, 1, { obj.location() }, exc);
406}
407
408
409Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
410 if (obj->IsJSObject()) return obj;
411 RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc);
412}
413
414
415Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
416 RETURN_NATIVE_CALL(to_integer, 1, { obj.location() }, exc);
417}
418
419
420Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
421 RETURN_NATIVE_CALL(to_uint32, 1, { obj.location() }, exc);
422}
423
424
425Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
426 RETURN_NATIVE_CALL(to_int32, 1, { obj.location() }, exc);
427}
428
429
430Handle<Object> Execution::NewDate(double time, bool* exc) {
431 Handle<Object> time_obj = Factory::NewNumber(time);
432 RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
433}
434
435
436#undef RETURN_NATIVE_CALL
437
438
439Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
440 int int_index = static_cast<int>(index);
441 if (int_index < 0 || int_index >= string->length()) {
442 return Factory::undefined_value();
443 }
444
445 Handle<Object> char_at =
446 GetProperty(Top::builtins(), Factory::char_at_symbol());
447 if (!char_at->IsJSFunction()) {
448 return Factory::undefined_value();
449 }
450
451 bool caught_exception;
452 Handle<Object> index_object = Factory::NewNumberFromInt(int_index);
453 Object** index_arg[] = { index_object.location() };
454 Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
455 string,
456 ARRAY_SIZE(index_arg),
457 index_arg,
458 &caught_exception);
459 if (caught_exception) {
460 return Factory::undefined_value();
461 }
462 return result;
463}
464
465
466Handle<JSFunction> Execution::InstantiateFunction(
467 Handle<FunctionTemplateInfo> data, bool* exc) {
468 // Fast case: see if the function has already been instantiated
469 int serial_number = Smi::cast(data->serial_number())->value();
470 Object* elm =
471 Top::global_context()->function_cache()->GetElement(serial_number);
ager@chromium.org32912102009-01-16 10:38:43 +0000472 if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473 // The function has not yet been instantiated in this context; do it.
474 Object** args[1] = { Handle<Object>::cast(data).location() };
475 Handle<Object> result =
476 Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
477 if (*exc) return Handle<JSFunction>::null();
478 return Handle<JSFunction>::cast(result);
479}
480
481
482Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
483 bool* exc) {
484 if (data->property_list()->IsUndefined() &&
485 !data->constructor()->IsUndefined()) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000486 // Initialization to make gcc happy.
487 Object* result = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000488 {
489 HandleScope scope;
490 Handle<FunctionTemplateInfo> cons_template =
491 Handle<FunctionTemplateInfo>(
492 FunctionTemplateInfo::cast(data->constructor()));
493 Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
494 if (*exc) return Handle<JSObject>::null();
495 Handle<Object> value = New(cons, 0, NULL, exc);
496 if (*exc) return Handle<JSObject>::null();
497 result = *value;
498 }
499 ASSERT(!*exc);
500 return Handle<JSObject>(JSObject::cast(result));
501 } else {
502 Object** args[1] = { Handle<Object>::cast(data).location() };
503 Handle<Object> result =
504 Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
505 if (*exc) return Handle<JSObject>::null();
506 return Handle<JSObject>::cast(result);
507 }
508}
509
510
511void Execution::ConfigureInstance(Handle<Object> instance,
512 Handle<Object> instance_template,
513 bool* exc) {
514 Object** args[2] = { instance.location(), instance_template.location() };
515 Execution::Call(Top::configure_instance_fun(), Top::builtins(), 2, args, exc);
516}
517
518
519Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
520 Handle<JSFunction> fun,
521 Handle<Object> pos,
522 Handle<Object> is_global) {
523 const int argc = 4;
524 Object** args[argc] = { recv.location(),
525 Handle<Object>::cast(fun).location(),
526 pos.location(),
527 is_global.location() };
528 bool caught_exception = false;
529 Handle<Object> result = TryCall(Top::get_stack_trace_line_fun(),
530 Top::builtins(), argc, args,
531 &caught_exception);
532 if (caught_exception || !result->IsString()) return Factory::empty_symbol();
533 return Handle<String>::cast(result);
534}
535
536
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000537static Object* RuntimePreempt() {
538 // Clear the preempt request flag.
539 StackGuard::Continue(PREEMPT);
540
541 ContextSwitcher::PreemptionReceived();
542
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000543#ifdef ENABLE_DEBUGGER_SUPPORT
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000544 if (Debug::InDebugger()) {
545 // If currently in the debugger don't do any actual preemption but record
546 // that preemption occoured while in the debugger.
547 Debug::PreemptionWhileInDebugger();
548 } else {
549 // Perform preemption.
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000550 v8::Unlocker unlocker;
551 Thread::YieldCPU();
552 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000553#else
554 // Perform preemption.
555 v8::Unlocker unlocker;
556 Thread::YieldCPU();
557#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000558
559 return Heap::undefined_value();
560}
561
562
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000563#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000564Object* Execution::DebugBreakHelper() {
565 // Just continue if breaks are disabled.
566 if (Debug::disable_break()) {
567 return Heap::undefined_value();
568 }
569
570 // Don't break in system functions. If the current function is
571 // either in the builtins object of some context or is in the debug
572 // context just return with the debug break stack guard active.
573 JavaScriptFrameIterator it;
574 JavaScriptFrame* frame = it.frame();
575 Object* fun = frame->function();
576 if (fun->IsJSFunction()) {
577 GlobalObject* global = JSFunction::cast(fun)->context()->global();
578 if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
579 return Heap::undefined_value();
580 }
581 }
582
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000583 // Check for debug command break only.
584 bool debug_command_only =
585 StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();
586
587 // Clear the debug request flags.
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000588 StackGuard::Continue(DEBUGBREAK);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000589 StackGuard::Continue(DEBUGCOMMAND);
590
591 // If debug command only and already in debugger ignore it.
592 if (debug_command_only && Debug::InDebugger()) {
593 return Heap::undefined_value();
594 }
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000595
596 HandleScope scope;
597 // Enter the debugger. Just continue if we fail to enter the debugger.
598 EnterDebugger debugger;
599 if (debugger.FailedToEnter()) {
600 return Heap::undefined_value();
601 }
602
603 // Notify the debug event listeners.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000604 Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000605
606 // Return to continue execution.
607 return Heap::undefined_value();
608}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000609#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000610
611Object* Execution::HandleStackGuardInterrupt() {
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000612#ifdef ENABLE_DEBUGGER_SUPPORT
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000613 if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
614 DebugBreakHelper();
615 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000616#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000617 if (StackGuard::IsPreempted()) RuntimePreempt();
618 if (StackGuard::IsInterrupted()) {
619 // interrupt
620 StackGuard::Continue(INTERRUPT);
621 return Top::StackOverflow();
622 }
623 return Heap::undefined_value();
624}
625
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000626// --- G C E x t e n s i o n ---
627
628const char* GCExtension::kSource = "native function gc();";
629
630
631v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
632 v8::Handle<v8::String> str) {
633 return v8::FunctionTemplate::New(GCExtension::GC);
634}
635
636
637v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
638 // All allocation spaces other than NEW_SPACE have the same effect.
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000639 Heap::CollectAllGarbage();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000640 return v8::Undefined();
641}
642
643
644static GCExtension kGCExtension;
645v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension);
646
647} } // namespace v8::internal