| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include <stdlib.h> | 28 #include <stdlib.h> |
| 29 | 29 |
| 30 #include "v8.h" | 30 #include "v8.h" |
| 31 | 31 |
| 32 #include "api.h" | 32 #include "api.h" |
| 33 #include "bootstrapper.h" | 33 #include "bootstrapper.h" |
| 34 #include "codegen.h" | 34 #include "codegen.h" |
| 35 #include "debug.h" | 35 #include "debug.h" |
| 36 #include "isolate-inl.h" |
| 36 #include "runtime-profiler.h" | 37 #include "runtime-profiler.h" |
| 37 #include "simulator.h" | 38 #include "simulator.h" |
| 38 #include "v8threads.h" | 39 #include "v8threads.h" |
| 39 #include "vm-state-inl.h" | 40 #include "vm-state-inl.h" |
| 40 | 41 |
| 41 namespace v8 { | 42 namespace v8 { |
| 42 namespace internal { | 43 namespace internal { |
| 43 | 44 |
| 44 | 45 |
| 45 StackGuard::StackGuard() | 46 StackGuard::StackGuard() |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 | 82 |
| 82 typedef Object* (*JSEntryFunction)( | 83 typedef Object* (*JSEntryFunction)( |
| 83 byte* entry, | 84 byte* entry, |
| 84 Object* function, | 85 Object* function, |
| 85 Object* receiver, | 86 Object* receiver, |
| 86 int argc, | 87 int argc, |
| 87 Object*** args); | 88 Object*** args); |
| 88 | 89 |
| 89 Handle<Code> code; | 90 Handle<Code> code; |
| 90 if (construct) { | 91 if (construct) { |
| 91 JSConstructEntryStub stub; | 92 code = isolate->factory()->js_construct_entry_code(); |
| 92 code = stub.GetCode(); | |
| 93 } else { | 93 } else { |
| 94 JSEntryStub stub; | 94 code = isolate->factory()->js_entry_code(); |
| 95 code = stub.GetCode(); | |
| 96 } | 95 } |
| 97 | 96 |
| 98 // Convert calls on global objects to be calls on the global | 97 // Convert calls on global objects to be calls on the global |
| 99 // receiver instead to avoid having a 'this' pointer which refers | 98 // receiver instead to avoid having a 'this' pointer which refers |
| 100 // directly to a global object. | 99 // directly to a global object. |
| 101 if (receiver->IsGlobalObject()) { | 100 if (receiver->IsGlobalObject()) { |
| 102 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 101 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
| 103 receiver = Handle<JSObject>(global->global_receiver()); | 102 receiver = Handle<JSObject>(global->global_receiver()); |
| 104 } | 103 } |
| 105 | 104 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 return Handle<Object>(value->ToObjectUnchecked(), isolate); | 143 return Handle<Object>(value->ToObjectUnchecked(), isolate); |
| 145 } | 144 } |
| 146 | 145 |
| 147 | 146 |
| 148 Handle<Object> Execution::Call(Handle<Object> callable, | 147 Handle<Object> Execution::Call(Handle<Object> callable, |
| 149 Handle<Object> receiver, | 148 Handle<Object> receiver, |
| 150 int argc, | 149 int argc, |
| 151 Object*** args, | 150 Object*** args, |
| 152 bool* pending_exception, | 151 bool* pending_exception, |
| 153 bool convert_receiver) { | 152 bool convert_receiver) { |
| 153 *pending_exception = false; |
| 154 |
| 154 if (!callable->IsJSFunction()) { | 155 if (!callable->IsJSFunction()) { |
| 155 callable = TryGetFunctionDelegate(callable, pending_exception); | 156 callable = TryGetFunctionDelegate(callable, pending_exception); |
| 156 if (*pending_exception) return callable; | 157 if (*pending_exception) return callable; |
| 157 } | 158 } |
| 158 Handle<JSFunction> func = Handle<JSFunction>::cast(callable); | 159 Handle<JSFunction> func = Handle<JSFunction>::cast(callable); |
| 159 | 160 |
| 160 // In non-strict mode, convert receiver. | 161 // In non-strict mode, convert receiver. |
| 161 if (convert_receiver && !receiver->IsJSReceiver() && | 162 if (convert_receiver && !receiver->IsJSReceiver() && |
| 162 !func->shared()->native() && !func->shared()->strict_mode()) { | 163 !func->shared()->native() && !func->shared()->strict_mode()) { |
| 163 if (receiver->IsUndefined() || receiver->IsNull()) { | 164 if (receiver->IsUndefined() || receiver->IsNull()) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 188 int argc, | 189 int argc, |
| 189 Object*** args, | 190 Object*** args, |
| 190 bool* caught_exception) { | 191 bool* caught_exception) { |
| 191 // Enter a try-block while executing the JavaScript code. To avoid | 192 // Enter a try-block while executing the JavaScript code. To avoid |
| 192 // duplicate error printing it must be non-verbose. Also, to avoid | 193 // duplicate error printing it must be non-verbose. Also, to avoid |
| 193 // creating message objects during stack overflow we shouldn't | 194 // creating message objects during stack overflow we shouldn't |
| 194 // capture messages. | 195 // capture messages. |
| 195 v8::TryCatch catcher; | 196 v8::TryCatch catcher; |
| 196 catcher.SetVerbose(false); | 197 catcher.SetVerbose(false); |
| 197 catcher.SetCaptureMessage(false); | 198 catcher.SetCaptureMessage(false); |
| 199 *caught_exception = false; |
| 198 | 200 |
| 199 Handle<Object> result = Invoke(false, func, receiver, argc, args, | 201 Handle<Object> result = Invoke(false, func, receiver, argc, args, |
| 200 caught_exception); | 202 caught_exception); |
| 201 | 203 |
| 202 if (*caught_exception) { | 204 if (*caught_exception) { |
| 203 ASSERT(catcher.HasCaught()); | 205 ASSERT(catcher.HasCaught()); |
| 204 Isolate* isolate = Isolate::Current(); | 206 Isolate* isolate = Isolate::Current(); |
| 205 ASSERT(isolate->has_pending_exception()); | 207 ASSERT(isolate->has_pending_exception()); |
| 206 ASSERT(isolate->external_caught_exception()); | 208 ASSERT(isolate->external_caught_exception()); |
| 207 if (isolate->pending_exception() == | 209 if (isolate->pending_exception() == |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 | 372 |
| 371 | 373 |
| 372 void StackGuard::DisableInterrupts() { | 374 void StackGuard::DisableInterrupts() { |
| 373 ExecutionAccess access(isolate_); | 375 ExecutionAccess access(isolate_); |
| 374 reset_limits(access); | 376 reset_limits(access); |
| 375 } | 377 } |
| 376 | 378 |
| 377 | 379 |
| 378 bool StackGuard::IsInterrupted() { | 380 bool StackGuard::IsInterrupted() { |
| 379 ExecutionAccess access(isolate_); | 381 ExecutionAccess access(isolate_); |
| 380 return thread_local_.interrupt_flags_ & INTERRUPT; | 382 return (thread_local_.interrupt_flags_ & INTERRUPT) != 0; |
| 381 } | 383 } |
| 382 | 384 |
| 383 | 385 |
| 384 void StackGuard::Interrupt() { | 386 void StackGuard::Interrupt() { |
| 385 ExecutionAccess access(isolate_); | 387 ExecutionAccess access(isolate_); |
| 386 thread_local_.interrupt_flags_ |= INTERRUPT; | 388 thread_local_.interrupt_flags_ |= INTERRUPT; |
| 387 set_interrupt_limits(access); | 389 set_interrupt_limits(access); |
| 388 } | 390 } |
| 389 | 391 |
| 390 | 392 |
| 391 bool StackGuard::IsPreempted() { | 393 bool StackGuard::IsPreempted() { |
| 392 ExecutionAccess access(isolate_); | 394 ExecutionAccess access(isolate_); |
| 393 return thread_local_.interrupt_flags_ & PREEMPT; | 395 return thread_local_.interrupt_flags_ & PREEMPT; |
| 394 } | 396 } |
| 395 | 397 |
| 396 | 398 |
| 397 void StackGuard::Preempt() { | 399 void StackGuard::Preempt() { |
| 398 ExecutionAccess access(isolate_); | 400 ExecutionAccess access(isolate_); |
| 399 thread_local_.interrupt_flags_ |= PREEMPT; | 401 thread_local_.interrupt_flags_ |= PREEMPT; |
| 400 set_interrupt_limits(access); | 402 set_interrupt_limits(access); |
| 401 } | 403 } |
| 402 | 404 |
| 403 | 405 |
| 404 bool StackGuard::IsTerminateExecution() { | 406 bool StackGuard::IsTerminateExecution() { |
| 405 ExecutionAccess access(isolate_); | 407 ExecutionAccess access(isolate_); |
| 406 return thread_local_.interrupt_flags_ & TERMINATE; | 408 return (thread_local_.interrupt_flags_ & TERMINATE) != 0; |
| 407 } | 409 } |
| 408 | 410 |
| 409 | 411 |
| 410 void StackGuard::TerminateExecution() { | 412 void StackGuard::TerminateExecution() { |
| 411 ExecutionAccess access(isolate_); | 413 ExecutionAccess access(isolate_); |
| 412 thread_local_.interrupt_flags_ |= TERMINATE; | 414 thread_local_.interrupt_flags_ |= TERMINATE; |
| 413 set_interrupt_limits(access); | 415 set_interrupt_limits(access); |
| 414 } | 416 } |
| 415 | 417 |
| 416 | 418 |
| 417 bool StackGuard::IsRuntimeProfilerTick() { | 419 bool StackGuard::IsRuntimeProfilerTick() { |
| 418 ExecutionAccess access(isolate_); | 420 ExecutionAccess access(isolate_); |
| 419 return thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK; | 421 return (thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK) != 0; |
| 420 } | 422 } |
| 421 | 423 |
| 422 | 424 |
| 423 void StackGuard::RequestRuntimeProfilerTick() { | 425 void StackGuard::RequestRuntimeProfilerTick() { |
| 424 // Ignore calls if we're not optimizing or if we can't get the lock. | 426 // Ignore calls if we're not optimizing or if we can't get the lock. |
| 425 if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) { | 427 if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) { |
| 426 thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK; | 428 thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK; |
| 427 if (thread_local_.postpone_interrupts_nesting_ == 0) { | 429 if (thread_local_.postpone_interrupts_nesting_ == 0) { |
| 428 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; | 430 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; |
| 429 isolate_->heap()->SetStackLimits(); | 431 isolate_->heap()->SetStackLimits(); |
| 430 } | 432 } |
| 431 ExecutionAccess::Unlock(isolate_); | 433 ExecutionAccess::Unlock(isolate_); |
| 432 } | 434 } |
| 433 } | 435 } |
| 434 | 436 |
| 435 | 437 |
| 438 bool StackGuard::IsGCRequest() { |
| 439 ExecutionAccess access(isolate_); |
| 440 return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0; |
| 441 } |
| 442 |
| 443 |
| 444 void StackGuard::RequestGC() { |
| 445 ExecutionAccess access(isolate_); |
| 446 thread_local_.interrupt_flags_ |= GC_REQUEST; |
| 447 if (thread_local_.postpone_interrupts_nesting_ == 0) { |
| 448 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; |
| 449 isolate_->heap()->SetStackLimits(); |
| 450 } |
| 451 } |
| 452 |
| 453 |
| 436 #ifdef ENABLE_DEBUGGER_SUPPORT | 454 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 437 bool StackGuard::IsDebugBreak() { | 455 bool StackGuard::IsDebugBreak() { |
| 438 ExecutionAccess access(isolate_); | 456 ExecutionAccess access(isolate_); |
| 439 return thread_local_.interrupt_flags_ & DEBUGBREAK; | 457 return thread_local_.interrupt_flags_ & DEBUGBREAK; |
| 440 } | 458 } |
| 441 | 459 |
| 442 | 460 |
| 443 void StackGuard::DebugBreak() { | 461 void StackGuard::DebugBreak() { |
| 444 ExecutionAccess access(isolate_); | 462 ExecutionAccess access(isolate_); |
| 445 thread_local_.interrupt_flags_ |= DEBUGBREAK; | 463 thread_local_.interrupt_flags_ |= DEBUGBREAK; |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv, | 751 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv, |
| 734 Handle<JSFunction> fun, | 752 Handle<JSFunction> fun, |
| 735 Handle<Object> pos, | 753 Handle<Object> pos, |
| 736 Handle<Object> is_global) { | 754 Handle<Object> is_global) { |
| 737 Isolate* isolate = fun->GetIsolate(); | 755 Isolate* isolate = fun->GetIsolate(); |
| 738 const int argc = 4; | 756 const int argc = 4; |
| 739 Object** args[argc] = { recv.location(), | 757 Object** args[argc] = { recv.location(), |
| 740 Handle<Object>::cast(fun).location(), | 758 Handle<Object>::cast(fun).location(), |
| 741 pos.location(), | 759 pos.location(), |
| 742 is_global.location() }; | 760 is_global.location() }; |
| 743 bool caught_exception = false; | 761 bool caught_exception; |
| 744 Handle<Object> result = | 762 Handle<Object> result = |
| 745 TryCall(isolate->get_stack_trace_line_fun(), | 763 TryCall(isolate->get_stack_trace_line_fun(), |
| 746 isolate->js_builtins_object(), argc, args, | 764 isolate->js_builtins_object(), argc, args, |
| 747 &caught_exception); | 765 &caught_exception); |
| 748 if (caught_exception || !result->IsString()) { | 766 if (caught_exception || !result->IsString()) { |
| 749 return isolate->factory()->empty_symbol(); | 767 return isolate->factory()->empty_symbol(); |
| 750 } | 768 } |
| 751 | 769 |
| 752 return Handle<String>::cast(result); | 770 return Handle<String>::cast(result); |
| 753 } | 771 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(), | 863 isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(), |
| 846 debug_command_only); | 864 debug_command_only); |
| 847 } | 865 } |
| 848 | 866 |
| 849 | 867 |
| 850 #endif | 868 #endif |
| 851 | 869 |
| 852 MaybeObject* Execution::HandleStackGuardInterrupt() { | 870 MaybeObject* Execution::HandleStackGuardInterrupt() { |
| 853 Isolate* isolate = Isolate::Current(); | 871 Isolate* isolate = Isolate::Current(); |
| 854 StackGuard* stack_guard = isolate->stack_guard(); | 872 StackGuard* stack_guard = isolate->stack_guard(); |
| 873 |
| 874 if (stack_guard->IsGCRequest()) { |
| 875 isolate->heap()->CollectAllGarbage(false); |
| 876 stack_guard->Continue(GC_REQUEST); |
| 877 } |
| 878 |
| 855 isolate->counters()->stack_interrupts()->Increment(); | 879 isolate->counters()->stack_interrupts()->Increment(); |
| 856 if (stack_guard->IsRuntimeProfilerTick()) { | 880 if (stack_guard->IsRuntimeProfilerTick()) { |
| 857 isolate->counters()->runtime_profiler_ticks()->Increment(); | 881 isolate->counters()->runtime_profiler_ticks()->Increment(); |
| 858 stack_guard->Continue(RUNTIME_PROFILER_TICK); | 882 stack_guard->Continue(RUNTIME_PROFILER_TICK); |
| 859 isolate->runtime_profiler()->OptimizeNow(); | 883 isolate->runtime_profiler()->OptimizeNow(); |
| 860 } | 884 } |
| 861 #ifdef ENABLE_DEBUGGER_SUPPORT | 885 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 862 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) { | 886 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) { |
| 863 DebugBreakHelper(); | 887 DebugBreakHelper(); |
| 864 } | 888 } |
| 865 #endif | 889 #endif |
| 866 if (stack_guard->IsPreempted()) RuntimePreempt(); | 890 if (stack_guard->IsPreempted()) RuntimePreempt(); |
| 867 if (stack_guard->IsTerminateExecution()) { | 891 if (stack_guard->IsTerminateExecution()) { |
| 868 stack_guard->Continue(TERMINATE); | 892 stack_guard->Continue(TERMINATE); |
| 869 return isolate->TerminateExecution(); | 893 return isolate->TerminateExecution(); |
| 870 } | 894 } |
| 871 if (stack_guard->IsInterrupted()) { | 895 if (stack_guard->IsInterrupted()) { |
| 872 stack_guard->Continue(INTERRUPT); | 896 stack_guard->Continue(INTERRUPT); |
| 873 return isolate->StackOverflow(); | 897 return isolate->StackOverflow(); |
| 874 } | 898 } |
| 875 return isolate->heap()->undefined_value(); | 899 return isolate->heap()->undefined_value(); |
| 876 } | 900 } |
| 877 | 901 |
| 878 } } // namespace v8::internal | 902 } } // namespace v8::internal |
| OLD | NEW |