Lua 소스 코드 읽 기 (7) 명령 - > Lua 명령 실행 과정

3536 단어
Lua 명령 실행 과정
지난 절 Lua 스 택 의 기반 이 있 습 니 다. 이 절 은 Lua 명령 집행 과정 에서 관련 된 관건 적 인 데이터 구조, 절차 와 해당 하 는 함 수 를 설명 합 니 다.
분석 Lua 코드 를 저장 한 후에 관련 된 opcode 를 생 성 합 니 다. Proto 구조 체 에 저 장 된 것 입 니 다. 하나의 Lua 파일 은 전체 Proto 구조 체 를 가지 고 있 습 니 다. 만약 에 내부 에 정의 함수 가 있다 면 모든 함수 에 해당 하 는 Proto 구조 체 가 있 습 니 다. 여기 에는 명령 집행 과 관련 된 몇 명의 구성원 만 열거 되 어 있 습 니 다.
Tvalue * k: 상수 의 배열 을 저장 합 니 다. Instruction * code: 명령 을 저장 하 는 배열 입 니 다. struct Proto * * p: 이 Proto 에서 정의 하 는 함수 와 관련 된 Proto 데이터 입 니 다. Proto 구조 체 는 Lua 파일 을 분석 한 결과 물이 기 때문에 분석 단계 에서 중간 에 사 용 된 임시 데 이 터 를 저장 하고 그 안에 데 이 터 를 기록 해 야 합 니 다. 분석 이 끝 난 후에 이 분석 과정 에서 임시로 사 용 된 데 이 터 는 더 이상 사용 하지 않 습 니 다. 이 구조 체 는 Func State 입 니 다. 여기 서 명령 과 관련 된 구성원 만 열거 합 니 다.
Proto * f: 연 결 된 Proto 구조 체. int pc: 현재 pc 인덱스, CPU 가 명령 을 실행 할 때의 카운터 와 유사 합 니 다. 이 변 수 는 현재 Proto 의 code 배열 에 얼마나 많은 데 이 터 를 기 록 했 는 지 저장 하 는 데 사 용 됩 니 다. int freereg: 현재 사용 가능 한 레지스터 인덱스 입 니 다. 이상 의 준비 가 되 어 있 습 니 다. Proto 에 명령 을 언제 기록 하 는 지 보 겠 습 니 다. Lua 코드 에서 서로 다른 명령 형식 에 몇 가지 함 수 를 제공 하 였 습 니 다. luaKcodeABx/luaK_codeABC 등, 이 함수 들 은 결국 함수 luaK 를 호출 합 니 다.code:
(lcode.c)
797 static int luaK_code (FuncState *fs, Instruction i, int line) {
798   Proto *f = fs->f;
803   f->code[fs->pc] = i;
808   return fs->pc++;
809 }

앞에서 분석 한 바 와 같이 luaKcode 는 Proto 구조 체 의 code 배열 에 명령 을 기록 하고 code 배열 의 다음 쓰기 가능 한 위 치 를 되 돌려 줍 니 다. 이것 은 FuncState 의 pc 구성원 으로 저 장 됩 니 다.
다음은 Lua 가상 컴퓨터 가 모든 명령 을 진정 으로 수행 하 는 함수 luaV 를 살 펴 보 겠 습 니 다.execute:
(lvm.c)
343 #define RA(i)   (base+GETARG_A(i))
344 /* to be used after possible stack reallocation */
345 #define RB(i)   check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
346 #define RC(i)   check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
347 #define RKB(i)  check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
348     ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
349 #define RKC(i)  check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
350     ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
351 #define KBx(i)  check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))

373 void luaV_execute (lua_State *L, int nexeccalls) {
374   LClosure *cl;
375   StkId base;
376   TValue *k;
377   const Instruction *pc;
378  reentry:  /* entry point */
380   pc = L->savedpc;
381   cl = &clvalue(L->ci->func)->l;
382   base = L->base;
383   k = cl->p->k;
384   /* main loop of interpreter */
385   for (;;) {
386     const Instruction i = *pc++;
387     StkId ra;
398     ra = RA(i);
402     switch (GET_OPCODE(i)) {
760     }
761   }
762 }

우선 함수 luaVexecute 에서 변수 pc 는 luaState 의 savedpc, 앞 에 나 타 났 던 luaD 입 니 다.precall 함수 에서 값 을 부여 하 는 것 은 함수 스 택 의 관련 변수 에 만 관심 을 가 질 뿐 이 줄 코드 를 열거 합 니 다.
(ldo.c)
264 int luaD_precall (lua_State *L, StkId func, int nresults) {
293     L->savedpc = p->code;  /* starting point */

그 다음 에 이 함수 의 주 체 는 큰 순환 이다. pc 포인터 가 가리 키 는 명령 을 순서대로 꺼 내 서 해석 하고 집행 하 는 것 이다. 그리고 RA / RB / RC 등 몇 개의 매크로 를 주의해 야 한다. 그 데 이 터 는 모두 base, 즉 함수 스 택 의 시작 주소 로 얻 은 것 이다. 따라서 지난 함수 스 택 의 내용 과 이 절의 내용 을 결합 하면 명확 한 결론 을 얻 을 수 있다.
     ,                        ,                         ,                  .  Lua                    ,          ,   base/top   .

명령 에 상대 적 인 오프셋 을 저장 하지만 하나의 값 을 저장 해 야 합 니 다. 현재 함수 스 택 에 얼마나 많은 값 이 할당 되 었 는 지 알 고 있 습 니 다. 이 데 이 터 를 저장 하 는 변 수 는 바로 Func State 구조 체 의 freereg 입 니 다.
그래서 그림 3.1 에서 가장 오른쪽 은 R [0]... R [n] 의 의 미 를 나타 낸다.

좋은 웹페이지 즐겨찾기