Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Do you not think the Truffle and Graal IRs do this?


No, they don’t do this.

They try to infer specialization from an AST interpreter. That’s not on the same planet as what I’m talking about.


Well I'm not sure what you think you're referring to then.

Do you mean an IR where all core library routines are first-class citizens, with their own nodes and information about their semantics encoded so that the compiler can reason about them?


Yes, that is what we do in JSC.

With the caveat that core routines that are very cool don’t get included no matter how simple they are and warm/hot ones get opcodes even if it’s very annoying to do it.


Right, so I get that, and I think so do other people in the small Ruby compiler community. It's just a much larger problem in Ruby due to the size and complexity of the standard library and the presence of more non-local effects (like accessing dynamic caller frames is often required). It's possibly so large that it's not reasonable to do it like that and people are looking for other options, like Truffle's PE. That's why it hasn't been achieved yet - it's not because anyone is unaware of common VM techniques.

Another big problem JavaScript doesn't have is that user C extensions are very often on the critical path in Ruby, so you must be able to optimise through them somehow. I don't think JavaScriptCore has any solutions for that we should be trying?


Chris, JSC’s IRs have extensive support for accessing non local callframes and doing a great job on effects generally. JS has _lots_ of this kind of nonsense in real code and the language supports it at least as much as Ruby does (like in super evils ways, like function.arguments).

JSC has extensive support for fast calls into native code because of the DOM. For example we have the Snippet JIT that allows the DOM to turn hot functions into almost first class compiler ops. Like, callbacks in the DOM can dictate codegen and effect analysis.

Josh, the canonical JSC approach to the iterator callback problem wouldn’t be to use builtins. That wouldn’t necessarily achieve great perf. It’s certainly not great for the baseline tier. I think the only good option is to make those iterators (like Array#each) be intrinsic as fuck: all call ICs can ask for inline machine code generation of the loop along with the call back to the passed in block. You could imagine this enabling inlining of the loop and its body even in the baseline JIT.

I get that people probably see the builtins in JSC and start having wild fantasies about what this can achieve. In reality for things where perf matters, you deploy ICs and custom template codegen.


I think the problem with the intrinsics approach is that lots of this code isn't stdlib but extensions like: https://github.com/ged/ruby-pg/blob/6853309b64852755daed3e9c...

I don't really see a good solution here other than lifting the control flow to Ruby with specific bytecode ops to minimize overhead and a good, typed FFI like LuaJIT has? Am I missing something?


Could establish an interface for those extensions to participate in the JIT and ICs. JSC does that for the DOM.

Other than that just try to make calls into JITed code as fast as possible. But that needs to be the backup plan, with the main plan being that perf-sensitive extensions play with the JIT.


But we have no control over these C extensions. And there's a huge corpus of existing C extensions that need to keep working. 500 million lines of C and C++, in fact, even for just the publicly available code.

And by the way - there isn't really any proper interface at all! There's just basically the whole internals of the C Ruby implementation exposed to C extension authors. There's no abstraction with handles and things like that.

There was an effort at one point to get C extension authors to use the FFI instead, and a JNI-style API to permit a moving garbage collector was proposed, but these approaches weren't successful in gaining any momentum.

All in all... that's why we don't just do it the JavaScriptCore way. We have different constraints to yours.


You don’t need to make all native extensions fast. You need to make some of the most common things fast and keep the rest of them working. It’s fine if not all extensions adopt a JIT interface.

The thing about moving GC is a red herring. Ruby wouldn’t benefit from it. JSC doesn’t use moving GC.


I think for CRuby to use the JSC approach we would need to translate methods written entirely in C which opaquely iterate over collections and invoke blocks of Ruby into Ruby which uses bytecodes to get an iterator and then iterate?




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: