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 |