HN user

_cogg

14 karma
Posts0
Comments8
View on HN
No posts found.
NaN Is Weird 4 months ago

Python supports arithmetic on mixed numeric types, so it makes sense that floats and ints should have a hash function that behaves somewhat consistently. I don't write a lot of python, but having used other scripting languages it wouldn't surprise me if numeric types get mixed up by accident often enough. You probably want int(2) and float(2) to be considered the same key in a dictionary to avoid surprises.

See: https://docs.python.org/3/library/stdtypes.html#hashing-of-n...

Yeah, I expect the real advantage of a JIT is that you can perform proper register allocation and avoid a lot of stack and/or virtual register manipulation.

I wrote a toy copy-patch JIT before and I don't remember being impressed with the performance, even compared to a naive dispatch loop, even on my ~11 year old processor.

Thank you! Not the author, but I'm also building a compiler. I've stumbled across these tests before and mostly just been irritated and confused about what to do with them.

Yeah, I was totally unaware of this. The namespace appears to be blocked in the sandbox -- probably rightfully so -- but now I'm curious as well. I might have to test it out and write a little addendum.

Edit: Looks like it's slower by a pretty good margin (~3.6 seconds). It's certainly possible I'm doing something stupid. This would be really nice to have for webassembly, where I'm convinced I need to implement some sort of virtual register allocation, and I'm still not entirely sure about control flow.

Author here. My background is in rust if anything. Honestly, I prefer to avoid playing these clever games with type systems unless it's really necessary. It just ended up being the perfect tool for this very specific problem. (How do I compile code in a sandbox that exposes a limited reflection API?)

Writing bindings isn't something I have a lot of experience with. The main difference I'm aware of is the FFI system, which creates bindings from C headers, and will result in faster calls with good JIT support. I assume it introduces some extra security challenges if you care about that. You'll still probably need to write some wrappers, either C-side or Lua-side if you want a nice API. I know there are other tools for creating bindings, but again, not my area of expertise.

You used to have to be extremely careful to keep the JIT happy, but I think this has been partially solved in LuaJIT 2.1.

Calling C functions using the old stack API would cause the JIT to abort. In Garrysmod's case, that includes such simple operations as constructing and performing arithmetic on vectors.

So when I was building a high-performance voxel library for Garrysmod, I ended up splitting my hot code into chunks that the JIT compiler would usually be happy with. One fast loop to generate a mesh, then a slow loop to convert that into a mesh structure the engine wants. Very carefully designed methods for bit-packing trees of 12-bit integer voxel data into flat tables of floats.

I've been thinking a lot about embedded scripting lately, to the extent that I've decided to roll my own language. I agree with all your points, but here are some of my own thoughts:

It should strive to be familiar for users of the host language, not invent weird new syntax. This is ultimately a personal preference, but what I want is a script-oriented rust: Dispense with some ugly stuff that makes it hard to compile or analyze (borrow checker, macros (maybe), giant core+std libs), but keep enough of the things that make it good (inferred static types, expression oriented, pattern matching).

Regarding the "no GC" point: My idea is to just not store any persistent state inside the script engine. Allocate temporary objects in arenas which only live for the duration of a top-level call. If you want persistent state, expose it through bindings. This has the added benefit of making hot reloading trivially easy -- when there's no state, there's nothing for your hot reloading system to break. There are some pretty obvious pitfalls of this. It could totally blow up in my face, so the door is open to adding optional global state and/or garbage collection down the line.

I have a very(!) minimal prototype, and I've written enough of a compiler before that I'm confident I can eventually produce something that works. Whether it lives up to my aspirations is a different story.

If you want something that actually exists now, maybe look into AngelScript. I haven't personally used it, but it's statically typed and supposedly has good C++ integration.