Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Spur, a new object representation for Cog


Published on

Title: Spur, a new object representation for Cog
Speaker: Elliot Miranda
Wed, August 20, 9am – 10am

Part 1:
Part 2:
Part 3:

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.

Published in: Software
  • Video:
    Part 1:
    Part 2:
    Part 3:
    Are you sure you want to  Yes  No
    Your message goes here

Spur, a new object representation for Cog

  1. 1. Spur Confused images and mixed metaphors for Squeak Pharo and Newspeak Wednesday, 20 August 2014
  2. 2. Three Parts VM Evolution Lazy Forwarding/ Partial Read Barrier Spur Memory Manager Wednesday, 20 August 2014
  3. 3. Spur isA: MemoryManager new faster more powerful 64-bit ready Wednesday, 20 August 2014
  4. 4. Spur isAn: Evolution Sista 64-bit HPS 7 Spur HPS 5 HPS BrouHaHa-TC BrouHaHa Cog v1 PS Squeak Dorado Berkeley Stack Smalltalk/V Cog v2 Wednesday, 20 August 2014
  5. 5. inherited traits class table 64-bit HPS 7 Spur HPS 5 HPS ephemerons 64-bits BrouHaHa-TC BrouHaHa Cog v1 SSlaimnugl abtroort haenrds icna-clihnee JIT PS Squeak V1 oibnjdeircet cttaiobnle Dorado Berkeley Stack Smalltalk/V contexts stack-to-register mapping JIT direct pointers context-to-stack mapping mceatchhoed Cog v2 weakness object-oriented Wednesday, 20 August 2014
  6. 6. object-oriented?? Object Memory NewObject Memory Stack Interpreter CoInterpreter SpurMemory Manager Spur32Bit MemMgr SpurGeneration Scavenger SpurSegment Manager Cogit VMStruct Type SimpleStack BasedCogit StackToRegister MappingCogit Spur64Bit MemMgr CogObject Representation CogObjRepFor SqueakV3 CogObjRepFor Spur CogObjRepFor 32BitSpur CogObjRepFor 64BitSpur teleology Wednesday, 20 August 2014
  7. 7. oops BS Direct Pointers size...flags...hash class inst vars ... refcount HPS Object Table Indirection size...flags...hash class indirection inst vars ... D-machine OTE 20-bit address size class inst vars ... Wednesday, 20 August 2014
  8. 8. oops! yeah, right... size...flags...hash class indirection inst vars ... size...flags...inst size...hash...class index indirection inst vars ... 64-bit HPS 7 sparse class table Wednesday, 20 August 2014
  9. 9. class indices/class tags class index is index of class in class table class’s identity hash is its index in class table ∴ its instances’ class tag Behavior>>identityHash (& Behavior>>new) use them in method caches; resolve to class object on #class or full method lookup constants, never moved by GC cheap allocation of well-known objects puns & special non-objects #slots identityHash fmt class index Wednesday, 20 August 2014
  10. 10. evolution top-down selection pressure (≈tests) bottom-up refinement (≈≈ pink plane) exaptation (≈ blue plane) Wednesday, 20 August 2014
  11. 11. Aquatic Ape Hypothesis Wednesday, 20 August 2014
  12. 12. The VM System heap lcoaockhuep prims irnetteerrp gc & alloc Wednesday, 20 August 2014
  13. 13. The VM System heap lcoaockhuep zcoodnee sztoancek prims irnetteerrp jit gc & alloc Wednesday, 20 August 2014
  14. 14. method lookup findNewMethod ! "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
  15. 15. Exapt method cache probe class tags stack zone primitives Wednesday, 20 August 2014
  16. 16. 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 barrier Wednesday, 20 August 2014
  17. 17. become size flags hash class index inst var 0 inst var 1 ..... size flags hash class index inst var 0 inst var 1 ..... Wednesday, 20 August 2014
  18. 18. become size flags forwarded index forwarding ptr copy copy size flags hash class index inst var 0 inst var 1 ..... size flags forwarded index forwarding ptr size flags hash class index inst var 0 inst var 1 ..... Wednesday, 20 August 2014
  19. 19. follow followForwarded: 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
  20. 20. lazy forwarding issues inst var access (& method access in interpreter) message sends class hierarchy method lookup global var access (including super sends) primitives Wednesday, 20 August 2014
  21. 21. lazy forwarding: inst vars partial read barrier size flags forwarded index forwarding ptr copy copy size flags hash class index inst var 0 inst var 1 ..... size flags forwarded index forwarding ptr size flags hash class index inst var 0 inst var 1 ..... + if became pointer or method object, scan stack zone to follow forwarding pointers Wednesday, 20 August 2014
  22. 22. lazy forwarding: sends findNewMethod ! (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
  23. 23. lazy forwarding: class hierarchy method lookup after any pointer become could scan every class in class table every method on entry to stack zone KISS read 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
  24. 24. lazy forwarding: global variable access after any pointer or method become could scan every method in stack & code zones every method on entry to stack zone KISS read 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
  25. 25. lazy forwarding: primitives bits width height depth offset mask x y bits width height depth offset self validate ifTrue: [self operate] ifFalse: [self fail] x y Wednesday, 20 August 2014
  26. 26. primitives self 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
  27. 27. Spur Memory Manager Spur Memory Manager Spur Generation Scavenger Spur Segment Manager ephemerons object representation & heap walking pig compaction pinning, bridges and segments debugging Wednesday, 20 August 2014
  28. 28. 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
  29. 29. object size/heap walk 8 22 5 22 <= 254 identityHash fmt class index at least one slot 255 slot count 255 identityHash fmt class index Wednesday, 20 August 2014
  30. 30. pig compaction if you have a hammer... Wednesday, 20 August 2014
  31. 31. another two finger at least one slot => use the xor trick free space free space free space Wednesday, 20 August 2014
  32. 32. pins, segments and bridges 255 span 255 1 bits bridge first segment isPinned Wednesday, 20 August 2014
  33. 33. achieving inner peace A garbage collector is a destructive graph rewriter when it goes wrong... Wednesday, 20 August 2014
  34. 34. kill more lemmings Wednesday, 20 August 2014
  35. 35. status -35% = 1/(1-0.35) performance functionality availability 64-bits = 1/0.65 = 1.54x -40% = 1/0.6 = 1.6 . -50% = 2x (new-old)/old Wednesday, 20 August 2014