gitee.com/yfmps/gopher-lua@v0.0.3/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 L.lhook != nil { 32 L.lhook.call(L, cf) 33 } 34 if L.cthook != nil { 35 L.cthook.call(L, cf) 36 } 37 if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { 38 return 39 } 40 } 41 } 42 43 func mainLoopWithContext(L *LState, baseframe *callFrame) { 44 var inst uint32 45 var cf *callFrame 46 47 if L.stack.IsEmpty() { 48 return 49 } 50 51 L.currentFrame = L.stack.Last() 52 if L.currentFrame.Fn.IsG { 53 callGFunction(L, false) 54 return 55 } 56 57 for { 58 cf = L.currentFrame 59 inst = cf.Fn.Proto.Code[cf.Pc] 60 cf.Pc++ 61 select { 62 case <-L.ctx.Done(): 63 L.RaiseError(L.ctx.Err().Error()) 64 return 65 default: 66 if L.lhook != nil { 67 L.lhook.call(L, cf) 68 } 69 if L.cthook != nil { 70 L.cthook.call(L, cf) 71 } 72 if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { 73 return 74 } 75 } 76 } 77 } 78 79 // regv is the first target register to copy the return values to. 80 // It can be reg.top, indicating that the copied values are going into new registers, or it can be below reg.top 81 // Indicating that the values should be within the existing registers. 82 // b is the available number of return values + 1. 83 // n is the desired number of return values. 84 // If n more than the available return values then the extra values are set to nil. 85 // When this function returns the top of the registry will be set to regv+n. 86 func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start 87 if b == 1 { 88 // this section is inlined by go-inline 89 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 90 { 91 rg := L.reg 92 regm := regv 93 newSize := regm + n 94 // this section is inlined by go-inline 95 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 96 { 97 requiredSize := newSize 98 if requiredSize > cap(rg.array) { 99 rg.resize(requiredSize) 100 } 101 } 102 for i := 0; i < n; i++ { 103 rg.array[regm+i] = LNil 104 } 105 // values beyond top don't need to be valid LValues, so setting them to nil is fine 106 // setting them to nil rather than LNil lets us invoke the golang memclr opto 107 oldtop := rg.top 108 rg.top = regm + n 109 if rg.top < oldtop { 110 nilRange := rg.array[rg.top:oldtop] 111 for i := range nilRange { 112 nilRange[i] = nil 113 } 114 } 115 } 116 } else { 117 // this section is inlined by go-inline 118 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 119 { 120 rg := L.reg 121 limit := -1 122 newSize := regv + n 123 // this section is inlined by go-inline 124 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 125 { 126 requiredSize := newSize 127 if requiredSize > cap(rg.array) { 128 rg.resize(requiredSize) 129 } 130 } 131 if limit == -1 || limit > rg.top { 132 limit = rg.top 133 } 134 for i := 0; i < n; i++ { 135 srcIdx := start + i 136 if srcIdx >= limit || srcIdx < 0 { 137 rg.array[regv+i] = LNil 138 } else { 139 rg.array[regv+i] = rg.array[srcIdx] 140 } 141 } 142 143 // values beyond top don't need to be valid LValues, so setting them to nil is fine 144 // setting them to nil rather than LNil lets us invoke the golang memclr opto 145 oldtop := rg.top 146 rg.top = regv + n 147 if rg.top < oldtop { 148 nilRange := rg.array[rg.top:oldtop] 149 for i := range nilRange { 150 nilRange[i] = nil 151 } 152 } 153 } 154 if b > 1 && n > (b-1) { 155 // this section is inlined by go-inline 156 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 157 { 158 rg := L.reg 159 regm := regv + b - 1 160 n := n - (b - 1) 161 newSize := regm + n 162 // this section is inlined by go-inline 163 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 164 { 165 requiredSize := newSize 166 if requiredSize > cap(rg.array) { 167 rg.resize(requiredSize) 168 } 169 } 170 for i := 0; i < n; i++ { 171 rg.array[regm+i] = LNil 172 } 173 // values beyond top don't need to be valid LValues, so setting them to nil is fine 174 // setting them to nil rather than LNil lets us invoke the golang memclr opto 175 oldtop := rg.top 176 rg.top = regm + n 177 if rg.top < oldtop { 178 nilRange := rg.array[rg.top:oldtop] 179 for i := range nilRange { 180 nilRange[i] = nil 181 } 182 } 183 } 184 } 185 } 186 } // +inline-end 187 188 func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { 189 parent := L.Parent 190 if parent == nil { 191 L.RaiseError("can not yield from outside of a coroutine") 192 } 193 L.G.CurrentThread = parent 194 L.Parent = nil 195 if !L.wrapped { 196 if haserror { 197 parent.Push(LFalse) 198 } else { 199 parent.Push(LTrue) 200 } 201 } 202 L.XMoveTo(parent, nargs) 203 L.stack.Pop() 204 offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase 205 L.currentFrame = L.stack.Last() 206 L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) 207 if kill { 208 L.kill() 209 } 210 } 211 212 func callGFunction(L *LState, tailcall bool) bool { 213 frame := L.currentFrame 214 gfnret := frame.Fn.GFunction(L) 215 if tailcall { 216 L.currentFrame = L.RemoveCallerFrame() 217 } 218 219 if gfnret < 0 { 220 switchToParentThread(L, L.GetTop(), false, false) 221 return true 222 } 223 224 wantret := frame.NRet 225 if wantret == MultRet { 226 wantret = gfnret 227 } 228 229 if tailcall && L.Parent != nil && L.stack.Sp() == 1 { 230 switchToParentThread(L, wantret, false, true) 231 return true 232 } 233 234 // this section is inlined by go-inline 235 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 236 { 237 rg := L.reg 238 regv := frame.ReturnBase 239 start := L.reg.Top() - gfnret 240 limit := -1 241 n := wantret 242 newSize := regv + n 243 // this section is inlined by go-inline 244 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 245 { 246 requiredSize := newSize 247 if requiredSize > cap(rg.array) { 248 rg.resize(requiredSize) 249 } 250 } 251 if limit == -1 || limit > rg.top { 252 limit = rg.top 253 } 254 for i := 0; i < n; i++ { 255 srcIdx := start + i 256 if srcIdx >= limit || srcIdx < 0 { 257 rg.array[regv+i] = LNil 258 } else { 259 rg.array[regv+i] = rg.array[srcIdx] 260 } 261 } 262 263 // values beyond top don't need to be valid LValues, so setting them to nil is fine 264 // setting them to nil rather than LNil lets us invoke the golang memclr opto 265 oldtop := rg.top 266 rg.top = regv + n 267 if rg.top < oldtop { 268 nilRange := rg.array[rg.top:oldtop] 269 for i := range nilRange { 270 nilRange[i] = nil 271 } 272 } 273 } 274 L.stack.Pop() 275 L.currentFrame = L.stack.Last() 276 return false 277 } 278 279 func threadRun(L *LState) { 280 if L.stack.IsEmpty() { 281 return 282 } 283 284 defer func() { 285 if rcv := recover(); rcv != nil { 286 var lv LValue 287 if v, ok := rcv.(*ApiError); ok { 288 lv = v.Object 289 } else { 290 lv = LString(fmt.Sprint(rcv)) 291 } 292 if parent := L.Parent; parent != nil { 293 if L.wrapped { 294 L.Push(lv) 295 parent.Panic(L) 296 } else { 297 L.SetTop(0) 298 L.Push(lv) 299 switchToParentThread(L, 1, true, true) 300 } 301 } else { 302 panic(rcv) 303 } 304 } 305 }() 306 L.mainLoop(L, nil) 307 } 308 309 type instFunc func(*LState, uint32, *callFrame) int 310 311 var jumpTable [opCodeMax + 1]instFunc 312 313 func init() { 314 jumpTable = [opCodeMax + 1]instFunc{ 315 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE 316 reg := L.reg 317 cf := L.currentFrame 318 lbase := cf.LocalBase 319 A := int(inst>>18) & 0xff //GETA 320 RA := lbase + A 321 B := int(inst & 0x1ff) //GETB 322 reg.Set(RA, reg.Get(lbase+B)) 323 return 0 324 }, 325 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN 326 reg := L.reg 327 cf := L.currentFrame 328 lbase := cf.LocalBase 329 A := int(inst>>18) & 0xff //GETA 330 B := int(inst & 0x1ff) //GETB 331 C := int(inst>>9) & 0x1ff //GETC 332 reg.Set(lbase+A, reg.Get(lbase+B)) 333 code := cf.Fn.Proto.Code 334 pc := cf.Pc 335 for i := 0; i < C; i++ { 336 inst = code[pc] 337 pc++ 338 A = int(inst>>18) & 0xff //GETA 339 B = int(inst & 0x1ff) //GETB 340 reg.Set(lbase+A, reg.Get(lbase+B)) 341 } 342 cf.Pc = pc 343 return 0 344 }, 345 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK 346 reg := L.reg 347 cf := L.currentFrame 348 lbase := cf.LocalBase 349 A := int(inst>>18) & 0xff //GETA 350 RA := lbase + A 351 Bx := int(inst & 0x3ffff) //GETBX 352 reg.Set(RA, cf.Fn.Proto.Constants[Bx]) 353 return 0 354 }, 355 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL 356 reg := L.reg 357 cf := L.currentFrame 358 lbase := cf.LocalBase 359 A := int(inst>>18) & 0xff //GETA 360 RA := lbase + A 361 B := int(inst & 0x1ff) //GETB 362 C := int(inst>>9) & 0x1ff //GETC 363 if B != 0 { 364 reg.Set(RA, LTrue) 365 } else { 366 reg.Set(RA, LFalse) 367 } 368 if C != 0 { 369 cf.Pc++ 370 } 371 return 0 372 }, 373 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL 374 reg := L.reg 375 cf := L.currentFrame 376 lbase := cf.LocalBase 377 A := int(inst>>18) & 0xff //GETA 378 RA := lbase + A 379 B := int(inst & 0x1ff) //GETB 380 for i := RA; i <= lbase+B; i++ { 381 reg.Set(i, LNil) 382 } 383 return 0 384 }, 385 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL 386 reg := L.reg 387 cf := L.currentFrame 388 lbase := cf.LocalBase 389 A := int(inst>>18) & 0xff //GETA 390 RA := lbase + A 391 B := int(inst & 0x1ff) //GETB 392 reg.Set(RA, cf.Fn.Upvalues[B].Value()) 393 return 0 394 }, 395 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL 396 reg := L.reg 397 cf := L.currentFrame 398 lbase := cf.LocalBase 399 A := int(inst>>18) & 0xff //GETA 400 RA := lbase + A 401 Bx := int(inst & 0x3ffff) //GETBX 402 //reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx])) 403 reg.Set(RA, L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx])) 404 return 0 405 }, 406 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE 407 reg := L.reg 408 cf := L.currentFrame 409 lbase := cf.LocalBase 410 A := int(inst>>18) & 0xff //GETA 411 RA := lbase + A 412 B := int(inst & 0x1ff) //GETB 413 C := int(inst>>9) & 0x1ff //GETC 414 reg.Set(RA, L.getField(reg.Get(lbase+B), L.rkValue(C))) 415 return 0 416 }, 417 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS 418 reg := L.reg 419 cf := L.currentFrame 420 lbase := cf.LocalBase 421 A := int(inst>>18) & 0xff //GETA 422 RA := lbase + A 423 B := int(inst & 0x1ff) //GETB 424 C := int(inst>>9) & 0x1ff //GETC 425 reg.Set(RA, L.getFieldString(reg.Get(lbase+B), L.rkString(C))) 426 return 0 427 }, 428 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL 429 reg := L.reg 430 cf := L.currentFrame 431 lbase := cf.LocalBase 432 A := int(inst>>18) & 0xff //GETA 433 RA := lbase + A 434 Bx := int(inst & 0x3ffff) //GETBX 435 //L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA)) 436 L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA)) 437 return 0 438 }, 439 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL 440 reg := L.reg 441 cf := L.currentFrame 442 lbase := cf.LocalBase 443 A := int(inst>>18) & 0xff //GETA 444 RA := lbase + A 445 B := int(inst & 0x1ff) //GETB 446 cf.Fn.Upvalues[B].SetValue(reg.Get(RA)) 447 return 0 448 }, 449 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE 450 reg := L.reg 451 cf := L.currentFrame 452 lbase := cf.LocalBase 453 A := int(inst>>18) & 0xff //GETA 454 RA := lbase + A 455 B := int(inst & 0x1ff) //GETB 456 C := int(inst>>9) & 0x1ff //GETC 457 L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C)) 458 return 0 459 }, 460 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS 461 reg := L.reg 462 cf := L.currentFrame 463 lbase := cf.LocalBase 464 A := int(inst>>18) & 0xff //GETA 465 RA := lbase + A 466 B := int(inst & 0x1ff) //GETB 467 C := int(inst>>9) & 0x1ff //GETC 468 L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C)) 469 return 0 470 }, 471 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE 472 reg := L.reg 473 cf := L.currentFrame 474 lbase := cf.LocalBase 475 A := int(inst>>18) & 0xff //GETA 476 RA := lbase + A 477 B := int(inst & 0x1ff) //GETB 478 C := int(inst>>9) & 0x1ff //GETC 479 reg.Set(RA, newLTable(B, C)) 480 return 0 481 }, 482 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF 483 reg := L.reg 484 cf := L.currentFrame 485 lbase := cf.LocalBase 486 A := int(inst>>18) & 0xff //GETA 487 RA := lbase + A 488 B := int(inst & 0x1ff) //GETB 489 C := int(inst>>9) & 0x1ff //GETC 490 selfobj := reg.Get(lbase + B) 491 reg.Set(RA, L.getFieldString(selfobj, L.rkString(C))) 492 reg.Set(RA+1, selfobj) 493 return 0 494 }, 495 opArith, // OP_ADD 496 opArith, // OP_SUB 497 opArith, // OP_MUL 498 opArith, // OP_DIV 499 opArith, // OP_MOD 500 opArith, // OP_POW 501 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM 502 reg := L.reg 503 cf := L.currentFrame 504 lbase := cf.LocalBase 505 A := int(inst>>18) & 0xff //GETA 506 RA := lbase + A 507 B := int(inst & 0x1ff) //GETB 508 unaryv := L.rkValue(B) 509 if nm, ok := unaryv.(LNumber); ok { 510 reg.SetNumber(RA, -nm) 511 } else { 512 op := L.metaOp1(unaryv, "__unm") 513 if op.Type() == LTFunction { 514 reg.Push(op) 515 reg.Push(unaryv) 516 L.Call(1, 1) 517 reg.Set(RA, reg.Pop()) 518 } else if str, ok1 := unaryv.(LString); ok1 { 519 if num, err := parseNumber(string(str)); err == nil { 520 reg.Set(RA, -num) 521 } else { 522 L.RaiseError("__unm undefined") 523 } 524 } else { 525 L.RaiseError("__unm undefined") 526 } 527 } 528 return 0 529 }, 530 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT 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 if LVIsFalse(reg.Get(lbase + B)) { 538 reg.Set(RA, LTrue) 539 } else { 540 reg.Set(RA, LFalse) 541 } 542 return 0 543 }, 544 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN 545 reg := L.reg 546 cf := L.currentFrame 547 lbase := cf.LocalBase 548 A := int(inst>>18) & 0xff //GETA 549 RA := lbase + A 550 B := int(inst & 0x1ff) //GETB 551 switch lv := L.rkValue(B).(type) { 552 case LString: 553 reg.SetNumber(RA, LNumber(len(lv))) 554 default: 555 op := L.metaOp1(lv, "__len") 556 if op.Type() == LTFunction { 557 reg.Push(op) 558 reg.Push(lv) 559 L.Call(1, 1) 560 ret := reg.Pop() 561 if ret.Type() == LTNumber { 562 reg.SetNumber(RA, ret.(LNumber)) 563 } else { 564 reg.SetNumber(RA, LNumber(0)) 565 } 566 } else if lv.Type() == LTTable { 567 reg.SetNumber(RA, LNumber(lv.(*LTable).Len())) 568 } else { 569 L.RaiseError("__len undefined") 570 } 571 } 572 return 0 573 }, 574 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT 575 reg := L.reg 576 cf := L.currentFrame 577 lbase := cf.LocalBase 578 A := int(inst>>18) & 0xff //GETA 579 RA := lbase + A 580 B := int(inst & 0x1ff) //GETB 581 C := int(inst>>9) & 0x1ff //GETC 582 RC := lbase + C 583 RB := lbase + B 584 reg.Set(RA, stringConcat(L, RC-RB+1, RC)) 585 return 0 586 }, 587 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP 588 cf := L.currentFrame 589 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 590 cf.Pc += Sbx 591 return 0 592 }, 593 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ 594 cf := L.currentFrame 595 A := int(inst>>18) & 0xff //GETA 596 B := int(inst & 0x1ff) //GETB 597 C := int(inst>>9) & 0x1ff //GETC 598 ret := equals(L, L.rkValue(B), L.rkValue(C), false) 599 v := 1 600 if ret { 601 v = 0 602 } 603 if v == A { 604 cf.Pc++ 605 } 606 return 0 607 }, 608 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT 609 cf := L.currentFrame 610 A := int(inst>>18) & 0xff //GETA 611 B := int(inst & 0x1ff) //GETB 612 C := int(inst>>9) & 0x1ff //GETC 613 ret := lessThan(L, L.rkValue(B), L.rkValue(C)) 614 v := 1 615 if ret { 616 v = 0 617 } 618 if v == A { 619 cf.Pc++ 620 } 621 return 0 622 }, 623 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE 624 cf := L.currentFrame 625 A := int(inst>>18) & 0xff //GETA 626 B := int(inst & 0x1ff) //GETB 627 C := int(inst>>9) & 0x1ff //GETC 628 lhs := L.rkValue(B) 629 rhs := L.rkValue(C) 630 ret := false 631 632 if v1, ok1 := lhs.assertFloat64(); ok1 { 633 if v2, ok2 := rhs.assertFloat64(); ok2 { 634 ret = v1 <= v2 635 } else { 636 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 637 } 638 } else { 639 if lhs.Type() != rhs.Type() { 640 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 641 } 642 switch lhs.Type() { 643 case LTString: 644 ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) <= 0 645 default: 646 switch objectRational(L, lhs, rhs, "__le") { 647 case 1: 648 ret = true 649 case 0: 650 ret = false 651 default: 652 ret = !objectRationalWithError(L, rhs, lhs, "__lt") 653 } 654 } 655 } 656 657 v := 1 658 if ret { 659 v = 0 660 } 661 if v == A { 662 cf.Pc++ 663 } 664 return 0 665 }, 666 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST 667 reg := L.reg 668 cf := L.currentFrame 669 lbase := cf.LocalBase 670 A := int(inst>>18) & 0xff //GETA 671 RA := lbase + A 672 C := int(inst>>9) & 0x1ff //GETC 673 if LVAsBool(reg.Get(RA)) == (C == 0) { 674 cf.Pc++ 675 } 676 return 0 677 }, 678 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET 679 reg := L.reg 680 cf := L.currentFrame 681 lbase := cf.LocalBase 682 A := int(inst>>18) & 0xff //GETA 683 RA := lbase + A 684 B := int(inst & 0x1ff) //GETB 685 C := int(inst>>9) & 0x1ff //GETC 686 if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) { 687 reg.Set(RA, value) 688 } else { 689 cf.Pc++ 690 } 691 return 0 692 }, 693 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL 694 if L.chook != nil { 695 L.chook.call(L, baseframe) 696 } 697 reg := L.reg 698 cf := L.currentFrame 699 lbase := cf.LocalBase 700 A := int(inst>>18) & 0xff //GETA 701 RA := lbase + A 702 B := int(inst & 0x1ff) //GETB 703 C := int(inst>>9) & 0x1ff //GETC 704 nargs := B - 1 705 if B == 0 { 706 nargs = reg.Top() - (RA + 1) 707 } 708 lv := reg.Get(RA) 709 nret := C - 1 710 var callable *LFunction 711 var meta bool 712 if fn, ok := lv.assertFunction(); ok { 713 callable = fn 714 meta = false 715 } else { 716 callable, meta = L.metaCall(lv) 717 } 718 // this section is inlined by go-inline 719 // source function is 'func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) ' in '_state.go' 720 { 721 ls := L 722 cf := callFrame{Fn: callable, Pc: 0, Base: RA, LocalBase: RA + 1, ReturnBase: RA, NArgs: nargs, NRet: nret, Parent: cf, TailCall: 0} 723 fn := lv 724 if meta { 725 cf.NArgs++ 726 ls.reg.Insert(fn, cf.LocalBase) 727 } 728 if cf.Fn == nil { 729 ls.RaiseError("attempt to call a non-function object") 730 } 731 if ls.stack.IsFull() { 732 ls.RaiseError("stack overflow") 733 } 734 ls.stack.Push(cf) 735 newcf := ls.stack.Last() 736 // this section is inlined by go-inline 737 // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' 738 { 739 cf := newcf 740 if cf.Fn.IsG { 741 ls.reg.SetTop(cf.LocalBase + cf.NArgs) 742 } else { 743 proto := cf.Fn.Proto 744 nargs := cf.NArgs 745 np := int(proto.NumParameters) 746 newSize := cf.LocalBase + np 747 // this section is inlined by go-inline 748 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 749 { 750 rg := ls.reg 751 requiredSize := newSize 752 if requiredSize > cap(rg.array) { 753 rg.resize(requiredSize) 754 } 755 } 756 for i := nargs; i < np; i++ { 757 ls.reg.array[cf.LocalBase+i] = LNil 758 nargs = np 759 } 760 761 if (proto.IsVarArg & VarArgIsVarArg) == 0 { 762 if nargs < int(proto.NumUsedRegisters) { 763 nargs = int(proto.NumUsedRegisters) 764 } 765 newSize = cf.LocalBase + nargs 766 // this section is inlined by go-inline 767 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 768 { 769 rg := ls.reg 770 requiredSize := newSize 771 if requiredSize > cap(rg.array) { 772 rg.resize(requiredSize) 773 } 774 } 775 for i := np; i < nargs; i++ { 776 ls.reg.array[cf.LocalBase+i] = LNil 777 } 778 ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) 779 } else { 780 /* swap vararg positions: 781 closure 782 namedparam1 <- lbase 783 namedparam2 784 vararg1 785 vararg2 786 787 TO 788 789 closure 790 nil 791 nil 792 vararg1 793 vararg2 794 namedparam1 <- lbase 795 namedparam2 796 */ 797 nvarargs := nargs - np 798 if nvarargs < 0 { 799 nvarargs = 0 800 } 801 802 ls.reg.SetTop(cf.LocalBase + nargs + np) 803 for i := 0; i < np; i++ { 804 //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) 805 ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] 806 //ls.reg.Set(cf.LocalBase+i, LNil) 807 ls.reg.array[cf.LocalBase+i] = LNil 808 } 809 810 if CompatVarArg { 811 ls.reg.SetTop(cf.LocalBase + nargs + np + 1) 812 if (proto.IsVarArg & VarArgNeedsArg) != 0 { 813 argtb := newLTable(nvarargs, 0) 814 for i := 0; i < nvarargs; i++ { 815 argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) 816 } 817 argtb.RawSetString("n", LNumber(nvarargs)) 818 //ls.reg.Set(cf.LocalBase+nargs+np, argtb) 819 ls.reg.array[cf.LocalBase+nargs+np] = argtb 820 } else { 821 ls.reg.array[cf.LocalBase+nargs+np] = LNil 822 } 823 } 824 cf.LocalBase += nargs 825 maxreg := cf.LocalBase + int(proto.NumUsedRegisters) 826 ls.reg.SetTop(maxreg) 827 } 828 } 829 } 830 ls.currentFrame = newcf 831 } 832 if callable.IsG && callGFunction(L, false) { 833 return 1 834 } 835 return 0 836 }, 837 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL 838 reg := L.reg 839 cf := L.currentFrame 840 lbase := cf.LocalBase 841 A := int(inst>>18) & 0xff //GETA 842 RA := lbase + A 843 B := int(inst & 0x1ff) //GETB 844 nargs := B - 1 845 if B == 0 { 846 nargs = reg.Top() - (RA + 1) 847 } 848 lv := reg.Get(RA) 849 var callable *LFunction 850 var meta bool 851 if fn, ok := lv.assertFunction(); ok { 852 callable = fn 853 meta = false 854 } else { 855 callable, meta = L.metaCall(lv) 856 } 857 if callable == nil { 858 L.RaiseError("attempt to call a non-function object") 859 } 860 // this section is inlined by go-inline 861 // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' 862 { 863 ls := L 864 idx := lbase 865 if ls.uvcache != nil { 866 var prev *Upvalue 867 for uv := ls.uvcache; uv != nil; uv = uv.next { 868 if uv.index >= idx { 869 if prev != nil { 870 prev.next = nil 871 } else { 872 ls.uvcache = nil 873 } 874 uv.Close() 875 } 876 prev = uv 877 } 878 } 879 } 880 if callable.IsG { 881 luaframe := cf 882 L.pushCallFrame(callFrame{ 883 Fn: callable, 884 Pc: 0, 885 Base: RA, 886 LocalBase: RA + 1, 887 ReturnBase: cf.ReturnBase, 888 NArgs: nargs, 889 NRet: cf.NRet, 890 Parent: cf, 891 TailCall: 0, 892 }, lv, meta) 893 if callGFunction(L, true) { 894 return 1 895 } 896 if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe { 897 return 1 898 } 899 } else { 900 base := cf.Base 901 cf.Fn = callable 902 cf.Pc = 0 903 cf.Base = RA 904 cf.LocalBase = RA + 1 905 cf.ReturnBase = cf.ReturnBase 906 cf.NArgs = nargs 907 cf.NRet = cf.NRet 908 cf.TailCall++ 909 lbase := cf.LocalBase 910 if meta { 911 cf.NArgs++ 912 L.reg.Insert(lv, cf.LocalBase) 913 } 914 // this section is inlined by go-inline 915 // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' 916 { 917 ls := L 918 if cf.Fn.IsG { 919 ls.reg.SetTop(cf.LocalBase + cf.NArgs) 920 } else { 921 proto := cf.Fn.Proto 922 nargs := cf.NArgs 923 np := int(proto.NumParameters) 924 newSize := cf.LocalBase + np 925 // this section is inlined by go-inline 926 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 927 { 928 rg := ls.reg 929 requiredSize := newSize 930 if requiredSize > cap(rg.array) { 931 rg.resize(requiredSize) 932 } 933 } 934 for i := nargs; i < np; i++ { 935 ls.reg.array[cf.LocalBase+i] = LNil 936 nargs = np 937 } 938 939 if (proto.IsVarArg & VarArgIsVarArg) == 0 { 940 if nargs < int(proto.NumUsedRegisters) { 941 nargs = int(proto.NumUsedRegisters) 942 } 943 newSize = cf.LocalBase + nargs 944 // this section is inlined by go-inline 945 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 946 { 947 rg := ls.reg 948 requiredSize := newSize 949 if requiredSize > cap(rg.array) { 950 rg.resize(requiredSize) 951 } 952 } 953 for i := np; i < nargs; i++ { 954 ls.reg.array[cf.LocalBase+i] = LNil 955 } 956 ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) 957 } else { 958 /* swap vararg positions: 959 closure 960 namedparam1 <- lbase 961 namedparam2 962 vararg1 963 vararg2 964 965 TO 966 967 closure 968 nil 969 nil 970 vararg1 971 vararg2 972 namedparam1 <- lbase 973 namedparam2 974 */ 975 nvarargs := nargs - np 976 if nvarargs < 0 { 977 nvarargs = 0 978 } 979 980 ls.reg.SetTop(cf.LocalBase + nargs + np) 981 for i := 0; i < np; i++ { 982 //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) 983 ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] 984 //ls.reg.Set(cf.LocalBase+i, LNil) 985 ls.reg.array[cf.LocalBase+i] = LNil 986 } 987 988 if CompatVarArg { 989 ls.reg.SetTop(cf.LocalBase + nargs + np + 1) 990 if (proto.IsVarArg & VarArgNeedsArg) != 0 { 991 argtb := newLTable(nvarargs, 0) 992 for i := 0; i < nvarargs; i++ { 993 argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) 994 } 995 argtb.RawSetString("n", LNumber(nvarargs)) 996 //ls.reg.Set(cf.LocalBase+nargs+np, argtb) 997 ls.reg.array[cf.LocalBase+nargs+np] = argtb 998 } else { 999 ls.reg.array[cf.LocalBase+nargs+np] = LNil 1000 } 1001 } 1002 cf.LocalBase += nargs 1003 maxreg := cf.LocalBase + int(proto.NumUsedRegisters) 1004 ls.reg.SetTop(maxreg) 1005 } 1006 } 1007 } 1008 // this section is inlined by go-inline 1009 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 1010 { 1011 rg := L.reg 1012 regv := base 1013 start := RA 1014 limit := -1 1015 n := reg.Top() - RA - 1 1016 newSize := regv + n 1017 // this section is inlined by go-inline 1018 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 1019 { 1020 requiredSize := newSize 1021 if requiredSize > cap(rg.array) { 1022 rg.resize(requiredSize) 1023 } 1024 } 1025 if limit == -1 || limit > rg.top { 1026 limit = rg.top 1027 } 1028 for i := 0; i < n; i++ { 1029 srcIdx := start + i 1030 if srcIdx >= limit || srcIdx < 0 { 1031 rg.array[regv+i] = LNil 1032 } else { 1033 rg.array[regv+i] = rg.array[srcIdx] 1034 } 1035 } 1036 1037 // values beyond top don't need to be valid LValues, so setting them to nil is fine 1038 // setting them to nil rather than LNil lets us invoke the golang memclr opto 1039 oldtop := rg.top 1040 rg.top = regv + n 1041 if rg.top < oldtop { 1042 nilRange := rg.array[rg.top:oldtop] 1043 for i := range nilRange { 1044 nilRange[i] = nil 1045 } 1046 } 1047 } 1048 cf.Base = base 1049 cf.LocalBase = base + (cf.LocalBase - lbase + 1) 1050 } 1051 return 0 1052 }, 1053 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN 1054 if L.rhook != nil { 1055 L.rhook.call(L, baseframe) 1056 } 1057 reg := L.reg 1058 cf := L.currentFrame 1059 lbase := cf.LocalBase 1060 A := int(inst>>18) & 0xff //GETA 1061 RA := lbase + A 1062 B := int(inst & 0x1ff) //GETB 1063 // this section is inlined by go-inline 1064 // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' 1065 { 1066 ls := L 1067 idx := lbase 1068 if ls.uvcache != nil { 1069 var prev *Upvalue 1070 for uv := ls.uvcache; uv != nil; uv = uv.next { 1071 if uv.index >= idx { 1072 if prev != nil { 1073 prev.next = nil 1074 } else { 1075 ls.uvcache = nil 1076 } 1077 uv.Close() 1078 } 1079 prev = uv 1080 } 1081 } 1082 } 1083 nret := B - 1 1084 if B == 0 { 1085 nret = reg.Top() - RA 1086 } 1087 n := cf.NRet 1088 if cf.NRet == MultRet { 1089 n = nret 1090 } 1091 1092 if L.Parent != nil && L.stack.Sp() == 1 { 1093 // this section is inlined by go-inline 1094 // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' 1095 { 1096 regv := reg.Top() 1097 start := RA 1098 b := B 1099 if b == 1 { 1100 // this section is inlined by go-inline 1101 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 1102 { 1103 rg := L.reg 1104 regm := regv 1105 newSize := regm + n 1106 // this section is inlined by go-inline 1107 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 1108 { 1109 requiredSize := newSize 1110 if requiredSize > cap(rg.array) { 1111 rg.resize(requiredSize) 1112 } 1113 } 1114 for i := 0; i < n; i++ { 1115 rg.array[regm+i] = LNil 1116 } 1117 // values beyond top don't need to be valid LValues, so setting them to nil is fine 1118 // setting them to nil rather than LNil lets us invoke the golang memclr opto 1119 oldtop := rg.top 1120 rg.top = regm + n 1121 if rg.top < oldtop { 1122 nilRange := rg.array[rg.top:oldtop] 1123 for i := range nilRange { 1124 nilRange[i] = nil 1125 } 1126 } 1127 } 1128 } else { 1129 // this section is inlined by go-inline 1130 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 1131 { 1132 rg := L.reg 1133 limit := -1 1134 newSize := regv + n 1135 // this section is inlined by go-inline 1136 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 1137 { 1138 requiredSize := newSize 1139 if requiredSize > cap(rg.array) { 1140 rg.resize(requiredSize) 1141 } 1142 } 1143 if limit == -1 || limit > rg.top { 1144 limit = rg.top 1145 } 1146 for i := 0; i < n; i++ { 1147 srcIdx := start + i 1148 if srcIdx >= limit || srcIdx < 0 { 1149 rg.array[regv+i] = LNil 1150 } else { 1151 rg.array[regv+i] = rg.array[srcIdx] 1152 } 1153 } 1154 1155 // values beyond top don't need to be valid LValues, so setting them to nil is fine 1156 // setting them to nil rather than LNil lets us invoke the golang memclr opto 1157 oldtop := rg.top 1158 rg.top = regv + n 1159 if rg.top < oldtop { 1160 nilRange := rg.array[rg.top:oldtop] 1161 for i := range nilRange { 1162 nilRange[i] = nil 1163 } 1164 } 1165 } 1166 if b > 1 && n > (b-1) { 1167 // this section is inlined by go-inline 1168 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 1169 { 1170 rg := L.reg 1171 regm := regv + b - 1 1172 n := n - (b - 1) 1173 newSize := regm + n 1174 // this section is inlined by go-inline 1175 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 1176 { 1177 requiredSize := newSize 1178 if requiredSize > cap(rg.array) { 1179 rg.resize(requiredSize) 1180 } 1181 } 1182 for i := 0; i < n; i++ { 1183 rg.array[regm+i] = LNil 1184 } 1185 // values beyond top don't need to be valid LValues, so setting them to nil is fine 1186 // setting them to nil rather than LNil lets us invoke the golang memclr opto 1187 oldtop := rg.top 1188 rg.top = regm + n 1189 if rg.top < oldtop { 1190 nilRange := rg.array[rg.top:oldtop] 1191 for i := range nilRange { 1192 nilRange[i] = nil 1193 } 1194 } 1195 } 1196 } 1197 } 1198 } 1199 switchToParentThread(L, n, false, true) 1200 return 1 1201 } 1202 islast := baseframe == L.stack.Pop() || L.stack.IsEmpty() 1203 // this section is inlined by go-inline 1204 // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' 1205 { 1206 regv := cf.ReturnBase 1207 start := RA 1208 b := B 1209 if b == 1 { 1210 // this section is inlined by go-inline 1211 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 1212 { 1213 rg := L.reg 1214 regm := regv 1215 newSize := regm + n 1216 // this section is inlined by go-inline 1217 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 1218 { 1219 requiredSize := newSize 1220 if requiredSize > cap(rg.array) { 1221 rg.resize(requiredSize) 1222 } 1223 } 1224 for i := 0; i < n; i++ { 1225 rg.array[regm+i] = LNil 1226 } 1227 // values beyond top don't need to be valid LValues, so setting them to nil is fine 1228 // setting them to nil rather than LNil lets us invoke the golang memclr opto 1229 oldtop := rg.top 1230 rg.top = regm + n 1231 if rg.top < oldtop { 1232 nilRange := rg.array[rg.top:oldtop] 1233 for i := range nilRange { 1234 nilRange[i] = nil 1235 } 1236 } 1237 } 1238 } else { 1239 // this section is inlined by go-inline 1240 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 1241 { 1242 rg := L.reg 1243 limit := -1 1244 newSize := regv + n 1245 // this section is inlined by go-inline 1246 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 1247 { 1248 requiredSize := newSize 1249 if requiredSize > cap(rg.array) { 1250 rg.resize(requiredSize) 1251 } 1252 } 1253 if limit == -1 || limit > rg.top { 1254 limit = rg.top 1255 } 1256 for i := 0; i < n; i++ { 1257 srcIdx := start + i 1258 if srcIdx >= limit || srcIdx < 0 { 1259 rg.array[regv+i] = LNil 1260 } else { 1261 rg.array[regv+i] = rg.array[srcIdx] 1262 } 1263 } 1264 1265 // values beyond top don't need to be valid LValues, so setting them to nil is fine 1266 // setting them to nil rather than LNil lets us invoke the golang memclr opto 1267 oldtop := rg.top 1268 rg.top = regv + n 1269 if rg.top < oldtop { 1270 nilRange := rg.array[rg.top:oldtop] 1271 for i := range nilRange { 1272 nilRange[i] = nil 1273 } 1274 } 1275 } 1276 if b > 1 && n > (b-1) { 1277 // this section is inlined by go-inline 1278 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 1279 { 1280 rg := L.reg 1281 regm := regv + b - 1 1282 n := n - (b - 1) 1283 newSize := regm + n 1284 // this section is inlined by go-inline 1285 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 1286 { 1287 requiredSize := newSize 1288 if requiredSize > cap(rg.array) { 1289 rg.resize(requiredSize) 1290 } 1291 } 1292 for i := 0; i < n; i++ { 1293 rg.array[regm+i] = LNil 1294 } 1295 // values beyond top don't need to be valid LValues, so setting them to nil is fine 1296 // setting them to nil rather than LNil lets us invoke the golang memclr opto 1297 oldtop := rg.top 1298 rg.top = regm + n 1299 if rg.top < oldtop { 1300 nilRange := rg.array[rg.top:oldtop] 1301 for i := range nilRange { 1302 nilRange[i] = nil 1303 } 1304 } 1305 } 1306 } 1307 } 1308 } 1309 L.currentFrame = L.stack.Last() 1310 if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG { 1311 return 1 1312 } 1313 return 0 1314 }, 1315 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP 1316 reg := L.reg 1317 cf := L.currentFrame 1318 lbase := cf.LocalBase 1319 A := int(inst>>18) & 0xff //GETA 1320 RA := lbase + A 1321 if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { 1322 if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 { 1323 if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 { 1324 init += step 1325 reg.SetNumber(RA, LNumber(init)) 1326 if (step > 0 && init <= limit) || (step <= 0 && init >= limit) { 1327 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 1328 cf.Pc += Sbx 1329 reg.SetNumber(RA+3, LNumber(init)) 1330 } else { 1331 reg.SetTop(RA + 1) 1332 } 1333 } else { 1334 L.RaiseError("for statement step must be a number") 1335 } 1336 } else { 1337 L.RaiseError("for statement limit must be a number") 1338 } 1339 } else { 1340 L.RaiseError("for statement init must be a number") 1341 } 1342 return 0 1343 }, 1344 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP 1345 reg := L.reg 1346 cf := L.currentFrame 1347 lbase := cf.LocalBase 1348 A := int(inst>>18) & 0xff //GETA 1349 RA := lbase + A 1350 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 1351 if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { 1352 if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 { 1353 reg.SetNumber(RA, LNumber(init-step)) 1354 } else { 1355 L.RaiseError("for statement step must be a number") 1356 } 1357 } else { 1358 L.RaiseError("for statement init must be a number") 1359 } 1360 cf.Pc += Sbx 1361 return 0 1362 }, 1363 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP 1364 reg := L.reg 1365 cf := L.currentFrame 1366 lbase := cf.LocalBase 1367 A := int(inst>>18) & 0xff //GETA 1368 RA := lbase + A 1369 C := int(inst>>9) & 0x1ff //GETC 1370 nret := C 1371 reg.SetTop(RA + 3 + 2) 1372 reg.Set(RA+3+2, reg.Get(RA+2)) 1373 reg.Set(RA+3+1, reg.Get(RA+1)) 1374 reg.Set(RA+3, reg.Get(RA)) 1375 L.callR(2, nret, RA+3) 1376 if value := reg.Get(RA + 3); value != LNil { 1377 reg.Set(RA+2, value) 1378 pc := cf.Fn.Proto.Code[cf.Pc] 1379 cf.Pc += int(pc&0x3ffff) - opMaxArgSbx 1380 } 1381 cf.Pc++ 1382 return 0 1383 }, 1384 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST 1385 reg := L.reg 1386 cf := L.currentFrame 1387 lbase := cf.LocalBase 1388 A := int(inst>>18) & 0xff //GETA 1389 RA := lbase + A 1390 B := int(inst & 0x1ff) //GETB 1391 C := int(inst>>9) & 0x1ff //GETC 1392 if C == 0 { 1393 C = int(cf.Fn.Proto.Code[cf.Pc]) 1394 cf.Pc++ 1395 } 1396 offset := (C - 1) * FieldsPerFlush 1397 table := reg.Get(RA).(*LTable) 1398 nelem := B 1399 if B == 0 { 1400 nelem = reg.Top() - RA - 1 1401 } 1402 for i := 1; i <= nelem; i++ { 1403 table.RawSetInt(offset+i, reg.Get(RA+i)) 1404 } 1405 return 0 1406 }, 1407 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE 1408 cf := L.currentFrame 1409 lbase := cf.LocalBase 1410 A := int(inst>>18) & 0xff //GETA 1411 RA := lbase + A 1412 // this section is inlined by go-inline 1413 // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' 1414 { 1415 ls := L 1416 idx := RA 1417 if ls.uvcache != nil { 1418 var prev *Upvalue 1419 for uv := ls.uvcache; uv != nil; uv = uv.next { 1420 if uv.index >= idx { 1421 if prev != nil { 1422 prev.next = nil 1423 } else { 1424 ls.uvcache = nil 1425 } 1426 uv.Close() 1427 } 1428 prev = uv 1429 } 1430 } 1431 } 1432 return 0 1433 }, 1434 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE 1435 reg := L.reg 1436 cf := L.currentFrame 1437 lbase := cf.LocalBase 1438 A := int(inst>>18) & 0xff //GETA 1439 RA := lbase + A 1440 Bx := int(inst & 0x3ffff) //GETBX 1441 proto := cf.Fn.Proto.FunctionPrototypes[Bx] 1442 closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues)) 1443 reg.Set(RA, closure) 1444 for i := 0; i < int(proto.NumUpvalues); i++ { 1445 inst = cf.Fn.Proto.Code[cf.Pc] 1446 cf.Pc++ 1447 B := opGetArgB(inst) 1448 switch opGetOpCode(inst) { 1449 case OP_MOVE: 1450 closure.Upvalues[i] = L.findUpvalue(lbase + B) 1451 case OP_GETUPVAL: 1452 closure.Upvalues[i] = cf.Fn.Upvalues[B] 1453 } 1454 } 1455 return 0 1456 }, 1457 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG 1458 reg := L.reg 1459 cf := L.currentFrame 1460 lbase := cf.LocalBase 1461 A := int(inst>>18) & 0xff //GETA 1462 RA := lbase + A 1463 B := int(inst & 0x1ff) //GETB 1464 nparams := int(cf.Fn.Proto.NumParameters) 1465 nvarargs := cf.NArgs - nparams 1466 if nvarargs < 0 { 1467 nvarargs = 0 1468 } 1469 nwant := B - 1 1470 if B == 0 { 1471 nwant = nvarargs 1472 } 1473 // this section is inlined by go-inline 1474 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 1475 { 1476 rg := reg 1477 regv := RA 1478 start := cf.Base + nparams + 1 1479 limit := cf.LocalBase 1480 n := nwant 1481 newSize := regv + n 1482 // this section is inlined by go-inline 1483 // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' 1484 { 1485 requiredSize := newSize 1486 if requiredSize > cap(rg.array) { 1487 rg.resize(requiredSize) 1488 } 1489 } 1490 if limit == -1 || limit > rg.top { 1491 limit = rg.top 1492 } 1493 for i := 0; i < n; i++ { 1494 srcIdx := start + i 1495 if srcIdx >= limit || srcIdx < 0 { 1496 rg.array[regv+i] = LNil 1497 } else { 1498 rg.array[regv+i] = rg.array[srcIdx] 1499 } 1500 } 1501 1502 // values beyond top don't need to be valid LValues, so setting them to nil is fine 1503 // setting them to nil rather than LNil lets us invoke the golang memclr opto 1504 oldtop := rg.top 1505 rg.top = regv + n 1506 if rg.top < oldtop { 1507 nilRange := rg.array[rg.top:oldtop] 1508 for i := range nilRange { 1509 nilRange[i] = nil 1510 } 1511 } 1512 } 1513 return 0 1514 }, 1515 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP 1516 return 0 1517 }, 1518 } 1519 } 1520 1521 func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW 1522 reg := L.reg 1523 cf := L.currentFrame 1524 lbase := cf.LocalBase 1525 A := int(inst>>18) & 0xff //GETA 1526 RA := lbase + A 1527 opcode := int(inst >> 26) //GETOPCODE 1528 B := int(inst & 0x1ff) //GETB 1529 C := int(inst>>9) & 0x1ff //GETC 1530 lhs := L.rkValue(B) 1531 rhs := L.rkValue(C) 1532 v1, ok1 := lhs.assertFloat64() 1533 v2, ok2 := rhs.assertFloat64() 1534 if ok1 && ok2 { 1535 reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2))) 1536 } else { 1537 reg.Set(RA, objectArith(L, opcode, lhs, rhs)) 1538 } 1539 return 0 1540 } 1541 1542 func luaModulo(lhs, rhs LNumber) LNumber { 1543 flhs := float64(lhs) 1544 frhs := float64(rhs) 1545 v := math.Mod(flhs, frhs) 1546 if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) { 1547 v += frhs 1548 } 1549 return LNumber(v) 1550 } 1551 1552 func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber { 1553 switch opcode { 1554 case OP_ADD: 1555 return lhs + rhs 1556 case OP_SUB: 1557 return lhs - rhs 1558 case OP_MUL: 1559 return lhs * rhs 1560 case OP_DIV: 1561 return lhs / rhs 1562 case OP_MOD: 1563 return luaModulo(lhs, rhs) 1564 case OP_POW: 1565 flhs := float64(lhs) 1566 frhs := float64(rhs) 1567 return LNumber(math.Pow(flhs, frhs)) 1568 } 1569 panic("should not reach here") 1570 return LNumber(0) 1571 } 1572 1573 func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue { 1574 event := "" 1575 switch opcode { 1576 case OP_ADD: 1577 event = "__add" 1578 case OP_SUB: 1579 event = "__sub" 1580 case OP_MUL: 1581 event = "__mul" 1582 case OP_DIV: 1583 event = "__div" 1584 case OP_MOD: 1585 event = "__mod" 1586 case OP_POW: 1587 event = "__pow" 1588 } 1589 op := L.metaOp2(lhs, rhs, event) 1590 if op.Type() == LTFunction { 1591 L.reg.Push(op) 1592 L.reg.Push(lhs) 1593 L.reg.Push(rhs) 1594 L.Call(2, 1) 1595 return L.reg.Pop() 1596 } 1597 if str, ok := lhs.(LString); ok { 1598 if lnum, err := parseNumber(string(str)); err == nil { 1599 lhs = lnum 1600 } 1601 } 1602 if str, ok := rhs.(LString); ok { 1603 if rnum, err := parseNumber(string(str)); err == nil { 1604 rhs = rnum 1605 } 1606 } 1607 if v1, ok1 := lhs.assertFloat64(); ok1 { 1608 if v2, ok2 := rhs.assertFloat64(); ok2 { 1609 return numberArith(L, opcode, LNumber(v1), LNumber(v2)) 1610 } 1611 } 1612 L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v", 1613 strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String())) 1614 1615 return LNil 1616 } 1617 1618 func stringConcat(L *LState, total, last int) LValue { 1619 rhs := L.reg.Get(last) 1620 total-- 1621 for i := last - 1; total > 0; { 1622 lhs := L.reg.Get(i) 1623 if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) { 1624 op := L.metaOp2(lhs, rhs, "__concat") 1625 if op.Type() == LTFunction { 1626 L.reg.Push(op) 1627 L.reg.Push(lhs) 1628 L.reg.Push(rhs) 1629 L.Call(2, 1) 1630 rhs = L.reg.Pop() 1631 total-- 1632 i-- 1633 } else { 1634 L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String()) 1635 return LNil 1636 } 1637 } else { 1638 buf := make([]string, total+1) 1639 buf[total] = LVAsString(rhs) 1640 for total > 0 { 1641 lhs = L.reg.Get(i) 1642 if !LVCanConvToString(lhs) { 1643 break 1644 } 1645 buf[total-1] = LVAsString(lhs) 1646 i-- 1647 total-- 1648 } 1649 rhs = LString(strings.Join(buf, "")) 1650 } 1651 } 1652 return rhs 1653 } 1654 1655 func lessThan(L *LState, lhs, rhs LValue) bool { 1656 // optimization for numbers 1657 if v1, ok1 := lhs.assertFloat64(); ok1 { 1658 if v2, ok2 := rhs.assertFloat64(); ok2 { 1659 return v1 < v2 1660 } 1661 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1662 } 1663 if lhs.Type() != rhs.Type() { 1664 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1665 return false 1666 } 1667 ret := false 1668 switch lhs.Type() { 1669 case LTString: 1670 ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0 1671 default: 1672 ret = objectRationalWithError(L, lhs, rhs, "__lt") 1673 } 1674 return ret 1675 } 1676 1677 func equals(L *LState, lhs, rhs LValue, raw bool) bool { 1678 if lhs.Type() != rhs.Type() { 1679 return false 1680 } 1681 1682 ret := false 1683 switch lhs.Type() { 1684 case LTNil: 1685 ret = true 1686 case LTNumber: 1687 v1, _ := lhs.assertFloat64() 1688 v2, _ := rhs.assertFloat64() 1689 ret = v1 == v2 1690 case LTBool: 1691 ret = bool(lhs.(LBool)) == bool(rhs.(LBool)) 1692 case LTString: 1693 ret = string(lhs.(LString)) == string(rhs.(LString)) 1694 case LTUserData, LTTable: 1695 if lhs == rhs { 1696 ret = true 1697 } else if !raw { 1698 switch objectRational(L, lhs, rhs, "__eq") { 1699 case 1: 1700 ret = true 1701 default: 1702 ret = false 1703 } 1704 } 1705 default: 1706 ret = lhs == rhs 1707 } 1708 return ret 1709 } 1710 1711 func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool { 1712 switch objectRational(L, lhs, rhs, event) { 1713 case 1: 1714 return true 1715 case 0: 1716 return false 1717 } 1718 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1719 return false 1720 } 1721 1722 func objectRational(L *LState, lhs, rhs LValue, event string) int { 1723 m1 := L.metaOp1(lhs, event) 1724 m2 := L.metaOp1(rhs, event) 1725 if m1.Type() == LTFunction && m1 == m2 { 1726 L.reg.Push(m1) 1727 L.reg.Push(lhs) 1728 L.reg.Push(rhs) 1729 L.Call(2, 1) 1730 if LVAsBool(L.reg.Pop()) { 1731 return 1 1732 } 1733 return 0 1734 } 1735 return -1 1736 }