aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/src/lj_vmevent.c
blob: 67cc6dc14e631bdf2f922cbfa5093250a376c42b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
** VM event handling.
** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
*/

#include <stdio.h>

#define lj_vmevent_c
#define LUA_CORE

#include "lj_obj.h"
#include "lj_str.h"
#include "lj_tab.h"
#include "lj_state.h"
#include "lj_dispatch.h"
#include "lj_vm.h"
#include "lj_vmevent.h"

ptrdiff_t lj_vmevent_prepare(lua_State *L, VMEvent ev)
{
  global_State *g = G(L);
  GCstr *s = lj_str_newlit(L, LJ_VMEVENTS_REGKEY);
  cTValue *tv = lj_tab_getstr(tabV(registry(L)), s);
  if (tvistab(tv)) {
    int hash = VMEVENT_HASH(ev);
    tv = lj_tab_getint(tabV(tv), hash);
    if (tv && tvisfunc(tv)) {
      lj_state_checkstack(L, LUA_MINSTACK);
      setfuncV(L, L->top++, funcV(tv));
      return savestack(L, L->top);
    }
  }
  g->vmevmask &= ~VMEVENT_MASK(ev);  /* No handler: cache this fact. */
  return 0;
}

void lj_vmevent_call(lua_State *L, ptrdiff_t argbase)
{
  global_State *g = G(L);
  uint8_t oldmask = g->vmevmask;
  uint8_t oldh = hook_save(g);
  int status;
  g->vmevmask = 0;  /* Disable all events. */
  hook_vmevent(g);
  status = lj_vm_pcall(L, restorestack(L, argbase), 0+1, 0);
  if (LJ_UNLIKELY(status)) {
    /* Really shouldn't use stderr here, but where else to complain? */
    L->top--;
    fprintf(stderr, "VM handler failed: %s\n",
	    tvisstr(L->top) ? strVdata(L->top) : "?");
  }
  hook_restore(g, oldh);
  if (g->vmevmask != VMEVENT_NOCACHE)
    g->vmevmask = oldmask;  /* Restore event mask, but not if not modified. */
}