コード例 #1
0
ファイル: lua_state_cloner.c プロジェクト: Shurakai/SimGrid
/**
 * @brief Copies the function on the top of src to the top of dst.
 *
 * It can be a Lua function or a C function.
 *
 * @param src source state
 * @param dst destination state
 */
static void sglua_copy_function(lua_State* src, lua_State* dst) {

  if (lua_iscfunction(src, -1)) {
    /* it's a C function */

    XBT_DEBUG("It's a C function");
    sglua_stack_dump("src before copying upvalues: ", src);

    /* get the function pointer */
    int function_index = lua_gettop(src);
    lua_CFunction f = lua_tocfunction(src, function_index);

    /* copy the upvalues */
    int i = 0;
    const char* upvalue_name = NULL;
    do {
      i++;
      upvalue_name = lua_getupvalue(src, function_index, i);

      if (upvalue_name != NULL) {
        XBT_DEBUG("Upvalue %s", upvalue_name);
        sglua_move_value(src, dst);
      }
    } while (upvalue_name != NULL);

    sglua_stack_dump("src before copying pointer: ", src);

    /* set the function */
    lua_pushcclosure(dst, f, i - 1);
    XBT_DEBUG("Function pointer copied");
  }
  else {
    /* it's a Lua function: dump it from src */

    s_sglua_buffer_t buffer;
    buffer.capacity = 128; /* an empty function uses 77 bytes */
    buffer.size = 0;
    buffer.data = xbt_new(char, buffer.capacity);

    /* copy the binary chunk from src into a buffer */
    _XBT_GNUC_UNUSED int error = lua_dump(src, sglua_memory_writer, &buffer);
    xbt_assert(!error, "Failed to dump the function from the source state: error %d",
        error);
    XBT_DEBUG("Fonction dumped: %zu bytes", buffer.size);

    /*
    fwrite(buffer.data, buffer.size, buffer.size, stderr);
    fprintf(stderr, "\n");
    */

    /* load the chunk into dst */
    error = luaL_loadbuffer(dst, buffer.data, buffer.size, "(dumped function)");
    xbt_assert(!error, "Failed to load the function into the destination state: %s",
        lua_tostring(dst, -1));
  }
}
コード例 #2
0
ファイル: lua_state_cloner.c プロジェクト: Shurakai/SimGrid
/**
 * @brief Pushes onto the stack a copy of the value on top another stack.
 * If the value is a table, its content is copied recursively.
 *
 * This function allows to move a value between two different global states.
 *
 * @param src the source state (not necessarily maestro)
 * @param dst the destination state
 */
void sglua_copy_value(lua_State* src, lua_State* dst) {

  luaL_checkany(src, -1);                  /* check the value to copy */

  int indent = (lua_gettop(dst) - 1) * 6;
  XBT_DEBUG("%sCopying data %s", sglua_get_spaces(indent), sglua_tostring(src, -1));

  sglua_stack_dump("src before copying a value (should be ... value): ", src);
  sglua_stack_dump("dst before copying a value (should be ...): ", dst);

  switch (lua_type(src, -1)) {

    case LUA_TNIL:
      sglua_copy_nil(src, dst);
      break;

    case LUA_TNUMBER:
      sglua_copy_number(src, dst);
      break;

    case LUA_TBOOLEAN:
      sglua_copy_boolean(src, dst);
      break;

    case LUA_TSTRING:
      sglua_copy_string(src, dst);
      break;

    case LUA_TFUNCTION:
      sglua_copy_function(src, dst);
      break;

    case LUA_TTABLE:
      sglua_copy_table(src, dst);
      break;

    case LUA_TLIGHTUSERDATA:
      sglua_copy_lightuserdata(src, dst);
      break;

    case LUA_TUSERDATA:
      sglua_copy_userdata(src, dst);
      break;

    case LUA_TTHREAD:
      sglua_copy_thread(src, dst);
      break;
  }

  XBT_DEBUG("%sData copied", sglua_get_spaces(indent));

  sglua_stack_dump("src after copying a value (should be ... value): ", src);
  sglua_stack_dump("dst after copying a value (should be ... value): ", dst);
}
コード例 #3
0
ファイル: lua_debug.cpp プロジェクト: fabienchaix/simgrid
/**
 * \brief Like luaL_checkudata, with additional debug logs.
 *
 * This function is for debugging purposes only.
 *
 * \param L a lua state
 * \param ud index of the userdata to check in the stack
 * \param tname key of the metatable of this userdata in the registry
 */
