spur, a new object representation for cog
DESCRIPTION
Title: Spur, a new object representation for Cog Speaker: Elliot Miranda Wed, August 20, 9am – 10am Video: Part 1: https://www.youtube.com/watch?v=k0nBNS1aHZ4 Part 2: https://www.youtube.com/watch?v=sn3irBZE7g4 Part 3: https://www.youtube.com/watch?v=1Vg0iFeg_pA Abstract: Spur is a new object representation and memory manager for the Cog VM. The object representation includes immediate characters and its simplicity allows Cog's JIT to implement many more operations, resulting in a faster VM. The object representation is designed to share the object header and the majority of the memory management code between 32-bit and 64-bit versions. Spur has two features new to Squeak/Pharo, the ability to grow and shrink memory via segments, and the ability to pin objects in memory. Spur has one altogether novel feature, a partial read barrier, which takes advantage of Smalltalk's message sending to provide lazy forwarding, which allows the system to implement become efficiently while retaining the speed advantages of direct pointers. This talk will explain these features with minimal manifestation of machine code on the slides and, for this author, plenty of pleasing pictures. Bio: Eliot Miranda is a long-time Smalltalk systems programmer and virtual machine architect. He started his technical life developing holographic optics for bubble chamber physics, in so doing discovering a love of computing. His early work, started while a student at York University, produced the BrouHaHa series of virtual machines. These were Smalltalk-80 interpreters and threaded code JITs, written in C. While at Queen Mary College in the University of London he was involved in applying these implementations to prototyping what-you-see-is-what-i-see interfaces for IBM and to implementing the bulk of the software for the Active Book, a very early ARM-based tablet computer. He was virtual machine lead and then technical lead for VisualWorks for a decade at ParcPlace and its successors, before joining Cadence where he helped adapt Squeak to implement Newspeak. He then joined Qwaq, the company applying Croquet to business communications, where he implemented Cog. He is now back at Cadence in a team applying Cog and Newspeak to SoC design support. He is currently enjoying collaborating with a number of people on Cog-related projects, not least of which is an adaptive optimization system for Pharo/Squeak called Sista. 2)TRANSCRIPT
SpurConfused images and mixed metaphors for Squeak Pharo and Newspeak
Wednesday, 20 August 2014
Three Parts
VM Evolution
Lazy Forwarding/Partial Read Barrier
Spur Memory ManagerWednesday, 20 August 2014
Spur isA: MemoryManager new
faster
more powerful
64-bit ready
Wednesday, 20 August 2014
Spur isAn: Evolution
Dorado Berkeley
SqueakPS
HPS
BrouHaHa
HPS 5
Stack
Cog v1
Spur64-bit HPS 7
Smalltalk/V
BrouHaHa-TC
Cog v2
Sista
Wednesday, 20 August 2014
inherited traits
Dorado Berkeley
Squeak V1PS
HPS
BrouHaHa
HPS 5
Stack
Cog v1
Spur64-bit HPS 7
Smalltalk/V
BrouHaHa-TC
contexts
ephemerons
stack-to-registermapping JIT
direct pointers
class table
Simulator andSlang brothers
context-to-stack mapping
methodcache
object tableindirection
in-linecache JIT
Cog v2
weakness object-oriented
64-bits
Wednesday, 20 August 2014
object-oriented?? ObjectMemory
NewObjectMemory
StackInterpreter
CoInterpreter SpurMemoryManager
Spur32BitMemMgr
SpurGenerationScavenger
SpurSegmentManager
Cogit
SimpleStackBasedCogit
StackToRegisterMappingCogit
Spur64BitMemMgr
CogObjectRepresentation
CogObjRepForSqueakV3
CogObjRepForSpur
CogObjRepFor32BitSpur
CogObjRepFor64BitSpur
VMStructType
teleology
Wednesday, 20 August 2014
oops
size...flags...hashclass
inst vars...
BS Direct Pointers
inst vars
size...flags...hashclass
indirection
HPS Object Table Indirection
inst vars...
D-machine OTE
20-bit addressrefcount size
classinst vars
...
Wednesday, 20 August 2014
oops!yeah, right...
size...flags...hashclass
indirectioninst vars
...
size...flags...inst size...hash...class indexindirectioninst vars
...
64-bit HPS 7sparseclasstable
Wednesday, 20 August 2014
class indices/class tags
class index is index of class in class tableclass’s identity hash is its index in class table∴ its instances’ class tagBehavior>>identityHash (& Behavior>>new)use them in method caches; resolve to class object on #class or full method lookupconstants, never moved by GCcheap allocation of well-known objectspuns & special non-objects
#slots identityHash fmt class index
Wednesday, 20 August 2014
evolution
top-down selection pressure(≈tests)
bottom-up refinement(≈≈ pink plane)exaptation(≈ blue plane)
Wednesday, 20 August 2014
Aquatic Ape HypothesisWednesday, 20 August 2014
The VM System
heap
lookupcache interp
reter prims gc & alloc
Wednesday, 20 August 2014
The VM System
heap
lookupcache code
zone stackzone
interp reter jit prims gc &
alloc
Wednesday, 20 August 2014
method lookupfindNewMethod! "Find the compiled method to be run when the current
messageSelector is sent to the class lkupClass, setting the values of newMethod and primitiveIndex."
! <inline: true>! | ok | ! ok := self lookupInMethodCacheSel: messageSelector class: lkupClass.! ok ifFalse: "entry was not found in the cache; look it up the hard way"! ! [self lookupMethodInClass: lkupClass.! ! self addNewMethodToCache]
Wednesday, 20 August 2014
Exapt
method cache probe
class tags
stack zone
primitivesWednesday, 20 August 2014
Exaptation
become lazy
all objects can be forwarders
forwarded class tag fails method cache probe
follow on message lookup
stack zone scan avoids inst var access read barrierWednesday, 20 August 2014
becomesize flags hash class index
inst var 0 inst var 1.....
size flags hash class indexinst var 0 inst var 1
.....
Wednesday, 20 August 2014
become size flags forwarded indexforwarding ptr
size flags hash class indexinst var 0 inst var 1
.....
size flags hash class indexinst var 0 inst var 1
.....
size flags forwarded indexforwarding ptr
copy copy
Wednesday, 20 August 2014
followfollowForwarded: objOop! | referent |! referent := self fetchPointer: 0 ofMaybeForwardedObject: objOop.! [(self isOopForwarded: referent)] whileTrue:! ! [referent := self fetchPointer: 0 ofMaybeForwardedObject: referent].! ^referent
followField: fieldIndex ofObject: anObject! | objOop |! objOop := self fetchPointer: fieldIndex ofObject: anObject.! (self isOopForwarded: objOop) ifTrue:! ! [objOop := self followForwarded: objOop.
self storePointer: fieldIndex ofObject: anObject withValue: objOop].! ^objOop
ObjectMemory>>followField: fieldIndex ofObject: anObject! ^self fetchPointer: fieldIndex ofObject: anObject
Wednesday, 20 August 2014
lazy forwarding issues
inst var access(& method access in interpreter)message sendsclass hierarchy method lookupglobal var access (including super sends)primitives
Wednesday, 20 August 2014
lazy forwarding: inst varspartial read barrier
size flags forwarded indexforwarding ptr
size flags hash class indexinst var 0 inst var 1
.....
size flags hash class indexinst var 0 inst var 1
.....
size flags forwarded indexforwarding ptr
copy copy
+ if became pointer or method object,scan stack zone to follow forwarding pointers
Wednesday, 20 August 2014
lazy forwarding: sendsfindNewMethod! (self lookupInMethodCacheSel: selector classTag: lkupClassTag) ifFalse:! ! [((heap isOopForwarded: selector)! ! or: [heap isForwardedClassTag: lkupClassTag]) ifTrue:! ! ! [(heap isOopForwarded: selector) ifTrue:! ! ! ! [selector := self handleForwardedSelectorFault: selector].! ! ! (heap isForwardedClassTag: lkupClassTag) ifTrue:! ! ! ! [lkupClassTag := self handleForwardedTagFault: lkupClassTag].! ! ! (self lookupInMethodCacheSel: selector classTag: lkupClassTag)! ! ! ! ifTrue: [^self]].! ! lkupClass := heap classForClassTag: lkupClassTag.! ! self lookupMethodInClass: lkupClass.! ! self addNewMethodToCache: lkupClass]
Wednesday, 20 August 2014
lazy forwarding:class hierarchy method lookup
after any pointer become could scanevery class in class tableevery method on entry to stack zoneKISSread barrier on access
superclassOf: classObj! "Read barrier here costs very little because lookup is rare,
& class and superclass almost certainly share a cache line." ^objectMemory followField: SuperclassIndex ofObject: classObj
Wednesday, 20 August 2014
lazy forwarding:global variable accessafter any pointer or method become could scanevery method in stack & code zonesevery method on entry to stack zoneKISSread barrier on access
pushLiteralVariable: literalIndex! | litVar |! litVar := self literal: literalIndex.! (heap isForwarded: litVar) ifTrue:! ! [litVar := heap followForwarded: litVar].! self push: (heap fetchPointer: ValueIndex ofObject: litVar)
Wednesday, 20 August 2014
lazy forwarding: primitivesbits
widthheight
offsetmask
depth
bitswidthheight
offsetdepth
xy
xy
self validateifTrue: [self operate]ifFalse: [self fail]
Wednesday, 20 August 2014
primitivesself validate
ifTrue: [self operate]ifFalse: [self fail]slowPrimitiveResponse
! primFailCode := 0.! self perform: primitiveFunctionPointer.! self successful ifFalse:! [self checkForAndFollowForwardedPrimitiveState ifTrue:! ! [primFailCode := 0.! ! self perform: primitiveFunctionPointer]]
checkForAndFollowForwardedPrimitiveState| depth |
! depth := primitiveAccessorDepths at:(self primitveIndexOf: newMethod).
^accessorDepth >= 0 and: [self followStackedArgumentsToDepth: accessorDepth]
Wednesday, 20 August 2014
Spur Memory Manager
ephemeronsobject representation & heap walkingpig compactionpinning, bridges and segmentsdebugging
SpurMemoryManager
SpurGenerationScavenger
SpurSegmentManager
Wednesday, 20 August 2014
ephemerons
processEphemerons! "There are ephemerons to be scavenged. Scavenge them and fire any whose keys are! still in pastSpace and/or eden. The unscavenged ephemerons in this cycle can only be! fired if all the unscavenged ephemerons in this cycle are firable, because references! to ephemeron keys from unfired ephemerons should prevent the ephemerons with! those keys from firing. So scavenge ephemerons with surviving keys, and only if none! are found, fire ephemerons with unreferenced keys, and scavenge them. Read the! class comment for a more in-depth description of the algorithm."
! | unfiredEphemeronsScavenged |! unfiredEphemeronsScavenged := self scavengeUnfiredEphemeronsInRememberedSet.! self scavengeUnfiredEphemeronsOnEphemeronList ifTrue:! ! [unfiredEphemeronsScavenged := true].! unfiredEphemeronsScavenged ifFalse:! ! [self fireEphemeronsInRememberedSet.! ! self fireEphemeronsOnEphemeronList]
Wednesday, 20 August 2014
object size/heap walk
<= 254 identityHash fmt class indexat least one slot
255 identityHash fmt class index 255 slot count
8 22 5 22
Wednesday, 20 August 2014
pig compaction
if you have a hammer...
Wednesday, 20 August 2014
another two fingerat least one slot
=> use the xor trick
freespace
freespace
freespace
Wednesday, 20 August 2014
pins, segments and bridges
255 1 bits bridge 255 span
first segment
isPinned
Wednesday, 20 August 2014
achieving inner peaceA garbage collector is a destructive graph rewriter
when it goes wrong...
Wednesday, 20 August 2014
kill more lemmings
Wednesday, 20 August 2014
performance
functionality
availabilitywww.mirandabanda.org
64-bits
status-35% = 1/(1-0.35)= 1/0.65 = 1.54x
-50% = 2x
-40% = 1/0.6 = 1.6.
(new-old)/old
Wednesday, 20 August 2014