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
Hi all
I have done a fresh svn co http://www.squeakvm.org/svn/squeak/branches/Cog
After doing that my previously successfull cmake build bit the dust.
As a sanity check, I then attempted a mvm build in build.linux32x86/squeak.cog.v3/build/mvm and this bombed out.
The same mvm build on an older source tree works fine.
For the c build, it gripes a lot about a lot of 'x' is used but never defined and ends with:
/../oscogvm/src/vm/cogit.c:1094:14: warning: 'oopisLessThan' used but never defined [enabled by default]
static sqInt oopisLessThan(sqInt anOop, sqInt otherOop) NoDbgRegParms;
^
make[1]: *** [cogit.o] Error 1
make: *** [vm/vm.a] Error 2
My cmake build (which was working prior to my svn CO of the latest) started complaining along similar lines:
/..../oscogvm/src/vm/cogit.c:21286:1: error: conflicting types for 'oopisLessThan'
oopisLessThan(sqInt anOop, sqInt otherOop)
^
/.../oscogvm/src/vm/cogit.c:1094:14: note: previous declaration of 'oopisLessThan' was here
static sqInt oopisLessThan(sqInt anOop, sqInt otherOop) NoDbgRegParms;
^
make[2]: *** [CMakeFiles/cog.dir/home/wm/usr/src/smalltalk/CMake.oscog/cogVMMaker/Contents/Resources/oscogvm/src/vm/cogit.c.o] Error 1
make[1]: *** [CMakeFiles/cog.dir/all] Error 2
make: *** [all] Error 2
Any pointers on how to think about this are appreciated.
cheers.
tty
thx.
tty
Hi Ronie, This is really exciting (and I've cross-posted to vm-dev). I
guess this will help multi-monitor displays to have a window on each
monitor?
Ronie Salgado wrote:
> Hello There,
>
> I have been working in OSWindow, which is a cross platform API for
> dealing with native operating system windows. This API requires using
> a custom VM and the library SDL2.
>
> With this API, even the main Pharo window is handled almost completely
> in image side using NativeBoost.
>
> The only support required from the VM is a small periodical check in
> the heartbeat about the presence of events. This no more than 10 lines
> of code.
Is there much you needed to change/delete from the existing VM window
initialization. Since the VM is shared with other Smalltalk platforms,
how compatible would this be to maintain in parallel with the existing
VM windows initialization?
cheers -ben
>
> This is currently working very well in my Linux machine, so I need to
> start testing this stuff.
>
> For Windows, soon I will be building the custom VM. My last built was
> very dirty and I want to do something more clean.
>
> For Mac OS X, I don't have one for testing. But Alex is going allow me
> to borrow one for some time. So be patience.
>
> As for Woden, it is a new 3D graphics engine that I started making.
> This one requires currently support of OSWindow and also shows some
> cool stuffs.
>
> As for prebuilt versions of the VM with OSWindow support along with
> preloaded images for both, OSWindow and Woden. And screenshots.
>
> Well, I am putting them here: http://ronie.cl/OSWindow/
>
> Greetings,
> Ronie
Eliot Miranda uploaded a new version of Cog to project VM Maker:
http://source.squeak.org/VMMaker/Cog-eem.176.mcz
==================== Summary ====================
Name: Cog-eem.176
Author: eem
Time: 31 July 2014, 10:26:23.464 am
UUID: 82a97d21-c0aa-4248-b3b2-50212b8d32f8
Ancestors: Cog-eem.174, Cog.pharo-EstebanLorenzano.175
Merge with Cog.pharo-EstebanLorenzano.175.
=============== Diff against Cog-eem.174 ===============
Item was added:
+ ----- Method: SpurBootstrap class>>BehaviorPROTOTYPEindexIfCompact (in category 'method prototypes') -----
+ BehaviorPROTOTYPEindexIfCompact
+ "Backward compatibility with the Squeak V3 object format.
+ Spur does not have a distinction between compact and non-compact classes."
+ ^0!
Item was changed:
+ ----- Method: SpurBootstrap class>>CharacterPROTOTYPEclone (in category 'method prototypes squeak') -----
- ----- Method: SpurBootstrap class>>CharacterPROTOTYPEclone (in category 'method prototypes') -----
CharacterPROTOTYPEclone
"Answer the receiver, because Characters are unique."
^self!
Item was added:
+ ----- Method: SpurBootstrap class>>CharacterPROTOTYPEsetValue: (in category 'method prototypes pharo') -----
+ CharacterPROTOTYPEsetValue: newValue
+ self error: 'Characters are immutable'!
Item was changed:
+ ----- Method: SpurBootstrap class>>ClassBuilderPROTOTYPEcomputeFormat:instSize:forSuper:ccIndex: (in category 'method prototypes') -----
- ----- Method: SpurBootstrap class>>ClassBuilderPROTOTYPEcomputeFormat:instSize:forSuper:ccIndex: (in category 'method prototypes squeak') -----
ClassBuilderPROTOTYPEcomputeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex
"Compute the new format for making oldClass a subclass of newSuper.
Answer the format or nil if there is any problem."
| instSize isVar isWords isPointers isWeak |
type == #compiledMethod ifTrue:
[newInstSize > 0 ifTrue:
[self error: 'A compiled method class cannot have named instance variables'.
^nil].
^CompiledMethod format].
instSize := newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]).
instSize > 65535 ifTrue:
[self error: 'Class has too many instance variables (', instSize printString,')'.
^nil].
type == #normal ifTrue:[isVar := isWeak := false. isWords := isPointers := true].
type == #bytes ifTrue:[isVar := true. isWords := isPointers := isWeak := false].
type == #words ifTrue:[isVar := isWords := true. isPointers := isWeak := false].
type == #variable ifTrue:[isVar := isPointers := isWords := true. isWeak := false].
type == #weak ifTrue:[isVar := isWeak := isWords := isPointers := true].
type == #ephemeron ifTrue:[isVar := false. isWeak := isWords := isPointers := true].
type == #immediate ifTrue:[isVar := isWeak := isPointers := false. isWords := true].
(isPointers not and: [instSize > 0]) ifTrue:
[self error: 'A non-pointer class cannot have named instance variables'.
^nil].
^self format: instSize variable: isVar words: isWords pointers: isPointers weak: isWeak!
Item was changed:
+ ----- Method: SpurBootstrap class>>ClassBuilderPROTOTYPEformat:variable:words:pointers:weak: (in category 'method prototypes') -----
- ----- Method: SpurBootstrap class>>ClassBuilderPROTOTYPEformat:variable:words:pointers:weak: (in category 'method prototypes squeak') -----
ClassBuilderPROTOTYPEformat: nInstVars variable: isVar words: isWords pointers: isPointers weak: isWeak
"Compute the format for the given instance specfication.
Above Cog Spur the class format is
<5 bits inst spec><16 bits inst size>
where the 5-bit inst spec is
0 = 0 sized objects (UndefinedObject True False et al)
1 = non-indexable objects with inst vars (Point et al)
2 = indexable objects with no inst vars (Array et al)
3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al)
4 = weak indexable objects with inst vars (WeakArray et al)
5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron)
6 = unused
7 = immediates (SmallInteger, Character)
8 = unused
9 = reserved for 64-bit indexable
10-11 = 32-bit indexable (Bitmap)
12-15 = 16-bit indexable
16-23 = 8-bit indexable
24-31 = compiled methods (CompiledMethod)"
| instSpec |
instSpec := isWeak
ifTrue:
[isVar
ifTrue: [4]
ifFalse: [5]]
ifFalse:
[isPointers
ifTrue:
[isVar
ifTrue: [nInstVars > 0 ifTrue: [3] ifFalse: [2]]
ifFalse: [nInstVars > 0 ifTrue: [1] ifFalse: [0]]]
ifFalse:
[isVar
ifTrue: [isWords ifTrue: [12] ifFalse: [16]]
ifFalse: [7]]].
^(instSpec bitShift: 16) + nInstVars!
Item was changed:
+ ----- Method: SpurBootstrap class>>ClassBuilderPROTOTYPEsuperclass:immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'method prototypes') -----
- ----- Method: SpurBootstrap class>>ClassBuilderPROTOTYPEsuperclass:immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'method prototypes squeak') -----
ClassBuilderPROTOTYPEsuperclass: aClass
immediateSubclass: t instanceVariableNames: f
classVariableNames: d poolDictionaries: s category: cat
"This is the standard initialization message for creating a
new immediate class as a subclass of an existing class."
| env |
aClass instSize > 0
ifTrue: [^self error: 'cannot make an immediate subclass of a class with named fields'].
aClass isVariable
ifTrue: [^self error: 'cannot make an immediate subclass of a class with indexed instance variables'].
aClass isPointers
ifFalse: [^self error: 'cannot make an immediate subclass of a class without pointer fields'].
"Cope with pre-environment and environment versions. Simplify asap."
env := (Smalltalk classNamed: #EnvironmentRequest)
ifNil: [aClass environment]
ifNotNil: [:erc| erc signal ifNil: [aClass environment]].
^self
name: t
inEnvironment: env
subclassOf: aClass
type: #immediate
instanceVariableNames: f
classVariableNames: d
poolDictionaries: s
category: cat!
Item was changed:
+ ----- Method: SpurBootstrap class>>ClassBuilderPROTOTYPEupdate:to: (in category 'method prototypes') -----
- ----- Method: SpurBootstrap class>>ClassBuilderPROTOTYPEupdate:to: (in category 'method prototypes squeak') -----
ClassBuilderPROTOTYPEupdate: oldClass to: newClass
"Convert oldClass, all its instances and possibly its meta class into newClass,
instances of newClass and possibly its meta class. The process is surprisingly
simple in its implementation and surprisingly complex in its nuances and potentially
bad side effects.
We can rely on two assumptions (which are critical):
#1: The method #updateInstancesFrom: will not create any lasting pointers to
'old' instances ('old' is quote on quote since #updateInstancesFrom: will do
a become of the old vs. the new instances and therefore it will not create
pointers to *new* instances before the #become: which are *old* afterwards)
#2: The non-preemptive execution of the critical piece of code guarantees that
nobody can get a hold by 'other means' (such as process interruption and
reflection) on the old instances.
Given the above two, we know that after #updateInstancesFrom: there are no pointers
to any old instances. After the forwarding become there will be no pointers to the old
class or meta class either.
Andreas Raab, 2/27/2003 23:42"
| meta |
meta := oldClass isMeta.
"Note: Everything from here on will run without the ability to get interrupted
to prevent any other process to create new instances of the old class."
["Note: The following removal may look somewhat obscure and needs an explanation.
When we mutate the class hierarchy we create new classes for any existing subclass.
So it may look as if we don't have to remove the old class from its superclass. However,
at the top of the hierarchy (the first class we reshape) that superclass itself is not newly
created so therefore it will hold both the oldClass and newClass in its (obsolete or not)
subclasses. Since the #become: below will transparently replace the pointers to oldClass
with newClass the superclass would have newClass in its subclasses TWICE. With rather
unclear effects if we consider that we may convert the meta-class hierarchy itself (which
is derived from the non-meta class hierarchy).
Due to this problem ALL classes are removed from their superclass just prior to converting
them. Here, breaking the superclass/subclass invariant really doesn't matter since we will
effectively remove the oldClass (becomeForward:) just a few lines below."
oldClass superclass removeSubclass: oldClass.
oldClass superclass removeObsoleteSubclass: oldClass.
"make sure that the VM cache is clean"
oldClass methodDict do: [:cm | cm flushCache].
"Convert the instances of oldClass into instances of newClass"
newClass updateInstancesFrom: oldClass.
meta
ifTrue:
[oldClass becomeForward: newClass.
oldClass updateMethodBindingsTo: oldClass binding]
ifFalse:
[{oldClass. oldClass class} elementsForwardIdentityTo: {newClass. newClass class}.
oldClass updateMethodBindingsTo: oldClass binding.
oldClass class updateMethodBindingsTo: oldClass class binding].
"eem 5/31/2014 07:22 At this point there used to be a garbage collect whose purpose was
to ensure no old instances existed after the becomeForward:. Without the GC it was possible
to resurrect old instances using e.g. allInstancesDo:. This was because the becomeForward:
updated references from the old objects to new objects but didn't destroy the old objects.
But as of late 2013/early 2014 becomeForward: has been modified to free all the old objects."]
valueUnpreemptively!
Item was changed:
+ ----- Method: SpurBootstrap class>>IntegerclassPROTOTYPEinitialize (in category 'method prototypes squeak') -----
- ----- Method: SpurBootstrap class>>IntegerclassPROTOTYPEinitialize (in category 'method prototypes') -----
IntegerclassPROTOTYPEinitialize
"Integer initialize"
self initializeLowBitPerByteTable!
Item was added:
+ ----- Method: SpurBootstrap class>>SmalltalkImagePROTOTYPEnewSpecialObjectsArray (in category 'method prototypes pharo') -----
+ SmalltalkImagePROTOTYPEnewSpecialObjectsArray
+ "Smalltalk recreateSpecialObjectsArray"
+
+ "To external package developers:
+ **** DO NOT OVERRIDE THIS METHOD. *****
+ If you are writing a plugin and need additional special object(s) for your own use,
+ use addGCRoot() function and use own, separate special objects registry "
+
+ "The Special Objects Array is an array of objects used by the Squeak virtual machine.
+ Its contents are critical and accesses to it by the VM are unchecked, so don't even
+ think of playing here unless you know what you are doing."
+ | newArray |
+ newArray := Array new: 60.
+ "Nil false and true get used throughout the interpreter"
+ newArray at: 1 put: nil.
+ newArray at: 2 put: false.
+ newArray at: 3 put: true.
+ "This association holds the active process (a ProcessScheduler)"
+ newArray at: 4 put: (self globals associationAt: #Processor).
+ "Numerous classes below used for type checking and instantiation"
+ newArray at: 5 put: Bitmap.
+ newArray at: 6 put: SmallInteger.
+ newArray at: 7 put: ByteString.
+ newArray at: 8 put: Array.
+ newArray at: 9 put: Smalltalk.
+ newArray at: 10 put: Float.
+ newArray at: 11 put: (self globals at: #MethodContext ifAbsent: [self globals at: #Context]).
+ newArray at: 12 put: nil. "was BlockContext."
+ newArray at: 13 put: Point.
+ newArray at: 14 put: LargePositiveInteger.
+ newArray at: 15 put: Display.
+ newArray at: 16 put: Message.
+ newArray at: 17 put: CompiledMethod.
+ newArray at: 18 put: ((self primitiveGetSpecialObjectsArray at: 18) ifNil: [Semaphore new]). "low space Semaphore"
+ newArray at: 19 put: Semaphore.
+ newArray at: 20 put: Character.
+ newArray at: 21 put: #doesNotUnderstand:.
+ newArray at: 22 put: #cannotReturn:.
+ newArray at: 23 put: nil. "This is the process signalling low space."
+ "An array of the 32 selectors that are compiled as special bytecodes,
+ paired alternately with the number of arguments each takes."
+ newArray at: 24 put: #( #+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1
+ #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1
+ #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 #class 0
+ #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0 ).
+ "An array of the 255 Characters in ascii order.
+ Cog inlines table into machine code at: prim so do not regenerate it.
+ This is nil in Spur, which has immediate Characters."
+ newArray at: 25 put: (self primitiveGetSpecialObjectsArray at: 25).
+ newArray at: 26 put: #mustBeBoolean.
+ newArray at: 27 put: ByteArray.
+ newArray at: 28 put: Process.
+ "An array of up to 31 classes whose instances will have compact headers; an empty array in Spur"
+ newArray at: 29 put: self compactClassesArray.
+ newArray at: 30 put: ((self primitiveGetSpecialObjectsArray at: 30) ifNil: [Semaphore new]). "delay Semaphore"
+ newArray at: 31 put: ((self primitiveGetSpecialObjectsArray at: 31) ifNil: [Semaphore new]). "user interrupt Semaphore"
+ "Entries 32 - 34 unreferenced. Previously these contained prototype instances to be copied for fast initialization"
+ newArray at: 32 put: nil. "was the prototype Float"
+ newArray at: 33 put: nil. "was the prototype 4-byte LargePositiveInteger"
+ newArray at: 34 put: nil. "was the prototype Point"
+ newArray at: 35 put: #cannotInterpret:.
+ newArray at: 36 put: nil. "was the prototype MethodContext"
+ newArray at: 37 put: BlockClosure.
+ newArray at: 38 put: nil. "was the prototype BlockContext"
+ "array of objects referred to by external code"
+ newArray at: 39 put: (self primitiveGetSpecialObjectsArray at: 39). "external semaphores"
+ newArray at: 40 put: nil. "Reserved for Mutex in Cog VMs"
+ newArray at: 41 put: ((self primitiveGetSpecialObjectsArray at: 41) ifNil: [LinkedList new]). "Reserved for a LinkedList instance for overlapped calls in CogMT"
+ newArray at: 42 put: ((self primitiveGetSpecialObjectsArray at: 42) ifNil: [Semaphore new]). "finalization Semaphore"
+ newArray at: 43 put: LargeNegativeInteger.
+ "External objects for callout.
+ Note: Written so that one can actually completely remove the FFI."
+ newArray at: 44 put: (self at: #ExternalAddress ifAbsent: []).
+ newArray at: 45 put: (self at: #ExternalStructure ifAbsent: []).
+ newArray at: 46 put: (self at: #ExternalData ifAbsent: []).
+ newArray at: 47 put: (self at: #ExternalFunction ifAbsent: []).
+ newArray at: 48 put: (self at: #ExternalLibrary ifAbsent: []).
+ newArray at: 49 put: #aboutToReturn:through:.
+ newArray at: 50 put: #run:with:in:.
+ "51 reserved for immutability message"
+ newArray at: 51 put: #attemptToAssign:withIndex:.
+ newArray at: 52 put: #(nil "nil => generic error" #'bad receiver'
+ #'bad argument' #'bad index'
+ #'bad number of arguments'
+ #'inappropriate operation' #'unsupported operation'
+ #'no modification' #'insufficient object memory'
+ #'insufficient C memory' #'not found' #'bad method'
+ #'internal error in named primitive machinery'
+ #'object may move' #'resource limit exceeded'
+ #'object is pinned' #'primitive write beyond end of object').
+ "53 to 55 are for Alien"
+ newArray at: 53 put: (self at: #Alien ifAbsent: []).
+ newArray at: 54 put: #invokeCallbackContext::. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks."
+ newArray at: 55 put: (self at: #UnsafeAlien ifAbsent: []).
+
+ "Used to be WeakFinalizationList for WeakFinalizationList hasNewFinalization, obsoleted by ephemeron support."
+ newArray at: 56 put: nil.
+
+ "reserved for foreign callback process"
+ newArray at: 57 put: (self primitiveGetSpecialObjectsArray at: 57 ifAbsent: []).
+
+ newArray at: 58 put: #unusedBytecode.
+ "59 reserved for Sista counter tripped message"
+ newArray at: 59 put: #conditionalBranchCounterTrippedOn:.
+ "60 reserved for Sista class trap message"
+ newArray at: 60 put: #classTrapFor:.
+
+ ^newArray!
Item was changed:
+ ----- Method: SpurBootstrap class>>SmalltalkImagePROTOTYPErecreateSpecialObjectsArray (in category 'method prototypes squeak') -----
- ----- Method: SpurBootstrap class>>SmalltalkImagePROTOTYPErecreateSpecialObjectsArray (in category 'method prototypes') -----
SmalltalkImagePROTOTYPErecreateSpecialObjectsArray
"Smalltalk recreateSpecialObjectsArray"
"To external package developers:
**** DO NOT OVERRIDE THIS METHOD. *****
If you are writing a plugin and need additional special object(s) for your own use,
use addGCRoot() function and use own, separate special objects registry "
"The Special Objects Array is an array of objects used by the Squeak virtual machine.
Its contents are critical and accesses to it by the VM are unchecked, so don't even
think of playing here unless you know what you are doing."
| newArray |
newArray := Array new: 60.
"Nil false and true get used throughout the interpreter"
newArray at: 1 put: nil.
newArray at: 2 put: false.
newArray at: 3 put: true.
"This association holds the active process (a ProcessScheduler)"
newArray at: 4 put: (self specialObjectsArray at: 4) "(self bindingOf: #Processor) but it answers an Alias".
"Numerous classes below used for type checking and instantiation"
newArray at: 5 put: Bitmap.
newArray at: 6 put: SmallInteger.
newArray at: 7 put: ByteString.
newArray at: 8 put: Array.
newArray at: 9 put: Smalltalk.
newArray at: 10 put: Float.
+ newArray at: 11 put: (self globals at: #MethodContext ifAbsent: [self globals at: #Context]).
+ newArray at: 12 put: nil. "was BlockContext."
- newArray at: 11 put: MethodContext.
- newArray at: 12 put: BlockContext.
newArray at: 13 put: Point.
newArray at: 14 put: LargePositiveInteger.
newArray at: 15 put: Display.
newArray at: 16 put: Message.
newArray at: 17 put: CompiledMethod.
+ newArray at: 18 put: ((self specialObjectsArray at: 18) ifNil: [Semaphore new]). "low space Semaphore"
- newArray at: 18 put: (self specialObjectsArray at: 18). "(low space Semaphore)"
newArray at: 19 put: Semaphore.
newArray at: 20 put: Character.
newArray at: 21 put: #doesNotUnderstand:.
newArray at: 22 put: #cannotReturn:.
newArray at: 23 put: nil. "This is the process signalling low space."
"An array of the 32 selectors that are compiled as special bytecodes,
paired alternately with the number of arguments each takes."
newArray at: 24 put: #( #+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1
#* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1
#at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 #class 0
#blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0 ).
"An array of the 255 Characters in ascii order.
Cog inlines table into machine code at: prim so do not regenerate it.
This is nil in Spur, which has immediate Characters."
newArray at: 25 put: (self specialObjectsArray at: 25).
newArray at: 26 put: #mustBeBoolean.
newArray at: 27 put: ByteArray.
newArray at: 28 put: Process.
"An array of up to 31 classes whose instances will have compact headers; an empty array in Spur"
newArray at: 29 put: self compactClassesArray.
+ newArray at: 30 put: ((self specialObjectsArray at: 30) ifNil: [Semaphore new]). "delay Semaphore"
+ newArray at: 31 put: ((self specialObjectsArray at: 31) ifNil: [Semaphore new]). "user interrupt Semaphore"
- newArray at: 30 put: (self specialObjectsArray at: 30). "(delay Semaphore)"
- newArray at: 31 put: (self specialObjectsArray at: 31). "(user interrupt Semaphore)"
"Entries 32 - 34 unreferenced. Previously these contained prototype instances to be copied for fast initialization"
newArray at: 32 put: nil. "was the prototype Float"
newArray at: 33 put: nil. "was the prototype 4-byte LargePositiveInteger"
newArray at: 34 put: nil. "was the prototype Point"
newArray at: 35 put: #cannotInterpret:.
newArray at: 36 put: nil. "was the prototype MethodContext"
newArray at: 37 put: BlockClosure.
newArray at: 38 put: nil. "was the prototype BlockContext"
"array of objects referred to by external code"
newArray at: 39 put: (self specialObjectsArray at: 39). "external semaphores"
newArray at: 40 put: nil. "Reserved for Mutex in Cog VMs"
+ newArray at: 41 put: ((self specialObjectsArray at: 41) ifNil: [LinkedList new]). "Reserved for a LinkedList instance for overlapped calls in CogMT"
- newArray at: 41 put: ((self specialObjectsArray at: 39) ifNil: [LinkedList new]). "Reserved for a LinkedList instance for overlapped calls in CogMT"
newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). "finalization Semaphore"
newArray at: 43 put: LargeNegativeInteger.
"External objects for callout.
Note: Written so that one can actually completely remove the FFI."
newArray at: 44 put: (self at: #ExternalAddress ifAbsent: []).
newArray at: 45 put: (self at: #ExternalStructure ifAbsent: []).
newArray at: 46 put: (self at: #ExternalData ifAbsent: []).
newArray at: 47 put: (self at: #ExternalFunction ifAbsent: []).
newArray at: 48 put: (self at: #ExternalLibrary ifAbsent: []).
newArray at: 49 put: #aboutToReturn:through:.
newArray at: 50 put: #run:with:in:.
"51 reserved for immutability message"
newArray at: 51 put: #attemptToAssign:withIndex:.
newArray at: 52 put: #(nil "nil => generic error" #'bad receiver'
#'bad argument' #'bad index'
#'bad number of arguments'
#'inappropriate operation' #'unsupported operation'
#'no modification' #'insufficient object memory'
#'insufficient C memory' #'not found' #'bad method'
#'internal error in named primitive machinery'
#'object may move' #'resource limit exceeded'
#'object is pinned' #'primitive write beyond end of object').
"53 to 55 are for Alien"
newArray at: 53 put: (self at: #Alien ifAbsent: []).
newArray at: 54 put: #invokeCallbackContext::. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks."
newArray at: 55 put: (self at: #UnsafeAlien ifAbsent: []).
"Used to be WeakFinalizationList for WeakFinalizationList hasNewFinalization, obsoleted by ephemeron support."
newArray at: 56 put: nil.
"reserved for foreign callback process"
newArray at: 57 put: (self specialObjectsArray at: 57 ifAbsent: []).
newArray at: 58 put: #unusedBytecode.
"59 reserved for Sista counter tripped message"
newArray at: 59 put: #conditionalBranchCounterTrippedOn:.
"60 reserved for Sista class trap message"
newArray at: 60 put: #classTrapFor:.
"Now replace the interpreter's reference in one atomic operation"
self specialObjectsArray becomeForward: newArray!
Item was changed:
----- Method: SpurBootstrap>>classNameForPrototypeMethod: (in category 'method prototypes') -----
classNameForPrototypeMethod: protoMethod
| protoSelector |
protoSelector := protoMethod selector.
+ #('SQUEAKPROTOTYPE' 'PHAROPROTOTYPE' 'PROTOTYPE') do:
+ [:prototype| | index |
+ (index := protoSelector indexOfSubCollection: 'PROTOTYPE') ~= 0 ifTrue:
+ [^(protoSelector first: index - 1) asSymbol]].
+ self error: 'really??'!
- ^(protoSelector first: (protoSelector indexOfSubCollection: 'PROTOTYPE') - 1) asSymbol!
Item was changed:
----- Method: SpurBootstrap>>rehashImage (in category 'bootstrap image') -----
rehashImage
"Rehash all collections in newHeap.
Find out which classes implement rehash, entering a 1 against their classIndex in rehashFlags.
Enumerate all objects, rehashing those whose class has a bit set in rehashFlags."
| n sim rehashFlags |
sim := StackInterpreterSimulator onObjectMemory: newHeap.
+ sim
+ setImageHeaderFlagsFrom: oldInterpreter getImageHeaderFlags;
+ imageName: 'spur image'.
- sim imageName: 'spur image'.
newHeap coInterpreter: sim.
sim bootstrapping: true.
sim initializeInterpreter: 0.
sim instVarNamed: 'methodDictLinearSearchLimit' put: SmallInteger maxVal.
newHeap
setHashBitsOf: newHeap nilObject to: 1;
setHashBitsOf: newHeap falseObject to: 2;
setHashBitsOf: newHeap trueObject to: 3.
rehashFlags := ByteArray new: newHeap numClassTablePages * newHeap classTablePageSize.
n := 0.
newHeap classTableObjectsDo:
[:class| | classIndex |
sim messageSelector: (map at: rehashSym).
"Lookup rehash but don't be fooled by ProtoObject>>rehash, which is just ^self."
((sim lookupMethodNoMNUEtcInClass: class) = 0
and: [(sim isQuickPrimitiveIndex: (sim primitiveIndexOf: (sim instVarNamed: 'newMethod'))) not]) ifTrue:
[n := n + 1.
classIndex := newHeap rawHashBitsOf: class.
rehashFlags
at: classIndex >> 3 + 1
put: ((rehashFlags at: classIndex >> 3 + 1)
bitOr: (1 << (classIndex bitAnd: 7)))]].
Transcript cr; print: n; nextPutAll: ' classes understand rehash. rehashing instances...'; flush.
n := 0.
self withExecutableInterpreter: sim
do: [sim setBreakSelector: 'error:'.
"don't rehash twice (actually without limit), so don't rehash any new objects created."
newHeap allExistingOldSpaceObjectsDo:
[:o| | classIndex |
classIndex := newHeap classIndexOf: o.
((rehashFlags at: classIndex >> 3 + 1) anyMask: 1 << (classIndex bitAnd: 7)) ifTrue:
[(n := n + 1) \\ 8 = 0 ifTrue:
[Transcript nextPut: $.; flush].
"2845 = n ifTrue: [self halt]."
"Rehash an object if its size is > 0.
Symbol implements rehash, but let's not waste time rehashing it; in Squeak
up to 2013 symbols are kept in a set which will get reashed anyway..
Don't rehash empty collections; they may be large for a reason and rehashing will shrink them."
((sim addressCouldBeClassObj: o)
or: [(self interpreter: sim
object: o
perform: (map at: sizeSym)
withArguments: #()) = (newHeap integerObjectOf: 0)]) ifFalse:
[self interpreter: sim
object: o
perform: (map at: rehashSym)
withArguments: #()]]]]!
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.839.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.839
Author: eem
Time: 30 July 2014, 7:41:05.928 pm
UUID: 11079ac8-603b-476f-8f5f-a4b551d0421f
Ancestors: VMMaker.oscog-eem.838
Spur:
Fix initialization of the heap-resident remembered set added
by VMMaker.oscog-eem.827. It must be created /after/ old
space is initialized.
Sista:
More work defining the Sista bytecodes in
SistaStackToRegisterMappingCogit.
=============== Diff against VMMaker.oscog-eem.838 ===============
Item was changed:
----- Method: Cogit>>generateTrampolines (in category 'initialization') -----
generateTrampolines
"Generate the run-time entries and exits at the base of the native code zone and update the base.
Read the class-side method trampolines for documentation on the various trampolines"
| methodZoneStart |
methodZoneStart := methodZoneBase.
self allocateOpcodes: 80 bytecodes: 0.
initialPC := 0.
endPC := numAbstractOpcodes - 1.
hasYoungReferent := false.
self generateSendTrampolines.
self generateMissAbortTrampolines.
objectRepresentation generateObjectRepresentationTrampolines.
self generateRunTimeTrampolines.
self cppIf: NewspeakVM ifTrue: [self generateNewspeakRuntime].
+ self cppIf: SistaVM ifTrue: [self generateSistaRuntime].
self generateEnilopmarts.
self generateTracingTrampolines.
"finish up"
self recordGeneratedRunTime: 'methodZoneBase' address: methodZoneBase.
processor flushICacheFrom: methodZoneStart to: methodZoneBase!
Item was changed:
----- Method: ObjectMemory>>isArrayNonImm: (in category 'header access') -----
isArrayNonImm: oop
+ <api>
+ "Answer if this is an indexable object with pointer elements, e.g., an array"
- "Answer true if this is an indexable object with pointer elements, e.g., an array"
^ (self formatOf: oop) = 2!
Item was changed:
----- Method: SimpleStackBasedCogit class>>initializeBytecodeTableForSistaV1 (in category 'class initialization') -----
initializeBytecodeTableForSistaV1
"SimpleStackBasedCogit initializeBytecodeTableForSistaV1"
self flag:
'Special selector send class must be inlined to agree with the interpreter, which
inlines class. If class is sent to e.g. a general instance of ProtoObject then unless
class is inlined there will be an MNU. It must be that the Cointerpreter and Cogit
have identical semantics. We get away with not hardwiring the other special
selectors either because in the Cointerpreter they are not inlined or because they
are inlined only to instances of classes for which there will always be a method.'.
self generatorTableFrom: #(
"1 byte bytecodes"
"pushes"
(1 0 15 genPushReceiverVariableBytecode)
(1 16 31 genPushLiteralVariable16CasesBytecode needsFrameNever: 1)
(1 32 63 genPushLiteralConstantBytecode needsFrameNever: 1)
(1 64 75 genPushTemporaryVariableBytecode)
(1 76 76 genPushReceiverBytecode)
(1 77 77 genPushConstantTrueBytecode needsFrameNever: 1)
(1 78 78 genPushConstantFalseBytecode needsFrameNever: 1)
(1 79 79 genPushConstantNilBytecode needsFrameNever: 1)
(1 80 80 genPushConstantZeroBytecode needsFrameNever: 1)
(1 81 81 genPushConstantOneBytecode needsFrameNever: 1)
(1 82 82 genExtPushPseudoVariable)
(1 83 83 duplicateTopBytecode needsFrameNever: 1)
(1 84 87 unknownBytecode)
"returns"
(1 88 88 genReturnReceiver return needsFrameIfInBlock: isMappedInBlock 0)
(1 89 89 genReturnTrue return needsFrameIfInBlock: isMappedInBlock 0)
(1 90 90 genReturnFalse return needsFrameIfInBlock: isMappedInBlock 0)
(1 91 91 genReturnNil return needsFrameIfInBlock: isMappedInBlock 0)
(1 92 92 genReturnTopFromMethod return needsFrameIfInBlock: isMappedInBlock -1)
(1 93 93 genReturnNilFromBlock return needsFrameNever: -1)
(1 94 94 genReturnTopFromBlock return needsFrameNever: -1)
(1 95 95 genExtNopBytecode needsFrameNever: 0)
"sends"
(1 96 117 genSpecialSelectorSend isMapped) "#+ #- #< #> #<= #>= #= #~= #* #/ #\\ #@ #bitShift: #// #bitAnd: #bitOr: #at: #at:put: #size #next #nextPut: #atEnd"
(1 118 118 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
(1 119 119 genSpecialSelectorClass needsFrameNever: notMapped 0) "not mapped because it is directly inlined (for now)"
(1 120 127 genSpecialSelectorSend isMapped) "#blockCopy: #value #value: #do: #new #new: #x #y"
(1 128 143 genSendLiteralSelector0ArgsBytecode isMapped)
(1 144 159 genSendLiteralSelector1ArgBytecode isMapped)
(1 160 175 genSendLiteralSelector2ArgsBytecode isMapped)
"jumps"
(1 176 183 genShortUnconditionalJump branch v3:ShortForward:Branch:Distance:)
(1 184 191 genShortJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(1 192 199 genShortJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
"stores"
(1 200 207 genStoreAndPopReceiverVariableBytecode needsFrameNever: -1) "N.B. not frameless if immutability"
(1 208 215 genStoreAndPopTemporaryVariableBytecode)
(1 216 216 genPopStackBytecode needsFrameNever: -1)
(1 217 223 unknownBytecode)
"2 byte bytecodes"
(2 224 224 extABytecode extension)
(2 225 225 extBBytecode extension)
"pushes"
(2 226 226 genExtPushReceiverVariableBytecode)
(2 227 227 genExtPushLiteralVariableBytecode needsFrameNever: 1)
(2 228 228 genExtPushLiteralBytecode needsFrameNever: 1)
(2 229 229 genLongPushTemporaryVariableBytecode)
(2 230 230 genPushClosureTempsBytecode)
(2 231 231 genPushNewArrayBytecode)
(2 232 232 genExtPushIntegerBytecode needsFrameNever: 1)
(2 233 233 genExtPushCharacterBytecode needsFrameNever: 1)
"returns"
"sends"
(2 234 234 genExtSendBytecode isMapped)
(2 235 235 genExtSendSuperBytecode isMapped)
"sista bytecodes"
(2 236 236 genExtTrapIfNotInstanceOfBehaviorsBytecode isMapped)
"jumps"
(2 237 237 genExtUnconditionalJump branch isMapped "because of interrupt check" v4:Long:Branch:Distance:)
(2 238 238 genExtJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
(2 239 239 genExtJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
"stores"
(2 240 240 genExtStoreAndPopReceiverVariableBytecode)
(2 241 241 genExtStoreAndPopLiteralVariableBytecode)
(2 242 242 genLongStoreAndPopTemporaryVariableBytecode)
(2 243 243 genExtStoreReceiverVariableBytecode)
(2 244 244 genExtStoreLiteralVariableBytecode)
(2 245 245 genLongStoreTemporaryVariableBytecode)
(2 246 247 unknownBytecode)
"3 byte bytecodes"
+ (3 248 248 genCallPrimitiveBytecode)
- (3 248 248 callPrimitiveBytecode)
(3 249 249 unknownBytecode) "reserved for Push Float"
(3 250 250 genExtPushClosureBytecode block v4:Block:Code:Size:)
(3 251 251 genPushRemoteTempLongBytecode)
(3 252 252 genStoreRemoteTempLongBytecode)
(3 253 253 genStoreAndPopRemoteTempLongBytecode)
(3 254 255 unknownBytecode))!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genExtTrapIfNotInstanceOfBehaviorsBytecode (in category 'bytecode generators') -----
+ genExtTrapIfNotInstanceOfBehaviorsBytecode
+ "SistaV1: * 236 11101100 iiiiiiii Trap If Not Instance Of Behavior/Array Of Behavior #iiiiiiii (+ Extend A * 256, where Extend A >= 0)"
+ "THis realy makes sense only for the optimizing JITs"
+ ^EncounteredUnknownBytecode!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genPushClosureTempsBytecode (in category 'bytecode generators') -----
+ genPushClosureTempsBytecode
+ "SistaV1: 230 11100110 iiiiiiii PushNClosureTemps iiiiiiii"
+ 1 to: byte1 do:
+ [:i| self genPushLiteral: objectMemory nilObject]!
Item was changed:
StackToRegisterMappingCogit subclass: #SistaStackToRegisterMappingCogit
+ instanceVariableNames: 'picDataIndex picData numCounters counters counterIndex initialCounterValue prevMapAbsPCMcpc ceClassTrapTrampoline'
- instanceVariableNames: 'picDataIndex picData numCounters counters counterIndex initialCounterValue prevMapAbsPCMcpc'
classVariableNames: 'CounterBytes MaxCounterValue'
poolDictionaries: 'VMSqueakClassIndices'
category: 'VMMaker-JIT'!
!SistaStackToRegisterMappingCogit commentStamp: 'eem 4/7/2014 12:23' prior: 0!
A SistaStackToRegisterMappingCogit is a refinement of StackToRegisterMappingCogit that generates code suitable for dynamic optimization by Sista, the Speculative Inlining Smalltalk Architecture, a project by Clément Bera and Eliot Miranda. Sista is an optimizer that exists in the Smalltalk image, /not/ in the VM, and optimizes by substituting normal bytecoded methods by optimized bytecoded methods that may use special bytecodes for which the Cogit can generate faster code. These bytecodes eliminate overheads such as bounds checks or polymorphic code (indexing Array, ByteArray, String etc). But the bulk of the optimization performed is in inlining blocks and sends for the common path.
The basic scheme is that SistaStackToRegisterMappingCogit generates code containing performance counters. When these counters trip, a callback into the image is performed, at which point Sista analyses some portion of the stack, looking at performance data for the methods on the stack, and optimises based on the stack and performance data. Execution then resumes in the optimized code.
SistaStackToRegisterMappingCogit adds counters to conditional branches. Each branch has an executed and a taken count, implemented at the two 16-bit halves of a single 32-bit word. Each counter pair is initialized with initialCounterValue. On entry to the branch the executed count is decremented and if the count goes below zero the ceMustBeBooleanAdd[True|False] trampoline called. The trampoline distinguishes between true mustBeBoolean and counter trips because in the former the register temporarily holding the counter value will contain zero. Then the condition is tested, and if the branch is taken the taken count is decremented. The two counter values allow an optimizer to collect basic block execution paths and to know what are the "hot" paths through execution that are worth agressively optimizing. Since conditional branches are about 1/6 as frequent as sends, and since they can be used to determine the hot path through code, they are a better choice to count than, for example, method or block entry.
SistaStackToRegisterMappingCogit implements picDataFor:into: that fills an Array with the state of the counters in a method and the state of each linked send in a method. This is used to implement a primitive used by the optimizer to answer the branch and send data for a method as an Array.
Instance Variables
counterIndex: <Integer>
counterMethodCache: <CogMethod>
counters: <Array of AbstractInstruction>
initialCounterValue: <Integer>
numCounters: <Integer>
picData: <Integer Oop>
picDataIndex: <Integer>
prevMapAbsPCMcpc: <Integer>
counterIndex
- xxxxx
counterMethodCache
- xxxxx
counters
- xxxxx
initialCounterValue
- xxxxx
numCounters
- xxxxx
picData
- xxxxx
picDataIndex
- xxxxx
prevMapAbsPCMcpc
- xxxxx
!
Item was added:
+ ----- Method: SistaStackToRegisterMappingCogit>>genExtTrapIfNotInstanceOfBehaviorsBytecode (in category 'bytecode generators') -----
+ genExtTrapIfNotInstanceOfBehaviorsBytecode
+ "SistaV1: * 236 11101100 iiiiiiii Trap If Not Instance Of Behavior/Array Of Behavior #iiiiiiii (+ Extend A * 256, where Extend A >= 0)"
+ | litIndex literal branches label numBranches |
+ <var: #branches type: #'AbstractInstruction **'>
+ self ssStorePop: false toPreferredReg: ReceiverResultReg.
+ litIndex := extA * 256 + byte1.
+ extA := 0.
+ literal := self getLiteral: litIndex.
+ numBranches := (objectMemory isArrayNonImm: literal)
+ ifTrue: [objectMemory numSlotsOf: literal]
+ ifFalse: [1].
+ branches := self alloca: numBranches type: (self cCoerceSimple: CogAbstractInstruction to: #'AbstractInstruction *').
+ (objectMemory isArrayNonImm: literal)
+ ifTrue: [objectRepresentation branchIfInstanceOfBehaviors: literal branches: branches]
+ ifFalse: [objectRepresentation branchIfInstanceOfBehavior: literal branches: branches].
+ "Only flush teh stack if the class trap traps. Use ssFlushNoUpdateTo: so we continue compiling as if
+ the stack had not been fliushed. Control does not return after the ceClassTrapTrampoline call."
+ self ssFlushNoUpdateTo: simStackPtr.
+ self CallRT: ceClassTrapTrampoline.
+ label := self Label.
+ 0 to: numBranches - 1 do:
+ [:i|
+ (branches at: i) jmpTarget: label].
+ ^0!
Item was added:
+ ----- Method: SistaStackToRegisterMappingCogit>>generateSistaRuntime (in category 'initialization') -----
+ generateSistaRuntime
+ "Class trap sends class trap message to context with top of stack, so we on't need any arguments..."
+ ceClassTrapTrampoline := self genTrampolineFor: #ceClassTrap
+ called: 'ceClassTrapTrampoline'!
Item was added:
+ ----- Method: SistaStackToRegisterMappingCogit>>ssFlushNoUpdateTo: (in category 'simulation stack') -----
+ ssFlushNoUpdateTo: index
+ "This version of ssFlushTo: does /not/ update the simulation stack; it merely h=generates the spill code.
+ It is used to spill all valiues to teh stack on a rare failing branch (the class trap) when we don't want to
+ flush the stack on the main path and hence mustn't update the simulation stack if there is no spill."
+ <var: 'copiedEntry' type: #CogSimStackEntry>
+ self assert: needsFrame.
+ methodOrBlockNumTemps to: simSpillBase - 1 do:
+ [:i| self assert: (self simStackAt: i) spilled].
+ simSpillBase <= index ifTrue:
+ [(simSpillBase max: 0) to: index do:
+ [:i| | copiedEntry |
+ copiedEntry := self cCode: [simStack at: index]
+ inSmalltalk: [(simStack at: index) copy].
+ copiedEntry
+ ensureSpilledAt: (self frameOffsetOfTemporary: i)
+ from: FPReg]]!
Item was changed:
----- Method: SpurMemoryManager>>initializeObjectMemory: (in category 'initialization') -----
initializeObjectMemory: bytesToShift
"Initialize object memory variables at startup time. Assume endOfMemory at al are
initialised by the image-reading code via setHeapBase:memoryLimit:endOfMemory:.
endOfMemory is assumed to point to the end of the last object in the image.
Assume: image reader also initializes the following variables:
specialObjectsOop
lastHash"
<inline: false>
| freeListObj |
"Catch mis-initializations leading to bad translations to C"
self assert: BaseHeaderSize = self baseHeaderSize.
self assert: (self maxSlotsForAlloc * BytesPerWord) asInteger > 0.
self bootstrapping ifFalse:
[self
initSegmentBridgeWithBytes: self bridgeSize
at: endOfMemory - self bridgeSize].
segmentManager adjustSegmentSwizzlesBy: bytesToShift.
"image may be at a different address; adjust oops for new location"
self adjustAllOopsBy: bytesToShift.
specialObjectsOop := segmentManager swizzleObj: specialObjectsOop.
"heavily used special objects"
nilObj := self splObj: NilObject.
falseObj := self splObj: FalseObject.
trueObj := self splObj: TrueObject.
"In Cog we insist that nil, true & false are next to each other (Cogit generates tighter
conditional branch code as a result). In addition, Spur places the free lists and
class table root page immediately following them."
self assert: nilObj = oldSpaceStart.
self assert: falseObj = (self objectAfter: nilObj).
self assert: trueObj = (self objectAfter: falseObj).
freeListObj := self objectAfter: trueObj.
self reInitializeClassTablePostLoad: (self objectAfter: freeListObj).
markStack := self swizzleObjStackAt: MarkStackRootIndex.
weaklingStack := self swizzleObjStackAt: WeaklingStackRootIndex.
ephemeronQueue := self swizzleObjStackAt: EphemeronQueueRootIndex.
self assert: self validObjStacks.
self assert: (self isEmptyObjStack: markStack).
self assert: (self isEmptyObjStack: weaklingStack).
self initializeFreeSpacePostLoad: freeListObj.
segmentManager collapseSegmentsPostSwizzle.
self computeFreeSpacePostSwizzle.
+ self initializeOldSpaceFirstFree: freeOldSpaceStart. "initializes endOfMemory, freeStart, free space"
self bootstrapping ifFalse:
[self initializeNewSpaceVariables.
scavenger initializeRememberedSet].
- self initializeOldSpaceFirstFree: freeOldSpaceStart. "initializes endOfMemory, freeStart"
segmentManager checkSegments.
numCompactionPasses := CompactionPassesForGC.
"These defaults should depend on machine size; e.g. too small on a powerful laptop, too big on a Pi."
growHeadroom := 16*1024*1024. "headroom when growing"
shrinkThreshold := 32*1024*1024. "free space before shrinking"
self setHeapSizeAtPreviousGC.
heapGrowthToSizeGCRatio := 0.333333. "By default GC after scavenge if heap has grown by a third since the last GC"!
Item was changed:
----- Method: SpurMemoryManager>>isArrayNonImm: (in category 'object testing') -----
isArrayNonImm: oop
+ <api>
+ "Answer if this is an indexable object with pointer elements, e.g., an array"
- "Answer true if this is an indexable object with pointer elements, e.g., an array"
^ (self formatOf: oop) = self arrayFormat!
Item was changed:
----- Method: StackToRegisterMappingCogit class>>initializeBytecodeTableForSistaV1 (in category 'class initialization') -----
initializeBytecodeTableForSistaV1
"StackToRegisterMappingCogit initializeBytecodeTableForSistaV1"
numPushNilsFunction := #sistaV1:Num:Push:Nils:.
pushNilSizeFunction := #sistaV1PushNilSize:.
self flag:
'Special selector send class must be inlined to agree with the interpreter, which
inlines class. If class is sent to e.g. a general instance of ProtoObject then unless
class is inlined there will be an MNU. It must be that the Cointerpreter and Cogit
have identical semantics. We get away with not hardwiring the other special
selectors either because in the Cointerpreter they are not inlined or because they
are inlined only to instances of classes for which there will always be a method.'.
self generatorTableFrom: #(
"1 byte bytecodes"
"pushes"
(1 0 15 genPushReceiverVariableBytecode needsFrameNever: 1)
(1 16 31 genPushLiteralVariable16CasesBytecode needsFrameNever: 1)
(1 32 63 genPushLiteralConstantBytecode needsFrameNever: 1)
(1 64 75 genPushTemporaryVariableBytecode needsFrameIfMod16GENumArgs: 1)
(1 76 76 genPushReceiverBytecode needsFrameNever: 1)
(1 77 77 genPushConstantTrueBytecode needsFrameNever: 1)
(1 78 78 genPushConstantFalseBytecode needsFrameNever: 1)
(1 79 79 genPushConstantNilBytecode needsFrameNever: 1)
(1 80 80 genPushConstantZeroBytecode needsFrameNever: 1)
(1 81 81 genPushConstantOneBytecode needsFrameNever: 1)
(1 82 82 genExtPushPseudoVariable)
(1 83 83 duplicateTopBytecode needsFrameNever: 1)
(1 84 87 unknownBytecode)
"returns"
(1 88 88 genReturnReceiver return needsFrameIfInBlock: isMappedInBlock 0)
(1 89 89 genReturnTrue return needsFrameIfInBlock: isMappedInBlock 0)
(1 90 90 genReturnFalse return needsFrameIfInBlock: isMappedInBlock 0)
(1 91 91 genReturnNil return needsFrameIfInBlock: isMappedInBlock 0)
(1 92 92 genReturnTopFromMethod return needsFrameIfInBlock: isMappedInBlock -1)
(1 93 93 genReturnNilFromBlock return needsFrameNever: -1)
(1 94 94 genReturnTopFromBlock return needsFrameNever: -1)
(1 95 95 genExtNopBytecode needsFrameNever: 0)
"sends"
(1 96 96 genSpecialSelectorArithmetic isMapped AddRR)
(1 97 97 genSpecialSelectorArithmetic isMapped SubRR)
(1 98 98 genSpecialSelectorComparison isMapped JumpLess)
(1 99 99 genSpecialSelectorComparison isMapped JumpGreater)
(1 100 100 genSpecialSelectorComparison isMapped JumpLessOrEqual)
(1 101 101 genSpecialSelectorComparison isMapped JumpGreaterOrEqual)
(1 102 102 genSpecialSelectorComparison isMapped JumpZero)
(1 103 103 genSpecialSelectorComparison isMapped JumpNonZero)
(1 104 109 genSpecialSelectorSend isMapped) " #* #/ #\\ #@ #bitShift: //"
(1 110 110 genSpecialSelectorArithmetic isMapped AndRR)
(1 111 111 genSpecialSelectorArithmetic isMapped OrRR)
(1 112 117 genSpecialSelectorSend isMapped) "#at: #at:put: #size #next #nextPut: #atEnd"
(1 118 118 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
(1 119 119 genSpecialSelectorClass needsFrameIfStackGreaterThanOne: notMapped 0) "not mapped because it is directly inlined (for now)"
(1 120 127 genSpecialSelectorSend isMapped) "#blockCopy: #value #value: #do: #new #new: #x #y"
(1 128 143 genSendLiteralSelector0ArgsBytecode isMapped)
(1 144 159 genSendLiteralSelector1ArgBytecode isMapped)
(1 160 175 genSendLiteralSelector2ArgsBytecode isMapped)
"jumps"
(1 176 183 genShortUnconditionalJump branch v3:ShortForward:Branch:Distance:)
(1 184 191 genShortJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(1 192 199 genShortJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
"stores"
(1 200 207 genStoreAndPopReceiverVariableBytecode needsFrameNever: -1) "N.B. not frameless if immutability"
(1 208 215 genStoreAndPopTemporaryVariableBytecode)
(1 216 216 genPopStackBytecode needsFrameNever: -1)
(1 217 223 unknownBytecode)
"2 byte bytecodes"
(2 224 224 extABytecode extension)
(2 225 225 extBBytecode extension)
"pushes"
(2 226 226 genExtPushReceiverVariableBytecode needsFrameNever: 1)
(2 227 227 genExtPushLiteralVariableBytecode needsFrameNever: 1)
(2 228 228 genExtPushLiteralBytecode needsFrameNever: 1)
(2 229 229 genLongPushTemporaryVariableBytecode)
(2 230 230 genPushClosureTempsBytecode)
(2 231 231 genPushNewArrayBytecode)
(2 232 232 genExtPushIntegerBytecode needsFrameNever: 1)
(2 233 233 genExtPushCharacterBytecode needsFrameNever: 1)
"returns"
"sends"
(2 234 234 genExtSendBytecode isMapped)
(2 235 235 genExtSendSuperBytecode isMapped)
"sista bytecodes"
(2 236 236 genExtTrapIfNotInstanceOfBehaviorsBytecode isMapped)
"jumps"
(2 237 237 genExtUnconditionalJump branch isMapped "because of interrupt check" v4:Long:Branch:Distance:)
(2 238 238 genExtJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
(2 239 239 genExtJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
"stores"
(2 240 240 genExtStoreAndPopReceiverVariableBytecode)
(2 241 241 genExtStoreAndPopLiteralVariableBytecode)
(2 242 242 genLongStoreAndPopTemporaryVariableBytecode)
(2 243 243 genExtStoreReceiverVariableBytecode)
(2 244 244 genExtStoreLiteralVariableBytecode)
(2 245 245 genLongStoreTemporaryVariableBytecode)
(2 246 247 unknownBytecode)
"3 byte bytecodes"
+ (3 248 248 genCallPrimitiveBytecode)
- (3 248 248 callPrimitiveBytecode)
(3 249 249 unknownBytecode) "reserved for Push Float"
(3 250 250 genExtPushClosureBytecode block v4:Block:Code:Size:)
(3 251 251 genPushRemoteTempLongBytecode)
(3 252 252 genStoreRemoteTempLongBytecode)
(3 253 253 genStoreAndPopRemoteTempLongBytecode)
(3 254 255 unknownBytecode))!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>sistaV1PushNilSize: (in category 'span functions') -----
+ sistaV1PushNilSize: aMethodObj
+ "230 11100110 iiiiiiii PushNClosureTemps iiiiiiii"
+ <inline: true>
+ ^2!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>squeakV3orSistaV1PushNilSize: (in category 'span functions') -----
+ squeakV3orSistaV1PushNilSize: aMethodObj
+ ^(coInterpreter methodUsesAlternateBytecodeSet: aMethodObj)
+ ifTrue: [self sistaV1PushNilSize: aMethodObj]
+ ifFalse: [self v3PushNilSize: aMethodObj]!
Item was added:
+ ----- Method: VMClass>>alloca:type: (in category 'C library extensions') -----
+ alloca: numElements type: elementType
+ <cmacro: '(numElements, elementType) alloca((numElements)*sizeof(elementType))'>
+ ^CArrayAccessor on: ((1 to: numElements) collect: [:ign| elementType new])!
Hi Vincent,
On Wed, Jul 30, 2014 at 6:09 AM, Blondeau Vincent <
vincent.blondeau(a)worldline.com> wrote:
>
>
>
>
> *De :* Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org] *De la part
> de* Eliot Miranda
> *Envoyé :* mercredi 30 juillet 2014 16:51
> *À :* Pharo Development List
> *Cc :* Squeak Virtual Machine Development Discussion
>
> *Objet :* Re: [Pharo-dev] Headless mode loss of focus under windows 7
>
>
>
> Hi Vincent,
>
> Hi,
>
>
> On Jul 29, 2014, at 11:54 PM, Blondeau Vincent <
> vincent.blondeau(a)worldline.com> wrote:
>
> Hi Eliot,
>
>
>
> I tried with the latest vm from your website (
> http://www.mirandabanda.org/files/Cog/VM/VM.r3056/cogwin-14.29.3056.zip
> -> SqueakConsole.exe). But unfortunately the problem is still there…
>
>
>
> I'm sorry for having wasted your time!
>
> Don’t worry. It takes me only 10 minutes :)
>
>
>
> There must be some code that gets run during startup that shouldn't be
> when the VM is running headless. Tracking it down could be done by running
> a debug VM under gdb in a console window. I guess the console in which gdb
> is running will lose focus at the same point. I don't have time to do this
> right now, but I'll try soon. How motivated are you to fix this?
>
> For now it’s not a top priority but sooner or later I will have the need
> to run the script again…
>
> I will try to do it this week or next week.
>
> Do I need to take a specific VM compiled with –g ?
>
Yes. You need an unstripped VM to get symbols. You can use an unstripped
VM but you tell gdb to read symbols from the unstripped VM:
U:\ gdb bin/Squeak.exe
...
(no debugging symbols found)
(gdb) file SqueakUnstripped.exe
(gdb) run trunk.image
But alas I don't include the unstripped VMs on my web site. I probably
should. But for now that means building your own VM. That's non-trivial
because you have to install cygwin. See
http://www.squeakvm.org/svn/squeak/branches/Cog/build.win32x86/HowToBuild
which I've attached. I'll let you know if I get to the task sooner.
>
>
> Vincent
>
>
>
> *De :* Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org
> <pharo-dev-bounces(a)lists.pharo.org>] *De la part de* Eliot Miranda
> *Envoyé :* mardi 29 juillet 2014 21:08
> *À :* Pharo Development List
> *Objet :* Re: [Pharo-dev] Headless mode loss of focus under windows 7
>
>
>
> Hi Vincent,
>
>
>
> use one if the console VMs from my website. They don't open up
> another window. Open up a recent cogwin zip and use SqueakConsole.exe
>
> Eliot (phone)
>
>
> On Jul 29, 2014, at 4:01 AM, Blondeau Vincent <
> vincent.blondeau(a)worldline.com> wrote:
>
> Hello everyone,
>
>
>
> Currently I use a batch script where a moose image (based on pharo) load a
> model, export some data and close itself without saving and that several
> times.
>
>
>
> I do it under windows 7 by this kind of loop in a .bat file:
>
> FOR /L %%i IN (1,1,10) DO (
>
> "Pharo.exe --headless sdco-sa-tooling-ci-5.image eval
> ‘<tasks>'
>
> )
>
>
>
> The problem is that at each execution of pharo, I lose focus from the
> window where I was currently working (a notepad by example).
>
> How can I do to solve it?
>
>
>
> Thanks in advance!
>
>
>
> Cheers,
>
>
>
> Vincent BLONDEAU
>
>
>
>
>
>
> ------------------------------
>
>
> Ce message et les pièces jointes sont confidentiels et réservés à l'usage
> exclusif de ses destinataires. Il peut également être protégé par le secret
> professionnel. Si vous recevez ce message par erreur, merci d'en avertir
> immédiatement l'expéditeur et de le détruire. L'intégrité du message ne
> pouvant être assurée sur Internet, la responsabilité de Worldline ne pourra
> être recherchée quant au contenu de ce message. Bien que les meilleurs
> efforts soient faits pour maintenir cette transmission exempte de tout
> virus, l'expéditeur ne donne aucune garantie à cet égard et sa
> responsabilité ne saurait être recherchée pour tout dommage résultant d'un
> virus transmis.
>
> This e-mail and the documents attached are confidential and intended
> solely for the addressee; it may also be privileged. If you receive this
> e-mail in error, please notify the sender immediately and destroy it. As
> its integrity cannot be secured on the Internet, the Worldline liability
> cannot be triggered for the message content. Although the sender endeavours
> to maintain a computer virus-free network, the sender does not warrant that
> this transmission is virus-free and will not be liable for any damages
> resulting from any virus transmitted.
>
> ------------------------------
>
> Ce message et les pièces jointes sont confidentiels et réservés à l'usage
> exclusif de ses destinataires. Il peut également être protégé par le secret
> professionnel. Si vous recevez ce message par erreur, merci d'en avertir
> immédiatement l'expéditeur et de le détruire. L'intégrité du message ne
> pouvant être assurée sur Internet, la responsabilité de Worldline ne pourra
> être recherchée quant au contenu de ce message. Bien que les meilleurs
> efforts soient faits pour maintenir cette transmission exempte de tout
> virus, l'expéditeur ne donne aucune garantie à cet égard et sa
> responsabilité ne saurait être recherchée pour tout dommage résultant d'un
> virus transmis.
>
> This e-mail and the documents attached are confidential and intended
> solely for the addressee; it may also be privileged. If you receive this
> e-mail in error, please notify the sender immediately and destroy it. As
> its integrity cannot be secured on the Internet, the Worldline liability
> cannot be triggered for the message content. Although the sender endeavours
> to maintain a computer virus-free network, the sender does not warrant that
> this transmission is virus-free and will not be liable for any damages
> resulting from any virus transmitted.
>
--
Aloha,
Eliot
Hi Vincent,
On Jul 29, 2014, at 11:54 PM, Blondeau Vincent <vincent.blondeau(a)worldline.com> wrote:
> Hi Eliot,
>
> I tried with the latest vm from your website (http://www.mirandabanda.org/files/Cog/VM/VM.r3056/cogwin-14.29.3056.zip -> SqueakConsole.exe). But unfortunately the problem is still there…
I'm sorry for having wasted your time! There must be some code that gets run during startup that shouldn't be when the VM is running headless. Tracking it down could be done by running a debug VM under gdb in a console window. I guess the console in which gdb is running will lose focus at the same point. I don't have time to do this right now, but I'll try soon. How motivated are you to fix this?
>
> Vincent
>
> De : Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org] De la part de Eliot Miranda
> Envoyé : mardi 29 juillet 2014 21:08
> À : Pharo Development List
> Objet : Re: [Pharo-dev] Headless mode loss of focus under windows 7
>
> Hi Vincent,
>
> use one if the console VMs from my website. They don't open up another window. Open up a recent cogwin zip and use SqueakConsole.exe
>
> Eliot (phone)
>
> On Jul 29, 2014, at 4:01 AM, Blondeau Vincent <vincent.blondeau(a)worldline.com> wrote:
>
> Hello everyone,
>
> Currently I use a batch script where a moose image (based on pharo) load a model, export some data and close itself without saving and that several times.
>
> I do it under windows 7 by this kind of loop in a .bat file:
> FOR /L %%i IN (1,1,10) DO (
> "Pharo.exe --headless sdco-sa-tooling-ci-5.image eval ‘<tasks>'
> )
>
> The problem is that at each execution of pharo, I lose focus from the window where I was currently working (a notepad by example).
> How can I do to solve it?
>
> Thanks in advance!
>
> Cheers,
>
> Vincent BLONDEAU
>
>
>
>
> Ce message et les pièces jointes sont confidentiels et réservés à l'usage exclusif de ses destinataires. Il peut également être protégé par le secret professionnel. Si vous recevez ce message par erreur, merci d'en avertir immédiatement l'expéditeur et de le détruire. L'intégrité du message ne pouvant être assurée sur Internet, la responsabilité de Worldline ne pourra être recherchée quant au contenu de ce message. Bien que les meilleurs efforts soient faits pour maintenir cette transmission exempte de tout virus, l'expéditeur ne donne aucune garantie à cet égard et sa responsabilité ne saurait être recherchée pour tout dommage résultant d'un virus transmis.
>
> This e-mail and the documents attached are confidential and intended solely for the addressee; it may also be privileged. If you receive this e-mail in error, please notify the sender immediately and destroy it. As its integrity cannot be secured on the Internet, the Worldline liability cannot be triggered for the message content. Although the sender endeavours to maintain a computer virus-free network, the sender does not warrant that this transmission is virus-free and will not be liable for any damages resulting from any virus transmitted.