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

experimental: Inline caches for the interpreter #858

Draft
wants to merge 87 commits into
base: pharo-12
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
c9586fe
Experimental IC tests (this will probably not work)
iglosiggio Oct 7, 2024
1d56e2d
Encode the class as a small integer and store the pointer to the pri…
iglosiggio Oct 7, 2024
f36b938
Change of plans, don't write the primitive ptr.....
iglosiggio Oct 7, 2024
103d6ff
Move the IC code to its own methods
iglosiggio Oct 7, 2024
b5fb723
Recategorize methods
iglosiggio Oct 7, 2024
06a3543
Don't update caches
iglosiggio Oct 7, 2024
9f475e7
sdfsdfkdfskj
iglosiggio Oct 7, 2024
30af042
sdfghjkl;
iglosiggio Oct 7, 2024
65bd19d
Plase don't inline meeee
iglosiggio Oct 7, 2024
98ff834
Ooops, off-by-one
iglosiggio Oct 7, 2024
e92e3df
don't read. only write.
iglosiggio Oct 7, 2024
05f2312
No read nor write
iglosiggio Oct 7, 2024
f25eb63
Read but never write
iglosiggio Oct 7, 2024
3665399
Only cache the first one
iglosiggio Oct 7, 2024
8ccb6fb
jdsflksjlkfskljdfdlsjksdfljkdfjkls
iglosiggio Oct 7, 2024
47c090d
dont read
iglosiggio Oct 7, 2024
106a6e7
Do read the cache
iglosiggio Oct 7, 2024
51ef13f
Don't read the cache :(
iglosiggio Oct 7, 2024
0f699f4
Always write the cache
iglosiggio Oct 7, 2024
999abca
allow cache reads
iglosiggio Oct 7, 2024
c8fe45e
Remove unused parameter in functionPointerFor:inClass:
iglosiggio Oct 8, 2024
ee14456
store classes instead of class tags at the IC
iglosiggio Oct 8, 2024
3c53902
disable cache reads
iglosiggio Oct 8, 2024
26a5b3c
Re-enable reading inline caches
iglosiggio Oct 8, 2024
3c71342
add assertion
iglosiggio Oct 8, 2024
7740942
booooo asserts don't work by default :(
iglosiggio Oct 8, 2024
65950e7
slang shenanigans
iglosiggio Oct 8, 2024
b133243
debug prints
iglosiggio Oct 8, 2024
086db3f
moar
iglosiggio Oct 8, 2024
796d147
Unset the start index after updating the cache
iglosiggio Oct 8, 2024
89166c4
...also on cache hits
iglosiggio Oct 8, 2024
897e111
Remove debug prints
iglosiggio Oct 8, 2024
82e38ef
revert
iglosiggio Oct 8, 2024
b6b808a
mmmm
iglosiggio Oct 8, 2024
1e1b21b
debug
iglosiggio Oct 8, 2024
2a1f3e6
move set of lkupClass
iglosiggio Oct 8, 2024
75d548e
two tests
iglosiggio Oct 8, 2024
7745260
forgot the accessors
iglosiggio Oct 8, 2024
5d77b8e
vm that only writes
iglosiggio Oct 8, 2024
3ccb501
dont write ICs
iglosiggio Oct 8, 2024
5ed04e6
dsfjlksdflkdfs
iglosiggio Oct 8, 2024
1057bb6
remove the sanity check
iglosiggio Oct 8, 2024
f148156
i'm dumb
iglosiggio Oct 8, 2024
5437d74
read and write
iglosiggio Oct 8, 2024
5a6d3fc
don't cache DNUs
iglosiggio Oct 10, 2024
622e939
Don't cache cannotInterpret:
iglosiggio Oct 10, 2024
278c5d4
idk
iglosiggio Oct 10, 2024
08feeab
why
iglosiggio Oct 10, 2024
8f79356
no inline lookup
iglosiggio Oct 10, 2024
f36a72d
PLEASE
iglosiggio Oct 10, 2024
ed83982
back
iglosiggio Oct 10, 2024
60a3b00
rewrite1
iglosiggio Oct 10, 2024
af9b39f
rewrite2
iglosiggio Oct 10, 2024
20f75ff
insane
iglosiggio Oct 10, 2024
b47663b
...
iglosiggio Oct 10, 2024
0f43521
sdjaklsjflksdf
iglosiggio Oct 10, 2024
ff9a73f
ksdlaskjdfd
iglosiggio Oct 10, 2024
47596eb
dgfdghfdfghfgh
iglosiggio Oct 10, 2024
a210ca3
cgfgnhdhgdgf
iglosiggio Oct 10, 2024
4d653a3
hgfhgfghhjf
iglosiggio Oct 10, 2024
b6eeff2
zxfkls;dkfsdf
iglosiggio Oct 10, 2024
916f202
ultima prueb adel dia
iglosiggio Oct 10, 2024
1ead33c
fldfshjldfslkhjdfslkjhdsf
iglosiggio Oct 11, 2024
4538918
ttttt
iglosiggio Oct 11, 2024
af24304
HERE IT WORKED
iglosiggio Oct 11, 2024
1d63316
Try to make this a bit faster
iglosiggio Oct 11, 2024
a35ce48
ooops
iglosiggio Oct 11, 2024
78751f8
test
iglosiggio Oct 11, 2024
bf3ad3a
mmmm
iglosiggio Oct 11, 2024
a13da95
dont read the caches
iglosiggio Oct 11, 2024
d793866
test
iglosiggio Oct 11, 2024
60e503e
revert
iglosiggio Oct 11, 2024
bb7b86a
test
iglosiggio Oct 11, 2024
6a07684
test2
iglosiggio Oct 11, 2024
96fa42b
try to use class tags instead of class objects
iglosiggio Oct 11, 2024
8f673bb
perf test
iglosiggio Oct 11, 2024
d801502
is this faster?
iglosiggio Oct 11, 2024
884dd9e
Don't cache external method calls
iglosiggio Oct 14, 2024
489e6d9
mmm
iglosiggio Oct 14, 2024
9247f7c
don't cache _any_ primitive methods
iglosiggio Oct 14, 2024
177ede7
missing cast
iglosiggio Oct 14, 2024
673908a
wrong cast
iglosiggio Oct 14, 2024
c6c1887
????
iglosiggio Oct 14, 2024
9d39b25
:cry:
iglosiggio Oct 14, 2024
a314179
oops
iglosiggio Oct 14, 2024
9cccab8
revert
iglosiggio Oct 14, 2024
a544027
bug bug bug
iglosiggio Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions smalltalksrc/VMMaker/CoInterpreter.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -1196,7 +1196,7 @@ CoInterpreter >> ceInterpretMethodFromPIC: aMethodObj receiver: rcvr [
messageSelector := pic selector.
newMethod := aMethodObj.
primitiveIndex := self primitiveIndexOf: aMethodObj.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex inClass: objectMemory nilObject.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex.
argumentCount := pic cmNumArgs.
instructionPointer := self popStack.
self interpretMethodFromMachineCode.
Expand Down Expand Up @@ -1226,7 +1226,7 @@ CoInterpreter >> ceMNUFromPICMNUMethod: aMethodObj receiver: rcvr [
self unreachable].
newMethod := aMethodObj.
primitiveIndex := self primitiveIndexOf: aMethodObj.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex inClass: objectMemory nilObject.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex.
^self interpretMethodFromMachineCode].
"handleMNU:InMachineCodeTo:classForMessage: assumes lkupClass is set, since every other use is
after a lookupMethodNoMNUEtcInClass: call, which sets lkupClass. Here we must set it manually.
Expand Down Expand Up @@ -2790,7 +2790,7 @@ CoInterpreter >> functionPointerForCompiledMethod: methodObj primitiveIndex: pri
<returnTypeC: 'void (*functionPointerForCompiledMethodprimitiveIndex(sqInt methodObj, sqInt primIndex))(void)'>
| functionPointer |
<var: #functionPointer declareC: #'void (*functionPointer)(void)'>
functionPointer := self functionPointerFor: primIndex inClass: nil.
functionPointer := self functionPointerFor: primIndex.
functionPointer == #primitiveCalloutToFFI ifTrue:
[^self functionForPrimitiveCallout].
functionPointer == #primitiveExternalCall ifTrue:
Expand Down
6 changes: 3 additions & 3 deletions smalltalksrc/VMMaker/CogVMSimulator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ CogVMSimulator >> functionForPrimitiveExternalCall: methodObj [
]

