<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 3, 2017, at 1:27 PM, John McCall <<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Feb 3, 2017, at 4:18 PM, Andrew Trick <<a href="mailto:atrick@apple.com" class="">atrick@apple.com</a>> wrote:</div><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class=""><div class="">On Feb 3, 2017, at 11:55 AM, Andrew Trick via swift-dev <<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class="">#3b. (lazy resolution) Offset tables can be completely localized.<br class=""><br class="">method_index = immediate<br class="">{ // common per-class method lookup<br class=""> isa = load[obj]<br class=""> offset = load[@local_class_method_table + method_index]<br class=""> if (!isInitializedOffset(offset)) {<br class=""> offset = @resolveMethodOffset(@class_id, method_index)<br class=""> store [@local_class_method_table + method_index]<br class=""> }<br class=""> if (isVtableOffset(offset))<br class=""> method_entry = load[isa + offset]<br class=""> else<br class=""> method_entry = @resolveMethodAddress(isa, @class_id, method_index)<br class="">}<br class="">call method_entry<br class=""></blockquote><br class="">The size of @local_class_method_table is not statically knowable.<br class="">Fortunately, it doesn't matter, because this mechanism does not actually<br class="">care about the table being contiguous; the lookup function could be<br class="">passed a per-method cache variable. This would also allow the lookup<br class="">function to be shared between classes.</blockquote></div></blockquote></div><br class=""><div class=""><div class="">Hmm... I thought the local method offset table size could be statically knowable because it will only be accesd for methods that were publicly available at build time, based on the sorted method index.</div></div></div></div></blockquote><div class=""><br class=""></div>Sure, I mean, you can pick a table size that's sufficient for all the offsets that will be passed. That would save a few instructions at call sites, at the cost of requiring the resolvers to be per-class.</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class="">We could simplify the method resolution API with a single exported symbol per-class (maybe that's what you're getting at):</div><div class=""><br class=""></div><div class="">method_entry = resolveMethodAddress_ForAClass(isa, method_index, &vtable_offset)</div></div></div></div></blockquote><div class=""><br class=""></div>Right, this is what I was thinking.</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">The problem with that is the client-side code can’t hoist and combine the method offset lookup anymore.</div></div></div></blockquote><div class=""><br class=""></div>Why not? vtable_offset is basically an opaque cache here. Sure, technically the call isn't readnone anymore, but it's an innocuous violation like adding memoization to sin().</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Or is there some finer-grained hoisting you're imagining than the entire call?</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">John.</div></div></blockquote></div><br class=""><div class="">I was briefly over-thinking the problem… we could hoist the part that wasn’t dependent on the `isa`. That’s probably not important, and if it were, we could still hoist the cache lookup.</div><div class=""><br class=""></div><div class="">This option does seem to have the lowest immediate ABI cost (one symbol per class) with a tremendous amount of flexibility for optimizing both the dispatch code and the metadata representation.</div><div class=""><br class=""></div><div class="">-Andy</div></body></html>