[루아2.5] hash mem opcode

3 분 소요

hash.c

hash.c 파일은 사실상 변경 내용이 없습니다.

[2.4]
static int hashindex (Hash *t, Object *ref)		/* hash function */
{
 switch (tag(ref))
 {
  case LUA_T_NIL:
   lua_error ("unexpected type to index table");
   return -1;  /* UNREACHEABLE */
  case LUA_T_NUMBER:
   return (((int)nvalue(ref))%nhash(t));
  case LUA_T_STRING:
   return (int)((tsvalue(ref)->hash)%nhash(t));  /* make it a valid index */
  case LUA_T_FUNCTION:
   return (((IntPoint)ref->value.tf)%nhash(t));
  case LUA_T_CFUNCTION:
   return (((IntPoint)fvalue(ref))%nhash(t));
  case LUA_T_ARRAY:
   return (((IntPoint)avalue(ref))%nhash(t));
  default:  /* user data */
   return (((IntPoint)uvalue(ref))%nhash(t));
 }
}

[2.5]
static int hashindex (Hash *t, Object *ref)		/* hash function */
{
  long int h;
  switch (tag(ref)) {
    case LUA_T_NIL:
      lua_error ("unexpected type to index table");
      h = 0;  /* UNREACHEABLE */
    case LUA_T_NUMBER:
      h = (long int)nvalue(ref); break;
    case LUA_T_STRING:
      h = tsvalue(ref)->hash; break;
    case LUA_T_FUNCTION:
      h = (IntPoint)ref->value.tf; break;
    case LUA_T_CFUNCTION:
      h = (IntPoint)fvalue(ref); break;
    case LUA_T_ARRAY:
      h = (IntPoint)avalue(ref); break;
    default:  /* user data */
      h = (IntPoint)uvalue(ref); break;
  }
  if (h < 0) h = -h;
  return h%nhash(t);  /* make it a valid index */
}

이 정도 차이만 있습니다. 동일 패턴 반복하면서 return 구문을 사용하는 코드를 변수를 사용해서 마지막에 return 한 번만 사용하는 코드로 바꿨습니다.

lua.stx

딱히 중요한 변경은 없습니다.

[2.4]
static void code_float (float n)
{
 CodeFloat code;
 code.f = n;
 code_byte(code.m.c1);
 code_byte(code.m.c2);
 code_byte(code.m.c3);
 code_byte(code.m.c4);
}

[2.5]
static void code_float (real n)
{
  check_space(sizeof(real));
  memcpy(basepc+pc, &n, sizeof(real));
  pc += sizeof(real);
}

모두 이런 스타일입니다. 함수 여러번 호출하는 코드를 memcpy() 하나로 바꿨습니다.

그 외엔 문법 수정인데, 문법 자체를 바꾼 것은 아니고 문법 서술을 바꾼 정도입니다.

mem.c

마찬가지로 코드 정리 수준의 변경 뿐입니다.

[2.4]
void *luaI_malloc (unsigned long size)
{
  void *block = malloc((size_t)size);
  if (block == NULL)
    mem_error();
  return block;
}


void *luaI_realloc (void *oldblock, unsigned long size)
{
  void *block = oldblock ? realloc(oldblock, (size_t)size) :
                           malloc((size_t)size);
  if (block == NULL)
    mem_error();
  return block;
}

[2.5]
void *luaI_realloc (void *oldblock, unsigned long size)
{
  void *block;
  size_t s = (size_t)size;
  if (s != size)
    lua_error("Allocation Error: Block too big");
  block = oldblock ? realloc(oldblock, s) : malloc(s);
  if (block == NULL)
    lua_error(memEM);
  return block;
}

luaI_realloc() 함수 내용을 보면 이미 luaI_malloc() 함수는 필요없습니다. luaI_realloc()에 null을 파라메터로 넘기면 되니까요. 그래서 루아 2.5에서는 luaI_malloc() 함수를 삭제했습니다.

opcode.c

변경한 코드 줄 수는 많지만 모두 동일한 이유로 같은 패턴의 코드 변경입니다. 코드 변경을 유발한 코드는 아래와 같습니다.

[2.4]
static StkId CBase = 0;  /* when Lua calls C or C calls Lua, points to */
                          /* the first slot after the last parameter. */
static int CnResults = 0; /* when Lua calls C, has the number of parameters; */
                         /* when C calls Lua, has the number of results. */

[2.5]
struct C_Lua_Stack {
 StkId base;  /* when Lua calls C or C calls Lua, points to */
              /* the first slot after the last parameter. */
 int num;     /* when Lua calls C, has the number of parameters; */
              /* when C calls Lua, has the number of results. */
};

static struct C_Lua_Stack CLS_current = {0, 0};

루아 2.4에서 각각 독립 변수로 관리하던 CBase 변수와 CnResults 변수를 구조체로 묶어서 C_Lua_Stack 구조체를 만들었습니다. 그래서 루아 2.4에서 반복적으로 두 변수를 같이 사용하던 코드가 구조체를 사용해서 보다 깔끔하게 변했습니다.

[2.4]
static StkId callC (lua_CFunction func, StkId base)
{
  StkId oldBase = CBase;
  int oldCnResults = CnResults;
  StkId firstResult;
  CnResults = (top-stack) - base;
  /* incorporate parameters on the stack */
  CBase = base+CnResults;  /* == top-stack */
  if (lua_callhook)
    callHook(base, LUA_T_CMARK, 0);
  (*func)();
  if (lua_callhook)  /* func may have changed lua_callhook */
    callHook(base, LUA_T_CMARK, 1);
  firstResult = CBase;
  CBase = oldBase;
  CnResults = oldCnResults;
  return firstResult;
}

[2.5]
static StkId callC (lua_CFunction func, StkId base)
{
  struct C_Lua_Stack oldCLS = CLS_current;
  StkId firstResult;
  CLS_current.num = (top-stack) - base;
  /* incorporate parameters on the stack */
  CLS_current.base = base+CLS_current.num;  /* == top-stack */
  if (lua_callhook)
    callHook(base, LUA_T_CMARK, 0);
  (*func)();
  if (lua_callhook)  /* func may have changed lua_callhook */
    callHook(base, LUA_T_CMARK, 1);
  firstResult = CLS_current.base;
  CLS_current = oldCLS;
  return firstResult;
}

이런 패턴입니다. 그러고 보니 루아 코드 전체에서 의미적으로 묶이는 전역 변수들(테이블 포인터와 테이블 갯수 변수 같은..)이 많은데 모두 위 코드 같은 패턴으로 바꾸는 것도 괜찮을 것 같다는 생각이 듭니다.

댓글남기기