{"id":3520,"date":"2011-06-18T10:34:47","date_gmt":"2011-06-18T15:34:47","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=3520"},"modified":"2014-06-25T09:21:36","modified_gmt":"2014-06-25T13:21:36","slug":"objc_msgsend_vtable","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2011\/06\/18\/objc_msgsend_vtable\/","title":{"rendered":"objc_msgSend_vtable"},"content":{"rendered":"<p><a href=\"http:\/\/www.sealiesoftware.com\/blog\/archive\/2011\/06\/17\/objc_explain_objc_msgSend_vtable.html\">Greg Parker<\/a>:<\/p>\r\n<blockquote cite=\"http:\/\/www.sealiesoftware.com\/blog\/archive\/2011\/06\/17\/objc_explain_objc_msgSend_vtable.html\"><p>The compiler knows which selectors are optimized by the runtime. It\r\n      compiles the call site differently,\r\n      calling <code>objc_msgSend_fixup<\/code> via a function pointer. At\r\n      runtime, <code>objc_msgSend_fixup<\/code> replaces the function\r\n      pointer with one of the <code>objc_msgSend_vtable<\/code> functions,\r\n      if the called selector is one of the optimized selectors.<\/p><\/blockquote>\r\n<p>Update (2014-06-25): <a href=\"http:\/\/opensource.apple.com\/source\/objc4\/objc4-437\/runtime\/objc-runtime-new.m\">objc-runtime-new.m<\/a> (via <a href=\"http:\/\/cocoasamurai.blogspot.com\/2010\/01\/understanding-objective-c-runtime.html\">Colin Wheeler<\/a>):<\/p>\r\n<blockquote cite=\"http:\/\/opensource.apple.com\/source\/objc4\/objc4-437\/runtime\/objc-runtime-new.m\"><pre>\/***********************************************************************\r\n* vtable dispatch\r\n* \r\n* Every class gets a vtable pointer. The vtable is an array of IMPs.\r\n* The selectors represented in the vtable are the same for all classes\r\n*   (i.e. no class has a bigger or smaller vtable).\r\n* Each vtable index has an associated trampoline which dispatches to \r\n*   the IMP at that index for the receiver class's vtable (after \r\n*   checking for NULL). Dispatch fixup uses these trampolines instead \r\n*   of objc_msgSend.\r\n* Fragility: The vtable size and list of selectors is chosen at launch \r\n*   time. No compiler-generated code depends on any particular vtable \r\n*   configuration, or even the use of vtable dispatch at all.\r\n* Memory size: If a class's vtable is identical to its superclass's \r\n*   (i.e. the class overrides none of the vtable selectors), then \r\n*   the class points directly to its superclass's vtable. This means \r\n*   selectors to be included in the vtable should be chosen so they are \r\n*   (1) frequently called, but (2) not too frequently overridden. In \r\n*   particular, -dealloc is a bad choice.\r\n* Forwarding: If a class doesn't implement some vtable selector, that \r\n*   selector's IMP is set to objc_msgSend in that class's vtable.\r\n* +initialize: Each class keeps the default vtable (which always \r\n*   redirects to objc_msgSend) until its +initialize is completed.\r\n*   Otherwise, the first message to a class could be a vtable dispatch, \r\n*   and the vtable trampoline doesn't include +initialize checking.\r\n* Changes: Categories, addMethod, and setImplementation all force vtable \r\n*   reconstruction for the class and all of its subclasses, if the \r\n*   vtable selectors are affected.\r\n**********************************************************************\/<\/pre><\/blockquote>\r\n<p><a href=\"http:\/\/stackoverflow.com\/questions\/12228350\/what-is-objc-msgsend-fixup-exactly\/15313433#15313433\">LuisABOL<\/a>:<\/p>\r\n<blockquote cite=\"http:\/\/stackoverflow.com\/questions\/12228350\/what-is-objc-msgsend-fixup-exactly\/15313433#15313433\"><p>At the program startup, the message reference trampolines are pointers to the <code>objc_msgSend_fixup<\/code> function. For each <code>message_ref<\/code>, when its <code>trampoline<\/code> pointer is invoked for the first time, <code>objc_msgSend_fixup<\/code> gets called receiving the <code>obj<\/code> to which the message\u2019s got to be sent and the <code>message_ref<\/code> structure from which it was called. So, what <code>objc_msgSend_fixup<\/code> must do is get the selector for the message to be called. Since, this has to be done only once for each message reference, <code>objc_msgSend_fixup<\/code> must also replace the <code>trampoline<\/code> field of the ref by a pointer to another function that doesn\u2019t fix the message\u2019s selector. This function is called <code>objc_msgSend_fixedup<\/code> (the selector has been fixed up). Now that the message selector has been set and this doesn\u2019t have to be done again, <code>objc_msgSend_fixup<\/code> just calls <code>objc_msgSend_fixedup<\/code> and this just calls <code>objc_msgSend<\/code>. After that, if a message ref\u2019s <code>trampoline<\/code> is called again, its selector is already fixed, and <code>objc_msgSend_fixedup<\/code> is the one that gets called.<\/p><\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Greg Parker: The compiler knows which selectors are optimized by the runtime. It compiles the call site differently, calling objc_msgSend_fixup via a function pointer. At runtime, objc_msgSend_fixup replaces the function pointer with one of the objc_msgSend_vtable functions, if the called selector is one of the optimized selectors. Update (2014-06-25): objc-runtime-new.m (via Colin Wheeler): \/*********************************************************************** * [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"","apple_news_api_id":"","apple_news_api_modified_at":"","apple_news_api_revision":"","apple_news_api_share_url":"","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[54,760,138,71],"class_list":["post-3520","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-objective-c","tag-objective-c-runtime","tag-optimization","tag-programming"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/3520","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=3520"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/3520\/revisions"}],"predecessor-version":[{"id":9040,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/3520\/revisions\/9040"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=3520"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=3520"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=3520"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}