github.com/erikdubbelboer/gopher-lua@v0.0.0-20160512044044-e68f0dc85040/vm.go (about) 1 package lua 2 3 //////////////////////////////////////////////////////// 4 // This file was generated by go-inline. DO NOT EDIT. // 5 //////////////////////////////////////////////////////// 6 7 import ( 8 "fmt" 9 "math" 10 "strings" 11 ) 12 13 func mainLoop(L *LState, baseframe *callFrame) { 14 var inst uint32 15 var cf *callFrame 16 17 if L.stack.IsEmpty() { 18 return 19 } 20 21 L.currentFrame = L.stack.Last() 22 if L.currentFrame.Fn.IsG { 23 callGFunction(L, false) 24 return 25 } 26 27 for { 28 cf = L.currentFrame 29 inst = cf.Fn.Proto.Code[cf.Pc] 30 cf.Pc++ 31 if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { 32 return 33 } 34 } 35 } 36 37 func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start 38 if b == 1 { 39 // this section is inlined by go-inline 40 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 41 { 42 rg := L.reg 43 regm := regv 44 for i := 0; i < n; i++ { 45 rg.array[regm+i] = LNil 46 } 47 rg.top = regm + n 48 } 49 } else { 50 // this section is inlined by go-inline 51 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 52 { 53 rg := L.reg 54 limit := -1 55 for i := 0; i < n; i++ { 56 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 57 rg.array[regv+i] = LNil 58 } else { 59 rg.array[regv+i] = rg.array[tidx] 60 } 61 } 62 rg.top = regv + n 63 } 64 } 65 } // +inline-end 66 67 func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { 68 parent := L.Parent 69 if parent == nil { 70 L.RaiseError("can not yield from outside of a coroutine") 71 } 72 L.G.CurrentThread = parent 73 L.Parent = nil 74 if !L.wrapped { 75 if haserror { 76 parent.Push(LFalse) 77 } else { 78 parent.Push(LTrue) 79 } 80 } 81 L.XMoveTo(parent, nargs) 82 L.stack.Pop() 83 offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase 84 L.currentFrame = L.stack.Last() 85 L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) 86 if kill { 87 L.kill() 88 } 89 } 90 91 func callGFunction(L *LState, tailcall bool) bool { 92 frame := L.currentFrame 93 gfnret := frame.Fn.GFunction(L) 94 if tailcall { 95 L.stack.Remove(L.stack.Sp() - 2) // remove caller lua function frame 96 L.currentFrame = L.stack.Last() 97 } 98 99 if gfnret < 0 { 100 switchToParentThread(L, L.GetTop(), false, false) 101 return true 102 } 103 104 wantret := frame.NRet 105 if wantret == MultRet { 106 wantret = gfnret 107 } 108 109 if tailcall && L.Parent != nil && L.stack.Sp() == 1 { 110 switchToParentThread(L, wantret, false, true) 111 return true 112 } 113 114 // this section is inlined by go-inline 115 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 116 { 117 rg := L.reg 118 regv := frame.ReturnBase 119 start := L.reg.Top() - gfnret 120 limit := -1 121 n := wantret 122 for i := 0; i < n; i++ { 123 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 124 rg.array[regv+i] = LNil 125 } else { 126 rg.array[regv+i] = rg.array[tidx] 127 } 128 } 129 rg.top = regv + n 130 } 131 L.stack.Pop() 132 L.currentFrame = L.stack.Last() 133 return false 134 } 135 136 func threadRun(L *LState) { 137 if L.stack.IsEmpty() { 138 return 139 } 140 141 defer func() { 142 if rcv := recover(); rcv != nil { 143 var lv LValue 144 if v, ok := rcv.(*ApiError); ok { 145 lv = v.Object 146 } else { 147 lv = LString(fmt.Sprint(rcv)) 148 } 149 if parent := L.Parent; parent != nil { 150 if L.wrapped { 151 L.Push(lv) 152 parent.Panic(L) 153 } else { 154 L.SetTop(0) 155 L.Push(lv) 156 switchToParentThread(L, 1, true, true) 157 } 158 } else { 159 panic(rcv) 160 } 161 } 162 }() 163 mainLoop(L, nil) 164 } 165 166 type instFunc func(*LState, uint32, *callFrame) int 167 168 var jumpTable [opCodeMax + 1]instFunc 169 170 func init() { 171 jumpTable = [opCodeMax + 1]instFunc{ 172 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE 173 reg := L.reg 174 cf := L.currentFrame 175 lbase := cf.LocalBase 176 A := int(inst>>18) & 0xff //GETA 177 RA := lbase + A 178 B := int(inst & 0x1ff) //GETB 179 reg.Set(RA, reg.Get(lbase+B)) 180 return 0 181 }, 182 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN 183 reg := L.reg 184 cf := L.currentFrame 185 lbase := cf.LocalBase 186 A := int(inst>>18) & 0xff //GETA 187 B := int(inst & 0x1ff) //GETB 188 C := int(inst>>9) & 0x1ff //GETC 189 reg.Set(lbase+A, reg.Get(lbase+B)) 190 code := cf.Fn.Proto.Code 191 pc := cf.Pc 192 for i := 0; i < C; i++ { 193 inst = code[pc] 194 pc++ 195 A = int(inst>>18) & 0xff //GETA 196 B = int(inst & 0x1ff) //GETB 197 reg.Set(lbase+A, reg.Get(lbase+B)) 198 } 199 cf.Pc = pc 200 return 0 201 }, 202 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK 203 reg := L.reg 204 cf := L.currentFrame 205 lbase := cf.LocalBase 206 A := int(inst>>18) & 0xff //GETA 207 RA := lbase + A 208 Bx := int(inst & 0x3ffff) //GETBX 209 reg.Set(RA, cf.Fn.Proto.Constants[Bx]) 210 return 0 211 }, 212 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL 213 reg := L.reg 214 cf := L.currentFrame 215 lbase := cf.LocalBase 216 A := int(inst>>18) & 0xff //GETA 217 RA := lbase + A 218 B := int(inst & 0x1ff) //GETB 219 C := int(inst>>9) & 0x1ff //GETC 220 if B != 0 { 221 reg.Set(RA, LTrue) 222 } else { 223 reg.Set(RA, LFalse) 224 } 225 if C != 0 { 226 cf.Pc++ 227 } 228 return 0 229 }, 230 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL 231 reg := L.reg 232 cf := L.currentFrame 233 lbase := cf.LocalBase 234 A := int(inst>>18) & 0xff //GETA 235 RA := lbase + A 236 B := int(inst & 0x1ff) //GETB 237 for i := RA; i <= lbase+B; i++ { 238 reg.Set(i, LNil) 239 } 240 return 0 241 }, 242 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL 243 reg := L.reg 244 cf := L.currentFrame 245 lbase := cf.LocalBase 246 A := int(inst>>18) & 0xff //GETA 247 RA := lbase + A 248 B := int(inst & 0x1ff) //GETB 249 reg.Set(RA, cf.Fn.Upvalues[B].Value()) 250 return 0 251 }, 252 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL 253 reg := L.reg 254 cf := L.currentFrame 255 lbase := cf.LocalBase 256 A := int(inst>>18) & 0xff //GETA 257 RA := lbase + A 258 Bx := int(inst & 0x3ffff) //GETBX 259 //reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx])) 260 reg.Set(RA, L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx])) 261 return 0 262 }, 263 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE 264 reg := L.reg 265 cf := L.currentFrame 266 lbase := cf.LocalBase 267 A := int(inst>>18) & 0xff //GETA 268 RA := lbase + A 269 B := int(inst & 0x1ff) //GETB 270 C := int(inst>>9) & 0x1ff //GETC 271 reg.Set(RA, L.getField(reg.Get(lbase+B), L.rkValue(C))) 272 return 0 273 }, 274 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS 275 reg := L.reg 276 cf := L.currentFrame 277 lbase := cf.LocalBase 278 A := int(inst>>18) & 0xff //GETA 279 RA := lbase + A 280 B := int(inst & 0x1ff) //GETB 281 C := int(inst>>9) & 0x1ff //GETC 282 reg.Set(RA, L.getFieldString(reg.Get(lbase+B), L.rkString(C))) 283 return 0 284 }, 285 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL 286 reg := L.reg 287 cf := L.currentFrame 288 lbase := cf.LocalBase 289 A := int(inst>>18) & 0xff //GETA 290 RA := lbase + A 291 Bx := int(inst & 0x3ffff) //GETBX 292 //L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA)) 293 L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA)) 294 return 0 295 }, 296 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL 297 reg := L.reg 298 cf := L.currentFrame 299 lbase := cf.LocalBase 300 A := int(inst>>18) & 0xff //GETA 301 RA := lbase + A 302 B := int(inst & 0x1ff) //GETB 303 cf.Fn.Upvalues[B].SetValue(reg.Get(RA)) 304 return 0 305 }, 306 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE 307 reg := L.reg 308 cf := L.currentFrame 309 lbase := cf.LocalBase 310 A := int(inst>>18) & 0xff //GETA 311 RA := lbase + A 312 B := int(inst & 0x1ff) //GETB 313 C := int(inst>>9) & 0x1ff //GETC 314 L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C)) 315 return 0 316 }, 317 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS 318 reg := L.reg 319 cf := L.currentFrame 320 lbase := cf.LocalBase 321 A := int(inst>>18) & 0xff //GETA 322 RA := lbase + A 323 B := int(inst & 0x1ff) //GETB 324 C := int(inst>>9) & 0x1ff //GETC 325 L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C)) 326 return 0 327 }, 328 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE 329 reg := L.reg 330 cf := L.currentFrame 331 lbase := cf.LocalBase 332 A := int(inst>>18) & 0xff //GETA 333 RA := lbase + A 334 B := int(inst & 0x1ff) //GETB 335 C := int(inst>>9) & 0x1ff //GETC 336 reg.Set(RA, newLTable(B, C)) 337 return 0 338 }, 339 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF 340 reg := L.reg 341 cf := L.currentFrame 342 lbase := cf.LocalBase 343 A := int(inst>>18) & 0xff //GETA 344 RA := lbase + A 345 B := int(inst & 0x1ff) //GETB 346 C := int(inst>>9) & 0x1ff //GETC 347 selfobj := reg.Get(lbase + B) 348 reg.Set(RA, L.getFieldString(selfobj, L.rkString(C))) 349 reg.Set(RA+1, selfobj) 350 return 0 351 }, 352 opArith, // OP_ADD 353 opArith, // OP_SUB 354 opArith, // OP_MUL 355 opArith, // OP_DIV 356 opArith, // OP_MOD 357 opArith, // OP_POW 358 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM 359 reg := L.reg 360 cf := L.currentFrame 361 lbase := cf.LocalBase 362 A := int(inst>>18) & 0xff //GETA 363 RA := lbase + A 364 B := int(inst & 0x1ff) //GETB 365 unaryv := L.rkValue(B) 366 if nm, ok := unaryv.(LNumber); ok { 367 reg.SetNumber(RA, -nm) 368 } else { 369 op := L.metaOp1(unaryv, "__unm") 370 if op.Type() == LTFunction { 371 reg.Push(op) 372 reg.Push(unaryv) 373 L.Call(1, 1) 374 reg.Set(RA, reg.Pop()) 375 } else if str, ok1 := unaryv.(LString); ok1 { 376 if num, err := parseNumber(string(str)); err == nil { 377 reg.Set(RA, -num) 378 } else { 379 L.RaiseError("__unm undefined") 380 } 381 } else { 382 L.RaiseError("__unm undefined") 383 } 384 } 385 return 0 386 }, 387 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT 388 reg := L.reg 389 cf := L.currentFrame 390 lbase := cf.LocalBase 391 A := int(inst>>18) & 0xff //GETA 392 RA := lbase + A 393 B := int(inst & 0x1ff) //GETB 394 if LVIsFalse(reg.Get(lbase + B)) { 395 reg.Set(RA, LTrue) 396 } else { 397 reg.Set(RA, LFalse) 398 } 399 return 0 400 }, 401 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN 402 reg := L.reg 403 cf := L.currentFrame 404 lbase := cf.LocalBase 405 A := int(inst>>18) & 0xff //GETA 406 RA := lbase + A 407 B := int(inst & 0x1ff) //GETB 408 switch lv := L.rkValue(B).(type) { 409 case LString: 410 reg.SetNumber(RA, LNumber(len(lv))) 411 default: 412 op := L.metaOp1(lv, "__len") 413 if op.Type() == LTFunction { 414 reg.Push(op) 415 reg.Push(lv) 416 L.Call(1, 1) 417 reg.Set(RA, reg.Pop()) 418 } else if lv.Type() == LTTable { 419 reg.SetNumber(RA, LNumber(lv.(*LTable).Len())) 420 } else { 421 L.RaiseError("__len undefined") 422 } 423 } 424 return 0 425 }, 426 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT 427 reg := L.reg 428 cf := L.currentFrame 429 lbase := cf.LocalBase 430 A := int(inst>>18) & 0xff //GETA 431 RA := lbase + A 432 B := int(inst & 0x1ff) //GETB 433 C := int(inst>>9) & 0x1ff //GETC 434 RC := lbase + C 435 RB := lbase + B 436 reg.Set(RA, stringConcat(L, RC-RB+1, RC)) 437 return 0 438 }, 439 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP 440 cf := L.currentFrame 441 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 442 cf.Pc += Sbx 443 return 0 444 }, 445 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ 446 cf := L.currentFrame 447 A := int(inst>>18) & 0xff //GETA 448 B := int(inst & 0x1ff) //GETB 449 C := int(inst>>9) & 0x1ff //GETC 450 ret := equals(L, L.rkValue(B), L.rkValue(C), false) 451 v := 1 452 if ret { 453 v = 0 454 } 455 if v == A { 456 cf.Pc++ 457 } 458 return 0 459 }, 460 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT 461 cf := L.currentFrame 462 A := int(inst>>18) & 0xff //GETA 463 B := int(inst & 0x1ff) //GETB 464 C := int(inst>>9) & 0x1ff //GETC 465 ret := lessThan(L, L.rkValue(B), L.rkValue(C)) 466 v := 1 467 if ret { 468 v = 0 469 } 470 if v == A { 471 cf.Pc++ 472 } 473 return 0 474 }, 475 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE 476 cf := L.currentFrame 477 A := int(inst>>18) & 0xff //GETA 478 B := int(inst & 0x1ff) //GETB 479 C := int(inst>>9) & 0x1ff //GETC 480 lhs := L.rkValue(B) 481 rhs := L.rkValue(C) 482 ret := false 483 484 if v1, ok1 := lhs.assertFloat64(); ok1 { 485 if v2, ok2 := rhs.assertFloat64(); ok2 { 486 ret = v1 <= v2 487 } else { 488 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 489 } 490 } else { 491 if lhs.Type() != rhs.Type() { 492 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 493 } 494 switch lhs.Type() { 495 case LTString: 496 ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) <= 0 497 default: 498 switch objectRational(L, lhs, rhs, "__le") { 499 case 1: 500 ret = true 501 case 0: 502 ret = false 503 default: 504 ret = !objectRationalWithError(L, rhs, lhs, "__lt") 505 } 506 } 507 } 508 509 v := 1 510 if ret { 511 v = 0 512 } 513 if v == A { 514 cf.Pc++ 515 } 516 return 0 517 }, 518 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST 519 reg := L.reg 520 cf := L.currentFrame 521 lbase := cf.LocalBase 522 A := int(inst>>18) & 0xff //GETA 523 RA := lbase + A 524 C := int(inst>>9) & 0x1ff //GETC 525 if LVAsBool(reg.Get(RA)) == (C == 0) { 526 cf.Pc++ 527 } 528 return 0 529 }, 530 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET 531 reg := L.reg 532 cf := L.currentFrame 533 lbase := cf.LocalBase 534 A := int(inst>>18) & 0xff //GETA 535 RA := lbase + A 536 B := int(inst & 0x1ff) //GETB 537 C := int(inst>>9) & 0x1ff //GETC 538 if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) { 539 reg.Set(RA, value) 540 } else { 541 cf.Pc++ 542 } 543 return 0 544 }, 545 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL 546 reg := L.reg 547 cf := L.currentFrame 548 lbase := cf.LocalBase 549 A := int(inst>>18) & 0xff //GETA 550 RA := lbase + A 551 B := int(inst & 0x1ff) //GETB 552 C := int(inst>>9) & 0x1ff //GETC 553 nargs := B - 1 554 if B == 0 { 555 nargs = reg.Top() - (RA + 1) 556 } 557 lv := reg.Get(RA) 558 nret := C - 1 559 var callable *LFunction 560 var meta bool 561 if fn, ok := lv.assertFunction(); ok { 562 callable = fn 563 meta = false 564 } else { 565 callable, meta = L.metaCall(lv) 566 } 567 // this section is inlined by go-inline 568 // source function is 'func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) ' in '_state.go' 569 { 570 ls := L 571 cf := callFrame{Fn: callable, Pc: 0, Base: RA, LocalBase: RA + 1, ReturnBase: RA, NArgs: nargs, NRet: nret, Parent: cf, TailCall: 0} 572 fn := lv 573 if meta { 574 cf.NArgs++ 575 ls.reg.Insert(fn, cf.LocalBase) 576 } 577 if cf.Fn == nil { 578 ls.RaiseError("attempt to call a non-function object") 579 } 580 if ls.stack.sp == ls.Options.CallStackSize { 581 ls.RaiseError("stack overflow") 582 } 583 // this section is inlined by go-inline 584 // source function is 'func (cs *callFrameStack) Push(v callFrame) ' in '_state.go' 585 { 586 cs := ls.stack 587 v := cf 588 cs.array[cs.sp] = v 589 cs.array[cs.sp].Idx = cs.sp 590 cs.sp++ 591 } 592 newcf := ls.stack.Last() 593 // this section is inlined by go-inline 594 // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' 595 { 596 cf := newcf 597 if cf.Fn.IsG { 598 ls.reg.SetTop(cf.LocalBase + cf.NArgs) 599 } else { 600 proto := cf.Fn.Proto 601 nargs := cf.NArgs 602 np := int(proto.NumParameters) 603 for i := nargs; i < np; i++ { 604 ls.reg.array[cf.LocalBase+i] = LNil 605 nargs = np 606 } 607 608 if (proto.IsVarArg & VarArgIsVarArg) == 0 { 609 if nargs < int(proto.NumUsedRegisters) { 610 nargs = int(proto.NumUsedRegisters) 611 } 612 for i := np; i < nargs; i++ { 613 ls.reg.array[cf.LocalBase+i] = LNil 614 } 615 ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) 616 } else { 617 /* swap vararg positions: 618 closure 619 namedparam1 <- lbase 620 namedparam2 621 vararg1 622 vararg2 623 624 TO 625 626 closure 627 nil 628 nil 629 vararg1 630 vararg2 631 namedparam1 <- lbase 632 namedparam2 633 */ 634 nvarargs := nargs - np 635 if nvarargs < 0 { 636 nvarargs = 0 637 } 638 639 ls.reg.SetTop(cf.LocalBase + nargs + np) 640 for i := 0; i < np; i++ { 641 //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) 642 ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] 643 //ls.reg.Set(cf.LocalBase+i, LNil) 644 ls.reg.array[cf.LocalBase+i] = LNil 645 } 646 647 if CompatVarArg { 648 ls.reg.SetTop(cf.LocalBase + nargs + np + 1) 649 if (proto.IsVarArg & VarArgNeedsArg) != 0 { 650 argtb := newLTable(nvarargs, 0) 651 for i := 0; i < nvarargs; i++ { 652 argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) 653 } 654 argtb.RawSetString("n", LNumber(nvarargs)) 655 //ls.reg.Set(cf.LocalBase+nargs+np, argtb) 656 ls.reg.array[cf.LocalBase+nargs+np] = argtb 657 } else { 658 ls.reg.array[cf.LocalBase+nargs+np] = LNil 659 } 660 } 661 cf.LocalBase += nargs 662 maxreg := cf.LocalBase + int(proto.NumUsedRegisters) 663 ls.reg.SetTop(maxreg) 664 } 665 } 666 } 667 ls.currentFrame = newcf 668 } 669 if callable.IsG && callGFunction(L, false) { 670 return 1 671 } 672 return 0 673 }, 674 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL 675 reg := L.reg 676 cf := L.currentFrame 677 lbase := cf.LocalBase 678 A := int(inst>>18) & 0xff //GETA 679 RA := lbase + A 680 B := int(inst & 0x1ff) //GETB 681 nargs := B - 1 682 if B == 0 { 683 nargs = reg.Top() - (RA + 1) 684 } 685 lv := reg.Get(RA) 686 var callable *LFunction 687 var meta bool 688 if fn, ok := lv.assertFunction(); ok { 689 callable = fn 690 meta = false 691 } else { 692 callable, meta = L.metaCall(lv) 693 } 694 // this section is inlined by go-inline 695 // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' 696 { 697 ls := L 698 idx := lbase 699 if ls.uvcache != nil { 700 var prev *Upvalue 701 for uv := ls.uvcache; uv != nil; uv = uv.next { 702 if uv.index >= idx { 703 if prev != nil { 704 prev.next = nil 705 } else { 706 ls.uvcache = nil 707 } 708 uv.Close() 709 } 710 prev = uv 711 } 712 } 713 } 714 if callable.IsG { 715 luaframe := cf 716 L.pushCallFrame(callFrame{ 717 Fn: callable, 718 Pc: 0, 719 Base: RA, 720 LocalBase: RA + 1, 721 ReturnBase: cf.ReturnBase, 722 NArgs: nargs, 723 NRet: cf.NRet, 724 Parent: cf, 725 TailCall: 0, 726 }, lv, meta) 727 if callGFunction(L, true) { 728 return 1 729 } 730 if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe { 731 return 1 732 } 733 } else { 734 base := cf.Base 735 cf.Fn = callable 736 cf.Pc = 0 737 cf.Base = RA 738 cf.LocalBase = RA + 1 739 cf.ReturnBase = cf.ReturnBase 740 cf.NArgs = nargs 741 cf.NRet = cf.NRet 742 cf.TailCall++ 743 lbase := cf.LocalBase 744 if meta { 745 cf.NArgs++ 746 L.reg.Insert(lv, cf.LocalBase) 747 } 748 // this section is inlined by go-inline 749 // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' 750 { 751 ls := L 752 if cf.Fn.IsG { 753 ls.reg.SetTop(cf.LocalBase + cf.NArgs) 754 } else { 755 proto := cf.Fn.Proto 756 nargs := cf.NArgs 757 np := int(proto.NumParameters) 758 for i := nargs; i < np; i++ { 759 ls.reg.array[cf.LocalBase+i] = LNil 760 nargs = np 761 } 762 763 if (proto.IsVarArg & VarArgIsVarArg) == 0 { 764 if nargs < int(proto.NumUsedRegisters) { 765 nargs = int(proto.NumUsedRegisters) 766 } 767 for i := np; i < nargs; i++ { 768 ls.reg.array[cf.LocalBase+i] = LNil 769 } 770 ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) 771 } else { 772 /* swap vararg positions: 773 closure 774 namedparam1 <- lbase 775 namedparam2 776 vararg1 777 vararg2 778 779 TO 780 781 closure 782 nil 783 nil 784 vararg1 785 vararg2 786 namedparam1 <- lbase 787 namedparam2 788 */ 789 nvarargs := nargs - np 790 if nvarargs < 0 { 791 nvarargs = 0 792 } 793 794 ls.reg.SetTop(cf.LocalBase + nargs + np) 795 for i := 0; i < np; i++ { 796 //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) 797 ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] 798 //ls.reg.Set(cf.LocalBase+i, LNil) 799 ls.reg.array[cf.LocalBase+i] = LNil 800 } 801 802 if CompatVarArg { 803 ls.reg.SetTop(cf.LocalBase + nargs + np + 1) 804 if (proto.IsVarArg & VarArgNeedsArg) != 0 { 805 argtb := newLTable(nvarargs, 0) 806 for i := 0; i < nvarargs; i++ { 807 argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) 808 } 809 argtb.RawSetString("n", LNumber(nvarargs)) 810 //ls.reg.Set(cf.LocalBase+nargs+np, argtb) 811 ls.reg.array[cf.LocalBase+nargs+np] = argtb 812 } else { 813 ls.reg.array[cf.LocalBase+nargs+np] = LNil 814 } 815 } 816 cf.LocalBase += nargs 817 maxreg := cf.LocalBase + int(proto.NumUsedRegisters) 818 ls.reg.SetTop(maxreg) 819 } 820 } 821 } 822 // this section is inlined by go-inline 823 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 824 { 825 rg := L.reg 826 regv := base 827 start := RA 828 limit := -1 829 n := reg.Top() - RA - 1 830 for i := 0; i < n; i++ { 831 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 832 rg.array[regv+i] = LNil 833 } else { 834 rg.array[regv+i] = rg.array[tidx] 835 } 836 } 837 rg.top = regv + n 838 } 839 cf.Base = base 840 cf.LocalBase = base + (cf.LocalBase - lbase + 1) 841 } 842 return 0 843 }, 844 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN 845 reg := L.reg 846 cf := L.currentFrame 847 lbase := cf.LocalBase 848 A := int(inst>>18) & 0xff //GETA 849 RA := lbase + A 850 B := int(inst & 0x1ff) //GETB 851 // this section is inlined by go-inline 852 // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' 853 { 854 ls := L 855 idx := lbase 856 if ls.uvcache != nil { 857 var prev *Upvalue 858 for uv := ls.uvcache; uv != nil; uv = uv.next { 859 if uv.index >= idx { 860 if prev != nil { 861 prev.next = nil 862 } else { 863 ls.uvcache = nil 864 } 865 uv.Close() 866 } 867 prev = uv 868 } 869 } 870 } 871 nret := B - 1 872 if B == 0 { 873 nret = reg.Top() - RA 874 } 875 n := cf.NRet 876 if cf.NRet == MultRet { 877 n = nret 878 } 879 880 if L.Parent != nil && L.stack.Sp() == 1 { 881 // this section is inlined by go-inline 882 // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' 883 { 884 regv := reg.Top() 885 start := RA 886 b := B 887 if b == 1 { 888 // this section is inlined by go-inline 889 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 890 { 891 rg := L.reg 892 regm := regv 893 for i := 0; i < n; i++ { 894 rg.array[regm+i] = LNil 895 } 896 rg.top = regm + n 897 } 898 } else { 899 // this section is inlined by go-inline 900 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 901 { 902 rg := L.reg 903 limit := -1 904 for i := 0; i < n; i++ { 905 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 906 rg.array[regv+i] = LNil 907 } else { 908 rg.array[regv+i] = rg.array[tidx] 909 } 910 } 911 rg.top = regv + n 912 } 913 } 914 } 915 switchToParentThread(L, n, false, true) 916 return 1 917 } 918 islast := baseframe == L.stack.Pop() || L.stack.IsEmpty() 919 // this section is inlined by go-inline 920 // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' 921 { 922 regv := cf.ReturnBase 923 start := RA 924 b := B 925 if b == 1 { 926 // this section is inlined by go-inline 927 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 928 { 929 rg := L.reg 930 regm := regv 931 for i := 0; i < n; i++ { 932 rg.array[regm+i] = LNil 933 } 934 rg.top = regm + n 935 } 936 } else { 937 // this section is inlined by go-inline 938 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 939 { 940 rg := L.reg 941 limit := -1 942 for i := 0; i < n; i++ { 943 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 944 rg.array[regv+i] = LNil 945 } else { 946 rg.array[regv+i] = rg.array[tidx] 947 } 948 } 949 rg.top = regv + n 950 } 951 } 952 } 953 L.currentFrame = L.stack.Last() 954 if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG { 955 return 1 956 } 957 return 0 958 }, 959 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP 960 reg := L.reg 961 cf := L.currentFrame 962 lbase := cf.LocalBase 963 A := int(inst>>18) & 0xff //GETA 964 RA := lbase + A 965 if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { 966 if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 { 967 if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 { 968 init += step 969 reg.SetNumber(RA, LNumber(init)) 970 if (step > 0 && init <= limit) || (step <= 0 && init >= limit) { 971 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 972 cf.Pc += Sbx 973 reg.SetNumber(RA+3, LNumber(init)) 974 } else { 975 reg.SetTop(RA + 1) 976 } 977 } else { 978 L.RaiseError("for statement step must be a number") 979 } 980 } else { 981 L.RaiseError("for statement limit must be a number") 982 } 983 } else { 984 L.RaiseError("for statement init must be a number") 985 } 986 return 0 987 }, 988 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP 989 reg := L.reg 990 cf := L.currentFrame 991 lbase := cf.LocalBase 992 A := int(inst>>18) & 0xff //GETA 993 RA := lbase + A 994 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 995 if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { 996 if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 { 997 reg.SetNumber(RA, LNumber(init-step)) 998 } else { 999 L.RaiseError("for statement step must be a number") 1000 } 1001 } else { 1002 L.RaiseError("for statement init must be a number") 1003 } 1004 cf.Pc += Sbx 1005 return 0 1006 }, 1007 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP 1008 reg := L.reg 1009 cf := L.currentFrame 1010 lbase := cf.LocalBase 1011 A := int(inst>>18) & 0xff //GETA 1012 RA := lbase + A 1013 C := int(inst>>9) & 0x1ff //GETC 1014 nret := C 1015 reg.SetTop(RA + 3) 1016 L.callR(2, nret, RA+3) 1017 reg.SetTop(RA + 2 + C + 1) 1018 if value := reg.Get(RA + 3); value != LNil { 1019 reg.Set(RA+2, value) 1020 } else { 1021 cf.Pc++ 1022 } 1023 return 0 1024 }, 1025 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST 1026 reg := L.reg 1027 cf := L.currentFrame 1028 lbase := cf.LocalBase 1029 A := int(inst>>18) & 0xff //GETA 1030 RA := lbase + A 1031 B := int(inst & 0x1ff) //GETB 1032 C := int(inst>>9) & 0x1ff //GETC 1033 if C == 0 { 1034 C = int(cf.Fn.Proto.Code[cf.Pc]) 1035 cf.Pc++ 1036 } 1037 offset := (C - 1) * FieldsPerFlush 1038 table := reg.Get(RA).(*LTable) 1039 nelem := B 1040 if B == 0 { 1041 nelem = reg.Top() - RA - 1 1042 } 1043 for i := 1; i <= nelem; i++ { 1044 table.RawSetInt(offset+i, reg.Get(RA+i)) 1045 } 1046 return 0 1047 }, 1048 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE 1049 cf := L.currentFrame 1050 lbase := cf.LocalBase 1051 A := int(inst>>18) & 0xff //GETA 1052 RA := lbase + A 1053 // this section is inlined by go-inline 1054 // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' 1055 { 1056 ls := L 1057 idx := RA 1058 if ls.uvcache != nil { 1059 var prev *Upvalue 1060 for uv := ls.uvcache; uv != nil; uv = uv.next { 1061 if uv.index >= idx { 1062 if prev != nil { 1063 prev.next = nil 1064 } else { 1065 ls.uvcache = nil 1066 } 1067 uv.Close() 1068 } 1069 prev = uv 1070 } 1071 } 1072 } 1073 return 0 1074 }, 1075 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE 1076 reg := L.reg 1077 cf := L.currentFrame 1078 lbase := cf.LocalBase 1079 A := int(inst>>18) & 0xff //GETA 1080 RA := lbase + A 1081 Bx := int(inst & 0x3ffff) //GETBX 1082 proto := cf.Fn.Proto.FunctionPrototypes[Bx] 1083 closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues)) 1084 reg.Set(RA, closure) 1085 for i := 0; i < int(proto.NumUpvalues); i++ { 1086 inst = cf.Fn.Proto.Code[cf.Pc] 1087 cf.Pc++ 1088 B := opGetArgB(inst) 1089 switch opGetOpCode(inst) { 1090 case OP_MOVE: 1091 closure.Upvalues[i] = L.findUpvalue(lbase + B) 1092 case OP_GETUPVAL: 1093 closure.Upvalues[i] = cf.Fn.Upvalues[B] 1094 } 1095 } 1096 return 0 1097 }, 1098 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG 1099 reg := L.reg 1100 cf := L.currentFrame 1101 lbase := cf.LocalBase 1102 A := int(inst>>18) & 0xff //GETA 1103 RA := lbase + A 1104 B := int(inst & 0x1ff) //GETB 1105 nparams := int(cf.Fn.Proto.NumParameters) 1106 nvarargs := cf.NArgs - nparams 1107 if nvarargs < 0 { 1108 nvarargs = 0 1109 } 1110 nwant := B - 1 1111 if B == 0 { 1112 nwant = nvarargs 1113 } 1114 // this section is inlined by go-inline 1115 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 1116 { 1117 rg := reg 1118 regv := RA 1119 start := cf.Base + nparams + 1 1120 limit := cf.LocalBase 1121 n := nwant 1122 for i := 0; i < n; i++ { 1123 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 1124 rg.array[regv+i] = LNil 1125 } else { 1126 rg.array[regv+i] = rg.array[tidx] 1127 } 1128 } 1129 rg.top = regv + n 1130 } 1131 return 0 1132 }, 1133 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP 1134 return 0 1135 }, 1136 } 1137 } 1138 1139 func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW 1140 reg := L.reg 1141 cf := L.currentFrame 1142 lbase := cf.LocalBase 1143 A := int(inst>>18) & 0xff //GETA 1144 RA := lbase + A 1145 opcode := int(inst >> 26) //GETOPCODE 1146 B := int(inst & 0x1ff) //GETB 1147 C := int(inst>>9) & 0x1ff //GETC 1148 lhs := L.rkValue(B) 1149 rhs := L.rkValue(C) 1150 v1, ok1 := lhs.assertFloat64() 1151 v2, ok2 := rhs.assertFloat64() 1152 if ok1 && ok2 { 1153 reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2))) 1154 } else { 1155 reg.Set(RA, objectArith(L, opcode, lhs, rhs)) 1156 } 1157 return 0 1158 } 1159 1160 func luaModulo(lhs, rhs LNumber) LNumber { 1161 flhs := float64(lhs) 1162 frhs := float64(rhs) 1163 v := math.Mod(flhs, frhs) 1164 if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) { 1165 v += frhs 1166 } 1167 return LNumber(v) 1168 } 1169 1170 func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber { 1171 switch opcode { 1172 case OP_ADD: 1173 return lhs + rhs 1174 case OP_SUB: 1175 return lhs - rhs 1176 case OP_MUL: 1177 return lhs * rhs 1178 case OP_DIV: 1179 return lhs / rhs 1180 case OP_MOD: 1181 return luaModulo(lhs, rhs) 1182 case OP_POW: 1183 flhs := float64(lhs) 1184 frhs := float64(rhs) 1185 return LNumber(math.Pow(flhs, frhs)) 1186 } 1187 panic("should not reach here") 1188 return LNumber(0) 1189 } 1190 1191 func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue { 1192 event := "" 1193 switch opcode { 1194 case OP_ADD: 1195 event = "__add" 1196 case OP_SUB: 1197 event = "__sub" 1198 case OP_MUL: 1199 event = "__mul" 1200 case OP_DIV: 1201 event = "__div" 1202 case OP_MOD: 1203 event = "__mod" 1204 case OP_POW: 1205 event = "__pow" 1206 } 1207 op := L.metaOp2(lhs, rhs, event) 1208 if op.Type() == LTFunction { 1209 L.reg.Push(op) 1210 L.reg.Push(lhs) 1211 L.reg.Push(rhs) 1212 L.Call(2, 1) 1213 return L.reg.Pop() 1214 } 1215 if str, ok := lhs.(LString); ok { 1216 if lnum, err := parseNumber(string(str)); err == nil { 1217 lhs = lnum 1218 } 1219 } 1220 if str, ok := rhs.(LString); ok { 1221 if rnum, err := parseNumber(string(str)); err == nil { 1222 rhs = rnum 1223 } 1224 } 1225 if v1, ok1 := lhs.assertFloat64(); ok1 { 1226 if v2, ok2 := rhs.assertFloat64(); ok2 { 1227 return numberArith(L, opcode, LNumber(v1), LNumber(v2)) 1228 } 1229 } 1230 L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v", 1231 strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String())) 1232 1233 return LNil 1234 } 1235 1236 func stringConcat(L *LState, total, last int) LValue { 1237 rhs := L.reg.Get(last) 1238 total-- 1239 for i := last - 1; total > 0; { 1240 lhs := L.reg.Get(i) 1241 if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) { 1242 op := L.metaOp2(lhs, rhs, "__concat") 1243 if op.Type() == LTFunction { 1244 L.reg.Push(op) 1245 L.reg.Push(lhs) 1246 L.reg.Push(rhs) 1247 L.Call(2, 1) 1248 rhs = L.reg.Pop() 1249 total-- 1250 i-- 1251 } else { 1252 L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String()) 1253 return LNil 1254 } 1255 } else { 1256 buf := make([]string, total+1) 1257 buf[total] = LVAsString(rhs) 1258 for total > 0 { 1259 lhs = L.reg.Get(i) 1260 if !LVCanConvToString(lhs) { 1261 break 1262 } 1263 buf[total-1] = LVAsString(lhs) 1264 i-- 1265 total-- 1266 } 1267 rhs = LString(strings.Join(buf, "")) 1268 } 1269 } 1270 return rhs 1271 } 1272 1273 func lessThan(L *LState, lhs, rhs LValue) bool { 1274 // optimization for numbers 1275 if v1, ok1 := lhs.assertFloat64(); ok1 { 1276 if v2, ok2 := rhs.assertFloat64(); ok2 { 1277 return v1 < v2 1278 } 1279 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1280 } 1281 if lhs.Type() != rhs.Type() { 1282 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1283 return false 1284 } 1285 ret := false 1286 switch lhs.Type() { 1287 case LTString: 1288 ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0 1289 default: 1290 ret = objectRationalWithError(L, lhs, rhs, "__lt") 1291 } 1292 return ret 1293 } 1294 1295 func equals(L *LState, lhs, rhs LValue, raw bool) bool { 1296 if lhs.Type() != rhs.Type() { 1297 return false 1298 } 1299 1300 ret := false 1301 switch lhs.Type() { 1302 case LTNil: 1303 ret = true 1304 case LTNumber: 1305 v1, _ := lhs.assertFloat64() 1306 v2, _ := rhs.assertFloat64() 1307 ret = v1 == v2 1308 case LTBool: 1309 ret = bool(lhs.(LBool)) == bool(rhs.(LBool)) 1310 case LTString: 1311 ret = string(lhs.(LString)) == string(rhs.(LString)) 1312 case LTUserData, LTTable: 1313 if lhs == rhs { 1314 ret = true 1315 } else if !raw { 1316 switch objectRational(L, lhs, rhs, "__eq") { 1317 case 1: 1318 ret = true 1319 default: 1320 ret = false 1321 } 1322 } 1323 default: 1324 ret = lhs == rhs 1325 } 1326 return ret 1327 } 1328 1329 func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool { 1330 switch objectRational(L, lhs, rhs, event) { 1331 case 1: 1332 return true 1333 case 0: 1334 return false 1335 } 1336 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1337 return false 1338 } 1339 1340 func objectRational(L *LState, lhs, rhs LValue, event string) int { 1341 m1 := L.metaOp1(lhs, event) 1342 m2 := L.metaOp1(rhs, event) 1343 if m1.Type() == LTFunction && m1 == m2 { 1344 L.reg.Push(m1) 1345 L.reg.Push(lhs) 1346 L.reg.Push(rhs) 1347 L.Call(2, 1) 1348 if LVAsBool(L.reg.Pop()) { 1349 return 1 1350 } 1351 return 0 1352 } 1353 return -1 1354 }