O2 and O1 compilation produce a segmentation fault due to stack corruption (when debugging we saw some extra pushes from the stack) on callbacks return. This happens on windows 32, when compiling with mingw gcc 7.4.0.
The issue can be reproduced easily by running the Alien qsort example in latest vms in both Pharo and Squeak.
This PR proposes to patch just the thunkEntry function. Not optimizing just that function solves the issue in our environment, though maybe there is a more fine-grained solution. We should still investigate what is the particular optimization that causes the problem.
You can view, comment on, or merge this pull request online at:
https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/353
-- Commit Summary --
* Patch callback thunkEntry to not optimize, failing in win32 using gcc 7.4.0
-- File Changes --
M platforms/Cross/plugins/IA32ABI/ia32abicc.c (2)
-- Patch Links --
https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/353.patchhttps://github.com/OpenSmalltalk/opensmalltalk-vm/pull/353.diff
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/353
In addition to the existing alpha blending rules (24 and 34), I propose 3 new additional rules.
Check https://en.wikipedia.org/wiki/Alpha_compositing
Existing rule 34 is a correct implementation of Alpha Blending for scaled forms, i.e. if premultiplied alpha is used. But rule 24 is a correct implementation of non-scaled forms, only for the case where destination is opaque (i.e. it's alpha is 1.0 in every pixel). If destination includes translucency (or it is completely transparent), the result is not correct. In order to fix it, the RGB of each pixel need to be divided by the pixel alpha.
The proposed blendUnscaled is the basic (for non-scaled forms) alpha blending described in Wikipedia. Note that users knowing that destination background is opaque might call the faster rule 24 instead.
The other two additional proposed rules are for converting to and from premultiplied alpha.
EXISTING blend 24 alphaBlend
resultAlpha = srcAlpha + destAlpha*(1-srcAlpha)
resultRGB = srcAlpha*source + (1-srcAlpha)*dest
EXISTING blendAlphaScaled 34 alphaBlendScaled
resultRGBA = source + (1-srcAlpha)*dest
NEW PROPOSED multiplyRGBByAlpha
Non premultiplied alpha -> premultiplied alpha. Only uses destination. Alpha unmodified. For each RGB component,
resultRGB = dest*destAlpha
NEW PROPOSED divideRGBByAlpha
Premultiplied alpha -> non premultiplied alpha. Only uses destination. Alpha unmodified. For each RGB component,
resultRGB = dest/destAlpha
NEW PROPOSED blendUnscaled
Equivalent to blend, and then divideRGBByAlpha
resultAlpha = srcAlpha + destAlpha*(1-srcAlpha)
resultRGB = (srcAlpha*source + (1-srcAlpha)*dest) / resultAlpha
This would allow handling of scaled (premultiplied-alpha) forms, and blending of regular forms including translucency, without the need to call slower smalltalk code to fix the results.
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/505
I am trying to build the unix sources for this project, exactly following the `HowToBuildFromSources` manual (the easy way). But unfortunately, when running `make` I get an error that `bld/plugins.int` is missing:
```
$ make
[ -d bld ] || mkdir bld
[ -f bld/Makefile ] || ( cd bld; ../config/configure; )
checking for gcc... gcc
# ... (75 lines skipped)
checking whether to build static libraries... no
/workspace/opensmalltalk-vm/src
/workspace/opensmalltalk-vm/src/plugins
checking sanity of generated src directory... bad
missing file: /workspace/opensmalltalk-vm/platforms/unix/bld/plugins.int
make: *** [Makefile:5: all] Error 1
```
See yourself:
[](https://gitpod.io/#snapshot/9bc102f3-ba84-437f-a226-a8851782c41b)
Is it me or is the documentation of the build process not up to date? Looking forward to your help!
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/507
`build.win32x86/HowToBuild` describes how we can build the VM using cygwin. However, I have installed WSL instead. When running `mvm`, it gives me:
```
../../platforms/win32/vm/sqWin32Utils.c:11:10: fatal error: Windows.h: No such file or directory
```
What do I have to do to enable mingw to find these header files? Any help is appreciated.
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/510
Eliot Miranda uploaded a new version of VMMaker to project VM Maker Inbox:
http://source.squeak.org/VMMakerInbox/VMMaker.oscog-eem.2765.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.2765
Author: eem
Time: 23 June 2020, 6:41:19.556484 pm
UUID: 91b9976e-60b9-4b5c-a2f8-b621dd454a07
Ancestors: VMMaker.oscog-eem.2764
Spur: Rewrite the revised followForwardedObjectFields:toDepth: soi it can be correctly inlined.
Slang: Change the order of application of ensureConditionalAssignmentsAreTransformedIn: so it is always the last thing done in tryToInlineMethodsIn:.
Straight-forward optimization of bindVariablesIn: in the common case of methods being inlined swith unchanged parameters.
=============== Diff against VMMaker.oscog-eem.2764 ===============
Item was changed:
----- Method: Spur32BitCoMemoryManager>>followForwardedObjectFields:toDepth: (in category 'as yet unclassified') -----
followForwardedObjectFields: objOop toDepth: depth
"Follow pointers in the object to depth.
Answer if any forwarders were found.
How to avoid cyclic structures?? A temporary mark bit? eem 6/22/2020 no need since depth is always finite."
<api>
<inline: false>
+ | found fmt limit |
- | oop found fmt |
found := false.
self assert: ((self isPointers: objOop) or: [self isOopCompiledMethod: objOop]).
fmt := self formatOf: objOop.
+ limit := (self numPointerSlotsOf: objOop format: fmt) - 1.
"It is essential to skip the first field of a method because it may be a
reference to a Cog method in the method zone, not a real object at all."
((self isCompiledMethodFormat: fmt)
ifTrue: [1]
ifFalse: [0])
+ to: limit
+ do: [:i| | oop |
- to: (self numPointerSlotsOf: objOop format: fmt) - 1
- do: [:i|
oop := self fetchPointer: i ofObject: objOop.
(self isNonImmediate: oop) ifTrue:
[(self isForwarded: oop) ifTrue:
[found := true.
oop := self followForwarded: oop.
self storePointer: i ofObject: objOop withValue: oop].
(depth > 0
and: [(self hasPointerFields: oop)
and: [self followForwardedObjectFields: oop toDepth: depth - 1]]) ifTrue:
[found := true]]].
^found!
Item was changed:
----- Method: Spur64BitCoMemoryManager>>followForwardedObjectFields:toDepth: (in category 'forwarding') -----
followForwardedObjectFields: objOop toDepth: depth
"Follow pointers in the object to depth.
Answer if any forwarders were found.
How to avoid cyclic structures?? A temporary mark bit? eem 6/22/2020 no need since depth is always finite."
<api>
<inline: false>
+ | found fmt limit |
- | oop found fmt |
found := false.
self assert: ((self isPointers: objOop) or: [self isOopCompiledMethod: objOop]).
fmt := self formatOf: objOop.
+ limit := (self numPointerSlotsOf: objOop format: fmt) - 1.
"It is essential to skip the first field of a method because it may be a
reference to a Cog method in the method zone, not a real object at all."
((self isCompiledMethodFormat: fmt)
ifTrue: [1]
ifFalse: [0])
+ to: limit
+ do: [:i| | oop |
- to: (self numPointerSlotsOf: objOop format: fmt) - 1
- do: [:i|
oop := self fetchPointer: i ofObject: objOop.
(self isNonImmediate: oop) ifTrue:
[(self isForwarded: oop) ifTrue:
[found := true.
oop := self followForwarded: oop.
self storePointer: i ofObject: objOop withValue: oop].
(depth > 0
and: [(self hasPointerFields: oop)
and: [self followForwardedObjectFields: oop toDepth: depth - 1]]) ifTrue:
[found := true]]].
^found!
Item was changed:
----- Method: TMethod>>exitVar:label:in: (in category 'inlining') -----
exitVar: exitVar label: exitLabel in: aCodeGen
"Replace each return statement in this method with an assignment to the
exit variable followed by either a return or a goto to the given label.
Answer if a goto was generated."
"Optimization: If exitVar is nil, the return value of the inlined method is not being used, so don't add the assignment statement."
| labelUsed map elisions eliminateReturnSelfs |
labelUsed := false.
map := Dictionary new.
elisions := Set new.
"Conceivably one might ^self from a struct class and mean it. In most cases though
^self means `get me outta here, fast'. So unless this method is from a VMStruct class,
elide any ^self's"
eliminateReturnSelfs := ((definingClass inheritsFrom: VMClass) and: [definingClass isStructClass]) not
and: [returnType = #void or: [returnType = #sqInt]].
parseTree nodesDo:
[:node | | replacement |
node isReturn ifTrue:
[self transformReturnSubExpression: node
toAssignmentOf: exitVar
andGoto: exitLabel
unless: eliminateReturnSelfs
into: [:rep :labelWasUsed|
replacement := rep.
labelWasUsed ifTrue: [labelUsed := true]]
in: aCodeGen.
"replaceNodesIn: is strictly top-down, so any replacement for ^expr ifTrue: [...^fu...] ifFalse: [...^bar...]
will prevent replacement of either ^fu or ^bar. The corollary is that ^expr ifTrue: [foo] ifFalse: [^bar]
must be transformed into expr ifTrue: [^foo] ifFalse: [^bar]"
(node expression isConditionalSend
and: [node expression hasExplicitReturn])
ifTrue:
[elisions add: node.
(node expression args reject: [:arg| arg endsWithReturn]) do:
[:nodeNeedingReturn|
self transformReturnSubExpression: nodeNeedingReturn statements last
toAssignmentOf: exitVar
andGoto: exitLabel
unless: eliminateReturnSelfs
into: [:rep :labelWasUsed|
replacement := rep.
+ labelWasUsed ifTrue: [labelUsed := true]]
+ in: aCodeGen.
- labelWasUsed ifTrue: [labelUsed := true]].
map
at: nodeNeedingReturn statements last
put: replacement]]
ifFalse:
[map
at: node
put: (replacement ifNil:
[TLabeledCommentNode new setComment: 'return ', node expression printString])]]].
map isEmpty ifTrue:
[self deny: labelUsed.
^false].
"Now do a top-down replacement for all returns that should be mapped to assignments and gotos"
parseTree replaceNodesIn: map.
"Now it is safe to eliminate the returning ifs..."
elisions isEmpty ifFalse:
[| elisionMap |
elisionMap := Dictionary new.
elisions do: [:returnNode| elisionMap at: returnNode put: returnNode expression].
parseTree replaceNodesIn: elisionMap].
"Now flatten any new statement lists..."
parseTree nodesDo:
[:node| | list |
(node isStmtList
and: [node statements notEmpty
and: [node statements last isStmtList]]) ifTrue:
[list := node statements last statements.
node statements removeLast; addAllLast: list]].
^labelUsed!
Item was changed:
----- Method: TMethod>>inlineFunctionCall:in: (in category 'inlining') -----
inlineFunctionCall: aSendNode in: aCodeGen
"Answer the body of the called function, substituting the actual
parameters for the formal argument variables in the method body.
Assume caller has established that:
1. the method arguments are all substitutable nodes, and
2. the method to be inlined contains no additional embedded returns."
| sel meth doNotRename argsForInlining substitutionDict |
+ aCodeGen maybeBreakForInlineOf: aSendNode in: self.
sel := aSendNode selector.
meth := (aCodeGen methodNamed: sel) copy.
meth ifNil:
[^self inlineBuiltin: aSendNode in: aCodeGen].
doNotRename := Set withAll: args.
argsForInlining := aSendNode argumentsForInliningCodeGenerator: aCodeGen.
meth args with: argsForInlining do:
[ :argName :exprNode |
exprNode isLeaf ifTrue:
[doNotRename add: argName]].
(meth statements size = 2
and: [meth statements first isSend
and: [meth statements first selector == #flag:]]) ifTrue:
[meth statements removeFirst].
meth renameVarsForInliningInto: self except: doNotRename in: aCodeGen.
meth renameLabelsForInliningInto: self.
self addVarsDeclarationsAndLabelsOf: meth except: doNotRename.
substitutionDict := Dictionary new: meth args size * 2.
meth args with: argsForInlining do:
[ :argName :exprNode |
+ (exprNode isVariable and: [exprNode name = argName]) ifFalse:
+ [substitutionDict at: argName put: exprNode].
- substitutionDict at: argName put: exprNode.
(doNotRename includes: argName) ifFalse:
[locals remove: argName]].
meth parseTree bindVariablesIn: substitutionDict.
^meth parseTree endsWithReturn
ifTrue: [meth parseTree copyWithoutReturn]
ifFalse: [meth parseTree]!
Item was changed:
----- Method: TMethod>>tryToInlineMethodsIn: (in category 'inlining') -----
tryToInlineMethodsIn: aCodeGen
"Expand any (complete) inline methods sent by this method.
Set the complete flag when all inlining has been done.
Answer if something was inlined."
| didSomething statementLists |
"complete ifTrue:
[^false]."
self definedAsMacro ifTrue:
[complete ifTrue:
[^false].
^complete := true].
- self ensureConditionalAssignmentsAreTransformedIn: aCodeGen.
didSomething := self tryToInlineMethodStatementsIn: aCodeGen statementListsInto: [:stmtLists| statementLists := stmtLists].
didSomething := (self tryToInlineMethodExpressionsIn: aCodeGen) or: [didSomething].
+ self ensureConditionalAssignmentsAreTransformedIn: aCodeGen.
didSomething ifTrue:
[writtenToGlobalVarsCache := nil].
complete ifFalse:
[self checkForCompletenessIn: aCodeGen.
complete ifTrue: [didSomething := true]]. "marking a method complete is progress"
^didSomething!
Item was changed:
----- Method: TStmtListNode>>bindVariablesIn: (in category 'transformations') -----
bindVariablesIn: aDictionary
+ aDictionary notEmpty ifTrue:
+ [statements := statements collect: [:s| s bindVariablesIn: aDictionary]]!
- statements := statements collect: [ :s | s bindVariablesIn: aDictionary ].!
I envison to have --quiet and --debugoutput FILENAME as options in the future. For an end-user it is difficult to separate application output/error from VM one (e.g. the infamous thread priority warning).
You can view, comment on, or merge this pull request online at:
https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/395
-- Commit Summary --
* debug: Prepare to let the app own stderr
* debug: Introduce the --quiet VM option to keep things silent
-- File Changes --
M build.macos32x86/common/Makefile.vm (2)
M build.macos64x64/common/Makefile.vm (2)
M platforms/Cross/vm/sq.h (7)
M platforms/iOS/vm/OSX/sqSqueakOSXApplication.m (5)
M platforms/unix/misc/threadValidate/sqUnixHeartbeat.c (6)
M platforms/unix/misc/threadValidate/threadValidate.c (14)
M platforms/unix/vm/aio.c (27)
M platforms/unix/vm/debug.c (22)
M platforms/unix/vm/debug.h (3)
M platforms/unix/vm/dlfcn-dyld.c (20)
M platforms/unix/vm/sqUnixCharConv.c (3)
M platforms/unix/vm/sqUnixExternalPrims.c (46)
M platforms/unix/vm/sqUnixHeartbeat.c (30)
M platforms/unix/vm/sqUnixITimerTickerHeartbeat.c (6)
M platforms/unix/vm/sqUnixMain.c (57)
M platforms/unix/vm/sqUnixMemory.c (8)
M platforms/unix/vm/sqUnixSpurMemory.c (4)
M platforms/unix/vm/sqaio.h (2)
-- Patch Links --
https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/395.patchhttps://github.com/OpenSmalltalk/opensmalltalk-vm/pull/395.diff
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/OpenSmalltalk/opensmalltalk-vm/pull/395
As the compiler tells:
```
OpenSmalltalk/opensmalltalk-vm/src/plugins/Squeak3D/Squeak3D.c:2475:7: warning: variable 'scale' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
if (!((l2vDistance == 0.0)
^~~~~~~~~~~~~~~~~~~~~~
/media/psf/Home/Smalltalk/OpenSmalltalk/opensmalltalk-vm/src/plugins/Squeak3D/Squeak3D.c:2480:42: note: uninitialized use occurs here
l2vDirection[0] = ((l2vDirection[0]) * scale);
^~~~~
```
That's effectively a bug in Smalltalk source, scale might be used uninitialized:
```
computeDirection
"Compute the direction for the current light and vertex"
| scale |
<inline: true>
<var: #scale type: #double>
(lightFlags anyMask: FlagPositional) ifTrue:[
"Must compute the direction for this vertex"
l2vDirection at: 0 put: (litVertex at: PrimVtxPositionX) - (primLight at: PrimLightPositionX).
l2vDirection at: 1 put: (litVertex at: PrimVtxPositionY) - (primLight at: PrimLightPositionY).
l2vDirection at: 2 put: (litVertex at: PrimVtxPositionZ) - (primLight at: PrimLightPositionZ).
"l2vDistance := self dotProductOf: l2vDirection with: l2vDirection."
l2vDistance := ((l2vDirection at: 0) * (l2vDirection at: 0)) +
((l2vDirection at: 1) * (l2vDirection at: 1)) +
((l2vDirection at: 2) * (l2vDirection at: 2)).
(l2vDistance = 0.0 or:[l2vDistance = 1.0])
ifFalse:[ l2vDistance := l2vDistance sqrt.
scale := -1.0/l2vDistance].
l2vDirection at: 0 put: (l2vDirection at: 0) * scale.
l2vDirection at: 1 put: (l2vDirection at: 1) * scale.
l2vDirection at: 2 put: (l2vDirection at: 2) * scale.
] ifFalse:[
(lightFlags anyMask: FlagDirectional) ifTrue:[
l2vDirection at: 0 put: (primLight at: PrimLightDirectionX).
l2vDirection at: 1 put: (primLight at: PrimLightDirectionY).
l2vDirection at: 2 put: (primLight at: PrimLightDirectionZ).
].
]
```
IMO:
- the scaling is not needed when distance is 0 or 1
- the scaling should be inside the block when distance is neither 0 nor 1
- the scaling should be positive
If I decipher correctly `l2vDirection` means light to vertex direction, that is:
LV vector = OV vector - OL vector
whatever origin O, and that is what we already do in code (PrimVtxPositionX - PrimLightPositionX). So I don't understand the -1.0 here...
If there is a -1.0, then we must also initialize scale to -1.0 when distance is 1.
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/434
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
I've noticed that in the FloatMathPlugin there is fdlibm
(freely distributable libm) :
platforms/Cross/plugins/FloatMathPlugin
This refers to the platforms/Cross/third-party/fdlibm
I wonder whether the VM shouldn't be using the system provided libm (-lm).
Perhaps for Croquet or other software that depends on FLoatMathPlugin,
see https://en.m.wikipedia.org/wiki/Croquet_Project
a special test framework could be ran in Squeak,
or perhaps as part of "./configure" configuration, to check the results,
of the underlying (system) libm, so that it provides results similar to fdlibm ?
Maybe fdlibm and libm "run bit identically" on some platforms.
This is because for Croquet the goal is to have the VM run bit identically.
Using the system provided -lm would possibly result in a smaller executable,
with less duplicated code (no overhead).
I'm no expert on libm, but perhaps the system provided libm is also faster.
Regards,
David Stes
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQEcBAEBCAAGBQJfEfHMAAoJEAwpOKXMq1Ma1psH/2yaIMdU6YMV8ZUSRlolvsH8
jlcuxPZV/Oo0FOq+jF2moBV01WquA8vCxZKm40s7ofrac7dWuNaaWwpDg/2xiVGc
p0crmTlv9FtHqTzjT3lrBMDxvOwq9oXAJUX+LaeGhNkYMbLE969m8hoRNSlDPPuk
NsXowTP7PpjyZ5RB5FApRHEnBzzyHjUIksUUhedCDWQRMqebEwxmHWbq6UobcED7
zVDx04crvw2hhzhKN8+AomZXNccMTDEQ6fTVBDeP7t4/iRmxo/6MmxOKMbQJ5dIi
fgYpODPPvXiAYipVx/lRXhgo5xEjQXgPjwBXKYQy8O2vJdH/0q/7r8u8k1MutbI=
=lWqV
-----END PGP SIGNATURE-----