JavaLookup: Make JavaLookup not to use JavaClass>>lookupMethodFor:
authorJan Vrany <jan.vrany@fit.cvut.cz>
Mon, 28 Mar 2016 00:09:52 +0100
changeset 3554 1e2d0859a20c
parent 3553 5329fb7027e8
child 3555 47da2d42a016
JavaLookup: Make JavaLookup not to use JavaClass>>lookupMethodFor: Instead, implement method lookup as defined in JVM spec in JavaLookuo::JVM>>lookupMethodForSelector:directedTo:
JavaLookup.st
--- a/JavaLookup.st	Sun Mar 27 22:29:04 2016 +0100
+++ b/JavaLookup.st	Mon Mar 28 00:09:52 2016 +0100
@@ -35,21 +35,28 @@
 	category:'Languages-Java-Interop'
 !
 
-Lookup subclass:#J2J
+Lookup subclass:#JVM
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:JavaLookup
+!
+
+JavaLookup::JVM subclass:#J2S
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:JavaLookup
+!
+
+JavaLookup::JVM subclass:#J2J
 	instanceVariableNames:''
 	classVariableNames:'NoSuchMethodErrorSelector AbstractMethodErrorSelectors'
 	poolDictionaries:''
 	privateIn:JavaLookup
 !
 
-Lookup subclass:#J2S
-	instanceVariableNames:''
-	classVariableNames:''
-	poolDictionaries:''
-	privateIn:JavaLookup
-!
-
-Lookup subclass:#S2J
+JavaLookup::JVM subclass:#S2J
 	instanceVariableNames:''
 	classVariableNames:''
 	poolDictionaries:''
@@ -256,101 +263,44 @@
     "Modified: / 22-03-2016 / 22:44:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
-!JavaLookup::J2J class methodsFor:'initialization'!
 
-initialize
-    "Invoked at system start or when the class is dynamically loaded."
-
-    "/ please change as required (and remove this comment)
+!JavaLookup::JVM methodsFor:'lookup'!
 
-    NoSuchMethodErrorSelector := #(
-            " 0" #'throwNoSuchMethodError'
-            " 1" #'throwNoSuchMethodError_:'
-            " 2" #'throwNoSuchMethodError_:_:'
-            " 3" #'throwNoSuchMethodError_:_:_:'
-            " 4" #'throwNoSuchMethodError_:_:_:_:'
-            " 5" #'throwNoSuchMethodError_:_:_:_:_:'
-            " 6" #'throwNoSuchMethodError_:_:_:_:_:_:'
-            " 7" #'throwNoSuchMethodError_:_:_:_:_:_:_:'
-            " 8" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:'
-            " 9" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:'
-            "10" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:'
-            "11" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:'
-            "12" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:_:'
-            "13" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:'
-            "14" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:_:'
-            "15" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:'
-    ).
+lookupMethodForSelector: selector directedTo: c
+    "This method performs standard Java lookup as required JVM 8 spec, 6.5 invokevirtual.
+     NOTE: This method only handles Java method, i.e., it never returns a Smalltak
+     (or other language's) extension method."
+
+    | m s |
+
+    "Let C be the class of objectref. The actual method to be invoked is selected by the 
+     following lookup procedure:
 
-    AbstractMethodErrorSelectors := #(
-            " 0" #'throwAbstractMethodError'
-            " 1" #'throwAbstractMethodError_:'
-            " 2" #'throwAbstractMethodError_:_:'
-            " 3" #'throwAbstractMethodError_:_:_:'
-            " 4" #'throwAbstractMethodError_:_:_:_:'
-            " 5" #'throwAbstractMethodError_:_:_:_:_:'
-            " 6" #'throwAbstractMethodError_:_:_:_:_:_:'
-            " 7" #'throwAbstractMethodError_:_:_:_:_:_:_:'
-            " 8" #'throwAbstractMethodError_:_:_:_:_:_:_:_:'
-            " 9" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:'
-            "10" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:'
-            "11" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:'
-            "12" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:_:'
-            "13" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:'
-            "14" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:_:'
-            "15" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:'
-    ).
+     1. If C contains a declaration for an instance method m that
+        overrides (§5.4.5) the resolved method, then m is the method
+        to be invoked.
+     2. Otherwise, if C has a superclass, a search for a declaration
+        of an instance method that overrides the resolved method
+        is performed, starting with the direct superclass of C and
+        continuing with the direct superclass of that class, and so forth,
+        until an overriding method is found or no further superclasses
+        exist. If an overriding method is found, it is the method to be
+        invoked."
 
