Skip to content

Commit

Permalink
optimize bulk OP_MOVE(introduce OP_MOVEN)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuin committed May 17, 2015
1 parent 8e24eb1 commit 2e5bfcb
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 8 deletions.
23 changes: 21 additions & 2 deletions compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -1557,8 +1557,16 @@ func patchCode(context *funcContext) { // {{{
if np := int(context.Proto.NumParameters); np > 1 {
maxreg = np
}
for pc, inst := range context.Code.List() {
switch opGetOpCode(inst) {
moven := 0
code := context.Code.List()
for pc := 0; pc < len(code); pc++ {
inst := code[pc]
curop := opGetOpCode(inst)
switch curop {
case OP_CLOSURE:
pc += int(context.Proto.FunctionPrototypes[opGetArgBx(inst)].NumUpvalues)
moven = 0
continue
case OP_SETGLOBAL, OP_SETUPVAL, OP_EQ, OP_LT, OP_LE, OP_TEST,
OP_TAILCALL, OP_RETURN, OP_FORPREP, OP_FORLOOP, OP_TFORLOOP,
OP_SETLIST, OP_CLOSE:
Expand Down Expand Up @@ -1603,6 +1611,17 @@ func patchCode(context *funcContext) { // {{{
maxreg = reg
}
}

// bulk move optimization(reducing op dipatch costs)
if curop == OP_MOVE {
moven++
} else {
if moven > 1 {
context.Code.SetOpCode(pc-moven, OP_MOVEN)
context.Code.SetC(pc-moven, intMin(moven-1, opMaxArgsC))
}
moven = 0
}
}
maxreg++
if maxreg > maxRegisters {
Expand Down
16 changes: 10 additions & 6 deletions opcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ const opMaxArgBx = (1 << opSizeBx) - 1
const opMaxArgSbx = opMaxArgBx >> 1

const (
OP_MOVE int = iota /* A B R(A) := R(B) */
OP_LOADK /* A Bx R(A) := Kst(Bx) */
OP_LOADBOOL /* A B C R(A) := (Bool)B; if (C) pc++ */
OP_LOADNIL /* A B R(A) := ... := R(B) := nil */
OP_GETUPVAL /* A B R(A) := UpValue[B] */
OP_MOVE int = iota /* A B R(A) := R(B) */
OP_MOVEN /* A B R(A) := R(B); followed by R(C) MOVE ops */
OP_LOADK /* A Bx R(A) := Kst(Bx) */
OP_LOADBOOL /* A B C R(A) := (Bool)B; if (C) pc++ */
OP_LOADNIL /* A B R(A) := ... := R(B) := nil */
OP_GETUPVAL /* A B R(A) := UpValue[B] */

OP_GETGLOBAL /* A Bx R(A) := Gbl[Kst(Bx)] */
OP_GETTABLE /* A B C R(A) := R(B)[RK(C)] */
Expand Down Expand Up @@ -126,6 +127,7 @@ type opProp struct {

var opProps = []opProp{
opProp{"MOVE", false, true, opArgModeR, opArgModeN, opTypeABC},
opProp{"MOVEN", false, true, opArgModeR, opArgModeN, opTypeABC},
opProp{"LOADK", false, true, opArgModeK, opArgModeN, opTypeABx},
opProp{"LOADBOOL", false, true, opArgModeU, opArgModeU, opTypeABC},
opProp{"LOADNIL", false, true, opArgModeR, opArgModeN, opTypeABC},
Expand Down Expand Up @@ -173,7 +175,7 @@ func opGetOpCode(inst uint32) int {
}

func opSetOpCode(inst *uint32, opcode int) {
*inst = (*inst & 0x3fffff) | uint32(opcode<<26)
*inst = (*inst & 0x3ffffff) | uint32(opcode<<26)
}

func opGetArgA(inst uint32) int {
Expand Down Expand Up @@ -282,6 +284,8 @@ func opToString(inst uint32) string {
switch op {
case OP_MOVE:
buf += fmt.Sprintf("; R(%v) := R(%v)", arga, argb)
case OP_MOVEN:
buf += fmt.Sprintf("; R(%v) := R(%v); followed by %v MOVE ops", arga, argb, argc)
case OP_LOADK:
buf += fmt.Sprintf("; R(%v) := Kst(%v)", arga, argbx)
case OP_LOADBOOL:
Expand Down
20 changes: 20 additions & 0 deletions vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,26 @@ func init() {
reg.Set(RA, reg.Get(lbase+B))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
reg.Set(lbase+A, reg.Get(lbase+B))
code := cf.Fn.Proto.Code
pc := cf.Pc
for i := 0; i < C; i++ {
inst = code[pc]
pc++
A = int(inst>>18) & 0xff //GETA
B = int(inst & 0x1ff) //GETB
reg.Set(lbase+A, reg.Get(lbase+B))
}
cf.Pc = pc
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK
reg := L.reg
cf := L.currentFrame
Expand Down

0 comments on commit 2e5bfcb

Please sign in to comment.