In conjunction with getting Open Cobalt running on FreeBSD I have been
looking into the problems with SqueakFFIPrims on FreeBSD and have
reached a point that is beyond my understanding. I am not sure if the
fix should come from the VM side or the FreeBSD port maintainer.
I needed to get source code back into the ports tree so I did a make
in /usr/ports/lang/squeak. I already had the 3.9 tarball, so that just
repopulated the source and did the initial build.
In the "files" folder I found patch files typical for a FreeBSD port.
These patch source files from a generic tarball to work with FreeBSD.
The one of interest was
patch-platforms__unix__plugins__SqueakFFIPrims__ffi-config
which contains
----x-----x-----
--- platforms/unix/plugins/SqueakFFIPrims/ffi-config.org Wed Apr
26 20:27:53 2006
+++ platforms/unix/plugins/SqueakFFIPrims/ffi-config Wed Apr 26
20:29:00 2006
@@ -39,6 +39,7 @@
case ${abi} in
linux) abi=sysv;;
+ freebsd*) abi=sysv;;
darwin*) abi=darwin;;
*) abi=libffi; lib="-lffi";;
esac
-----x-----x-----
I then had the folder
work/Squeak-3.9-7/platforms/unix/plugins/SqueakFFIPrims
In it is a file 00README which explains how to test FFI.
It says to run ffi-test-config but I have no such file.
It says to type "make" to build a test suite but the build failed.
It says to try with make CPU=any ABI=libffi LIB=-lffi
which also failed. I traced the problem to the gcc search paths for
includes and libraries -- turns out FreeBSD only searches /usr/include
and /usr/lib when the required files are in /usr/local/include
and /usr/local/lib.
After some fiddling I finally had a "main" to test. It failed:
ffi-test-main.c failed at line 361. Here is a bit from that file, ending
with line 361:
ffiInitialize();
for (ul= 0; ul < 15; ++ul)
ffiPushSingleFloat(fa[ul]);
GO(FFITypeSingleFloat, many);
f= ffiReturnFloatValue();
ffiCleanup();
CHECK(f - ff < FLT_EPSILON);
I worked out the CHECK macro but could not find what FLT_EPSILON is. At
that point I decided to stop and come to you for help.
Where do I go from here?
--
Gary Dunn, Honolulu
osp(a)aloha.com
http://openslate.net/http://e9erust.blogspot.com/
Sent from Slate001
> All I can say is that I am impressed by the numbers it is really much
>> faster.
>> I still don't understand why I send this email with a subject say
>> IdentitySet because what I really need is a fast/large IdentityDictionary
>> :( Anyway, there's a place where we can use this LargeIdentitySet in Fuel
>> I think).
>>
>> So Levente, you say this is not possible to adapt this for dictionary?
>> can
>> we contact Eliot to provide such a primitive?
>>
>
> As promised, I uploaded my LargeIdentityDictionary implementation to
> http://leves.web.elte.hu/**squeak/**LargeIdentityDictionary.st<http://leves.web.elte.hu/squeak/LargeIdentityDictionary.st>.
> The numbers will be a bit worse compared to LargeIdentitySet, because of
> the lack of the primitive, but it's still 2-3x faster than other solutions
> (IdentityDictionary, PluggableIdentityDictionary, subclassing, etc). I'm
> about to propose this primitive with other improvements on the vm-dev list.
>
>
Hi Eliot/Levente. What is the status of this? Do we have already the new
primitive? If true, how can we adapt LargeIdentitySet to use such new
primitive?
Thanks!
>
> Levente
>
>
>> thanks
>>
>> On Fri, Dec 16, 2011 at 3:28 PM, Levente Uzonyi <leves(a)elte.hu> wrote:
>>
>> On Fri, 16 Dec 2011, Henrik Sperre Johansen wrote:
>>>
>>> On 16.12.2011 03:26, Levente Uzonyi wrote:
>>>
>>>>
>>>>
>>>>> How about my numbers? :)
>>>>>
>>>>> "Preallocate objects, so we won't count gc time."
>>>>> n := 1000000.
>>>>> objects := Array new: n streamContents: [ :stream |
>>>>> n timesRepeat: [ stream nextPut: Object new ] ].
>>>>>
>>>>> set := IdentitySet new: n.
>>>>> Smalltalk garbageCollect.
>>>>> [1 to: n do: [ :i | set add: (objects at: i) ] ] timeToRun. "4949"
>>>>>
>>>>> set := LargeIdentitySet new.
>>>>> Smalltalk garbageCollect.
>>>>> [1 to: n do: [ :i | set add: (objects at: i) ] ] timeToRun. "331"
>>>>>
>>>>> set := (PluggableSet new: n)
>>>>> hashBlock: [ :object | object identityHash * 4096 + object class
>>>>> identityHash * 64 ]; "Change this to #basicIdentityHash in Pharo"
>>>>> equalBlock: [ :a :b | a == b ];
>>>>> yourself.
>>>>> Smalltalk garbageCollect.
>>>>> [1 to: n do: [ :i | set add: (objects at: i) ] ] timeToRun. "5511"
>>>>>
>>>>>
>>>>> I also have a LargeIdentityDictionary, which is relatively fast, but
>>>>> not
>>>>> as fast as LargeIdentitySet, because (for some unknown reason) we don't
>>>>> have a primitive that could support it. If we had a primitive like
>>>>> primitive 132 which would return the index of the element if found or
>>>>> 0 if
>>>>> not, then we could have a really fast LargeIdentityDictionary.
>>>>>
>>>>>
>>>>> Levente
>>>>>
>>>>> Hehe yes, if writing a version fully exploiting the limited range,
>>>> that's
>>>> probably the approach I would go for as well.
>>>> (IAssuming it's the version at http://leves.web.elte.hu/**
>>>> squeak/LargeIdentitySet.st<htt**p://leves.web.elte.hu/squeak/**
>>>> LargeIdentitySet.st<http://leves.web.elte.hu/squeak/LargeIdentitySet.st>
>>>> >
>>>> )
>>>>
>>>> Mariano commented in the version at http://www.squeaksource.com/**
>>>> FuelExperiments <http://www.squeaksource.com/**FuelExperiments<http://www.squeaksource.com/FuelExperiments>>
>>>> that it's
>>>>
>>>> slow for them, which I guess is due to not adopting #identityHash calls
>>>> to
>>>> #basicIdentityHash calls for Pharo:
>>>> ((0 to: 4095) collect: [:each | each << 22 \\ 4096 ]) asSet size -> 1
>>>> So it basically uses 1 bucket instead of 4096... Whoops. :)
>>>>
>>>> Uploaded a new version to the MC repository which is adapted for Pharo,
>>>> on the same machine my numbers were taken from, it does the same test
>>>> as I
>>>> used above in 871 ms. (181 with preallocation).
>>>>
>>>>
>>> Cool. One more thing: in Squeak the method using primitive 132 directly
>>> was renamed to #instVarsInclude:, so now #pointsTo: works as expected. If
>>> this was also added to Pharo, then the #pointsTo: sends should be changed
>>> to #instVarsInclude:, otherwise Array can be reported as included even if
>>> it wasn't added.
>>> I'll upload my LargeIdentityDictionary implementation to the same place
>>> this evening, since it's still 2-3 factor faster than other solutionts
>>> and
>>> there seem to be demand for it.
>>>
>>>
>>> Levente
>>>
>>>
>>> Cheers,
>>>> Henry
>>>>
>>>>
>>>>
>>>>
>>>
>>
>> --
>> Mariano
>> http://marianopeck.wordpress.**com <http://marianopeck.wordpress.com>
>>
>>
>
--
Mariano
http://marianopeck.wordpress.com
On ubuntu 12.04 64 bit, any change in size of Scratch's window causes it to
turn black and slowly shrink down to a thin strip. Quite an interesting bug!
Here's a video:
http://youtu.be/bpTX7O3NDy4
Fullscreen (via the window button - not Scratch's presentation mode) makes
the window fullscreen, but there is no repaint - the window remains black
until it is changed back into window mode (by clicking the rectangle). This
issue also happens on my 32 bit test OS.
Here's the command I used to launch, in case it's helpful:
/usr/lib/squeak/4.4.7-2357/squeakvm -encoding UTF-8 -vm-display-x11 -xshm
-plugins /usr/lib/scratch/plugins/:/usr/lib/squeak/4.4.7-2357/
-vm-sound-pulse /usr/share/scratch/Scratch.image
Any idea what might have changed in the VM that could cause these
issues? Could this be related to changes made for compiz compatibility?
-Amos
http://www.mirandabanda.org/files/Cog/VM/VM.r2559/
CogVM binaries as per VMMaker.oscog-eem.163/r2559.
Make wakeHighestPriority filter-out zombie processes; fixes Newspeak/Glue
crash.
Add -blockonerror flag to Unix & Mac VMs to allow attaching gdb on
error/segv.
Make the sigsegv handler catch SIGILL and SIGBUS on Unix and Mac.
Add 64-bit file support to linux builds.
Fix sqUnixX11.c ClipChildren to ClipByChildren.
--
best,
Eliot
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.177.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.177
Author: eem
Time: 27 June 2012, 12:25:12.409 pm
UUID: 4d05e29b-763c-451f-9354-f5f0cef201a1
Ancestors: VMMaker.oscog-eem.176
Add internalStackValue:put:.
Comment the purpose of the prim response routines.
=============== Diff against VMMaker.oscog-eem.176 ===============
Item was changed:
----- Method: CoInterpreter>>slowPrimitiveResponse (in category 'primitive support') -----
slowPrimitiveResponse
+ "Invoke a normal (non-quick) primitive.
+ Called under the assumption that primFunctionPtr has been preloaded"
- "Called under the assumption that primFunctionPtr has been preloaded"
| nArgs savedFramePointer savedStackPointer |
<inline: true>
<asmLabel: false>
<var: #savedFramePointer type: #'char *'>
<var: #savedStackPointer type: #'char *'>
cogit recordPrimTrace ifTrue:
[self fastLogPrim: messageSelector].
FailImbalancedPrimitives ifTrue:
[nArgs := argumentCount.
savedStackPointer := stackPointer.
savedFramePointer := framePointer].
self initPrimCall.
self dispatchFunctionPointer: primitiveFunctionPointer.
(FailImbalancedPrimitives
and: [self successful
and: [framePointer = savedFramePointer
and: [(self isMachineCodeFrame: framePointer) not]]]) ifTrue:"Don't fail if primitive has done something radical, e.g. perform:"
[stackPointer ~= (savedStackPointer + (nArgs * BytesPerWord)) ifTrue:
[self flag: 'Would be nice to make this a message send of e.g. unbalancedPrimitive to the current process or context'.
"This is necessary but insufficient; the result may still have been written to the stack.
At least we'll know something is wrong."
stackPointer := savedStackPointer.
self failUnbalancedPrimitive]].
"If we are profiling, take accurate primitive measures"
nextProfileTick > 0 ifTrue:
[self checkProfileTick: newMethod].
^self successful!
Item was changed:
----- Method: StackInterpreter>>externalQuickPrimitiveResponse (in category 'primitive support') -----
externalQuickPrimitiveResponse
+ "Invoke a quick primitive.
+ Called under the assumption that primFunctionPtr has been preloaded"
- "Called under the assumption that primFunctionPtr has been preloaded"
| localPrimIndex |
self assert: self isPrimitiveFunctionPointerAnIndex.
localPrimIndex := self cCoerceSimple: primitiveFunctionPointer to: #sqInt.
self assert: (localPrimIndex > 255 and: [localPrimIndex < 520]).
"Quick return inst vars"
localPrimIndex >= 264 ifTrue:
[self pop: 1 thenPush: (objectMemory fetchPointer: localPrimIndex - 264 ofObject: self stackTop).
^true].
"Quick return constants"
localPrimIndex = 256 ifTrue: [^true "return self"].
localPrimIndex = 257 ifTrue: [self pop: 1 thenPush: objectMemory trueObject. ^true].
localPrimIndex = 258 ifTrue: [self pop: 1 thenPush: objectMemory falseObject. ^true].
localPrimIndex = 259 ifTrue: [self pop: 1 thenPush: objectMemory nilObject. ^true].
self pop: 1 thenPush: (objectMemory integerObjectOf: localPrimIndex - 261).
^true!
Item was changed:
----- Method: StackInterpreter>>internalQuickPrimitiveResponse (in category 'primitive support') -----
internalQuickPrimitiveResponse
+ "Invoke a quick primitive.
+ Called under the assumption that primFunctionPtr has been preloaded"
- "Called under the assumption that primFunctionPtr has been preloaded"
| localPrimIndex |
self assert: self isPrimitiveFunctionPointerAnIndex.
localPrimIndex := self cCoerceSimple: primitiveFunctionPointer to: #sqInt.
self assert: (localPrimIndex > 255 and: [localPrimIndex < 520]).
"Quick return inst vars"
localPrimIndex >= 264 ifTrue:
[self internalStackTopPut: (objectMemory fetchPointer: localPrimIndex - 264 ofObject: self internalStackTop).
^true].
"Quick return constants"
localPrimIndex = 256 ifTrue: [^true "return self"].
localPrimIndex = 257 ifTrue: [self internalStackTopPut: objectMemory trueObject. ^true].
localPrimIndex = 258 ifTrue: [self internalStackTopPut: objectMemory falseObject. ^true].
localPrimIndex = 259 ifTrue: [self internalStackTopPut: objectMemory nilObject. ^true].
self internalStackTopPut: (objectMemory integerObjectOf: localPrimIndex - 261).
^true!
Item was added:
+ ----- Method: StackInterpreter>>internalStackValue:put: (in category 'internal interpreter access') -----
+ internalStackValue: offset put: aValue
+ "In the StackInterpreter stacks grow down."
+ ^stackPages longAtPointer: localSP + (offset * BytesPerWord) put: aValue!
Item was changed:
----- Method: StackInterpreter>>slowPrimitiveResponse (in category 'primitive support') -----
slowPrimitiveResponse
+ "Invoke a normal (non-quick) primitive.
+ Called under the assumption that primFunctionPtr has been preloaded"
- "Called under the assumption that primFunctionPtr has been preloaded"
| nArgs savedFramePointer savedStackPointer |
<inline: true>
<asmLabel: false>
<var: #savedFramePointer type: #'char *'>
<var: #savedStackPointer type: #'char *'>
FailImbalancedPrimitives ifTrue:
[nArgs := argumentCount.
savedStackPointer := stackPointer.
savedFramePointer := framePointer].
self initPrimCall.
self dispatchFunctionPointer: primitiveFunctionPointer.
(FailImbalancedPrimitives
and: [self successful
and: [framePointer = savedFramePointer]]) ifTrue:"Don't fail if primitive has done something radical, e.g. perform:"
[stackPointer ~= (savedStackPointer + (nArgs * BytesPerWord)) ifTrue:
[self flag: 'Would be nice to make this a message send of e.g. unbalancedPrimitive to the current process or context'.
"This is necessary but insufficient; the result may still have been written to the stack.
At least we'll know something is wrong."
stackPointer := savedStackPointer.
self failUnbalancedPrimitive]].
"If we are profiling, take accurate primitive measures"
nextProfileTick > 0 ifTrue:
[self checkProfileTick: newMethod].
^self successful!