blob: f484d8d9b819af699e25786c8b66b8167441afe1 [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"
Ben Murdochb0fe1622011-05-05 13:52:32 +010036#include "runtime-profiler.h"
Steve Blockd0582a62009-12-15 09:54:21 +000037#include "simulator.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "v8threads.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010039#include "vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040
41namespace v8 {
42namespace internal {
43
44
45static Handle<Object> Invoke(bool construct,
46 Handle<JSFunction> func,
47 Handle<Object> receiver,
48 int argc,
49 Object*** args,
50 bool* has_pending_exception) {
Steve Blocka7e24c12009-10-30 11:49:00 +000051 // Entering JavaScript.
52 VMState state(JS);
53
54 // Placeholder for return value.
John Reck59135872010-11-02 12:39:01 -070055 MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
Steve Blocka7e24c12009-10-30 11:49:00 +000056
57 typedef Object* (*JSEntryFunction)(
58 byte* entry,
59 Object* function,
60 Object* receiver,
61 int argc,
62 Object*** args);
63
64 Handle<Code> code;
65 if (construct) {
66 JSConstructEntryStub stub;
67 code = stub.GetCode();
68 } else {
69 JSEntryStub stub;
70 code = stub.GetCode();
71 }
72
73 // Convert calls on global objects to be calls on the global
74 // receiver instead to avoid having a 'this' pointer which refers
75 // directly to a global object.
76 if (receiver->IsGlobalObject()) {
77 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
78 receiver = Handle<JSObject>(global->global_receiver());
79 }
80
Leon Clarkee46be812010-01-19 14:06:41 +000081 // Make sure that the global object of the context we're about to
82 // make the current one is indeed a global object.
83 ASSERT(func->context()->global()->IsGlobalObject());
84
Steve Blocka7e24c12009-10-30 11:49:00 +000085 {
86 // Save and restore context around invocation and block the
87 // allocation of handles without explicit handle scopes.
88 SaveContext save;
89 NoHandleAllocation na;
90 JSEntryFunction entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
91
92 // Call the function through the right JS entry stub.
Andrei Popescu402d9372010-02-26 13:31:12 +000093 byte* entry_address = func->code()->entry();
Steve Block3ce2e202009-11-05 08:53:23 +000094 JSFunction* function = *func;
95 Object* receiver_pointer = *receiver;
96 value = CALL_GENERATED_CODE(entry, entry_address, function,
97 receiver_pointer, argc, args);
Steve Blocka7e24c12009-10-30 11:49:00 +000098 }
99
100#ifdef DEBUG
101 value->Verify();
102#endif
103
104 // Update the pending exception flag and return the value.
105 *has_pending_exception = value->IsException();
106 ASSERT(*has_pending_exception == Top::has_pending_exception());
107 if (*has_pending_exception) {
108 Top::ReportPendingMessages();
109 return Handle<Object>();
110 } else {
111 Top::clear_pending_message();
112 }
113
John Reck59135872010-11-02 12:39:01 -0700114 return Handle<Object>(value->ToObjectUnchecked());
Steve Blocka7e24c12009-10-30 11:49:00 +0000115}
116
117
118Handle<Object> Execution::Call(Handle<JSFunction> func,
119 Handle<Object> receiver,
120 int argc,
121 Object*** args,
122 bool* pending_exception) {
123 return Invoke(false, func, receiver, argc, args, pending_exception);
124}
125
126
127Handle<Object> Execution::New(Handle<JSFunction> func, int argc,
128 Object*** args, bool* pending_exception) {
129 return Invoke(true, func, Top::global(), argc, args, pending_exception);
130}
131
132
133Handle<Object> Execution::TryCall(Handle<JSFunction> func,
134 Handle<Object> receiver,
135 int argc,
136 Object*** args,
137 bool* caught_exception) {
138 // Enter a try-block while executing the JavaScript code. To avoid
139 // duplicate error printing it must be non-verbose. Also, to avoid
140 // creating message objects during stack overflow we shouldn't
141 // capture messages.
142 v8::TryCatch catcher;
143 catcher.SetVerbose(false);
144 catcher.SetCaptureMessage(false);
145
146 Handle<Object> result = Invoke(false, func, receiver, argc, args,
147 caught_exception);
148
149 if (*caught_exception) {
150 ASSERT(catcher.HasCaught());
151 ASSERT(Top::has_pending_exception());
152 ASSERT(Top::external_caught_exception());
153 if (Top::pending_exception() == Heap::termination_exception()) {
154 result = Factory::termination_exception();
155 } else {
156 result = v8::Utils::OpenHandle(*catcher.Exception());
157 }
158 Top::OptionalRescheduleException(true);
159 }
160
161 ASSERT(!Top::has_pending_exception());
162 ASSERT(!Top::external_caught_exception());
163 return result;
164}
165
166
167Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
168 ASSERT(!object->IsJSFunction());
169
170 // If you return a function from here, it will be called when an
171 // attempt is made to call the given object as a function.
172
173 // Regular expressions can be called as functions in both Firefox
174 // and Safari so we allow it too.
175 if (object->IsJSRegExp()) {
176 Handle<String> exec = Factory::exec_symbol();
John Reck59135872010-11-02 12:39:01 -0700177 // TODO(lrn): Bug 617. We should use the default function here, not the
178 // one on the RegExp object.
179 Object* exec_function;
180 { MaybeObject* maybe_exec_function = object->GetProperty(*exec);
181 // This can lose an exception, but the alternative is to put a failure
182 // object in a handle, which is not GC safe.
183 if (!maybe_exec_function->ToObject(&exec_function)) {
184 return Factory::undefined_value();
185 }
186 }
187 return Handle<Object>(exec_function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000188 }
189
190 // Objects created through the API can have an instance-call handler
191 // that should be used when calling the object as a function.
192 if (object->IsHeapObject() &&
193 HeapObject::cast(*object)->map()->has_instance_call_handler()) {
194 return Handle<JSFunction>(
195 Top::global_context()->call_as_function_delegate());
196 }
197
198 return Factory::undefined_value();
199}
200
201
202Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
203 ASSERT(!object->IsJSFunction());
204
205 // If you return a function from here, it will be called when an
206 // attempt is made to call the given object as a constructor.
207
208 // Objects created through the API can have an instance-call handler
209 // that should be used when calling the object as a function.
210 if (object->IsHeapObject() &&
211 HeapObject::cast(*object)->map()->has_instance_call_handler()) {
212 return Handle<JSFunction>(
213 Top::global_context()->call_as_constructor_delegate());
214 }
215
216 return Factory::undefined_value();
217}
218
219
220// Static state for stack guards.
221StackGuard::ThreadLocal StackGuard::thread_local_;
222
223
224bool StackGuard::IsStackOverflow() {
225 ExecutionAccess access;
226 return (thread_local_.jslimit_ != kInterruptLimit &&
227 thread_local_.climit_ != kInterruptLimit);
228}
229
230
231void StackGuard::EnableInterrupts() {
232 ExecutionAccess access;
Steve Block6ded16b2010-05-10 14:33:55 +0100233 if (has_pending_interrupts(access)) {
234 set_interrupt_limits(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000235 }
236}
237
238
239void StackGuard::SetStackLimit(uintptr_t limit) {
240 ExecutionAccess access;
241 // If the current limits are special (eg due to a pending interrupt) then
242 // leave them alone.
243 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(limit);
Steve Blockd0582a62009-12-15 09:54:21 +0000244 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 thread_local_.jslimit_ = jslimit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000246 }
Steve Blockd0582a62009-12-15 09:54:21 +0000247 if (thread_local_.climit_ == thread_local_.real_climit_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000248 thread_local_.climit_ = limit;
249 }
Steve Blockd0582a62009-12-15 09:54:21 +0000250 thread_local_.real_climit_ = limit;
251 thread_local_.real_jslimit_ = jslimit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000252}
253
254
255void StackGuard::DisableInterrupts() {
256 ExecutionAccess access;
257 reset_limits(access);
258}
259
260
Steve Blocka7e24c12009-10-30 11:49:00 +0000261bool StackGuard::IsInterrupted() {
262 ExecutionAccess access;
263 return thread_local_.interrupt_flags_ & INTERRUPT;
264}
265
266
267void StackGuard::Interrupt() {
268 ExecutionAccess access;
269 thread_local_.interrupt_flags_ |= INTERRUPT;
Steve Block6ded16b2010-05-10 14:33:55 +0100270 set_interrupt_limits(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000271}
272
273
274bool StackGuard::IsPreempted() {
275 ExecutionAccess access;
276 return thread_local_.interrupt_flags_ & PREEMPT;
277}
278
279
280void StackGuard::Preempt() {
281 ExecutionAccess access;
282 thread_local_.interrupt_flags_ |= PREEMPT;
Steve Block6ded16b2010-05-10 14:33:55 +0100283 set_interrupt_limits(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000284}
285
286
287bool StackGuard::IsTerminateExecution() {
288 ExecutionAccess access;
289 return thread_local_.interrupt_flags_ & TERMINATE;
290}
291
292
293void StackGuard::TerminateExecution() {
294 ExecutionAccess access;
295 thread_local_.interrupt_flags_ |= TERMINATE;
Steve Block6ded16b2010-05-10 14:33:55 +0100296 set_interrupt_limits(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000297}
298
299
Ben Murdochb0fe1622011-05-05 13:52:32 +0100300bool StackGuard::IsRuntimeProfilerTick() {
301 ExecutionAccess access;
302 return thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK;
303}
304
305
306void StackGuard::RequestRuntimeProfilerTick() {
307 // Ignore calls if we're not optimizing or if we can't get the lock.
308 if (FLAG_opt && ExecutionAccess::TryLock()) {
309 thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK;
310 if (thread_local_.postpone_interrupts_nesting_ == 0) {
311 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
312 Heap::SetStackLimits();
313 }
314 ExecutionAccess::Unlock();
315 }
316}
317
318
Steve Blocka7e24c12009-10-30 11:49:00 +0000319#ifdef ENABLE_DEBUGGER_SUPPORT
320bool StackGuard::IsDebugBreak() {
321 ExecutionAccess access;
322 return thread_local_.interrupt_flags_ & DEBUGBREAK;
323}
324
325
326void StackGuard::DebugBreak() {
327 ExecutionAccess access;
328 thread_local_.interrupt_flags_ |= DEBUGBREAK;
Steve Block6ded16b2010-05-10 14:33:55 +0100329 set_interrupt_limits(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000330}
331
332
333bool StackGuard::IsDebugCommand() {
334 ExecutionAccess access;
335 return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
336}
337
338
339void StackGuard::DebugCommand() {
340 if (FLAG_debugger_auto_break) {
341 ExecutionAccess access;
342 thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
Steve Block6ded16b2010-05-10 14:33:55 +0100343 set_interrupt_limits(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000344 }
345}
346#endif
347
348void StackGuard::Continue(InterruptFlag after_what) {
349 ExecutionAccess access;
350 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
Steve Block6ded16b2010-05-10 14:33:55 +0100351 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000352 reset_limits(access);
353 }
354}
355
356
357int StackGuard::ArchiveSpacePerThread() {
358 return sizeof(ThreadLocal);
359}
360
361
362char* StackGuard::ArchiveStackGuard(char* to) {
363 ExecutionAccess access;
364 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
365 ThreadLocal blank;
366 thread_local_ = blank;
367 return to + sizeof(ThreadLocal);
368}
369
370
371char* StackGuard::RestoreStackGuard(char* from) {
372 ExecutionAccess access;
373 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
Steve Blockd0582a62009-12-15 09:54:21 +0000374 Heap::SetStackLimits();
Steve Blocka7e24c12009-10-30 11:49:00 +0000375 return from + sizeof(ThreadLocal);
376}
377
378
379static internal::Thread::LocalStorageKey stack_limit_key =
380 internal::Thread::CreateThreadLocalKey();
381
382
383void StackGuard::FreeThreadResources() {
384 Thread::SetThreadLocal(
385 stack_limit_key,
Steve Blockd0582a62009-12-15 09:54:21 +0000386 reinterpret_cast<void*>(thread_local_.real_climit_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000387}
388
389
390void StackGuard::ThreadLocal::Clear() {
Steve Blockd0582a62009-12-15 09:54:21 +0000391 real_jslimit_ = kIllegalLimit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000392 jslimit_ = kIllegalLimit;
Steve Blockd0582a62009-12-15 09:54:21 +0000393 real_climit_ = kIllegalLimit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000394 climit_ = kIllegalLimit;
395 nesting_ = 0;
396 postpone_interrupts_nesting_ = 0;
397 interrupt_flags_ = 0;
Steve Blockd0582a62009-12-15 09:54:21 +0000398 Heap::SetStackLimits();
Steve Blocka7e24c12009-10-30 11:49:00 +0000399}
400
401
402void StackGuard::ThreadLocal::Initialize() {
Steve Blockd0582a62009-12-15 09:54:21 +0000403 if (real_climit_ == kIllegalLimit) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 // Takes the address of the limit variable in order to find out where
405 // the top of stack is right now.
Steve Block1e0659c2011-05-24 12:43:12 +0100406 const uintptr_t kLimitSize = FLAG_stack_size * KB;
Steve Block3ce2e202009-11-05 08:53:23 +0000407 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
408 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
Steve Blockd0582a62009-12-15 09:54:21 +0000409 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
Steve Blockd0582a62009-12-15 09:54:21 +0000411 real_climit_ = limit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000412 climit_ = limit;
Steve Blockd0582a62009-12-15 09:54:21 +0000413 Heap::SetStackLimits();
Steve Blocka7e24c12009-10-30 11:49:00 +0000414 }
415 nesting_ = 0;
416 postpone_interrupts_nesting_ = 0;
417 interrupt_flags_ = 0;
418}
419
420
421void StackGuard::ClearThread(const ExecutionAccess& lock) {
422 thread_local_.Clear();
423}
424
425
426void StackGuard::InitThread(const ExecutionAccess& lock) {
427 thread_local_.Initialize();
428 void* stored_limit = Thread::GetThreadLocal(stack_limit_key);
429 // You should hold the ExecutionAccess lock when you call this.
430 if (stored_limit != NULL) {
431 StackGuard::SetStackLimit(reinterpret_cast<intptr_t>(stored_limit));
432 }
433}
434
435
436// --- C a l l s t o n a t i v e s ---
437
438#define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \
439 do { \
440 Object** args[argc] = argv; \
441 ASSERT(has_pending_exception != NULL); \
442 return Call(Top::name##_fun(), Top::builtins(), argc, args, \
443 has_pending_exception); \
444 } while (false)
445
446
447Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
448 // See the similar code in runtime.js:ToBoolean.
449 if (obj->IsBoolean()) return obj;
450 bool result = true;
451 if (obj->IsString()) {
452 result = Handle<String>::cast(obj)->length() != 0;
453 } else if (obj->IsNull() || obj->IsUndefined()) {
454 result = false;
455 } else if (obj->IsNumber()) {
456 double value = obj->Number();
457 result = !((value == 0) || isnan(value));
458 }
459 return Handle<Object>(Heap::ToBoolean(result));
460}
461
462
463Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
464 RETURN_NATIVE_CALL(to_number, 1, { obj.location() }, exc);
465}
466
467
468Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
469 RETURN_NATIVE_CALL(to_string, 1, { obj.location() }, exc);
470}
471
472
473Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
474 RETURN_NATIVE_CALL(to_detail_string, 1, { obj.location() }, exc);
475}
476
477
478Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
479 if (obj->IsJSObject()) return obj;
480 RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc);
481}
482
483
484Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
485 RETURN_NATIVE_CALL(to_integer, 1, { obj.location() }, exc);
486}
487
488
489Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
490 RETURN_NATIVE_CALL(to_uint32, 1, { obj.location() }, exc);
491}
492
493
494Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
495 RETURN_NATIVE_CALL(to_int32, 1, { obj.location() }, exc);
496}
497
498
499Handle<Object> Execution::NewDate(double time, bool* exc) {
500 Handle<Object> time_obj = Factory::NewNumber(time);
501 RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
502}
503
504
505#undef RETURN_NATIVE_CALL
506
507
Ben Murdochf87a2032010-10-22 12:50:53 +0100508Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
509 Handle<String> flags,
510 bool* exc) {
511 Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
512 Handle<JSFunction>(Top::global_context()->regexp_function()),
513 pattern,
514 flags,
515 exc);
516 if (*exc) return Handle<JSRegExp>();
517 return Handle<JSRegExp>::cast(re_obj);
518}
519
520
Steve Blocka7e24c12009-10-30 11:49:00 +0000521Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
522 int int_index = static_cast<int>(index);
523 if (int_index < 0 || int_index >= string->length()) {
524 return Factory::undefined_value();
525 }
526
527 Handle<Object> char_at =
528 GetProperty(Top::builtins(), Factory::char_at_symbol());
529 if (!char_at->IsJSFunction()) {
530 return Factory::undefined_value();
531 }
532
533 bool caught_exception;
534 Handle<Object> index_object = Factory::NewNumberFromInt(int_index);
535 Object** index_arg[] = { index_object.location() };
536 Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
537 string,
538 ARRAY_SIZE(index_arg),
539 index_arg,
540 &caught_exception);
541 if (caught_exception) {
542 return Factory::undefined_value();
543 }
544 return result;
545}
546
547
548Handle<JSFunction> Execution::InstantiateFunction(
549 Handle<FunctionTemplateInfo> data, bool* exc) {
550 // Fast case: see if the function has already been instantiated
551 int serial_number = Smi::cast(data->serial_number())->value();
John Reck59135872010-11-02 12:39:01 -0700552 Object* elm = Top::global_context()->function_cache()->
553 GetElementNoExceptionThrown(serial_number);
Steve Blocka7e24c12009-10-30 11:49:00 +0000554 if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
555 // The function has not yet been instantiated in this context; do it.
556 Object** args[1] = { Handle<Object>::cast(data).location() };
557 Handle<Object> result =
558 Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
559 if (*exc) return Handle<JSFunction>::null();
560 return Handle<JSFunction>::cast(result);
561}
562
563
564Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
565 bool* exc) {
566 if (data->property_list()->IsUndefined() &&
567 !data->constructor()->IsUndefined()) {
568 // Initialization to make gcc happy.
569 Object* result = NULL;
570 {
571 HandleScope scope;
572 Handle<FunctionTemplateInfo> cons_template =
573 Handle<FunctionTemplateInfo>(
574 FunctionTemplateInfo::cast(data->constructor()));
575 Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
576 if (*exc) return Handle<JSObject>::null();
577 Handle<Object> value = New(cons, 0, NULL, exc);
578 if (*exc) return Handle<JSObject>::null();
579 result = *value;
580 }
581 ASSERT(!*exc);
582 return Handle<JSObject>(JSObject::cast(result));
583 } else {
584 Object** args[1] = { Handle<Object>::cast(data).location() };
585 Handle<Object> result =
586 Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
587 if (*exc) return Handle<JSObject>::null();
588 return Handle<JSObject>::cast(result);
589 }
590}
591
592
593void Execution::ConfigureInstance(Handle<Object> instance,
594 Handle<Object> instance_template,
595 bool* exc) {
596 Object** args[2] = { instance.location(), instance_template.location() };
597 Execution::Call(Top::configure_instance_fun(), Top::builtins(), 2, args, exc);
598}
599
600
601Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
602 Handle<JSFunction> fun,
603 Handle<Object> pos,
604 Handle<Object> is_global) {
605 const int argc = 4;
606 Object** args[argc] = { recv.location(),
607 Handle<Object>::cast(fun).location(),
608 pos.location(),
609 is_global.location() };
610 bool caught_exception = false;
611 Handle<Object> result = TryCall(Top::get_stack_trace_line_fun(),
612 Top::builtins(), argc, args,
613 &caught_exception);
614 if (caught_exception || !result->IsString()) return Factory::empty_symbol();
615 return Handle<String>::cast(result);
616}
617
618
619static Object* RuntimePreempt() {
620 // Clear the preempt request flag.
621 StackGuard::Continue(PREEMPT);
622
623 ContextSwitcher::PreemptionReceived();
624
625#ifdef ENABLE_DEBUGGER_SUPPORT
626 if (Debug::InDebugger()) {
627 // If currently in the debugger don't do any actual preemption but record
628 // that preemption occoured while in the debugger.
629 Debug::PreemptionWhileInDebugger();
630 } else {
631 // Perform preemption.
632 v8::Unlocker unlocker;
633 Thread::YieldCPU();
634 }
635#else
636 // Perform preemption.
637 v8::Unlocker unlocker;
638 Thread::YieldCPU();
639#endif
640
641 return Heap::undefined_value();
642}
643
644
645#ifdef ENABLE_DEBUGGER_SUPPORT
646Object* Execution::DebugBreakHelper() {
647 // Just continue if breaks are disabled.
648 if (Debug::disable_break()) {
649 return Heap::undefined_value();
650 }
651
Leon Clarkee46be812010-01-19 14:06:41 +0000652 // Ignore debug break during bootstrapping.
653 if (Bootstrapper::IsActive()) {
654 return Heap::undefined_value();
655 }
656
Steve Blocka7e24c12009-10-30 11:49:00 +0000657 {
658 JavaScriptFrameIterator it;
659 ASSERT(!it.done());
660 Object* fun = it.frame()->function();
661 if (fun && fun->IsJSFunction()) {
662 // Don't stop in builtin functions.
663 if (JSFunction::cast(fun)->IsBuiltin()) {
664 return Heap::undefined_value();
665 }
666 GlobalObject* global = JSFunction::cast(fun)->context()->global();
667 // Don't stop in debugger functions.
668 if (Debug::IsDebugGlobal(global)) {
669 return Heap::undefined_value();
670 }
671 }
672 }
673
674 // Collect the break state before clearing the flags.
675 bool debug_command_only =
676 StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();
677
Leon Clarkee46be812010-01-19 14:06:41 +0000678 // Clear the debug break request flag.
Steve Blocka7e24c12009-10-30 11:49:00 +0000679 StackGuard::Continue(DEBUGBREAK);
Leon Clarkee46be812010-01-19 14:06:41 +0000680
681 ProcessDebugMesssages(debug_command_only);
682
683 // Return to continue execution.
684 return Heap::undefined_value();
685}
686
687void Execution::ProcessDebugMesssages(bool debug_command_only) {
688 // Clear the debug command request flag.
Steve Blocka7e24c12009-10-30 11:49:00 +0000689 StackGuard::Continue(DEBUGCOMMAND);
690
691 HandleScope scope;
692 // Enter the debugger. Just continue if we fail to enter the debugger.
693 EnterDebugger debugger;
694 if (debugger.FailedToEnter()) {
Leon Clarkee46be812010-01-19 14:06:41 +0000695 return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000696 }
697
698 // Notify the debug event listeners. Indicate auto continue if the break was
699 // a debug command break.
700 Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
Steve Blocka7e24c12009-10-30 11:49:00 +0000701}
Leon Clarkee46be812010-01-19 14:06:41 +0000702
703
Steve Blocka7e24c12009-10-30 11:49:00 +0000704#endif
705
John Reck59135872010-11-02 12:39:01 -0700706MaybeObject* Execution::HandleStackGuardInterrupt() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100707 Counters::stack_interrupts.Increment();
708 if (StackGuard::IsRuntimeProfilerTick()) {
709 Counters::runtime_profiler_ticks.Increment();
710 StackGuard::Continue(RUNTIME_PROFILER_TICK);
711 RuntimeProfiler::OptimizeNow();
712 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000713#ifdef ENABLE_DEBUGGER_SUPPORT
714 if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
715 DebugBreakHelper();
716 }
717#endif
718 if (StackGuard::IsPreempted()) RuntimePreempt();
719 if (StackGuard::IsTerminateExecution()) {
720 StackGuard::Continue(TERMINATE);
721 return Top::TerminateExecution();
722 }
723 if (StackGuard::IsInterrupted()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000724 StackGuard::Continue(INTERRUPT);
725 return Top::StackOverflow();
726 }
727 return Heap::undefined_value();
728}
729
Steve Blocka7e24c12009-10-30 11:49:00 +0000730} } // namespace v8::internal