Inline-Lua

 view release on metacpan or  search on metacpan

ffi/target/release/build/mlua-sys-6a99a2ae50f12319/out/luajit-build/build/src/lj_err.c  view on Meta::CPAN

** LuaJIT can either use internal or external frame unwinding:
**
** - Internal frame unwinding (INT) is free-standing and doesn't require
**   any OS or library support.
**
** - External frame unwinding (EXT) uses the system-provided unwind handler.
**
** Pros and Cons:
**
** - EXT requires unwind tables for *all* functions on the C stack between
**   the pcall/catch and the error/throw. C modules used by Lua code can
**   throw errors, so these need to have unwind tables, too. Transitively
**   this applies to all system libraries used by C modules -- at least
**   when they have callbacks which may throw an error.
**
** - INT is faster when actually throwing errors, but this happens rarely.
**   Setting up error handlers is zero-cost in any case.
**
** - INT needs to save *all* callee-saved registers when entering the
**   interpreter. EXT only needs to save those actually used inside the
**   interpreter. JIT-compiled code may need to save some more.
**
** - EXT provides full interoperability with C++ exceptions. You can throw
**   Lua errors or C++ exceptions through a mix of Lua frames and C++ frames.
**   C++ destructors are called as needed. C++ exceptions caught by pcall
**   are converted to the string "C++ exception". Lua errors can be caught
**   with catch (...) in C++.
**
** - INT has only limited support for automatically catching C++ exceptions
**   on POSIX systems using DWARF2 stack unwinding. Other systems may use
**   the wrapper function feature. Lua errors thrown through C++ frames
**   cannot be caught by C++ code and C++ destructors are not run.
**
** - EXT can handle errors from internal helper functions that are called
**   from JIT-compiled code (except for Windows/x86 and 32 bit ARM).
**   INT has no choice but to call the panic handler, if this happens.
**   Note: this is mainly relevant for out-of-memory errors.
**
** EXT is the default on all systems where the toolchain produces unwind
** tables by default (*). This is hard-coded and/or detected in src/Makefile.
** You can thwart the detection with: TARGET_XCFLAGS=-DLUAJIT_UNWIND_INTERNAL
**
** INT is the default on all other systems.
**
** EXT can be manually enabled for toolchains that are able to produce
** conforming unwind tables:
**   "TARGET_XCFLAGS=-funwind-tables -DLUAJIT_UNWIND_EXTERNAL"
** As explained above, *all* C code used directly or indirectly by LuaJIT
** must be compiled with -funwind-tables (or -fexceptions). C++ code must
** *not* be compiled with -fno-exceptions.
**
** If you're unsure whether error handling inside the VM works correctly,
** try running this and check whether it prints "OK":
**
**   luajit -e "print(select(2, load('OK')):match('OK'))"
**
** (*) Originally, toolchains only generated unwind tables for C++ code. For
** interoperability reasons, this can be manually enabled for plain C code,
** too (with -funwind-tables). With the introduction of the x64 architecture,
** the corresponding POSIX and Windows ABIs mandated unwind tables for all
** code. Over the following years most desktop and server platforms have
** enabled unwind tables by default on all architectures. OTOH mobile and
** embedded platforms do not consistently mandate unwind tables.
*/

/* -- Error messages ------------------------------------------------------ */

/* Error message strings. */
LJ_DATADEF const char *lj_err_allmsg =
#define ERRDEF(name, msg)	msg "\0"
#include "lj_errmsg.h"
;

/* -- Internal frame unwinding -------------------------------------------- */

/* Unwind Lua stack and move error message to new top. */
LJ_NOINLINE static void unwindstack(lua_State *L, TValue *top)
{
  lj_func_closeuv(L, top);
  if (top < L->top-1) {
    copyTV(L, top, L->top-1);
    L->top = top+1;
  }
  lj_state_relimitstack(L);
}

/* Unwind until stop frame. Optionally cleanup frames. */
static void *err_unwind(lua_State *L, void *stopcf, int errcode)
{
  TValue *frame = L->base-1;
  void *cf = L->cframe;
  while (cf) {
    int32_t nres = cframe_nres(cframe_raw(cf));
    if (nres < 0) {  /* C frame without Lua frame? */
      TValue *top = restorestack(L, -nres);
      if (frame < top) {  /* Frame reached? */
	if (errcode) {
	  L->base = frame+1;
	  L->cframe = cframe_prev(cf);
	  unwindstack(L, top);
	}
	return cf;
      }
    }
    if (frame <= tvref(L->stack)+LJ_FR2)
      break;
    switch (frame_typep(frame)) {
    case FRAME_LUA:  /* Lua frame. */
    case FRAME_LUAP:
      frame = frame_prevl(frame);
      break;
    case FRAME_C:  /* C frame. */
    unwind_c:
#if LJ_UNWIND_EXT
      if (errcode) {
	L->base = frame_prevd(frame) + 1;
	L->cframe = cframe_prev(cf);
	unwindstack(L, frame - LJ_FR2);
      } else if (cf != stopcf) {
	cf = cframe_prev(cf);
	frame = frame_prevd(frame);



( run in 0.531 second using v1.01-cache-2.11-cpan-e1769b4cff6 )