Discussion:
Compiled debug.getmetatable/setmetatable?
Daniel Kolesa
2014-06-14 14:59:29 UTC
Permalink
Hello,

I'm implementing a language on top of LuaJIT and I would like to implement
a few things on top of the metatable system as part of the language's
runtime, however there's a problem: debug.getmetatable is not compiled...

that means it'll make things slow. Regular getmetatable is compiled, I
benchmarked things and with getmetatable stuff is fast but with the debug
version it's really slow - I need the debug version as I need it to ignore
__metatable.

Is there any chance these two functions (or at least debug.getmetatable)
will get compiled?

Regards,

Daniel
Karel Tuma
2014-06-14 16:43:36 UTC
Permalink
Post by Daniel Kolesa
runtime, however there's a problem: debug.getmetatable is not compiled...
__metatable.
https://github.com/katlogic/ljx/commit/882ce33223c83421e01c391f2ae6cac09fc70d5a
Daniel Kolesa
2014-06-14 18:16:24 UTC
Permalink
Post by Karel Tuma
Post by Daniel Kolesa
runtime, however there's a problem: debug.getmetatable is not compiled...
__metatable.
https://github.com/katlogic/ljx/commit/882ce33223c83421e01c391f2ae6cac09fc70d5a
Very nice. That's pretty much what I would need except that I cannot use
anything that's not upstream and I'd need it to work on all types.
Karel Tuma
2014-06-14 18:32:42 UTC
Permalink
Post by Daniel Kolesa
Post by Karel Tuma
Post by Daniel Kolesa
runtime, however there's a problem: debug.getmetatable is not compiled...
__metatable.
https://github.com/katlogic/ljx/commit/882ce33223c83421e01c391f2ae6cac09fc70d5a
Very nice. That's pretty much what I would need except that I cannot use
anything that's not upstream and I'd need it to work on all types.
Care to elaborate? ctids and base_mt are global, not per object so the performance
benefit somewhat eludes me. If there is use case for userdata, thats easy to fix.

As for upstream thats up to Mike, unfortunately my customizations of luajit
are too numerous / ugly / fragile / opinionated / incomplete so I better refrain
from making [PROPOSAL] threads here :)
Mike Pall
2014-06-17 07:46:59 UTC
Permalink
Post by Daniel Kolesa
I'm implementing a language on top of LuaJIT and I would like to implement
a few things on top of the metatable system as part of the language's
runtime, however there's a problem: debug.getmetatable is not compiled...
I'm not sure it's a good idea to subvert the metatable system.
Quite a bit of optimization has gone into it. And it's tricky to
fully imitate metamethod lookups on your own. Maybe there's a
different way to achieve your goals?
Post by Daniel Kolesa
Is there any chance these two functions (or at least debug.getmetatable)
will get compiled?
Technically, yes. But I want to avoid adding code for edge cases,
since it increases complexity for little gain.

--Mike
Daniel Kolesa
2014-06-17 08:50:03 UTC
Permalink
Post by Daniel Kolesa
Post by Daniel Kolesa
I'm implementing a language on top of LuaJIT and I would like to
implement
Post by Daniel Kolesa
a few things on top of the metatable system as part of the language's
runtime, however there's a problem: debug.getmetatable is not compiled...
I'm not sure it's a good idea to subvert the metatable system.
Quite a bit of optimization has gone into it. And it's tricky to
fully imitate metamethod lookups on your own. Maybe there's a
different way to achieve your goals?
I want to implement a few extra metamethods. Is there any other way you can
think of? (other than modifying LuaJIT, which I specifically want to avoid)
Post by Daniel Kolesa
Post by Daniel Kolesa
Is there any chance these two functions (or at least debug.getmetatable)
will get compiled?
Technically, yes. But I want to avoid adding code for edge cases,
since it increases complexity for little gain.
Katlogic has already implemented it with pretty little new code here (and
in a non-invasive way that could be patched into luajit directly):
https://github.com/katlogic/ljx/commit/882ce332 ,
https://github.com/katlogic/ljx/commit/a875c96 Technically, I only care
about the getmetatable part; compiled debug.setmetatable is of no use for
me.
Post by Daniel Kolesa
--Mike
Daniel
Coda Highland
2014-06-17 13:52:49 UTC
Permalink
Post by Daniel Kolesa
Post by Mike Pall
Post by Daniel Kolesa
I'm implementing a language on top of LuaJIT and I would like to implement
a few things on top of the metatable system as part of the language's
runtime, however there's a problem: debug.getmetatable is not compiled...
I'm not sure it's a good idea to subvert the metatable system.
Quite a bit of optimization has gone into it. And it's tricky to
fully imitate metamethod lookups on your own. Maybe there's a
different way to achieve your goals?
I want to implement a few extra metamethods. Is there any other way you can
think of? (other than modifying LuaJIT, which I specifically want to avoid)
There's nothing exceptionally special about most metamethods. It's
just a contract. If you're adding new code that needs new contracts,
you can define new functions, SAY that they're metamethods, and just
run from there.

