Lunatic: fixups and debugging helpers.

- add LuaJIT's 'v' module printing trace info
- translator: fix game function name definitions
- revert math.fmod -> math.modf, they are different!
- disable JIT compilation for a function we're getting strange crashes with
- Make some of DukePlayer_t's members 'bool' on the Lua side. It's way
  too easy to write something like "ps.jetpack_on" where "ps.jetpack_on~=0"
  was meant. [Background: Kyle873 observed that Duke was always floating.]
- Error out if looping in our_module(). I find this behavior more logical
  than returning true.
- fix a couple of missed FORBID variables

git-svn-id: https://svn.eduke32.com/eduke32@3530 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-02-28 17:30:04 +00:00
parent 677c585b72
commit 1606c17a77
8 changed files with 240 additions and 25 deletions

View file

@ -160,6 +160,7 @@ ifneq (0,$(LUNATIC))
$(OBJ)/luaJIT_BC_bcheck.$o \
$(OBJ)/luaJIT_BC_xmath.$o \
$(OBJ)/luaJIT_BC_defs.$o \
$(OBJ)/luaJIT_BC_v.$o \
# now, take care of having the necessary symbols (sector, wall, etc.) in the
# executable no matter what the debugging level

View file

@ -2198,6 +2198,8 @@ void C_DefineGameFuncName(int32_t idx, const char *name)
Bstrncpyz(gamefunctions[idx], name, MAXGAMEFUNCLEN);
Bstrncpyz(keydefaults[3*idx], name, MAXGAMEFUNCLEN);
hash_add(&h_gamefuncs, gamefunctions[idx], idx, 0);
}
#endif

View file

