• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <stdlib.h>
29 
30 #include "v8.h"
31 
32 #include "api.h"
33 #include "bootstrapper.h"
34 #include "codegen.h"
35 #include "debug.h"
36 #include "runtime-profiler.h"
37 #include "simulator.h"
38 #include "v8threads.h"
39 #include "vm-state-inl.h"
40 
41 namespace v8 {
42 namespace internal {
43 
44 
StackGuard()45 StackGuard::StackGuard()
46     : isolate_(NULL) {
47 }
48 
49 
set_interrupt_limits(const ExecutionAccess & lock)50 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
51   ASSERT(isolate_ != NULL);
52   // Ignore attempts to interrupt when interrupts are postponed.
53   if (should_postpone_interrupts(lock)) return;
54   thread_local_.jslimit_ = kInterruptLimit;
55   thread_local_.climit_ = kInterruptLimit;
56   isolate_->heap()->SetStackLimits();
57 }
58 
59 
reset_limits(const ExecutionAccess & lock)60 void StackGuard::reset_limits(const ExecutionAccess& lock) {
61   ASSERT(isolate_ != NULL);
62   thread_local_.jslimit_ = thread_local_.real_jslimit_;
63   thread_local_.climit_ = thread_local_.real_climit_;
64   isolate_->heap()->SetStackLimits();
65 }
66 
67 
Invoke(bool construct,Handle<JSFunction> func,Handle<Object> receiver,int argc,Object *** args,bool * has_pending_exception)68 static Handle<Object> Invoke(bool construct,
69                              Handle<JSFunction> func,
70                              Handle<Object> receiver,
71                              int argc,
72                              Object*** args,
73                              bool* has_pending_exception) {
74   Isolate* isolate = func->GetIsolate();
75 
76   // Entering JavaScript.
77   VMState state(isolate, JS);
78 
79   // Placeholder for return value.
80   MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
81 
82   typedef Object* (*JSEntryFunction)(
83     byte* entry,
84     Object* function,
85     Object* receiver,
86     int argc,
87     Object*** args);
88 
89   Handle<Code> code;
90   if (construct) {
91     JSConstructEntryStub stub;
92     code = stub.GetCode();
93   } else {
94     JSEntryStub stub;
95     code = stub.GetCode();
96   }
97 
98   // Convert calls on global objects to be calls on the global
99   // receiver instead to avoid having a 'this' pointer which refers
100   // directly to a global object.
101   if (receiver->IsGlobalObject()) {
102     Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
103     receiver = Handle<JSObject>(global->global_receiver());
104   }
105 
106   // Make sure that the global object of the context we're about to
107   // make the current one is indeed a global object.
108   ASSERT(func->context()->global()->IsGlobalObject());
109 
110   {
111     // Save and restore context around invocation and block the
112     // allocation of handles without explicit handle scopes.
113     SaveContext save(isolate);
114     NoHandleAllocation na;
115     JSEntryFunction entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
116 
117     // Call the function through the right JS entry stub.
118     byte* entry_address = func->code()->entry();
119     JSFunction* function = *func;
120     Object* receiver_pointer = *receiver;
121     value = CALL_GENERATED_CODE(entry, entry_address, function,
122                                 receiver_pointer, argc, args);
123   }
124 
125 #ifdef DEBUG
126   value->Verify();
127 #endif
128 
129   // Update the pending exception flag and return the value.
130   *has_pending_exception = value->IsException();
131   ASSERT(*has_pending_exception == Isolate::Current()->has_pending_exception());
132   if (*has_pending_exception) {
133     isolate->ReportPendingMessages();
134     if (isolate->pending_exception() == Failure::OutOfMemoryException()) {
135       if (!isolate->ignore_out_of_memory()) {
136         V8::FatalProcessOutOfMemory("JS", true);
137       }
138     }
139     return Handle<Object>();
140   } else {
141     isolate->clear_pending_message();
142   }
143 
144   return Handle<Object>(value->ToObjectUnchecked(), isolate);
145 }
146 
147 
Call(Handle<JSFunction> func,Handle<Object> receiver,int argc,Object *** args,bool * pending_exception)148 Handle<Object> Execution::Call(Handle<JSFunction> func,
149                                Handle<Object> receiver,
150                                int argc,
151                                Object*** args,
152                                bool* pending_exception) {
153   return Invoke(false, func, receiver, argc, args, pending_exception);
154 }
155 
156 
New(Handle<JSFunction> func,int argc,Object *** args,bool * pending_exception)157 Handle<Object> Execution::New(Handle<JSFunction> func, int argc,
158                               Object*** args, bool* pending_exception) {
159   return Invoke(true, func, Isolate::Current()->global(), argc, args,
160                 pending_exception);
161 }
162 
163 
TryCall(Handle<JSFunction> func,Handle<Object> receiver,int argc,Object *** args,bool * caught_exception)164 Handle<Object> Execution::TryCall(Handle<JSFunction> func,
165                                   Handle<Object> receiver,
166                                   int argc,
167                                   Object*** args,
168                                   bool* caught_exception) {
169   // Enter a try-block while executing the JavaScript code. To avoid
170   // duplicate error printing it must be non-verbose.  Also, to avoid
171   // creating message objects during stack overflow we shouldn't
172   // capture messages.
173   v8::TryCatch catcher;
174   catcher.SetVerbose(false);
175   catcher.SetCaptureMessage(false);
176 
177   Handle<Object> result = Invoke(false, func, receiver, argc, args,
178                                  caught_exception);
179 
180   if (*caught_exception) {
181     ASSERT(catcher.HasCaught());
182     Isolate* isolate = Isolate::Current();
183     ASSERT(isolate->has_pending_exception());
184     ASSERT(isolate->external_caught_exception());
185     if (isolate->pending_exception() ==
186         isolate->heap()->termination_exception()) {
187       result = isolate->factory()->termination_exception();
188     } else {
189       result = v8::Utils::OpenHandle(*catcher.Exception());
190     }
191     isolate->OptionalRescheduleException(true);
192   }
193 
194   ASSERT(!Isolate::Current()->has_pending_exception());
195   ASSERT(!Isolate::Current()->external_caught_exception());
196   return result;
197 }
198 
199 
GetFunctionDelegate(Handle<Object> object)200 Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
201   ASSERT(!object->IsJSFunction());
202   Isolate* isolate = Isolate::Current();
203   Factory* factory = isolate->factory();
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 function.
207 
208   // Regular expressions can be called as functions in both Firefox
209   // and Safari so we allow it too.
210   if (object->IsJSRegExp()) {
211     Handle<String> exec = factory->exec_symbol();
212     // TODO(lrn): Bug 617.  We should use the default function here, not the
213     // one on the RegExp object.
214     Object* exec_function;
215     { MaybeObject* maybe_exec_function = object->GetProperty(*exec);
216       // This can lose an exception, but the alternative is to put a failure
217       // object in a handle, which is not GC safe.
218       if (!maybe_exec_function->ToObject(&exec_function)) {
219         return factory->undefined_value();
220       }
221     }
222     return Handle<Object>(exec_function);
223   }
224 
225   // Objects created through the API can have an instance-call handler
226   // that should be used when calling the object as a function.
227   if (object->IsHeapObject() &&
228       HeapObject::cast(*object)->map()->has_instance_call_handler()) {
229     return Handle<JSFunction>(
230         isolate->global_context()->call_as_function_delegate());
231   }
232 
233   return factory->undefined_value();
234 }
235 
236 
GetConstructorDelegate(Handle<Object> object)237 Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
238   ASSERT(!object->IsJSFunction());
239   Isolate* isolate = Isolate::Current();
240 
241   // If you return a function from here, it will be called when an
242   // attempt is made to call the given object as a constructor.
243 
244   // Objects created through the API can have an instance-call handler
245   // that should be used when calling the object as a function.
246   if (object->IsHeapObject() &&
247       HeapObject::cast(*object)->map()->has_instance_call_handler()) {
248     return Handle<JSFunction>(
249         isolate->global_context()->call_as_constructor_delegate());
250   }
251 
252   return isolate->factory()->undefined_value();
253 }
254 
255 
IsStackOverflow()256 bool StackGuard::IsStackOverflow() {
257   ExecutionAccess access(isolate_);
258   return (thread_local_.jslimit_ != kInterruptLimit &&
259           thread_local_.climit_ != kInterruptLimit);
260 }
261 
262 
EnableInterrupts()263 void StackGuard::EnableInterrupts() {
264   ExecutionAccess access(isolate_);
265   if (has_pending_interrupts(access)) {
266     set_interrupt_limits(access);
267   }
268 }
269 
270 
SetStackLimit(uintptr_t limit)271 void StackGuard::SetStackLimit(uintptr_t limit) {
272   ExecutionAccess access(isolate_);
273   // If the current limits are special (eg due to a pending interrupt) then
274   // leave them alone.
275   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(limit);
276   if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
277     thread_local_.jslimit_ = jslimit;
278   }
279   if (thread_local_.climit_ == thread_local_.real_climit_) {
280     thread_local_.climit_ = limit;
281   }
282   thread_local_.real_climit_ = limit;
283   thread_local_.real_jslimit_ = jslimit;
284 }
285 
286 
DisableInterrupts()287 void StackGuard::DisableInterrupts() {
288   ExecutionAccess access(isolate_);
289   reset_limits(access);
290 }
291 
292 
IsInterrupted()293 bool StackGuard::IsInterrupted() {
294   ExecutionAccess access(isolate_);
295   return thread_local_.interrupt_flags_ & INTERRUPT;
296 }
297 
298 
Interrupt()299 void StackGuard::Interrupt() {
300   ExecutionAccess access(isolate_);
301   thread_local_.interrupt_flags_ |= INTERRUPT;
302   set_interrupt_limits(access);
303 }
304 
305 
IsPreempted()306 bool StackGuard::IsPreempted() {
307   ExecutionAccess access(isolate_);
308   return thread_local_.interrupt_flags_ & PREEMPT;
309 }
310 
311 
Preempt()312 void StackGuard::Preempt() {
313   ExecutionAccess access(isolate_);
314   thread_local_.interrupt_flags_ |= PREEMPT;
315   set_interrupt_limits(access);
316 }
317 
318 
IsTerminateExecution()319 bool StackGuard::IsTerminateExecution() {
320   ExecutionAccess access(isolate_);
321   return thread_local_.interrupt_flags_ & TERMINATE;
322 }
323 
324 
TerminateExecution()325 void StackGuard::TerminateExecution() {
326   ExecutionAccess access(isolate_);
327   thread_local_.interrupt_flags_ |= TERMINATE;
328   set_interrupt_limits(access);
329 }
330 
331 
IsRuntimeProfilerTick()332 bool StackGuard::IsRuntimeProfilerTick() {
333   ExecutionAccess access(isolate_);
334   return thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK;
335 }
336 
337 
RequestRuntimeProfilerTick()338 void StackGuard::RequestRuntimeProfilerTick() {
339   // Ignore calls if we're not optimizing or if we can't get the lock.
340   if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) {
341     thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK;
342     if (thread_local_.postpone_interrupts_nesting_ == 0) {
343       thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
344       isolate_->heap()->SetStackLimits();
345     }
346     ExecutionAccess::Unlock(isolate_);
347   }
348 }
349 
350 
351 #ifdef ENABLE_DEBUGGER_SUPPORT
IsDebugBreak()352 bool StackGuard::IsDebugBreak() {
353   ExecutionAccess access(isolate_);
354   return thread_local_.interrupt_flags_ & DEBUGBREAK;
355 }
356 
357 
DebugBreak()358 void StackGuard::DebugBreak() {
359   ExecutionAccess access(isolate_);
360   thread_local_.interrupt_flags_ |= DEBUGBREAK;
361   set_interrupt_limits(access);
362 }
363 
364 
IsDebugCommand()365 bool StackGuard::IsDebugCommand() {
366   ExecutionAccess access(isolate_);
367   return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
368 }
369 
370 
DebugCommand()371 void StackGuard::DebugCommand() {
372   if (FLAG_debugger_auto_break) {
373     ExecutionAccess access(isolate_);
374     thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
375     set_interrupt_limits(access);
376   }
377 }
378 #endif
379 
Continue(InterruptFlag after_what)380 void StackGuard::Continue(InterruptFlag after_what) {
381   ExecutionAccess access(isolate_);
382   thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
383   if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
384     reset_limits(access);
385   }
386 }
387 
388 
ArchiveStackGuard(char * to)389 char* StackGuard::ArchiveStackGuard(char* to) {
390   ExecutionAccess access(isolate_);
391   memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
392   ThreadLocal blank;
393 
394   // Set the stack limits using the old thread_local_.
395   // TODO(isolates): This was the old semantics of constructing a ThreadLocal
396   //                 (as the ctor called SetStackLimits, which looked at the
397   //                 current thread_local_ from StackGuard)-- but is this
398   //                 really what was intended?
399   isolate_->heap()->SetStackLimits();
400   thread_local_ = blank;
401 
402   return to + sizeof(ThreadLocal);
403 }
404 
405 
RestoreStackGuard(char * from)406 char* StackGuard::RestoreStackGuard(char* from) {
407   ExecutionAccess access(isolate_);
408   memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
409   isolate_->heap()->SetStackLimits();
410   return from + sizeof(ThreadLocal);
411 }
412 
413 
FreeThreadResources()414 void StackGuard::FreeThreadResources() {
415   Isolate::CurrentPerIsolateThreadData()->set_stack_limit(
416       thread_local_.real_climit_);
417 }
418 
419 
Clear()420 void StackGuard::ThreadLocal::Clear() {
421   real_jslimit_ = kIllegalLimit;
422   jslimit_ = kIllegalLimit;
423   real_climit_ = kIllegalLimit;
424   climit_ = kIllegalLimit;
425   nesting_ = 0;
426   postpone_interrupts_nesting_ = 0;
427   interrupt_flags_ = 0;
428 }
429 
430 
Initialize()431 bool StackGuard::ThreadLocal::Initialize() {
432   bool should_set_stack_limits = false;
433   if (real_climit_ == kIllegalLimit) {
434     // Takes the address of the limit variable in order to find out where
435     // the top of stack is right now.
436     const uintptr_t kLimitSize = FLAG_stack_size * KB;
437     uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
438     ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
439     real_jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
440     jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
441     real_climit_ = limit;
442     climit_ = limit;
443     should_set_stack_limits = true;
444   }
445   nesting_ = 0;
446   postpone_interrupts_nesting_ = 0;
447   interrupt_flags_ = 0;
448   return should_set_stack_limits;
449 }
450 
451 
ClearThread(const ExecutionAccess & lock)452 void StackGuard::ClearThread(const ExecutionAccess& lock) {
453   thread_local_.Clear();
454   isolate_->heap()->SetStackLimits();
455 }
456 
457 
InitThread(const ExecutionAccess & lock)458 void StackGuard::InitThread(const ExecutionAccess& lock) {
459   if (thread_local_.Initialize()) isolate_->heap()->SetStackLimits();
460   uintptr_t stored_limit =
461       Isolate::CurrentPerIsolateThreadData()->stack_limit();
462   // You should hold the ExecutionAccess lock when you call this.
463   if (stored_limit != 0) {
464     StackGuard::SetStackLimit(stored_limit);
465   }
466 }
467 
468 
469 // --- C a l l s   t o   n a t i v e s ---
470 
471 #define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception)            \
472   do {                                                                         \
473     Isolate* isolate = Isolate::Current();                                     \
474     Object** args[argc] = argv;                                                \
475     ASSERT(has_pending_exception != NULL);                                     \
476     return Call(isolate->name##_fun(),                                         \
477                 isolate->js_builtins_object(), argc, args,                     \
478                 has_pending_exception);                                        \
479   } while (false)
480 
481 
ToBoolean(Handle<Object> obj)482 Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
483   // See the similar code in runtime.js:ToBoolean.
484   if (obj->IsBoolean()) return obj;
485   bool result = true;
486   if (obj->IsString()) {
487     result = Handle<String>::cast(obj)->length() != 0;
488   } else if (obj->IsNull() || obj->IsUndefined()) {
489     result = false;
490   } else if (obj->IsNumber()) {
491     double value = obj->Number();
492     result = !((value == 0) || isnan(value));
493   }
494   return Handle<Object>(HEAP->ToBoolean(result));
495 }
496 
497 
ToNumber(Handle<Object> obj,bool * exc)498 Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
499   RETURN_NATIVE_CALL(to_number, 1, { obj.location() }, exc);
500 }
501 
502 
ToString(Handle<Object> obj,bool * exc)503 Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
504   RETURN_NATIVE_CALL(to_string, 1, { obj.location() }, exc);
505 }
506 
507 
ToDetailString(Handle<Object> obj,bool * exc)508 Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
509   RETURN_NATIVE_CALL(to_detail_string, 1, { obj.location() }, exc);
510 }
511 
512 
ToObject(Handle<Object> obj,bool * exc)513 Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
514   if (obj->IsJSObject()) return obj;
515   RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc);
516 }
517 
518 
ToInteger(Handle<Object> obj,bool * exc)519 Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
520   RETURN_NATIVE_CALL(to_integer, 1, { obj.location() }, exc);
521 }
522 
523 
ToUint32(Handle<Object> obj,bool * exc)524 Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
525   RETURN_NATIVE_CALL(to_uint32, 1, { obj.location() }, exc);
526 }
527 
528 
ToInt32(Handle<Object> obj,bool * exc)529 Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
530   RETURN_NATIVE_CALL(to_int32, 1, { obj.location() }, exc);
531 }
532 
533 
NewDate(double time,bool * exc)534 Handle<Object> Execution::NewDate(double time, bool* exc) {
535   Handle<Object> time_obj = FACTORY->NewNumber(time);
536   RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
537 }
538 
539 
540 #undef RETURN_NATIVE_CALL
541 
542 
NewJSRegExp(Handle<String> pattern,Handle<String> flags,bool * exc)543 Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
544                                         Handle<String> flags,
545                                         bool* exc) {
546   Handle<JSFunction> function = Handle<JSFunction>(
547       pattern->GetIsolate()->global_context()->regexp_function());
548   Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
549       function, pattern, flags, exc);
550   if (*exc) return Handle<JSRegExp>();
551   return Handle<JSRegExp>::cast(re_obj);
552 }
553 
554 
CharAt(Handle<String> string,uint32_t index)555 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
556   Isolate* isolate = string->GetIsolate();
557   Factory* factory = isolate->factory();
558 
559   int int_index = static_cast<int>(index);
560   if (int_index < 0 || int_index >= string->length()) {
561     return factory->undefined_value();
562   }
563 
564   Handle<Object> char_at =
565       GetProperty(isolate->js_builtins_object(),
566                   factory->char_at_symbol());
567   if (!char_at->IsJSFunction()) {
568     return factory->undefined_value();
569   }
570 
571   bool caught_exception;
572   Handle<Object> index_object = factory->NewNumberFromInt(int_index);
573   Object** index_arg[] = { index_object.location() };
574   Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
575                                   string,
576                                   ARRAY_SIZE(index_arg),
577                                   index_arg,
578                                   &caught_exception);
579   if (caught_exception) {
580     return factory->undefined_value();
581   }
582   return result;
583 }
584 
585 
InstantiateFunction(Handle<FunctionTemplateInfo> data,bool * exc)586 Handle<JSFunction> Execution::InstantiateFunction(
587     Handle<FunctionTemplateInfo> data, bool* exc) {
588   Isolate* isolate = data->GetIsolate();
589   // Fast case: see if the function has already been instantiated
590   int serial_number = Smi::cast(data->serial_number())->value();
591   Object* elm =
592       isolate->global_context()->function_cache()->
593           GetElementNoExceptionThrown(serial_number);
594   if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
595   // The function has not yet been instantiated in this context; do it.
596   Object** args[1] = { Handle<Object>::cast(data).location() };
597   Handle<Object> result =
598       Call(isolate->instantiate_fun(),
599            isolate->js_builtins_object(), 1, args, exc);
600   if (*exc) return Handle<JSFunction>::null();
601   return Handle<JSFunction>::cast(result);
602 }
603 
604 
InstantiateObject(Handle<ObjectTemplateInfo> data,bool * exc)605 Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
606                                               bool* exc) {
607   Isolate* isolate = data->GetIsolate();
608   if (data->property_list()->IsUndefined() &&
609       !data->constructor()->IsUndefined()) {
610     // Initialization to make gcc happy.
611     Object* result = NULL;
612     {
613       HandleScope scope(isolate);
614       Handle<FunctionTemplateInfo> cons_template =
615           Handle<FunctionTemplateInfo>(
616               FunctionTemplateInfo::cast(data->constructor()));
617       Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
618       if (*exc) return Handle<JSObject>::null();
619       Handle<Object> value = New(cons, 0, NULL, exc);
620       if (*exc) return Handle<JSObject>::null();
621       result = *value;
622     }
623     ASSERT(!*exc);
624     return Handle<JSObject>(JSObject::cast(result));
625   } else {
626     Object** args[1] = { Handle<Object>::cast(data).location() };
627     Handle<Object> result =
628         Call(isolate->instantiate_fun(),
629              isolate->js_builtins_object(), 1, args, exc);
630     if (*exc) return Handle<JSObject>::null();
631     return Handle<JSObject>::cast(result);
632   }
633 }
634 
635 
ConfigureInstance(Handle<Object> instance,Handle<Object> instance_template,bool * exc)636 void Execution::ConfigureInstance(Handle<Object> instance,
637                                   Handle<Object> instance_template,
638                                   bool* exc) {
639   Isolate* isolate = Isolate::Current();
640   Object** args[2] = { instance.location(), instance_template.location() };
641   Execution::Call(isolate->configure_instance_fun(),
642                   isolate->js_builtins_object(), 2, args, exc);
643 }
644 
645 
GetStackTraceLine(Handle<Object> recv,Handle<JSFunction> fun,Handle<Object> pos,Handle<Object> is_global)646 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
647                                             Handle<JSFunction> fun,
648                                             Handle<Object> pos,
649                                             Handle<Object> is_global) {
650   Isolate* isolate = fun->GetIsolate();
651   const int argc = 4;
652   Object** args[argc] = { recv.location(),
653                           Handle<Object>::cast(fun).location(),
654                           pos.location(),
655                           is_global.location() };
656   bool caught_exception = false;
657   Handle<Object> result =
658       TryCall(isolate->get_stack_trace_line_fun(),
659               isolate->js_builtins_object(), argc, args,
660               &caught_exception);
661   if (caught_exception || !result->IsString()) {
662       return isolate->factory()->empty_symbol();
663   }
664 
665   return Handle<String>::cast(result);
666 }
667 
668 
RuntimePreempt()669 static Object* RuntimePreempt() {
670   Isolate* isolate = Isolate::Current();
671 
672   // Clear the preempt request flag.
673   isolate->stack_guard()->Continue(PREEMPT);
674 
675   ContextSwitcher::PreemptionReceived();
676 
677 #ifdef ENABLE_DEBUGGER_SUPPORT
678   if (isolate->debug()->InDebugger()) {
679     // If currently in the debugger don't do any actual preemption but record
680     // that preemption occoured while in the debugger.
681     isolate->debug()->PreemptionWhileInDebugger();
682   } else {
683     // Perform preemption.
684     v8::Unlocker unlocker;
685     Thread::YieldCPU();
686   }
687 #else
688   { // NOLINT
689     // Perform preemption.
690     v8::Unlocker unlocker;
691     Thread::YieldCPU();
692   }
693 #endif
694 
695   return isolate->heap()->undefined_value();
696 }
697 
698 
699 #ifdef ENABLE_DEBUGGER_SUPPORT
DebugBreakHelper()700 Object* Execution::DebugBreakHelper() {
701   Isolate* isolate = Isolate::Current();
702 
703   // Just continue if breaks are disabled.
704   if (isolate->debug()->disable_break()) {
705     return isolate->heap()->undefined_value();
706   }
707 
708   // Ignore debug break during bootstrapping.
709   if (isolate->bootstrapper()->IsActive()) {
710     return isolate->heap()->undefined_value();
711   }
712 
713   {
714     JavaScriptFrameIterator it(isolate);
715     ASSERT(!it.done());
716     Object* fun = it.frame()->function();
717     if (fun && fun->IsJSFunction()) {
718       // Don't stop in builtin functions.
719       if (JSFunction::cast(fun)->IsBuiltin()) {
720         return isolate->heap()->undefined_value();
721       }
722       GlobalObject* global = JSFunction::cast(fun)->context()->global();
723       // Don't stop in debugger functions.
724       if (isolate->debug()->IsDebugGlobal(global)) {
725         return isolate->heap()->undefined_value();
726       }
727     }
728   }
729 
730   // Collect the break state before clearing the flags.
731   bool debug_command_only =
732       isolate->stack_guard()->IsDebugCommand() &&
733       !isolate->stack_guard()->IsDebugBreak();
734 
735   // Clear the debug break request flag.
736   isolate->stack_guard()->Continue(DEBUGBREAK);
737 
738   ProcessDebugMesssages(debug_command_only);
739 
740   // Return to continue execution.
741   return isolate->heap()->undefined_value();
742 }
743 
ProcessDebugMesssages(bool debug_command_only)744 void Execution::ProcessDebugMesssages(bool debug_command_only) {
745   Isolate* isolate = Isolate::Current();
746   // Clear the debug command request flag.
747   isolate->stack_guard()->Continue(DEBUGCOMMAND);
748 
749   HandleScope scope(isolate);
750   // Enter the debugger. Just continue if we fail to enter the debugger.
751   EnterDebugger debugger;
752   if (debugger.FailedToEnter()) {
753     return;
754   }
755 
756   // Notify the debug event listeners. Indicate auto continue if the break was
757   // a debug command break.
758   isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(),
759                                     debug_command_only);
760 }
761 
762 
763 #endif
764 
HandleStackGuardInterrupt()765 MaybeObject* Execution::HandleStackGuardInterrupt() {
766   Isolate* isolate = Isolate::Current();
767   StackGuard* stack_guard = isolate->stack_guard();
768   isolate->counters()->stack_interrupts()->Increment();
769   if (stack_guard->IsRuntimeProfilerTick()) {
770     isolate->counters()->runtime_profiler_ticks()->Increment();
771     stack_guard->Continue(RUNTIME_PROFILER_TICK);
772     isolate->runtime_profiler()->OptimizeNow();
773   }
774 #ifdef ENABLE_DEBUGGER_SUPPORT
775   if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
776     DebugBreakHelper();
777   }
778 #endif
779   if (stack_guard->IsPreempted()) RuntimePreempt();
780   if (stack_guard->IsTerminateExecution()) {
781     stack_guard->Continue(TERMINATE);
782     return isolate->TerminateExecution();
783   }
784   if (stack_guard->IsInterrupted()) {
785     stack_guard->Continue(INTERRUPT);
786     return isolate->StackOverflow();
787   }
788   return isolate->heap()->undefined_value();
789 }
790 
791 } }  // namespace v8::internal
792