void* sglua_checkudata_debug(lua_State* L, int ud, const char* tname)
{
  XBT_DEBUG("Checking the userdata: ud = %d", ud);
  sglua_stack_dump(L, "my_checkudata: ");
  void* p = lua_touserdata(L, ud);
  lua_getfield(L, LUA_REGISTRYINDEX, tname);
  const void* correct_mt = lua_topointer(L, -1);

  int has_mt = lua_getmetatable(L, ud);
  XBT_DEBUG("Checking the userdata: has metatable ? %d", has_mt);
  const void* actual_mt = nullptr;
  if (has_mt) {
    actual_mt = lua_topointer(L, -1);
    lua_pop(L, 1);
  }
  XBT_DEBUG("Checking the task's metatable: expected %p, found %p", correct_mt, actual_mt);
  sglua_stack_dump(L, "my_checkudata: ");

  if (p == nullptr || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
    XBT_ERROR("Error: Userdata is nullptr, couldn't find metatable or top of stack does not equal element below it.");
  lua_pop(L, 2);
  return p;
}
コード例 #4
0
ファイル: lua_state_cloner.c プロジェクト: Shurakai/SimGrid
/**
 * @brief Copies the table value on top of src to the top of dst.
 *
 * A deep copy of the table is made. If the table has a metatable, the
 * metatable is also copied.
 * If the table comes from maestro and is already known by the destination
 * state, it is not copied again.
 *
 * @param src source state
 * @param dst destination state
 */
static void sglua_copy_table(lua_State* src, lua_State* dst) {

                                  /* src: ... table
                                     dst: ... */
  int indent = lua_gettop(dst) * 6  + 2;

  /* get from maestro the pointer that identifies this table */
  void* table_ptr = sglua_get_maestro_table_ptr(src, -1);
  int known_by_maestro = (table_ptr != NULL);

  if (!known_by_maestro) {
    /* the table didn't come from maestro: nevermind, use the pointer of src */
    table_ptr = (void*) lua_topointer(src, -1);
    XBT_DEBUG("%sMaestro does not know this table",
        sglua_get_spaces(indent));
  }

  if (sglua_is_maestro(src)) {
    /* register the table in maestro itself */
    XBT_DEBUG("%sKeeping track of this table in maestro itself",
        sglua_get_spaces(indent));
    sglua_add_maestro_table(src, -1, table_ptr);
    known_by_maestro = 1;
    xbt_assert(sglua_get_maestro_table_ptr(src, -1) == table_ptr);
  }

  /* to avoid infinite recursion, see if this table is already known by dst */
  sglua_get_table_by_ptr(dst, table_ptr);
                                  /* dst: ... table/nil */
  if (!lua_isnil(dst, -1)) {
    XBT_DEBUG("%sNothing to do: table already known (%p)",
        sglua_get_spaces(indent), table_ptr);
                                  /* dst: ... table */
  }
  else {
    XBT_DEBUG("%sFirst visit of this table (%p)", sglua_get_spaces(indent),
        table_ptr);
                                  /* dst: ... nil */
    lua_pop(dst, 1);
                                  /* dst: ... */

    /* first visit: create the new table in dst */
    lua_newtable(dst);
                                  /* dst: ... table */

    /* mark the table as known right now to avoid infinite recursion */
    sglua_add_maestro_table(dst, -1, table_ptr);
    /* we may have added a table with a non-maestro pointer, but if it was the
     * case, we will remove it later */
    XBT_DEBUG("%sTable marked as known", sglua_get_spaces(indent));
    xbt_assert(sglua_get_maestro_table_ptr(dst, -1) == table_ptr);

    sglua_stack_dump("dst after marking the table as known (should be ... table): ", dst);

    /* copy the metatable if any */
    int has_meta_table = lua_getmetatable(src, -1);
                                  /* src: ... table mt? */
    if (has_meta_table) {
      XBT_DEBUG("%sCopying the metatable", sglua_get_spaces(indent));
                                  /* src: ... table mt */
      sglua_copy_table(src, dst);
                                  /* dst: ... table mt */
      lua_pop(src, 1);
                                  /* src: ... table */
      lua_setmetatable(dst, -2);
                                  /* dst: ... table */
    }
    else {
                                  /* src: ... table */
      XBT_DEBUG("%sNo metatable", sglua_get_spaces(indent));
    }

    sglua_stack_dump("src before traversing the table (should be ... table): ", src);
    sglua_stack_dump("dst before traversing the table (should be ... table): ", dst);

    /* traverse the table of src and copy each element */
    lua_pushnil(src);
                                  /* src: ... table nil */
    while (lua_next(src, -2) != 0) {
                                  /* src: ... table key value */

      XBT_DEBUG("%sCopying table element %s", sglua_get_spaces(indent),
          sglua_keyvalue_tostring(src, -2, -1));

      sglua_stack_dump("src before copying table element (should be ... table key value): ", src);
      sglua_stack_dump("dst before copying table element (should be ... table): ", dst);

      /* copy the key */
      lua_pushvalue(src, -2);
                                  /* src: ... table key value key */
      indent += 2;
      XBT_DEBUG("%sCopying the key part of the table element",
          sglua_get_spaces(indent));
      sglua_move_value(src, dst);
                                  /* src: ... table key value
                                     dst: ... table key */
      XBT_DEBUG("%sCopied the key part of the table element",
          sglua_get_spaces(indent));

      /* copy the value */
      XBT_DEBUG("%sCopying the value part of the table element",
          sglua_get_spaces(indent));
      sglua_move_value(src, dst);
                                  /* src: ... table key
                                     dst: ... table key value */
      XBT_DEBUG("%sCopied the value part of the table element",
          sglua_get_spaces(indent));
      indent -= 2;

      /* set the table element */
      lua_settable(dst, -3);
                                  /* dst: ... table */

      /* the key stays on top of src for next iteration */
      sglua_stack_dump("src before next iteration (should be ... table key): ", src);
      sglua_stack_dump("dst before next iteration (should be ... table): ", dst);

      XBT_DEBUG("%sTable element copied", sglua_get_spaces(indent));
    }
    XBT_DEBUG("%sFinished traversing the table", sglua_get_spaces(indent));
  }

  if (!known_by_maestro) {
    /* actually,it was not a maestro table: forget the pointer */
    sglua_remove_maestro_table(dst, -1, table_ptr);
  }
}