1// Copyright 2012 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 "deoptimizer.h"
37#include "isolate-inl.h"
38#include "runtime-profiler.h"
39#include "simulator.h"
40#include "v8threads.h"
41#include "vm-state-inl.h"
42
43namespace v8 {
44namespace internal {
45
46
47StackGuard::StackGuard()
48    : isolate_(NULL) {
49}
50
51
52void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
53  ASSERT(isolate_ != NULL);
54  // Ignore attempts to interrupt when interrupts are postponed.
55  if (should_postpone_interrupts(lock)) return;
56  thread_local_.jslimit_ = kInterruptLimit;
57  thread_local_.climit_ = kInterruptLimit;
58  isolate_->heap()->SetStackLimits();
59}
60
61
62void StackGuard::reset_limits(const ExecutionAccess& lock) {
63  ASSERT(isolate_ != NULL);
64  thread_local_.jslimit_ = thread_local_.real_jslimit_;
65  thread_local_.climit_ = thread_local_.real_climit_;
66  isolate_->heap()->SetStackLimits();
67}
68
69
70static Handle<Object> Invoke(bool is_construct,
71                             Handle<JSFunction> function,
72                             Handle<Object> receiver,
73                             int argc,
74                             Handle<Object> args[],
75                             bool* has_pending_exception) {
76  Isolate* isolate = function->GetIsolate();
77
78  // Entering JavaScript.
79  VMState<JS> state(isolate);
80
81  // Placeholder for return value.
82  MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
83
84  typedef Object* (*JSEntryFunction)(byte* entry,
85                                     Object* function,
86                                     Object* receiver,
87                                     int argc,
88                                     Object*** args);
89
90  Handle<Code> code = is_construct
91      ? isolate->factory()->js_construct_entry_code()
92      : isolate->factory()->js_entry_code();
93
94  // Convert calls on global objects to be calls on the global
95  // receiver instead to avoid having a 'this' pointer which refers
96  // directly to a global object.
97  if (receiver->IsGlobalObject()) {
98    Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
99    receiver = Handle<JSObject>(global->global_receiver());
100  }
101
102  // Make sure that the global object of the context we're about to
103  // make the current one is indeed a global object.
104  ASSERT(function->context()->global_object()->IsGlobalObject());
105
106  {
107    // Save and restore context around invocation and block the
108    // allocation of handles without explicit handle scopes.
109    SaveContext save(isolate);
110    SealHandleScope shs(isolate);
111    JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
112
113    // Call the function through the right JS entry stub.
114    byte* function_entry = function->code()->entry();
115    JSFunction* func = *function;
116    Object* recv = *receiver;
117    Object*** argv = reinterpret_cast<Object***>(args);
118    value =
119        CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
120  }
121
122#ifdef VERIFY_HEAP
123  value->Verify();
124#endif
125
126  // Update the pending exception flag and return the value.
127  *has_pending_exception = value->IsException();
128  ASSERT(*has_pending_exception == isolate->has_pending_exception());
129  if (*has_pending_exception) {
130    isolate->ReportPendingMessages();
131    if (isolate->pending_exception()->IsOutOfMemory()) {
132      if (!isolate->ignore_out_of_memory()) {
133        V8::FatalProcessOutOfMemory("JS", true);
134      }
135    }
136#ifdef ENABLE_DEBUGGER_SUPPORT
137    // Reset stepping state when script exits with uncaught exception.
138    if (isolate->debugger()->IsDebuggerActive()) {
139      isolate->debug()->ClearStepping();
140    }
141#endif  // ENABLE_DEBUGGER_SUPPORT
142    return Handle<Object>();
143  } else {
144    isolate->clear_pending_message();
145  }
146
147  return Handle<Object>(value->ToObjectUnchecked(), isolate);
148}
149
150
151Handle<Object> Execution::Call(Handle<Object> callable,
152                               Handle<Object> receiver,
153                               int argc,
154                               Handle<Object> argv[],
155                               bool* pending_exception,
156                               bool convert_receiver) {
157  *pending_exception = false;
158
159  if (!callable->IsJSFunction()) {
160    callable = TryGetFunctionDelegate(callable, pending_exception);
161    if (*pending_exception) return callable;
162  }
163  Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
164
165  // In non-strict mode, convert receiver.
166  if (convert_receiver && !receiver->IsJSReceiver() &&
167      !func->shared()->native() && func->shared()->is_classic_mode()) {
168    if (receiver->IsUndefined() || receiver->IsNull()) {
169      Object* global = func->context()->global_object()->global_receiver();
170      // Under some circumstances, 'global' can be the JSBuiltinsObject
171      // In that case, don't rewrite.  (FWIW, the same holds for
172      // GetIsolate()->global_object()->global_receiver().)
173      if (!global->IsJSBuiltinsObject()) {
174        receiver = Handle<Object>(global, func->GetIsolate());
175      }
176    } else {
177      receiver = ToObject(receiver, pending_exception);
178    }
179    if (*pending_exception) return callable;
180  }
181
182  return Invoke(false, func, receiver, argc, argv, pending_exception);
183}
184
185
186Handle<Object> Execution::New(Handle<JSFunction> func,
187                              int argc,
188                              Handle<Object> argv[],
189                              bool* pending_exception) {
190  return Invoke(true, func, func->GetIsolate()->global_object(), argc, argv,
191                pending_exception);
192}
193
194
195Handle<Object> Execution::TryCall(Handle<JSFunction> func,
196                                  Handle<Object> receiver,
197                                  int argc,
198                                  Handle<Object> args[],
199                                  bool* caught_exception) {
200  // Enter a try-block while executing the JavaScript code. To avoid
201  // duplicate error printing it must be non-verbose.  Also, to avoid
202  // creating message objects during stack overflow we shouldn't
203  // capture messages.
204  v8::TryCatch catcher;
205  catcher.SetVerbose(false);
206  catcher.SetCaptureMessage(false);
207  *caught_exception = false;
208
209  // Get isolate now, because handle might be persistent
210  // and get destroyed in the next call.
211  Isolate* isolate = func->GetIsolate();
212  Handle<Object> result = Invoke(false, func, receiver, argc, args,
213                                 caught_exception);
214
215  if (*caught_exception) {
216    ASSERT(catcher.HasCaught());
217    ASSERT(isolate->has_pending_exception());
218    ASSERT(isolate->external_caught_exception());
219    if (isolate->is_out_of_memory() && !isolate->ignore_out_of_memory()) {
220      V8::FatalProcessOutOfMemory("OOM during Execution::TryCall");
221    }
222    if (isolate->pending_exception() ==
223        isolate->heap()->termination_exception()) {
224      result = isolate->factory()->termination_exception();
225    } else {
226      result = v8::Utils::OpenHandle(*catcher.Exception());
227    }
228    isolate->OptionalRescheduleException(true);
229  }
230
231  ASSERT(!isolate->has_pending_exception());
232  ASSERT(!isolate->external_caught_exception());
233  return result;
234}
235
236
237Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
238  ASSERT(!object->IsJSFunction());
239  Isolate* isolate = Isolate::Current();
240  Factory* factory = isolate->factory();
241
242  // If you return a function from here, it will be called when an
243  // attempt is made to call the given object as a function.
244
245  // If object is a function proxy, get its handler. Iterate if necessary.
246  Object* fun = *object;
247  while (fun->IsJSFunctionProxy()) {
248    fun = JSFunctionProxy::cast(fun)->call_trap();
249  }
250  if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
251
252  // Objects created through the API can have an instance-call handler
253  // that should be used when calling the object as a function.
254  if (fun->IsHeapObject() &&
255      HeapObject::cast(fun)->map()->has_instance_call_handler()) {
256    return Handle<JSFunction>(
257        isolate->native_context()->call_as_function_delegate());
258  }
259
260  return factory->undefined_value();
261}
262
263
264Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object,
265                                                 bool* has_pending_exception) {
266  ASSERT(!object->IsJSFunction());
267  Isolate* isolate = Isolate::Current();
268
269  // If object is a function proxy, get its handler. Iterate if necessary.
270  Object* fun = *object;
271  while (fun->IsJSFunctionProxy()) {
272    fun = JSFunctionProxy::cast(fun)->call_trap();
273  }
274  if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
275
276  // Objects created through the API can have an instance-call handler
277  // that should be used when calling the object as a function.
278  if (fun->IsHeapObject() &&
279      HeapObject::cast(fun)->map()->has_instance_call_handler()) {
280    return Handle<JSFunction>(
281        isolate->native_context()->call_as_function_delegate());
282  }
283
284  // If the Object doesn't have an instance-call handler we should
285  // throw a non-callable exception.
286  i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
287      "called_non_callable", i::HandleVector<i::Object>(&object, 1));
288  isolate->Throw(*error_obj);
289  *has_pending_exception = true;
290
291  return isolate->factory()->undefined_value();
292}
293
294
295Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
296  ASSERT(!object->IsJSFunction());
297  Isolate* isolate = Isolate::Current();
298
299  // If you return a function from here, it will be called when an
300  // attempt is made to call the given object as a constructor.
301
302  // If object is a function proxies, get its handler. Iterate if necessary.
303  Object* fun = *object;
304  while (fun->IsJSFunctionProxy()) {
305    fun = JSFunctionProxy::cast(fun)->call_trap();
306  }
307  if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
308
309  // Objects created through the API can have an instance-call handler
310  // that should be used when calling the object as a function.
311  if (fun->IsHeapObject() &&
312      HeapObject::cast(fun)->map()->has_instance_call_handler()) {
313    return Handle<JSFunction>(
314        isolate->native_context()->call_as_constructor_delegate());
315  }
316
317  return isolate->factory()->undefined_value();
318}
319
320
321Handle<Object> Execution::TryGetConstructorDelegate(
322    Handle<Object> object,
323    bool* has_pending_exception) {
324  ASSERT(!object->IsJSFunction());
325  Isolate* isolate = Isolate::Current();
326
327  // If you return a function from here, it will be called when an
328  // attempt is made to call the given object as a constructor.
329
330  // If object is a function proxies, get its handler. Iterate if necessary.
331  Object* fun = *object;
332  while (fun->IsJSFunctionProxy()) {
333    fun = JSFunctionProxy::cast(fun)->call_trap();
334  }
335  if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
336
337  // Objects created through the API can have an instance-call handler
338  // that should be used when calling the object as a function.
339  if (fun->IsHeapObject() &&
340      HeapObject::cast(fun)->map()->has_instance_call_handler()) {
341    return Handle<JSFunction>(
342        isolate->native_context()->call_as_constructor_delegate());
343  }
344
345  // If the Object doesn't have an instance-call handler we should
346  // throw a non-callable exception.
347  i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
348      "called_non_callable", i::HandleVector<i::Object>(&object, 1));
349  isolate->Throw(*error_obj);
350  *has_pending_exception = true;
351
352  return isolate->factory()->undefined_value();
353}
354
355
356bool StackGuard::IsStackOverflow() {
357  ExecutionAccess access(isolate_);
358  return (thread_local_.jslimit_ != kInterruptLimit &&
359          thread_local_.climit_ != kInterruptLimit);
360}
361
362
363void StackGuard::EnableInterrupts() {
364  ExecutionAccess access(isolate_);
365  if (has_pending_interrupts(access)) {
366    set_interrupt_limits(access);
367  }
368}
369
370
371void StackGuard::SetStackLimit(uintptr_t limit) {
372  ExecutionAccess access(isolate_);
373  // If the current limits are special (e.g. due to a pending interrupt) then
374  // leave them alone.
375  uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
376  if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
377    thread_local_.jslimit_ = jslimit;
378  }
379  if (thread_local_.climit_ == thread_local_.real_climit_) {
380    thread_local_.climit_ = limit;
381  }
382  thread_local_.real_climit_ = limit;
383  thread_local_.real_jslimit_ = jslimit;
384}
385
386
387void StackGuard::DisableInterrupts() {
388  ExecutionAccess access(isolate_);
389  reset_limits(access);
390}
391
392
393bool StackGuard::ShouldPostponeInterrupts() {
394  ExecutionAccess access(isolate_);
395  return should_postpone_interrupts(access);
396}
397
398
399bool StackGuard::IsInterrupted() {
400  ExecutionAccess access(isolate_);
401  return (thread_local_.interrupt_flags_ & INTERRUPT) != 0;
402}
403
404
405void StackGuard::Interrupt() {
406  ExecutionAccess access(isolate_);
407  thread_local_.interrupt_flags_ |= INTERRUPT;
408  set_interrupt_limits(access);
409}
410
411
412bool StackGuard::IsPreempted() {
413  ExecutionAccess access(isolate_);
414  return thread_local_.interrupt_flags_ & PREEMPT;
415}
416
417
418void StackGuard::Preempt() {
419  ExecutionAccess access(isolate_);
420  thread_local_.interrupt_flags_ |= PREEMPT;
421  set_interrupt_limits(access);
422}
423
424
425bool StackGuard::IsTerminateExecution() {
426  ExecutionAccess access(isolate_);
427  return (thread_local_.interrupt_flags_ & TERMINATE) != 0;
428}
429
430
431void StackGuard::CancelTerminateExecution() {
432  ExecutionAccess access(isolate_);
433  Continue(TERMINATE);
434  isolate_->CancelTerminateExecution();
435}
436
437
438void StackGuard::TerminateExecution() {
439  ExecutionAccess access(isolate_);
440  thread_local_.interrupt_flags_ |= TERMINATE;
441  set_interrupt_limits(access);
442}
443
444
445bool StackGuard::IsGCRequest() {
446  ExecutionAccess access(isolate_);
447  return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0;
448}
449
450
451void StackGuard::RequestGC() {
452  ExecutionAccess access(isolate_);
453  thread_local_.interrupt_flags_ |= GC_REQUEST;
454  if (thread_local_.postpone_interrupts_nesting_ == 0) {
455    thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
456    isolate_->heap()->SetStackLimits();
457  }
458}
459
460
461bool StackGuard::IsFullDeopt() {
462  ExecutionAccess access(isolate_);
463  return (thread_local_.interrupt_flags_ & FULL_DEOPT) != 0;
464}
465
466
467void StackGuard::FullDeopt() {
468  ExecutionAccess access(isolate_);
469  thread_local_.interrupt_flags_ |= FULL_DEOPT;
470  set_interrupt_limits(access);
471}
472
473
474#ifdef ENABLE_DEBUGGER_SUPPORT
475bool StackGuard::IsDebugBreak() {
476  ExecutionAccess access(isolate_);
477  return thread_local_.interrupt_flags_ & DEBUGBREAK;
478}
479
480
481void StackGuard::DebugBreak() {
482  ExecutionAccess access(isolate_);
483  thread_local_.interrupt_flags_ |= DEBUGBREAK;
484  set_interrupt_limits(access);
485}
486
487
488bool StackGuard::IsDebugCommand() {
489  ExecutionAccess access(isolate_);
490  return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
491}
492
493
494void StackGuard::DebugCommand() {
495  if (FLAG_debugger_auto_break) {
496    ExecutionAccess access(isolate_);
497    thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
498    set_interrupt_limits(access);
499  }
500}
501#endif
502
503void StackGuard::Continue(InterruptFlag after_what) {
504  ExecutionAccess access(isolate_);
505  thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
506  if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
507    reset_limits(access);
508  }
509}
510
511
512char* StackGuard::ArchiveStackGuard(char* to) {
513  ExecutionAccess access(isolate_);
514  OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
515  ThreadLocal blank;
516
517  // Set the stack limits using the old thread_local_.
518  // TODO(isolates): This was the old semantics of constructing a ThreadLocal
519  //                 (as the ctor called SetStackLimits, which looked at the
520  //                 current thread_local_ from StackGuard)-- but is this
521  //                 really what was intended?
522  isolate_->heap()->SetStackLimits();
523  thread_local_ = blank;
524
525  return to + sizeof(ThreadLocal);
526}
527
528
529char* StackGuard::RestoreStackGuard(char* from) {
530  ExecutionAccess access(isolate_);
531  OS::MemCopy(
532      reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
533  isolate_->heap()->SetStackLimits();
534  return from + sizeof(ThreadLocal);
535}
536
537
538void StackGuard::FreeThreadResources() {
539  Isolate::PerIsolateThreadData* per_thread =
540      isolate_->FindOrAllocatePerThreadDataForThisThread();
541  per_thread->set_stack_limit(thread_local_.real_climit_);
542}
543
544
545void StackGuard::ThreadLocal::Clear() {
546  real_jslimit_ = kIllegalLimit;
547  jslimit_ = kIllegalLimit;
548  real_climit_ = kIllegalLimit;
549  climit_ = kIllegalLimit;
550  nesting_ = 0;
551  postpone_interrupts_nesting_ = 0;
552  interrupt_flags_ = 0;
553}
554
555
556bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
557  bool should_set_stack_limits = false;
558  if (real_climit_ == kIllegalLimit) {
559    // Takes the address of the limit variable in order to find out where
560    // the top of stack is right now.
561    const uintptr_t kLimitSize = FLAG_stack_size * KB;
562    uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
563    ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
564    real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
565    jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
566    real_climit_ = limit;
567    climit_ = limit;
568    should_set_stack_limits = true;
569  }
570  nesting_ = 0;
571  postpone_interrupts_nesting_ = 0;
572  interrupt_flags_ = 0;
573  return should_set_stack_limits;
574}
575
576
577void StackGuard::ClearThread(const ExecutionAccess& lock) {
578  thread_local_.Clear();
579  isolate_->heap()->SetStackLimits();
580}
581
582
583void StackGuard::InitThread(const ExecutionAccess& lock) {
584  if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
585  Isolate::PerIsolateThreadData* per_thread =
586      isolate_->FindOrAllocatePerThreadDataForThisThread();
587  uintptr_t stored_limit = per_thread->stack_limit();
588  // You should hold the ExecutionAccess lock when you call this.
589  if (stored_limit != 0) {
590    SetStackLimit(stored_limit);
591  }
592}
593
594
595// --- C a l l s   t o   n a t i v e s ---
596
597#define RETURN_NATIVE_CALL(name, args, has_pending_exception)           \
598  do {                                                                  \
599    Isolate* isolate = Isolate::Current();                              \
600    Handle<Object> argv[] = args;                                       \
601    ASSERT(has_pending_exception != NULL);                              \
602    return Call(isolate->name##_fun(),                                  \
603                isolate->js_builtins_object(),                          \
604                ARRAY_SIZE(argv), argv,                                 \
605                has_pending_exception);                                 \
606  } while (false)
607
608
609Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
610  RETURN_NATIVE_CALL(to_number, { obj }, exc);
611}
612
613
614Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
615  RETURN_NATIVE_CALL(to_string, { obj }, exc);
616}
617
618
619Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
620  RETURN_NATIVE_CALL(to_detail_string, { obj }, exc);
621}
622
623
624Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
625  if (obj->IsSpecObject()) return obj;
626  RETURN_NATIVE_CALL(to_object, { obj }, exc);
627}
628
629
630Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
631  RETURN_NATIVE_CALL(to_integer, { obj }, exc);
632}
633
634
635Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
636  RETURN_NATIVE_CALL(to_uint32, { obj }, exc);
637}
638
639
640Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
641  RETURN_NATIVE_CALL(to_int32, { obj }, exc);
642}
643
644
645Handle<Object> Execution::NewDate(double time, bool* exc) {
646  Isolate* isolate = Isolate::Current();
647  Handle<Object> time_obj = isolate->factory()->NewNumber(time);
648  RETURN_NATIVE_CALL(create_date, { time_obj }, exc);
649}
650
651
652#undef RETURN_NATIVE_CALL
653
654
655Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
656                                        Handle<String> flags,
657                                        bool* exc) {
658  Handle<JSFunction> function = Handle<JSFunction>(
659      pattern->GetIsolate()->native_context()->regexp_function());
660  Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
661      function, pattern, flags, exc);
662  if (*exc) return Handle<JSRegExp>();
663  return Handle<JSRegExp>::cast(re_obj);
664}
665
666
667Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
668  Isolate* isolate = string->GetIsolate();
669  Factory* factory = isolate->factory();
670
671  int int_index = static_cast<int>(index);
672  if (int_index < 0 || int_index >= string->length()) {
673    return factory->undefined_value();
674  }
675
676  Handle<Object> char_at = GetProperty(
677      isolate, isolate->js_builtins_object(), factory->char_at_string());
678  if (!char_at->IsJSFunction()) {
679    return factory->undefined_value();
680  }
681
682  bool caught_exception;
683  Handle<Object> index_object = factory->NewNumberFromInt(int_index);
684  Handle<Object> index_arg[] = { index_object };
685  Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
686                                  string,
687                                  ARRAY_SIZE(index_arg),
688                                  index_arg,
689                                  &caught_exception);
690  if (caught_exception) {
691    return factory->undefined_value();
692  }
693  return result;
694}
695
696
697Handle<JSFunction> Execution::InstantiateFunction(
698    Handle<FunctionTemplateInfo> data,
699    bool* exc) {
700  Isolate* isolate = data->GetIsolate();
701  // Fast case: see if the function has already been instantiated
702  int serial_number = Smi::cast(data->serial_number())->value();
703  Object* elm =
704      isolate->native_context()->function_cache()->
705          GetElementNoExceptionThrown(serial_number);
706  if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
707  // The function has not yet been instantiated in this context; do it.
708  Handle<Object> args[] = { data };
709  Handle<Object> result = Call(isolate->instantiate_fun(),
710                               isolate->js_builtins_object(),
711                               ARRAY_SIZE(args),
712                               args,
713                               exc);
714  if (*exc) return Handle<JSFunction>::null();
715  return Handle<JSFunction>::cast(result);
716}
717
718
719Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
720                                              bool* exc) {
721  Isolate* isolate = data->GetIsolate();
722  if (data->property_list()->IsUndefined() &&
723      !data->constructor()->IsUndefined()) {
724    // Initialization to make gcc happy.
725    Object* result = NULL;
726    {
727      HandleScope scope(isolate);
728      Handle<FunctionTemplateInfo> cons_template =
729          Handle<FunctionTemplateInfo>(
730              FunctionTemplateInfo::cast(data->constructor()));
731      Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
732      if (*exc) return Handle<JSObject>::null();
733      Handle<Object> value = New(cons, 0, NULL, exc);
734      if (*exc) return Handle<JSObject>::null();
735      result = *value;
736    }
737    ASSERT(!*exc);
738    return Handle<JSObject>(JSObject::cast(result));
739  } else {
740    Handle<Object> args[] = { data };
741    Handle<Object> result = Call(isolate->instantiate_fun(),
742                                 isolate->js_builtins_object(),
743                                 ARRAY_SIZE(args),
744                                 args,
745                                 exc);
746    if (*exc) return Handle<JSObject>::null();
747    return Handle<JSObject>::cast(result);
748  }
749}
750
751
752void Execution::ConfigureInstance(Handle<Object> instance,
753                                  Handle<Object> instance_template,
754                                  bool* exc) {
755  Isolate* isolate = Isolate::Current();
756  Handle<Object> args[] = { instance, instance_template };
757  Execution::Call(isolate->configure_instance_fun(),
758                  isolate->js_builtins_object(),
759                  ARRAY_SIZE(args),
760                  args,
761                  exc);
762}
763
764
765Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
766                                            Handle<JSFunction> fun,
767                                            Handle<Object> pos,
768                                            Handle<Object> is_global) {
769  Isolate* isolate = fun->GetIsolate();
770  Handle<Object> args[] = { recv, fun, pos, is_global };
771  bool caught_exception;
772  Handle<Object> result = TryCall(isolate->get_stack_trace_line_fun(),
773                                  isolate->js_builtins_object(),
774                                  ARRAY_SIZE(args),
775                                  args,
776                                  &caught_exception);
777  if (caught_exception || !result->IsString()) {
778      return isolate->factory()->empty_string();
779  }
780
781  return Handle<String>::cast(result);
782}
783
784
785static Object* RuntimePreempt() {
786  Isolate* isolate = Isolate::Current();
787
788  // Clear the preempt request flag.
789  isolate->stack_guard()->Continue(PREEMPT);
790
791  ContextSwitcher::PreemptionReceived();
792
793#ifdef ENABLE_DEBUGGER_SUPPORT
794  if (isolate->debug()->InDebugger()) {
795    // If currently in the debugger don't do any actual preemption but record
796    // that preemption occoured while in the debugger.
797    isolate->debug()->PreemptionWhileInDebugger();
798  } else {
799    // Perform preemption.
800    v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
801    Thread::YieldCPU();
802  }
803#else
804  { // NOLINT
805    // Perform preemption.
806    v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
807    Thread::YieldCPU();
808  }
809#endif
810
811  return isolate->heap()->undefined_value();
812}
813
814
815#ifdef ENABLE_DEBUGGER_SUPPORT
816Object* Execution::DebugBreakHelper() {
817  Isolate* isolate = Isolate::Current();
818
819  // Just continue if breaks are disabled.
820  if (isolate->debug()->disable_break()) {
821    return isolate->heap()->undefined_value();
822  }
823
824  // Ignore debug break during bootstrapping.
825  if (isolate->bootstrapper()->IsActive()) {
826    return isolate->heap()->undefined_value();
827  }
828
829  // Ignore debug break if debugger is not active.
830  if (!isolate->debugger()->IsDebuggerActive()) {
831    return isolate->heap()->undefined_value();
832  }
833
834  StackLimitCheck check(isolate);
835  if (check.HasOverflowed()) {
836    return isolate->heap()->undefined_value();
837  }
838
839  {
840    JavaScriptFrameIterator it(isolate);
841    ASSERT(!it.done());
842    Object* fun = it.frame()->function();
843    if (fun && fun->IsJSFunction()) {
844      // Don't stop in builtin functions.
845      if (JSFunction::cast(fun)->IsBuiltin()) {
846        return isolate->heap()->undefined_value();
847      }
848      GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
849      // Don't stop in debugger functions.
850      if (isolate->debug()->IsDebugGlobal(global)) {
851        return isolate->heap()->undefined_value();
852      }
853    }
854  }
855
856  // Collect the break state before clearing the flags.
857  bool debug_command_only =
858      isolate->stack_guard()->IsDebugCommand() &&
859      !isolate->stack_guard()->IsDebugBreak();
860
861  // Clear the debug break request flag.
862  isolate->stack_guard()->Continue(DEBUGBREAK);
863
864  ProcessDebugMessages(debug_command_only);
865
866  // Return to continue execution.
867  return isolate->heap()->undefined_value();
868}
869
870
871void Execution::ProcessDebugMessages(bool debug_command_only) {
872  Isolate* isolate = Isolate::Current();
873  // Clear the debug command request flag.
874  isolate->stack_guard()->Continue(DEBUGCOMMAND);
875
876  StackLimitCheck check(isolate);
877  if (check.HasOverflowed()) {
878    return;
879  }
880
881  HandleScope scope(isolate);
882  // Enter the debugger. Just continue if we fail to enter the debugger.
883  EnterDebugger debugger;
884  if (debugger.FailedToEnter()) {
885    return;
886  }
887
888  // Notify the debug event listeners. Indicate auto continue if the break was
889  // a debug command break.
890  isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(),
891                                    debug_command_only);
892}
893
894
895#endif
896
897MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
898  StackGuard* stack_guard = isolate->stack_guard();
899  if (stack_guard->ShouldPostponeInterrupts()) {
900    return isolate->heap()->undefined_value();
901  }
902
903  if (stack_guard->IsGCRequest()) {
904    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
905                                       "StackGuard GC request");
906    stack_guard->Continue(GC_REQUEST);
907  }
908
909  isolate->counters()->stack_interrupts()->Increment();
910  isolate->counters()->runtime_profiler_ticks()->Increment();
911  isolate->runtime_profiler()->OptimizeNow();
912#ifdef ENABLE_DEBUGGER_SUPPORT
913  if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
914    DebugBreakHelper();
915  }
916#endif
917  if (stack_guard->IsPreempted()) RuntimePreempt();
918  if (stack_guard->IsTerminateExecution()) {
919    stack_guard->Continue(TERMINATE);
920    return isolate->TerminateExecution();
921  }
922  if (stack_guard->IsInterrupted()) {
923    stack_guard->Continue(INTERRUPT);
924    return isolate->StackOverflow();
925  }
926  if (stack_guard->IsFullDeopt()) {
927    stack_guard->Continue(FULL_DEOPT);
928    Deoptimizer::DeoptimizeAll(isolate);
929  }
930  return isolate->heap()->undefined_value();
931}
932
933
934} }  // namespace v8::internal
935