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 |