JavaLookup: make Java-to-Java lookup returning a trampoline when method is not found.
The trampoline in turn throws `NoSuchMethodError` or `AbstractMethodError`. This
way, there's no need to detect Java-to-Java send in JavaObject>>doesNotUnderstand:
to correctly handle these (rare) cases (as done in commit e546e1df7a01)
--- a/JavaLookup.st Tue Mar 22 23:42:40 2016 +0000
+++ b/JavaLookup.st Wed Mar 23 10:07:43 2016 +0000
@@ -37,7 +37,7 @@
Lookup subclass:#J2J
instanceVariableNames:''
- classVariableNames:''
+ classVariableNames:'NoSuchMethodErrorSelector AbstractMethodErrorSelectors'
poolDictionaries:''
privateIn:JavaLookup
!
@@ -256,6 +256,54 @@
"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)
+
+ 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
@@ -268,30 +316,41 @@
| method superMethod |
method := super lookupMethodForSelector: selector directedTo: initialSearchClass.
- method isNil ifTrue:[ ^ nil ].
-
- superMethod := super lookupMethodForSelector: selector directedTo: method mclass superclass.
- [ superMethod notNil ] whileTrue:[
- (method overrides: superMethod) ifFalse:[
- method := superMethod
+ method notNil ifTrue:[
+ superMethod := super lookupMethodForSelector: selector directedTo: method mclass superclass.
+ [ superMethod notNil ] whileTrue:[
+ (method overrides: superMethod) ifFalse:[
+ method := superMethod
+ ].
+ superMethod := super lookupMethodForSelector: selector directedTo: superMethod mclass superclass.
].
- superMethod := super lookupMethodForSelector: selector directedTo: superMethod mclass superclass.
].
-
- ^method
+ ^ method
"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>"
! !
!JavaLookup::J2S methodsFor:'lookup'!
@@ -1131,3 +1190,4 @@
JavaLookup initialize!
+JavaLookup::J2J initialize!
--- a/JavaObject.st Tue Mar 22 23:42:40 2016 +0000
+++ b/JavaObject.st Wed Mar 23 10:07:43 2016 +0000
@@ -333,23 +333,6 @@
"/ 3 - context of method that sent the not understood message
"/ Hence the `thisContext sender sender below.
sender := thisContext sender sender.
- "/ When a sending context is a JavaContext, then throw NoSuchMethodError/AbstractMethodError
- "/ This may happen if classfile was changes meanwhile so it's now
- "/ incompatible
- sender class == JavaContext ifTrue:[
- "/ Sigh, must check whether the instruction was INVOKEINTERFACE which
- "/ throws AbstractMethodError rather than NoSuchMethodError. Arghh...
-
- | error |
-
- (sender method byteCode at: sender pc - 1) == 185 ifTrue:[
- error := 'java.lang.AbstractMethodError'
- ] ifFalse:[
- error := 'java.lang.NoSuchMethodError'
- ].
- JavaVM throwExceptionClassName: error withMessage: ('No method %1 in class %2' bindWith: aMessage selector with: self class javaName).
- ^ nil
- ].
didNotUnderstood := false.
retval := self class perform: aMessage onReceiver: self from: sender ifNotFound: [ didNotUnderstood := true ].
^ didNotUnderstood ifTrue:[
@@ -361,7 +344,7 @@
"Modified: / 16-11-1998 / 16:50:56 / cg"
"Modified: / 19-09-2011 / 23:43:56 / Jan Kurs <kursjan@fit.cvut.cz>"
"Modified: / 01-01-2012 / 19:49:35 / kursjan <kursjan@fit.cvut.cz>"
- "Modified: / 21-03-2016 / 01:24:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 23-03-2016 / 10:01:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaObject methodsFor:'printing & storing'!
--- a/JavaVM.st Tue Mar 22 23:42:40 2016 +0000
+++ b/JavaVM.st Wed Mar 23 10:07:43 2016 +0000
@@ -3437,13 +3437,6 @@
!JavaVM class methodsFor:'helpers - exceptions'!
-throwAbstractMethodError
- ^ self throwExceptionClassName: 'java.lang.AbstractMethodError'
- withMessage: 'resolving a method ref failed'.
-
- "Created: / 11-04-2011 / 20:32:53 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
-!
-
throwArrayIndexOutOfBoundsException: badIndex
| exClass ex |
@@ -3888,20 +3881,6 @@
"Created: / 13-04-2011 / 12:16:36 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
-throwNoSuchMethodError
- ^ self throwNoSuchMethodError: 'looking up a method failed'.
-
- "Created: / 11-04-2011 / 20:33:19 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
- "Modified: / 21-03-2016 / 01:11:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-throwNoSuchMethodError: message
- ^ self throwExceptionClassName: 'java.lang.NoSuchMethodError'
- withMessage: message
-
- "Created: / 21-03-2016 / 01:11:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
throwNullPointerException
self throwNullPointerException:'null pointer'
@@ -3988,6 +3967,203 @@
"Created: / 20-07-2012 / 19:15:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
+!JavaVM class methodsFor:'helpers - exceptions - trampolines'!
+
+throwAbstractMethodError
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 11-04-2011 / 20:32:53 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+ "Modified: / 23-03-2016 / 09:59:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:32:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:33:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11 _: a12
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:34:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11 _: a12 _: a13
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:34:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11 _: a12 _: a13 _: a14
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:34:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwAbstractMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11 _: a12 _: a13 _: a14 _: a15
+ ^ JavaVM throwExceptionClassName: 'java.lang.AbstractMethodError' withMessage: 'trying to execute abstract method or (missing) interface method'.
+
+ "Created: / 23-03-2016 / 09:34:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 11-04-2011 / 20:33:19 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+ "Modified: / 23-03-2016 / 09:58:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 21-03-2016 / 01:11:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 23-03-2016 / 09:58:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:35:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:35:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:35:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:35:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:35:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:35:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:35:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:35:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:36:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:36:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11 _: a12
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:36:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11 _: a12 _: a13
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:36:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11 _: a12 _: a13 _: a14
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:36:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+throwNoSuchMethodError: a1 _: a2 _: a3 _: a4 _: a5 _: a6 _: a7 _: a8 _: a9 _: a10 _: a11 _: a12 _: a13 _: a14 _: a15
+ ^ JavaVM throwExceptionClassName: 'java.lang.NoSuchMethodError' withMessage: 'method not found'
+
+ "Created: / 23-03-2016 / 09:36:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
!JavaVM class methodsFor:'helpers - io'!
commonOpenStreamUsing: aBlock