📄 top.cc.svn-base
字号:
// The callers of this method are not expecting a GC. AssertNoAllocation no_gc; // Get the data object from access check info. JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); Object* info = constructor->shared()->function_data(); if (info == Heap::undefined_value()) return; Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); if (data_obj == Heap::undefined_value()) return; HandleScope scope; Handle<JSObject> receiver_handle(receiver); Handle<Object> data(AccessCheckInfo::cast(data_obj)->data()); thread_local_.failed_access_check_callback_( v8::Utils::ToLocal(receiver_handle), type, v8::Utils::ToLocal(data));}bool Top::MayNamedAccess(JSObject* receiver, Object* key, v8::AccessType type) { ASSERT(receiver->IsAccessCheckNeeded()); // Check for compatibility between the security tokens in the // current security context and the accessed object. ASSERT(Top::security_context()); // The callers of this method are not expecting a GC. AssertNoAllocation no_gc; // During bootstrapping, callback functions are not enabled yet. if (Bootstrapper::IsActive()) return true; if (receiver->IsJSGlobalObject()) { JSGlobalObject* global = JSGlobalObject::cast(receiver); JSGlobalObject* current = JSGlobalObject::cast(Top::security_context()->global()); if (current->security_token() == global->security_token()) return true; } // Get named access check callback JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); Object* info = constructor->shared()->function_data(); if (info == Heap::undefined_value()) return false; Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); if (data_obj == Heap::undefined_value()) return false; Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback(); v8::NamedSecurityCallback callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj); if (!callback) return false; HandleScope scope; Handle<JSObject> receiver_handle(receiver); Handle<Object> key_handle(key); Handle<Object> data(AccessCheckInfo::cast(data_obj)->data()); LOG(ApiNamedSecurityCheck(key)); bool result = false; { // Leaving JavaScript. VMState state(OTHER); result = callback(v8::Utils::ToLocal(receiver_handle), v8::Utils::ToLocal(key_handle), type, v8::Utils::ToLocal(data)); } return result;}bool Top::MayIndexedAccess(JSObject* receiver, uint32_t index, v8::AccessType type) { ASSERT(receiver->IsAccessCheckNeeded()); // Check for compatibility between the security tokens in the // current security context and the accessed object. ASSERT(Top::security_context()); // The callers of this method are not expecting a GC. AssertNoAllocation no_gc; // During bootstrapping, callback functions are not enabled yet. if (Bootstrapper::IsActive()) return true; if (receiver->IsJSGlobalObject()) { JSGlobalObject* global = JSGlobalObject::cast(receiver); JSGlobalObject* current = JSGlobalObject::cast(Top::security_context()->global()); if (current->security_token() == global->security_token()) return true; } // Get indexed access check callback JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); Object* info = constructor->shared()->function_data(); if (info == Heap::undefined_value()) return false; Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); if (data_obj == Heap::undefined_value()) return false; Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback(); v8::IndexedSecurityCallback callback = v8::ToCData<v8::IndexedSecurityCallback>(fun_obj); if (!callback) return false; HandleScope scope; Handle<JSObject> receiver_handle(receiver); Handle<Object> data(AccessCheckInfo::cast(data_obj)->data()); LOG(ApiIndexedSecurityCheck(index)); bool result = false; { // Leaving JavaScript. VMState state(OTHER); result = callback(v8::Utils::ToLocal(receiver_handle), index, type, v8::Utils::ToLocal(data)); } return result;}Failure* Top::StackOverflow() { HandleScope scope; Handle<String> key = Factory::stack_overflow_symbol(); Handle<JSObject> boilerplate = Handle<JSObject>::cast( GetProperty(Top::security_context_builtins(), key)); Handle<Object> exception = Copy(boilerplate); // TODO(1240995): To avoid having to call JavaScript code to compute // the message for stack overflow exceptions which is very likely to // double fault with another stack overflow exception, we use a // precomputed message. This is somewhat problematic in that it // doesn't use ReportUncaughtException to determine the location // from where the exception occurred. It should probably be // reworked. static const char* kMessage = "Uncaught RangeError: Maximum call stack size exceeded"; DoThrow(*exception, NULL, kMessage, false); return Failure::Exception();}Failure* Top::Throw(Object* exception, MessageLocation* location) { DoThrow(exception, location, NULL, false); return Failure::Exception();}Failure* Top::ReThrow(Object* exception, MessageLocation* location) { DoThrow(exception, location, NULL, true); return Failure::Exception();}void Top::ScheduleThrow(Object* exception) { // When scheduling a throw we first throw the exception to get the // error reporting if it is uncaught before rescheduling it. Throw(exception); thread_local_.scheduled_exception_ = pending_exception(); thread_local_.external_caught_exception_ = false; clear_pending_exception();}Object* Top::PromoteScheduledException() { Object* thrown = scheduled_exception(); clear_scheduled_exception(); // Re-throw the exception to avoid getting repeated error reporting. return ReThrow(thrown);}// NOTE: The stack trace frame iterator is an iterator that only// traverse proper JavaScript frames; that is JavaScript frames that// have proper JavaScript functions. This excludes the problematic// functions in runtime.js.class StackTraceFrameIterator: public JavaScriptFrameIterator { public: StackTraceFrameIterator() { if (!done() && !frame()->function()->IsJSFunction()) Advance(); } void Advance() { while (true) { JavaScriptFrameIterator::Advance(); if (done()) return; if (frame()->function()->IsJSFunction()) return; } }};void Top::PrintCurrentStackTrace(FILE* out) { StackTraceFrameIterator it; while (!it.done()) { HandleScope scope; // Find code position if recorded in relocation info. JavaScriptFrame* frame = it.frame(); int pos = frame->FindCode()->SourcePosition(frame->pc()); Handle<Object> pos_obj(Smi::FromInt(pos)); // Fetch function and receiver. Handle<JSFunction> fun(JSFunction::cast(frame->function())); Handle<Object> recv(frame->receiver()); // Advance to the next JavaScript frame and determine if the // current frame is the top-level frame. it.Advance(); Handle<Object> is_top_level = it.done() ? Factory::true_value() : Factory::false_value(); // Generate and print strack trace line. Handle<String> line = Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level); if (line->length() > 0) { line->PrintOn(out); fprintf(out, "\n"); } }}void Top::ComputeLocation(MessageLocation* target) { *target = MessageLocation(empty_script(), -1, -1); StackTraceFrameIterator it; if (!it.done()) { JavaScriptFrame* frame = it.frame(); JSFunction* fun = JSFunction::cast(frame->function()); Object* script = fun->shared()->script(); if (script->IsScript() && !(Script::cast(script)->source()->IsUndefined())) { int pos = frame->FindCode()->SourcePosition(frame->pc()); // Compute the location from the function and the reloc info. Handle<Script> casted_script(Script::cast(script)); *target = MessageLocation(casted_script, pos, pos + 1); } }}void Top::ReportUncaughtException(Handle<Object> exception, MessageLocation* location, Handle<String> stack_trace) { Handle<Object> message = MessageHandler::MakeMessageObject("uncaught_exception", location, HandleVector<Object>(&exception, 1), stack_trace); // Report the uncaught exception. MessageHandler::ReportMessage(location, message);}bool Top::ShouldReportException(bool* is_caught_externally) { StackHandler* handler = StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); // Determine if we have an external exception handler and get the // address of the external handler so we can compare the address to // determine which one is closer to the top of the stack. bool has_external_handler = (thread_local_.try_catch_handler_ != NULL); Address external_handler_address = reinterpret_cast<Address>(thread_local_.try_catch_handler_); // NOTE: The stack is assumed to grown towards lower addresses. If // the handler is at a higher address than the external address it // means that it is below it on the stack. // Find the top-most try-catch or try-finally handler. while (handler != NULL && handler->is_entry()) { handler = handler->next(); } // The exception has been externally caught if and only if there is // an external handler which is above any JavaScript try-catch or // try-finally handlers. *is_caught_externally = has_external_handler && (handler == NULL || handler->address() > external_handler_address); // Find the top-most try-catch handler. while (handler != NULL && !handler->is_try_catch()) { handler = handler->next(); } // If we have a try-catch handler then the exception is caught in // JavaScript code. bool is_uncaught_by_js = (handler == NULL); // If there is no external try-catch handler, we report the // exception if it isn't caught by JavaScript code. if (!has_external_handler) return is_uncaught_by_js; if (is_uncaught_by_js || handler->address() > external_handler_address) { // Only report the exception if the external handler is verbose. return thread_local_.try_catch_handler_->is_verbose_; } else { // Report the exception if it isn't caught by JavaScript code. return is_uncaught_by_js; }}void Top::DoThrow(Object* exception, MessageLocation* location, const char* message, bool is_rethrow) { ASSERT(!has_pending_exception()); ASSERT(!external_caught_exception()); HandleScope scope; Handle<Object> exception_handle(exception); bool is_caught_externally = false; bool report_exception = (exception != Failure::OutOfMemoryException()) && ShouldReportException(&is_caught_externally); if (is_rethrow) report_exception = false; Handle<Object> message_obj; MessageLocation potential_computed_location; bool try_catch_needs_message = is_caught_externally && thread_local_.try_catch_handler_->capture_message_; if (report_exception || try_catch_needs_message) { if (location == NULL) { // If no location was specified we use a computed one instead ComputeLocation(&potential_computed_location); location = &potential_computed_location; } Handle<String> stack_trace; if (FLAG_trace_exception) stack_trace = StackTrace(); message_obj = MessageHandler::MakeMessageObject("uncaught_exception", location, HandleVector<Object>(&exception_handle, 1), stack_trace); } // If the exception is caught externally, we store it in the // try/catch handler. The C code can find it later and process it if // necessary. if (is_caught_externally) { thread_local_.try_catch_handler_->exception_ = reinterpret_cast<void*>(*exception_handle); if (!message_obj.is_null()) { thread_local_.try_catch_handler_->message_ = reinterpret_cast<void*>(*message_obj); } } // Notify debugger of exception. Debugger::OnException(exception_handle, report_exception); if (report_exception) { if (message != NULL) { MessageHandler::ReportMessage(message); } else { MessageHandler::ReportMessage(location, message_obj); } } thread_local_.external_caught_exception_ = is_caught_externally; // NOTE: Notifying the debugger or reporting the exception may have caused // new exceptions. For now, we just ignore that and set the pending exception // to the original one. set_pending_exception(*exception_handle);}void Top::TraceException(bool flag) { FLAG_trace_exception = flag;}bool Top::optional_reschedule_exception(bool is_bottom_call) { if (!is_out_of_memory() && (thread_local_.external_caught_exception_ || is_bottom_call)) { thread_local_.external_caught_exception_ = false; clear_pending_exception(); return false; } else { thread_local_.scheduled_exception_ = pending_exception(); clear_pending_exception(); return true; }}bool Top::is_out_of_memory() { if (has_pending_exception()) { Object* e = pending_exception(); if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { return true; } } if (has_scheduled_exception()) { Object* e = scheduled_exception(); if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { return true; } } return false;}Handle<Context> Top::global_context() { GlobalObject* global = thread_local_.context_->global(); return Handle<Context>(global->global_context());}Object* Top::LookupSpecialFunction(JSObject* receiver, JSObject* prototype, JSFunction* function) { if (receiver->IsJSArray()) { FixedArray* table = context()->global_context()->special_function_table(); for (int index = 0; index < table->length(); index +=3) { if ((prototype == table->get(index)) && (function == table->get(index+1))) { return table->get(index+2); } } } return Heap::undefined_value();}char* Top::ArchiveThread(char* to) { memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(thread_local_)); InitializeThreadLocal(); return to + sizeof(thread_local_);}char* Top::RestoreThread(char* from) { memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(thread_local_)); return from + sizeof(thread_local_);}ExecutionAccess::ExecutionAccess() { Top::break_access_->Lock();}ExecutionAccess::~ExecutionAccess() { Top::break_access_->Unlock();}} } // namespace v8::internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -