Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hi sendVTable bytecode :) #11

Draft
wants to merge 11 commits into
base: pharo-12
Choose a base branch
from
1 change: 1 addition & 0 deletions smalltalksrc/Melchor/VMObjectIndices.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Class {
'TheLowSpaceSemaphore',
'TheTimerSemaphore',
'TrueObject',
'VTableIndex',
'ValueIndex',
'XIndex',
'YIndex'
Expand Down
12 changes: 12 additions & 0 deletions smalltalksrc/VMMaker/CoInterpreter.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -1685,6 +1685,18 @@ CoInterpreter >> ceSendFromInLineCacheMiss: cogMethodOrPIC [
self unreachable
]

{ #category : 'trampolines' }
CoInterpreter >> ceSendFromVTableInterpreted: aMethod [
<api>

instructionPointer := self popStack.
newMethod := aMethod.
primitiveFunctionPointer := 0.

self executeNewMethod: false.
self returnToExecutive: false
]

{ #category : 'trampolines' }
CoInterpreter >> ceSendMustBeBoolean: anObject [
<api>
Expand Down
16 changes: 16 additions & 0 deletions smalltalksrc/VMMaker/CogARMv8Compiler.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,7 @@ CogARMv8Compiler >> computeMaximumSize [
[Nop] -> [^4].
"Control"
[Call] -> [^4].
[CallR] -> [^4].
[CallFull] -> [^self literalLoadInstructionBytes + 4].
[JumpR] -> [^4].
[Jump] -> [^4].
Expand Down Expand Up @@ -1590,6 +1591,20 @@ CogARMv8Compiler >> concretizeCallFull [
^ machineCodeSize := instrOffset + 4
]

{ #category : 'generate machine code' }
CogARMv8Compiler >> concretizeCallR [

"C5.6.27 BLR
Branch with link to register, calls a subroutine at an address in a register, setting register X30 to PC + 4"

| reg op |
self assert: (operands at: 0) ~= 0.
op := 2r1101011000111111000000 << 10.
reg := (operands at: 0) signedIntFromLong << 5.
self machineCodeAt: 0 put: op + reg.
^ machineCodeSize := 4
]

{ #category : 'generate machine code' }
CogARMv8Compiler >> concretizeCmpC32R [

Expand Down Expand Up @@ -3413,6 +3428,7 @@ CogARMv8Compiler >> dispatchConcretize [
[Nop] -> [^self concretizeNop].
"Control"
[Call] -> [^self concretizeCall]. "call code within code space"
[CallR] -> [^self concretizeCallR]. "call to a Register"
[CallFull] -> [^self concretizeCallFull]. "call code anywhere in address space"
[JumpR] -> [^self concretizeJumpR].
[JumpFull] -> [^self concretizeJumpFull]."jump within address space"
Expand Down
2 changes: 1 addition & 1 deletion smalltalksrc/VMMaker/CogAbstractInstruction.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,7 @@ CogAbstractInstruction >> getOperandsWithFormat: format [
ifTrue: [ (operand > 16 and: [ opcode ~= Label ])
ifTrue: [
(operand allMask: 16r80000000)
ifTrue: [ strOperands add: operand, '/', operand signedIntFromLong ].
ifTrue: [ strOperands add: operand asString, '/', operand signedIntFromLong asString ].
strOperands add: operand asString, '/', (operand hex)]
ifFalse: [
strOperands add: operand.
Expand Down
6 changes: 4 additions & 2 deletions smalltalksrc/VMMaker/Cogit.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ Class {
'statCompileMethodUsecs',
'jitCodeZoneWriteEnabled',
'cePrimReturnEnterCogCode',
'cePrimReturnEnterCogCodeProfiling'
'cePrimReturnEnterCogCodeProfiling',
'vTableSend'
],
#classVars : [
'AnnotationConstantNames',
Expand Down Expand Up @@ -1340,7 +1341,7 @@ Cogit class >> notesAndQueries [

{ #category : 'accessing' }
Cogit class >> numTrampolines [
^39 "31 + 4 each for self and super sends"
^40 "31 + 4 * 2 each for self and super sends + 1 for vTable"

"self withAllSubclasses collect: [:c| {c. (c instVarNames select: [:ea| ea beginsWith: 'ce']) size}]"
]
Expand Down Expand Up @@ -7995,6 +7996,7 @@ Cogit >> generateRunTimeTrampolines [

{ #category : 'initialization' }
Cogit >> generateSendTrampolines [

0 to: NumSendTrampolines - 1 do:
[:numArgs|
ordinarySendTrampolines
Expand Down
30 changes: 29 additions & 1 deletion smalltalksrc/VMMaker/StackInterpreter.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,9 @@ StackInterpreter class >> initializeBytecodeTableForSistaV1 [
(244 extStoreLiteralVariableBytecode)
(245 longStoreTemporaryVariableBytecode)

(246 247 unknownBytecode)
(246 sendVTableMessage)

(247 unknownBytecode)

"3 byte bytecodes"
(248 callPrimitiveBytecode)
Expand Down Expand Up @@ -798,6 +800,7 @@ StackInterpreter class >> initializeClassIndices [
SuperclassIndex := 0.
MethodDictionaryIndex := 1.
InstanceSpecificationIndex := 2.
VTableIndex := 5.
"Fields of a message dictionary"
MethodArrayIndex := 1.
SelectorStart := 2.
Expand Down Expand Up @@ -7622,6 +7625,7 @@ StackInterpreter >> initialize [
statProcessSwitch := statStackPageDivorce :=
statIdleUsecs := 0.
imageVersionNumber := 0.
desiredStackPageBytes := 256 * objectMemory wordSize.
]

{ #category : 'initialization' }
Expand Down Expand Up @@ -13624,6 +13628,30 @@ StackInterpreter >> sendLiteralSelector2ArgsBytecode [
self commonSendOrdinary
]

{ #category : 'bytecodes' }
StackInterpreter >> sendVTableMessage [

| byte methodIndex rcvr classTag class vTable |
byte := self fetchByte.
methodIndex := (byte >> 3) + (extA << 5).
extA := 0.
argumentCount := (byte bitAnd: 7) + (extB << 3).
extB := 0.
numExtB := 0.

rcvr := self stackValue: argumentCount.
classTag := objectMemory fetchClassTagOf: rcvr.

class := objectMemory classForClassTag: classTag.
vTable := objectMemory fetchPointer: VTableIndex ofObject: class.

newMethod := objectMemory fetchPointer: methodIndex ofObject: vTable.
primitiveFunctionPointer := 0.

self executeNewMethod: false.
self fetchNextBytecode
]

{ #category : 'debug support' }
StackInterpreter >> setBreakMNUSelector: aString [
<api>
Expand Down
48 changes: 47 additions & 1 deletion smalltalksrc/VMMaker/StackToRegisterMappingCogit.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,8 @@ StackToRegisterMappingCogit class >> initializeBytecodeTableForSistaV1 [
(2 244 244 genExtStoreLiteralVariableBytecode isMappedIfImmutability)
(2 245 245 genLongStoreTemporaryVariableBytecode)

(2 246 247 unknownBytecode)
(2 246 246 genSendVTableMessage)
(2 247 247 unknownBytecode)

"3 byte bytecodes"
(3 248 248 genCallPrimitiveBytecode hasUnsafeJump)
Expand Down Expand Up @@ -2501,6 +2502,46 @@ StackToRegisterMappingCogit >> genSendTrampolineFor: aRoutine numArgs: numArgs c
^startAddress
]

{ #category : 'bytecode generator support' }
StackToRegisterMappingCogit >> genSendVTableMessage [

| methodIndex argumentCount jumpInterpret mergeJump |
methodIndex := (byte1 >> 3) + (extA << 5).
extA := 0.
argumentCount := (byte1 bitAnd: 7) + (extB << 3).
extB := 0.
numExtB := 0.

"Allocate registers"
self marshallSendArguments: argumentCount.

"Fetch the method from the VTable"
objectRepresentation genGetClassObjectOf: ReceiverResultReg into: ClassReg scratchReg: TempReg instRegIsReceiver: true.
self MoveMw: (VTableIndex + 1) * objectMemory wordSize r: ClassReg R: TempReg.
self MoveMw: (methodIndex + 1) * objectMemory wordSize r: TempReg R: TempReg.

"If the method is compiled, we jump to it, if not we jump to the interpret."
objectRepresentation genLoadSlot: HeaderIndex sourceReg: TempReg destReg: ClassReg.
jumpInterpret := objectRepresentation genJumpImmediate: ClassReg.

"Jump to the method's unchecked entry-point."
self AddCq: cmNoCheckEntryOffset R: ClassReg.
self CallR: ClassReg. "Receiver and Args travel in registers"
mergeJump := self Jump: 0.

"Call the trampoline to continue execution in the interpreter"
jumpInterpret jmpTarget: self Label.
self PushR: ReceiverResultReg.
self CallRT: vTableSend. "Receiver and Args travel in the stack"

mergeJump jmpTarget: self Label.
self annotateBytecode: self Label.

self voidReceiverOptStatus.
self ssPushRegister: ReceiverResultReg.
^0
]

{ #category : 'bytecode generators' }
StackToRegisterMappingCogit >> genSistaExtStoreAndPopReceiverVariableBytecodePopBoolean: popBoolean [
<inline: true>
Expand Down Expand Up @@ -3204,6 +3245,11 @@ StackToRegisterMappingCogit >> generateMissAbortTrampolines [
{ #category : 'initialization' }
StackToRegisterMappingCogit >> generateSendTrampolines [
"Override to generate code to push the register arg(s) for <= numRegArg arity sends."

vTableSend := self genTrampolineFor: #ceSendFromVTableInterpreted:
called: 'VTableSend'
arg: TempReg.

0 to: NumSendTrampolines - 1 do:
[:numArgs|
ordinarySendTrampolines
Expand Down
25 changes: 25 additions & 0 deletions smalltalksrc/VMMakerTests/VMByteCodesTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -745,3 +745,28 @@ VMByteCodesTest >> testSubVectorBytecode [
self assert: (memory fetchFloat64: 1 ofObject: result) equals: 2.0.

]

{ #category : 'tests-send' }
VMByteCodesTest >> testVTableCall [

| aMethod receiver |
aMethod := methodBuilder
bytecodes: #[ 246 0 ];
buildMethod. "send VTable" "index"

receiver := self configVTable .

stackBuilder addNewFrame
method: aMethod;
stack: { receiver }.
stackBuilder buildStack.

interpreter setBreakSelector: nil.
interpreter method: aMethod.
interpreter currentBytecode: 246.

interpreter fetchByte.
self interpret: [ interpreter sendVTableMessage ].

self assert: interpreter stackTop equals: receiver
]
28 changes: 27 additions & 1 deletion smalltalksrc/VMMakerTests/VMSpurMemoryManagerTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ VMSpurMemoryManagerTest class >> wordSizeParameters [
yourself
]

{ #category : 'tests-send' }
VMSpurMemoryManagerTest >> configVTable [
| aMethodToActivate receiver receiverClass vTable |
aMethodToActivate := methodBuilder newMethod
numberOfArguments: 0;
buildMethod.
receiver := memory integerObjectOf: 41.
receiverClass := self setSmallIntegerClassIntoClassTable.

vTable := self setUpVTableIn: receiverClass.

memory storePointer: 0 ofObject: vTable withValue: aMethodToActivate.

^ receiver
]

{ #category : 'configuring' }
VMSpurMemoryManagerTest >> configureEnvironmentBuilder [

Expand Down Expand Up @@ -462,7 +478,7 @@ VMSpurMemoryManagerTest >> newClassInOldSpaceWithSlots: numberOfSlots instSpec:
| newClass formatWithSlots |

newClass := memory
allocateSlotsInOldSpace: 3
allocateSlotsInOldSpace: 6
format: memory nonIndexablePointerFormat
classIndex: memory arrayClassIndexPun.

Expand Down Expand Up @@ -876,6 +892,16 @@ VMSpurMemoryManagerTest >> setUpUsingImage [

]

{ #category : 'initialization' }
VMSpurMemoryManagerTest >> setUpVTableIn: aClass [
"The VTable is an array in the 4th entry of the class"

| array |
array := self newArrayWithSlots: 10.
memory storePointer: VTableIndex ofObject: aClass withValue: array.
^ array
]

{ #category : 'accessing' }
VMSpurMemoryManagerTest >> sizeOfObjectWithSlots: slots [

Expand Down