blob: 11dacfeede76912a9a0c4984eb7a2384238b5e07 [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 Block3ce2e202009-11-05 08:53:23 +0000406 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
407 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
Steve Blockd0582a62009-12-15 09:54:21 +0000408 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000409 jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
Steve Blockd0582a62009-12-15 09:54:21 +0000410 real_climit_ = limit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 climit_ = limit;
Steve Blockd0582a62009-12-15 09:54:21 +0000412 Heap::SetStackLimits();
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 }
414 nesting_ = 0;
415 postpone_interrupts_nesting_ = 0;
416 interrupt_flags_ = 0;
417}
418
419
420void StackGuard::ClearThread(const ExecutionAccess& lock) {
421 thread_local_.Clear();
422}
423
424
425void StackGuard::InitThread(const ExecutionAccess& lock) {
426 thread_local_.Initialize();
427 void* stored_limit = Thread::GetThreadLocal(stack_limit_key);
428 // You should hold the ExecutionAccess lock when you call this.
429 if (stored_limit != NULL) {
430 StackGuard::SetStackLimit(reinterpret_cast<intptr_t>(stored_limit));
431 }
432}
433
434
435// --- C a l l s t o n a t i v e s ---
436
437#define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \
438 do { \
439 Object** args[argc] = argv; \
440 ASSERT(has_pending_exception != NULL); \
441 return Call(Top::name##_fun(), Top::builtins(), argc, args, \
442 has_pending_exception); \
443 } while (false)
444
445
446Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
447 // See the similar code in runtime.js:ToBoolean.
448 if (obj->IsBoolean()) return obj;
449 bool result = true;
450 if (obj->IsString()) {
451 result = Handle<String>::cast(obj)->length() != 0;
452 } else if (obj->IsNull() || obj->IsUndefined()) {
453 result = false;
454 } else if (obj->IsNumber()) {
455 double value = obj->Number();
456 result = !((value == 0) || isnan(value));
457 }
458 return Handle<Object>(Heap::ToBoolean(result));
459}
460
461
462Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
463 RETURN_NATIVE_CALL(to_number, 1, { obj.location() }, exc);
464}
465
466
467Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
468 RETURN_NATIVE_CALL(to_string, 1, { obj.location() }, exc);
469}
470
471
472Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
473 RETURN_NATIVE_CALL(to_detail_string, 1, { obj.location() }, exc);
474}
475
476
477Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
478 if (obj->IsJSObject()) return obj;
479 RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc);
480}
481
482
483Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
484 RETURN_NATIVE_CALL(to_integer, 1, { obj.location() }, exc);
485}
486
487
488Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
489 RETURN_NATIVE_CALL(to_uint32, 1, { obj.location() }, exc);
490}
491
492
493Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
494 RETURN_NATIVE_CALL(to_int32, 1, { obj.location() }, exc);
495}
496
497
498Handle<Object> Execution::NewDate(double time, bool* exc) {
499 Handle<Object> time_obj = Factory::NewNumber(time);
500 RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
501}
502
503
504#undef RETURN_NATIVE_CALL
505
506
Ben Murdochf87a2032010-10-22 12:50:53 +0100507Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
508 Handle<String> flags,
509 bool* exc) {
510 Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
511 Handle<JSFunction>(Top::global_context()->regexp_function()),
512 pattern,
513 flags,
514 exc);
515 if (*exc) return Handle<JSRegExp>();
516 return Handle<JSRegExp>::cast(re_obj);
517}
518
519
Steve Blocka7e24c12009-10-30 11:49:00 +0000520Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
521 int int_index = static_cast<int>(index);
522 if (int_index < 0 || int_index >= string->length()) {
523 return Factory::undefined_value();
524 }
525
526 Handle<Object> char_at =
527 GetProperty(Top::builtins(), Factory::char_at_symbol());
528 if (!char_at->IsJSFunction()) {
529 return Factory::undefined_value();
530 }
531
532 bool caught_exception;
533 Handle<Object> index_object = Factory::NewNumberFromInt(int_index);
534 Object** index_arg[] = { index_object.location() };
535 Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
536 string,
537 ARRAY_SIZE(index_arg),
538 index_arg,
539 &caught_exception);
540 if (caught_exception) {
541 return Factory::undefined_value();
542 }
543 return result;
544}
545
546
547Handle<JSFunction> Execution::InstantiateFunction(
548 Handle<FunctionTemplateInfo> data, bool* exc) {
549 // Fast case: see if the function has already been instantiated
550 int serial_number = Smi::cast(data->serial_number())->value();
John Reck59135872010-11-02 12:39:01 -0700551 Object* elm = Top::global_context()->function_cache()->
552 GetElementNoExceptionThrown(serial_number);
Steve Blocka7e24c12009-10-30 11:49:00 +0000553 if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
554 // The function has not yet been instantiated in this context; do it.
555 Object** args[1] = { Handle<Object>::cast(data).location() };
556 Handle<Object> result =
557 Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
558 if (*exc) return Handle<JSFunction>::null();
559 return Handle<JSFunction>::cast(result);
560}
561
562
563Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
564 bool* exc) {
565 if (data->property_list()->IsUndefined() &&
566 !data->constructor()->IsUndefined()) {
567 // Initialization to make gcc happy.
568 Object* result = NULL;
569 {
570 HandleScope scope;
571 Handle<FunctionTemplateInfo> cons_template =
572 Handle<FunctionTemplateInfo>(
573 FunctionTemplateInfo::cast(data->constructor()));
574 Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
575 if (*exc) return Handle<JSObject>::null();
576 Handle<Object> value = New(cons, 0, NULL, exc);
577 if (*exc) return Handle<JSObject>::null();
578 result = *value;
579 }
580 ASSERT(!*exc);
581 return Handle<JSObject>(JSObject::cast(result));
582 } else {
583 Object** args[1] = { Handle<Object>::cast(data).location() };
584 Handle<Object> result =
585 Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
586 if (*exc) return Handle<JSObject>::null();
587 return Handle<JSObject>::cast(result);
588 }
589}
590
591
592void Execution::ConfigureInstance(Handle<Object> instance,
593 Handle<Object> instance_template,
594 bool* exc) {
595 Object** args[2] = { instance.location(), instance_template.location() };
596 Execution::Call(Top::configure_instance_fun(), Top::builtins(), 2, args, exc);
597}
598
599
600Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
601 Handle<JSFunction> fun,
602 Handle<Object> pos,
603 Handle<Object> is_global) {
604 const int argc = 4;
605 Object** args[argc] = { recv.location(),
606 Handle<Object>::cast(fun).location(),
607 pos.location(),
608 is_global.location() };
609 bool caught_exception = false;
610 Handle<Object> result = TryCall(Top::get_stack_trace_line_fun(),
611 Top::builtins(), argc, args,
612 &caught_exception);
613 if (caught_exception || !result->IsString()) return Factory::empty_symbol();
614 return Handle<String>::cast(result);
615}
616
617
618static Object* RuntimePreempt() {
619 // Clear the preempt request flag.
620 StackGuard::Continue(PREEMPT);
621
622 ContextSwitcher::PreemptionReceived();
623
624#ifdef ENABLE_DEBUGGER_SUPPORT
625 if (Debug::InDebugger()) {
626 // If currently in the debugger don't do any actual preemption but record
627 // that preemption occoured while in the debugger.
628 Debug::PreemptionWhileInDebugger();
629 } else {
630 // Perform preemption.
631 v8::Unlocker unlocker;
632 Thread::YieldCPU();
633 }
634#else
635 // Perform preemption.
636 v8::Unlocker unlocker;
637 Thread::YieldCPU();
638#endif
639
640 return Heap::undefined_value();
641}
642
643
644#ifdef ENABLE_DEBUGGER_SUPPORT
645Object* Execution::DebugBreakHelper() {
646 // Just continue if breaks are disabled.
647 if (Debug::disable_break()) {
648 return Heap::undefined_value();
649 }
650
Leon Clarkee46be812010-01-19 14:06:41 +0000651 // Ignore debug break during bootstrapping.
652 if (Bootstrapper::IsActive()) {
653 return Heap::undefined_value();
654 }
655
Steve Blocka7e24c12009-10-30 11:49:00 +0000656 {
657 JavaScriptFrameIterator it;
658 ASSERT(!it.done());
659 Object* fun = it.frame()->function();
660 if (fun && fun->IsJSFunction()) {
661 // Don't stop in builtin functions.
662 if (JSFunction::cast(fun)->IsBuiltin()) {
663 return Heap::undefined_value();
664 }
665 GlobalObject* global = JSFunction::cast(fun)->context()->global();
666 // Don't stop in debugger functions.
667 if (Debug::IsDebugGlobal(global)) {
668 return Heap::undefined_value();
669 }
670 }
671 }
672
673 // Collect the break state before clearing the flags.
674 bool debug_command_only =
675 StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();
676
Leon Clarkee46be812010-01-19 14:06:41 +0000677 // Clear the debug break request flag.
Steve Blocka7e24c12009-10-30 11:49:00 +0000678 StackGuard::Continue(DEBUGBREAK);
Leon Clarkee46be812010-01-19 14:06:41 +0000679
680 ProcessDebugMesssages(debug_command_only);
681
682 // Return to continue execution.
683 return Heap::undefined_value();
684}
685
686void Execution::ProcessDebugMesssages(bool debug_command_only) {
687 // Clear the debug command request flag.
Steve Blocka7e24c12009-10-30 11:49:00 +0000688 StackGuard::Continue(DEBUGCOMMAND);
689
690 HandleScope scope;
691 // Enter the debugger. Just continue if we fail to enter the debugger.
692 EnterDebugger debugger;
693 if (debugger.FailedToEnter()) {
Leon Clarkee46be812010-01-19 14:06:41 +0000694 return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000695 }
696
697 // Notify the debug event listeners. Indicate auto continue if the break was
698 // a debug command break.
699 Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
Steve Blocka7e24c12009-10-30 11:49:00 +0000700}
Leon Clarkee46be812010-01-19 14:06:41 +0000701
702
Steve Blocka7e24c12009-10-30 11:49:00 +0000703#endif
704
John Reck59135872010-11-02 12:39:01 -0700705MaybeObject* Execution::HandleStackGuardInterrupt() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100706 Counters::stack_interrupts.Increment();
707 if (StackGuard::IsRuntimeProfilerTick()) {
708 Counters::runtime_profiler_ticks.Increment();
709 StackGuard::Continue(RUNTIME_PROFILER_TICK);
710 RuntimeProfiler::OptimizeNow();
711 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000712#ifdef ENABLE_DEBUGGER_SUPPORT
713 if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
714 DebugBreakHelper();
715 }
716#endif
717 if (StackGuard::IsPreempted()) RuntimePreempt();
718 if (StackGuard::IsTerminateExecution()) {
719 StackGuard::Continue(TERMINATE);
720 return Top::TerminateExecution();
721 }
722 if (StackGuard::IsInterrupted()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000723 StackGuard::Continue(INTERRUPT);
724 return Top::StackOverflow();
725 }
726 return Heap::undefined_value();
727}
728
Steve Blocka7e24c12009-10-30 11:49:00 +0000729} } // namespace v8::internal