Eliot Miranda uploaded a new version of Cog to project VM Maker:
http://source.squeak.org/VMMaker/Cog-eem.332.mcz
==================== Summary ====================
Name: Cog-eem.332
Author: eem
Time: 28 November 2016, 6:45:50.501077 pm
UUID: f03c7758-477b-4ab1-a087-b34314331352
Ancestors: Cog-nice.331
Fix a comment.
=============== Diff against Cog-nice.331 ===============
Item was changed:
----- Method: BochsX64Alien>>postCallArgumentsNumArgs:in: (in category 'execution') -----
postCallArgumentsNumArgs: numArgs "<Integer>" in: memory "<ByteArray|Bitmap>"
+ "Answer an argument vector of the requested size after a Win64 or SysV
- "Answer an argument vector of the requested size after a vanilla
ABI call. On X64 this simply means accessing register arguments.
For compatibility with Cog/Slang we answer unsigned values."
+ self assert: numArgs <= 4.
- self assert: numArgs <= 4. "Microsoft & System V agree for the first 4 reg args oinly"
^((CogX64Compiler isSysV
ifTrue: [#(rdi rsi rdx rcx r8 r9)]
ifFalse: [#(rcx rdx r8 r9)]) copyFrom: 1 to: numArgs) collect:
[:getter|
self perform: getter]!
Nicolas Cellier uploaded a new version of Cog to project VM Maker:
http://source.squeak.org/VMMaker/Cog-nice.331.mcz
==================== Summary ====================
Name: Cog-nice.331
Author: nice
Time: 29 November 2016, 2:33:51.558777 am
UUID: 892573e1-367b-4f88-91f5-37d8d62e3be2
Ancestors: Cog-eem.330
Fix the Win64 x64 register arguments
=============== Diff against Cog-eem.330 ===============
Item was changed:
----- Method: BochsX64Alien>>postCallArgumentsNumArgs:in: (in category 'execution') -----
postCallArgumentsNumArgs: numArgs "<Integer>" in: memory "<ByteArray|Bitmap>"
"Answer an argument vector of the requested size after a vanilla
+ ABI call. On X64 this simply means accessing register arguments.
- ABI call. On X86 this simply means accessing register arguments.
For compatibility with Cog/Slang we answer unsigned values."
self assert: numArgs <= 4. "Microsoft & System V agree for the first 4 reg args oinly"
+ ^((CogX64Compiler isSysV
- ^((CogX64Compiler ABI == #SysV
ifTrue: [#(rdi rsi rdx rcx r8 r9)]
+ ifFalse: [#(rcx rdx r8 r9)]) copyFrom: 1 to: numArgs) collect:
- ifFalse: [#(rdi rsi r8 r9)]) copyFrom: 1 to: numArgs) collect:
[:getter|
self perform: getter]!
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.2001.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.2001
Author: nice
Time: 27 November 2016, 7:17:07.355232 pm
UUID: ec391a53-4fcd-4591-a8e7-18058ef51295
Ancestors: VMMaker.oscog-nice.2000
Correctly marshal the trampoline arguments for Win64 x64 ABI.
The registers for passing first 4 integer/pointer parameters are RCX, RDX, R8, R9.
More over, it's necessary to reserve shadow space on the stack so that the callee can save those 4 registers even when there is less than 4.
Consequently, it's mandatory for cogit to invoke genRemoveNArgsFromStack: even when numArgs = 0, and let the backEnd decide what to do.
Correct a typo in cResultRegister comment.
=============== Diff against VMMaker.oscog-nice.2000 ===============
Item was changed:
----- Method: CogIA32Compiler>>genRemoveNArgsFromStack: (in category 'abi') -----
genRemoveNArgsFromStack: n
+ n = 0 ifFalse: [cogit AddCq: n * 4 R: ESP].
- cogit AddCq: n * 4 R: ESP.
^0!
Item was changed:
----- Method: CogX64Compiler>>cResultRegister (in category 'accessing') -----
cResultRegister
+ "Answer the register through which C functions return integral results."
- "Answer the register through which C funcitons return integral results."
<inline: true>
^RAX!
Item was changed:
----- Method: CogX64Compiler>>genMarshallNArgs:arg:arg:arg:arg: (in category 'abi') -----
genMarshallNArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3
"Generate the code to pass up to four arguments in a C run-time call. Hack: each argument is
either a negative number, which encodes a constant, or a non-negative number, that of a register.
Run-time calls have no more than four arguments, so chosen so that on ARM, where in its C ABI the
first four integer arguments are passed in registers, all arguments can be passed in registers. We
defer to the back end to generate this code not so much that the back end knows whether it uses
the stack or registers to pass arguments (it does, but...). In fact we defer for an extremely evil reason.
Doing so allows the x64 (where up to 6 args are passed) to assign the register arguments in an order
that allows some of the argument registers to be used for specific abstract registers, specifically
ReceiverResultReg and ClassReg. This is evil, evil, evil, but also it's really nice to keep using the old
register assignments the original author has grown accustomed to.
How can this possibly work? Look at Cogit class>>runtime for a list of the run-time calls and their
arguments, including which arguments are passed in which registers. Look at CogX64Compiler's
subclass implementations of initializeAbstractRegisters. There are no calls in which ReceiverResultReg
(RDX) and/or ClassReg (RCX) are passed along with Arg0Reg and Arg1Reg, and none in which the use of
either ReceiverResultReg or ClassReg conflict for args 3 & 4. So if args are assigned in order, the
registers do not get overwritten. Yes, this is evil, but it's so nice to continue to use RCX & RDX.
+ Argument registers for args 0 to 3 in SysV are RDI RSI RDX RCX, and in Win64 are RCX RDX R8 R9"
- Argument registers for args 0 to 3 in SysV are RDI RSI RDX RCX, and in Win64 are RDI RSI R8 R9"
<inline: true>
+ self
+ cppIf: #WIN64
+ ifTrue:
+ ["WIN64 ABI allways reserve shadow space on the stack for callee to save up to 4 register parameters"
+ cogit SubCq: 32 R: RSP].
numArgs = 0 ifTrue: [^self].
+ self
+ cppIf: #WIN64
+ ifTrue:
+ [(cogit isTrampolineArgConstant: regOrConst0)
+ ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst0) R: RCX] "a.k.a. Arg0Reg"
+ ifFalse:
+ [regOrConst0 ~= RCX ifTrue:
+ [cogit MoveR: regOrConst0 R: RCX]].
+ numArgs = 1 ifTrue: [^self].
+ (cogit isTrampolineArgConstant: regOrConst1)
+ ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst1) R: RDX] "a.k.a. Arg1Reg"
+ ifFalse:
+ [regOrConst1 ~= RDX ifTrue:
+ [cogit MoveR: regOrConst1 R: RDX]].
+ numArgs = 2 ifTrue: [^self].
+ (cogit isTrampolineArgConstant: regOrConst2)
+ ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst2) R: R8] "a.k.a. RISCTempReg in CogInLineLiteralsX64Compiler and Extra6Reg in CogOutOfLineLiteralsX64Compiler"
+ ifFalse:
+ [regOrConst2 ~= R8 ifTrue:
+ [cogit MoveR: regOrConst2 R: R8]].
+ numArgs = 3 ifTrue: [^self].
+ (cogit isTrampolineArgConstant: regOrConst3)
+ ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst3) R: R9] "a.k.a. SendNumArgsReg"
+ ifFalse:
+ [regOrConst3 ~= R9 ifTrue:
+ [cogit MoveR: regOrConst3 R: R9]]]
- (cogit isTrampolineArgConstant: regOrConst0)
- ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst0) R: RDI] "a.k.a. Arg0Reg"
ifFalse:
+ [(cogit isTrampolineArgConstant: regOrConst0)
+ ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst0) R: RDI] "a.k.a. Arg0Reg"
- [regOrConst0 ~= RDI ifTrue:
- [cogit MoveR: regOrConst0 R: RDI]].
- numArgs = 1 ifTrue: [^self].
- (cogit isTrampolineArgConstant: regOrConst1)
- ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst1) R: RSI] "a.k.a. Arg1Reg"
- ifFalse:
- [regOrConst1 ~= RSI ifTrue:
- [cogit MoveR: regOrConst1 R: RSI]].
- numArgs = 2 ifTrue: [^self].
- self cppIf: ABI == #SysV ifTrue:
- [(cogit isTrampolineArgConstant: regOrConst2)
- ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst2) R: RDX] "a.k.a. ReceiverResultReg"
- ifFalse:
- [regOrConst2 ~= RDX ifTrue:
- [cogit MoveR: regOrConst2 R: RDX]].
- numArgs = 3 ifTrue: [^self].
- (cogit isTrampolineArgConstant: regOrConst3)
- ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst3) R: RCX] "a.k.a. ClassReg"
ifFalse:
+ [regOrConst0 ~= RDI ifTrue:
+ [cogit MoveR: regOrConst0 R: RDI]].
+ numArgs = 1 ifTrue: [^self].
+ (cogit isTrampolineArgConstant: regOrConst1)
+ ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst1) R: RSI] "a.k.a. Arg1Reg"
- [regOrConst3 ~= RCX ifTrue:
- [cogit MoveR: regOrConst3 R: RCX]]].
- self cppIf: ABI == #MSVC ifTrue: "completely untested..."
- [(cogit isTrampolineArgConstant: regOrConst2)
- ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst2) R: R8] "a.k.a. RISCTempReg in CogInLineLiteralsX64Compiler and Extra6Reg in CogOutOfLineLiteralsX64Compiler"
- ifFalse:
- [regOrConst2 ~= R8 ifTrue:
- [cogit MoveR: regOrConst2 R: R8]].
- numArgs = 3 ifTrue: [^self].
- (cogit isTrampolineArgConstant: regOrConst3)
- ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst3) R: R9] "a.k.a. SendNumArgsReg"
ifFalse:
+ [regOrConst1 ~= RSI ifTrue:
+ [cogit MoveR: regOrConst1 R: RSI]].
+ numArgs = 2 ifTrue: [^self].
+ (cogit isTrampolineArgConstant: regOrConst2)
+ ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst2) R: RDX] "a.k.a. ReceiverResultReg"
+ ifFalse:
+ [regOrConst2 ~= RDX ifTrue:
+ [cogit MoveR: regOrConst2 R: RDX]].
+ numArgs = 3 ifTrue: [^self].
+ (cogit isTrampolineArgConstant: regOrConst3)
+ ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst3) R: RCX] "a.k.a. ClassReg"
+ ifFalse:
+ [regOrConst3 ~= RCX ifTrue:
+ [cogit MoveR: regOrConst3 R: RCX]]].
- [regOrConst3 ~= R9 ifTrue:
- [cogit MoveR: regOrConst3 R: R9]]].
self assert: numArgs <= 4!
Item was changed:
----- Method: CogX64Compiler>>genRemoveNArgsFromStack: (in category 'abi') -----
genRemoveNArgsFromStack: n
+ "This is a no-op on x64 SysV since the ABI passes up to 6 args in registers and trampolines currently observe a limit of 4.
+ But the WIN64 ABI allways reserve shadow space for saving up to 4 parameter registers (even if less than 4 args)."
+ self assert: n <= 4.
+ self cppIf: #WIN64 ifTrue:
+ [cogit AddCq: 32 R: RSP].
- "This is a no-op on x64 since the ABI passes up to 6 args in registers and trampolines currently observe a limit of 4."
- self assert: n <= 6.
^0!
Item was changed:
----- Method: Cogit>>compileCallFor:numArgs:arg:arg:arg:arg:floatResultReg:regsToSave: (in category 'initialization') -----
compileCallFor: aRoutine numArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3 floatResultReg: resultRegOrNone regsToSave: regMask
"Generate a call to aRoutine with up to 4 arguments. If resultRegOrNone is not
NoReg assign the C result to resultRegOrNone. If saveRegs, save all registers.
Hack: a negative arg value indicates an abstract register, a non-negative value
indicates a constant."
<var: #aRoutine type: #'void *'>
<inline: false>
| regsToSave |
regsToSave := resultRegOrNone = NoReg
ifTrue: [regMask]
ifFalse: [regMask bitClear: (self registerMaskFor: resultRegOrNone)].
cStackAlignment > objectMemory wordSize ifTrue:
[backEnd
genAlignCStackSavingRegisters: regsToSave
numArgs: numArgs
wordAlignment: cStackAlignment / objectMemory wordSize].
backEnd
genSaveRegs: regsToSave;
genMarshallNArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3.
self CallFullRT: (self cCode: [aRoutine asUnsignedInteger]
inSmalltalk: [self simulatedTrampolineFor: aRoutine]).
resultRegOrNone ~= NoReg ifTrue:
[backEnd cFloatResultToRd: resultRegOrNone].
+ backEnd genRemoveNArgsFromStack: numArgs.
- numArgs > 0 ifTrue:
- [backEnd genRemoveNArgsFromStack: numArgs].
backEnd genRestoreRegs: regsToSave!
Item was changed:
----- Method: Cogit>>compileCallFor:numArgs:arg:arg:arg:arg:resultReg:regsToSave: (in category 'initialization') -----
compileCallFor: aRoutine numArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3 resultReg: resultRegOrNone regsToSave: regMask
"Generate a call to aRoutine with up to 4 arguments. If resultRegOrNone is not
NoReg assign the C result to resultRegOrNone. If saveRegs, save all registers.
Hack: a negative arg value indicates an abstract register, a non-negative value
indicates a constant."
<var: #aRoutine type: #'void *'>
<inline: false>
| regsToSave |
regsToSave := resultRegOrNone = NoReg
ifTrue: [regMask]
ifFalse: [regMask bitClear: (self registerMaskFor: resultRegOrNone)].
cStackAlignment > objectMemory wordSize ifTrue:
[backEnd
genAlignCStackSavingRegisters: regsToSave
numArgs: numArgs
wordAlignment: cStackAlignment / objectMemory wordSize].
backEnd
genSaveRegs: regsToSave;
genMarshallNArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3.
self CallFullRT: (self cCode: [aRoutine asUnsignedInteger]
inSmalltalk: [self simulatedTrampolineFor: aRoutine]).
resultRegOrNone ~= NoReg ifTrue:
[backEnd genWriteCResultIntoReg: resultRegOrNone].
+ backEnd genRemoveNArgsFromStack: numArgs.
- numArgs > 0 ifTrue:
- [backEnd genRemoveNArgsFromStack: numArgs].
backEnd genRestoreRegs: regsToSave!
Item was changed:
----- Method: Cogit>>compileCallFor:numArgs:arg:arg:arg:arg:resultReg:resultReg:regsToSave: (in category 'initialization') -----
compileCallFor: aRoutine numArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3 resultReg: resultRegOrNone resultReg: resultReg2OrNone regsToSave: regMask
"Generate a call to aRoutine with up to 4 arguments. If resultRegOrNone is not
NoReg assign the C result to resultRegOrNone. If saveRegs, save all registers.
Hack: a negative arg value indicates an abstract register, a non-negative value
indicates a constant."
<var: #aRoutine type: #'void *'>
<inline: false>
| regsToSave |
regsToSave := resultRegOrNone = NoReg
ifTrue: [regMask]
ifFalse: [regMask bitClear: (self registerMaskFor: resultRegOrNone)].
cStackAlignment > objectMemory wordSize ifTrue:
[backEnd
genAlignCStackSavingRegisters: regsToSave
numArgs: numArgs
wordAlignment: cStackAlignment / objectMemory wordSize].
backEnd
genSaveRegs: regsToSave;
genMarshallNArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3.
self CallFullRT: (self cCode: [aRoutine asUnsignedInteger]
inSmalltalk: [self simulatedTrampolineFor: aRoutine]).
resultRegOrNone ~= NoReg ifTrue:
[backEnd genWriteCResultIntoReg: resultRegOrNone].
resultReg2OrNone ~= NoReg ifTrue:
[backEnd genWriteCSecondResultIntoReg: resultReg2OrNone].
+ backEnd genRemoveNArgsFromStack: numArgs.
- numArgs > 0 ifTrue:
- [backEnd genRemoveNArgsFromStack: numArgs].
backEnd genRestoreRegs: regsToSave!
Hi,
Support for primitive 169 for Object>>#~~ has been in the VM for a while.
The default implementation in Squeak 5 uses this primitive for example.
I've just added today (VMMaker commit 2003) support for inlined #~~ like
#== (including JIT support, branch pipelining, etc.). If one puts #~~ in
the specialObjectsArray at the location of #blockCopy:, the bytecode
compiler generates the special send bytecode for #~~ leading to improved
performance and consistency between #== and #~~.
With today's update, the VM supports 3 inlined operations without any type
checks: #==, #~~ and #class. It is possible to disable such optimisations
in the bytecode compiler (In Pharo #class inlining is disabled there for
example). Eliot would like to add support to disable these operations at VM
level as a VM command line parameter too, and we may do it in the future.
Now this is for the VM support. It's up to the Pharo/Squeak/other community
to decide what behavior they want in their runtime for these 3 selectors.
In my opinion, I believe that #~~ should be consistent with #==, hence they
should be both inlined or both sends to primitives. I don't like the
current situation in Pharo nor in Squeak.
Now when we look for solutions, we see that one of #== and #~~ needs to be
a primitive (it's essential), hence it makes sense to have both Object>>#==
and Object>>#~~ as primitives (with the primitive pragma in the method
body). The inlining of #== and #~~ is arguable and I let the community
decide what they believe is best for their runtime, though I would rather
have the same behavior for both selectors.
Cheers
On Wed, Nov 23, 2016 at 2:39 PM, Aliaksei Syrel <alex.syrel(a)gmail.com>
wrote:
> Hi
>
> It is been a while...
> So, do we want to replace ~~ with a primitive? :)
>
> Cheers
> Alex
>
>
>
> --
> View this message in context: http://forum.world.st/About-
> and-tp3898409p4924391.html
> Sent from the Pharo Smalltalk Developers mailing list archive at
> Nabble.com.
>
>
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2006.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.2006
Author: eem
Time: 25 November 2016, 7:19:10.023637 pm
UUID: cad39d34-1c14-416f-aeae-5b9fc776a3fc
Ancestors: VMMaker.oscog-eem.2005
RegisterAllocatingCogit:
methodOrBlockNumTemps must not be reset to the actual value ignoring the initial pushNils. Doing so wrecks spilling.
scanMethod must add an extra fixup for conditional branches since, if preceded by a special selector send, there may be two fixups created, one for each target, the target of the jump and the fall-through after the non-inlined send (see e.g. the two ensureFixupAt: sends in genBinaryInlineComparison:opFalse:destReg:).
This gets execution as far as the send of #<= in the loop in Interval>>#collect: which ends up passing nil as the second argument. It maybe time to tackle inlining of special selector comparisons.
=============== Diff against VMMaker.oscog-eem.2005 ===============
Item was changed:
----- Method: StackToRegisterMappingCogit>>compileBlockFrameBuild: (in category 'compile abstract instructions') -----
compileBlockFrameBuild: blockStart
"Build a frame for a block activation. See CoInterpreter class>>initializeFrameIndices.
Override to push the register receiver and register arguments, if any, and to correctly
initialize the explicitly nilled/pushed temp entries (they are /not/ of type constant nil)."
super compileBlockFrameBuild: blockStart.
methodOrBlockNumTemps := blockStart numArgs + blockStart numCopied + blockStart numInitialNils.
self initSimStackForFramefulMethod: blockStart startpc.
blockStart numInitialNils > 0 ifTrue:
[blockStart numInitialNils > 1
ifTrue:
[self genMoveNilR: TempReg.
1 to: blockStart numInitialNils do:
[:ign| self PushR: TempReg]]
ifFalse:
+ [self genPushConstant: objectMemory nilObject]]!
- [self genPushConstant: objectMemory nilObject].
- methodOrBlockNumTemps := blockStart numArgs + blockStart numCopied]!
Item was changed:
----- Method: StackToRegisterMappingCogit>>scanMethod (in category 'compile abstract instructions') -----
scanMethod
"Scan the method (and all embedded blocks) to determine
- what the last bytecode is; extra bytes at the end of a method are used to encode things like source pointers or temp names
- if the method needs a frame or not
- what are the targets of any backward branches.
- how many blocks it creates
Answer the block count or on error a negative error code"
| latestContinuation nExts descriptor pc numBlocks distance targetPC framelessStackDelta seenInstVarStore |
<var: #descriptor type: #'BytecodeDescriptor *'>
needsFrame := useTwoPaths := seenInstVarStore := false.
LowcodeVM ifTrue: [ hasNativeFrame := false ].
self maybeInitNumFixups.
self maybeInitNumCounters.
prevBCDescriptor := nil.
NewspeakVM ifTrue:
[numIRCs := 0].
(primitiveIndex > 0
and: [coInterpreter isQuickPrimitiveIndex: primitiveIndex]) ifTrue:
[^0].
pc := latestContinuation := initialPC.
numBlocks := framelessStackDelta := nExts := extA := extB := 0.
[pc <= endPC] whileTrue:
[byte0 := (objectMemory fetchByte: pc ofObject: methodObj) + bytecodeSetOffset.
descriptor := self generatorAt: byte0.
descriptor isExtension ifTrue:
[descriptor opcode = Nop ifTrue: "unknown bytecode tag; see Cogit class>>#generatorTableFrom:"
[^EncounteredUnknownBytecode].
self loadSubsequentBytesForDescriptor: descriptor at: pc.
self perform: descriptor generator].
(descriptor isReturn
and: [pc >= latestContinuation]) ifTrue:
[endPC := pc].
needsFrame ifFalse:
[(descriptor needsFrameFunction isNil
or: [self perform: descriptor needsFrameFunction with: framelessStackDelta])
ifTrue:
["With immutability we win simply by avoiding a frame build if the receiver is young and not immutable."
self cppIf: IMMUTABILITY
ifTrue: [descriptor is1ByteInstVarStore
ifTrue: [useTwoPaths := true]
ifFalse: [needsFrame := true. useTwoPaths := false]]
ifFalse: [needsFrame := true. useTwoPaths := false]]
ifFalse:
[framelessStackDelta := framelessStackDelta + descriptor stackDelta.
"Without immutability we win if there are two or more stores and the receiver is new."
self cppIf: IMMUTABILITY
ifTrue: []
ifFalse:
[descriptor is1ByteInstVarStore ifTrue:
[seenInstVarStore
ifTrue: [useTwoPaths := true]
ifFalse: [seenInstVarStore := true]]]]].
descriptor isBranch ifTrue:
[distance := self spanFor: descriptor at: pc exts: nExts in: methodObj.
targetPC := pc + descriptor numBytes + distance.
(self isBackwardBranch: descriptor at: pc exts: nExts in: methodObj)
ifTrue: [self initializeFixupAt: targetPC - initialPC]
ifFalse:
[latestContinuation := latestContinuation max: targetPC.
+ (descriptor isBranchTrue or: [descriptor isBranchFalse]) ifTrue:
+ [self maybeCountFixup].
self maybeCountFixup.
self maybeCountCounter]].
descriptor isBlockCreation ifTrue:
[numBlocks := numBlocks + 1.
distance := self spanFor: descriptor at: pc exts: nExts in: methodObj.
targetPC := pc + descriptor numBytes + distance.
latestContinuation := latestContinuation max: targetPC.
self maybeCountFixup].
NewspeakVM ifTrue:
+ [descriptor hasIRC ifTrue: [numIRCs := numIRCs + 1]].
- [descriptor hasIRC ifTrue:
- [numIRCs := numIRCs + 1]].
pc := pc + descriptor numBytes.
+ nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [extA := extB := 0].
- descriptor isExtension
- ifTrue: [nExts := nExts + 1]
- ifFalse: [nExts := extA := extB := 0].
prevBCDescriptor := descriptor].
^numBlocks!
Hi Peter,
I'd appreciate it if you used reply to all to keep the conversation thread going.
> On Nov 25, 2016, at 10:31 AM, Peter Uhnak <i.uhnak(a)gmail.com> wrote:
>
> Out of interest... is the single extra dispatch really that expensive?
Yes, in the common case where the send of #== is followed by a jump, as it is in ifNil:ifNotNil: or == foo ifTrue: etc. when #== is inclined the following jump is eliminated and the VM jumps on the condition codes for the comparison. When #== is a real send it answers the true or false objects and the following jump must compare this result against true or false.
Note that Sista will be able to perform the inclining optimisation so we will get the performance back once Sista is deployed.
>
> And speaking of object inequality... I would like to propose "<>" instead of "~=", because I never remember on which side ~ should be..
>
> Peter
>
>> On Wed, Nov 23, 2016 at 05:39:03AM -0800, Aliaksei Syrel wrote:
>> Hi
>>
>> It is been a while...
>> So, do we want to replace ~~ with a primitive? :)
>>
>> Cheers
>> Alex
>>
>>
>>
>> --
>> View this message in context: http://forum.world.st/About-and-tp3898409p4924391.html
>> Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
>>
>