Bug 1: Evaluate this:
[codesyntax lang=”smalltalk”]
[ self halt. 3 + 4 ] ensure: [ Transcript show: 'hello world'].
[/codesyntax]
Jump into the debugger and press hop until you are in the method #ensure:.
Now evaluate “Smalltalk unusedMemory” anywhere and press “Jump” in the debugger => VM crash. The global compact may of course be triggered by the system itself. If this happens you get “random” crashes.
Explanation: The global compact also clears the code cache. If the debugged process is being activated (pressing “skip/jump”) the compiled methods must be re-jitted. When the first block in the above method is being invoked the method is not yet a “debuggable” method, so the jitted representation also is not translated as debuggable, so the return address on the stack expects a normally jitted compiled method. If the debugger is opened on the “self halt” the compiled method is converted into a debuggable compiled method. The debugger now does not correctly handle this case and is modifying the debuggable flag for methods on the stack, where the return address has not been adjusted. Returning from such a method causes a general protection fault.
Fix:
[codesyntax lang=”smalltalk”]
Debugger>>#cacheInfo:for: cacheInfo: methodInfo for: aMethod "Private - cache the compiled method info for later use." | cache | ( aMethod isCompiledMethod and: [ methodInfo method ~~ aMethod ] ) ifTrue: [ methodInfo method classField isNil ifTrue: [ methodInfo method info: aMethod info.]. methodInfo flushICTables]. cache := self getMethodInfoCache. self maxInfoCacheSize <= cache size ifTrue: [ self resetInfoCache. cache := self getMethodInfoCache]. cache at: aMethod put: methodInfo
[/codesyntax]