lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Tue, Aug 31, 2010 at 22:23, Mike Pall <mikelu-1008@mike.de> wrote:
> Alexander Gladysh wrote:
>> I use it to get a list of GET/SETGLOBAL instructions from a given
>> function and to get number of upvalues. (Note that in future I'll
>> probably want to traverse the list of upvalues and check if they're
>> allowed...)

>> Is there a way to implement my function (see below) in current LJ2?
>> I'll settle for non-stable API.

> See: http://lua-users.org/lists/lua-l/2009-11/msg00535.html

A lot of magic constants there. I hope that you will mention in the
changelog if you change the API :-)

> The opcodes you're looking for are GGET and GSET. The table
> returned by jit.util.funcinfo() has the field "upvalues", which
> contains the number of upvalues.

Thanks! I had to dig around in the LJ2 source a bit, but looks like I
made it. Won a half of a second by transition to LJ2 :-) (Now an
external tool being launched from the code slows down things, but it
is another story.)

See my implementation below, perhaps it will be useful for someone
else. (It is not completely equivalent to my original code — I did
some refatoring to abstract the actual inspection method.)

Alexander.

  local update_info = function(self)
    method_arguments(self)

    self.info_ = self.info_ or assert(
        jutil.funcinfo(self.chunk_),
        "not a Lua function"
      )
  end

  local update_globals_lists = function(self)
    method_arguments(self)

    if self.gets_ ~= nil then
      assert(self.sets_ ~= nil)
    else
      assert(self.sets_ == nil)

      self.gets_, self.sets_ = { }, { }

      update_info(self)

      local info = self.info_
      local chunk = self.chunk_

      for i = 1, info.bytecodes do
        local ins, m = jutil.funcbc(chunk, i)
        if not ins then
          break -- TODO: ?!
        end

        local oidx = 6 * bit.band(ins, 0xff)
        local opcode = string_sub(bcnames, oidx + 1, oidx + 6)
        if opcode == "GGET  " or opcode == "GSET  " then
          local d = bit.rshift(ins, 16)
          local name = jutil.funck(chunk, -d - 1)

          local list = (opcode == "GGET  ") and self.gets_ or self.sets_

          local global = list[name]
          if not global then
            global = { }
            list[name] = global
          end

          global[#global + 1] =
          {
            line = jutil.funcinfo(chunk, i).currentline;
            source = info.source;
          }
        end
      end
    end
  end