Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Brian Shirai
@brixen
that would certainly work, but as the size of holes shrinks, the cost to allocate an object essentially doubles (allocate a slab in a hole that is asymptotically approaching the size of an individual object, so only an object or two can be allocated in the slab before it needs to be refilled)
I guess I'll soup up the Immix diagnostics and look at how it behaves
Brian Shirai
@brixen
ok, here's the plan: 1. only allow pinned objects in third region (ie large objects, pinned, machine code); 2. split memory handles out of references; 3. pass addresses of slots into the collector trace function so we can update them when moving objects; 4. ensure write barrier is functional so we can detect cross-thread updates; 5. implement Immix evacuation so we can compact memory
Ready. Set. Go.
stretch goal: functions
double stretch goal: THCA (Thread-local Heap Container & Allocator)
Brian Shirai
@brixen
I am much happier now that a change to the Immix header only causes like 16 files to be compiled instead of 320
now that I've finally got Immix integrated, I need to clean it up (eg put the utility classes into the Immix class namespace, clean up some of the concepts)
Brian Shirai
@brixen
I think this idea of allocating a hole as a thread local buffer for threads that won't have a separate heap is going to work quite nicely (once compaction is in place)
Brian Shirai
@brixen
pointer arithmetic is so dicey
Chuck Remes
@chuckremes
stretch goal!!
Brian Shirai
@brixen
all my stretch goal budget was wasted on pointer arithmetic shenanigans :sob:
a good life lesson would be: "whenever tempted to use C++ trickery to 'wow, I'll just change what addition is', just don't"
Chuck Remes
@chuckremes
heh
Brian Shirai
@brixen
removing the pinned objects is a bit of surgery but since I've got type-specific bits, totally doable
it will incur a copy for a String object passed into the C-API, but we can pre-emptively pin for Strings created in the C-API
and we already pin the RTuple objects
as the use of C-API fades, this will require no further intervention
so all around a reasonable change
Chuck Remes
@chuckremes
+1
Brian Shirai
@brixen
can't wait to remove frozen and tainted, they bug me so damn much and have for a decade :sob:
used the bit freed up by pinned to add one to the object_id field
the header bits structure is pretty nice
Brian Shirai
@brixen
pinned is out, no obvious errors
Brian Shirai
@brixen
that was quite a laborious change to pass the address of the object into the collector trace method
but now the stage is set for Immix evacuation, and that's very exciting
probably will clean up Immix a bit more first and implement the thread local allocator using Immix holes first
oh, before any of that, I'll make the collector partially recursive, which will reduce the work to maintain the mark stack
Brian Shirai
@brixen
oh @chuckremes do I have a little treat for you
May 28 22:56:01 [43265] <Warn> Therad id: 3 updating an instance of CompiledCode created by Thread id: 1
and
rubinius 4.1.c1 (2.3.1 9bef0d76 2019-05-28 8.0.0) [x86_64-darwin18.6.0]
Ruby Exception hit toplevel:
Thread id: 3 updating an instance of CompiledCode created by Thread id: 1 (RuntimeError)
it is very very blunt right now (all or nothing), but there are two options, log or raise (or both)
I'll figure out how to make it more subtle, but to start, logging should give a lot of info
the raising option would need so rescue case probably high up
so a combination of compile-time raise option and run-time rescue option could make this quite workable
   --log-concurrent-update    Log when T2 updates an object created by T1
   --raise-concurrent-update  Raise a RuntimeError when T2 updates an object created by T1
Brian Shirai
@brixen
@chuckremes just pushed that code
I'll add some niceties probably tomorrow
since I have the MemoryVisitor now, I need to implement become as well, which will make programming proxies really nice :grinning:
another thing we can do with MemoryVisitor is search a subgraph of the object graph, say from an explicit set of 1+ "roots" instead of the graph roots
I should expose some nice methods for that in Rubinius::Memory
Chuck Remes
@chuckremes
those are treats!
will play with them soon
Brian Shirai
@brixen
gotta figure out what's happening with the rubinius log file lock deadlock
Brian Shirai
@brixen
@chuckremes I’ve made it through my list above pretty quickly, and while I’ve got more to do on the GC (including tracking down nokogiri issue), I’m curious what would be the next most useful thing for you?
Brian Shirai
@brixen
thinking about the JIT, here are some things that are important:
  1. I want to respect "do a little, get a little; do a lot, get a lot";
  2. by using functions as the interface between nanopasses, we can leverage f: A -> B, g: B -> C for composition of passes;
  3. we need an explicit mechanism for describing dependencies independent of the function composition;
  4. then 2 and 3 give us the ability to parallelize compilation where dependencies for pass B(i) are met by an B(i-n), n >= 1
I wish it was easy to do subscript
Brian Shirai
@brixen
the "do a little, get a little" is really important because the old JIT was "do a lot, get a little" and deterred people from contributing
Brian Shirai
@brixen
@chuckremes ok, you need to configure with --{log, raise}-concurrent-update and then you can run rbx with -Xmachine.concurrent.update.{log, raise}=true