46 StackGuard::StackGuard()
51 void StackGuard::set_interrupt_limits(
const ExecutionAccess& lock) {
54 if (should_postpone_interrupts(lock))
return;
55 thread_local_.jslimit_ = kInterruptLimit;
56 thread_local_.climit_ = kInterruptLimit;
61 void StackGuard::reset_limits(
const ExecutionAccess& lock) {
63 thread_local_.jslimit_ = thread_local_.real_jslimit_;
64 thread_local_.climit_ = thread_local_.real_climit_;
69 static Handle<Object> Invoke(
bool is_construct,
70 Handle<JSFunction>
function,
71 Handle<Object> receiver,
73 Handle<Object> args[],
74 bool* has_pending_exception) {
75 Isolate* isolate =
function->GetIsolate();
78 VMState state(isolate, JS);
83 typedef Object* (*JSEntryFunction)(
byte* entry,
89 Handle<Code> code = is_construct
90 ? isolate->factory()->js_construct_entry_code()
91 : isolate->factory()->js_entry_code();
96 if (receiver->IsGlobalObject()) {
98 receiver = Handle<JSObject>(global->global_receiver());
103 ASSERT(function->context()->global()->IsGlobalObject());
108 SaveContext save(isolate);
109 NoHandleAllocation na;
110 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
113 byte* function_entry =
function->code()->entry();
114 JSFunction* func = *
function;
115 Object* recv = *receiver;
116 Object*** argv =
reinterpret_cast<Object***
>(args);
126 *has_pending_exception = value->IsException();
127 ASSERT(*has_pending_exception == Isolate::Current()->has_pending_exception());
128 if (*has_pending_exception) {
129 isolate->ReportPendingMessages();
131 if (!isolate->ignore_out_of_memory()) {
135 return Handle<Object>();
137 isolate->clear_pending_message();
140 return Handle<Object>(value->ToObjectUnchecked(), isolate);
148 bool* pending_exception,
149 bool convert_receiver) {
150 *pending_exception =
false;
152 if (!callable->IsJSFunction()) {
154 if (*pending_exception)
return callable;
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();
166 if (!global->IsJSBuiltinsObject()) receiver =
Handle<Object>(global);
168 receiver =
ToObject(receiver, pending_exception);
170 if (*pending_exception)
return callable;
173 return Invoke(
false, func, receiver, argc, argv, pending_exception);
180 bool* pending_exception) {
181 return Invoke(
true, func, Isolate::Current()->global(), argc, argv,
190 bool* caught_exception) {
198 *caught_exception =
false;
203 if (*caught_exception) {
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();
214 isolate->OptionalRescheduleException(
true);
217 ASSERT(!Isolate::Current()->has_pending_exception());
218 ASSERT(!Isolate::Current()->external_caught_exception());
224 ASSERT(!object->IsJSFunction());
225 Isolate* isolate = Isolate::Current();
226 Factory* factory = isolate->factory();
232 Object* fun = *object;
233 while (fun->IsJSFunctionProxy()) {
240 if (fun->IsHeapObject() &&
243 isolate->global_context()->call_as_function_delegate());
246 return factory->undefined_value();
251 bool* has_pending_exception) {
252 ASSERT(!object->IsJSFunction());
253 Isolate* isolate = Isolate::Current();
256 Object* fun = *object;
257 while (fun->IsJSFunctionProxy()) {
264 if (fun->IsHeapObject() &&
267 isolate->global_context()->call_as_function_delegate());
273 "called_non_callable", i::HandleVector<i::Object>(&
object, 1));
274 isolate->Throw(*error_obj);
275 *has_pending_exception =
true;
277 return isolate->factory()->undefined_value();
282 ASSERT(!object->IsJSFunction());
283 Isolate* isolate = Isolate::Current();
289 Object* fun = *object;
290 while (fun->IsJSFunctionProxy()) {
297 if (fun->IsHeapObject() &&
300 isolate->global_context()->call_as_constructor_delegate());
303 return isolate->factory()->undefined_value();
309 bool* has_pending_exception) {
310 ASSERT(!object->IsJSFunction());
311 Isolate* isolate = Isolate::Current();
317 Object* fun = *object;
318 while (fun->IsJSFunctionProxy()) {
325 if (fun->IsHeapObject() &&
328 isolate->global_context()->call_as_constructor_delegate());
334 "called_non_callable", i::HandleVector<i::Object>(&
object, 1));
335 isolate->Throw(*error_obj);
336 *has_pending_exception =
true;
338 return isolate->factory()->undefined_value();
343 ExecutionAccess access(isolate_);
344 return (thread_local_.jslimit_ != kInterruptLimit &&
345 thread_local_.climit_ != kInterruptLimit);
349 void StackGuard::EnableInterrupts() {
350 ExecutionAccess access(isolate_);
351 if (has_pending_interrupts(access)) {
352 set_interrupt_limits(access);
358 ExecutionAccess access(isolate_);
362 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
363 thread_local_.jslimit_ =
jslimit;
365 if (thread_local_.climit_ == thread_local_.real_climit_) {
366 thread_local_.climit_ = limit;
368 thread_local_.real_climit_ = limit;
369 thread_local_.real_jslimit_ =
jslimit;
373 void StackGuard::DisableInterrupts() {
374 ExecutionAccess access(isolate_);
375 reset_limits(access);
380 ExecutionAccess access(isolate_);
381 return should_postpone_interrupts(access);
386 ExecutionAccess access(isolate_);
387 return (thread_local_.interrupt_flags_ &
INTERRUPT) != 0;
392 ExecutionAccess access(isolate_);
393 thread_local_.interrupt_flags_ |=
INTERRUPT;
394 set_interrupt_limits(access);
399 ExecutionAccess access(isolate_);
400 return thread_local_.interrupt_flags_ &
PREEMPT;
405 ExecutionAccess access(isolate_);
406 thread_local_.interrupt_flags_ |=
PREEMPT;
407 set_interrupt_limits(access);
412 ExecutionAccess access(isolate_);
413 return (thread_local_.interrupt_flags_ &
TERMINATE) != 0;
418 ExecutionAccess access(isolate_);
419 thread_local_.interrupt_flags_ |=
TERMINATE;
420 set_interrupt_limits(access);
425 ExecutionAccess access(isolate_);
432 if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) {
434 if (thread_local_.postpone_interrupts_nesting_ == 0) {
435 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
438 ExecutionAccess::Unlock(isolate_);
444 ExecutionAccess access(isolate_);
445 return (thread_local_.interrupt_flags_ &
GC_REQUEST) != 0;
450 ExecutionAccess access(isolate_);
452 if (thread_local_.postpone_interrupts_nesting_ == 0) {
453 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
459 #ifdef ENABLE_DEBUGGER_SUPPORT
460 bool StackGuard::IsDebugBreak() {
461 ExecutionAccess access(isolate_);
462 return thread_local_.interrupt_flags_ &
DEBUGBREAK;
466 void StackGuard::DebugBreak() {
467 ExecutionAccess access(isolate_);
469 set_interrupt_limits(access);
473 bool StackGuard::IsDebugCommand() {
474 ExecutionAccess access(isolate_);
479 void StackGuard::DebugCommand() {
480 if (FLAG_debugger_auto_break) {
481 ExecutionAccess access(isolate_);
483 set_interrupt_limits(access);
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);
498 ExecutionAccess access(isolate_);
499 memcpy(to, reinterpret_cast<char*>(&thread_local_),
sizeof(ThreadLocal));
508 thread_local_ = blank;
510 return to +
sizeof(ThreadLocal);
515 ExecutionAccess access(isolate_);
516 memcpy(reinterpret_cast<char*>(&thread_local_), from,
sizeof(ThreadLocal));
518 return from +
sizeof(ThreadLocal);
524 isolate_->FindOrAllocatePerThreadDataForThisThread();
529 void StackGuard::ThreadLocal::Clear() {
530 real_jslimit_ = kIllegalLimit;
531 jslimit_ = kIllegalLimit;
532 real_climit_ = kIllegalLimit;
533 climit_ = kIllegalLimit;
535 postpone_interrupts_nesting_ = 0;
536 interrupt_flags_ = 0;
540 bool StackGuard::ThreadLocal::Initialize(
Isolate* isolate) {
541 bool should_set_stack_limits =
false;
542 if (real_climit_ == kIllegalLimit) {
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);
550 real_climit_ = limit;
552 should_set_stack_limits =
true;
555 postpone_interrupts_nesting_ = 0;
556 interrupt_flags_ = 0;
557 return should_set_stack_limits;
562 thread_local_.Clear();
570 isolate_->FindOrAllocatePerThreadDataForThisThread();
571 uintptr_t stored_limit = per_thread->
stack_limit();
573 if (stored_limit != 0) {
581 #define RETURN_NATIVE_CALL(name, args, has_pending_exception) \
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); \
595 if (obj->IsBoolean())
return obj;
597 if (obj->IsString()) {
599 }
else if (obj->IsNull() || obj->IsUndefined()) {
601 }
else if (obj->IsNumber()) {
602 double value = obj->Number();
603 result = !((value == 0) ||
isnan(value));
625 if (obj->IsSpecObject())
return obj;
651 #undef RETURN_NATIVE_CALL
658 pattern->GetIsolate()->global_context()->regexp_function());
660 function, pattern, flags, exc);
667 Isolate* isolate =
string->GetIsolate();
670 int int_index =
static_cast<int>(index);
671 if (int_index < 0 || int_index >= string->length()) {
672 return factory->undefined_value();
677 factory->char_at_symbol());
678 if (!char_at->IsJSFunction()) {
679 return factory->undefined_value();
682 bool caught_exception;
690 if (caught_exception) {
691 return factory->undefined_value();
700 Isolate* isolate = data->GetIsolate();
702 int serial_number =
Smi::cast(data->serial_number())->value();
705 GetElementNoExceptionThrown(serial_number);
721 Isolate* isolate = data->GetIsolate();
722 if (data->property_list()->IsUndefined() &&
723 !data->constructor()->IsUndefined()) {
725 Object* result =
NULL;
755 Isolate* isolate = Isolate::Current();
769 Isolate* isolate = fun->GetIsolate();
771 bool caught_exception;
777 if (caught_exception || !result->IsString()) {
778 return isolate->
factory()->empty_symbol();
785 static Object* RuntimePreempt() {
786 Isolate* isolate = Isolate::Current();
793 #ifdef ENABLE_DEBUGGER_SUPPORT
794 if (isolate->debug()->InDebugger()) {
797 isolate->debug()->PreemptionWhileInDebugger();
800 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
806 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
811 return isolate->
heap()->undefined_value();
815 #ifdef ENABLE_DEBUGGER_SUPPORT
816 Object* Execution::DebugBreakHelper() {
817 Isolate* isolate = Isolate::Current();
820 if (isolate->debug()->disable_break()) {
821 return isolate->heap()->undefined_value();
825 if (isolate->bootstrapper()->IsActive()) {
826 return isolate->heap()->undefined_value();
829 StackLimitCheck
check(isolate);
830 if (
check.HasOverflowed()) {
831 return isolate->heap()->undefined_value();
837 Object* fun = it.frame()->function();
838 if (fun && fun->IsJSFunction()) {
841 return isolate->heap()->undefined_value();
845 if (isolate->debug()->IsDebugGlobal(global)) {
846 return isolate->heap()->undefined_value();
852 bool debug_command_only =
853 isolate->stack_guard()->IsDebugCommand() &&
854 !isolate->stack_guard()->IsDebugBreak();
859 ProcessDebugMessages(debug_command_only);
862 return isolate->heap()->undefined_value();
865 void Execution::ProcessDebugMessages(
bool debug_command_only) {
866 Isolate* isolate = Isolate::Current();
870 StackLimitCheck
check(isolate);
871 if (
check.HasOverflowed()) {
875 HandleScope scope(isolate);
877 EnterDebugger debugger;
878 if (debugger.FailedToEnter()) {
884 isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(),
894 return isolate->
heap()->undefined_value();
899 "StackGuard GC request");
903 isolate->
counters()->stack_interrupts()->Increment();
905 if (FLAG_count_based_interrupts ||
907 isolate->
counters()->runtime_profiler_ticks()->Increment();
911 #ifdef ENABLE_DEBUGGER_SUPPORT
912 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
925 return isolate->
heap()->undefined_value();
static Handle< Object > New(Handle< JSFunction > func, int argc, Handle< Object > argv[], bool *pending_exception)
Failure * StackOverflow()
static Handle< Object > TryCall(Handle< JSFunction > func, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *caught_exception)
static Handle< Object > ToUint32(Handle< Object > obj, bool *exc)
Local< Value > Exception() const
bool IsRuntimeProfilerTick()
void SetCaptureMessage(bool value)
void CollectAllGarbage(int flags, const char *gc_reason=NULL)
static HeapObject * cast(Object *obj)
static Handle< T > cast(Handle< S > that)
static Failure * OutOfMemoryException()
static Handle< Object > CreateRegExpLiteral(Handle< JSFunction > constructor, Handle< String > pattern, Handle< String > flags, bool *has_pending_exception)
static Handle< Object > ToInteger(Handle< Object > obj, bool *exc)
static Handle< Object > GetConstructorDelegate(Handle< Object > object)
static Handle< Object > ToObject(Handle< Object > obj, bool *exc)
static Handle< Object > ToInt32(Handle< Object > obj, bool *exc)
#define ASSERT(condition)
static void ConfigureInstance(Handle< Object > instance, Handle< Object > data, bool *exc)
kPropertyAccessorsOffset kNamedPropertyHandlerOffset instance_template
static Handle< Object > ToDetailString(Handle< Object > obj, bool *exc)
void SetVerbose(bool value)
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
static Smi * cast(Object *object)
StackGuard * stack_guard()
Handle< Context > global_context()
bool has_instance_call_handler()
static JSFunctionProxy * cast(Object *obj)
void RequestRuntimeProfilerTick()
static Handle< Object > CharAt(Handle< String > str, uint32_t index)
static Handle< Object > ToBoolean(Handle< Object > obj)
char * RestoreStackGuard(char *from)
void ClearThread(const ExecutionAccess &lock)
RuntimeProfiler * runtime_profiler()
static void PreemptionReceived()
char * ArchiveStackGuard(char *to)
static MUST_USE_RESULT MaybeObject * HandleStackGuardInterrupt(Isolate *isolate)
bool IsTerminateExecution()
static const int kNoGCFlags
void TerminateExecution()
static uintptr_t JsLimitFromCLimit(v8::internal::Isolate *isolate, uintptr_t c_limit)
static FunctionTemplateInfo * cast(Object *obj)
static Handle< JSRegExp > NewJSRegExp(Handle< String > pattern, Handle< String > flags, bool *exc)
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4)
static Handle< Object > NewDate(double time, bool *exc)
Handle< JSBuiltinsObject > js_builtins_object()
static Handle< Object > Call(Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Handle< Object > NewNumberFromInt(int32_t value, PretenureFlag pretenure=NOT_TENURED)
static Handle< JSFunction > InstantiateFunction(Handle< FunctionTemplateInfo > data, bool *exc)
bool ShouldPostponeInterrupts()
void Continue(InterruptFlag after_what)
JavaScriptFrameIteratorTemp< StackFrameIterator > JavaScriptFrameIterator
static Handle< Object > GetFunctionDelegate(Handle< Object > object)
void set_stack_limit(uintptr_t value)
static Handle< T > null()
#define RETURN_NATIVE_CALL(name, args, has_pending_exception)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
static Handle< Object > ToNumber(Handle< Object > obj, bool *exc)
static Handle< JSObject > InstantiateObject(Handle< ObjectTemplateInfo > data, bool *exc)
Failure * TerminateExecution()
static Handle< String > GetStackTraceLine(Handle< Object > recv, Handle< JSFunction > fun, Handle< Object > pos, Handle< Object > is_global)
static Handle< Object > ToString(Handle< Object > obj, bool *exc)
void FreeThreadResources()
static Handle< Object > TryGetConstructorDelegate(Handle< Object > object, bool *has_pending_exception)
void SetStackLimit(uintptr_t limit)
uintptr_t stack_limit() const
void check(i::Vector< const char > string)
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
static Handle< Object > TryGetFunctionDelegate(Handle< Object > object, bool *has_pending_exception)
static JSObject * cast(Object *obj)
void InitThread(const ExecutionAccess &lock)
static v8::internal::Handle< v8::internal::TemplateInfo > OpenHandle(const Template *that)
static JSFunction * cast(Object *obj)