Don't over-optimize final methods. It is only valid to resolve a final method to a specific implementing function when that function resides in the same parcel as the invocant. A ancestor class in another parcel has the option of adding or removing an implementation, so the descendant class cannot know for sure what function it should resolve to.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/3c71bc73 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/3c71bc73 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/3c71bc73 Branch: refs/heads/master Commit: 3c71bc735463cd58a831c515baa7301f5234038d Parents: 5103537 Author: Marvin Humphrey <[email protected]> Authored: Wed May 20 16:40:56 2015 -0700 Committer: Marvin Humphrey <[email protected]> Committed: Wed May 27 15:40:38 2015 -0700 ---------------------------------------------------------------------- compiler/src/CFCBindMethod.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3c71bc73/compiler/src/CFCBindMethod.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCBindMethod.c b/compiler/src/CFCBindMethod.c index 567812b..925f481 100644 --- a/compiler/src/CFCBindMethod.c +++ b/compiler/src/CFCBindMethod.c @@ -39,7 +39,7 @@ S_method_def(CFCMethod *method, CFCClass *klass, int optimized_final_meth); * directly, since this method may not be overridden. */ static char* -S_final_method_def(CFCMethod *method, CFCClass *klass) { +S_optimized_final_method_def(CFCMethod *method, CFCClass *klass) { return S_method_def(method, klass, true); } @@ -52,12 +52,20 @@ S_virtual_method_def(CFCMethod *method, CFCClass *klass) { char* CFCBindMeth_method_def(CFCMethod *method, CFCClass *klass) { + // If the method is final and the class where it is declared final is in + // the same parcel as the invocant, we can optimize the call by resolving + // to the implementing function directly. if (CFCMethod_final(method)) { - return S_final_method_def(method, klass); - } - else { - return S_virtual_method_def(method, klass); + CFCClass *ancestor = klass; + while (ancestor && !CFCMethod_is_fresh(method, ancestor)) { + ancestor = CFCClass_get_parent(ancestor); + } + if (CFCClass_get_parcel(ancestor) == CFCClass_get_parcel(klass)) { + return S_optimized_final_method_def(method, klass); + } } + + return S_virtual_method_def(method, klass); } static char*
