{"id":149,"date":"2013-09-13T11:51:53","date_gmt":"2013-09-13T19:51:53","guid":{"rendered":"http:\/\/www.mirandabanda.org\/cogblog\/?p=149"},"modified":"2013-09-13T12:29:59","modified_gmt":"2013-09-13T20:29:59","slug":"lazy-become-and-a-partial-read-barrier","status":"publish","type":"post","link":"http:\/\/www.mirandabanda.org\/cogblog\/2013\/09\/13\/lazy-become-and-a-partial-read-barrier\/","title":{"rendered":"Lazy Become and a Partial Read Barrier for Spur"},"content":{"rendered":"<h2>Lazy Become and a Partial Read Barrier for <a href=\"http:\/\/www.mirandabanda.org\/cogblog\/2013\/09\/05\/a-spur-gear-for-cog\/\">Spur<\/a><\/h2>\n<p>One of the stated design goals for Spur is to support pinned objects via lazy become. \u00c2\u00a0This is one of the<a href=\"http:\/\/www.codinghorror.com\/blog\/2005\/04\/rube-goldberg-software-devices.html\"> less well-thought-out<\/a> parts of the design. \u00c2\u00a0If I can make lazy become work it&#8217;ll be (as I hope to convince you in this article) a significant improvement over the current Squeak VM&#8217;s become implementation. \u00c2\u00a0But it must work, and to that end I thought I&#8217;d write a post describing my current design of the scheme, and allow y&#8217;all to criticise it, either shooting it down in flames, saving me the effort of <a href=\"http:\/\/blogs.artinfo.com\/cuttingroom\/2012\/12\/06\/will-johnny-depps-don-quixote-leave-terry-gilliam-tilting-at-windmills\/\">tilting at windmills<\/a>, \u00c2\u00a0or helping fill in the blanks and offer \u00c2\u00a0improvements to help the scheme&#8217;s success. So let&#8217;s have a tilt at describing become:.<\/p>\n<h3>How becoming<\/h3>\n<p>Become is Smalltalk-speak for an operation that changes all references to one object into references to another. \u00c2\u00a0There are two becomes. two-way, where two objects exchange identities, and one-way where references to a first object are replaced by references to a second object, and the first object becomes inaccessible, to be swept away by the garbage collector. \u00c2\u00a0This operation has traditionally been used to grow collections in Smalltalk, and to update live instances when a class definition changes, adding or removing variables. \u00c2\u00a0It can also be used to replace a movable copy of an object with a non-movable copy in some more suitable space, for example effectively morphing a movable object in new space with an immobile one in old space. \u00c2\u00a0Being able to pin objects down is invaluable in a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Foreign_function_interface\">Foreign Function Interface<\/a> (FFI) where one wants to pass storage to other components.<\/p>\n<p>The traditional implementation of <a href=\"http:\/\/www.mirandabanda.org\/bluebook\/bluebook_chapter30.html#TheObjectTable30\">become in the earliest Smalltalk-80 implementations<\/a> was based around a two-part object representation. \u00c2\u00a0The system had a table of object headers, all of the same size, and each header contained some information used by the garbage collector (contents contain pointers or not, etc)\u00c2\u00a0<em>and<\/em> a pointer to the body of the object, the body containing the object&#8217;s class, its size, and its fields. \u00c2\u00a0The two-way become operation is simple with this representation; simply swap the pointers to the object bodies, plus whatever other header bits are relevant. \u00c2\u00a0Here there is effectively a read barrier on every class and instance variable access, through the pointer, so-called &#8220;object table indirection&#8221;. \u00c2\u00a0The <a href=\"http:\/\/en.wikipedia.org\/wiki\/VisualWorks\">VisualWorks<\/a> memory manager still uses this scheme, updated to work with a generational collector.<\/p>\n<p>Subsequently, Digitalk&#8217;s Smalltalk\/V used a flat object representation without object table indirection, and hence provided a one-way become which scanned through memory, replacing any reference to the first object with a reference to the second.<\/p>\n<p>The existing Squeak\/Cog garbage collector has a flat object representation, and supports both two-way and one-way bulk becomes. \u00c2\u00a0The input to the become primitive is two arrays of objects, and the become is pair-wise, performing either a two-way or a one-way become on each pair of objects in the two arrays. \u00c2\u00a0This is implemented above the VM&#8217;s compaction system which stops the world, allocates some forwarding blocks, replaces the headers of objects to move or become, with pointers to their forwarding blocks, which contain their final position after become or compaction, scans memory following object references through forwarding blocks updating pointers, and then, if compacting, moving objects, finally discarding the forwarding blocks.<\/p>\n<p>All approaches support grow, and instance migration (although IIRC Smalltalk\/V didn&#8217;t migrate instances on class redefinition), but while the cost of the object indirection version is O(1), with hidden costs in object table indirection, the flat implementation is O(n) in the size of the heap, and in the age of 64-bit machines that&#8217;s a problem.<\/p>\n<p>An alternative implementation, oft-used in Lisp systems, is to add a read barrier to all object access, and mark objects as forwarders. \u00c2\u00a0This can be used to implement <a href=\"http:\/\/citeseerx.ist.psu.edu\/viewdoc\/summary?doi=10.1.1.52.8857\">lazy copying garbage collection<\/a> where objects are copied from one semi-space to another in parallel to the main program (the &#8220;mutator&#8221;). \u00c2\u00a0To become, or move an object one replaces the object&#8217;s header or first field with a <em>forwarding\u00c2\u00a0<\/em>pointer to the desired target or copy in a new location, marking the &#8220;corpse&#8221; as forwarded. \u00c2\u00a0The program checks the forwarded flag on each access. \u00c2\u00a0If there is hardware support, as in a Lisp machine, this can work well. \u00c2\u00a0But without hardware support, and like the object table representation, it has costs, slowing down program execution due to the scattering of forwarding checks and forwarding pointer follows throughout program execution.<\/p>\n<h3>The Spur Conjecture<\/h3>\n<p>Smalltalk provides strict object encapsulation; the only way to access the state of an object is to send it a message. \u00c2\u00a0OK, <a href=\"https:\/\/www.youtube.com\/watch?v=lSieUhqIR6k\">bald-faced lies<\/a> are very popular these days, but with Smalltalk there&#8217;s more than a grain of truth here. \u00c2\u00a0The only violations of this principle are though certain primitives. \u00c2\u00a0The add primitives, for example, be it on SmallIntegers (fixnums) or Large integers (bignums) access the state of both the receiver and the argument in computing the result. \u00c2\u00a0One might think that instVarAt: and instVarAt:put:, which can access the instance variables of any object from the outside, violate encapsulation, but one still has to send the message to the object one is accessing. \u00c2\u00a0<a href=\"http:\/\/bracha.org\/mirrors.pdf\">Mirror primitives<\/a>, however, do violate encapsulation, allowing one to reach inside an object without sending a message to it, passing the object to be accessed as an argument to the mirror primitive. \u00c2\u00a0The up side is that mirrors provide security, they are capabilities that only certain parts of a system are trusted with; instVarAt: and instVarAt:put: declare open season on internals and are thankfully used with discretion in Smalltalk systems.<\/p>\n<p>Given strict encapsulation it seems to me that we can rely on message sending to follow forwarding pointers. \u00c2\u00a0(almost) Every message send in Smalltalk involves some form of check of the class of the receiver. \u00c2\u00a0In the abstract, a message is activated by fetching a receiver object&#8217;s class, and searching the method dictionaries in the class&#8217;s hierarchy until a matching method is found. \u00c2\u00a0In practice, the process is optimized using <a href=\"http:\/\/www.mirandabanda.org\/cogblog\/2011\/03\/01\/build-me-a-jit-as-fast-as-you-can\/\">method lookup caches<\/a>. \u00c2\u00a0Every send involves fetching either the object&#8217;s class, or a unique class identifier (e.g. an index into a class table) from the object and comparing it against a possibly matching tag in a cache. \u00c2\u00a0If they match, the right method is in the cache. \u00c2\u00a0If they don&#8217;t match a full lookup is needed. \u00c2\u00a0By arranging that forwarding objects have their class tags changed, the message send cache probe becomes a forwarding object trap. \u00c2\u00a0Whenever a message is sent to a forwarding object the cache probe will fail and the failure path can follow the forwarding pointer.<\/p>\n<p>The scheme then implements pinning and become using forwarding pointers. \u00c2\u00a0The old space collector will not move pinned objects, and to avoid pinned objects filling up new space, an unpinned young object is pinned by allocating a pinned copy in old space and marking the young object as a forwarding object pointing to the copy. \u00c2\u00a0Two-way become is implemented by either swapping contents if the two objects have the same size, or allocating two copies, and forwarding the originals to the exchanged copies. \u00c2\u00a0One-way become is implemented by marking the first object as forwarded, pointing to the second object. \u00c2\u00a0This seems great in principle, but there are a number of pitfalls, not just the primitive argument one mentioned above.<\/p>\n<p>My Spur conjecture is that using a message send trap is an effective approach because the pitfalls are limited and manageable. \u00c2\u00a0So what are the pitfalls?<\/p>\n<p>&nbsp;<\/p>\n<h3>Falling With Style<\/h3>\n<p>&nbsp;<\/p>\n<p>The first pitfall is that Smalltalk accesses two other objects far more than the receiver, which are the current method and the active context. \u00c2\u00a0Smalltalk-80&#8217;s execution model executes bytecodes and references literals stored in the current CompiledMethod object. \u00c2\u00a0In most good Smalltalk implementations, methods are compiled on-the-fly to machine code and the machine code is executed. \u00c2\u00a0In fact, Cog is a hybrid interpreter+JIT, interpreting essentially only at start-up. \u00c2\u00a0So the becoming of methods is really only an issue in \u00c2\u00a0the interpreter. \u00c2\u00a0Smalltalk-80&#8217;s execution model also\u00c2\u00a0provides access to the underlying activation record, a context, and in a fast Smalltalk implementation (and Cog&#8217;s not too shabby) contexts are essentially virtual, created on-demand only when the program asks to see them; the VM&#8217;s actual activation records are more-or-less conventional stack frames, and contexts are proxy objects for them. \u00c2\u00a0And while message sending is heavily optimized, when a method cache probe does fail the class hierarchy of the receiver is searched, and any object there-in could have been becomed.<\/p>\n<p>The more-or-less conventional stack frames are housed not on the machine stack but in a\u00c2\u00a0<a href=\"http:\/\/www.mirandabanda.org\/cogblog\/2009\/01\/14\/under-cover-contexts-and-the-big-frame-up\/\"><em>stack zone<\/em><\/a> of quite limited size, organized as a set of pages. \u00c2\u00a0The stack zone acts much like a young generation for contexts, storing the most recently active N stack frames. \u00c2\u00a0While the number of pages in the stack zone is a settable parameter, the zone&#8217;s size is typically less than 100 kb. \u00c2\u00a0So it is practicable and quick to scan the stack zone and follow forwarding pointers after a become operation. \u00c2\u00a0We can know that the receiver in a stack frame is never a forwarding pointer and hence not need a read barrier when reading its instance variables. \u00c2\u00a0We can know that the method in an interpreted frame\u00c2\u00a0is never a forwarding pointer and hence not need a read barrier when interpreting bytecodes or accessing literals. \u00c2\u00a0However, a literal itself may be a forwarded object, and so, for example, we may have to follow the message selector on a message probe miss. \u00c2\u00a0We must scan the first-level method lookup cache and remove forwarded entries there-in; again the\u00c2\u00a0first-level method lookup cache \u00c2\u00a0is quite small, perhaps 4k entries.<\/p>\n<p>To avoid checking class fetch (where the class table is indexed by an instance&#8217;s class index to locate its class object for method lookup) we can scan the class table after a become operation. \u00c2\u00a0There can be up to 4M classes in Spur, but this is still a tiny fraction of a large heap &#8211; ignoring page density, faulting in 4M pages could be expensive ;-). \u00c2\u00a0But in the common case the class table contains a few thousand classes, most of them in the first few pages of the table, and that&#8217;s a tiny amount of memory to scan. \u00c2\u00a0There is a wrinkle; the class table contains only classes that have been entered into the table, either by being instantiated, or by being entered into a hash table (this because <a href=\"http:\/\/www.mirandabanda.org\/cogblog\/2013\/09\/05\/a-spur-gear-for-cog\/#identityHashIsClassIndex\">a class&#8217;s index into the table is its identityHash<\/a>). \u00c2\u00a0But method lookup traverses a class&#8217;s superclass chain, and e.g. abstract superclasses on the chain may not have been entered into the table. \u00c2\u00a0So the scan for forwarding pointers needs to follow the superclass chain of each class in the table until a class with an index is found; classes with indices are in the table so will be seen in scanning the table.<\/p>\n<p>In Squeak super sends are implemented using a method&#8217;s <em>method class association<\/em>; this is its last literal and is an association from class name to class object of the class that owns the method, the method&#8217;s method class (quite different from the method&#8217;s class). \u00c2\u00a0A superclass send fetches the value of the method class association and then the superclass \u00c2\u00a0of the method class, and starts the lookup in this superclass. \u00c2\u00a0To avoid a read barrier on accessing the superclass, the stack zone scan needs to follow the method class association to the class.<\/p>\n<p>Since the <a href=\"http:\/\/www.mirandabanda.org\/cogblog\/2009\/01\/14\/under-cover-contexts-and-the-big-frame-up\/\">stack zone<\/a>\u00c2\u00a0houses \u00c2\u00a0only some activation records, return from the base stack frame in a stack page may attempt to return out of the stack zone into a context. \u00c2\u00a0At this point the VM &#8220;faults in&#8221; the context into a new stack page (which I term marrying it with its stack frame). \u00c2\u00a0This process must now check for forwarding pointers throughout the context and the method&#8217;s method class association. \u00c2\u00a0Since marrying a context is an expensive operation this adds hopefully negligible overhead.<\/p>\n<p>Access to literals other than the method class association are of three kinds, message selectors, global variable associations, and ordinary literals. \u00c2\u00a0Let&#8217;s consider these in turn.<\/p>\n<ul>\n<li>If a message selector is a forwarding pointer then, provided that we scan the method cache and follow there-in, the forwarded message selector will cause a cache miss and the message selector can be followed prior to the class-hierarchy lookup.<\/li>\n<li>Smalltalk implements global variable access by using as a literal the Association for the variable that is owned by some global dictionary (a key,value pair e.g. of class name to class object, e.g. in Smalltalk or a class&#8217;s classPool). \u00c2\u00a0push\/store\/popLiteralVariable all fetch a literal, and either read or write the literal&#8217;s value field. \u00c2\u00a0The fetch of the literal needs an explicit check (otherwise we would have to scan all literals in all methods in the stack zone, and the entire method on return, and global variables are relatively rare; in my work image 8.7% of literals are globals).<\/li>\n<li>ordinary literals are simply objects pushed onto the stack. These, like the referents of the receiver&#8217;s inst vars may be forwarded. \u00c2\u00a0No read barrier is needed here; access will be handled further down the line in method activation.<\/li>\n<\/ul>\n<p>With the above approaches all bases appear to be covered except for primitives (have I forgotten anything else?). \u00c2\u00a0And the primitive issue, which we introduced at the beginning of this section, is access to sub-state of the receiver and\/or access to arguments. \u00c2\u00a0These may be forwarding pointers.<\/p>\n<p>First of all, the message send trap catches access to the receiver itself; this cannot be a forwarding pointer, and if the receiver is a flat non-pointer array such as a Float, a ByteArray or a String (all implemented as arrays of bits), the state cannot be forwarding pointers.<\/p>\n<p>Secondly, not all state-accessing primitives are affected. \u00c2\u00a0e.g. in at:put: (almost *) no checks are required because the receiver will have been caught by the message send trap, the index is a SmallInteger (an immediate, and immediates can&#8217;t be becomed), and the argument is either an immediate Character (in String&gt;&gt;at:put:) or a possibly forwarded object that will simply be stored into the array; \u00c2\u00a0i.e. the last argument&#8217;s state is inspected only if it is an immediate. \u00c2\u00a0(*) the exception is 64-bit indexable and 32-bit indexable arrays, these are floats &amp; bitmaps which could take LargeIntegers whose contents are copied into the relevant field). \u00c2\u00a0But e.g. in beCursor extensive checks are required because the primitive inspects the state of the receiver to some depth, accessing a couple of form instances, and a point that are sub-state of the Cursor object.<\/p>\n<p>How should the design solve the issue of state access in primitives? \u00c2\u00a0One approach would be an explicit call in the primitive, to follow the pointers in the receiver, and in accessing the arguments from the stack. This can be made convenient via providing something like ensureNoForwardingPointersIn: obj toDepth: n, which in beCursor&#8217;s case would look like interpreter ensureNoForwardingPointersIn: cursorObj toDepth: 3 (the offset point of the mask form). Another approach would be to put an explicit read barrier in store\/fetchPointer:ofObject:[withValue:] et al, but provide an additional api (e.g. store\/fetchPointer:ofNonForwardedObject:[withValue:] et al) and use it in the VM&#8217;s internals. The former approach is error-prone, requiring extensive testing, but the latter approach is expensive, potentially ugly, touching nearly all of the core VM code. It would appear that one of these two approaches must be chosen. \u00c2\u00a0I favour the former, but I could be quite mad.<\/p>\n<p>Finally, the Squeak VM cognoscenti amongst you will know that the Squeak VMs support primitive plugins that can be dynamically-loaded and interface to the VM via interpreterProxy. \u00c2\u00a0interpreterProxy&#8217;s API is a simple place to introduce read barriers as required.<\/p>\n<h3>Pleas<\/h3>\n<p>OK, please respond with conversation,\u00c2\u00a0contradiction,\u00c2\u00a0criticism, positive or negative. \u00c2\u00a0OK, please respond with conversation,\u00c2\u00a0contradiction,\u00c2\u00a0criticism, positive or negative.<\/p>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=HLQhLcKyGs8\"><em>Talk talk talk<\/em>, it&#8217;s only\u00c2\u00a0<em>talk<\/em>. Comments, cliches, commentary, controversy. Chatter,\u00c2\u00a0<em>chit<\/em>&#8211;<em>chat<\/em>,\u00c2\u00a0<em>chit<\/em>&#8211;<em>chat<\/em>,\u00c2\u00a0<em>chit<\/em>&#8211;<em>chat<\/em>,\u00c2\u00a0<em>Conversation<\/em>, contradiction,\u00c2\u00a0<em>criticism.<\/em><\/a><\/p>\n<p>&nbsp;<\/p>\n<div class=\"pdf24Plugin-cp\"> \t<form name=\"pdf24Form0\" method=\"post\" action=\"https:\/\/doc2pdf.pdf24.org\/wordpress.php\" target=\"pdf24PopWin\" onsubmit=\"var pdf24Win = window.open('about:blank', 'pdf24PopWin', 'resizable=yes,scrollbars=yes,width=600,height=250,left='+(screen.width\/2-300)+',top='+(screen.height\/3-125)+''); pdf24Win.focus(); if(typeof pdf24OnCreatePDF === 'function'){void(pdf24OnCreatePDF(this,pdf24Win));}\"> \t\t<input type=\"hidden\" name=\"blogCharset\" value=\"Cw1x07UAAA==\" \/><input type=\"hidden\" name=\"blogPosts\" value=\"MwQA\" \/><input type=\"hidden\" name=\"blogUrl\" value=\"yygpKbDS1y8vL9fLzSxKzEtJTAIRevlF6frJ+elJOfnpAA==\" \/><input type=\"hidden\" name=\"blogName\" value=\"c85PV3DKyU8HAA==\" \/><input type=\"hidden\" name=\"blogValueEncoding\" value=\"gzdeflate base64\" \/><input type=\"hidden\" name=\"postId_0\" value=\"MzSxBAA=\" \/><input type=\"hidden\" name=\"postTitle_0\" value=\"80msqlRwSk3Oz01VSMxLUUhUCEgsKslMzFEISk1MUXBKLCrKTC1SSMsvUgguKC0CAA==\" \/><input type=\"hidden\" name=\"postLink_0\" value=\"FcpBDoAgDATAF5WinvQ3WyBIApY0JERfr17mNOcY\/WCec7pWDFeE\/Di1zEGzVM28+mVjv\/NnxXOTpKAt0fcI1GGjoJIlRBKYlWT8Ag==\" \/><input type=\"hidden\" name=\"postAuthor_0\" value=\"S0zJzcwDAA==\" \/><input type=\"hidden\" name=\"postDateTime_0\" value=\"MzIwNNY1sNQ1NFYwNLQysLQyNQYA\" \/><input type=\"hidden\" name=\"postContent_0\" value=\"tVzrkttGdv6fp0DJFddMQg5nJN+ikccla1frycqXWI79I5VyNYEm2R4ADaOBoeifeZI8S\/JiOd85pxsNckbeTe3Wem2RbHSfPtfvXKAXu6c3b8xvh+JLW\/rGFqatClN8Z\/rBmbr43pqq+NL0vbN9sfF98cIUu95uPn+yG4bu+Wq13+8vGtfTU2aNf134frsq\/XZd++3q6eXVs9Xlv6wuP16ZZejGfrm1pl\/SPktasnpy85a+e7EyNy9WRMU\/vOhuvm1t4TfFsLNFGMxgq6KywW3bYutNHZgCPFO4UAy+CGPX+X4oOte2tNSvf7HlEIp7Z4oaV1rzlS6K\/\/2v\/\/nvH3b0DP3j0wkPXaX0lWu3O9\/3vqcPzUrvQTe4\/GjVj2u73Pq6Wtt+uwx+M+xNb5eVvXelDRe7oamf3BS1DaHY27peDjs\/bnfD0o8Dbll0xNUQ7ycXE+JuN8VtUZq2aMydzWkv9r6\/K9zw4QefPb369Lqu6fvizARavvOdBRNK3967trTFwY+Fa2lvuiXEV9b2nESJU9zG0e5D4Zqu9\/e2sfRn+m\/PhJRj3+OLt7+O1twVP36th4VIAz1V8zNmcF4p\/nKk3YaiGcPANC5YcYicYWeGwtKfbwu9fnGrG1bFvncDqVjReXqMGFD2bk38LppDokLlHZWg3NHJsrmpa78vDroZfeLb046udIGoHBaFdfRQX4Sd9wP2JQorv2\/Blk1tGhsWRTD3fKLl\/e1mAwWi0461AYIPF+Bju\/GsCuU4YNPe059Js5+u6J\/LT1Z7R5L+xe\/a9kCa0HVhWfl2+evo3vnBLmtr7u1ysH1\/WG5ppTPNcnA1NlqaYbl3bdXQ14GMQb8uiH\/pa6jNghlOmr+zdYcFG\/pFJG2LdW3au8D88ZsN3R1rMzGzneDBjJ1JvmEsSW\/DRfHWk9YO6fsd0UxSAkGgJhOUaMTzixerjux19+zmKxIJf0m\/khU\/YytWV0J6+LYhOQ2mviPzh3LBgEnNSXV7ViZRl3Jn2q0NkHBBMrCkCEQXKGdrZbOmC9Pn+a+m9ZB3NHD6hRSfBLv3SihdjT4s9+awKPb8O36LfsK+k4MLVxGnSI+gH8zJ1uIZfeToTGJ\/T9qrVBle0NWmJAe0PpwsDkRHG12TGgkJYraH0ko3NCwPt65J5Qdcogh729EpoIZ2x6Nb068NEV36uqanfZ\/5t4mvO\/IRQ28qh0\/EVzgU2xZjsGylpMX7uAMtwNmTrJItj11FPrioHamDa8kh872IKy3drKwN+bnKblzLh0Qp0tMVnGhBou5t49nc7k3vDF0rqL8b2NuRS+dLRqqUkbQ5PYblRGJ3gHVCZ4RZezJxWtCSjc0W0QUClK7xJJEwuoF\/Ch3tt2C1s+8M\/BhMHpe+t8QTWtzt2ObSiUnbitbu5Xk9k9xI0\/i1w6IWDCkoEsgK9YmWt8IudJnOtUnTxAmBy\/emHnmFAw+PnY5tL\/buznW2chJJ8Wn1mq5EPvHnzdiytH4mU7D9hs59cqO\/Fa\/1t+I2\/sYR5+z169tz1WMQvTfqEjoIL5D2QJVgaOw4SQ87WkZr1MK7GzKrXJGOgsFDnvNBSLCuR7v2\/i794WdSl45IfXbJcfMDOudb5tYPYM+zyyc3MfqIoyPgUJOBDplL+ezyiBp2l3RHilwGKmV6PzKcgRNA8I3SJUXrbZhHNFw0HMJgGzIefkj0YRMf2hEWsj30m9xUjE8UVCjC\/qYhyppyp+sQlwfjgEuCXIOUsBGmsb4\/Zs7FGZ5k161bULhkiQeYFLk8inNDeQ6aX9jmhs59saL\/cljldRKGKTb46hAJjQ4ofa97Q2On31MEYONeUPwM2e3waeNsXYWJY+peI1SYHJDDk2xwbD2MSuZsv5YFB\/JxRsJTuqdeIPpHAmXwK109wvuQSwJ0EY1VZq9Bm\/ji2t6TkguFX7HLZ+2n43PLN7SSpLxWaEsEY9ODejW+rTq85LsK8c7gYQ9gk5NMuMIvS1IMEiyY+PTyWokf1Nor14uv5Z+vricW\/mVO4EcXRlP\/RFArPLnJPrDKN+RnifjGtKRKhH8GIATSsiB8jyhK\/Dm7WsaV6ku3tlWpkX1PYSV6gLfjOljChu1QUxj9g9s6WF9SlWSPqx9FsQ2w1iOmxkcSHC4e445o2g4RtACIodCMHWNEjqh458jQAsUQ2FeUh3BhoWGEfXGbReSoVbPYqyw4WSRxe+YF7TsXGKAJUF698tsHrBeB930ckAtq5kKOysM41Ihy7LEe67sJxURdcW1HzIv2Lczoete4gWN0YHxDOm0OYfJcYcId64TMOuN6gp+B1IJsFr4JV1MAbRJJwGvH3IexwNFhi+yU6KknEuaZV\/LVkOia8CmvztINRB8jUUwdscp58F3gxaS1dcUO2JekyUFcKxFPeRhjDkLt5V2IKmDlKXXcOanEwQYU0PXkUgvRhCMP5PqHNheqonPWZQ7GQ3mNYCGzgR+O\/Oqzqy1YbUM02Y1HVsNwKWrLBCBVr09IEEPG50hvkjDt7zbpuHa7KBSBJVVgSskDVo4IkV3ZKo4PSbr\/knyJ6cgYSeZguSbdgJCLuads3Fa9\/5mpJfsrbm+\/fzXzEZWrWhX5oE\/k6BJAkn1wbydseb4gexjA+Fq0pkQCOQttuRMpyJUHDULfnl2dq3B3riKgz8+ysj7ug5ghMOEjtMP7tedR0xEaIxWkZF1kB38Bt0C\/ffLRco1EmZhHYCBwwpM03sDH0enNxGygYpJoa8SiZ+cvaMNhyU6WDnnjQqeGglAtCUdVHYc2fAvAovmKxjAQ2hiKAdEiTIgqQLzLDBc4PYPoiaCTsFVSah+s7d9dkJu86MJ4Yatxde\/svvLlKowNHXf4ovLu86vLiyv638dPLz777ONPn9xwvQMgHsp35FHp1gLqBMJGYntG\/Y5o2vS+YWgbbOOWgten1BB8IuCHwFxHt9kwpOo9aV5TnOEbjdjNSGz2vQboc2WCTx6C7JidxpSM4NyZqzmCUYpOfK9Bh9FTjDkAb5PVMZwDjjsCcaiH9OC96bd2EF8i6Y7hDIU9IesGxBmtWW9UUn4TrF4oF3E1hZTICTJuuJbMF4C7tdkmf2+0WqAVq4SrdrQWhbDoGhY4iQlkFVXVXwgWgT4J+LB1PdWSIi54YC\/S1Nrd2dzWxWSPA6sbOPqyfZObVb\/KuVe8pH1ny5FNuRqnWE8cJI6zl9zkjlBZAgqyb6OAxHUnNw3qT46ZCiVgNZcuX\/kWdxh7m+olyT1GyIPUrHdlghAUDwxZVK24mTnRkg9HUIays2Cmquk8Y9ZaqWUEj0yX1pKFCe+\/\/fNibslBM7gD3WdcW6587c1Q7r64\/7x+6+y\/7369\/f6TO0rPTF0tN1z3QGLGVgrBMYzufEfUcn0xkA4TFlAPDtWfrssqlKyFU3fyj9AcYqOTKmA\/wnXTukll+e73zgs\/tKIKTEMyLB1yDi4DSQAqbS9JVIRJGZyCu5y+n9UJFvB6DiYu9CKv3gIZnG3cu3Zswjls8Q2sEqUp\/W1NuTj\/9pBIBOvtoLildchhIiyjXUZ2qq7l2D0O0ZBJwcdasxkUxylg7gbctr2T2hki54+mfzk8T7FYPtImzxNWAU8nik5SmyAac4gqw06VtWwcAunjQrlt55ooMmXnyxkHF51U1djTiqYdpXNcPAlKD91TLndSf+3JbUj+0ziU48NFV22e3HzNHzKpSYl05\/dI4BZk7o\/RahLSaq1Um+DUiBd0waMCE2wZt9DS0HQNFJlROpmnzVqrkxsB3cJnTEKNceeI8kkNR4rjIMIJPNCVIXoDJCNj74YDA5ODRD\/TmbWruWgpD7FRJGWPnQYToTRbRD8GoG9c8fr9mkNxh2BYzxk9wXFrAoo9Las6gZNavKJRg73bjICUDBLYxAEueyuYKassRriS4M6fiA9tdHYzecH2CE40gtWt3HFvWZV7ZPC0JAomiopWilN+wF2r1RMwbSg+nBd\/ZD+V7zCn1LX3vr7PUowG7OSIECGf4FT9EG1aw6NiwDVdzXDhNx3Fqk\/y50x8TRmAHUqtQSa\/8HA1hhNHa3pZLgZGuloRtxkokTHblIXxMxMQISSIB0lGLZkqyDF6rO7hAA7Gtkr0dyDclVbQMKkiuw8uMg+kwb8R9SPbwV\/bErxaXT5bXV6t1qOjCNLYpVn+4oalCRRNAv+XYs+S5Lx6cqPE1d7fkZGUnIHA4IVKkaHKTsWV2Kmp7OPFLU5tx9ZRNq+ilD7ABqj5zF6QY0LNt63sO2k+xJo3o4\/zzEkqtCYyOPHqtfVktgZGJf0uVPUPE9cHwlUMkfhOOabSRcL2nt39JKIo3NOHKp9lVdgAVQiyysg7eri1NiG\/Lw+co7dbUSWyrcxkIszmPpDkt\/Hm26B1\/moxc\/EsBCaLUxqbmhrmdGPUkzsh4yfKWLmaN7OPoF7zwWfj9fUctN+KjYFOx94KfSB0RT5wkMinPuEoy1W\/MCvxSKGM8+gp0wncX5ZyUhVzelH9R90Mo5TYHciqQ0wtpSaSSMz71qntYu69q46b2mj64RwSZWpM4AnSYF1JVjOxyYW4AbkYrZeIk9GvYxYxURlTwuhcZvuZhyXJt1bXK3l5d1AOzAvDR\/UfIir2avem465mqnq7TSojHStiXm+H+U73wmrOCJWNGalsomRIjsOWEhp7f5U+lRDW+4nO+TPvA2a51eKELbMuYJZcS4DbEhJh6JfwqwCrIXU0KdUbm7Xlalvnhg1dnO4JPfoFDXhx0LEKmHAHcA7+QKEhltyStn99kGykTNlIQh+i2mZu2jBZDl3tVEZPVSHwy1DwF0KUPia8BlE4nHUL1Wn4TuHAW8\/FfAUR04NfRBo\/bNehu04Z1GsjFvAT5xDDoZ4SqHylWLIIR7dMV5vCu2I1KZhKqSBZmumzVCSP7RFOR4rjzIL654TmhTus0O9U3HnXKgWiKRttfGVr\/UxErQ8DaQzyQOyZlQQJ8FEgr6V1Z1OtKRLyisKPq231tRCU69stDiGWbD39kMGceQNtoXeJJRbZjjRpSccsNzWnm5rQF6AwXXr2pYt3sxOe2DAOQtEcalTsDuveVYInKY2nf\/\/zv97+sJi+4BgeEAoc1ysZ35IMKXXph+XYJSVKdW1N4OMNuOGUPYryXRi5oYgnJRFKp\/8VYkLbGotTsh5TK6GFQJTtay5mKdDDo6RDvkftOupFKhaSXzV5X\/O46HiGdcS3RA\/sfvCUZ+3Men04jxuKzHKW3bt+GE29KEp4GJFjZRtpM9QH6eQPWQ3IhDvN4FjBm+vjEj1diDY8vZecDatZ+n7JE1CYSxLnQw+Q0Ag3b3qZwRGklBFN5787TAboGbY1IpKXtFgKv8dw33GB7d5BwhGTLuJ4gtpkDhUqD3wIqDCh9wkYH+F4wSH4CZtysjPlx+yZl5ysjxQ\/OTzxfIUEjnnf6C\/jCvOBEk+kUBCwb2dmJUsRFaAxDyXMvwO7MYZ3tbr6aMXquSwx\/rWMQljSA2zha7ddMj1kYAS\/UaKUk3+jGMLlSa7zEK9+Hd0w+fcYkrem5cyA4UKwXKPvSGYZLJr2gxqFohnJo3KBzyjkmPqRrAqRyAU7vZT6wJlBWGhLRpf7zYylEWLGpkEWQ0FSquJPBDklW+qLKBw3lru7WIcV0+gUSv8IK4fOlWxstVRXyM1cXV4Wd+vkn5ygMUmnpJFM2kT8o1Nha6U5oUMQzGOZrHaXzEnTXS8sSfJdy5jXDEdqDePIuCSJgUDwB4qcUzcWSokM4ri\/wPaGbyTrCQ9Ul95DV0xtWsm1ojuuhDgeZvtb0DeLKlN0BYaMZagUW3V0IBaUTPwBl7M1xRcGiBM5dj7eFfxRHXFv+RHBsD7PRiaHpumBbzPcJU6rcWHiH49bJoVhjENu5Z5i0gOJsmIHzjQmUsleeqkZiQu7ljQVn3HI7+2pEhHrDwhZ3D\/emS4UH93F3Sf\/F7MZLpwwzGe3y1l6caYzeckbaysuSNatyUubNGqewWtqTiyVbjArn9ZktIyJjk1+ifNYQUo8zM99v1nJfGFsh3U496Ov5XnxJcDTEbhLx1uqohikpNCx6bW3zVW5mgvHaBpyr+bq6rpw21bcG7xTUdk2cMlvY0aZC6Uj6EBxXRJ31shjOiwkEV8vz7PRXL2dbxo0VE045bL2rzmvs3uulgcOzHKjhXhYiYpN3FDbWLRe6NCgyTvGHvSsv8lXNw359UGwGXe91e3ljGXXu6f739X2+nFipcqpTGcvMgVfZGkCihWJKVmaaa5htsJIqBNhpAGh3We\/zHYwqGfvlIAzlmnMc\/6WU\/Af6PTp4Ss67Ta8wt1uodlPbsxRFS+rRaXrsbUMsXYluyBGZ8owt2PK5NAe59LMfPswksYL1yk5djqqIoUwLWRma6RXz4LCYvZx8MG\/J48Zbg9Sn+kfDHPw5uHIZR7TCKXiOn50CRlnYqlTfkpDnMJELXdeJ2Xi3zEFUCoYm+0VvNRuMJJrOaDI+FGEI3K16PYo3dFpeqaXEatumtUTpkQb8kliAOiK6FWm0ULwpTPSC6cfr5ODgeBrJA8xRHFKId2H6SGpVMpeLUI+5uZzPzmrZ0szYd+GLD4vsj9P7bqcxjOJCJXbcK6atZCOnuLlqpwvc3FymYHjgvbSMSqbxiseY0iaeznWDp6ZP31WY\/TA\/RH8GMuj+uLEtENq\/0sAOx0YnJDD\/OjFMZpjJX9ImR+9VKymMR1pDo\/f8hh2f7X7+X9B\/xz2mxuwgpMTZSy8MDdGTjNBDF8NY99OGoBh3DnknDAoxzq4DrTgm26Qxhw\/z2OCmxOIrpX4vLjyUkMuew5NWeMIBIdPOIY4BSFxkZ+Om3FBdSLnTKo8twXZVIOSX3\/Qir74CAzFTrc5z+p5sUvCOA04V\/pFjzm4bHIgpyqVVN5jb5m2qENl7UjEmumOUrRLOCF\/9wK\/VaSWeJdIWnit3dZu63jymdQEAyzTbFIqc6QylNcei6Kpx620V0vurS0IB1ZcaZqjX\/pqW\/s1ebFp4nbaIr6aARYaghBztP4me3uFLo5uahw+gGWTOuktxpr+Vbub282swqn424WHswwZrEvzqLEXmVDkrNiQJW8RZC+OxmpODubYIthCW0IM\/DNVOHpAcaicY3mKwfczv7GcShvi44gDdHG+\/QO1pnDKfBH3+hADVchyIRzzMg8xUrOZnpbhhIBIIjie3YWekRqWh+LMFHf2sBBnzxOlDDjQa300YC1kzaxfy928OZ7hT995X6uJdmPYrbhwuup890Zu8mO6LvpIVhpneksFQAIf2f1DVPwOG4cOWZXOkzvwjNdU7pAt1Y9F7kkwELOsXekGdRRnbE+YyoV67afiUqwTgMhkfE4+p3rncRlhGvsFNOyTmrKvhk3IgiO5pzl6o6PypEQW0wJ4S09eR2ygip9dfPqPuFciB4\/JXhTfJ107sVheqKP\/seQH0XB9MjZMcImL4gdY8GIa\/9JK+HDSdc8gMnleukqIafrRxNs3fh7HU1uUR4yuo9JHrEeOrUIBfDP2rAQ8TCaSlFeAYuk\/hcF48xV7mu7mJ6dDPzLynA3SQnYIjQFfWtPrFAmHZyTq70q8+rWZDbsUZ6wOt\/h66ylkAgAdBml418F+cT4VTeddIa59xwbGnuNo76sR41tailnbrfY54zxViPOwLq9xh3G9TDNNx+NMq1RS4U6mtqKm8l+wR4KZ9U5jpHktrbVNwfWFkz4zN6NKI1BxXnyf6lxcrLlOQ4dITfKqTXauVuJP6786x493zVK9CYPteHFyJ\/7wde0Nj3d8eRjsS\/6RPdHbgVP5M+4+5YPvIRvPx1sr54tsSGyi833cecvdRLyMgcU4gZ9eToA0UxhuH3LHLppA9J1GJ310JKb4p3PaL808sg8gUA9VzNt7iT97mfiKyR6twKiCvtV0Iq6FDp5p7mVmQ3VoceDlOrzxMsSXjeJHll4abUiTBdX54oHxuZDeYMg2LF7tDJJXHISYwaL5cDtc4\/\/KhXMRWxrUOK7taczHndV1IROMTThVPpbstdTILijRZUeB9CwSOKXaLG4udIWOZSOVDVJCFyFbol8nl0g+2rkmv6DT6DpdznxNpeVnT4+\/ZI1bKCCCaDdQ21B8aJruGmrYoH4X32tA1BnwIjpPN6bBx\/3OBzu16bMZ7MSA+PaVBMGsBBF1bm1fjX3g6uigePT3FC5zYcKro6nKmVLCPQFnVMSi3SJL0YCHx07e5+NhrvTGgTZ3UvKgHekTL6eEa0812iLefw47YVl6qZ9oqHVgQVqOtIXspc5qNo76RRruTP30fSzvzSCCmV77Tk8vjlLKlFu449Z17DbOstbkoKdsLYXeafi\/MZXVzpWDmeEvWBAwjH3AcIlAHKdJrGNvv\/Gvkwf7Tmm6bZ+DfUTxHyCe50Ub41GmGRN6Q9YojAB+lc2zhu3vHFTybt\/mxz2TaX+\/2aAzJfKOJQITOE1rSGdf6qsDp9LAe7PjMBPKHEy04hJWDPqUmud+Iy+2Pv8PpI8\/AiQ+\/8\/CwnNLuTiOeQLfVelFW9M5nUJ7cM9vfPs6+qhH9z9nqY\/8tyNEjci6uWmYk5EW3z+\/N7wpBlGX9BloUsyToUayXvLP8pqRDqyQvxuG401i7onBmCF1p8ctQtjgR5mIa\/GG7yF\/ubbEEAZl8ujVXBS3gwoioiUZeo32GfTFswlfcRIOQAW\/Ff+ijWJj7v3Yx3yssVqyv51K6lLJarLE97W8MiUxLP01GfTEtvUBHUiHEne7pfPwl3BwlJi3udJD0\/tTk1\/r6nHrWq28qclVB0p8pLO4JF9d6QxNevM74h0iA9aY2cV36KXLbY+\/TYJ\/+d2t9jrlFV157R7zzREVzhSb3w6Kznl6peG72pqQZnDwJkGHb3hovcO8E5dL2G\/0QYawQRUiCF4oL6dv9C\/xaBb6Bp28mdfarZkGpf+O+0c5\/8UvQnz15t92b8o\/H\/4UPpMm+Q\/8NkP8F1dpF9Nf2yJti\/jCdlpxgXkd9r4LylUdlHbBLRuMfuBFVr4J0oFAAiUQA8taxG3IagbeRvtH8p2R7\/4uq15lnNYrnvKaH438vkgjAw\/MdP0f\" \/> \t\t<a href=\"https:\/\/www.pdf24.org\" target=\"_blank\" title=\"www.pdf24.org\" rel=\"nofollow\"><img src=\"http:\/\/www.mirandabanda.org\/cogblog\/wp-content\/plugins\/pdf24-post-to-pdf\/img\/pdf_32x32.png\" alt=\"\" border=\"0\" height=\"32\" \/><\/a> \t\t<span class=\"pdf24Plugin-cp-space\">&nbsp;&nbsp;<\/span> \t\t<span class=\"pdf24Plugin-cp-text\">Send article as PDF<\/span> \t\t<span class=\"pdf24Plugin-cp-space\">&nbsp;&nbsp;<\/span> \t\t<input class=\"pdf24Plugin-cp-input\" style=\"margin: 0px;\" type=\"text\" name=\"sendEmailTo\" placeholder=\"Enter email address\" \/> \t\t<input class=\"pdf24Plugin-cp-submit\" style=\"margin: 0px;\" type=\"submit\" value=\"Send\" \/> \t<\/form> <\/div>","protected":false},"excerpt":{"rendered":"<p>Lazy Become and a Partial Read Barrier for Spur One of the stated design goals for Spur is to support pinned objects via lazy become. \u00c2\u00a0This is one of the less well-thought-out parts of the design. \u00c2\u00a0If I can make lazy become work it&#8217;ll be (as I hope to convince you in this article) a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,7],"tags":[],"_links":{"self":[{"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/posts\/149"}],"collection":[{"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/comments?post=149"}],"version-history":[{"count":7,"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/posts\/149\/revisions"}],"predecessor-version":[{"id":164,"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/posts\/149\/revisions\/164"}],"wp:attachment":[{"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/media?parent=149"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/categories?post=149"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.mirandabanda.org\/cogblog\/wp-json\/wp\/v2\/tags?post=149"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}