@ -3,6 +3,7 @@
local require = require
local ffi = require("ffi")
local ffiC = ffi.C
local jit = require("jit")
-- Lua C API functions, this comes from El_PushCFunctions() in lunatic_game.c.
local CF = CF
@ -323,16 +324,15 @@ function _div(a,b)
if (b==0) then
error("divide by zero", 2)
end
-- NOTE: math.modf() is compiled, math.fmod() is not:
-- http://wiki.luajit.org/NYI#Math-Library
return (a - math.modf(a,b))/b
-- NOTE: don't confuse with math.modf!
return (a - math.fmod(a,b))/b
end
function _mod(a,b)
if (b==0) then
error("mod by zero", 2)
end
return (math.modf(a,b))
return (math.fmod(a,b))
end
-- Sect_ToggleInterpolation() clone
@ -722,6 +722,11 @@ function _gametext(tilenum, x, y, qnum, shade, pal, orientation,
ffiC.G_PrintGameText(0, tilenum, bit.arshift(x,1), y, cstr, shade, pal,
orientation, cx1, cy1, cx2, cy2, zoom)
end
-- XXX: JIT-compiling FFI calls to G_PrintGameText crashes LuaJIT somewhere in
-- its internal routines. I'm not sure who is to blame here but I suspect we
-- have some undefined behavior somewhere. Reproducible with DukePlus 2.35 on
-- x86 when clicking wildly through its menu.
jit.off(_gametext)
local D = {
-- TODO: dynamic tile remapping

View file

@ -34,8 +34,8 @@ local gv_access = {}
-- accessible through the "gv" global. The "defs_common" module will
-- use this function.
--
-- Notes: do not declare multiple pointers on one line (this is bad:
-- "int32_t *a, *b"). Do not name array arguments (or add a space
-- Notes: do not declare multiple scalars on one line (this is bad:
-- "int32_t a, b"). Do not name array arguments (or add a space
-- between the identifier and the '[' instead).
function decl(str, ...)
-- NOTE that the regexp also catches non-array/non-function identifiers
@ -166,6 +166,11 @@ bcarray.new("int16_t", 64, "loogie", "int16_x_64")
bcarray.new("int16_t", ffiC.MAX_WEAPONS, "weapon", "int16_x_MAX_WEAPONS")
bcarray.new("int16_t", ffiC.GET_MAX, "inventory", "int16_x_GET_MAX")
-- NOTE: writing e.g. "ps.jetpack_on" in Lua when "ps.jetpack_on~=0" was meant
-- is probably one of the most commonly committed errors, so we make it a bool
-- type instead of uint8_t. The only issue is that if CON coders used these
-- fields to store more than just one bit, we're in trouble.
-- This will need to be documented and frozen for release.
local DUKEPLAYER_STRUCT = [[
__attribute__((packed)) struct {
vec3_t pos, opos, vel, npos;
@ -223,24 +228,35 @@ __attribute__((packed)) struct {
uint8_t max_secret_rooms, secret_rooms;
uint8_t frag, fraggedself, quick_kick, last_quick_kick;
uint8_t return_to_center, reloading;
uint8_t return_to_center;
bool reloading;
const uint8_t weapreccnt;
uint8_t aim_mode, auto_aim, weaponswitch, movement_lock, team;
uint8_t tipincs, hbomb_hold_delay, frag_ps, kickback_pic;
uint8_t gm, on_warping_sector, footprintcount, hurt_delay;
uint8_t hbomb_on, jumping_toggle, rapid_fire_hold, on_ground;
uint8_t gm;
bool on_warping_sector;
uint8_t footprintcount, hurt_delay;
bool hbomb_on, jumping_toggle, rapid_fire_hold, on_ground;
// NOTE: there's array indexing with inven_icon, but always after a
// bound check:
uint8_t inven_icon, buttonpalette, over_shoulder_on, show_empty_weapon;
uint8_t inven_icon, buttonpalette;
bool over_shoulder_on;
uint8_t show_empty_weapon;
uint8_t jetpack_on, spritebridge, lastrandomspot;
uint8_t scuba_on, footprintpal, heat_on, invdisptime;
bool jetpack_on, spritebridge;
uint8_t lastrandomspot; // unused
bool scuba_on;
uint8_t footprintpal;
bool heat_on;
uint8_t invdisptime;
uint8_t holster_weapon, falling_counter, footprintshade;
bool holster_weapon;
uint8_t falling_counter, footprintshade;
uint8_t refresh_inventory, last_full_weapon;
uint8_t toggle_key_flag, knuckle_incs, knee_incs, access_incs;
bool toggle_key_flag;
uint8_t knuckle_incs, knee_incs, access_incs;
uint8_t walking_snd_toggle, palookup, hard_landing, fist_incs;
int8_t numloogs, loogcnt, scream_voice;
@ -920,7 +936,7 @@ local player_mt = {
set_curr_weapon = function(p, weap)
check_weapon_idx(weap)
p.curr_weapon = weap
ffi.cast(player_ptr_ct, p).curr_weapon = weap
end,
get_inv_amount = function(p, inv)
@ -1217,9 +1233,14 @@ local function our_require(modname, ...)
--- search user modules
if (package_loaded[modname] ~= nil) then
local omod = package_loaded[modname]
if (omod ~= nil) then
if (omod==true) then
error("Loop while loading modules", ERRLEV-1)
end
-- already loaded
return package_loaded[modname]
return omod
end
local modfn = modname .. ".lua"
@ -1624,6 +1645,7 @@ end
-- REMOVE this for release
DBG_ = {}
DBG_.debug = require("debug")
DBG_.printkv = printkv
DBG_.loadstring = loadstring
DBG_.serializeGamevars = serializeGamevars

View file

@ -6,17 +6,22 @@
local ffi = require("ffi")
local ffiC = ffi.C
local bit = require("bit")
-- Lunatic debugging:
-- 1: pront diagnostic information
-- 2: also disable JIT compilation
-- Lunatic debugging (mostly bitfield):
-- ~=0: print diagnostic information
-- 2: disable JIT compilation
-- 4: load LuaJIT's 'v' module, printing trace info
ffi.cdef "enum { _DEBUG_LUNATIC=1 }"
if (ffiC._DEBUG_LUNATIC >= 2) then
if (bit.band(ffiC._DEBUG_LUNATIC, 2)~=0) then
require("jit").off()
end
local bit = require("bit")
if (bit.band(ffiC._DEBUG_LUNATIC, 4)~=0) then
require("v").on()
end
local math = require("math")
local string = require("string")
local table = require("table")
@ -159,7 +164,10 @@ assert(ffi.alignof("palette_t")==1)
local vec3_ct = ffi.typeof("vec3_t")
local hitdata_ct = ffi.typeof("hitdata_t")
decl[[const int32_t engine_main_arrays_are_static, engine_v8;]]
decl[[
const int32_t engine_main_arrays_are_static;
const int32_t engine_v8;
]]
--== Engine data and functions ==--
@ -233,7 +241,8 @@ const int32_t windowx1, windowy1, windowx2, windowy2;
]]
decl[[
int32_t yxaspect, viewingrange;
int32_t yxaspect;
int32_t viewingrange;
int32_t spritesortcnt;
int32_t guniqhudid;
const int32_t rendmode;

View file

@ -406,6 +406,14 @@ gameevent("DISPLAYROOMS",
end
)
gameevent("DISPLAYREST", function()
for i=0,10 do
for j=1,100 do
con._gametext(2822, j, i, 12, 0, 0, 16, 0,0,gv.xdim,gv.ydim,8192)
end
end
end)
local CS = sprite.CSTAT
gameevent("ANIMATESPRITES",

View file

@ -0,0 +1,167 @@
----------------------------------------------------------------------------
-- Verbose mode of the LuaJIT compiler.
--
-- Copyright (C) 2005-2013 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h
----------------------------------------------------------------------------
--
-- This module shows verbose information about the progress of the
-- JIT compiler. It prints one line for each generated trace. This module
-- is useful to see which code has been compiled or where the compiler
-- punts and falls back to the interpreter.
--
-- Example usage:
--
-- luajit -jv -e "for i=1,1000 do for j=1,1000 do end end"
-- luajit -jv=myapp.out myapp.lua
--
-- Default output is to stderr. To redirect the output to a file, pass a
-- filename as an argument (use '-' for stdout) or set the environment
-- variable LUAJIT_VERBOSEFILE. The file is overwritten every time the
-- module is started.
--
-- The output from the first example should look like this:
--
-- [TRACE 1 (command line):1 loop]
-- [TRACE 2 (1/3) (command line):1 -> 1]
--
-- The first number in each line is the internal trace number. Next are
-- the file name ('(command line)') and the line number (':1') where the
-- trace has started. Side traces also show the parent trace number and
-- the exit number where they are attached to in parentheses ('(1/3)').
-- An arrow at the end shows where the trace links to ('-> 1'), unless
-- it loops to itself.
--
-- In this case the inner loop gets hot and is traced first, generating
-- a root trace. Then the last exit from the 1st trace gets hot, too,
-- and triggers generation of the 2nd trace. The side trace follows the
-- path along the outer loop and *around* the inner loop, back to its
-- start, and then links to the 1st trace. Yes, this may seem unusual,
-- if you know how traditional compilers work. Trace compilers are full
-- of surprises like this -- have fun! :-)
--
-- Aborted traces are shown like this:
--
-- [TRACE --- foo.lua:44 -- leaving loop in root trace at foo:lua:50]
--
-- Don't worry -- trace aborts are quite common, even in programs which
-- can be fully compiled. The compiler may retry several times until it
-- finds a suitable trace.
--
-- Of course this doesn't work with features that are not-yet-implemented
-- (NYI error messages). The VM simply falls back to the interpreter. This
-- may not matter at all if the particular trace is not very high up in
-- the CPU usage profile. Oh, and the interpreter is quite fast, too.
--
-- Also check out the -jdump module, which prints all the gory details.
--
------------------------------------------------------------------------------
-- Cache some library functions and objects.
local jit = require("jit")
assert(jit.version_num == 20001, "LuaJIT core/library version mismatch")
local jutil = require("jit.util")
local vmdef = require("jit.vmdef")
local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo
local type, format = type, string.format
local stdout, stderr = io.stdout, io.stderr
-- Active flag and output file handle.
local active, out
------------------------------------------------------------------------------
local startloc, startex
local function fmtfunc(func, pc)
local fi = funcinfo(func, pc)
if fi.loc then
return fi.loc
elseif fi.ffid then
return vmdef.ffnames[fi.ffid]
elseif fi.addr then
return format("C:%x", fi.addr)
else
return "(?)"
end
end
-- Format trace error message.
local function fmterr(err, info)
if type(err) == "number" then
if type(info) == "function" then info = fmtfunc(info) end
err = format(vmdef.traceerr[err], info)
end
return err
end
-- Dump trace states.
local function dump_trace(what, tr, func, pc, otr, oex)
if what == "start" then
startloc = fmtfunc(func, pc)
startex = otr and "("..otr.."/"..oex..") " or ""
else
if what == "abort" then
local loc = fmtfunc(func, pc)
if loc ~= startloc then
out:write(format("[TRACE --- %s%s -- %s at %s]\n",
startex, startloc, fmterr(otr, oex), loc))
else
out:write(format("[TRACE --- %s%s -- %s]\n",
startex, startloc, fmterr(otr, oex)))
end
elseif what == "stop" then
local info = traceinfo(tr)
local link, ltype = info.link, info.linktype
if ltype == "interpreter" then
out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n",
tr, startex, startloc))
elseif link == tr or link == 0 then
out:write(format("[TRACE %3s %s%s %s]\n",
tr, startex, startloc, ltype))
elseif ltype == "root" then
out:write(format("[TRACE %3s %s%s -> %d]\n",
tr, startex, startloc, link))
else
out:write(format("[TRACE %3s %s%s -> %d %s]\n",
tr, startex, startloc, link, ltype))
end
else
out:write(format("[TRACE %s]\n", what))
end
out:flush()
end
end
------------------------------------------------------------------------------
-- Detach dump handlers.
local function dumpoff()
if active then
active = false
jit.attach(dump_trace)
if out and out ~= stdout and out ~= stderr then out:close() end
out = nil
end
end
-- Open the output file and attach dump handlers.
local function dumpon(outfile)
if active then dumpoff() end
if not outfile then outfile = os.getenv("LUAJIT_VERBOSEFILE") end
if outfile then
out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
else
out = stderr
end
jit.attach(dump_trace, "trace")
active = true
end
-- Public module functions.
module(...)
on = dumpon
off = dumpoff
start = dumpon -- For -j command line option.

View file

@ -203,6 +203,7 @@ typedef struct {
int16_t transporter_hold;
uint8_t max_secret_rooms, secret_rooms;
// XXX: 255 values for frag(gedself) seems too small.
uint8_t frag, fraggedself, quick_kick, last_quick_kick;
uint8_t return_to_center, reloading, weapreccnt;
uint8_t aim_mode, auto_aim, weaponswitch, movement_lock, team;