| 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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 if (object->IsHeapObject() && | 227 if (object->IsHeapObject() && |
| 228 HeapObject::cast(*object)->map()->has_instance_call_handler()) { | 228 HeapObject::cast(*object)->map()->has_instance_call_handler()) { |
| 229 return Handle<JSFunction>( | 229 return Handle<JSFunction>( |
| 230 isolate->global_context()->call_as_function_delegate()); | 230 isolate->global_context()->call_as_function_delegate()); |
| 231 } | 231 } |
| 232 | 232 |
| 233 return factory->undefined_value(); | 233 return factory->undefined_value(); |
| 234 } | 234 } |
| 235 | 235 |
| 236 | 236 |
| 237 Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object, |
| 238 bool* has_pending_exception) { |
| 239 ASSERT(!object->IsJSFunction()); |
| 240 Isolate* isolate = Isolate::Current(); |
| 241 |
| 242 // Objects created through the API can have an instance-call handler |
| 243 // that should be used when calling the object as a function. |
| 244 if (object->IsHeapObject() && |
| 245 HeapObject::cast(*object)->map()->has_instance_call_handler()) { |
| 246 return Handle<JSFunction>( |
| 247 isolate->global_context()->call_as_function_delegate()); |
| 248 } |
| 249 |
| 250 // If the Object doesn't have an instance-call handler we should |
| 251 // throw a non-callable exception. |
| 252 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( |
| 253 "called_non_callable", i::HandleVector<i::Object>(&object, 1)); |
| 254 isolate->Throw(*error_obj); |
| 255 *has_pending_exception = true; |
| 256 |
| 257 return isolate->factory()->undefined_value(); |
| 258 } |
| 259 |
| 260 |
| 237 Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { | 261 Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { |
| 238 ASSERT(!object->IsJSFunction()); | 262 ASSERT(!object->IsJSFunction()); |
| 239 Isolate* isolate = Isolate::Current(); | 263 Isolate* isolate = Isolate::Current(); |
| 240 | 264 |
| 241 // If you return a function from here, it will be called when an | 265 // If you return a function from here, it will be called when an |
| 242 // attempt is made to call the given object as a constructor. | 266 // attempt is made to call the given object as a constructor. |
| 243 | 267 |
| 244 // Objects created through the API can have an instance-call handler | 268 // Objects created through the API can have an instance-call handler |
| 245 // that should be used when calling the object as a function. | 269 // that should be used when calling the object as a function. |
| 246 if (object->IsHeapObject() && | 270 if (object->IsHeapObject() && |
| 247 HeapObject::cast(*object)->map()->has_instance_call_handler()) { | 271 HeapObject::cast(*object)->map()->has_instance_call_handler()) { |
| 248 return Handle<JSFunction>( | 272 return Handle<JSFunction>( |
| 249 isolate->global_context()->call_as_constructor_delegate()); | 273 isolate->global_context()->call_as_constructor_delegate()); |
| 250 } | 274 } |
| 251 | 275 |
| 252 return isolate->factory()->undefined_value(); | 276 return isolate->factory()->undefined_value(); |
| 253 } | 277 } |
| 254 | 278 |
| 255 | 279 |
| 280 Handle<Object> Execution::TryGetConstructorDelegate( |
| 281 Handle<Object> object, |
| 282 bool* has_pending_exception) { |
| 283 ASSERT(!object->IsJSFunction()); |
| 284 Isolate* isolate = Isolate::Current(); |
| 285 |
| 286 // If you return a function from here, it will be called when an |
| 287 // attempt is made to call the given object as a constructor. |
| 288 |
| 289 // Objects created through the API can have an instance-call handler |
| 290 // that should be used when calling the object as a function. |
| 291 if (object->IsHeapObject() && |
| 292 HeapObject::cast(*object)->map()->has_instance_call_handler()) { |
| 293 return Handle<JSFunction>( |
| 294 isolate->global_context()->call_as_constructor_delegate()); |
| 295 } |
| 296 |
| 297 // If the Object doesn't have an instance-call handler we should |
| 298 // throw a non-callable exception. |
| 299 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( |
| 300 "called_non_callable", i::HandleVector<i::Object>(&object, 1)); |
| 301 isolate->Throw(*error_obj); |
| 302 *has_pending_exception = true; |
| 303 |
| 304 return isolate->factory()->undefined_value(); |
| 305 } |
| 306 |
| 307 |
| 256 bool StackGuard::IsStackOverflow() { | 308 bool StackGuard::IsStackOverflow() { |
| 257 ExecutionAccess access(isolate_); | 309 ExecutionAccess access(isolate_); |
| 258 return (thread_local_.jslimit_ != kInterruptLimit && | 310 return (thread_local_.jslimit_ != kInterruptLimit && |
| 259 thread_local_.climit_ != kInterruptLimit); | 311 thread_local_.climit_ != kInterruptLimit); |
| 260 } | 312 } |
| 261 | 313 |
| 262 | 314 |
| 263 void StackGuard::EnableInterrupts() { | 315 void StackGuard::EnableInterrupts() { |
| 264 ExecutionAccess access(isolate_); | 316 ExecutionAccess access(isolate_); |
| 265 if (has_pending_interrupts(access)) { | 317 if (has_pending_interrupts(access)) { |
| 266 set_interrupt_limits(access); | 318 set_interrupt_limits(access); |
| 267 } | 319 } |
| 268 } | 320 } |
| 269 | 321 |
| 270 | 322 |
| 271 void StackGuard::SetStackLimit(uintptr_t limit) { | 323 void StackGuard::SetStackLimit(uintptr_t limit) { |
| 272 ExecutionAccess access(isolate_); | 324 ExecutionAccess access(isolate_); |
| 273 // If the current limits are special (eg due to a pending interrupt) then | 325 // If the current limits are special (eg due to a pending interrupt) then |
| 274 // leave them alone. | 326 // leave them alone. |
| 275 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(limit); | 327 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit); |
| 276 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) { | 328 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) { |
| 277 thread_local_.jslimit_ = jslimit; | 329 thread_local_.jslimit_ = jslimit; |
| 278 } | 330 } |
| 279 if (thread_local_.climit_ == thread_local_.real_climit_) { | 331 if (thread_local_.climit_ == thread_local_.real_climit_) { |
| 280 thread_local_.climit_ = limit; | 332 thread_local_.climit_ = limit; |
| 281 } | 333 } |
| 282 thread_local_.real_climit_ = limit; | 334 thread_local_.real_climit_ = limit; |
| 283 thread_local_.real_jslimit_ = jslimit; | 335 thread_local_.real_jslimit_ = jslimit; |
| 284 } | 336 } |
| 285 | 337 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 real_jslimit_ = kIllegalLimit; | 473 real_jslimit_ = kIllegalLimit; |
| 422 jslimit_ = kIllegalLimit; | 474 jslimit_ = kIllegalLimit; |
| 423 real_climit_ = kIllegalLimit; | 475 real_climit_ = kIllegalLimit; |
| 424 climit_ = kIllegalLimit; | 476 climit_ = kIllegalLimit; |
| 425 nesting_ = 0; | 477 nesting_ = 0; |
| 426 postpone_interrupts_nesting_ = 0; | 478 postpone_interrupts_nesting_ = 0; |
| 427 interrupt_flags_ = 0; | 479 interrupt_flags_ = 0; |
| 428 } | 480 } |
| 429 | 481 |
| 430 | 482 |
| 431 bool StackGuard::ThreadLocal::Initialize() { | 483 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { |
| 432 bool should_set_stack_limits = false; | 484 bool should_set_stack_limits = false; |
| 433 if (real_climit_ == kIllegalLimit) { | 485 if (real_climit_ == kIllegalLimit) { |
| 434 // Takes the address of the limit variable in order to find out where | 486 // Takes the address of the limit variable in order to find out where |
| 435 // the top of stack is right now. | 487 // the top of stack is right now. |
| 436 const uintptr_t kLimitSize = FLAG_stack_size * KB; | 488 const uintptr_t kLimitSize = FLAG_stack_size * KB; |
| 437 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; | 489 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; |
| 438 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); | 490 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); |
| 439 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(limit); | 491 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); |
| 440 jslimit_ = SimulatorStack::JsLimitFromCLimit(limit); | 492 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); |
| 441 real_climit_ = limit; | 493 real_climit_ = limit; |
| 442 climit_ = limit; | 494 climit_ = limit; |
| 443 should_set_stack_limits = true; | 495 should_set_stack_limits = true; |
| 444 } | 496 } |
| 445 nesting_ = 0; | 497 nesting_ = 0; |
| 446 postpone_interrupts_nesting_ = 0; | 498 postpone_interrupts_nesting_ = 0; |
| 447 interrupt_flags_ = 0; | 499 interrupt_flags_ = 0; |
| 448 return should_set_stack_limits; | 500 return should_set_stack_limits; |
| 449 } | 501 } |
| 450 | 502 |
| 451 | 503 |
| 452 void StackGuard::ClearThread(const ExecutionAccess& lock) { | 504 void StackGuard::ClearThread(const ExecutionAccess& lock) { |
| 453 thread_local_.Clear(); | 505 thread_local_.Clear(); |
| 454 isolate_->heap()->SetStackLimits(); | 506 isolate_->heap()->SetStackLimits(); |
| 455 } | 507 } |
| 456 | 508 |
| 457 | 509 |
| 458 void StackGuard::InitThread(const ExecutionAccess& lock) { | 510 void StackGuard::InitThread(const ExecutionAccess& lock) { |
| 459 if (thread_local_.Initialize()) isolate_->heap()->SetStackLimits(); | 511 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits(); |
| 460 uintptr_t stored_limit = | 512 Isolate::PerIsolateThreadData* per_thread = |
| 461 Isolate::CurrentPerIsolateThreadData()->stack_limit(); | 513 isolate_->FindOrAllocatePerThreadDataForThisThread(); |
| 514 uintptr_t stored_limit = per_thread->stack_limit(); |
| 462 // You should hold the ExecutionAccess lock when you call this. | 515 // You should hold the ExecutionAccess lock when you call this. |
| 463 if (stored_limit != 0) { | 516 if (stored_limit != 0) { |
| 464 StackGuard::SetStackLimit(stored_limit); | 517 StackGuard::SetStackLimit(stored_limit); |
| 465 } | 518 } |
| 466 } | 519 } |
| 467 | 520 |
| 468 | 521 |
| 469 // --- C a l l s t o n a t i v e s --- | 522 // --- C a l l s t o n a t i v e s --- |
| 470 | 523 |
| 471 #define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \ | 524 #define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \ |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 | 727 |
| 675 ContextSwitcher::PreemptionReceived(); | 728 ContextSwitcher::PreemptionReceived(); |
| 676 | 729 |
| 677 #ifdef ENABLE_DEBUGGER_SUPPORT | 730 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 678 if (isolate->debug()->InDebugger()) { | 731 if (isolate->debug()->InDebugger()) { |
| 679 // If currently in the debugger don't do any actual preemption but record | 732 // If currently in the debugger don't do any actual preemption but record |
| 680 // that preemption occoured while in the debugger. | 733 // that preemption occoured while in the debugger. |
| 681 isolate->debug()->PreemptionWhileInDebugger(); | 734 isolate->debug()->PreemptionWhileInDebugger(); |
| 682 } else { | 735 } else { |
| 683 // Perform preemption. | 736 // Perform preemption. |
| 684 v8::Unlocker unlocker; | 737 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate)); |
| 685 Thread::YieldCPU(); | 738 Thread::YieldCPU(); |
| 686 } | 739 } |
| 687 #else | 740 #else |
| 688 { // NOLINT | 741 { // NOLINT |
| 689 // Perform preemption. | 742 // Perform preemption. |
| 690 v8::Unlocker unlocker; | 743 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate)); |
| 691 Thread::YieldCPU(); | 744 Thread::YieldCPU(); |
| 692 } | 745 } |
| 693 #endif | 746 #endif |
| 694 | 747 |
| 695 return isolate->heap()->undefined_value(); | 748 return isolate->heap()->undefined_value(); |
| 696 } | 749 } |
| 697 | 750 |
| 698 | 751 |
| 699 #ifdef ENABLE_DEBUGGER_SUPPORT | 752 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 700 Object* Execution::DebugBreakHelper() { | 753 Object* Execution::DebugBreakHelper() { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 return isolate->TerminateExecution(); | 835 return isolate->TerminateExecution(); |
| 783 } | 836 } |
| 784 if (stack_guard->IsInterrupted()) { | 837 if (stack_guard->IsInterrupted()) { |
| 785 stack_guard->Continue(INTERRUPT); | 838 stack_guard->Continue(INTERRUPT); |
| 786 return isolate->StackOverflow(); | 839 return isolate->StackOverflow(); |
| 787 } | 840 } |
| 788 return isolate->heap()->undefined_value(); | 841 return isolate->heap()->undefined_value(); |
| 789 } | 842 } |
| 790 | 843 |
| 791 } } // namespace v8::internal | 844 } } // namespace v8::internal |
| OLD | NEW |