{ #category : 'interpreter shell' }
CogVMSimulator >> functionPointerFor: primIndex inClass: lookupClass [
CogVMSimulator >> functionPointerFor: primIndex [
"Override Interpreter to handle the external primitives caching. See also
internalExecuteNewMethod."

Expand Down Expand Up @@ -1327,7 +1327,7 @@ CogVMSimulator >> primitiveContextAtPut [
CogVMSimulator >> primitiveDoPrimitiveWithArgs [
| primIndex |
primIndex := objectMemory integerValueOf: (self stackValue: 1).
transcript nextPutAll: 'DO PRIMITIVE: '; print: (self functionPointerFor: primIndex inClass: nil); cr; flush.
transcript nextPutAll: 'DO PRIMITIVE: '; print: (self functionPointerFor: primIndex); cr; flush.
(#(76 "primitiveStoreStackp" 188 189 "eval method") includes: primIndex) ifTrue:
[self halt].
^super primitiveDoPrimitiveWithArgs
Expand Down Expand Up @@ -1731,7 +1731,7 @@ CogVMSimulator >> saneFunctionPointerForFailureOfPrimIndex: primIndex [
and: [self isPrimitiveFunctionPointerAnIndex not
and: [primIndex ~= PrimNumberExternalCall
and: [(self isMetaPrimitiveIndex: primIndex) not]]]) ifTrue:
[basePrimitive := self functionPointerFor: primIndex inClass: objectMemory nilObject.
[basePrimitive := self functionPointerFor: primIndex.
^(cogit lookupAddress: primitiveFunctionPointer) endsWith: basePrimitive].

^super saneFunctionPointerForFailureOfPrimIndex: primIndex
Expand Down
4 changes: 2 additions & 2 deletions smalltalksrc/VMMaker/CurrentImageCoInterpreterFacade.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,10 @@ CurrentImageCoInterpreterFacade >> freeStartAddress [
]

{ #category : 'accessing' }
CurrentImageCoInterpreterFacade >> functionPointerFor: primIndex inClass: lookupClass [
CurrentImageCoInterpreterFacade >> functionPointerFor: primIndex [
^primIndex = 0
ifTrue: [#primitiveFail]
ifFalse: [coInterpreter functionPointerFor: primIndex inClass: lookupClass]
ifFalse: [coInterpreter functionPointerFor: primIndex]
]

{ #category : 'accessing' }
Expand Down
134 changes: 109 additions & 25 deletions smalltalksrc/VMMaker/StackInterpreter.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,8 @@ Class {
'pendingFinalizationSignals',
'imageVersionNumber',
'desiredStackPageBytes',
'imageReaderWriter'
'imageReaderWriter',
'inlineCacheStartIndex'
],
#classVars : [
'AlternateHeaderHasPrimFlag',
Expand Down Expand Up @@ -1972,7 +1973,7 @@ StackInterpreter >> addNewMethodToCache: classObj [
(objectMemory isOopCompiledMethod: newMethod)
ifTrue:
[primitiveIndex := self primitiveIndexOf: newMethod.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex inClass: classObj]
primitiveFunctionPointer := self functionPointerFor: primitiveIndex]
ifFalse:
[self assert: ((objectMemory isNonImmediate: newMethod)
and: [objectMemory isForwarded: newMethod]) not.
Expand Down Expand Up @@ -5649,7 +5650,8 @@ StackInterpreter >> extSendBytecode [
"238 11101110 i i i i i j j j Send Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"
| byte |
byte := self fetchByte.
messageSelector := self literal: (byte >> 3) + (extA << 5).
inlineCacheStartIndex := (byte >> 3) + (extA << 5).
messageSelector := self literal: inlineCacheStartIndex.
extA := 0.
argumentCount := (byte bitAnd: 7) + (extB << 3).
extB := 0.
Expand All @@ -5665,7 +5667,8 @@ StackInterpreter >> extSendSuperBytecode [
ifFalse: [Send To Superclass of Stacked Class Literal Selector #iiiii (+ Extend A * 32) with jjj (+ (Extend B bitAnd: 63) * 8) Arguments]"
| byte |
byte := self fetchByte.
messageSelector := self literal: (byte >> 3) + (extA << 5).
inlineCacheStartIndex := (byte >> 3) + (extA << 5).
messageSelector := self literal: inlineCacheStartIndex.
extA := 0.
BytecodeSetHasDirectedSuperSend ifTrue:
[extB >= 64 ifTrue:
Expand Down Expand Up @@ -6047,27 +6050,29 @@ StackInterpreter >> findNewMethodInClassTag: classTagArg ifFound: aBlock [
<inline: true>
| classTag |
classTag := classTagArg.

(self tryToUseInlineCacheFor: classTag) ifTrue: [ ^ aBlock value ].

"Entry was not found in the local IC cache; perhaps something was forwarded.
Resolve forwarders and retry"
(objectMemory isOopForwarded: messageSelector) ifTrue: [
messageSelector := self handleForwardedSelectorFaultFor: messageSelector ].
(objectMemory isForwardedClassTag: classTag) ifTrue: [
classTag := self handleForwardedSendFaultForTag: classTag ].

"ICs failed. Try the lookup cache"
(self inlineLookupInMethodCacheSel: messageSelector classTag: classTag)
ifTrue: [
self updateInlineCacheIfNeeded: classTag.
^ aBlock value ]
ifFalse: [
"Entry was not found in the cache; perhaps something was forwarded.
Resolve forwarders and retry"
((objectMemory isOopForwarded: messageSelector) or: [
objectMemory isForwardedClassTag: classTag ]) ifTrue: [
(objectMemory isOopForwarded: messageSelector) ifTrue: [
messageSelector := self handleForwardedSelectorFaultFor:
messageSelector ].
(objectMemory isForwardedClassTag: classTag) ifTrue: [
classTag := self handleForwardedSendFaultForTag: classTag ].
(self lookupInMethodCacheSel: messageSelector classTag: classTag)
ifTrue: [ ^ aBlock value ] ].

"Entry was not found in the cache; look it up the hard way "
"All caches failed. Do a proper lookup"
lkupClass := objectMemory classForClassTag: classTag.
(objectMemory isOopForwarded: lkupClass) ifTrue: [
lkupClass := objectMemory followForwarded: lkupClass ].
self lookupMethodInClass: lkupClass.
self addNewMethodToCache: lkupClass ]
ifTrue: [ aBlock value ]
self addNewMethodToCache: lkupClass.
self updateInlineCacheIfNeeded: classTag ]
]

{ #category : 'message sending' }
Expand Down Expand Up @@ -6927,7 +6932,7 @@ StackInterpreter >> functionForPrimitiveCallout [
]

{ #category : 'method lookup cache' }
StackInterpreter >> functionPointerFor: primIdx inClass: theClass [
StackInterpreter >> functionPointerFor: primIdx [
"Find an actual function pointer for this primitiveIndex. This is an
opportunity to specialise the prim for the relevant class (format for
example). Default for now is simply the entry in the base primitiveTable."
Expand Down Expand Up @@ -7676,6 +7681,7 @@ StackInterpreter >> initializeInterpreter: bytesToShift [
profileSemaphore := profileProcess := profileMethod := objectMemory nilObject.
self initializeGlobalSessionID.
metaAccessorDepth := -2.
inlineCacheStartIndex := -1

]

Expand Down Expand Up @@ -7703,6 +7709,18 @@ StackInterpreter >> initializePageTraceToInvalid: aPage [
aPage trace: StackPageTraceInvalid "for assert checking of the page tracing flags"
]

{ #category : 'accessing' }
StackInterpreter >> inlineCacheStartIndex [

^ inlineCacheStartIndex
]

{ #category : 'accessing' }
StackInterpreter >> inlineCacheStartIndex: anObject [

inlineCacheStartIndex := anObject
]

{ #category : 'method lookup cache' }
StackInterpreter >> inlineLookupInMethodCacheSel: selector classTag: classTag [
"This method implements a simple method lookup cache. If an entry for the given selector and classTag is
Expand Down Expand Up @@ -8650,6 +8668,12 @@ StackInterpreter >> literal: offset ofMethod: methodPointer put: oop [

]

{ #category : 'compiled methods' }
StackInterpreter >> literal: offset put: oop [
self assert: method = (self iframeMethod: framePointer).
^self literal: offset ofMethod: method put: oop
]

{ #category : 'compiled methods' }
StackInterpreter >> literalCountOfAlternateHeader: headerPointer [
<inline: true>
Expand Down Expand Up @@ -9400,7 +9424,7 @@ StackInterpreter >> mappedDirectCall [
localPrimIndex := self primitiveIndexOfMethod: newMethod header: methodHeader.
argumentCount := self argumentCountOfMethodHeader: methodHeader.
"The primitive function pointer is not cached in the interpreter, but it's called quickly in the JIT"
primitiveFunctionPointer := self functionPointerFor: localPrimIndex inClass: objectMemory nilObject..
primitiveFunctionPointer := self functionPointerFor: localPrimIndex.
self activateNewMethod
]

Expand Down Expand Up @@ -13492,7 +13516,7 @@ StackInterpreter >> safeMethodClassOf: methodPointer [
StackInterpreter >> saneFunctionPointerForFailureOfPrimIndex: primIndex [
| basePrimitive |
<var: 'basePrimitive' declareC: 'void (*basePrimitive)(void)'>
basePrimitive := self functionPointerFor: primIndex inClass: objectMemory nilObject.
basePrimitive := self functionPointerFor: primIndex.
^primitiveFunctionPointer = basePrimitive
or: [(basePrimitive = #primitiveExternalCall and: [self isPrimitiveFunctionPointerAnIndex not])
or: [(self isMetaPrimitiveIndex: primIndex) and: [metaAccessorDepth > -2]]]
Expand Down Expand Up @@ -13592,7 +13616,8 @@ StackInterpreter >> sendCannotReturn: resultOop [
StackInterpreter >> sendLiteralSelector0ArgsBytecode [
"Can use any of the first 16 literals for the selector."
| rcvr |
messageSelector := self literal: (currentBytecode bitAnd: 16rF).
inlineCacheStartIndex := currentBytecode bitAnd: 16rF.
messageSelector := self literal: inlineCacheStartIndex.
argumentCount := 0.
rcvr := self stackValue: 0.
lkupClassTag := objectMemory fetchClassTagOf: rcvr.
Expand All @@ -13604,7 +13629,8 @@ StackInterpreter >> sendLiteralSelector0ArgsBytecode [
StackInterpreter >> sendLiteralSelector1ArgBytecode [
"Can use any of the first 16 literals for the selector."
| rcvr |
messageSelector := self literal: (currentBytecode bitAnd: 16rF).
inlineCacheStartIndex := currentBytecode bitAnd: 16rF.
messageSelector := self literal: inlineCacheStartIndex.
argumentCount := 1.
rcvr := self stackValue: 1.
lkupClassTag := objectMemory fetchClassTagOf: rcvr.
Expand All @@ -13616,7 +13642,8 @@ StackInterpreter >> sendLiteralSelector1ArgBytecode [
StackInterpreter >> sendLiteralSelector2ArgsBytecode [
"Can use any of the first 16 literals for the selector."
| rcvr |
messageSelector := self literal: (currentBytecode bitAnd: 16rF).
inlineCacheStartIndex := currentBytecode bitAnd: 16rF.
messageSelector := self literal: inlineCacheStartIndex.
argumentCount := 2.
rcvr := self stackValue: 2.
lkupClassTag := objectMemory fetchClassTagOf: rcvr.
Expand Down Expand Up @@ -15708,6 +15735,34 @@ StackInterpreter >> tryLoadNewPlugin: pluginString pluginEntries: pluginEntries
^ pluginString asString -> plugin
]

{ #category : 'interpreter inline caches' }
StackInterpreter >> tryToUseInlineCacheFor: classTag [
| inlineCacheClassTag |
<inline: true>
"If there's no cache then return"
inlineCacheStartIndex = -1 ifTrue: [ ^ false ].

"If the cached tag is not the same one then return"
inlineCacheClassTag := objectMemory integerValueOf: (self literal: inlineCacheStartIndex + 1).
inlineCacheClassTag = classTag ifFalse: [ ^ false ].

"Otherwise let's get the method and primitive function pointer"
newMethod := self literal: inlineCacheStartIndex + 2.
(objectMemory isOopCompiledMethod: newMethod)
ifTrue: [
| primitiveIndex |
primitiveIndex := self primitiveIndexOf: newMethod.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex ]
ifFalse: [
self assert: (
(objectMemory isNonImmediate: newMethod) and: [objectMemory isForwarded: newMethod]) not.
primitiveFunctionPointer := #primitiveInvokeObjectAsMethod ].

"... and notify the caller that we were able to use the IC"
inlineCacheStartIndex := -1.
^ true
]

{ #category : 'debug printing' }
StackInterpreter >> ultimateLiteralOf: aMethodOop [
<api>
Expand Down Expand Up @@ -16026,6 +16081,35 @@ StackInterpreter >> unknownShortOrCodeSizeInKs [
^theUnknownShort
]

{ #category : 'interpreter inline caches' }
StackInterpreter >> updateInlineCacheIfNeeded: classTag [
<inline: true>
| classTagObj |
"If there's no cache then return"
inlineCacheStartIndex = -1 ifTrue: [ ^ self ].
"Don't cache doesNotUnderstand:"
messageSelector = (objectMemory splObj: SelectorDoesNotUnderstand) ifTrue: [
inlineCacheStartIndex := -1.
^ self ].
"Don't cache cannotInterpret:"
messageSelector = (objectMemory splObj: SelectorCannotInterpret) ifTrue: [
inlineCacheStartIndex := -1.
^ self ].
"Don't cache external methods (we need a mechanism for quickening of external methods)"
primitiveFunctionPointer = #primitiveExternalCall ifTrue: [
inlineCacheStartIndex := -1.
^ self ].

classTagObj := objectMemory integerObjectOf: classTag.

"... otherwise lets update the IC"
self literal: inlineCacheStartIndex + 1 put: classTagObj.
self literal: inlineCacheStartIndex + 2 put: newMethod.

"... and now there's no inline cache to work with"
inlineCacheStartIndex := -1
]

{ #category : 'image save/restore' }
StackInterpreter >> updateObjectsPostByteSwap [

Expand Down
6 changes: 3 additions & 3 deletions smalltalksrc/VMMaker/StackInterpreterPrimitives.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ StackInterpreterPrimitives >> primitiveDoPrimitiveWithArgs [
[^self primitiveFailFor: PrimErrLimitExceeded negated].

primIdx := objectMemory integerValueOf: primIdx.
primitiveFunctionPointer := self functionPointerFor: primIdx inClass: nil.
primitiveFunctionPointer := self functionPointerFor: primIdx.
primitiveFunctionPointer = 0 ifTrue:
[primitiveFunctionPointer := #primitiveDoPrimitiveWithArgs.
^self primitiveFailFor: PrimErrBadIndex negated].
Expand Down Expand Up @@ -1027,7 +1027,7 @@ StackInterpreterPrimitives >> primitiveExecuteMethod [
[^self primitiveFailFor: PrimErrBadNumArgs].
newMethod := self popStack.
primitiveIndex := self primitiveIndexOf: newMethod.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex inClass: nil.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex.
argumentCount := argumentCount - 1.
self executeNewMethod.
"Recursive xeq affects primErrorCode"
Expand Down Expand Up @@ -1064,7 +1064,7 @@ StackInterpreterPrimitives >> primitiveExecuteMethodArgsArray [
self push: (objectMemory fetchPointer: i ofObject: argumentArray)].
newMethod := methodArgument.
primitiveIndex := self primitiveIndexOf: newMethod.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex inClass: nil.
primitiveFunctionPointer := self functionPointerFor: primitiveIndex.
argumentCount := argCnt.
self executeNewMethod.
"Recursive xeq affects primErrorCode"
Expand Down
2 changes: 1 addition & 1 deletion smalltalksrc/VMMaker/StackInterpreterSimulator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ StackInterpreterSimulator >> framePointer [
]

{ #category : 'interpreter shell' }
StackInterpreterSimulator >> functionPointerFor: primIndex inClass: lookupClass [
StackInterpreterSimulator >> functionPointerFor: primIndex [
"Override Interpreter to handle the external primitives caching. See also
internalExecuteNewMethod."

Expand Down
2 changes: 1 addition & 1 deletion smalltalksrc/VMMakerTests/VMByteCodesTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ VMByteCodesTest >> testSendMessageWithTwoArgumentsMakeAFrame [

| selectorOop aMethod aMethodToActivate receiver receiverClass aMethodDictionary arg1 arg2 |
selectorOop := memory integerObjectOf: 42.
methodBuilder newMethod literals: { selectorOop }.
methodBuilder newMethod literals: { selectorOop. interpreter objectMemory nilObject. interpreter objectMemory nilObject. }.
aMethod := methodBuilder buildMethod.
aMethodToActivate := methodBuilder newMethod
numberOfArguments: 2;
Expand Down
Loading