-    "Modified: / 23-03-2016 / 09:41:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-! !
-
-!JavaLookup::J2J methodsFor:'lookup'!
-
-lookupMethodForSelector: selector directedTo: initialSearchClass
-    "This method performs standard Java lookup as required JVM spec. See 
-        - JVM spec, 5.4.2.1 Method overriding
-        - JVM spec, 6.4 invokevirtual
-
-     This is hacky because of those stupid package-private methods. Sigh."
-
-    | method superMethod |
-
-    method := super lookupMethodForSelector: selector directedTo: initialSearchClass.
-    method notNil ifTrue:[
-        superMethod := super lookupMethodForSelector: selector directedTo: method mclass superclass.
-        [ superMethod notNil ] whileTrue:[
-            (method overrides: superMethod) ifFalse:[
-                method := superMethod
+    m := super lookupMethodForSelector: selector directedTo: c.
+    m isJavaMethod ifTrue:[
+        m notNil ifTrue:[
+            [ (s := super lookupMethodForSelector: selector directedTo: m mclass superclass) notNil ] whileTrue:[
+                (m overrides: s) ifFalse:[
+                    m := s
+                ].
             ].
-            superMethod := super lookupMethodForSelector: selector directedTo: superMethod mclass superclass.
         ].
     ].
-    ^ method
+    ^ m
 
     "Created: / 05-07-2012 / 11:06:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 23-03-2016 / 09:44:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-lookupMethodForSelector:selector directedTo:initialSearchClass for:aReceiver withArguments:argArrayOrNil from:sendingContext ilc: ilcCache
-    | method |
-    method := self lookupMethodForSelector: selector directedTo: initialSearchClass.
-    "/ No method found. Return a trampoline that will throw NoSuchMethodError or AbstractMethodError
-    "/ (for INVOKEINTERFACE)
-    method isNil ifTrue:[ 
-        "/ This is a hacky check whether the failing instruction is INVOKEINTERFACE or not
-        (sendingContext method byteCode at: sendingContext pc - 1) == 185 ifTrue:[ 
-            method := JavaVM class >> (AbstractMethodErrorSelectors at: argArrayOrNil size + 1)
-        ] ifFalse:[ 
-            method := JavaVM class >> (NoSuchMethodErrorSelector at: argArrayOrNil size + 1)
-        ].
-    ].
-    ilcCache notNil ifTrue:[
-        ilcCache bindTo: method forClass: initialSearchClass.
-    ].
-    ^ method.
-
-    "Created: / 22-03-2016 / 22:43:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 23-03-2016 / 09:57:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (comment): / 27-03-2016 / 23:45:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !JavaLookup::J2S methodsFor:'lookup'!
@@ -451,6 +401,80 @@
     "Modified: / 24-02-2012 / 20:36:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!JavaLookup::J2J class methodsFor:'initialization'!
+
+initialize
+    "Invoked at system start or when the class is dynamically loaded."
+
+    "/ please change as required (and remove this comment)
+
+    NoSuchMethodErrorSelector := #(
+            " 0" #'throwNoSuchMethodError'
+            " 1" #'throwNoSuchMethodError_:'
+            " 2" #'throwNoSuchMethodError_:_:'
+            " 3" #'throwNoSuchMethodError_:_:_:'
+            " 4" #'throwNoSuchMethodError_:_:_:_:'
+            " 5" #'throwNoSuchMethodError_:_:_:_:_:'
+            " 6" #'throwNoSuchMethodError_:_:_:_:_:_:'
+            " 7" #'throwNoSuchMethodError_:_:_:_:_:_:_:'
+            " 8" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:'
+            " 9" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:'
+            "10" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:'
+            "11" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:'
+            "12" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:_:'
+            "13" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:'
+            "14" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:_:'
+            "15" #'throwNoSuchMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:'
+    ).
+
+    AbstractMethodErrorSelectors := #(
+            " 0" #'throwAbstractMethodError'
+            " 1" #'throwAbstractMethodError_:'
+            " 2" #'throwAbstractMethodError_:_:'
+            " 3" #'throwAbstractMethodError_:_:_:'
+            " 4" #'throwAbstractMethodError_:_:_:_:'
+            " 5" #'throwAbstractMethodError_:_:_:_:_:'
+            " 6" #'throwAbstractMethodError_:_:_:_:_:_:'
+            " 7" #'throwAbstractMethodError_:_:_:_:_:_:_:'
+            " 8" #'throwAbstractMethodError_:_:_:_:_:_:_:_:'
+            " 9" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:'
+            "10" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:'
+            "11" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:'
+            "12" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:_:'
+            "13" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:'
+            "14" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:_:'
+            "15" #'throwAbstractMethodError_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:'
+    ).
+
+    "Modified: / 23-03-2016 / 09:41:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!JavaLookup::J2J methodsFor:'lookup'!
+
+lookupMethodForSelector:selector directedTo:initialSearchClass for:aReceiver withArguments:argArrayOrNil from:sendingContext ilc: ilcCache
+    | method |
+
+    method := self lookupMethodForSelector: selector directedTo: initialSearchClass.
+    "/ No method found. Return a trampoline that will throw NoSuchMethodError or AbstractMethodError
+    "/ (for INVOKEINTERFACE)
+    method isNil ifTrue:[ 
+        "/ This is a hacky check whether the failing instruction is INVOKEINTERFACE or not
+        (sendingContext method byteCode at: sendingContext pc - 1) == 185 ifTrue:[ 
+            method := JavaVM class >> (AbstractMethodErrorSelectors at: argArrayOrNil size + 1)
+        ] ifFalse:[ 
+            method := JavaVM class >> (NoSuchMethodErrorSelector at: argArrayOrNil size + 1)
+        ].
+    ].
+    ilcCache notNil ifTrue:[
+        ilcCache bindTo: method forClass: initialSearchClass.
+    ].
+    ^ method.
+
+    "Created: / 22-03-2016 / 22:43:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 23-03-2016 / 09:57:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (format): / 28-03-2016 / 00:00:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !JavaLookup::S2J methodsFor:'lookup'!
 
 lookupMethodForSelector: selector directedTo: initialSearchClass for: receiver withArguments: argArrayOrNil from: sendingContext ilc: ilc 
@@ -479,7 +503,7 @@
         ].
     ] ifFalse:[ 
         "/ Lookup instance method
-        method := receiver class lookupMethodFor: selector.
+        method := self lookupMethodForSelector: selector directedTo: receiver class.
         method notNil ifTrue:[ ^ method ].
     ].
 
@@ -543,7 +567,7 @@
     "Modified (comment): / 02-01-2012 / 10:35:25 / kursjan <kursjan@fit.cvut.cz>"
     "Modified: / 18-11-2012 / 18:17:28 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
     "Modified: / 16-12-2012 / 13:59:55 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
-    "Modified: / 23-03-2016 / 19:37:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 27-03-2016 / 23:57:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 lookupMethodsForSelector: selector in: initialSearchClass static: static