| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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-inl.h" | 34 #include "codegen-inl.h" |
| 35 #include "debug.h" | 35 #include "debug.h" |
| 36 #include "runtime-profiler.h" |
| 36 #include "simulator.h" | 37 #include "simulator.h" |
| 37 #include "v8threads.h" | 38 #include "v8threads.h" |
| 39 #include "vm-state-inl.h" |
| 38 | 40 |
| 39 namespace v8 { | 41 namespace v8 { |
| 40 namespace internal { | 42 namespace internal { |
| 41 | 43 |
| 42 | 44 |
| 43 StackGuard::StackGuard() | 45 StackGuard::StackGuard() |
| 44 : isolate_(NULL) { | 46 : isolate_(NULL) { |
| 45 } | 47 } |
| 46 | 48 |
| 47 | 49 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 HeapObject::cast(*object)->map()->has_instance_call_handler()) { | 239 HeapObject::cast(*object)->map()->has_instance_call_handler()) { |
| 238 return Handle<JSFunction>( | 240 return Handle<JSFunction>( |
| 239 Isolate::Current()->global_context()->call_as_constructor_delegate()); | 241 Isolate::Current()->global_context()->call_as_constructor_delegate()); |
| 240 } | 242 } |
| 241 | 243 |
| 242 return FACTORY->undefined_value(); | 244 return FACTORY->undefined_value(); |
| 243 } | 245 } |
| 244 | 246 |
| 245 | 247 |
| 246 bool StackGuard::IsStackOverflow() { | 248 bool StackGuard::IsStackOverflow() { |
| 247 ExecutionAccess access; | 249 ExecutionAccess access(isolate_); |
| 248 return (thread_local_.jslimit_ != kInterruptLimit && | 250 return (thread_local_.jslimit_ != kInterruptLimit && |
| 249 thread_local_.climit_ != kInterruptLimit); | 251 thread_local_.climit_ != kInterruptLimit); |
| 250 } | 252 } |
| 251 | 253 |
| 252 | 254 |
| 253 void StackGuard::EnableInterrupts() { | 255 void StackGuard::EnableInterrupts() { |
| 254 ExecutionAccess access; | 256 ExecutionAccess access(isolate_); |
| 255 if (has_pending_interrupts(access)) { | 257 if (has_pending_interrupts(access)) { |
| 256 set_interrupt_limits(access); | 258 set_interrupt_limits(access); |
| 257 } | 259 } |
| 258 } | 260 } |
| 259 | 261 |
| 260 | 262 |
| 261 void StackGuard::SetStackLimit(uintptr_t limit) { | 263 void StackGuard::SetStackLimit(uintptr_t limit) { |
| 262 ExecutionAccess access; | 264 ExecutionAccess access(isolate_); |
| 263 // If the current limits are special (eg due to a pending interrupt) then | 265 // If the current limits are special (eg due to a pending interrupt) then |
| 264 // leave them alone. | 266 // leave them alone. |
| 265 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(limit); | 267 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(limit); |
| 266 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) { | 268 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) { |
| 267 thread_local_.jslimit_ = jslimit; | 269 thread_local_.jslimit_ = jslimit; |
| 268 } | 270 } |
| 269 if (thread_local_.climit_ == thread_local_.real_climit_) { | 271 if (thread_local_.climit_ == thread_local_.real_climit_) { |
| 270 thread_local_.climit_ = limit; | 272 thread_local_.climit_ = limit; |
| 271 } | 273 } |
| 272 thread_local_.real_climit_ = limit; | 274 thread_local_.real_climit_ = limit; |
| 273 thread_local_.real_jslimit_ = jslimit; | 275 thread_local_.real_jslimit_ = jslimit; |
| 274 } | 276 } |
| 275 | 277 |
| 276 | 278 |
| 277 void StackGuard::DisableInterrupts() { | 279 void StackGuard::DisableInterrupts() { |
| 278 ExecutionAccess access; | 280 ExecutionAccess access(isolate_); |
| 279 reset_limits(access); | 281 reset_limits(access); |
| 280 } | 282 } |
| 281 | 283 |
| 282 | 284 |
| 283 bool StackGuard::IsInterrupted() { | 285 bool StackGuard::IsInterrupted() { |
| 284 ExecutionAccess access; | 286 ExecutionAccess access(isolate_); |
| 285 return thread_local_.interrupt_flags_ & INTERRUPT; | 287 return thread_local_.interrupt_flags_ & INTERRUPT; |
| 286 } | 288 } |
| 287 | 289 |
| 288 | 290 |
| 289 void StackGuard::Interrupt() { | 291 void StackGuard::Interrupt() { |
| 290 ExecutionAccess access; | 292 ExecutionAccess access(isolate_); |
| 291 thread_local_.interrupt_flags_ |= INTERRUPT; | 293 thread_local_.interrupt_flags_ |= INTERRUPT; |
| 292 set_interrupt_limits(access); | 294 set_interrupt_limits(access); |
| 293 } | 295 } |
| 294 | 296 |
| 295 | 297 |
| 296 bool StackGuard::IsPreempted() { | 298 bool StackGuard::IsPreempted() { |
| 297 ExecutionAccess access; | 299 ExecutionAccess access(isolate_); |
| 298 return thread_local_.interrupt_flags_ & PREEMPT; | 300 return thread_local_.interrupt_flags_ & PREEMPT; |
| 299 } | 301 } |
| 300 | 302 |
| 301 | 303 |
| 302 void StackGuard::Preempt() { | 304 void StackGuard::Preempt() { |
| 303 ExecutionAccess access; | 305 ExecutionAccess access(isolate_); |
| 304 thread_local_.interrupt_flags_ |= PREEMPT; | 306 thread_local_.interrupt_flags_ |= PREEMPT; |
| 305 set_interrupt_limits(access); | 307 set_interrupt_limits(access); |
| 306 } | 308 } |
| 307 | 309 |
| 308 | 310 |
| 309 bool StackGuard::IsTerminateExecution() { | 311 bool StackGuard::IsTerminateExecution() { |
| 310 ExecutionAccess access; | 312 ExecutionAccess access(isolate_); |
| 311 return thread_local_.interrupt_flags_ & TERMINATE; | 313 return thread_local_.interrupt_flags_ & TERMINATE; |
| 312 } | 314 } |
| 313 | 315 |
| 314 | 316 |
| 315 void StackGuard::TerminateExecution() { | 317 void StackGuard::TerminateExecution() { |
| 316 ExecutionAccess access; | 318 ExecutionAccess access(isolate_); |
| 317 thread_local_.interrupt_flags_ |= TERMINATE; | 319 thread_local_.interrupt_flags_ |= TERMINATE; |
| 318 set_interrupt_limits(access); | 320 set_interrupt_limits(access); |
| 319 } | 321 } |
| 320 | 322 |
| 321 | 323 |
| 324 bool StackGuard::IsRuntimeProfilerTick() { |
| 325 ExecutionAccess access(isolate_); |
| 326 return thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK; |
| 327 } |
| 328 |
| 329 |
| 330 void StackGuard::RequestRuntimeProfilerTick() { |
| 331 // Ignore calls if we're not optimizing or if we can't get the lock. |
| 332 if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) { |
| 333 thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK; |
| 334 if (thread_local_.postpone_interrupts_nesting_ == 0) { |
| 335 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; |
| 336 isolate_->heap()->SetStackLimits(); |
| 337 } |
| 338 ExecutionAccess::Unlock(isolate_); |
| 339 } |
| 340 } |
| 341 |
| 342 |
| 322 #ifdef ENABLE_DEBUGGER_SUPPORT | 343 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 323 bool StackGuard::IsDebugBreak() { | 344 bool StackGuard::IsDebugBreak() { |
| 324 ExecutionAccess access; | 345 ExecutionAccess access(isolate_); |
| 325 return thread_local_.interrupt_flags_ & DEBUGBREAK; | 346 return thread_local_.interrupt_flags_ & DEBUGBREAK; |
| 326 } | 347 } |
| 327 | 348 |
| 328 | 349 |
| 329 void StackGuard::DebugBreak() { | 350 void StackGuard::DebugBreak() { |
| 330 ExecutionAccess access; | 351 ExecutionAccess access(isolate_); |
| 331 thread_local_.interrupt_flags_ |= DEBUGBREAK; | 352 thread_local_.interrupt_flags_ |= DEBUGBREAK; |
| 332 set_interrupt_limits(access); | 353 set_interrupt_limits(access); |
| 333 } | 354 } |
| 334 | 355 |
| 335 | 356 |
| 336 bool StackGuard::IsDebugCommand() { | 357 bool StackGuard::IsDebugCommand() { |
| 337 ExecutionAccess access; | 358 ExecutionAccess access(isolate_); |
| 338 return thread_local_.interrupt_flags_ & DEBUGCOMMAND; | 359 return thread_local_.interrupt_flags_ & DEBUGCOMMAND; |
| 339 } | 360 } |
| 340 | 361 |
| 341 | 362 |
| 342 void StackGuard::DebugCommand() { | 363 void StackGuard::DebugCommand() { |
| 343 if (FLAG_debugger_auto_break) { | 364 if (FLAG_debugger_auto_break) { |
| 344 ExecutionAccess access; | 365 ExecutionAccess access(isolate_); |
| 345 thread_local_.interrupt_flags_ |= DEBUGCOMMAND; | 366 thread_local_.interrupt_flags_ |= DEBUGCOMMAND; |
| 346 set_interrupt_limits(access); | 367 set_interrupt_limits(access); |
| 347 } | 368 } |
| 348 } | 369 } |
| 349 #endif | 370 #endif |
| 350 | 371 |
| 351 void StackGuard::Continue(InterruptFlag after_what) { | 372 void StackGuard::Continue(InterruptFlag after_what) { |
| 352 ExecutionAccess access; | 373 ExecutionAccess access(isolate_); |
| 353 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); | 374 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); |
| 354 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { | 375 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { |
| 355 reset_limits(access); | 376 reset_limits(access); |
| 356 } | 377 } |
| 357 } | 378 } |
| 358 | 379 |
| 359 | 380 |
| 360 char* StackGuard::ArchiveStackGuard(char* to) { | 381 char* StackGuard::ArchiveStackGuard(char* to) { |
| 361 ExecutionAccess access; | 382 ExecutionAccess access(isolate_); |
| 362 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 383 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
| 363 ThreadLocal blank; | 384 ThreadLocal blank; |
| 364 | 385 |
| 365 // Set the stack limits using the old thread_local_. | 386 // Set the stack limits using the old thread_local_. |
| 366 // TODO(isolates): This was the old semantics of constructing a ThreadLocal | 387 // TODO(isolates): This was the old semantics of constructing a ThreadLocal |
| 367 // (as the ctor called SetStackLimits, which looked at the | 388 // (as the ctor called SetStackLimits, which looked at the |
| 368 // current thread_local_ from StackGuard)-- but is this | 389 // current thread_local_ from StackGuard)-- but is this |
| 369 // really what was intended? | 390 // really what was intended? |
| 370 isolate_->heap()->SetStackLimits(); | 391 isolate_->heap()->SetStackLimits(); |
| 371 thread_local_ = blank; | 392 thread_local_ = blank; |
| 372 | 393 |
| 373 return to + sizeof(ThreadLocal); | 394 return to + sizeof(ThreadLocal); |
| 374 } | 395 } |
| 375 | 396 |
| 376 | 397 |
| 377 char* StackGuard::RestoreStackGuard(char* from) { | 398 char* StackGuard::RestoreStackGuard(char* from) { |
| 378 ExecutionAccess access; | 399 ExecutionAccess access(isolate_); |
| 379 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); | 400 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); |
| 380 isolate_->heap()->SetStackLimits(); | 401 isolate_->heap()->SetStackLimits(); |
| 381 return from + sizeof(ThreadLocal); | 402 return from + sizeof(ThreadLocal); |
| 382 } | 403 } |
| 383 | 404 |
| 384 | 405 |
| 385 void StackGuard::FreeThreadResources() { | 406 void StackGuard::FreeThreadResources() { |
| 386 Isolate::CurrentPerIsolateThreadData()->set_stack_limit( | 407 Isolate::CurrentPerIsolateThreadData()->set_stack_limit( |
| 387 thread_local_.real_climit_); | 408 thread_local_.real_climit_); |
| 388 } | 409 } |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 // a debug command break. | 736 // a debug command break. |
| 716 Isolate::Current()->debugger()->OnDebugBreak(FACTORY->undefined_value(), | 737 Isolate::Current()->debugger()->OnDebugBreak(FACTORY->undefined_value(), |
| 717 debug_command_only); | 738 debug_command_only); |
| 718 } | 739 } |
| 719 | 740 |
| 720 | 741 |
| 721 #endif | 742 #endif |
| 722 | 743 |
| 723 MaybeObject* Execution::HandleStackGuardInterrupt() { | 744 MaybeObject* Execution::HandleStackGuardInterrupt() { |
| 724 Isolate* isolate = Isolate::Current(); | 745 Isolate* isolate = Isolate::Current(); |
| 746 StackGuard* stack_guard = isolate->stack_guard(); |
| 747 isolate->counters()->stack_interrupts()->Increment(); |
| 748 if (stack_guard->IsRuntimeProfilerTick()) { |
| 749 isolate->counters()->runtime_profiler_ticks()->Increment(); |
| 750 stack_guard->Continue(RUNTIME_PROFILER_TICK); |
| 751 isolate->runtime_profiler()->OptimizeNow(); |
| 752 } |
| 725 #ifdef ENABLE_DEBUGGER_SUPPORT | 753 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 726 if (isolate->stack_guard()->IsDebugBreak() || | 754 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) { |
| 727 isolate->stack_guard()->IsDebugCommand()) { | |
| 728 DebugBreakHelper(); | 755 DebugBreakHelper(); |
| 729 } | 756 } |
| 730 #endif | 757 #endif |
| 731 if (isolate->stack_guard()->IsPreempted()) RuntimePreempt(); | 758 if (stack_guard->IsPreempted()) RuntimePreempt(); |
| 732 if (isolate->stack_guard()->IsTerminateExecution()) { | 759 if (stack_guard->IsTerminateExecution()) { |
| 733 isolate->stack_guard()->Continue(TERMINATE); | 760 stack_guard->Continue(TERMINATE); |
| 734 return isolate->TerminateExecution(); | 761 return isolate->TerminateExecution(); |
| 735 } | 762 } |
| 736 if (isolate->stack_guard()->IsInterrupted()) { | 763 if (stack_guard->IsInterrupted()) { |
| 737 // interrupt | 764 // interrupt |
| 738 isolate->stack_guard()->Continue(INTERRUPT); | 765 stack_guard->Continue(INTERRUPT); |
| 739 return isolate->StackOverflow(); | 766 return isolate->StackOverflow(); |
| 740 } | 767 } |
| 741 return isolate->heap()->undefined_value(); | 768 return isolate->heap()->undefined_value(); |
| 742 } | 769 } |
| 743 | 770 |
| 744 } } // namespace v8::internal | 771 } } // namespace v8::internal |
| OLD | NEW |