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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); | 59 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); |
60 Iterate(v, thread); | 60 Iterate(v, thread); |
61 return thread_storage + sizeof(ThreadLocalTop); | 61 return thread_storage + sizeof(ThreadLocalTop); |
62 } | 62 } |
63 | 63 |
64 | 64 |
65 #define VISIT(field) v->VisitPointer(reinterpret_cast<Object**>(&(field))); | 65 #define VISIT(field) v->VisitPointer(reinterpret_cast<Object**>(&(field))); |
66 | 66 |
67 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { | 67 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { |
68 v->VisitPointer(&(thread->pending_exception_)); | 68 v->VisitPointer(&(thread->pending_exception_)); |
69 v->VisitPointer(bit_cast<Object**, Context**>(&(thread->security_context_))); | |
70 v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_))); | 69 v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_))); |
71 v->VisitPointer(&(thread->scheduled_exception_)); | 70 v->VisitPointer(&(thread->scheduled_exception_)); |
72 | 71 |
73 for (v8::TryCatch* block = thread->try_catch_handler_; | 72 for (v8::TryCatch* block = thread->try_catch_handler_; |
74 block != NULL; | 73 block != NULL; |
75 block = block->next_) { | 74 block = block->next_) { |
76 v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_))); | 75 v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_))); |
77 v->VisitPointer(bit_cast<Object**, void**>(&(block->message_))); | 76 v->VisitPointer(bit_cast<Object**, void**>(&(block->message_))); |
78 } | 77 } |
79 | 78 |
80 // Iterate over pointers on native execution stack. | 79 // Iterate over pointers on native execution stack. |
81 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { | 80 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { |
82 it.frame()->Iterate(v); | 81 it.frame()->Iterate(v); |
83 } | 82 } |
84 } | 83 } |
85 #undef VISIT | 84 #undef VISIT |
86 | 85 |
87 | 86 |
88 void Top::Iterate(ObjectVisitor* v) { | 87 void Top::Iterate(ObjectVisitor* v) { |
89 ThreadLocalTop* current_t = &thread_local_; | 88 ThreadLocalTop* current_t = &thread_local_; |
90 Iterate(v, current_t); | 89 Iterate(v, current_t); |
91 } | 90 } |
92 | 91 |
93 | 92 |
94 void Top::InitializeThreadLocal() { | 93 void Top::InitializeThreadLocal() { |
95 thread_local_.c_entry_fp_ = 0; | 94 thread_local_.c_entry_fp_ = 0; |
96 thread_local_.handler_ = 0; | 95 thread_local_.handler_ = 0; |
97 thread_local_.stack_is_cooked_ = false; | 96 thread_local_.stack_is_cooked_ = false; |
98 thread_local_.try_catch_handler_ = NULL; | 97 thread_local_.try_catch_handler_ = NULL; |
99 thread_local_.security_context_ = NULL; | |
100 thread_local_.context_ = NULL; | 98 thread_local_.context_ = NULL; |
101 thread_local_.external_caught_exception_ = false; | 99 thread_local_.external_caught_exception_ = false; |
102 thread_local_.failed_access_check_callback_ = NULL; | 100 thread_local_.failed_access_check_callback_ = NULL; |
103 clear_pending_exception(); | 101 clear_pending_exception(); |
104 clear_scheduled_exception(); | 102 clear_scheduled_exception(); |
105 thread_local_.save_context_ = NULL; | 103 thread_local_.save_context_ = NULL; |
106 } | 104 } |
107 | 105 |
108 | 106 |
109 // Create a dummy thread that will wait forever on a semaphore. The only | 107 // Create a dummy thread that will wait forever on a semaphore. The only |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 void Top::SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback) { | 435 void Top::SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback) { |
438 ASSERT(thread_local_.failed_access_check_callback_ == NULL); | 436 ASSERT(thread_local_.failed_access_check_callback_ == NULL); |
439 thread_local_.failed_access_check_callback_ = callback; | 437 thread_local_.failed_access_check_callback_ = callback; |
440 } | 438 } |
441 | 439 |
442 | 440 |
443 void Top::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) { | 441 void Top::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) { |
444 if (!thread_local_.failed_access_check_callback_) return; | 442 if (!thread_local_.failed_access_check_callback_) return; |
445 | 443 |
446 ASSERT(receiver->IsAccessCheckNeeded()); | 444 ASSERT(receiver->IsAccessCheckNeeded()); |
447 ASSERT(Top::security_context()); | 445 ASSERT(Top::context()); |
448 // The callers of this method are not expecting a GC. | 446 // The callers of this method are not expecting a GC. |
449 AssertNoAllocation no_gc; | 447 AssertNoAllocation no_gc; |
450 | 448 |
451 // Get the data object from access check info. | 449 // Get the data object from access check info. |
452 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); | 450 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); |
453 Object* info = constructor->shared()->function_data(); | 451 Object* info = constructor->shared()->function_data(); |
454 if (info == Heap::undefined_value()) return; | 452 if (info == Heap::undefined_value()) return; |
455 | 453 |
456 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); | 454 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); |
457 if (data_obj == Heap::undefined_value()) return; | 455 if (data_obj == Heap::undefined_value()) return; |
458 | 456 |
459 HandleScope scope; | 457 HandleScope scope; |
460 Handle<JSObject> receiver_handle(receiver); | 458 Handle<JSObject> receiver_handle(receiver); |
461 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data()); | 459 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data()); |
462 thread_local_.failed_access_check_callback_( | 460 thread_local_.failed_access_check_callback_( |
463 v8::Utils::ToLocal(receiver_handle), | 461 v8::Utils::ToLocal(receiver_handle), |
464 type, | 462 type, |
465 v8::Utils::ToLocal(data)); | 463 v8::Utils::ToLocal(data)); |
466 } | 464 } |
467 | 465 |
| 466 |
| 467 enum MayAccessDecision{ |
| 468 YES, NO, UNKNOWN |
| 469 }; |
| 470 |
| 471 |
| 472 static MayAccessDecision MayAccessPreCheck(JSObject* receiver, |
| 473 v8::AccessType type) { |
| 474 // During bootstrapping, callback functions are not enabled yet. |
| 475 if (Bootstrapper::IsActive()) return YES; |
| 476 |
| 477 if (receiver->IsJSGlobalProxy()) { |
| 478 Object* receiver_context = JSGlobalProxy::cast(receiver)->context(); |
| 479 if (!receiver_context->IsContext()) return NO; |
| 480 |
| 481 // Get the global context of current top context. |
| 482 // avoid using Top::global_context() because it uses Handle. |
| 483 Context* global_context = Top::context()->global()->global_context(); |
| 484 if (receiver_context == global_context) return YES; |
| 485 |
| 486 if (Context::cast(receiver_context)->security_token() == |
| 487 global_context->security_token()) |
| 488 return YES; |
| 489 } |
| 490 |
| 491 return UNKNOWN; |
| 492 } |
| 493 |
| 494 |
468 bool Top::MayNamedAccess(JSObject* receiver, Object* key, v8::AccessType type) { | 495 bool Top::MayNamedAccess(JSObject* receiver, Object* key, v8::AccessType type) { |
469 ASSERT(receiver->IsAccessCheckNeeded()); | 496 ASSERT(receiver->IsAccessCheckNeeded()); |
470 // Check for compatibility between the security tokens in the | 497 // Check for compatibility between the security tokens in the |
471 // current security context and the accessed object. | 498 // current lexical context and the accessed object. |
472 ASSERT(Top::security_context()); | 499 ASSERT(Top::context()); |
473 // The callers of this method are not expecting a GC. | 500 // The callers of this method are not expecting a GC. |
474 AssertNoAllocation no_gc; | 501 AssertNoAllocation no_gc; |
475 | 502 |
476 // During bootstrapping, callback functions are not enabled yet. | 503 MayAccessDecision decision = MayAccessPreCheck(receiver, type); |
477 if (Bootstrapper::IsActive()) return true; | 504 if (decision != UNKNOWN) return decision == YES; |
478 | |
479 if (receiver->IsJSGlobalObject()) { | |
480 JSGlobalObject* global = JSGlobalObject::cast(receiver); | |
481 JSGlobalObject* current = | |
482 JSGlobalObject::cast(Top::security_context()->global()); | |
483 if (current->security_token() == global->security_token()) return true; | |
484 } | |
485 | 505 |
486 // Get named access check callback | 506 // Get named access check callback |
487 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); | 507 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); |
488 Object* info = constructor->shared()->function_data(); | 508 Object* info = constructor->shared()->function_data(); |
489 if (info == Heap::undefined_value()) return false; | 509 if (info == Heap::undefined_value()) return false; |
490 | 510 |
491 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); | 511 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); |
492 if (data_obj == Heap::undefined_value()) return false; | 512 if (data_obj == Heap::undefined_value()) return false; |
493 | 513 |
494 Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback(); | 514 Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback(); |
(...skipping 18 matching lines...) Expand all Loading... |
513 } | 533 } |
514 return result; | 534 return result; |
515 } | 535 } |
516 | 536 |
517 | 537 |
518 bool Top::MayIndexedAccess(JSObject* receiver, | 538 bool Top::MayIndexedAccess(JSObject* receiver, |
519 uint32_t index, | 539 uint32_t index, |
520 v8::AccessType type) { | 540 v8::AccessType type) { |
521 ASSERT(receiver->IsAccessCheckNeeded()); | 541 ASSERT(receiver->IsAccessCheckNeeded()); |
522 // Check for compatibility between the security tokens in the | 542 // Check for compatibility between the security tokens in the |
523 // current security context and the accessed object. | 543 // current lexical context and the accessed object. |
524 ASSERT(Top::security_context()); | 544 ASSERT(Top::context()); |
525 // The callers of this method are not expecting a GC. | 545 // The callers of this method are not expecting a GC. |
526 AssertNoAllocation no_gc; | 546 AssertNoAllocation no_gc; |
527 | 547 |
528 // During bootstrapping, callback functions are not enabled yet. | 548 MayAccessDecision decision = MayAccessPreCheck(receiver, type); |
529 if (Bootstrapper::IsActive()) return true; | 549 if (decision != UNKNOWN) return decision == YES; |
530 | |
531 if (receiver->IsJSGlobalObject()) { | |
532 JSGlobalObject* global = JSGlobalObject::cast(receiver); | |
533 JSGlobalObject* current = | |
534 JSGlobalObject::cast(Top::security_context()->global()); | |
535 if (current->security_token() == global->security_token()) return true; | |
536 } | |
537 | 550 |
538 // Get indexed access check callback | 551 // Get indexed access check callback |
539 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); | 552 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); |
540 Object* info = constructor->shared()->function_data(); | 553 Object* info = constructor->shared()->function_data(); |
541 if (info == Heap::undefined_value()) return false; | 554 if (info == Heap::undefined_value()) return false; |
542 | 555 |
543 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); | 556 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); |
544 if (data_obj == Heap::undefined_value()) return false; | 557 if (data_obj == Heap::undefined_value()) return false; |
545 | 558 |
546 Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback(); | 559 Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback(); |
(...skipping 16 matching lines...) Expand all Loading... |
563 v8::Utils::ToLocal(data)); | 576 v8::Utils::ToLocal(data)); |
564 } | 577 } |
565 return result; | 578 return result; |
566 } | 579 } |
567 | 580 |
568 | 581 |
569 Failure* Top::StackOverflow() { | 582 Failure* Top::StackOverflow() { |
570 HandleScope scope; | 583 HandleScope scope; |
571 Handle<String> key = Factory::stack_overflow_symbol(); | 584 Handle<String> key = Factory::stack_overflow_symbol(); |
572 Handle<JSObject> boilerplate = | 585 Handle<JSObject> boilerplate = |
573 Handle<JSObject>::cast( | 586 Handle<JSObject>::cast(GetProperty(Top::builtins(), key)); |
574 GetProperty(Top::security_context_builtins(), key)); | |
575 Handle<Object> exception = Copy(boilerplate); | 587 Handle<Object> exception = Copy(boilerplate); |
576 // TODO(1240995): To avoid having to call JavaScript code to compute | 588 // TODO(1240995): To avoid having to call JavaScript code to compute |
577 // the message for stack overflow exceptions which is very likely to | 589 // the message for stack overflow exceptions which is very likely to |
578 // double fault with another stack overflow exception, we use a | 590 // double fault with another stack overflow exception, we use a |
579 // precomputed message. This is somewhat problematic in that it | 591 // precomputed message. This is somewhat problematic in that it |
580 // doesn't use ReportUncaughtException to determine the location | 592 // doesn't use ReportUncaughtException to determine the location |
581 // from where the exception occurred. It should probably be | 593 // from where the exception occurred. It should probably be |
582 // reworked. | 594 // reworked. |
583 static const char* kMessage = | 595 static const char* kMessage = |
584 "Uncaught RangeError: Maximum call stack size exceeded"; | 596 "Uncaught RangeError: Maximum call stack size exceeded"; |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 Top::break_access_->Lock(); | 894 Top::break_access_->Lock(); |
883 } | 895 } |
884 | 896 |
885 | 897 |
886 ExecutionAccess::~ExecutionAccess() { | 898 ExecutionAccess::~ExecutionAccess() { |
887 Top::break_access_->Unlock(); | 899 Top::break_access_->Unlock(); |
888 } | 900 } |
889 | 901 |
890 | 902 |
891 } } // namespace v8::internal | 903 } } // namespace v8::internal |
OLD | NEW |