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 "isolate-inl.h"
37#include "runtime-profiler.h"
38#include "simulator.h"
39#include "v8threads.h"
40#include "vm-state-inl.h"
41
42namespace v8 {
43namespace internal {
44
45
46StackGuard::StackGuard()
47    : isolate_(NULL) {
48}
49
50
51void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
52  ASSERT(isolate_ != NULL);
53  // Ignore attempts to interrupt when interrupts are postponed.
54  if (should_postpone_interrupts(lock)) return;
55  thread_local_.jslimit_ = kInterruptLimit;
56  thread_local_.climit_ = kInterruptLimit;
57  isolate_->heap()->SetStackLimits();
58}
59
60
61void StackGuard::reset_limits(const ExecutionAccess& lock) {
62  ASSERT(isolate_ != NULL);
63  thread_local_.jslimit_ = thread_local_.real_jslimit_;
64  thread_local_.climit_ = thread_local_.real_climit_;
65  isolate_->heap()->SetStackLimits();
66}
67
68
69static Handle<Object> Invoke(bool is_construct,
70                             Handle<JSFunction> function,
71                             Handle<Object> receiver,
72                             int argc,
73                             Handle<Object> args[],
74                             bool* has_pending_exception) {
75  Isolate* isolate = function->GetIsolate();
76
77  // Entering JavaScript.
78  VMState state(isolate, JS);
79
80  // Placeholder for return value.
81  MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
82
83  typedef Object* (*JSEntryFunction)(byte* entry,
84                                     Object* function,
85                                     Object* receiver,
86                                     int argc,
87                                     Object*** args);
88
89  Handle<Code> code = is_construct
90      ? isolate->factory()->js_construct_entry_code()
91      : isolate->factory()->js_entry_code();
92
93  // Convert calls on global objects to be calls on the global
94  // receiver instead to avoid having a 'this' pointer which refers
95  // directly to a global object.
96  if (receiver->IsGlobalObject()) {
97    Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
98    receiver = Handle<JSObject>(global->global_receiver());
99  }
100
101  // Make sure that the global object of the context we're about to
102  // make the current one is indeed a global object.
103  ASSERT(function->context()->global()->IsGlobalObject());
104
105  {
106    // Save and restore context around invocation and block the
107    // allocation of handles without explicit handle scopes.
108    SaveContext save(isolate);
109    NoHandleAllocation na;
110    JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
111
112    // Call the function through the right JS entry stub.
113    byte* function_entry = function->code()->entry();
114    JSFunction* func = *function;
115    Object* recv = *receiver;
116    Object*** argv = reinterpret_cast<Object***>(args);
117    value =
118        CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
119  }
120
121#ifdef DEBUG
122  value->Verify();
123#endif
124
125  // Update the pending exception flag and return the value.
126  *has_pending_exception = value->IsException();
127  ASSERT(*has_pending_exception == Isolate::Current()->has_pending_exception());
128  if (*has_pending_exception) {
129    isolate->ReportPendingMessages();
130    if (isolate->pending_exception() == Failure::OutOfMemoryException()) {
131      if (!isolate->ignore_out_of_memory()) {
132        V8::FatalProcessOutOfMemory("JS", true);
133      }
134    }
135    return Handle<Object>();
136  } else {
137    isolate->clear_pending_message();
138  }
139
140  return Handle<Object>(value->ToObjectUnchecked(), isolate);
141}
142
143
144Handle<Object> Execution::Call(Handle<Object> callable,
145                               Handle<Object> receiver,
146                               int argc,
147                               Handle<Object> argv[],
148                               bool* pending_exception,
149                               bool convert_receiver) {
150  *pending_exception = false;
151
152  if (!callable->IsJSFunction()) {
153    callable = TryGetFunctionDelegate(callable, pending_exception);
154    if (*pending_exception) return callable;
155  }
156  Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
157
158  // In non-strict mode, convert receiver.
159  if (convert_receiver && !receiver->IsJSReceiver() &&
160      !func->shared()->native() && func->shared()->is_classic_mode()) {
161    if (receiver->IsUndefined() || receiver->IsNull()) {
162      Object* global = func->context()->global()->global_receiver();
163      // Under some circumstances, 'global' can be the JSBuiltinsObject
164      // In that case, don't rewrite.
165      // (FWIW, the same holds for GetIsolate()->global()->global_receiver().)
166      if (!global->IsJSBuiltinsObject()) receiver = Handle<Object>(global);
167    } else {
168      receiver = ToObject(receiver, pending_exception);
169    }
170    if (*pending_exception) return callable;
171  }
172
173  return Invoke(false, func, receiver, argc, argv, pending_exception);
174}
175
176
177Handle<Object> Execution::New(Handle<JSFunction> func,
178                              int argc,
179                              Handle<Object> argv[],
180                              bool* pending_exception) {
181  return Invoke(true, func, Isolate::Current()->global(), argc, argv,
182                pending_exception);
183}
184
185
186Handle<Object> Execution::TryCall(Handle<JSFunction> func,
187                                  Handle<Object> receiver,
188                                  int argc,
189                                  Handle<Object> args[],
190                                  bool* caught_exception) {
191  // Enter a try-block while executing the JavaScript code. To avoid
192  // duplicate error printing it must be non-verbose.  Also, to avoid
193  // creating message objects during stack overflow we shouldn't
194  // capture messages.
195  v8::TryCatch catcher;
196  catcher.SetVerbose(false);
197  catcher.SetCaptureMessage(false);
198  *caught_exception = false;
199
200  Handle<Object> result = Invoke(false, func, receiver, argc, args,
201                                 caught_exception);
202
203  if (*caught_exception) {
204    ASSERT(catcher.HasCaught());
205    Isolate* isolate = Isolate::Current();
206    ASSERT(isolate->has_pending_exception());
207    ASSERT(isolate->external_caught_exception());
208    if (isolate->pending_exception() ==
209        isolate->heap()->termination_exception()) {
210      result = isolate->factory()->termination_exception();
211    } else {
212      result = v8::Utils::OpenHandle(*catcher.Exception());
213    }
214    isolate->OptionalRescheduleException(true);
215  }
216
217  ASSERT(!Isolate::Current()->has_pending_exception());
218  ASSERT(!Isolate::Current()->external_caught_exception());
219  return result;
220}
221
222
223Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
224  ASSERT(!object->IsJSFunction());
225  Isolate* isolate = Isolate::Current();
226  Factory* factory = isolate->factory();
227
228  // If you return a function from here, it will be called when an
229  // attempt is made to call the given object as a function.
230
231  // If object is a function proxy, get its handler. Iterate if necessary.
232  Object* fun = *object;
233  while (fun->IsJSFunctionProxy()) {
234    fun = JSFunctionProxy::cast(fun)->call_trap();
235  }
236  if (fun->IsJSFunction()) return Handle<Object>(fun);
237
238  // Objects created through the API can have an instance-call handler
239  // that should be used when calling the object as a function.
240  if (fun->IsHeapObject() &&
241      HeapObject::cast(fun)->map()->has_instance_call_handler()) {
242    return Handle<JSFunction>(
243        isolate->global_context()->call_as_function_delegate());
244  }
245
246  return factory->undefined_value();
247}
248
249
250Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object,
251                                                 bool* has_pending_exception) {
252  ASSERT(!object->IsJSFunction());
253  Isolate* isolate = Isolate::Current();
254
255  // If object is a function proxy, get its handler. Iterate if necessary.
256  Object* fun = *object;
257  while (fun->IsJSFunctionProxy()) {
258    fun = JSFunctionProxy::cast(fun)->call_trap();
259  }
260  if (fun->IsJSFunction()) return Handle<Object>(fun);
261
262  // Objects created through the API can have an instance-call handler
263  // that should be used when calling the object as a function.
264  if (fun->IsHeapObject() &&
265      HeapObject::cast(fun)->map()->has_instance_call_handler()) {
266    return Handle<JSFunction>(
267        isolate->global_context()->call_as_function_delegate());
268  }
269
270  // If the Object doesn't have an instance-call handler we should
271  // throw a non-callable exception.
272  i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
273      "called_non_callable", i::HandleVector<i::Object>(&object, 1));
274  isolate->Throw(*error_obj);
275  *has_pending_exception = true;
276
277  return isolate->factory()->undefined_value();
278}
279
280
281Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
282  ASSERT(!object->IsJSFunction());
283  Isolate* isolate = Isolate::Current();
284
285  // If you return a function from here, it will be called when an
286  // attempt is made to call the given object as a constructor.
287
288  // If object is a function proxies, get its handler. Iterate if necessary.
289  Object* fun = *object;
290  while (fun->IsJSFunctionProxy()) {
291    fun = JSFunctionProxy::cast(fun)->call_trap();
292  }
293  if (fun->IsJSFunction()) return Handle<Object>(fun);
294
295  // Objects created through the API can have an instance-call handler
296  // that should be used when calling the object as a function.
297  if (fun->IsHeapObject() &&
298      HeapObject::cast(fun)->map()->has_instance_call_handler()) {
299    return Handle<JSFunction>(
300        isolate->global_context()->call_as_constructor_delegate());
301  }
302
303  return isolate->factory()->undefined_value();
304}
305
306
307Handle<Object> Execution::TryGetConstructorDelegate(
308    Handle<Object> object,
309    bool* has_pending_exception) {
310  ASSERT(!object->IsJSFunction());
311  Isolate* isolate = Isolate::Current();
312
313  // If you return a function from here, it will be called when an
314  // attempt is made to call the given object as a constructor.
315
316  // If object is a function proxies, get its handler. Iterate if necessary.
317  Object* fun = *object;
318  while (fun->IsJSFunctionProxy()) {
319    fun = JSFunctionProxy::cast(fun)->call_trap();
320  }
321  if (fun->IsJSFunction()) return Handle<Object>(fun);
322
323  // Objects created through the API can have an instance-call handler
324  // that should be used when calling the object as a function.
325  if (fun->IsHeapObject() &&
326      HeapObject::cast(fun)->map()->has_instance_call_handler()) {
327    return Handle<JSFunction>(
328        isolate->global_context()->call_as_constructor_delegate());
329  }
330
331  // If the Object doesn't have an instance-call handler we should
332  // throw a non-callable exception.
333  i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
334      "called_non_callable", i::HandleVector<i::Object>(&object, 1));
335  isolate->Throw(*error_obj);
336  *has_pending_exception = true;
337
338  return isolate->factory()->undefined_value();
339}
340
341
342bool StackGuard::IsStackOverflow() {
343  ExecutionAccess access(isolate_);
344  return (thread_local_.jslimit_ != kInterruptLimit &&
345          thread_local_.climit_ != kInterruptLimit);
346}
347
348
349void StackGuard::EnableInterrupts() {
350  ExecutionAccess access(isolate_);
351  if (has_pending_interrupts(access)) {
352    set_interrupt_limits(access);
353  }
354}
355
356
357void StackGuard::SetStackLimit(uintptr_t limit) {
358  ExecutionAccess access(isolate_);
359  // If the current limits are special (e.g. due to a pending interrupt) then
360  // leave them alone.
361  uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
362  if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
363    thread_local_.jslimit_ = jslimit;
364  }
365  if (thread_local_.climit_ == thread_local_.real_climit_) {
366    thread_local_.climit_ = limit;
367  }
368  thread_local_.real_climit_ = limit;
369  thread_local_.real_jslimit_ = jslimit;
370}
371
372
373void StackGuard::DisableInterrupts() {
374  ExecutionAccess access(isolate_);
375  reset_limits(access);
376}
377
378
379bool StackGuard::ShouldPostponeInterrupts() {
380  ExecutionAccess access(isolate_);
381  return should_postpone_interrupts(access);
382}
383
384
385bool StackGuard::IsInterrupted() {
386  ExecutionAccess access(isolate_);
387  return (thread_local_.interrupt_flags_ & INTERRUPT) != 0;
388}
389
390
391void StackGuard::Interrupt() {
392  ExecutionAccess access(isolate_);
393  thread_local_.interrupt_flags_ |= INTERRUPT;
394  set_interrupt_limits(access);
395}
396
397
398bool StackGuard::IsPreempted() {
399  ExecutionAccess access(isolate_);
400  return thread_local_.interrupt_flags_ & PREEMPT;
401}
402
403
404void StackGuard::Preempt() {
405  ExecutionAccess access(isolate_);
406  thread_local_.interrupt_flags_ |= PREEMPT;
407  set_interrupt_limits(access);
408}
409
410
411bool StackGuard::IsTerminateExecution() {
412  ExecutionAccess access(isolate_);
413  return (thread_local_.interrupt_flags_ & TERMINATE) != 0;
414}
415
416
417void StackGuard::TerminateExecution() {
418  ExecutionAccess access(isolate_);
419  thread_local_.interrupt_flags_ |= TERMINATE;
420  set_interrupt_limits(access);
421}
422
423
424bool StackGuard::IsRuntimeProfilerTick() {
425  ExecutionAccess access(isolate_);
426  return (thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK) != 0;
427}
428
429
430void StackGuard::RequestRuntimeProfilerTick() {
431  // Ignore calls if we're not optimizing or if we can't get the lock.
432  if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) {
433    thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK;
434    if (thread_local_.postpone_interrupts_nesting_ == 0) {
435      thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
436      isolate_->heap()->SetStackLimits();
437    }
438    ExecutionAccess::Unlock(isolate_);
439  }
440}
441
442
443bool StackGuard::IsGCRequest() {
444  ExecutionAccess access(isolate_);
445  return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0;
446}
447
448
449void StackGuard::RequestGC() {
450  ExecutionAccess access(isolate_);
451  thread_local_.interrupt_flags_ |= GC_REQUEST;
452  if (thread_local_.postpone_interrupts_nesting_ == 0) {
453    thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
454    isolate_->heap()->SetStackLimits();
455  }
456}
457
458
459#ifdef ENABLE_DEBUGGER_SUPPORT
460bool StackGuard::IsDebugBreak() {
461  ExecutionAccess access(isolate_);
462  return thread_local_.interrupt_flags_ & DEBUGBREAK;
463}
464
465
466void StackGuard::DebugBreak() {
467  ExecutionAccess access(isolate_);
468  thread_local_.interrupt_flags_ |= DEBUGBREAK;
469  set_interrupt_limits(access);
470}
471
472
473bool StackGuard::IsDebugCommand() {
474  ExecutionAccess access(isolate_);
475  return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
476}
477
478
479void StackGuard::DebugCommand() {
480  if (FLAG_debugger_auto_break) {
481    ExecutionAccess access(isolate_);
482    thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
483    set_interrupt_limits(access);
484  }
485}
486#endif
487
488void StackGuard::Continue(InterruptFlag after_what) {
489  ExecutionAccess access(isolate_);
490  thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
491  if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
492    reset_limits(access);
493  }
494}
495
496
497char* StackGuard::ArchiveStackGuard(char* to) {
498  ExecutionAccess access(isolate_);
499  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
500  ThreadLocal blank;
501
502  // Set the stack limits using the old thread_local_.
503  // TODO(isolates): This was the old semantics of constructing a ThreadLocal
504  //                 (as the ctor called SetStackLimits, which looked at the
505  //                 current thread_local_ from StackGuard)-- but is this
506  //                 really what was intended?
507  isolate_->heap()->SetStackLimits();
508  thread_local_ = blank;
509
510  return to + sizeof(ThreadLocal);
511}
512
513
514char* StackGuard::RestoreStackGuard(char* from) {
515  ExecutionAccess access(isolate_);
516  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
517  isolate_->heap()->SetStackLimits();
518  return from + sizeof(ThreadLocal);
519}
520
521
522void StackGuard::FreeThreadResources() {
523  Isolate::PerIsolateThreadData* per_thread =
524      isolate_->FindOrAllocatePerThreadDataForThisThread();
525  per_thread->set_stack_limit(thread_local_.real_climit_);
526}
527
528
529void StackGuard::ThreadLocal::Clear() {
530  real_jslimit_ = kIllegalLimit;
531  jslimit_ = kIllegalLimit;
532  real_climit_ = kIllegalLimit;
533  climit_ = kIllegalLimit;
534  nesting_ = 0;
535  postpone_interrupts_nesting_ = 0;
536  interrupt_flags_ = 0;
537}
538
539
540bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
541  bool should_set_stack_limits = false;
542  if (real_climit_ == kIllegalLimit) {
543    // Takes the address of the limit variable in order to find out where
544    // the top of stack is right now.
545    const uintptr_t kLimitSize = FLAG_stack_size * KB;
546    uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
547    ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
548    real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
549    jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
550    real_climit_ = limit;
551    climit_ = limit;
552    should_set_stack_limits = true;
553  }
554  nesting_ = 0;
555  postpone_interrupts_nesting_ = 0;
556  interrupt_flags_ = 0;
557  return should_set_stack_limits;
558}
559
560
561void StackGuard::ClearThread(const ExecutionAccess& lock) {
562  thread_local_.Clear();
563  isolate_->heap()->SetStackLimits();
564}
565
566
567void StackGuard::InitThread(const ExecutionAccess& lock) {
568  if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
569  Isolate::PerIsolateThreadData* per_thread =
570      isolate_->FindOrAllocatePerThreadDataForThisThread();
571  uintptr_t stored_limit = per_thread->stack_limit();
572  // You should hold the ExecutionAccess lock when you call this.
573  if (stored_limit != 0) {
574    SetStackLimit(stored_limit);
575  }
576}
577
578
579// --- C a l l s   t o   n a t i v e s ---
580
581#define RETURN_NATIVE_CALL(name, args, has_pending_exception)           \
582  do {                                                                  \
583    Isolate* isolate = Isolate::Current();                              \
584    Handle<Object> argv[] = args;                                       \
585    ASSERT(has_pending_exception != NULL);                              \
586    return Call(isolate->name##_fun(),                                  \
587                isolate->js_builtins_object(),                          \
588                ARRAY_SIZE(argv), argv,                                 \
589                has_pending_exception);                                 \
590  } while (false)
591
592
593Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
594  // See the similar code in runtime.js:ToBoolean.
595  if (obj->IsBoolean()) return obj;
596  bool result = true;
597  if (obj->IsString()) {
598    result = Handle<String>::cast(obj)->length() != 0;
599  } else if (obj->IsNull() || obj->IsUndefined()) {
600    result = false;
601  } else if (obj->IsNumber()) {
602    double value = obj->Number();
603    result = !((value == 0) || isnan(value));
604  }
605  return Handle<Object>(HEAP->ToBoolean(result));
606}
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  Handle<Object> time_obj = FACTORY->NewNumber(time);
647  RETURN_NATIVE_CALL(create_date, { time_obj }, exc);
648}
649
650
651#undef RETURN_NATIVE_CALL
652
653
654Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
655                                        Handle<String> flags,
656                                        bool* exc) {
657  Handle<JSFunction> function = Handle<JSFunction>(
658      pattern->GetIsolate()->global_context()->regexp_function());
659  Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
660      function, pattern, flags, exc);
661  if (*exc) return Handle<JSRegExp>();
662  return Handle<JSRegExp>::cast(re_obj);
663}
664
665
666Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
667  Isolate* isolate = string->GetIsolate();
668  Factory* factory = isolate->factory();
669
670  int int_index = static_cast<int>(index);
671  if (int_index < 0 || int_index >= string->length()) {
672    return factory->undefined_value();
673  }
674
675  Handle<Object> char_at =
676      GetProperty(isolate->js_builtins_object(),
677                  factory->char_at_symbol());
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->global_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_symbol();
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  StackLimitCheck check(isolate);
830  if (check.HasOverflowed()) {
831    return isolate->heap()->undefined_value();
832  }
833
834  {
835    JavaScriptFrameIterator it(isolate);
836    ASSERT(!it.done());
837    Object* fun = it.frame()->function();
838    if (fun && fun->IsJSFunction()) {
839      // Don't stop in builtin functions.
840      if (JSFunction::cast(fun)->IsBuiltin()) {
841        return isolate->heap()->undefined_value();
842      }
843      GlobalObject* global = JSFunction::cast(fun)->context()->global();
844      // Don't stop in debugger functions.
845      if (isolate->debug()->IsDebugGlobal(global)) {
846        return isolate->heap()->undefined_value();
847      }
848    }
849  }
850
851  // Collect the break state before clearing the flags.
852  bool debug_command_only =
853      isolate->stack_guard()->IsDebugCommand() &&
854      !isolate->stack_guard()->IsDebugBreak();
855
856  // Clear the debug break request flag.
857  isolate->stack_guard()->Continue(DEBUGBREAK);
858
859  ProcessDebugMessages(debug_command_only);
860
861  // Return to continue execution.
862  return isolate->heap()->undefined_value();
863}
864
865void Execution::ProcessDebugMessages(bool debug_command_only) {
866  Isolate* isolate = Isolate::Current();
867  // Clear the debug command request flag.
868  isolate->stack_guard()->Continue(DEBUGCOMMAND);
869
870  StackLimitCheck check(isolate);
871  if (check.HasOverflowed()) {
872    return;
873  }
874
875  HandleScope scope(isolate);
876  // Enter the debugger. Just continue if we fail to enter the debugger.
877  EnterDebugger debugger;
878  if (debugger.FailedToEnter()) {
879    return;
880  }
881
882  // Notify the debug event listeners. Indicate auto continue if the break was
883  // a debug command break.
884  isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(),
885                                    debug_command_only);
886}
887
888
889#endif
890
891MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
892  StackGuard* stack_guard = isolate->stack_guard();
893  if (stack_guard->ShouldPostponeInterrupts()) {
894    return isolate->heap()->undefined_value();
895  }
896
897  if (stack_guard->IsGCRequest()) {
898    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
899                                       "StackGuard GC request");
900    stack_guard->Continue(GC_REQUEST);
901  }
902
903  isolate->counters()->stack_interrupts()->Increment();
904  // If FLAG_count_based_interrupts, every interrupt is a profiler interrupt.
905  if (FLAG_count_based_interrupts ||
906      stack_guard->IsRuntimeProfilerTick()) {
907    isolate->counters()->runtime_profiler_ticks()->Increment();
908    stack_guard->Continue(RUNTIME_PROFILER_TICK);
909    isolate->runtime_profiler()->OptimizeNow();
910  }
911#ifdef ENABLE_DEBUGGER_SUPPORT
912  if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
913    DebugBreakHelper();
914  }
915#endif
916  if (stack_guard->IsPreempted()) RuntimePreempt();
917  if (stack_guard->IsTerminateExecution()) {
918    stack_guard->Continue(TERMINATE);
919    return isolate->TerminateExecution();
920  }
921  if (stack_guard->IsInterrupted()) {
922    stack_guard->Continue(INTERRUPT);
923    return isolate->StackOverflow();
924  }
925  return isolate->heap()->undefined_value();
926}
927
928
929} }  // namespace v8::internal
930