And if you want to go down the "elaborate" road, there are even niftier projects out there like the Javascript transistor-level simulation of a 6502.
There's always room to spend cycles. But simulating a 1980's computer to the level of precision required by "correct user experience" is a straightforward engineering task these days that doesn't require anything more than "just plain code."
You can't wrap Lightning itself, otherwise any possible gains you could expect are lost at the CGO transition.
What prevents wrapping lightning? (I'm not at all familiar with Lightning)
> any possible gains you could expect are lost at the CGO transition
I was under the impression that the CGO overhead was due to marshaling data -- could that not be avoided by representing the JIT'd code as unsafe.Pointer's and type annotations (akin to how reflect invokes reflect.Values)? Or is there a whole realm of stuff I'm missing?
EDIT:
Did a bit of digging; reflect.Value.Call internally uses reflect·call (defined in runtime[1]), which obviously uses the Go ABI. Since any JIT'd code we want to load will expect to be called with the C ABI, presumably, we're stuck with runtime·asmcgocall[2]. Combined with runtime·cgocall[3], it certainly is longer than a vanilla preamble in C, so there's definitely some significant overhead not related to, e.g., cgo.GoString. I don't have enough prowess to determine the actual performance impact, though :(
Could be a fun weekend project.
--
[1] http://code.google.com/p/go/source/browse/src/pkg/runtime/as...
[2] http://code.google.com/p/go/source/browse/src/pkg/runtime/as...
[3] http://code.google.com/p/go/source/browse/src/pkg/runtime/cg...
Time to go profiling again! :)
I assume this is possible with Go as it has the ability to call unsafe code?
> "There is no facility in the Go programming language to support in-line assembler language code, and there are no plans to do so" http://stackoverflow.com/questions/2951028/is-it-possible-to...
Of course the C parts of Go's standard library have optimized assembly - using C's capability to do.
So Go is not easier in any way for dropping into assembly - in fact it's much harder, you can't do it in the language, at best you might be lucky if Go's library does some stuff like that for you.
http://golang.org/src/pkg/math/exp.go?s=368:395#L4
You'll notice that 'exp' is defined below, using Go.
However, 'Exp' is also defined in Assembly. For example, amd64:
http://golang.org/src/pkg/math/exp_amd64.s
This is all compatible with the `go` tool. You just drop in your Assembly, run `go build`, and the appropriate Assembly version is chosen based on your target architecture (or the Go code is used as a fallback if no Assembly for the target architecture exists).
I don't have much experience with inlining Assembly in C, but this is pretty damn easy.
No. It sounds like the `go` tool is aware of how to compile different pieces of code for different architectures.
> but you could do exactly the same thing in C - and you can also inline assembly in your C source file.
Why does this make C easier? Does C automatically choose the correct target architecture for every piece of Assembly you write?
It gives you more options. It makes it more practical to interleave C and assembly at a very granular level, whereas it sounds like you can only do it at the function level or coarser in go.
>Does C automatically choose the correct target architecture for every piece of Assembly you write?
No. I won't deny that go has a good build system, but I'm more interested in the language.
Inlining some assembly where you need it - interacting with C variables, etc. - is definitely the most convenient thing.
Of course, if you don't want that, you can just put the assembly code in a separate function, also very easy to do with C.
It's about the same as C. If you want to see really easy, take a look at how LuaJIT does it (DynASM).