Lua1.1 Virtual Machine command analysis (1)

Source: Internet
Author: User
Tags switch case

After the syntax analysis lua_parse, call lua_execute to execute the bytecode generated by the syntax analysis.
The VM command is an enumeration type, that is, opcode in opcode. h. The switch case in lua_execute shows the corresponding operation of the command.
> Pushnil

   case PUSHNIL: tag(top++) = T_NIL; break;

Set the object type at the top of the stack to t_nil. This stack is the stack that previously described as the interaction between Lua and C.

> Push0, push1, push2

   case PUSH0: tag(top) = T_NUMBER; nvalue(top++) = 0; break;   case PUSH1: tag(top) = T_NUMBER; nvalue(top++) = 1; break;   case PUSH2: tag(top) = T_NUMBER; nvalue(top++) = 2; break;

Set the object type at the top of the stack to t_number and the value to 0/1/2. This is the command optimization, put the operands in the command, so that the command is shorter and the execution is faster.
These commands are the optimized version of pushbyte commands, or the special version is more suitable.

> Pushbyte

   case PUSHBYTE: tag(top) = T_NUMBER; nvalue(top++) = *pc++; break;

Set the object type at the top of the stack to t_number. The value is obtained from the current bytecode (that is, a byte at the PC pointer. The value occupies one byte in the bytecode.

> Pushword

   case PUSHWORD:   {    CodeWord code;    get_word(code,pc);    tag(top) = T_NUMBER; nvalue(top++) = code.w;   }   break;

Set the object type at the top of the stack to t_number. The value is obtained from the current bytecode (that is, two bytes at the PC pointer. The value occupies two bytes in the bytecode.
Get_word is the opposite process of code_word in Y. Tab. C. Codeword is a consortium.

   typedef union   {    struct {char c1; char c2;} m;    Word w;   } CodeWord;

In code_word

   static void code_word (Word n)   {    CodeWord code;    code.w = n;    code_byte(code.m.c1);    code_byte(code.m.c2);   }

We can see that the value is set to W at the time of setting, and then code_byte is called to generate bytecode for the two bytes of W respectively.
Since codeword is a consortium, W and m here are the same piece of memory, so code_word can be correctly executed as expected.
This kind of Federated operation is a small technique in C language. For example, this technique can be used to test the byte sequence (for example, whether your processor architecture is a large-end or a small-End sequence.

> Pushfloat

   case PUSHFLOAT:   {    CodeFloat code;    get_float(code,pc);    tag(top) = T_NUMBER; nvalue(top++) = code.f;   }   break;

Set the object type at the top of the stack to t_number. The value is obtained from the current bytecode (that is, the four bytes at the PC pointer. The value occupies four bytes in the bytecode.
The get_float is the same as the get_word above.

> Pushstring

   case PUSHSTRING:   {    CodeWord code;    get_word(code,pc);    tag(top) = T_STRING; svalue(top++) = lua_constant[code.w];   }   break;

Set the object type at the top of the stack to t_string. The value is obtained from the constant table, and the subscript is obtained from the current bytecode. The subscript occupies two bytes.

> Pushlocal0, pushlocal1, pushlocal2, pushlocal3, pushlocal4,
Pushlocal5, pushlocal6, pushlocal7, pushlocal8, pushlocal9,

   case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2:   case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5:   case PUSHLOCAL6: case PUSHLOCAL7: case PUSHLOCAL8:   case PUSHLOCAL9: *top++ = *(base + (int)(opcode-PUSHLOCAL0)); break;

Set the object at the top of the stack to the local variable N (0 <= n <= 9), which is also the command optimization. Subtract the opcode of the current command from pushlocal0 to get the offset n.
The local variable is the offset from the base of the stack. It can also be understood as the subscript of the array.
These commands are the special version of pushlocal.

> Pushlocal

   case PUSHLOCAL: *top++ = *(base + (*pc++)); break;

Set the object at the top of the stack to the local variable N (the offset of N is obtained from the bytecode ).

> Pushglobal,

   case PUSHGLOBAL:   {    CodeWord code;    get_word(code,pc);    *top++ = s_object(code.w);   }   break;

Set the object at the top of the stack to the global variable n (n is obtained from the global symbol table, and its subscript is obtained from the bytecode, which occupies two bytes ).

> Pushindexed,

   case PUSHINDEXED:    --top;    if (tag(top-1) != T_ARRAY)    {     lua_reportbug ("indexed expression not a table");     return 1;    }    {     Object *h = lua_hashdefine (avalue(top-1), top);     if (h == NULL) return 1;     *(top-1) = *h;    }   break;

Set the array element index. The top of the current stack is the element index to be set, and top-1 is the array.
Use lua_hashdefine to set top as an index into an array and return the key-value pair's node value Val address.
Set to top-1 for future use.

> Pushmark

   case PUSHMARK: tag(top++) = T_MARK; break;

Set the object at the top of the stack to t_mark, which is used for marking. For example, when a function is called, a t_mark will be added to the stack after the function is added to the stack.

> Pushobject

   case PUSHOBJECT: *top = *(top-3); top++; break;

Set the objects at the top of the stack to the last 4th objects at the top of the stack.
 

> Storelocal0, storelocal1, storelocal2, storelocal3, storelocal4,
Storelocal5, storelocal6, storelocal7, storelocal8, storelocal9,

   case STORELOCAL0: case STORELOCAL1: case STORELOCAL2:   case STORELOCAL3: case STORELOCAL4: case STORELOCAL5:   case STORELOCAL6: case STORELOCAL7: case STORELOCAL8:   case STORELOCAL9: *(base + (int)(opcode-STORELOCAL0)) = *(--top); break;

Set the local variable N (0 <= n <= 9) as the object at the top of the stack. This is also the command optimization. Subtract the opcode of the current command from storelocal0 to get the offset n.
The local variable is the offset from the base of the stack. It can also be understood as the subscript of the array.
These commands are the special version of storelocal.

> Storelocal

   case STORELOCAL: *(base + (*pc++)) = *(--top); break;

Set the local variable N (the offset of N is obtained from the bytecode) to the object at the top of the stack.

> Storeglobal

   case STOREGLOBAL:   {    CodeWord code;    get_word(code,pc);    s_object(code.w) = *(--top);   }   break;

Set the global variable n (n is obtained from the global symbol table, and its subscript is obtained from the bytecode, which occupies two bytes) as the object at the top of the stack.

> Storeindexed0

   case STOREINDEXED0:    if (tag(top-3) != T_ARRAY)    {     lua_reportbug ("indexed expression not a table");     return 1;    }    {     Object *h = lua_hashdefine (avalue(top-3), top-2);     if (h == NULL) return 1;     *h = *(top-1);    }    top -= 3;   break;

Set the array element. The array is in top-3, the array index is in top-2, and the array value is in top-1.
After the settings are complete, the three objects are output to the stack.

> Storeindexed

   case STOREINDEXED:   {    int n = *pc++;    if (tag(top-3-n) != T_ARRAY)    {     lua_reportbug ("indexed expression not a table");     return 1;    }    {     Object *h = lua_hashdefine (avalue(top-3-n), top-2-n);     if (h == NULL) return 1;     *h = *(top-1);    }    top--;   }   break;

Sets the array element of the specified offset, which is obtained from the bytecode, the array is in the top-3-n, the index is in the top-2-n, and the value is at the top of the stack.
After the setting is complete, the top value of the stack goes out of the stack.

> Storelist0,
Storelist

   case STORELIST0:   case STORELIST:   {    int m, n;    Object *arr;    if (opcode == STORELIST0) m = 0;    else m = *(pc++) * FIELDS_PER_FLUSH;    n = *(pc++);    arr = top-n-1;    if (tag(arr) != T_ARRAY)    {     lua_reportbug ("internal error - table expected");     return 1;    }    while (n)    {     tag(top) = T_NUMBER; nvalue(top) = n+m;     *(lua_hashdefine (avalue(arr), top)) = *(top-1);     top--;     n--;    }   }   break;

Set the array value, m as the subscript, and N as the number of array elements. The array values to be set are all on the stack, and the stack top is the last element.
Therefore, in the while loop, assigning a value to an array is to assign a value to the subscript with a large value, and then assign a value to a small value. Each value is assigned to the stack with a single value.

> Storerecord

   case STORERECORD:   {    int n = *(pc++);    Object *arr = top-n-1;    if (tag(arr) != T_ARRAY)    {     lua_reportbug ("internal error - table expected");     return 1;    }    while (n)    {     CodeWord code;     get_word(code,pc);     tag(top) = T_STRING; svalue(top) = lua_constant[code.w];     *(lua_hashdefine (avalue(arr), top)) = *(top-1);     top--;     n--;    }   }   break;

Assign values to records. n is the number of values to be assigned. The element index to be assigned is obtained from the bytecode, the right value is obtained from the stack, and the stack is obtained after the assignment.
A record refers to a table whose subscript is a constant string, and an array refers to a table whose subscript is an integer. For specific differences, see the manual.

> Adjust

   case ADJUST:   {    Object *newtop = base + *(pc++);    while (top < newtop) tag(top++) = T_NIL;    top = newtop; /* top could be bigger than newtop */   }   break;

Adjust the number of elements on the stack and retrieve the number of elements from the bytecode. If the new stack is higher than the current stack, the element from the current stack to the new stack is left blank.
After a function is called, it is called to adjust the stack. The next bytecode (PC) of adjust is the number of returned function values.
If the number of functions to be returned is greater than the number of actually returned functions, the while completion is null.
(If the number of returned values is less than the actual number, the excess values will be discarded. This is achieved by setting top .)

> Createarray

   case CREATEARRAY:    if (tag(top-1) == T_NIL)     nvalue(top-1) = 101;    else    {     if (tonumber(top-1)) return 1;     if (nvalue(top-1) <= 0) nvalue(top-1) = 101;    }    avalue(top-1) = lua_createarray(nvalue(top-1));    if (avalue(top-1) == NULL)     return 1;    tag(top-1) = T_ARRAY;   break;

Create an array. The number of elements is obtained from the top of the stack. If no number is specified or a negative number is specified, set it to 101. If the top of the stack is not a number, an error occurs.
Create an array, assign values to the top element of the stack, and set the object type on the top of the stack to t_array.
(To be continued)

Lua1.1 Virtual Machine command analysis (1)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.