As an example, plenty of people define a __type metafield to go with a
wrapper around type() to allow creating user-defined types.

/s/ Adam
Daniel Kolesa
2014-06-17 17:38:20 UTC
Permalink
Post by Daniel Kolesa
Post by Daniel Kolesa
Post by Mike Pall
Post by Daniel Kolesa
I'm implementing a language on top of LuaJIT and I would like to implement
a few things on top of the metatable system as part of the language's
runtime, however there's a problem: debug.getmetatable is not compiled...
I'm not sure it's a good idea to subvert the metatable system.
Quite a bit of optimization has gone into it. And it's tricky to
fully imitate metamethod lookups on your own. Maybe there's a
different way to achieve your goals?
I want to implement a few extra metamethods. Is there any other way you
can
Post by Daniel Kolesa
think of? (other than modifying LuaJIT, which I specifically want to
avoid)
There's nothing exceptionally special about most metamethods. It's
just a contract. If you're adding new code that needs new contracts,
you can define new functions, SAY that they're metamethods, and just
run from there.
As an example, plenty of people define a __type metafield to go with a
wrapper around type() to allow creating user-defined types.
/s/ Adam
I know what metamethods are and how they work, and that's exactly what i'm
doing, my concern is performance - i need a fast way to retrieve the
metatable, right now it slow.

Daniel
Coda Highland
2014-06-17 17:42:53 UTC
Permalink
Post by Daniel Kolesa
I know what metamethods are and how they work, and that's exactly what i'm
doing, my concern is performance - i need a fast way to retrieve the
metatable, right now it slow.
Oh, I see. I misunderstood what you had said. That does make sense.

/s/ Adam
Coda Highland
2014-06-17 19:23:29 UTC
Permalink
Post by Daniel Kolesa
Post by Coda Highland
There's nothing exceptionally special about most metamethods. It's
just a contract. If you're adding new code that needs new contracts,
you can define new functions, SAY that they're metamethods, and just
run from there.
As an example, plenty of people define a __type metafield to go with a
wrapper around type() to allow creating user-defined types.
/s/ Adam
I know what metamethods are and how they work, and that's exactly what i'm
doing, my concern is performance - i need a fast way to retrieve the
metatable, right now it slow.
Daniel
It occurs to me that you could optimize this case without needing to
modify LuaJIT. You could maintain a table with weak keys mapping
tables to their metatables. If you control the construction of the
table, you can store the mapping yourself; if the table isn't found in
there, you can use debug.setmetatable once and cache the result,
thereby avoiding the non-compiled case as frequently as possible.

It's a little bit workaround-ish but that kind of technique is pretty
common anyway.

/s/ Adam
Karel Tuma
2014-06-17 19:07:21 UTC
Permalink
Post by Daniel Kolesa
Post by Mike Pall
Technically, yes. But I want to avoid adding code for edge cases,
since it increases complexity for little gain.
Katlogic has already implemented it with pretty little new code here (and
The feel I'm getting is that incorporating changes like this one would
open the floodgates for microoptimizations. The problem is not trivial
mods like this per se, but aggresively compiling every little edge
case would still triple the size of *record.c / lj_asm.c.

Compared to rather inconclusive benefits of compiling debug.*,
things like patterns+string.match [1] are better candidates
from that perspective since the benefit shows up across the board.

Note that non-trivial things like that tend to be invasive
and most likely fall short technically on my part.

[1]
https://github.com/katlogic/ljx/commit/27000d124b748ad9db9f9d88fd08ecaf9411d6b6
https://github.com/katlogic/ljx/commit/77d03fae1b6a91f094de4431ff4f745236511a93
Mike Pall
2014-06-18 10:43:32 UTC
Permalink
Post by Daniel Kolesa
Katlogic has already implemented it with pretty little new code here (and
https://github.com/katlogic/ljx/commit/882ce332 ,
https://github.com/katlogic/ljx/commit/a875c96 Technically, I only care
about the getmetatable part; compiled debug.setmetatable is of no use for
me.
Committed. Thanks to Karel!

--Mike
Daniel Kolesa
2014-06-18 11:22:30 UTC
Permalink
Post by Mike Pall
Post by Daniel Kolesa
Katlogic has already implemented it with pretty little new code here (and
https://github.com/katlogic/ljx/commit/882ce332 ,
https://github.com/katlogic/ljx/commit/a875c96 Technically, I only care
about the getmetatable part; compiled debug.setmetatable is of no use for
me.
Committed. Thanks to Karel!
--Mike
Daniel

Loading...