Preserve method identity when updating class methods (when possible).
Upon class update, method identity is preserved when possoble. As a consequence,
when method is bytecode interpreted, this allows for installing new bytecode
and restarting existing context with new code.
--- a/JavaClassReloader.st Fri Apr 19 00:01:10 2013 +0200
+++ b/JavaClassReloader.st Fri Apr 19 00:29:56 2013 +0200
@@ -270,12 +270,29 @@
simply copy methods and other info from new class to old one.
References must be flushed anyway!!"
+ | oldMethods newMethods |
+ oldMethods := oldClass methodDictionary.
+ newMethods := newClass methodDictionary copy.
+
+ newMethods keysDo:[:selector|
+ | oldM newM |
- oldClass setMethodDictionary: newClass methodDictionary.
+ oldM := oldMethods at: selector ifAbsent:[nil].
+ oldM notNil ifTrue:[
+ newM := newMethods at: selector.
+ (oldM canBeUpdatedFrom: newM) ifTrue:[
+ oldM updateFrom: newM.
+ newMethods at: selector put: oldM.
+ ]
+ ]
+ ].
+ newMethods do:[:m|m setJavaClass: oldClass].
+ oldClass setMethodDictionary: newMethods.
oldClass setConstantPool: newClass constantPool.
"Created: / 16-12-2012 / 17:36:52 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+ "Modified: / 19-04-2013 / 00:24:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaClassReloader::SingleClassReloader methodsFor:'reloading'!
--- a/JavaMethod.st Fri Apr 19 00:01:10 2013 +0200
+++ b/JavaMethod.st Fri Apr 19 00:29:56 2013 +0200
@@ -1385,6 +1385,17 @@
^javaClass programmingLanguage
"Created: / 26-10-2010 / 23:42:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+updateFrom: anotherMethod
+
+ self class allInstVarNames keysAndValuesDo:[:index :name|
+ (#(#'code*' #'javaClass') includes: name) ifFalse:[
+ self instVarAt: index put: (anotherMethod instVarAt: index)
+ ]
+ ]
+
+ "Created: / 19-04-2013 / 00:08:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaMethod methodsFor:'debugging'!
@@ -2144,7 +2155,17 @@
to just to take anotherMethod's bytecode. Used to implement fix & restart
workflow"
- ^false
+ "/ Allready jitted method cannot be updated - no way to restart existing context into
+ "/ new code
+ self code notNil ifTrue:[ ^ false ].
+
+ "/ Args and their types must match
+ selector ~~ anotherMethod selector ifTrue: [ ^ false ].
+
+ "/ max stack depth must be smaller or equal of the current
+ (self numVars + self stackSize) < (anotherMethod numVars + anotherMethod stackSize) ifTrue:[ ^ false ].
+
+ ^true
"Created: / 18-04-2013 / 23:43:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!