From dc300409c3c675db3ba3d7beaddb65939e5d489c Mon Sep 17 00:00:00 2001 From: Theo Date: Thu, 3 Dec 2020 16:24:36 +0100 Subject: [PATCH 01/10] Pushing in the middle of blah --- .../VMMakerTests/VMBlockTest.class.st | 291 +++++++++--------- 1 file changed, 147 insertions(+), 144 deletions(-) diff --git a/smalltalksrc/VMMakerTests/VMBlockTest.class.st b/smalltalksrc/VMMakerTests/VMBlockTest.class.st index c56d22fe0d1..d0cb0f3deeb 100644 --- a/smalltalksrc/VMMakerTests/VMBlockTest.class.st +++ b/smalltalksrc/VMMakerTests/VMBlockTest.class.st @@ -15,9 +15,64 @@ VMBlockTest >> anEmptyMethod [ { #category : #'as yet unclassified' } VMBlockTest >> evaluatingABlock [ + ^[42] value +] + +{ #category : #'as yet unclassified' } +VMBlockTest >> evaluatingABlockWithLocalBlockVariable [ + + ^ [ + | aVariable | + aVariable := 42. + aVariable ] value +] + +{ #category : #'as yet unclassified' } +VMBlockTest >> evaluatingABlockWithLocalMethodVariableAssignedInTheBlock [ + + | aVariable | + ^ [ + aVariable := 42. + aVariable ] value +] + +{ #category : #'as yet unclassified' } +VMBlockTest >> evaluatingABlockWithLocalMethodVariableRead [ + + | aVariable | + aVariable := 42. + ^ [ aVariable ] value +] + +{ #category : #'as yet unclassified' } +VMBlockTest >> evaluatingABlockWithNonLocalReturn [ + [^1] value ] +{ #category : #testing } +VMBlockTest >> executeMethod: aMethodToTest [ + + | methodReturning initialMethod | + + methodReturning := self createMethodOopFromPharoMethod: + aMethodToTest. + + initialMethod := self createMethodOopFromPharoMethod: + self class >> #anEmptyMethod. + + "We want to avoid baseFrameReturn (base frame initialisation)" + stackBuilder addNewFrame method: initialMethod. + stackBuilder addNewFrame + method: methodReturning; + receiver: memory trueObject. + stackBuilder buildStack. + + interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodReturning). + interpreter interpretWhile: [ interpreter method = methodReturning ]. + +] + { #category : #helpers } VMBlockTest >> installBlockClosureClass [ | aClass | @@ -61,190 +116,151 @@ VMBlockTest >> methodWithLocalReturningABlock [ ^ [ a ] ] +{ #category : #running } +VMBlockTest >> setUp [ + + super setUp. + self installBlockClosureClass. +] + { #category : #testing } VMBlockTest >> testCreatingABlockClosureShouldCopyUsedMethodVariable [ - | methodReturning initialMethod | - - initialMethod := self createMethodOopFromPharoMethod: - self class >> #anEmptyMethod. - methodReturning := self createMethodOopFromPharoMethod: - self class >> #methodWithLocalReturningABlock. - - self installBlockClosureClass. - "We want to avoid baseFrameReturn (base frame initialisation)" - stackBuilder addNewFrame method: initialMethod. - stackBuilder addNewFrame - method: methodReturning; - receiver: memory trueObject. - stackBuilder buildStack. - - interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodReturning). - interpreter interpretWhile: [ interpreter method = methodReturning ]. + | methodToTest | + methodToTest := self class >> #methodWithLocalReturningABlock. + self executeMethod: methodToTest. "We assign 1 to the local variable of the method, see methodWithLocalReturningABlock" self - assert: (memory fetchPointer: ClosureFirstCopiedValueIndex ofObject: interpreter stackTop) equals: (memory integerObjectOf: 1). - + assert: (memory + fetchPointer: ClosureFirstCopiedValueIndex + ofObject: interpreter stackTop) + equals: (memory integerObjectOf: 1) ] { #category : #testing } VMBlockTest >> testCreatingABlockClosureShouldHaveCorrectPC [ - | methodReturning initialMethod | - - initialMethod := self createMethodOopFromPharoMethod: - self class >> #anEmptyMethod. - methodReturning := self createMethodOopFromPharoMethod: - self class >> #methodReturningABlock. + | methodToTest | + methodToTest := self class >> #methodReturningABlock. - self installBlockClosureClass. - "We want to avoid baseFrameReturn (base frame initialisation)" - stackBuilder addNewFrame method: initialMethod. - stackBuilder addNewFrame - method: methodReturning; - receiver: memory trueObject. - stackBuilder buildStack. - - interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodReturning). - interpreter interpretWhile: [ interpreter method = methodReturning ]. + self executeMethod: methodToTest. - "hard code for now should be modified" + self flag:#'hard code for now should be modified'. self - assert: (memory fetchPointer: ClosureStartPCIndex ofObject: interpreter stackTop) equals: (memory integerObjectOf: 29). - + assert: (memory + fetchPointer: ClosureStartPCIndex + ofObject: interpreter stackTop) + equals: (memory integerObjectOf: 29) ] { #category : #testing } VMBlockTest >> testCreatingABlockClosureShouldHaveOuterContextObject [ - | methodReturning initialMethod | + | methodToTest | + methodToTest := self class >> #methodReturningABlock. - initialMethod := self createMethodOopFromPharoMethod: - self class >> #anEmptyMethod. - methodReturning := self createMethodOopFromPharoMethod: - self class >> #methodReturningABlock. - - self installBlockClosureClass. - "We want to avoid baseFrameReturn (base frame initialisation)" - stackBuilder addNewFrame method: initialMethod. - stackBuilder addNewFrame - method: methodReturning; - receiver: memory trueObject. - stackBuilder buildStack. - - interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodReturning). - - interpreter interpretWhile: [ interpreter method = methodReturning ]. + self executeMethod: methodToTest. "Currently fails because the stack frame is not overriden. So the interpreter considers it's still married even thought the stack frame is already dead" - self - assert: (interpreter isWidowedContext: (memory outerContextOf: interpreter stackTop)) - + self assert: (interpreter isWidowedContext: + (memory outerContextOf: interpreter stackTop)) ] { #category : #'as yet unclassified' } VMBlockTest >> testCreatingABlockInsideABlockClosureShouldCopyUsedBlockVariable [ - | methodReturning initialMethod | - - initialMethod := self createMethodOopFromPharoMethod: - self class >> #anEmptyMethod. - methodReturning := self createMethodOopFromPharoMethod: - self class >> #methodReturningABlockInsideABlockWithLocal. + | methodToTest | + methodToTest := self class + >> #methodReturningABlockInsideABlockWithLocal. - self installBlockClosureClass. - "We want to avoid baseFrameReturn (base frame initialisation)" - stackBuilder addNewFrame method: initialMethod. - stackBuilder addNewFrame - method: methodReturning; - receiver: memory trueObject. - stackBuilder buildStack. - - interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodReturning). - interpreter interpretWhile: [ interpreter method = methodReturning ]. + self executeMethod: methodToTest. "We assign 2 to the local variable of the block, see methodReturningABlockInsideABlock" self - assert: (memory fetchPointer: ClosureFirstCopiedValueIndex ofObject: interpreter stackTop) equals: (memory integerObjectOf: 2). - + assert: (memory + fetchPointer: ClosureFirstCopiedValueIndex + ofObject: interpreter stackTop) + equals: (memory integerObjectOf: 2) ] { #category : #testing } VMBlockTest >> testCreatingABlockWithTwoArgumentsClosureShouldHaveTwoArguments [ - | methodReturning initialMethod | + | methodToTest | + methodToTest := self class >> #methodReturningABlockWithTwoArguments. - initialMethod := self createMethodOopFromPharoMethod: - self class >> #anEmptyMethod. - methodReturning := self createMethodOopFromPharoMethod: - self class >> #methodReturningABlockWithTwoArguments. - - self installBlockClosureClass. - "We want to avoid baseFrameReturn (base frame initialisation)" - stackBuilder addNewFrame method: initialMethod. - stackBuilder addNewFrame - method: methodReturning; - receiver: memory trueObject. - stackBuilder buildStack. - - interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodReturning). - interpreter interpretWhile: [ interpreter method = methodReturning ]. + self executeMethod: methodToTest. self - assert: (memory fetchPointer: ClosureNumArgsIndex ofObject: interpreter stackTop) equals: (memory integerObjectOf: 2). - + assert: (memory + fetchPointer: ClosureNumArgsIndex + ofObject: interpreter stackTop) + equals: (memory integerObjectOf: 2) ] { #category : #testing } VMBlockTest >> testCreatingABlockWithoutArgumentsClosureShouldHaveNoArgument [ - | methodReturning initialMethod | - - initialMethod := self createMethodOopFromPharoMethod: - self class >> #anEmptyMethod. - methodReturning := self createMethodOopFromPharoMethod: - self class >> #methodReturningABlock. + | methodToTest | + methodToTest := self class >> #methodReturningABlock. - self installBlockClosureClass. - "We want to avoid baseFrameReturn (base frame initialisation)" - stackBuilder addNewFrame method: initialMethod. - stackBuilder addNewFrame - method: methodReturning; - receiver: memory trueObject. - stackBuilder buildStack. - - interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodReturning). - interpreter interpretWhile: [ interpreter method = methodReturning ]. + self executeMethod: methodToTest. + self + assert: (memory + fetchPointer: ClosureNumArgsIndex + ofObject: interpreter stackTop) + equals: (memory integerObjectOf: 0) +] + +{ #category : #'as yet unclassified' } +VMBlockTest >> testEvaluatingABlock [ + + | methodToTest | + methodToTest := self class >> #evaluatingABlock. + + self executeMethod: methodToTest. self - assert: (memory fetchPointer: ClosureNumArgsIndex ofObject: interpreter stackTop) equals: (memory integerObjectOf: 0). + assert: interpreter stackTop + equals: (memory integerObjectOf: 42) +] + +{ #category : #'as yet unclassified' } +VMBlockTest >> testEvaluatingABlockWithLocalBlockVariable [ + | methodToTest | + methodToTest := self class >> #evaluatingABlockWithLocalBlockVariable. + + self executeMethod: methodToTest. + + self + assert: interpreter stackTop + equals: (memory integerObjectOf: 42) ] { #category : #'as yet unclassified' } -VMBlockTest >> testEvaluatingABlock [ +VMBlockTest >> testEvaluatingABlockWithLocalMethodVariable [ - | methodReturning initialMethod | - - initialMethod := self createMethodOopFromPharoMethod: - self class >> #anEmptyMethod. - methodReturning := self createMethodOopFromPharoMethod: - self class >> #evaluatingABlock. + | methodToTest | + methodToTest := self class >> #evaluatingABlockWithLocalMethodVariableAssignedInTheBlock. - self installBlockClosureClass. - "We want to avoid baseFrameReturn (base frame initialisation)" - stackBuilder addNewFrame method: initialMethod. - stackBuilder addNewFrame - method: methodReturning; - receiver: memory trueObject. - stackBuilder buildStack. + self executeMethod: methodToTest. - interpreter instructionPointer: - (methodBuilder bytecodeAt: 0 forMethod: methodReturning). - interpreter interpretWhile: [ interpreter method = methodReturning ]. + self + assert: interpreter stackTop + equals: (memory integerObjectOf: 42) +] + +{ #category : #'as yet unclassified' } +VMBlockTest >> testEvaluatingABlockWithNonLocalReturn [ + + | methodToTest | + methodToTest := self class >> #evaluatingABlockWithNonLocalReturn. + + self executeMethod: methodToTest. self assert: true ] @@ -252,23 +268,10 @@ VMBlockTest >> testEvaluatingABlock [ { #category : #testing } VMBlockTest >> testPushClosureBytecodePushesClosure [ - | methodReturning initialMethod | - - initialMethod := self createMethodOopFromPharoMethod: - self class >> #anEmptyMethod. - methodReturning := self createMethodOopFromPharoMethod: - self class >> #methodReturningABlock. - - self installBlockClosureClass. - "We want to avoid baseFrameReturn (base frame initialisation)" - stackBuilder addNewFrame method: initialMethod. - stackBuilder addNewFrame - method: methodReturning; - receiver: memory trueObject. - stackBuilder buildStack. + |methodToTest| + methodToTest := self class >> #methodReturningABlock. - interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodReturning). - interpreter interpretWhile: [ interpreter method = methodReturning ]. + self executeMethod: methodToTest. self assert: (memory fetchClassOf: interpreter stackTop) From 74d163ddafd2995bb2fce173056c8b17521f7d17 Mon Sep 17 00:00:00 2001 From: Theo Date: Thu, 17 Dec 2020 15:41:22 +0100 Subject: [PATCH 02/10] First commit of branch VMInspector --- .../VMMaker-Tools/SpurByteLayout.class.st | 43 +++ smalltalksrc/VMMaker-Tools/SpurClass.class.st | 113 +++++++ .../SpurCompiledMethodLayout.class.st | 11 + .../VMMaker-Tools/SpurEmptyLayout.class.st | 5 + .../VMMaker-Tools/SpurFileImage.class.st | 304 ++++++++++++++++++ .../VMMaker-Tools/SpurFixedLayout.class.st | 21 ++ .../VMMaker-Tools/SpurHiddenRoots.class.st | 36 +++ smalltalksrc/VMMaker-Tools/SpurImage.class.st | 110 +++++++ .../SpurImmediateLayout.class.st | 5 + .../VMMaker-Tools/SpurLayout.class.st | 141 ++++++++ .../VMMaker-Tools/SpurMethod.class.st | 55 ++++ .../SpurMethodDictionary.class.st | 35 ++ .../VMMaker-Tools/SpurObject.class.st | 281 ++++++++++++++++ .../VMMaker-Tools/SpurSimulatorImage.class.st | 73 +++++ .../VMMaker-Tools/SpurVariableLayout.class.st | 21 ++ ...riableWithInstanceVariablesLayout.class.st | 5 + .../VMBytecodeToIRMapping.class.st | 2 +- .../VMMaker-Tools/VMDebugger.class.st | 2 +- .../VMMaker-Tools/VMInspectorTest.class.st | 64 ++++ .../VMMachineCodeDebugger.class.st | 2 +- .../VMMachineCodeDebuggerInstruction.class.st | 2 +- .../VMMachineCodeDebuggerStackItem.class.st | 2 +- .../VMMethodBytecodeToIRMapping.class.st | 2 +- .../VMMaker-Tools/VMTFreeListNode.class.st | 2 +- .../VMTFreeListNodeEdge.class.st | 2 +- .../VMMaker-Tools/VMTFreeLists.class.st | 2 +- .../VMMaker-Tools/VMTFreeTreeNode.class.st | 2 +- .../VMTFreeTreeNodeEdge2.class.st | 2 +- .../VMMaker-Tools/VMTHiddenRoot.class.st | 2 +- .../VMMaker-Tools/VMTHiddenRootTable.class.st | 2 +- .../VMMaker-Tools/VMTStackFrame.class.st | 2 +- .../VMMakerTests/VMBlockTest.class.st | 269 ++++------------ 32 files changed, 1406 insertions(+), 214 deletions(-) create mode 100644 smalltalksrc/VMMaker-Tools/SpurByteLayout.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurClass.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurCompiledMethodLayout.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurEmptyLayout.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurFileImage.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurFixedLayout.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurHiddenRoots.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurImage.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurImmediateLayout.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurLayout.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurMethod.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurMethodDictionary.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurObject.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurVariableLayout.class.st create mode 100644 smalltalksrc/VMMaker-Tools/SpurVariableWithInstanceVariablesLayout.class.st create mode 100644 smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st diff --git a/smalltalksrc/VMMaker-Tools/SpurByteLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurByteLayout.class.st new file mode 100644 index 00000000000..558eb28cdd4 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurByteLayout.class.st @@ -0,0 +1,43 @@ +Class { + #name : #SpurByteLayout, + #superclass : #SpurLayout, + #category : #'VMMaker-Tools-Model' +} + +{ #category : #accessing } +SpurByteLayout >> asLocalByteArray [ + | localByteArray | + localByteArray := ByteArray new: self byteSize . + 1 to: localByteArray size do: [ :i | + localByteArray byteAt: i put: (self at: i). + ]. + ^ localByteArray +] + +{ #category : #accessing } +SpurByteLayout >> at: anInteger [ + + " ToDo: consider inst vars " + | slotIndex byteIndex | + slotIndex := (anInteger - 1) // self wordSize . + byteIndex := (anInteger - 1) % self wordSize . + ^ (self slotAt: slotIndex + 1) at: byteIndex + 1 +] + +{ #category : #accessing } +SpurByteLayout >> objectPrintOn: aStream [ + aStream nextPutAll: self object asLocalByteArray asString +] + +{ #category : #accessing } +SpurByteLayout >> slotAt: anInteger [ + + | bodyAddress | + self assert: anInteger > 0 description: 'Index must be greater than 0'. + self assert: self numberOfSlots >= anInteger description: 'Index Out of Bounds'. + + bodyAddress := self address + self headerSize + ((anInteger - 1) * self wordSize). + + ^ self memory copyFrom: bodyAddress to: bodyAddress + self wordSize + (0 - 1) + +] diff --git a/smalltalksrc/VMMaker-Tools/SpurClass.class.st b/smalltalksrc/VMMaker-Tools/SpurClass.class.st new file mode 100644 index 00000000000..7919bd3f6a7 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurClass.class.st @@ -0,0 +1,113 @@ +Class { + #name : #SpurClass, + #superclass : #SpurObject, + #category : #'VMMaker-Tools-Model' +} + +{ #category : #'accessing - instance variables' } +SpurClass >> allInstanceVariableNames [ + ^ (1 to: self numberOfSlots) collect: [ :index | self slotAt: index ] . +] + +{ #category : #'as yet unclassified' } +SpurClass >> classFormat [ + ^ self slotAt: self slotIndexForClassFormat +] + +{ #category : #accessing } +SpurClass >> className [ +"We assume this is a byteSymbol here" + ^ self image printByteSymbol: (self slotAt: self slotIndexForClassName) + + " ] on: Error + do: [ (self slotAt: self slotIndexForMetaclassSoleInstance ) asSpurClass className , ' class'] " + +] + +{ #category : #'gt-inspector-extension' } +SpurClass >> gtInspectorLayoutIn: composite [ + ^ composite table + title: 'asd'; + display: [ + { + 'self' -> self . + 'superclass' -> self spSuperclass . + 'format:' -> self classFormat . + 'instSpec' -> self instSpec . + 'instSize' -> self instSize} ]; + column: 'Key' evaluated: [:each | each key ]; + column: 'Value' evaluated: [ :each | each value ]; + send: #value + +] + +{ #category : #'accessing-header' } +SpurClass >> instSize [ + "Answer the number of named instance variables + (as opposed to indexed variables) of the receiver. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size>" + ^self classFormat bitAnd: 16rFFFF +] + +{ #category : #'accessing-header' } +SpurClass >> instSpec [ + ^ (self classFormat bitShift: -16) bitAnd: 16r1F +] + +{ #category : #accessing } +SpurClass >> methodDictionary [ + + ^ SpurMethodDictionary on: (self slotAt: self slotIndexForMethodDictionary) address image: self image +] + +{ #category : #'accessing - instance variables' } +SpurClass >> printOn: aStream [ + aStream nextPutAll: self className + "aStream nextPutAll: self className" + +] + +{ #category : #constants } +SpurClass >> slotIndexForClassFormat [ + ^ 3 +] + +{ #category : #constants } +SpurClass >> slotIndexForClassName [ + self flag: '4 for Candle'. + ^ "4" 7 +] + +{ #category : #constants } +SpurClass >> slotIndexForMetaclassInstanceVariableNames [ + self flag: '5 for Candle'. + ^ "5" 0 +] + +{ #category : #constants } +SpurClass >> slotIndexForMetaclassSoleInstance [ + self flag: '4 for Candle'. + + ^ "4" 6 +] + +{ #category : #constants } +SpurClass >> slotIndexForMethodDictionary [ + + ^ 2 +] + +{ #category : #constants } +SpurClass >> slotIndexForSuperclass [ + ^ 1 +] + +{ #category : #accessing } +SpurClass >> spSuperclass [ + | superclassOrNil | + superclassOrNil := self slotAt: self slotIndexForSuperclass. + ^ superclassOrNil spIsNil + ifTrue: [ superclassOrNil ] + ifFalse: [ superclassOrNil asSpurClass ] +] diff --git a/smalltalksrc/VMMaker-Tools/SpurCompiledMethodLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurCompiledMethodLayout.class.st new file mode 100644 index 00000000000..ad7ed49e3d3 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurCompiledMethodLayout.class.st @@ -0,0 +1,11 @@ +Class { + #name : #SpurCompiledMethodLayout, + #superclass : #SpurLayout, + #category : #'VMMaker-Tools-Model' +} + +{ #category : #testing } +SpurCompiledMethodLayout >> isCompiledMethod [ + + ^ true +] diff --git a/smalltalksrc/VMMaker-Tools/SpurEmptyLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurEmptyLayout.class.st new file mode 100644 index 00000000000..0a1f296b509 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurEmptyLayout.class.st @@ -0,0 +1,5 @@ +Class { + #name : #SpurEmptyLayout, + #superclass : #SpurLayout, + #category : #'VMMaker-Tools-Model' +} diff --git a/smalltalksrc/VMMaker-Tools/SpurFileImage.class.st b/smalltalksrc/VMMaker-Tools/SpurFileImage.class.st new file mode 100644 index 00000000000..135182cf965 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurFileImage.class.st @@ -0,0 +1,304 @@ +Class { + #name : #SpurFileImage, + #superclass : #SpurImage, + #instVars : [ + 'format', + 'memory', + 'headerSize', + 'dataSize', + 'oldBaseAddress', + 'specialObjectsArrayOop' + ], + #category : #'VMMaker-Tools-Model' +} + +{ #category : #'as yet unclassified' } +SpurFileImage class >> onFile: aFile [ + + | memory | + memory := aFile asFileReference binaryReadStream contents. + ^ self onMemory: memory +] + +{ #category : #'as yet unclassified' } +SpurFileImage class >> onMemory: aByteArray [ + + ^ self basicNew + memory: aByteArray; + initialize; + yourself +] + +{ #category : #'as yet unclassified' } +SpurFileImage class >> onMyself [ +| memory nilOop VM| + "nilOop := aSpur32BitMMLESimulator nilObject. + memory := aSpur32BitMMLESimulator memory asByteArray. + memory := fullMemory copyFrom: nilOop + 1 to: fullMemory size." + VM = VirtualMachine new. + + ^ self basicNew + memory: memory; + version: VM parameterAt: 41; + headerSize: nilOop; + specialObjectsArrayOop: VM specialObjectsOop; + oldBaseAddress: nilOop; + yourself +] + +{ #category : #'as yet unclassified' } +SpurFileImage class >> onSpurSimulator: aSpur32BitMMLESimulator [ + | memory nilOop | + nilOop := aSpur32BitMMLESimulator nilObject. + memory := aSpur32BitMMLESimulator memory memoryObject. + "memory := fullMemory copyFrom: nilOop + 1 to: fullMemory size." + + ^ self basicNew + memory: memory; + headerSize: nilOop - aSpur32BitMMLESimulator memory initialAddress - 1; + specialObjectsArrayOop: aSpur32BitMMLESimulator specialObjectsOop - aSpur32BitMMLESimulator memory initialAddress; + oldBaseAddress: nilOop - aSpur32BitMMLESimulator memory initialAddress; + hiddenRoots: aSpur32BitMMLESimulator hiddenRootsObject - aSpur32BitMMLESimulator memory initialAddress; + format: 64; + yourself +] + +{ #category : #'special-classes' } +SpurFileImage >> arrayClass [ + "indexInClassTable 51" + ^ self specialObjectsArray slotAt: 8 +] + +{ #category : #'special-classes' } +SpurFileImage >> byteArrayClass [ + "indexInClassTable 50" + ^ self specialObjectsArray slotAt: 27 +] + +{ #category : #'special-classes' } +SpurFileImage >> byteStringClass [ + "indexInClassTable 52" + ^ self specialObjectsArray slotAt: 7 +] + +{ #category : #'special-classes' } +SpurFileImage >> characterClass [ + "indexInClassTable 2" + ^ self specialObjectsArray slotAt: 20 +] + +{ #category : #'special-objects' } +SpurFileImage >> classTableFirstPage [ + ^ self hiddenRootsObj classTableFirstPage +] + +{ #category : #'special-objects' } +SpurFileImage >> firstObject [ + + ^ SpurObject on: headerSize + 1 image: self +] + +{ #category : #accessing } +SpurFileImage >> format [ + ^format +] + +{ #category : #accessing } +SpurFileImage >> format: anObject [ + + format := anObject +] + +{ #category : #'gt-inspector-extension' } +SpurFileImage >> gtInspectorSpecialObjectsArrayIn: composite [ + + + ^ [(self specialObjectsArray gtInspectorLayoutIn: composite) title: 'SOArray' ] on:Error do: [ 'lalala' ] +] + +{ #category : #accessing } +SpurFileImage >> headerSize [ + + ^ headerSize +] + +{ #category : #accessing } +SpurFileImage >> headerSize: anInteger [ + headerSize := anInteger +] + +{ #category : #accessing } +SpurFileImage >> initialize [ + + super initialize. + self readImageHeader. +] + +{ #category : #'special-classes' } +SpurFileImage >> is32bit [ + ^(format = 32) +] + +{ #category : #'special-classes' } +SpurFileImage >> is64bit [ + ^(format = 64) +] + +{ #category : #'special-classes' } +SpurFileImage >> largeNegativeIntegerClass [ + "indexInClassTable 32" + ^ self specialObjectsArray slotAt: 43 +] + +{ #category : #'special-classes' } +SpurFileImage >> largePositiveIntegerClass [ + "indexInClassTable 33" + ^ self specialObjectsArray slotAt: 14 +] + +{ #category : #accessing } +SpurFileImage >> memory [ + ^ memory +] + +{ #category : #accessing } +SpurFileImage >> memory: aCollection [ + memory := aCollection +] + +{ #category : #'special-classes' } +SpurFileImage >> messageClass [ + "indexInClassTable 35" + ^ self specialObjectsArray slotAt: 16 +] + +{ #category : #'special-objects' } +SpurFileImage >> nilObject [ + ^ self firstObject +] + +{ #category : #accessing } +SpurFileImage >> oldBaseAddress [ + ^ oldBaseAddress +] + +{ #category : #accessing } +SpurFileImage >> oldBaseAddress: anInteger [ + oldBaseAddress := anInteger +] + +{ #category : #'special-classes' } +SpurFileImage >> pointClass [ + "indexInClassTable 54" + ^ self specialObjectsArray slotAt: 13 +] + +{ #category : #accessing } +SpurFileImage >> printByteSymbol: aByteSymbolClass [ + + ^ aByteSymbolClass asLocalByteArray asString reject: [ :e | e = Character null] +] + +{ #category : #accessing } +SpurFileImage >> readImageHeader [ + +"Reading the version will allow us to find the format" + self readVersionFromImageHeader. + self is32bit ifTrue:[ + self readImageHeader32 ]. + self is64bit ifTrue:[ + self readImageHeader64 ] + +] + +{ #category : #accessing } +SpurFileImage >> readImageHeader32 [ + | lastHash savedWindowSize headerFlags | + + headerSize := (memory copyFrom: 5 to: 8) + unsignedLongAt: 1 + bigEndian: false. + dataSize := (memory copyFrom: 9 to: 12) + unsignedLongAt: 1 + bigEndian: false. + self assert: headerSize + dataSize = memory size. + oldBaseAddress := (memory copyFrom: 13 to: 16) + unsignedLongAt: 1 + bigEndian: false. + specialObjectsArrayOop := (memory copyFrom: 17 to: 20) + unsignedLongAt: 1 + bigEndian: false. + lastHash := (memory copyFrom: 21 to: 24) + unsignedLongAt: 1 + bigEndian: false. + savedWindowSize := (memory copyFrom: 25 to: 28) + unsignedLongAt: 1 + bigEndian: false. + headerFlags := (memory copyFrom: 29 to: 32) + unsignedLongAt: 1 + bigEndian: false +] + +{ #category : #accessing } +SpurFileImage >> readImageHeader64 [ + | lastHash savedWindowSize headerFlags | + + headerSize := (memory copyFrom: 5 to: 8) + unsignedLongAt: 1 + bigEndian: false. + dataSize := (memory copyFrom: 9 to: 16) + unsignedLong64At: 1 + bigEndian: false. + self assert: headerSize + dataSize = memory size. + oldBaseAddress := (memory copyFrom: 17 to: 24) + unsignedLong64At: 1 + bigEndian: false. + specialObjectsArrayOop := (memory copyFrom: 25 to: 32) + unsignedLong64At: 1 + bigEndian: false. + lastHash := (memory copyFrom: 33 to: 40) + unsignedLong64At: 1 + bigEndian: false. + savedWindowSize := (memory copyFrom: 41 to: 48) + unsignedLong64At: 1 + bigEndian: false. + headerFlags := (memory copyFrom: 49 to: 56) + unsignedLong64At: 1 + bigEndian: false +] + +{ #category : #accessing } +SpurFileImage >> readVersionFromImageHeader [ + | version | + version := (memory copyFrom: 1 to: 4) + unsignedLongAt: 1 + bigEndian: false. + self flag: #ugly. + version < 10000 + ifTrue: [ format := 32] + ifFalse: [ format := 64]. + +] + +{ #category : #'special-classes' } +SpurFileImage >> semaphoreClass [ + "indexInClassTable 48" + ^ self specialObjectsArray slotAt: 19 +] + +{ #category : #'special-classes' } +SpurFileImage >> smallIntegerClass [ + "indexInClassTable 1" + ^ self specialObjectsArray slotAt: 6 +] + +{ #category : #accessing } +SpurFileImage >> specialObjectsArray [ + + ^ SpurObject on: specialObjectsArrayOop - oldBaseAddress + headerSize + 1 image: self +] + +{ #category : #accessing } +SpurFileImage >> specialObjectsArrayOop: anInteger [ + specialObjectsArrayOop := anInteger +] diff --git a/smalltalksrc/VMMaker-Tools/SpurFixedLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurFixedLayout.class.st new file mode 100644 index 00000000000..b5b763d7b6e --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurFixedLayout.class.st @@ -0,0 +1,21 @@ +Class { + #name : #SpurFixedLayout, + #superclass : #SpurLayout, + #category : #'VMMaker-Tools-Model' +} + +{ #category : #'gt-inspector-extension' } +SpurFixedLayout >> allSlots [ + ^ (1 to: self object numberOfSlots) collect: [ :index | self object slotAt: index ] +] + +{ #category : #'gt-inspector-extension' } +SpurFixedLayout >> gtInspectorLayoutIn: composite [ + ^ composite table + title: 'Inst Vars'; + display: [ + self allSlots collectWithIndex: [ :slot :index | index -> slot ] ]; + column: 'Index' evaluated: [:each | each key ]; + column: 'Value' evaluated: [ :each | each value ]; + send: #value +] diff --git a/smalltalksrc/VMMaker-Tools/SpurHiddenRoots.class.st b/smalltalksrc/VMMaker-Tools/SpurHiddenRoots.class.st new file mode 100644 index 00000000000..0adc9bf159a --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurHiddenRoots.class.st @@ -0,0 +1,36 @@ +Class { + #name : #SpurHiddenRoots, + #superclass : #SpurObject, + #category : #'VMMaker-Tools-Model' +} + +{ #category : #'as yet unclassified' } +SpurHiddenRoots >> classOrNilAtIndex: classIndex [ + + | classTablePage nilObj | + + "self assert: (classIndex <= self tagMask or: [classIndex >= image arrayClassIndexPun])." + nilObj := image nilObject. + classTablePage := self classTablePageNumber: (classIndex >> image classTableMajorIndexShift) + 1. + classTablePage = nilObj ifTrue: + [^nilObj]. + ^ (classTablePage + slotAt: (classIndex bitAnd: image classTableMinorIndexMask) + 1) asSpurClass +] + +{ #category : #'as yet unclassified' } +SpurHiddenRoots >> classTableFirstPage [ + ^ self classTablePageNumber: 1 +] + +{ #category : #'as yet unclassified' } +SpurHiddenRoots >> classTablePageNumber: anInteger [ + "anInteger is 1 based" + | classTablePage | + classTablePage := SpurObject + on:(self slotAt: anInteger) address + image: image. + self assert: classTablePage format = image arrayFormat. + self assert: classTablePage classIndex = image arrayClassIndexPun. + ^ classTablePage +] diff --git a/smalltalksrc/VMMaker-Tools/SpurImage.class.st b/smalltalksrc/VMMaker-Tools/SpurImage.class.st new file mode 100644 index 00000000000..30b7e2da480 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurImage.class.st @@ -0,0 +1,110 @@ +" +""| version (4 bytes) | headerSize (4 bytes) | datasize (4 bytes) | old base address (4 bytes) | special objects oop (4 bytes) | = 20 bytes + | last hash (4 bytes)| saved window size (4 bytes) | headerFlags (4 bytes) | extraVMMemory (4bytes) | stack pages (2 bytes) | = 18 bytes + | native method zone size (2 bytes) | eden size (4 bytes) | semaphore table max size (2 bytes) | the2ndUnknownShort (2 bytes) | = 10 bytes + | first segment size (4 bytes) | free old space (4 bytes) | = 8 bytes + | The rest 8 bytes are empty"" + +(spur specialObjectsArray slotAt: 1) address = spur firstObject address. +" +Class { + #name : #SpurImage, + #superclass : #Object, + #instVars : [ + 'hiddenRoots', + 'classTable' + ], + #category : #'VMMaker-Tools-Model' +} + +{ #category : #constants } +SpurImage >> arrayClassIndexPun [ + ^ 16 +] + +{ #category : #constants } +SpurImage >> arrayFormat [ + ^ 2 +] + +{ #category : #constants } +SpurImage >> classIndexFieldWidth [ + "22-bit class mask => ~ 4M classes" + ^22 +] + +{ #category : #accessing } +SpurImage >> classTable [ + + ^ classTable +] + +{ #category : #accessing } +SpurImage >> classTable: anObject [ + + classTable := anObject +] + +{ #category : #constants } +SpurImage >> classTableMajorIndexShift [ + "1024 entries per page (2^10); 22 bit classIndex implies 2^12 pages" + ^10 +] + +{ #category : #constants } +SpurImage >> classTableMinorIndexMask [ + "1024 entries per page (2^10); 22 bit classIndex implies 2^12 pages" + "self basicNew classTableMinorIndexMask" + ^1 << self classTableMajorIndexShift - 1 +] + +{ #category : #constants } +SpurImage >> classTablePageSize [ + + ^1 << self classTableMajorIndexShift +] + +{ #category : #constants } +SpurImage >> classTableRootSlots [ + "Answer the number of slots for class table pages in the hidden root object." + ^1 << (self classIndexFieldWidth - self classTableMajorIndexShift) +] + +{ #category : #'special-objects' } +SpurImage >> falseObject [ + ^ self nilObject nextObject +] + +{ #category : #'special-objects' } +SpurImage >> freeListObj [ + + ^ self trueObject nextObject +] + +{ #category : #'as yet unclassified' } +SpurImage >> hiddenRoots: anInteger [ + hiddenRoots := anInteger +] + +{ #category : #'special-objects' } +SpurImage >> hiddenRootsObj [ + + hiddenRoots ifNil: [ + hiddenRoots := self freeListObj nextObject address ]. + ^ SpurHiddenRoots on: hiddenRoots image: self +] + +{ #category : #'as yet unclassified' } +SpurImage >> imageFormat: anInteger [ + self shouldBeImplemented. +] + +{ #category : #'special-objects' } +SpurImage >> nilObject [ + ^ self subclassResponsibility +] + +{ #category : #'special-objects' } +SpurImage >> trueObject [ + ^ self falseObject nextObject +] diff --git a/smalltalksrc/VMMaker-Tools/SpurImmediateLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurImmediateLayout.class.st new file mode 100644 index 00000000000..49a9a783883 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurImmediateLayout.class.st @@ -0,0 +1,5 @@ +Class { + #name : #SpurImmediateLayout, + #superclass : #SpurLayout, + #category : #'VMMaker-Tools-Model' +} diff --git a/smalltalksrc/VMMaker-Tools/SpurLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurLayout.class.st new file mode 100644 index 00000000000..39492a2bd20 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurLayout.class.st @@ -0,0 +1,141 @@ +Class { + #name : #SpurLayout, + #superclass : #Object, + #instVars : [ + 'object' + ], + #category : #'VMMaker-Tools-Model' +} + +{ #category : #'as yet unclassified' } +SpurLayout class >> layoutClassFromFormat: objFormat [ + (objFormat = 0) + ifTrue: [ ^ SpurEmptyLayout ]. + (objFormat = 1) + ifTrue: [ ^ SpurFixedLayout ]. + (objFormat = 2) + ifTrue: [ ^ SpurVariableLayout ]. + (objFormat = 3) + ifTrue: [ ^SpurVariableWithInstanceVariablesLayout ]. + (objFormat = 4) + ifTrue: [ ^SpurVariableWithInstanceVariablesLayout ]. + (objFormat = 5) + ifTrue: [ ^SpurVariableWithInstanceVariablesLayout ]. + + (objFormat = 7) + ifTrue: [ ^SpurImmediateLayout]. + + (objFormat < 24 and: [ objFormat > 8 ]) + ifTrue: [ ^ SpurByteLayout ]. + (objFormat < 32 and: [ objFormat > 23 ]) + ifTrue: [ ^ SpurCompiledMethodLayout ]. + + ^ self error: 'Unused or invalid format.' + +] + +{ #category : #'as yet unclassified' } +SpurLayout class >> on: aSpurObject image: aSpurImage [ + | layoutClass | + "TH; Why passing the image here ?" + + layoutClass := self layoutClassFromFormat: aSpurObject objectFormat. + + ^ layoutClass new + object: aSpurObject. +] + +{ #category : #accessing } +SpurLayout >> address [ + ^ self object address +] + +{ #category : #accessing } +SpurLayout >> at: anInteger [ + + ^ self slotAt: anInteger +] + +{ #category : #accessing } +SpurLayout >> basicNumberOfSlots [ + ^ self headerInteger >> (self headerSize * 8 "bits" - 8 "number of slots mask size") +] + +{ #category : #accessing } +SpurLayout >> byteSize [ + ^ self object byteSize . +] + +{ #category : #'gt-inspector-extension' } +SpurLayout >> gtInspectorLayoutIn: composite [ + ^composite text + title: 'Spur view'; + display: [ [self object asString] on:Error do: [ 'Error printing' ] ] +] + +{ #category : #accessing } +SpurLayout >> headerInteger [ + ^ self object headerInteger +] + +{ #category : #accessing } +SpurLayout >> headerSize [ + ^ self object headerSize +] + +{ #category : #accessing } +SpurLayout >> image [ + ^ self object image +] + +{ #category : #testing } +SpurLayout >> isCompiledMethod [ + + ^ false +] + +{ #category : #accessing } +SpurLayout >> memory [ + ^ self object memory +] + +{ #category : #accessing } +SpurLayout >> numberOfSlots [ + + | slotsInHeader | + slotsInHeader := self basicNumberOfSlots. + slotsInHeader == 16rFF + ifTrue: [ ^ self previousHeaderInteger ]. + ^ slotsInHeader +] + +{ #category : #accessing } +SpurLayout >> object [ + ^ object +] + +{ #category : #accessing } +SpurLayout >> object: anObject [ + object := anObject +] + +{ #category : #printing } +SpurLayout >> objectPrintOn: aStream [ + aStream nextPutAll: 'a ', (self object basicClass asString) +] + +{ #category : #accessing } +SpurLayout >> previousHeaderInteger [ + ^ self object previousHeaderInteger +] + +{ #category : #accessing } +SpurLayout >> slotAt: anInteger [ + + ^ self image objectForOop: (object fetchPointer: anInteger) +] + +{ #category : #accessing } +SpurLayout >> wordSize [ + ^ self object wordSize +] diff --git a/smalltalksrc/VMMaker-Tools/SpurMethod.class.st b/smalltalksrc/VMMaker-Tools/SpurMethod.class.st new file mode 100644 index 00000000000..5dced4636a9 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurMethod.class.st @@ -0,0 +1,55 @@ +Class { + #name : #SpurMethod, + #superclass : #SpurObject, + #category : #'VMMaker-Tools-Model' +} + +{ #category : #accessing } +SpurMethod >> lastLiteral [ + + ^ self literalAt: (self numberOfLiterals + 1) +] + +{ #category : #accessing } +SpurMethod >> literalAt: anIndex [ + + ^ self slotAt: anIndex +] + +{ #category : #accessing } +SpurMethod >> methodClass [ + + | methodClassBinding | + methodClassBinding := self lastLiteral. + ^ (methodClassBinding slotAt: 2) vmPrintOop +] + +{ #category : #accessing } +SpurMethod >> methodHeader [ + ^ self slotAt: 1 +] + +{ #category : #accessing } +SpurMethod >> numberOfLiterals [ + "Mask to get the numberOfLietrals" + ^self methodHeader bitAnd: 16r7FFF +] + +{ #category : #accessing } +SpurMethod >> penultimateLiteral [ + + ^ self literalAt: self numberOfLiterals +] + +{ #category : #accessing } +SpurMethod >> selector [ + | selectorLiteral | + selectorLiteral := self penultimateLiteral. + (selectorLiteral basicClass asSpurClass className + = 'AdditionalMethodState') + ifFalse: [ ^ self image printByteSymbol: selectorLiteral ] + ifTrue: [ | selectorInAdditional | + selectorInAdditional := selectorLiteral + slotAt: 2. "Supossed to be the selector" + ^ self image printByteSymbol: selectorInAdditional ] +] diff --git a/smalltalksrc/VMMaker-Tools/SpurMethodDictionary.class.st b/smalltalksrc/VMMaker-Tools/SpurMethodDictionary.class.st new file mode 100644 index 00000000000..dd64011d524 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurMethodDictionary.class.st @@ -0,0 +1,35 @@ +Class { + #name : #SpurMethodDictionary, + #superclass : #SpurObject, + #category : #'VMMaker-Tools-Model' +} + +{ #category : #accessing } +SpurMethodDictionary >> firstMethod [ + + | index arrayOfMethod | + index := self firstSelectorIndex. + + arrayOfMethod := self slotAt: 2. + ^arrayOfMethod slotAt: index. + +] + +{ #category : #accessing } +SpurMethodDictionary >> firstSelector [ + + ^ self slotAt: self firstSelectorIndex + 2 +] + +{ #category : #accessing } +SpurMethodDictionary >> firstSelectorIndex [ + | currentIndex found | + currentIndex := 1. + found := nil. + [ currentIndex + 2 < self numberOfSlots and: [ found isNil ] ] + whileTrue: [ | object | + (object := (self slotAt: currentIndex + 2)) spIsNil + ifTrue: [ currentIndex := currentIndex + 1 ] + ifFalse: [ found := object. ^currentIndex ]. ]. + ^ nil +] diff --git a/smalltalksrc/VMMaker-Tools/SpurObject.class.st b/smalltalksrc/VMMaker-Tools/SpurObject.class.st new file mode 100644 index 00000000000..7cc3ff1fbcc --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurObject.class.st @@ -0,0 +1,281 @@ +" +spur := SpurImage onFile: Smalltalk imagePath. +firstObject := spur firstObject. +secondObject := firstObject nextObject. +thirdObject := secondObject nextObject. +fourthObject := thirdObject nextObject. +fifthObject := fourthObject nextObject. + +firstObject basicNumberOfSlots. +secondObject basicNumberOfSlots. +thirdObject basicNumberOfSlots. +fourthObject classIndex. + +fifthObject classIndex. +fifthObject format. +fifthObject numberOfSlots. + +fifthObject nextObject nextObject nextObject nextObject nextObject nextObject numberOfSlots. + +(spur specialObjectsArray slotAt: 1) address = spur firstObject address. + +1) Podemos encontrar a nil? +2) Podemos encontrar a true? +3) Podemos encontrar a false? + +4) Podemos encontrar la tabla de clases? + 4.1) Como a partir de un class index (en el header del objeto) encontramos una clase en la tabla. + 4.2) Una vez que tenes la clase, recuperar el nombre de la clase (7ma variable es el nombre) + 4.3) Transformar un string en la imagen a un string normal. + 4.4) hacer un pretty print del objeto: + - nombre de la clase + - tipo de objeto / format + - tamaƱo +" +Class { + #name : #SpurObject, + #superclass : #Object, + #instVars : [ + 'address', + 'image', + 'spurLayout' + ], + #category : #'VMMaker-Tools-Model' +} + +{ #category : #'as yet unclassified' } +SpurObject class >> on: address image: anImage [ + ^self new + address: address; + image: anImage; + yourself. + +] + +{ #category : #accessing } +SpurObject >> address [ + ^ address +] + +{ #category : #accessing } +SpurObject >> address: anInteger [ + address := anInteger +] + +{ #category : #'accessing-slots' } +SpurObject >> allSlots [ + + ^ self spurLayout allSlots +] + +{ #category : #'as yet unclassified' } +SpurObject >> asLocalByteArray [ + ^ self spurLayout asLocalByteArray +] + +{ #category : #converting } +SpurObject >> asSpurClass [ + ^ SpurClass on: self address image: self image +] + +{ #category : #accessing } +SpurObject >> basicClass [ + + ^ self image hiddenRootsObj classOrNilAtIndex: self classIndex. +] + +{ #category : #'accessing-slots' } +SpurObject >> basicNumberOfSlots [ + + ^ self spurLayout basicNumberOfSlots +] + +{ #category : #'as yet unclassified' } +SpurObject >> byteSize [ + + | numberOfSlots | + numberOfSlots := self numberOfSlots. + ^ (numberOfSlots = 0 + ifTrue: [ 1 ] + ifFalse: [ numberOfSlots ]) * self wordSize. +] + +{ #category : #'accessing-header' } +SpurObject >> classIndex [ + + ^ self headerInteger bitAnd: (2 raisedTo: 22) -1 +] + +{ #category : #'as yet unclassified' } +SpurObject >> endAddress [ + + | basicSize padding | + "All objects start aligned to 64 bits. + This means all objects FINISH aligned to 64 bits too" + basicSize := self headerSize + self byteSize. + padding := basicSize % 8. + ^ address + basicSize + padding +] + +{ #category : #'as yet unclassified' } +SpurObject >> fetchPointer: anInteger [ + + ^ self image fetchPointer: anInteger ofObject: self address +] + +{ #category : #'accessing-header' } +SpurObject >> format [ + + ^ (self headerInteger >> 24) bitAnd: 2r11111 +] + +{ #category : #'gt-inspector-extension' } +SpurObject >> gtInspectorLayoutIn: composite [ + + ^self spurLayout gtInspectorLayoutIn: composite + +] + +{ #category : #'accessing-header' } +SpurObject >> headerInteger [ + + ^ self image headerOf: address +] + +{ #category : #'accessing-header' } +SpurObject >> headerSize [ + + ^ 8 "always 64 bits" +] + +{ #category : #constants } +SpurObject >> identityHashHalfWordMask [ + + ^16r3fffff +] + +{ #category : #accessing } +SpurObject >> image [ + ^ image +] + +{ #category : #accessing } +SpurObject >> image: anImage [ + image := anImage +] + +{ #category : #'accessing-header' } +SpurObject >> indexInClassTable [ + " Applies only if self contains a class. + Returns the index in the classTable of the class stored in objOop" + ^ self rawHashBits +] + +{ #category : #'as yet unclassified' } +SpurObject >> instanceVariables [ + + | numberOfSlots | + numberOfSlots := self image numberOfSlotsOf: self. + ^ (1 to: numberOfSlots) collect: [ :index | self slotAt: index ] +] + +{ #category : #accessing } +SpurObject >> memory [ + + ^ image memory +] + +{ #category : #'as yet unclassified' } +SpurObject >> numberOfSlots [ + + ^ self image numberOfSlotsOf: self +] + +{ #category : #'accessing-header' } +SpurObject >> objectFormat [ + + ^ (self headerInteger >> 24) bitAnd: 2r11111 +] + +{ #category : #'as yet unclassified' } +SpurObject >> oop [ + + ^ address +] + +{ #category : #'accessing-header' } +SpurObject >> previousHeaderInteger [ + + ^ self memory integerAt: address + (0 - self headerSize) size: 4 signed: false +] + +{ #category : #'as yet unclassified' } +SpurObject >> printSimpleOn: aLimitedWriteStream [ + + aLimitedWriteStream nextPutAll: self address hex +] + +{ #category : #'accessing-header' } +SpurObject >> rawHashBits [ + " Returns the index in the classTable of the class in objOop" + self flag: #endianness. + ^((self memory unsignedLongAt: self oop + 4 bigEndian: false) bitAnd: self identityHashHalfWordMask) +] + +{ #category : #'as yet unclassified' } +SpurObject >> simulator [ + ^self image simulator +] + +{ #category : #'accessing-slots' } +SpurObject >> slotAt: anInteger [ +"Api is 1 based but the memory api is O based" + + ^ self spurLayout slotAt: anInteger - 1 +] + +{ #category : #'as yet unclassified' } +SpurObject >> slotAt: anInteger put: aSpurObject [ +"Our api is 1 based but the simulator is 0 based" + ^ self simulator + storePointer: anInteger - 1 + ofObject: self address + withValue: aSpurObject address +] + +{ #category : #accessing } +SpurObject >> slots [ + ^(self headerInteger bitAnd: 16rFF00000000000000) >> 56. +] + +{ #category : #testing } +SpurObject >> spIsNil [ + ^ self address = self image nilObject address +] + +{ #category : #accessing } +SpurObject >> spurLayout [ + ^ spurLayout ifNil: [ spurLayout := SpurLayout on: self image: image ] +] + +{ #category : #accessing } +SpurObject >> spurLayout: anObject [ + spurLayout := anObject +] + +{ #category : #'as yet unclassified' } +SpurObject >> vmClass [ + ^self image classOf: self +] + +{ #category : #'as yet unclassified' } +SpurObject >> vmPrintOop [ + + +] + +{ #category : #constants } +SpurObject >> wordSize [ + + ^ self image wordSize +] diff --git a/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st b/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st new file mode 100644 index 00000000000..c7d352aca9c --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st @@ -0,0 +1,73 @@ +Class { + #name : #SpurSimulatorImage, + #superclass : #SpurImage, + #instVars : [ + 'simulator' + ], + #classInstVars : [ + 'simulator' + ], + #category : #'VMMaker-Tools-Model' +} + +{ #category : #'as yet unclassified' } +SpurSimulatorImage class >> onSpurSimulator: aSpur64BitMMLESimulator [ + + ^ self new + simulator: aSpur64BitMMLESimulator; + yourself +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> classOf: aSpurObject [ + ^self objectForOop: (simulator fetchClassOf: aSpurObject address) +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> fetchPointer: anInteger ofObject: objectOop [ + + ^ simulator fetchPointer: anInteger ofObject: objectOop +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> headerOf: anInteger [ + ^simulator objectMemory baseHeader: anInteger +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> memory [ + ^simulator +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> nilObject [ + ^SpurObject on: simulator nilObject image: self + +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> numberOfSlotsOf: aSpurObject [ + + ^simulator numSlotsOf: aSpurObject address +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> objectForOop: anInteger [ + + ^ SpurObject on: anInteger image: self +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> simulator [ + ^ simulator +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> simulator: aSpur64BitMMLESimulator [ + simulator := aSpur64BitMMLESimulator +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> wordSize [ + ^simulator wordSize +] diff --git a/smalltalksrc/VMMaker-Tools/SpurVariableLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurVariableLayout.class.st new file mode 100644 index 00000000000..807fe64b678 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurVariableLayout.class.st @@ -0,0 +1,21 @@ +Class { + #name : #SpurVariableLayout, + #superclass : #SpurLayout, + #category : #'VMMaker-Tools-Model' +} + +{ #category : #'gt-inspector-extension' } +SpurVariableLayout >> allSlots [ + ^ self object instanceVariables +] + +{ #category : #'gt-inspector-extension' } +SpurVariableLayout >> gtInspectorLayoutIn: composite [ + ^ composite table + title: 'Items'; + display: [ + self allSlots collectWithIndex: [ :slot :index | index -> slot ] ]; + column: 'Index' evaluated: [:each | each key ]; + column: 'Value' evaluated: [ :each | each value ]; + send: #value +] diff --git a/smalltalksrc/VMMaker-Tools/SpurVariableWithInstanceVariablesLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurVariableWithInstanceVariablesLayout.class.st new file mode 100644 index 00000000000..f02f3b3e403 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/SpurVariableWithInstanceVariablesLayout.class.st @@ -0,0 +1,5 @@ +Class { + #name : #SpurVariableWithInstanceVariablesLayout, + #superclass : #SpurLayout, + #category : #'VMMaker-Tools-Model' +} diff --git a/smalltalksrc/VMMaker-Tools/VMBytecodeToIRMapping.class.st b/smalltalksrc/VMMaker-Tools/VMBytecodeToIRMapping.class.st index d130040229f..1dc1ae633cd 100644 --- a/smalltalksrc/VMMaker-Tools/VMBytecodeToIRMapping.class.st +++ b/smalltalksrc/VMMaker-Tools/VMBytecodeToIRMapping.class.st @@ -5,7 +5,7 @@ Class { 'bytecodeInstruction', 'irInstruction' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } { #category : #accessing } diff --git a/smalltalksrc/VMMaker-Tools/VMDebugger.class.st b/smalltalksrc/VMMaker-Tools/VMDebugger.class.st index fed034dab5c..958173ca5f2 100644 --- a/smalltalksrc/VMMaker-Tools/VMDebugger.class.st +++ b/smalltalksrc/VMMaker-Tools/VMDebugger.class.st @@ -13,7 +13,7 @@ Class { 'stack', 'frameContainer' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-MachineCodeDebugger' } { #category : #specs } diff --git a/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st new file mode 100644 index 00000000000..a6e4dffea28 --- /dev/null +++ b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st @@ -0,0 +1,64 @@ +Class { + #name : #VMInspectorTest, + #superclass : #VMInterpreterTests, + #instVars : [ + 'imageName', + 'image' + ], + #pools : [ + 'VMBasicConstants', + 'VMBytecodeConstants', + 'VMObjectIndices' + ], + #category : #'VMMaker-Tools-Tests' +} + +{ #category : #running } +VMInspectorTest >> setUp [ + + super setUp. + image := SpurSimulatorImage onSpurSimulator: memory. + + + + +] + +{ #category : #tests } +VMInspectorTest >> testNilHasNoInstanceVariable [ + + self assert: image nilObject instanceVariables isEmpty. +] + +{ #category : #tests } +VMInspectorTest >> testObjectWithInstanceVariableCycleWeCanNavigate [ + + | objectOop1 object1 objectOop2 object2 | + objectOop1 := self newObjectWithSlots: 1. + objectOop2 := self newObjectWithSlots: 1. + + object1 := (image objectForOop: objectOop1). + object2 := (image objectForOop: objectOop2). + + object1 slotAt: 1 put: object2. + object2 slotAt: 1 put: object1. + + self assert: (object1 slotAt: 1) equals: object2. + self assert: (object2 slotAt: 1) equals: object1. +] + +{ #category : #tests } +VMInspectorTest >> testObjectWithInstanceVariableHasInstanceVariable [ + + | objectOop | + objectOop := self newObjectWithSlots: 2. + self assert: (image objectForOop: objectOop) instanceVariables isNotEmpty. +] + +{ #category : #tests } +VMInspectorTest >> testPrintNil [ + + | nilObject | + nilObject:= image nilObject. + self assert: nilObject printString equals: 'a(n) ', nilObject address hex, '@', nilObject address hex. +] diff --git a/smalltalksrc/VMMaker-Tools/VMMachineCodeDebugger.class.st b/smalltalksrc/VMMaker-Tools/VMMachineCodeDebugger.class.st index dadd6503494..a0fe4ba54d6 100644 --- a/smalltalksrc/VMMaker-Tools/VMMachineCodeDebugger.class.st +++ b/smalltalksrc/VMMaker-Tools/VMMachineCodeDebugger.class.st @@ -13,7 +13,7 @@ Class { 'ipInput', 'jumpToButton' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-MachineCodeDebugger' } { #category : #specs } diff --git a/smalltalksrc/VMMaker-Tools/VMMachineCodeDebuggerInstruction.class.st b/smalltalksrc/VMMaker-Tools/VMMachineCodeDebuggerInstruction.class.st index d19fb0cda74..84d271de45d 100644 --- a/smalltalksrc/VMMaker-Tools/VMMachineCodeDebuggerInstruction.class.st +++ b/smalltalksrc/VMMaker-Tools/VMMachineCodeDebuggerInstruction.class.st @@ -7,7 +7,7 @@ Class { 'machineSimulator', 'debugger' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-MachineCodeDebugger' } { #category : #accessing } diff --git a/smalltalksrc/VMMaker-Tools/VMMachineCodeDebuggerStackItem.class.st b/smalltalksrc/VMMaker-Tools/VMMachineCodeDebuggerStackItem.class.st index 71406f5a9a0..b8ac1b37091 100644 --- a/smalltalksrc/VMMaker-Tools/VMMachineCodeDebuggerStackItem.class.st +++ b/smalltalksrc/VMMaker-Tools/VMMachineCodeDebuggerStackItem.class.st @@ -5,7 +5,7 @@ Class { 'address', 'machineSimulator' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-MachineCodeDebugger' } { #category : #'instance creation' } diff --git a/smalltalksrc/VMMaker-Tools/VMMethodBytecodeToIRMapping.class.st b/smalltalksrc/VMMaker-Tools/VMMethodBytecodeToIRMapping.class.st index 1899906bd22..8b41046d570 100644 --- a/smalltalksrc/VMMaker-Tools/VMMethodBytecodeToIRMapping.class.st +++ b/smalltalksrc/VMMaker-Tools/VMMethodBytecodeToIRMapping.class.st @@ -6,7 +6,7 @@ Class { 'ir', 'mappingList' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } { #category : #'instance creation' } diff --git a/smalltalksrc/VMMaker-Tools/VMTFreeListNode.class.st b/smalltalksrc/VMMaker-Tools/VMTFreeListNode.class.st index 8da7d377f6f..c5f7d16028e 100644 --- a/smalltalksrc/VMMaker-Tools/VMTFreeListNode.class.st +++ b/smalltalksrc/VMMaker-Tools/VMTFreeListNode.class.st @@ -5,7 +5,7 @@ Class { 'nodeOop', 'memory' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } { #category : #'instance-creation' } diff --git a/smalltalksrc/VMMaker-Tools/VMTFreeListNodeEdge.class.st b/smalltalksrc/VMMaker-Tools/VMTFreeListNodeEdge.class.st index eceeea24112..9ad7ed259bf 100644 --- a/smalltalksrc/VMMaker-Tools/VMTFreeListNodeEdge.class.st +++ b/smalltalksrc/VMMaker-Tools/VMTFreeListNodeEdge.class.st @@ -6,7 +6,7 @@ Class { 'label', 'nodeOop' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } { #category : #'instance-creation' } diff --git a/smalltalksrc/VMMaker-Tools/VMTFreeLists.class.st b/smalltalksrc/VMMaker-Tools/VMTFreeLists.class.st index 5a30887c109..4019272acd4 100644 --- a/smalltalksrc/VMMaker-Tools/VMTFreeLists.class.st +++ b/smalltalksrc/VMMaker-Tools/VMTFreeLists.class.st @@ -4,7 +4,7 @@ Class { #instVars : [ 'memory' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } { #category : #'instance-creation' } diff --git a/smalltalksrc/VMMaker-Tools/VMTFreeTreeNode.class.st b/smalltalksrc/VMMaker-Tools/VMTFreeTreeNode.class.st index af2283df513..386edc6d19e 100644 --- a/smalltalksrc/VMMaker-Tools/VMTFreeTreeNode.class.st +++ b/smalltalksrc/VMMaker-Tools/VMTFreeTreeNode.class.st @@ -1,7 +1,7 @@ Class { #name : #VMTFreeTreeNode, #superclass : #VMTFreeListNode, - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } { #category : #accessing } diff --git a/smalltalksrc/VMMaker-Tools/VMTFreeTreeNodeEdge2.class.st b/smalltalksrc/VMMaker-Tools/VMTFreeTreeNodeEdge2.class.st index 42a2a312ce8..34095921650 100644 --- a/smalltalksrc/VMMaker-Tools/VMTFreeTreeNodeEdge2.class.st +++ b/smalltalksrc/VMMaker-Tools/VMTFreeTreeNodeEdge2.class.st @@ -1,5 +1,5 @@ Class { #name : #VMTFreeTreeNodeEdge2, #superclass : #VMTFreeListNodeEdge, - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } diff --git a/smalltalksrc/VMMaker-Tools/VMTHiddenRoot.class.st b/smalltalksrc/VMMaker-Tools/VMTHiddenRoot.class.st index 2e3ef4fcf38..5668908a278 100644 --- a/smalltalksrc/VMMaker-Tools/VMTHiddenRoot.class.st +++ b/smalltalksrc/VMMaker-Tools/VMTHiddenRoot.class.st @@ -7,7 +7,7 @@ Class { 'label', 'oop' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } { #category : #accessing } diff --git a/smalltalksrc/VMMaker-Tools/VMTHiddenRootTable.class.st b/smalltalksrc/VMMaker-Tools/VMTHiddenRootTable.class.st index b619d2a4c61..edd9f08c4d7 100644 --- a/smalltalksrc/VMMaker-Tools/VMTHiddenRootTable.class.st +++ b/smalltalksrc/VMMaker-Tools/VMTHiddenRootTable.class.st @@ -4,7 +4,7 @@ Class { #instVars : [ 'memory' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } { #category : #'instance-creation' } diff --git a/smalltalksrc/VMMaker-Tools/VMTStackFrame.class.st b/smalltalksrc/VMMaker-Tools/VMTStackFrame.class.st index f54ca8db406..46911bce9cd 100644 --- a/smalltalksrc/VMMaker-Tools/VMTStackFrame.class.st +++ b/smalltalksrc/VMMaker-Tools/VMTStackFrame.class.st @@ -5,7 +5,7 @@ Class { 'memory', 'framePointer' ], - #category : #'VMMaker-Tools' + #category : #'VMMaker-Tools-InspectorExtensions' } { #category : #accessing } diff --git a/smalltalksrc/VMMakerTests/VMBlockTest.class.st b/smalltalksrc/VMMakerTests/VMBlockTest.class.st index d0cb0f3deeb..3ca8fdf8851 100644 --- a/smalltalksrc/VMMakerTests/VMBlockTest.class.st +++ b/smalltalksrc/VMMakerTests/VMBlockTest.class.st @@ -12,67 +12,6 @@ Class { VMBlockTest >> anEmptyMethod [ ] -{ #category : #'as yet unclassified' } -VMBlockTest >> evaluatingABlock [ - - ^[42] value -] - -{ #category : #'as yet unclassified' } -VMBlockTest >> evaluatingABlockWithLocalBlockVariable [ - - ^ [ - | aVariable | - aVariable := 42. - aVariable ] value -] - -{ #category : #'as yet unclassified' } -VMBlockTest >> evaluatingABlockWithLocalMethodVariableAssignedInTheBlock [ - - | aVariable | - ^ [ - aVariable := 42. - aVariable ] value -] - -{ #category : #'as yet unclassified' } -VMBlockTest >> evaluatingABlockWithLocalMethodVariableRead [ - - | aVariable | - aVariable := 42. - ^ [ aVariable ] value -] - -{ #category : #'as yet unclassified' } -VMBlockTest >> evaluatingABlockWithNonLocalReturn [ - - [^1] value -] - -{ #category : #testing } -VMBlockTest >> executeMethod: aMethodToTest [ - - | methodReturning initialMethod | - - methodReturning := self createMethodOopFromPharoMethod: - aMethodToTest. - - initialMethod := self createMethodOopFromPharoMethod: - self class >> #anEmptyMethod. - - "We want to avoid baseFrameReturn (base frame initialisation)" - stackBuilder addNewFrame method: initialMethod. - stackBuilder addNewFrame - method: methodReturning; - receiver: memory trueObject. - stackBuilder buildStack. - - interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodReturning). - interpreter interpretWhile: [ interpreter method = methodReturning ]. - -] - { #category : #helpers } VMBlockTest >> installBlockClosureClass [ | aClass | @@ -93,14 +32,6 @@ VMBlockTest >> methodReturningABlock [ ] -{ #category : #'as yet unclassified' } -VMBlockTest >> methodReturningABlockInsideABlockWithLocal [ - - true ifTrue:[|anArgument| anArgument := 2. - ^[anArgument]] - -] - { #category : #supports } VMBlockTest >> methodReturningABlockWithTwoArguments [ @@ -108,170 +39,108 @@ VMBlockTest >> methodReturningABlockWithTwoArguments [ ] -{ #category : #supports } -VMBlockTest >> methodWithLocalReturningABlock [ - - | a | - a:= 1. - ^ [ a ] -] - -{ #category : #running } -VMBlockTest >> setUp [ - - super setUp. - self installBlockClosureClass. -] - -{ #category : #testing } -VMBlockTest >> testCreatingABlockClosureShouldCopyUsedMethodVariable [ - - | methodToTest | - methodToTest := self class >> #methodWithLocalReturningABlock. - - self executeMethod: methodToTest. - "We assign 1 to the local variable of the method, see methodWithLocalReturningABlock" - self - assert: (memory - fetchPointer: ClosureFirstCopiedValueIndex - ofObject: interpreter stackTop) - equals: (memory integerObjectOf: 1) -] - -{ #category : #testing } -VMBlockTest >> testCreatingABlockClosureShouldHaveCorrectPC [ - - | methodToTest | - methodToTest := self class >> #methodReturningABlock. - - self executeMethod: methodToTest. - - self flag:#'hard code for now should be modified'. - self - assert: (memory - fetchPointer: ClosureStartPCIndex - ofObject: interpreter stackTop) - equals: (memory integerObjectOf: 29) -] - { #category : #testing } VMBlockTest >> testCreatingABlockClosureShouldHaveOuterContextObject [ - | methodToTest | - methodToTest := self class >> #methodReturningABlock. + | methodOop previousMethodOop | + methodOop := self createMethodOopFromPharoMethod: + self class >> #methodReturningABlock. + + previousMethodOop := self createMethodOopFromPharoMethod: + self class >> #anEmptyMethod. - self executeMethod: methodToTest. + self installBlockClosureClass. + "We want to avoid baseFrameReturn (base frame initialisation)" + stackBuilder addNewFrame method: previousMethodOop. + stackBuilder addNewFrame + method: methodOop; + receiver: memory trueObject. + stackBuilder buildStack. + + interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodOop). + 1halt. + interpreter interpretWhile: [ interpreter method = methodOop ]. "Currently fails because the stack frame is not overriden. So the interpreter considers it's still married even thought the stack frame is already dead" - self assert: (interpreter isWidowedContext: - (memory outerContextOf: interpreter stackTop)) -] - -{ #category : #'as yet unclassified' } -VMBlockTest >> testCreatingABlockInsideABlockClosureShouldCopyUsedBlockVariable [ - - | methodToTest | - methodToTest := self class - >> #methodReturningABlockInsideABlockWithLocal. - - self executeMethod: methodToTest. - - "We assign 2 to the local variable of the block, see methodReturningABlockInsideABlock" self - assert: (memory - fetchPointer: ClosureFirstCopiedValueIndex - ofObject: interpreter stackTop) - equals: (memory integerObjectOf: 2) + assert: (interpreter isWidowedContext: (memory outerContextOf: interpreter stackTop)) + ] { #category : #testing } VMBlockTest >> testCreatingABlockWithTwoArgumentsClosureShouldHaveTwoArguments [ - | methodToTest | - methodToTest := self class >> #methodReturningABlockWithTwoArguments. - - self executeMethod: methodToTest. - - self - assert: (memory - fetchPointer: ClosureNumArgsIndex - ofObject: interpreter stackTop) - equals: (memory integerObjectOf: 2) -] + | methodOop previousMethodOop | + methodOop := self createMethodOopFromPharoMethod: + self class >> #methodReturningABlockWithTwoArguments. -{ #category : #testing } -VMBlockTest >> testCreatingABlockWithoutArgumentsClosureShouldHaveNoArgument [ + previousMethodOop := self createMethodOopFromPharoMethod: + self class >> #anEmptyMethod. - | methodToTest | - methodToTest := self class >> #methodReturningABlock. + self installBlockClosureClass. + "We want to avoid baseFrameReturn (base frame initialisation)" + stackBuilder addNewFrame method: previousMethodOop. + stackBuilder addNewFrame + method: methodOop; + receiver: memory trueObject. + stackBuilder buildStack. + + interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodOop). + interpreter interpretWhile: [ interpreter method = methodOop ]. - self executeMethod: methodToTest. self - assert: (memory - fetchPointer: ClosureNumArgsIndex - ofObject: interpreter stackTop) - equals: (memory integerObjectOf: 0) -] - -{ #category : #'as yet unclassified' } -VMBlockTest >> testEvaluatingABlock [ - - | methodToTest | - methodToTest := self class >> #evaluatingABlock. + assert: (memory fetchPointer: ClosureNumArgsIndex ofObject: interpreter stackTop) equals: (memory integerObjectOf: 2). - self executeMethod: methodToTest. - - self - assert: interpreter stackTop - equals: (memory integerObjectOf: 42) ] -{ #category : #'as yet unclassified' } -VMBlockTest >> testEvaluatingABlockWithLocalBlockVariable [ - - | methodToTest | - methodToTest := self class >> #evaluatingABlockWithLocalBlockVariable. - - self executeMethod: methodToTest. - - self - assert: interpreter stackTop - equals: (memory integerObjectOf: 42) -] +{ #category : #testing } +VMBlockTest >> testCreatingABlockWithoutArgumentsClosureShouldHaveNoArgument [ -{ #category : #'as yet unclassified' } -VMBlockTest >> testEvaluatingABlockWithLocalMethodVariable [ + | methodOop previousMethodOop | + methodOop := self createMethodOopFromPharoMethod: + self class >> #methodReturningABlock. - | methodToTest | - methodToTest := self class >> #evaluatingABlockWithLocalMethodVariableAssignedInTheBlock. + previousMethodOop := self createMethodOopFromPharoMethod: + self class >> #anEmptyMethod. - self executeMethod: methodToTest. + self installBlockClosureClass. + "We want to avoid baseFrameReturn (base frame initialisation)" + stackBuilder addNewFrame method: previousMethodOop. + stackBuilder addNewFrame + method: methodOop; + receiver: memory trueObject. + stackBuilder buildStack. + + interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodOop). + interpreter interpretWhile: [ interpreter method = methodOop ]. self - assert: interpreter stackTop - equals: (memory integerObjectOf: 42) -] - -{ #category : #'as yet unclassified' } -VMBlockTest >> testEvaluatingABlockWithNonLocalReturn [ + assert: (memory fetchPointer: ClosureNumArgsIndex ofObject: interpreter stackTop) equals: (memory integerObjectOf: 0). - | methodToTest | - methodToTest := self class >> #evaluatingABlockWithNonLocalReturn. - - self executeMethod: methodToTest. - - self assert: true ] { #category : #testing } VMBlockTest >> testPushClosureBytecodePushesClosure [ - |methodToTest| - methodToTest := self class >> #methodReturningABlock. + | methodOop previousMethodOop | + methodOop := self createMethodOopFromPharoMethod: + self class >> #methodReturningABlock. + + previousMethodOop := self createMethodOopFromPharoMethod: + self class >> #anEmptyMethod. + + self installBlockClosureClass. + "We want to avoid baseFrameReturn (base frame initialisation)" + stackBuilder addNewFrame method: previousMethodOop. + stackBuilder addNewFrame + method: methodOop; + receiver: memory trueObject. + stackBuilder buildStack. - self executeMethod: methodToTest. + interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodOop). + interpreter interpretWhile: [ interpreter method = methodOop ]. self assert: (memory fetchClassOf: interpreter stackTop) From e6c1e6cf466b5179e30985a44963321b8eee4a7d Mon Sep 17 00:00:00 2001 From: Theo Date: Thu, 17 Dec 2020 16:34:10 +0100 Subject: [PATCH 03/10] Dumb commit --- smalltalksrc/VMMakerTests/VMBlockTest.class.st | 1 - 1 file changed, 1 deletion(-) diff --git a/smalltalksrc/VMMakerTests/VMBlockTest.class.st b/smalltalksrc/VMMakerTests/VMBlockTest.class.st index 3ca8fdf8851..dbf7f1e8e5d 100644 --- a/smalltalksrc/VMMakerTests/VMBlockTest.class.st +++ b/smalltalksrc/VMMakerTests/VMBlockTest.class.st @@ -58,7 +58,6 @@ VMBlockTest >> testCreatingABlockClosureShouldHaveOuterContextObject [ stackBuilder buildStack. interpreter instructionPointer: (methodBuilder bytecodeAt: 0 forMethod: methodOop). - 1halt. interpreter interpretWhile: [ interpreter method = methodOop ]. "Currently fails because the stack frame is not overriden. From faa6a106cb69f8beee8a494200790f7e0f897d51 Mon Sep 17 00:00:00 2001 From: Theo Date: Thu, 17 Dec 2020 16:39:11 +0100 Subject: [PATCH 04/10] Lost those 3 methods --- .../VMMaker-Tools/SpurObject.class.st | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/smalltalksrc/VMMaker-Tools/SpurObject.class.st b/smalltalksrc/VMMaker-Tools/SpurObject.class.st index 7cc3ff1fbcc..5a4c16157f1 100644 --- a/smalltalksrc/VMMaker-Tools/SpurObject.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurObject.class.st @@ -52,6 +52,12 @@ SpurObject class >> on: address image: anImage [ ] +{ #category : #something } +SpurObject >> = aSpurObject [ + ^ self address = aSpurObject address + +] + { #category : #accessing } SpurObject >> address [ ^ address @@ -185,6 +191,16 @@ SpurObject >> memory [ ^ image memory ] +{ #category : #something } +SpurObject >> nextObject [ + + | maybeObject | + maybeObject := SpurObject on: self endAddress + self headerSize image: image. + ^ maybeObject basicNumberOfSlots = 16rFF + ifTrue: [ maybeObject ] + ifFalse: [ SpurObject on: self endAddress image: image ]. +] + { #category : #'as yet unclassified' } SpurObject >> numberOfSlots [ @@ -209,6 +225,16 @@ SpurObject >> previousHeaderInteger [ ^ self memory integerAt: address + (0 - self headerSize) size: 4 signed: false ] +{ #category : #something } +SpurObject >> printOn: aStream [ + + aStream nextPutAll: 'a(n) '. + self vmClass printSimpleOn: aStream. + aStream + nextPutAll: '@'; + nextPutAll: self address hex +] + { #category : #'as yet unclassified' } SpurObject >> printSimpleOn: aLimitedWriteStream [ From 1b6c18d5838cb9455445bf03952f551260a267c7 Mon Sep 17 00:00:00 2001 From: hogoww Date: Thu, 17 Dec 2020 16:50:39 +0100 Subject: [PATCH 05/10] [cleanup] correct ish protocol names... --- .../VMMaker-Tools/SpurObject.class.st | 32 +++++++++---------- .../EncoderForV3.extension.st | 10 ------ 2 files changed, 16 insertions(+), 26 deletions(-) delete mode 100644 smalltalksrc/VMMakerCompatibilityForPharo6/EncoderForV3.extension.st diff --git a/smalltalksrc/VMMaker-Tools/SpurObject.class.st b/smalltalksrc/VMMaker-Tools/SpurObject.class.st index 5a4c16157f1..205db7024d5 100644 --- a/smalltalksrc/VMMaker-Tools/SpurObject.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurObject.class.st @@ -52,7 +52,7 @@ SpurObject class >> on: address image: anImage [ ] -{ #category : #something } +{ #category : #testing } SpurObject >> = aSpurObject [ ^ self address = aSpurObject address @@ -74,7 +74,7 @@ SpurObject >> allSlots [ ^ self spurLayout allSlots ] -{ #category : #'as yet unclassified' } +{ #category : #converting } SpurObject >> asLocalByteArray [ ^ self spurLayout asLocalByteArray ] @@ -96,7 +96,7 @@ SpurObject >> basicNumberOfSlots [ ^ self spurLayout basicNumberOfSlots ] -{ #category : #'as yet unclassified' } +{ #category : #'accessing-header' } SpurObject >> byteSize [ | numberOfSlots | @@ -112,7 +112,7 @@ SpurObject >> classIndex [ ^ self headerInteger bitAnd: (2 raisedTo: 22) -1 ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SpurObject >> endAddress [ | basicSize padding | @@ -123,7 +123,7 @@ SpurObject >> endAddress [ ^ address + basicSize + padding ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SpurObject >> fetchPointer: anInteger [ ^ self image fetchPointer: anInteger ofObject: self address @@ -177,7 +177,7 @@ SpurObject >> indexInClassTable [ ^ self rawHashBits ] -{ #category : #'as yet unclassified' } +{ #category : #'accessing-slots' } SpurObject >> instanceVariables [ | numberOfSlots | @@ -201,7 +201,7 @@ SpurObject >> nextObject [ ifFalse: [ SpurObject on: self endAddress image: image ]. ] -{ #category : #'as yet unclassified' } +{ #category : #'accessing-slots' } SpurObject >> numberOfSlots [ ^ self image numberOfSlotsOf: self @@ -213,7 +213,7 @@ SpurObject >> objectFormat [ ^ (self headerInteger >> 24) bitAnd: 2r11111 ] -{ #category : #'as yet unclassified' } +{ #category : #converting } SpurObject >> oop [ ^ address @@ -225,7 +225,7 @@ SpurObject >> previousHeaderInteger [ ^ self memory integerAt: address + (0 - self headerSize) size: 4 signed: false ] -{ #category : #something } +{ #category : #printing } SpurObject >> printOn: aStream [ aStream nextPutAll: 'a(n) '. @@ -235,7 +235,7 @@ SpurObject >> printOn: aStream [ nextPutAll: self address hex ] -{ #category : #'as yet unclassified' } +{ #category : #printing } SpurObject >> printSimpleOn: aLimitedWriteStream [ aLimitedWriteStream nextPutAll: self address hex @@ -248,21 +248,21 @@ SpurObject >> rawHashBits [ ^((self memory unsignedLongAt: self oop + 4 bigEndian: false) bitAnd: self identityHashHalfWordMask) ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SpurObject >> simulator [ ^self image simulator ] { #category : #'accessing-slots' } SpurObject >> slotAt: anInteger [ -"Api is 1 based but the memory api is O based" + "Api is 1 based but the memory api is O based" ^ self spurLayout slotAt: anInteger - 1 ] -{ #category : #'as yet unclassified' } +{ #category : #'accessing-slots' } SpurObject >> slotAt: anInteger put: aSpurObject [ -"Our api is 1 based but the simulator is 0 based" + "Our api is 1 based but the simulator is 0 based" ^ self simulator storePointer: anInteger - 1 ofObject: self address @@ -289,12 +289,12 @@ SpurObject >> spurLayout: anObject [ spurLayout := anObject ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SpurObject >> vmClass [ ^self image classOf: self ] -{ #category : #'as yet unclassified' } +{ #category : #printing } SpurObject >> vmPrintOop [ diff --git a/smalltalksrc/VMMakerCompatibilityForPharo6/EncoderForV3.extension.st b/smalltalksrc/VMMakerCompatibilityForPharo6/EncoderForV3.extension.st deleted file mode 100644 index abfdc131f4c..00000000000 --- a/smalltalksrc/VMMakerCompatibilityForPharo6/EncoderForV3.extension.st +++ /dev/null @@ -1,10 +0,0 @@ -Extension { #name : #EncoderForV3 } - -{ #category : #'*VMMakerCompatibilityForPharo6-instruction stream support' } -EncoderForV3 class >> extensionsAt: pc in: aCompiledMethod into: trinaryBlock [ - "If the bytecode at pc is an extension then evaluate aTrinaryBlock - with the values of extA and extB and number of extension *bytes*. - If the bytecode at pc is not an extension then evaluate with 0, 0, 0. - There are no extensions in the SqueakV3/Smalltalk-80 bytecode set, so..." - ^trinaryBlock value: 0 value: 0 value: 0 -] From 1e810ebc708546630388b9e8868597e5a172f09a Mon Sep 17 00:00:00 2001 From: hogoww Date: Fri, 18 Dec 2020 16:54:24 +0100 Subject: [PATCH 06/10] [improvement] slightly better inspector --- .../VMMaker-Tools/SpurByteLayout.class.st | 2 +- smalltalksrc/VMMaker-Tools/SpurClass.class.st | 2 +- .../SpurCompiledMethodLayout.class.st | 2 +- .../VMMaker-Tools/SpurEmptyLayout.class.st | 2 +- .../VMMaker-Tools/SpurFileImage.class.st | 31 +++-- .../VMMaker-Tools/SpurFixedLayout.class.st | 2 +- .../VMMaker-Tools/SpurHiddenRoots.class.st | 2 +- smalltalksrc/VMMaker-Tools/SpurImage.class.st | 25 ++++- .../SpurImmediateLayout.class.st | 2 +- .../VMMaker-Tools/SpurLayout.class.st | 2 +- .../VMMaker-Tools/SpurMethod.class.st | 2 +- .../SpurMethodDictionary.class.st | 2 +- .../VMMaker-Tools/SpurObject.class.st | 104 ++++++++++++----- .../VMMaker-Tools/SpurSimulatorImage.class.st | 31 ++--- .../VMMaker-Tools/SpurVariableLayout.class.st | 2 +- ...riableWithInstanceVariablesLayout.class.st | 2 +- .../VMMaker-Tools/VMInspectorTest.class.st | 106 +++++++++++++++++- .../VMMakerTests/VMFrameBuilder.class.st | 14 --- 18 files changed, 252 insertions(+), 83 deletions(-) diff --git a/smalltalksrc/VMMaker-Tools/SpurByteLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurByteLayout.class.st index 558eb28cdd4..7ee8b1736ef 100644 --- a/smalltalksrc/VMMaker-Tools/SpurByteLayout.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurByteLayout.class.st @@ -1,7 +1,7 @@ Class { #name : #SpurByteLayout, #superclass : #SpurLayout, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #accessing } diff --git a/smalltalksrc/VMMaker-Tools/SpurClass.class.st b/smalltalksrc/VMMaker-Tools/SpurClass.class.st index 7919bd3f6a7..f66a90a2b3f 100644 --- a/smalltalksrc/VMMaker-Tools/SpurClass.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurClass.class.st @@ -1,7 +1,7 @@ Class { #name : #SpurClass, #superclass : #SpurObject, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #'accessing - instance variables' } diff --git a/smalltalksrc/VMMaker-Tools/SpurCompiledMethodLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurCompiledMethodLayout.class.st index ad7ed49e3d3..1b1af53bb1a 100644 --- a/smalltalksrc/VMMaker-Tools/SpurCompiledMethodLayout.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurCompiledMethodLayout.class.st @@ -1,7 +1,7 @@ Class { #name : #SpurCompiledMethodLayout, #superclass : #SpurLayout, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #testing } diff --git a/smalltalksrc/VMMaker-Tools/SpurEmptyLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurEmptyLayout.class.st index 0a1f296b509..bab65e4c2b0 100644 --- a/smalltalksrc/VMMaker-Tools/SpurEmptyLayout.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurEmptyLayout.class.st @@ -1,5 +1,5 @@ Class { #name : #SpurEmptyLayout, #superclass : #SpurLayout, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } diff --git a/smalltalksrc/VMMaker-Tools/SpurFileImage.class.st b/smalltalksrc/VMMaker-Tools/SpurFileImage.class.st index 135182cf965..acfcec79e54 100644 --- a/smalltalksrc/VMMaker-Tools/SpurFileImage.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurFileImage.class.st @@ -9,7 +9,7 @@ Class { 'oldBaseAddress', 'specialObjectsArrayOop' ], - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #'as yet unclassified' } @@ -132,16 +132,19 @@ SpurFileImage >> initialize [ super initialize. self readImageHeader. + simulator := self wordsize = 4 + ifTrue: [ Spur32BitMemoryManager simulatorClass new ] + ifFalse: [ Spur64BitMemoryManager simulatorClass new ]. ] { #category : #'special-classes' } -SpurFileImage >> is32bit [ - ^(format = 32) +SpurFileImage >> is32Bit [ + ^ format = 32 ] { #category : #'special-classes' } -SpurFileImage >> is64bit [ - ^(format = 64) +SpurFileImage >> is64Bit [ + ^ format = 64 ] { #category : #'special-classes' } @@ -172,6 +175,15 @@ SpurFileImage >> messageClass [ ^ self specialObjectsArray slotAt: 16 ] +{ #category : #'special-objects' } +SpurFileImage >> nextObjectOf: aSpurObject [ + | maybeObject | + maybeObject := SpurObject on: aSpurObject endAddress + self headerSize image: self. + ^ maybeObject basicNumberOfSlots = 16rFF + ifTrue: [ maybeObject ] + ifFalse: [ SpurObject on: aSpurObject endAddress image: self ]. +] + { #category : #'special-objects' } SpurFileImage >> nilObject [ ^ self firstObject @@ -204,9 +216,9 @@ SpurFileImage >> readImageHeader [ "Reading the version will allow us to find the format" self readVersionFromImageHeader. - self is32bit ifTrue:[ + self is32Bit ifTrue:[ self readImageHeader32 ]. - self is64bit ifTrue:[ + self is64Bit ifTrue:[ self readImageHeader64 ] ] @@ -302,3 +314,8 @@ SpurFileImage >> specialObjectsArray [ SpurFileImage >> specialObjectsArrayOop: anInteger [ specialObjectsArrayOop := anInteger ] + +{ #category : #'special-classes' } +SpurFileImage >> wordsize [ + ^ self is32Bit ifTrue: [ 4 ] ifFalse: [ 8 ] +] diff --git a/smalltalksrc/VMMaker-Tools/SpurFixedLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurFixedLayout.class.st index b5b763d7b6e..4f9c14f15b3 100644 --- a/smalltalksrc/VMMaker-Tools/SpurFixedLayout.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurFixedLayout.class.st @@ -1,7 +1,7 @@ Class { #name : #SpurFixedLayout, #superclass : #SpurLayout, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #'gt-inspector-extension' } diff --git a/smalltalksrc/VMMaker-Tools/SpurHiddenRoots.class.st b/smalltalksrc/VMMaker-Tools/SpurHiddenRoots.class.st index 0adc9bf159a..79d729008c9 100644 --- a/smalltalksrc/VMMaker-Tools/SpurHiddenRoots.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurHiddenRoots.class.st @@ -1,7 +1,7 @@ Class { #name : #SpurHiddenRoots, #superclass : #SpurObject, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #'as yet unclassified' } diff --git a/smalltalksrc/VMMaker-Tools/SpurImage.class.st b/smalltalksrc/VMMaker-Tools/SpurImage.class.st index 30b7e2da480..7e5fe00f914 100644 --- a/smalltalksrc/VMMaker-Tools/SpurImage.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurImage.class.st @@ -12,9 +12,10 @@ Class { #superclass : #Object, #instVars : [ 'hiddenRoots', - 'classTable' + 'classTable', + 'simulator' ], - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #constants } @@ -99,12 +100,32 @@ SpurImage >> imageFormat: anInteger [ self shouldBeImplemented. ] +{ #category : #'special-objects' } +SpurImage >> nextObjectOf: anOop [ + ^ self subclassResponsibility +] + { #category : #'special-objects' } SpurImage >> nilObject [ ^ self subclassResponsibility ] +{ #category : #'as yet unclassified' } +SpurImage >> simulator [ + ^ simulator +] + +{ #category : #'as yet unclassified' } +SpurImage >> simulator: aSpur64BitMMLESimulator [ + simulator := aSpur64BitMMLESimulator +] + { #category : #'special-objects' } SpurImage >> trueObject [ ^ self falseObject nextObject ] + +{ #category : #'special-objects' } +SpurImage >> wordsize [ + ^ self subclassResponsibility +] diff --git a/smalltalksrc/VMMaker-Tools/SpurImmediateLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurImmediateLayout.class.st index 49a9a783883..6c0e8a3c5f9 100644 --- a/smalltalksrc/VMMaker-Tools/SpurImmediateLayout.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurImmediateLayout.class.st @@ -1,5 +1,5 @@ Class { #name : #SpurImmediateLayout, #superclass : #SpurLayout, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } diff --git a/smalltalksrc/VMMaker-Tools/SpurLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurLayout.class.st index 39492a2bd20..592b339fe3d 100644 --- a/smalltalksrc/VMMaker-Tools/SpurLayout.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurLayout.class.st @@ -4,7 +4,7 @@ Class { #instVars : [ 'object' ], - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #'as yet unclassified' } diff --git a/smalltalksrc/VMMaker-Tools/SpurMethod.class.st b/smalltalksrc/VMMaker-Tools/SpurMethod.class.st index 5dced4636a9..58e91ca2971 100644 --- a/smalltalksrc/VMMaker-Tools/SpurMethod.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurMethod.class.st @@ -1,7 +1,7 @@ Class { #name : #SpurMethod, #superclass : #SpurObject, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #accessing } diff --git a/smalltalksrc/VMMaker-Tools/SpurMethodDictionary.class.st b/smalltalksrc/VMMaker-Tools/SpurMethodDictionary.class.st index dd64011d524..d50b39f7cdb 100644 --- a/smalltalksrc/VMMaker-Tools/SpurMethodDictionary.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurMethodDictionary.class.st @@ -1,7 +1,7 @@ Class { #name : #SpurMethodDictionary, #superclass : #SpurObject, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #accessing } diff --git a/smalltalksrc/VMMaker-Tools/SpurObject.class.st b/smalltalksrc/VMMaker-Tools/SpurObject.class.st index 205db7024d5..cddafad6856 100644 --- a/smalltalksrc/VMMaker-Tools/SpurObject.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurObject.class.st @@ -40,7 +40,7 @@ Class { 'image', 'spurLayout' ], - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #'as yet unclassified' } @@ -53,9 +53,11 @@ SpurObject class >> on: address image: anImage [ ] { #category : #testing } -SpurObject >> = aSpurObject [ - ^ self address = aSpurObject address +SpurObject >> = anotherObject [ + "if an oop is provided directly, we still allow the comparison" + (anotherObject isKindOf: SmallInteger) ifTrue: [ ^ anotherObject = address ]. + ^ anotherObject address = address ] { #category : #accessing } @@ -112,6 +114,11 @@ SpurObject >> classIndex [ ^ self headerInteger bitAnd: (2 raisedTo: 22) -1 ] +{ #category : #printing } +SpurObject >> classOop [ + ^ self simulator fetchClassOf: address +] + { #category : #accessing } SpurObject >> endAddress [ @@ -179,10 +186,22 @@ SpurObject >> indexInClassTable [ { #category : #'accessing-slots' } SpurObject >> instanceVariables [ + ^ (1 to: self numSlots) collect: [ :index | self slotAt: index ] +] - | numberOfSlots | - numberOfSlots := self image numberOfSlotsOf: self. - ^ (1 to: numberOfSlots) collect: [ :index | self slotAt: index ] +{ #category : #testing } +SpurObject >> isImmediate [ + ^ self simulator isImmediate: address +] + +{ #category : #testing } +SpurObject >> isOld [ + ^ self simulator isOldObject: self address +] + +{ #category : #testing } +SpurObject >> isYoung [ + ^ self simulator isYoungObject: self address ] { #category : #accessing } @@ -193,18 +212,12 @@ SpurObject >> memory [ { #category : #something } SpurObject >> nextObject [ - - | maybeObject | - maybeObject := SpurObject on: self endAddress + self headerSize image: image. - ^ maybeObject basicNumberOfSlots = 16rFF - ifTrue: [ maybeObject ] - ifFalse: [ SpurObject on: self endAddress image: image ]. + ^ image nextObjectOf: self ] { #category : #'accessing-slots' } -SpurObject >> numberOfSlots [ - - ^ self image numberOfSlotsOf: self +SpurObject >> numSlots [ + ^ self image numSlotsOf: self. ] { #category : #'accessing-header' } @@ -225,20 +238,47 @@ SpurObject >> previousHeaderInteger [ ^ self memory integerAt: address + (0 - self headerSize) size: 4 signed: false ] +{ #category : #printing } +SpurObject >> printAsCharacter [ + ^ self shouldBeImplemented +] + +{ #category : #printing } +SpurObject >> printAsImmediate [ + self isCharacter ifTrue: [ ^ self printAsCharacter ]. + "default case is a smallInteger" + ^ self printAsInteger +] + +{ #category : #printing } +SpurObject >> printAsInteger [ + ^ 'SmallInteger: ', address printString +] + { #category : #printing } SpurObject >> printOn: aStream [ + | knownObject | + knownObject := VMFrameBuilder new memory: self simulator ; adaptAddressToMemory: address. + knownObject isString ifTrue: [ ^ aStream << knownObject ]. - aStream nextPutAll: 'a(n) '. - self vmClass printSimpleOn: aStream. - aStream - nextPutAll: '@'; - nextPutAll: self address hex + self isImmediate ifTrue:[ ^ aStream << self printAsImmediate ]. + + address printOn: aStream + ] { #category : #printing } -SpurObject >> printSimpleOn: aLimitedWriteStream [ +SpurObject >> printString [ + | knownObject | + knownObject := VMFrameBuilder new memory: self simulator ; adaptAddressToMemory: address. + knownObject isString ifTrue: [ ^ knownObject ]. + + self isImmediate ifTrue:[ ^ self printAsImmediate ]. + + ^ String streamContents: [ :s | + s << address printString. + ] - aLimitedWriteStream nextPutAll: self address hex ] { #category : #'accessing-header' } @@ -254,19 +294,27 @@ SpurObject >> simulator [ ] { #category : #'accessing-slots' } -SpurObject >> slotAt: anInteger [ +SpurObject >> slotAt: anIndex [ "Api is 1 based but the memory api is O based" - - ^ self spurLayout slotAt: anInteger - 1 + self numSlots >= anIndex ifFalse: [ SubscriptOutOfBounds signal ]. + ^ SpurObject on: (self spurLayout slotAt: anIndex - 1) image: image ] { #category : #'accessing-slots' } -SpurObject >> slotAt: anInteger put: aSpurObject [ +SpurObject >> slotAt: anIndex put: aSpurObjectOrOop [ "Our api is 1 based but the simulator is 0 based" + + | value | + self numSlots >= anIndex ifFalse: [ SubscriptOutOfBounds signal ]. + + value := aSpurObjectOrOop isInteger + ifTrue:[ aSpurObjectOrOop ] + ifFalse: [ aSpurObjectOrOop address ]. + ^ self simulator - storePointer: anInteger - 1 + storePointer: anIndex - 1 ofObject: self address - withValue: aSpurObject address + withValue: value ] { #category : #accessing } diff --git a/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st b/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st index c7d352aca9c..29a7671440a 100644 --- a/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st @@ -1,13 +1,10 @@ Class { #name : #SpurSimulatorImage, #superclass : #SpurImage, - #instVars : [ - 'simulator' - ], #classInstVars : [ 'simulator' ], - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #'as yet unclassified' } @@ -23,6 +20,11 @@ SpurSimulatorImage >> classOf: aSpurObject [ ^self objectForOop: (simulator fetchClassOf: aSpurObject address) ] +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> falseObject [ + ^ self objectForOop: simulator falseObject +] + { #category : #'as yet unclassified' } SpurSimulatorImage >> fetchPointer: anInteger ofObject: objectOop [ @@ -39,14 +41,20 @@ SpurSimulatorImage >> memory [ ^simulator ] +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> nextObjectOf: anOop [ + "The simulator relies on class indexes, which we do not really set" + self shouldNotImplement +] + { #category : #'as yet unclassified' } SpurSimulatorImage >> nilObject [ - ^SpurObject on: simulator nilObject image: self + ^ SpurObject on: simulator nilObject image: self ] { #category : #'as yet unclassified' } -SpurSimulatorImage >> numberOfSlotsOf: aSpurObject [ +SpurSimulatorImage >> numSlotsOf: aSpurObject [ ^simulator numSlotsOf: aSpurObject address ] @@ -58,16 +66,11 @@ SpurSimulatorImage >> objectForOop: anInteger [ ] { #category : #'as yet unclassified' } -SpurSimulatorImage >> simulator [ - ^ simulator -] - -{ #category : #'as yet unclassified' } -SpurSimulatorImage >> simulator: aSpur64BitMMLESimulator [ - simulator := aSpur64BitMMLESimulator +SpurSimulatorImage >> trueObject [ + ^ self objectForOop: simulator trueObject ] { #category : #'as yet unclassified' } SpurSimulatorImage >> wordSize [ - ^simulator wordSize + ^ simulator wordSize ] diff --git a/smalltalksrc/VMMaker-Tools/SpurVariableLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurVariableLayout.class.st index 807fe64b678..5dbeb2fd8dc 100644 --- a/smalltalksrc/VMMaker-Tools/SpurVariableLayout.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurVariableLayout.class.st @@ -1,7 +1,7 @@ Class { #name : #SpurVariableLayout, #superclass : #SpurLayout, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } { #category : #'gt-inspector-extension' } diff --git a/smalltalksrc/VMMaker-Tools/SpurVariableWithInstanceVariablesLayout.class.st b/smalltalksrc/VMMaker-Tools/SpurVariableWithInstanceVariablesLayout.class.st index f02f3b3e403..e710a991be7 100644 --- a/smalltalksrc/VMMaker-Tools/SpurVariableWithInstanceVariablesLayout.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurVariableWithInstanceVariablesLayout.class.st @@ -1,5 +1,5 @@ Class { #name : #SpurVariableWithInstanceVariablesLayout, #superclass : #SpurLayout, - #category : #'VMMaker-Tools-Model' + #category : #'VMMaker-Tools-imageInspector' } diff --git a/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st index a6e4dffea28..af9de4db1e9 100644 --- a/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st +++ b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st @@ -22,6 +22,47 @@ VMInspectorTest >> setUp [ +] + +{ #category : #tests } +VMInspectorTest >> testEqualsOtherObject [ + | object1 object2 | + object1 := image objectForOop: (image simulator integerObjectOf: 42). + object2 := image objectForOop: (image simulator integerObjectOf: 42). + + self assert: object1 equals: object2 +] + +{ #category : #'test-testing' } +VMInspectorTest >> testIsImmediateObject [ + | object | + object := image objectForOop: (image simulator integerObjectOf: 42). + + self assert: object isImmediate +] + +{ #category : #'test-testing' } +VMInspectorTest >> testIsNotImmediateObject [ + | object | + object := image objectForOop: (self newObjectWithSlots: 1). + + self assert: object isImmediate not +] + +{ #category : #'test-testing' } +VMInspectorTest >> testIsOld [ + | oop | + oop := SpurObject on: (self newOldSpaceObjectWithSlots: 1) image: image. + + self assert: oop isOld. +] + +{ #category : #'test-testing' } +VMInspectorTest >> testIsYoung [ + | oop | + oop := SpurObject on: (self newObjectWithSlots: 1) image: image. + + self assert: oop isYoung. ] { #category : #tests } @@ -30,6 +71,24 @@ VMInspectorTest >> testNilHasNoInstanceVariable [ self assert: image nilObject instanceVariables isEmpty. ] +{ #category : #'tests-printing' } +VMInspectorTest >> testNotEqualsNil [ + | object1 object2 | + object1 := image objectForOop: (image simulator integerObjectOf: 42). + object2 := image objectForOop: (image simulator nilObject). + + self deny: object1 equals: object2 +] + +{ #category : #'tests-printing' } +VMInspectorTest >> testObjectEqualOop [ + | object1 object2 | + object1 := image objectForOop: (image simulator integerObjectOf: 42). + object2 := image simulator integerObjectOf: 42. + + self assert: object1 equals: object2 +] + { #category : #tests } VMInspectorTest >> testObjectWithInstanceVariableCycleWeCanNavigate [ @@ -43,8 +102,8 @@ VMInspectorTest >> testObjectWithInstanceVariableCycleWeCanNavigate [ object1 slotAt: 1 put: object2. object2 slotAt: 1 put: object1. - self assert: (object1 slotAt: 1) equals: object2. - self assert: (object2 slotAt: 1) equals: object1. + self assert: (object1 slotAt: 1) address equals: object2. + self assert: (object2 slotAt: 1) address equals: object1. ] { #category : #tests } @@ -55,10 +114,45 @@ VMInspectorTest >> testObjectWithInstanceVariableHasInstanceVariable [ self assert: (image objectForOop: objectOop) instanceVariables isNotEmpty. ] -{ #category : #tests } +{ #category : #'tests-printing' } +VMInspectorTest >> testObjectWithNilClass [ + | oop object | + oop := self newObjectWithSlots: 1. + object := SpurObject on: oop image: image. + + self assert: object printString equals: oop printString +] + +{ #category : #'tests-printing' } +VMInspectorTest >> testPrintFalse [ + + self assert: 'falseObject' equals: image falseObject printString +] + +{ #category : #'tests-printing' } VMInspectorTest >> testPrintNil [ - | nilObject | - nilObject:= image nilObject. - self assert: nilObject printString equals: 'a(n) ', nilObject address hex, '@', nilObject address hex. + self assert: 'nilObject' equals: image nilObject printString +] + +{ #category : #'tests-printing' } +VMInspectorTest >> testPrintTrue [ + + self assert: 'trueObject' equals: image trueObject printString +] + +{ #category : #tests } +VMInspectorTest >> testSlotAtPut [ + + | objectOop1 object1 objectOop2 object2 | + objectOop1 := self newObjectWithSlots: 1. + objectOop2 := self newObjectWithSlots: 1. + + object1 := (image objectForOop: objectOop1). + object2 := (image objectForOop: objectOop2). + + object1 slotAt: 1 put: object2. + object2 slotAt: 1 put: object1. + + self assert: (object1 slotAt: 1) address equals: object2. ] diff --git a/smalltalksrc/VMMakerTests/VMFrameBuilder.class.st b/smalltalksrc/VMMakerTests/VMFrameBuilder.class.st index 15ad604be67..491e4b2af05 100644 --- a/smalltalksrc/VMMakerTests/VMFrameBuilder.class.st +++ b/smalltalksrc/VMMakerTests/VMFrameBuilder.class.st @@ -160,20 +160,6 @@ VMFrameBuilder >> gtInspectorItemsIn: composite [ ] -{ #category : #initialization } -VMFrameBuilder >> initializeWithInterpreter: anInterpreter andMemory: aMemory [ - memory := aMemory. - interpreter := anInterpreter. "allow to not care if it's for a cog or stack interpreter" - method := memory nilObject. - context := memory nilObject. - receiver := memory nilObject. - temps := OrderedCollection new. - stack := OrderedCollection new. - - previousFrameArgsSize := 0. " set by the StackBuilder" - argumentSize := 0. -] - { #category : #accesing } VMFrameBuilder >> instructionPointer [ ^ instructionPointer From b74810f0a46ce8f4d2ab2d4ad596423bfe5c32f7 Mon Sep 17 00:00:00 2001 From: hogoww Date: Tue, 4 May 2021 17:16:14 +0200 Subject: [PATCH 07/10] [improvement] better inspection, when sending a message to the VM, we use the oop value, not the object --- .../VMMaker-Tools/SpurObject.class.st | 74 +++++++++++++++++-- .../VMMaker-Tools/SpurSimulatorImage.class.st | 25 ++++++- .../VMMaker-Tools/VMInspectorTest.class.st | 43 ++++++++++- 3 files changed, 132 insertions(+), 10 deletions(-) diff --git a/smalltalksrc/VMMaker-Tools/SpurObject.class.st b/smalltalksrc/VMMaker-Tools/SpurObject.class.st index cddafad6856..8ee0d304ba1 100644 --- a/smalltalksrc/VMMaker-Tools/SpurObject.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurObject.class.st @@ -83,7 +83,7 @@ SpurObject >> asLocalByteArray [ { #category : #converting } SpurObject >> asSpurClass [ - ^ SpurClass on: self address image: self image + ^ SpurClass on: address image: self image ] { #category : #accessing } @@ -116,7 +116,12 @@ SpurObject >> classIndex [ { #category : #printing } SpurObject >> classOop [ - ^ self simulator fetchClassOf: address + ^ self simulator fetchClassOf: address value +] + +{ #category : #printing } +SpurObject >> classSpurObject [ + ^ self class on: self classOop image: image ] { #category : #accessing } @@ -133,7 +138,7 @@ SpurObject >> endAddress [ { #category : #accessing } SpurObject >> fetchPointer: anInteger [ - ^ self image fetchPointer: anInteger ofObject: self address + ^ self image fetchPointer: anInteger ofObject: self address value ] { #category : #'accessing-header' } @@ -149,6 +154,11 @@ SpurObject >> gtInspectorLayoutIn: composite [ ] +{ #category : #accessing } +SpurObject >> header [ + ^ self isImmediate ifFalse: [ image simulator baseHeader: address value] +] + { #category : #'accessing-header' } SpurObject >> headerInteger [ @@ -184,6 +194,41 @@ SpurObject >> indexInClassTable [ ^ self rawHashBits ] +{ #category : #accessing } +SpurObject >> inspectionItems: aBuilder [ + + | items | + self isImmediate ifTrue: [ + ^ address value inspectIntegerIn: aBuilder ]. + items := { + #header -> (self header printStringBase: 2). + #class -> self classSpurObject. + #numSlots -> self numSlots. + + } asDictionary. + 1 to: self numSlots do: [ :i| + items add: (('slot', i printString) -> (self slotAt: i)) ]. + items add: #format -> self format. + items add: #hash -> self oopHash. + items add: #pinned -> self isPinned. + items add: (#space -> (self isOld ifTrue: 'Old Space' ifFalse: 'Young Space')). + items add: #immutable -> self isImmutable. + + + + ^ aBuilder newTable + addColumn: (SpStringTableColumn + title: 'Key' + evaluated: [ :each | StObjectPrinter asTruncatedTextFrom: each key ]) + beSortable; + addColumn: (SpStringTableColumn + title: 'Value' + evaluated: [ :each | StObjectPrinter asTruncatedTextFrom: each value ]) + beSortable; + items: items associations; + yourself +] + { #category : #'accessing-slots' } SpurObject >> instanceVariables [ ^ (1 to: self numSlots) collect: [ :index | self slotAt: index ] @@ -191,17 +236,22 @@ SpurObject >> instanceVariables [ { #category : #testing } SpurObject >> isImmediate [ - ^ self simulator isImmediate: address + ^ self simulator isImmediate: address value +] + +{ #category : #testing } +SpurObject >> isImmutable [ + ^ image simulator isImmutable: address value ] { #category : #testing } SpurObject >> isOld [ - ^ self simulator isOldObject: self address + ^ self simulator isOldObject: self address value ] { #category : #testing } SpurObject >> isYoung [ - ^ self simulator isYoungObject: self address + ^ self simulator isYoungObject: self address value ] { #category : #accessing } @@ -232,6 +282,11 @@ SpurObject >> oop [ ^ address ] +{ #category : #something } +SpurObject >> oopHash [ + ^ image simulator rawHashBitsOf: address value +] + { #category : #'accessing-header' } SpurObject >> previousHeaderInteger [ @@ -337,6 +392,13 @@ SpurObject >> spurLayout: anObject [ spurLayout := anObject ] +{ #category : #testing } +SpurObject >> value [ + ^ (address class includesBehavior: SpurObject) + ifTrue: [ address address ] + ifFalse: [ address ] +] + { #category : #accessing } SpurObject >> vmClass [ ^self image classOf: self diff --git a/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st b/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st index 29a7671440a..dade6b16f0e 100644 --- a/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurSimulatorImage.class.st @@ -1,6 +1,9 @@ Class { #name : #SpurSimulatorImage, #superclass : #SpurImage, + #instVars : [ + 'currentObject' + ], #classInstVars : [ 'simulator' ], @@ -20,6 +23,11 @@ SpurSimulatorImage >> classOf: aSpurObject [ ^self objectForOop: (simulator fetchClassOf: aSpurObject address) ] +{ #category : #accessing } +SpurSimulatorImage >> currentObject: anOop [ + currentObject := anOop +] + { #category : #'as yet unclassified' } SpurSimulatorImage >> falseObject [ ^ self objectForOop: simulator falseObject @@ -33,7 +41,20 @@ SpurSimulatorImage >> fetchPointer: anInteger ofObject: objectOop [ { #category : #'as yet unclassified' } SpurSimulatorImage >> headerOf: anInteger [ - ^simulator objectMemory baseHeader: anInteger + ^simulator objectMemory baseHeader: anInteger value +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> inspectOop: anOop [ + ^ (SpurObject on: anOop image: self) inspect +] + +{ #category : #'as yet unclassified' } +SpurSimulatorImage >> inspectionItems: aBuilder [ + + ^ aBuilder newList + items: { currentObject }; + yourself ] { #category : #'as yet unclassified' } @@ -56,7 +77,7 @@ SpurSimulatorImage >> nilObject [ { #category : #'as yet unclassified' } SpurSimulatorImage >> numSlotsOf: aSpurObject [ - ^simulator numSlotsOf: aSpurObject address + ^simulator numSlotsOf: aSpurObject address value ] { #category : #'as yet unclassified' } diff --git a/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st index af9de4db1e9..02bfaab8c4a 100644 --- a/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st +++ b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st @@ -13,15 +13,36 @@ Class { #category : #'VMMaker-Tools-Tests' } +{ #category : #tests } +VMInspectorTest >> setSmallIntegerClassIntoClassTable [ + + | class | + class := self + newClassInOldSpaceWithSlots: 0 + instSpec: memory forwardedFormat. + image simulator setHashBitsOf: class to: memory smallIntegerTag. + image simulator + storePointer: memory smallIntegerTag + ofObject: memory classTableFirstPage + withValue: class. + ^class + +] + { #category : #running } VMInspectorTest >> setUp [ super setUp. image := SpurSimulatorImage onSpurSimulator: memory. +] +{ #category : #'test-testing' } +VMInspectorTest >> testClassOfObjectIsNilObjectByDefault [ + | objectOop object | + objectOop := self newObjectWithSlots: 1. - - + object := (image objectForOop: objectOop). + self assert: object classSpurObject equals: image simulator nilObject ] { #category : #tests } @@ -33,6 +54,24 @@ VMInspectorTest >> testEqualsOtherObject [ self assert: object1 equals: object2 ] +{ #category : #tests } +VMInspectorTest >> testInspectOopInspectRightObject [ + | objectOop window | + objectOop := self newObjectWithSlots: 1. + window := image inspectOop: objectOop. + [self assert: window title equals: 'Inspector on ', objectOop printString] + ensure: [ window close ] +] + +{ #category : #tests } +VMInspectorTest >> testIntegerKnowsItsClass [ + | class object | + class := self setSmallIntegerClassIntoClassTable. + object := SpurObject on: (image simulator integerObjectOf: 42) image: image. + object inspect. + self assert: class equals: object classOop +] + { #category : #'test-testing' } VMInspectorTest >> testIsImmediateObject [ | object | From 78f0a7c29d939c989cdad70551d02997f8571a5e Mon Sep 17 00:00:00 2001 From: hogoww Date: Tue, 4 May 2021 17:29:11 +0200 Subject: [PATCH 08/10] [cleanup] --- smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st | 1 - 1 file changed, 1 deletion(-) diff --git a/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st index 02bfaab8c4a..a98a21e7a28 100644 --- a/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st +++ b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st @@ -68,7 +68,6 @@ VMInspectorTest >> testIntegerKnowsItsClass [ | class object | class := self setSmallIntegerClassIntoClassTable. object := SpurObject on: (image simulator integerObjectOf: 42) image: image. - object inspect. self assert: class equals: object classOop ] From 4f0325ff9dc4b7ae2db22bf3931b822bb22daa75 Mon Sep 17 00:00:00 2001 From: hogoww Date: Tue, 4 May 2021 17:29:37 +0200 Subject: [PATCH 09/10] [improvement]add immutability tests --- .../VMMaker-Tools/VMInspectorTest.class.st | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st index a98a21e7a28..996e4250163 100644 --- a/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st +++ b/smalltalksrc/VMMaker-Tools/VMInspectorTest.class.st @@ -54,6 +54,24 @@ VMInspectorTest >> testEqualsOtherObject [ self assert: object1 equals: object2 ] +{ #category : #'test-testing' } +VMInspectorTest >> testImmutability [ + | object objectOop | + objectOop := (self newObjectWithSlots: 1). + object := image objectForOop: objectOop. + image simulator setIsImmutableOf: objectOop to: true. + + self assert: object isImmutable +] + +{ #category : #'test-testing' } +VMInspectorTest >> testImmutabilityISFalseByDefault [ + | object | + object := image objectForOop: (self newObjectWithSlots: 1). + + self assert: object isImmutable not +] + { #category : #tests } VMInspectorTest >> testInspectOopInspectRightObject [ | objectOop window | From 05ba902bb0242ee5cda812ff1e914fe4c3df5a6a Mon Sep 17 00:00:00 2001 From: hogoww Date: Tue, 4 May 2021 17:30:40 +0200 Subject: [PATCH 10/10] [improvement] better order, add classIndex --- smalltalksrc/VMMaker-Tools/SpurObject.class.st | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/smalltalksrc/VMMaker-Tools/SpurObject.class.st b/smalltalksrc/VMMaker-Tools/SpurObject.class.st index 8ee0d304ba1..dc364c74d5a 100644 --- a/smalltalksrc/VMMaker-Tools/SpurObject.class.st +++ b/smalltalksrc/VMMaker-Tools/SpurObject.class.st @@ -203,9 +203,9 @@ SpurObject >> inspectionItems: aBuilder [ items := { #header -> (self header printStringBase: 2). #class -> self classSpurObject. - #numSlots -> self numSlots. - - } asDictionary. + #classIndex -> self classIndex. + #numSlots -> self numSlots. + } asOrderedCollection . 1 to: self numSlots do: [ :i| items add: (('slot', i printString) -> (self slotAt: i)) ]. items add: #format -> self format. @@ -225,7 +225,7 @@ SpurObject >> inspectionItems: aBuilder [ title: 'Value' evaluated: [ :each | StObjectPrinter asTruncatedTextFrom: each value ]) beSortable; - items: items associations; + items: items; yourself ]