Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

iexport.go 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. // Copyright 2019 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Indexed binary package export.
  5. // This file was derived from $GOROOT/src/cmd/compile/internal/gc/iexport.go;
  6. // see that file for specification of the format.
  7. package gcimporter
  8. import (
  9. "bytes"
  10. "encoding/binary"
  11. "go/ast"
  12. "go/constant"
  13. "go/token"
  14. "go/types"
  15. "io"
  16. "math/big"
  17. "reflect"
  18. "sort"
  19. )
  20. // Current indexed export format version. Increase with each format change.
  21. // 0: Go1.11 encoding
  22. const iexportVersion = 0
  23. // IExportData returns the binary export data for pkg.
  24. //
  25. // If no file set is provided, position info will be missing.
  26. // The package path of the top-level package will not be recorded,
  27. // so that calls to IImportData can override with a provided package path.
  28. func IExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) {
  29. defer func() {
  30. if e := recover(); e != nil {
  31. if ierr, ok := e.(internalError); ok {
  32. err = ierr
  33. return
  34. }
  35. // Not an internal error; panic again.
  36. panic(e)
  37. }
  38. }()
  39. p := iexporter{
  40. out: bytes.NewBuffer(nil),
  41. fset: fset,
  42. allPkgs: map[*types.Package]bool{},
  43. stringIndex: map[string]uint64{},
  44. declIndex: map[types.Object]uint64{},
  45. typIndex: map[types.Type]uint64{},
  46. localpkg: pkg,
  47. }
  48. for i, pt := range predeclared() {
  49. p.typIndex[pt] = uint64(i)
  50. }
  51. if len(p.typIndex) > predeclReserved {
  52. panic(internalErrorf("too many predeclared types: %d > %d", len(p.typIndex), predeclReserved))
  53. }
  54. // Initialize work queue with exported declarations.
  55. scope := pkg.Scope()
  56. for _, name := range scope.Names() {
  57. if ast.IsExported(name) {
  58. p.pushDecl(scope.Lookup(name))
  59. }
  60. }
  61. // Loop until no more work.
  62. for !p.declTodo.empty() {
  63. p.doDecl(p.declTodo.popHead())
  64. }
  65. // Append indices to data0 section.
  66. dataLen := uint64(p.data0.Len())
  67. w := p.newWriter()
  68. w.writeIndex(p.declIndex)
  69. w.flush()
  70. // Assemble header.
  71. var hdr intWriter
  72. hdr.WriteByte('i')
  73. hdr.uint64(iexportVersion)
  74. hdr.uint64(uint64(p.strings.Len()))
  75. hdr.uint64(dataLen)
  76. // Flush output.
  77. io.Copy(p.out, &hdr)
  78. io.Copy(p.out, &p.strings)
  79. io.Copy(p.out, &p.data0)
  80. return p.out.Bytes(), nil
  81. }
  82. // writeIndex writes out an object index. mainIndex indicates whether
  83. // we're writing out the main index, which is also read by
  84. // non-compiler tools and includes a complete package description
  85. // (i.e., name and height).
  86. func (w *exportWriter) writeIndex(index map[types.Object]uint64) {
  87. // Build a map from packages to objects from that package.
  88. pkgObjs := map[*types.Package][]types.Object{}
  89. // For the main index, make sure to include every package that
  90. // we reference, even if we're not exporting (or reexporting)
  91. // any symbols from it.
  92. pkgObjs[w.p.localpkg] = nil
  93. for pkg := range w.p.allPkgs {
  94. pkgObjs[pkg] = nil
  95. }
  96. for obj := range index {
  97. pkgObjs[obj.Pkg()] = append(pkgObjs[obj.Pkg()], obj)
  98. }
  99. var pkgs []*types.Package
  100. for pkg, objs := range pkgObjs {
  101. pkgs = append(pkgs, pkg)
  102. sort.Slice(objs, func(i, j int) bool {
  103. return objs[i].Name() < objs[j].Name()
  104. })
  105. }
  106. sort.Slice(pkgs, func(i, j int) bool {
  107. return w.exportPath(pkgs[i]) < w.exportPath(pkgs[j])
  108. })
  109. w.uint64(uint64(len(pkgs)))
  110. for _, pkg := range pkgs {
  111. w.string(w.exportPath(pkg))
  112. w.string(pkg.Name())
  113. w.uint64(uint64(0)) // package height is not needed for go/types
  114. objs := pkgObjs[pkg]
  115. w.uint64(uint64(len(objs)))
  116. for _, obj := range objs {
  117. w.string(obj.Name())
  118. w.uint64(index[obj])
  119. }
  120. }
  121. }
  122. type iexporter struct {
  123. fset *token.FileSet
  124. out *bytes.Buffer
  125. localpkg *types.Package
  126. // allPkgs tracks all packages that have been referenced by
  127. // the export data, so we can ensure to include them in the
  128. // main index.
  129. allPkgs map[*types.Package]bool
  130. declTodo objQueue
  131. strings intWriter
  132. stringIndex map[string]uint64
  133. data0 intWriter
  134. declIndex map[types.Object]uint64
  135. typIndex map[types.Type]uint64
  136. }
  137. // stringOff returns the offset of s within the string section.
  138. // If not already present, it's added to the end.
  139. func (p *iexporter) stringOff(s string) uint64 {
  140. off, ok := p.stringIndex[s]
  141. if !ok {
  142. off = uint64(p.strings.Len())
  143. p.stringIndex[s] = off
  144. p.strings.uint64(uint64(len(s)))
  145. p.strings.WriteString(s)
  146. }
  147. return off
  148. }
  149. // pushDecl adds n to the declaration work queue, if not already present.
  150. func (p *iexporter) pushDecl(obj types.Object) {
  151. // Package unsafe is known to the compiler and predeclared.
  152. assert(obj.Pkg() != types.Unsafe)
  153. if _, ok := p.declIndex[obj]; ok {
  154. return
  155. }
  156. p.declIndex[obj] = ^uint64(0) // mark n present in work queue
  157. p.declTodo.pushTail(obj)
  158. }
  159. // exportWriter handles writing out individual data section chunks.
  160. type exportWriter struct {
  161. p *iexporter
  162. data intWriter
  163. currPkg *types.Package
  164. prevFile string
  165. prevLine int64
  166. }
  167. func (w *exportWriter) exportPath(pkg *types.Package) string {
  168. if pkg == w.p.localpkg {
  169. return ""
  170. }
  171. return pkg.Path()
  172. }
  173. func (p *iexporter) doDecl(obj types.Object) {
  174. w := p.newWriter()
  175. w.setPkg(obj.Pkg(), false)
  176. switch obj := obj.(type) {
  177. case *types.Var:
  178. w.tag('V')
  179. w.pos(obj.Pos())
  180. w.typ(obj.Type(), obj.Pkg())
  181. case *types.Func:
  182. sig, _ := obj.Type().(*types.Signature)
  183. if sig.Recv() != nil {
  184. panic(internalErrorf("unexpected method: %v", sig))
  185. }
  186. w.tag('F')
  187. w.pos(obj.Pos())
  188. w.signature(sig)
  189. case *types.Const:
  190. w.tag('C')
  191. w.pos(obj.Pos())
  192. w.value(obj.Type(), obj.Val())
  193. case *types.TypeName:
  194. if obj.IsAlias() {
  195. w.tag('A')
  196. w.pos(obj.Pos())
  197. w.typ(obj.Type(), obj.Pkg())
  198. break
  199. }
  200. // Defined type.
  201. w.tag('T')
  202. w.pos(obj.Pos())
  203. underlying := obj.Type().Underlying()
  204. w.typ(underlying, obj.Pkg())
  205. t := obj.Type()
  206. if types.IsInterface(t) {
  207. break
  208. }
  209. named, ok := t.(*types.Named)
  210. if !ok {
  211. panic(internalErrorf("%s is not a defined type", t))
  212. }
  213. n := named.NumMethods()
  214. w.uint64(uint64(n))
  215. for i := 0; i < n; i++ {
  216. m := named.Method(i)
  217. w.pos(m.Pos())
  218. w.string(m.Name())
  219. sig, _ := m.Type().(*types.Signature)
  220. w.param(sig.Recv())
  221. w.signature(sig)
  222. }
  223. default:
  224. panic(internalErrorf("unexpected object: %v", obj))
  225. }
  226. p.declIndex[obj] = w.flush()
  227. }
  228. func (w *exportWriter) tag(tag byte) {
  229. w.data.WriteByte(tag)
  230. }
  231. func (w *exportWriter) pos(pos token.Pos) {
  232. if w.p.fset == nil {
  233. w.int64(0)
  234. return
  235. }
  236. p := w.p.fset.Position(pos)
  237. file := p.Filename
  238. line := int64(p.Line)
  239. // When file is the same as the last position (common case),
  240. // we can save a few bytes by delta encoding just the line
  241. // number.
  242. //
  243. // Note: Because data objects may be read out of order (or not
  244. // at all), we can only apply delta encoding within a single
  245. // object. This is handled implicitly by tracking prevFile and
  246. // prevLine as fields of exportWriter.
  247. if file == w.prevFile {
  248. delta := line - w.prevLine
  249. w.int64(delta)
  250. if delta == deltaNewFile {
  251. w.int64(-1)
  252. }
  253. } else {
  254. w.int64(deltaNewFile)
  255. w.int64(line) // line >= 0
  256. w.string(file)
  257. w.prevFile = file
  258. }
  259. w.prevLine = line
  260. }
  261. func (w *exportWriter) pkg(pkg *types.Package) {
  262. // Ensure any referenced packages are declared in the main index.
  263. w.p.allPkgs[pkg] = true
  264. w.string(w.exportPath(pkg))
  265. }
  266. func (w *exportWriter) qualifiedIdent(obj types.Object) {
  267. // Ensure any referenced declarations are written out too.
  268. w.p.pushDecl(obj)
  269. w.string(obj.Name())
  270. w.pkg(obj.Pkg())
  271. }
  272. func (w *exportWriter) typ(t types.Type, pkg *types.Package) {
  273. w.data.uint64(w.p.typOff(t, pkg))
  274. }
  275. func (p *iexporter) newWriter() *exportWriter {
  276. return &exportWriter{p: p}
  277. }
  278. func (w *exportWriter) flush() uint64 {
  279. off := uint64(w.p.data0.Len())
  280. io.Copy(&w.p.data0, &w.data)
  281. return off
  282. }
  283. func (p *iexporter) typOff(t types.Type, pkg *types.Package) uint64 {
  284. off, ok := p.typIndex[t]
  285. if !ok {
  286. w := p.newWriter()
  287. w.doTyp(t, pkg)
  288. off = predeclReserved + w.flush()
  289. p.typIndex[t] = off
  290. }
  291. return off
  292. }
  293. func (w *exportWriter) startType(k itag) {
  294. w.data.uint64(uint64(k))
  295. }
  296. func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
  297. switch t := t.(type) {
  298. case *types.Named:
  299. w.startType(definedType)
  300. w.qualifiedIdent(t.Obj())
  301. case *types.Pointer:
  302. w.startType(pointerType)
  303. w.typ(t.Elem(), pkg)
  304. case *types.Slice:
  305. w.startType(sliceType)
  306. w.typ(t.Elem(), pkg)
  307. case *types.Array:
  308. w.startType(arrayType)
  309. w.uint64(uint64(t.Len()))
  310. w.typ(t.Elem(), pkg)
  311. case *types.Chan:
  312. w.startType(chanType)
  313. // 1 RecvOnly; 2 SendOnly; 3 SendRecv
  314. var dir uint64
  315. switch t.Dir() {
  316. case types.RecvOnly:
  317. dir = 1
  318. case types.SendOnly:
  319. dir = 2
  320. case types.SendRecv:
  321. dir = 3
  322. }
  323. w.uint64(dir)
  324. w.typ(t.Elem(), pkg)
  325. case *types.Map:
  326. w.startType(mapType)
  327. w.typ(t.Key(), pkg)
  328. w.typ(t.Elem(), pkg)
  329. case *types.Signature:
  330. w.startType(signatureType)
  331. w.setPkg(pkg, true)
  332. w.signature(t)
  333. case *types.Struct:
  334. w.startType(structType)
  335. w.setPkg(pkg, true)
  336. n := t.NumFields()
  337. w.uint64(uint64(n))
  338. for i := 0; i < n; i++ {
  339. f := t.Field(i)
  340. w.pos(f.Pos())
  341. w.string(f.Name())
  342. w.typ(f.Type(), pkg)
  343. w.bool(f.Anonymous())
  344. w.string(t.Tag(i)) // note (or tag)
  345. }
  346. case *types.Interface:
  347. w.startType(interfaceType)
  348. w.setPkg(pkg, true)
  349. n := t.NumEmbeddeds()
  350. w.uint64(uint64(n))
  351. for i := 0; i < n; i++ {
  352. f := t.Embedded(i)
  353. w.pos(f.Obj().Pos())
  354. w.typ(f.Obj().Type(), f.Obj().Pkg())
  355. }
  356. n = t.NumExplicitMethods()
  357. w.uint64(uint64(n))
  358. for i := 0; i < n; i++ {
  359. m := t.ExplicitMethod(i)
  360. w.pos(m.Pos())
  361. w.string(m.Name())
  362. sig, _ := m.Type().(*types.Signature)
  363. w.signature(sig)
  364. }
  365. default:
  366. panic(internalErrorf("unexpected type: %v, %v", t, reflect.TypeOf(t)))
  367. }
  368. }
  369. func (w *exportWriter) setPkg(pkg *types.Package, write bool) {
  370. if write {
  371. w.pkg(pkg)
  372. }
  373. w.currPkg = pkg
  374. }
  375. func (w *exportWriter) signature(sig *types.Signature) {
  376. w.paramList(sig.Params())
  377. w.paramList(sig.Results())
  378. if sig.Params().Len() > 0 {
  379. w.bool(sig.Variadic())
  380. }
  381. }
  382. func (w *exportWriter) paramList(tup *types.Tuple) {
  383. n := tup.Len()
  384. w.uint64(uint64(n))
  385. for i := 0; i < n; i++ {
  386. w.param(tup.At(i))
  387. }
  388. }
  389. func (w *exportWriter) param(obj types.Object) {
  390. w.pos(obj.Pos())
  391. w.localIdent(obj)
  392. w.typ(obj.Type(), obj.Pkg())
  393. }
  394. func (w *exportWriter) value(typ types.Type, v constant.Value) {
  395. w.typ(typ, nil)
  396. switch v.Kind() {
  397. case constant.Bool:
  398. w.bool(constant.BoolVal(v))
  399. case constant.Int:
  400. var i big.Int
  401. if i64, exact := constant.Int64Val(v); exact {
  402. i.SetInt64(i64)
  403. } else if ui64, exact := constant.Uint64Val(v); exact {
  404. i.SetUint64(ui64)
  405. } else {
  406. i.SetString(v.ExactString(), 10)
  407. }
  408. w.mpint(&i, typ)
  409. case constant.Float:
  410. f := constantToFloat(v)
  411. w.mpfloat(f, typ)
  412. case constant.Complex:
  413. w.mpfloat(constantToFloat(constant.Real(v)), typ)
  414. w.mpfloat(constantToFloat(constant.Imag(v)), typ)
  415. case constant.String:
  416. w.string(constant.StringVal(v))
  417. case constant.Unknown:
  418. // package contains type errors
  419. default:
  420. panic(internalErrorf("unexpected value %v (%T)", v, v))
  421. }
  422. }
  423. // constantToFloat converts a constant.Value with kind constant.Float to a
  424. // big.Float.
  425. func constantToFloat(x constant.Value) *big.Float {
  426. assert(x.Kind() == constant.Float)
  427. // Use the same floating-point precision (512) as cmd/compile
  428. // (see Mpprec in cmd/compile/internal/gc/mpfloat.go).
  429. const mpprec = 512
  430. var f big.Float
  431. f.SetPrec(mpprec)
  432. if v, exact := constant.Float64Val(x); exact {
  433. // float64
  434. f.SetFloat64(v)
  435. } else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int {
  436. // TODO(gri): add big.Rat accessor to constant.Value.
  437. n := valueToRat(num)
  438. d := valueToRat(denom)
  439. f.SetRat(n.Quo(n, d))
  440. } else {
  441. // Value too large to represent as a fraction => inaccessible.
  442. // TODO(gri): add big.Float accessor to constant.Value.
  443. _, ok := f.SetString(x.ExactString())
  444. assert(ok)
  445. }
  446. return &f
  447. }
  448. // mpint exports a multi-precision integer.
  449. //
  450. // For unsigned types, small values are written out as a single
  451. // byte. Larger values are written out as a length-prefixed big-endian
  452. // byte string, where the length prefix is encoded as its complement.
  453. // For example, bytes 0, 1, and 2 directly represent the integer
  454. // values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-,
  455. // 2-, and 3-byte big-endian string follow.
  456. //
  457. // Encoding for signed types use the same general approach as for
  458. // unsigned types, except small values use zig-zag encoding and the
  459. // bottom bit of length prefix byte for large values is reserved as a
  460. // sign bit.
  461. //
  462. // The exact boundary between small and large encodings varies
  463. // according to the maximum number of bytes needed to encode a value
  464. // of type typ. As a special case, 8-bit types are always encoded as a
  465. // single byte.
  466. //
  467. // TODO(mdempsky): Is this level of complexity really worthwhile?
  468. func (w *exportWriter) mpint(x *big.Int, typ types.Type) {
  469. basic, ok := typ.Underlying().(*types.Basic)
  470. if !ok {
  471. panic(internalErrorf("unexpected type %v (%T)", typ.Underlying(), typ.Underlying()))
  472. }
  473. signed, maxBytes := intSize(basic)
  474. negative := x.Sign() < 0
  475. if !signed && negative {
  476. panic(internalErrorf("negative unsigned integer; type %v, value %v", typ, x))
  477. }
  478. b := x.Bytes()
  479. if len(b) > 0 && b[0] == 0 {
  480. panic(internalErrorf("leading zeros"))
  481. }
  482. if uint(len(b)) > maxBytes {
  483. panic(internalErrorf("bad mpint length: %d > %d (type %v, value %v)", len(b), maxBytes, typ, x))
  484. }
  485. maxSmall := 256 - maxBytes
  486. if signed {
  487. maxSmall = 256 - 2*maxBytes
  488. }
  489. if maxBytes == 1 {
  490. maxSmall = 256
  491. }
  492. // Check if x can use small value encoding.
  493. if len(b) <= 1 {
  494. var ux uint
  495. if len(b) == 1 {
  496. ux = uint(b[0])
  497. }
  498. if signed {
  499. ux <<= 1
  500. if negative {
  501. ux--
  502. }
  503. }
  504. if ux < maxSmall {
  505. w.data.WriteByte(byte(ux))
  506. return
  507. }
  508. }
  509. n := 256 - uint(len(b))
  510. if signed {
  511. n = 256 - 2*uint(len(b))
  512. if negative {
  513. n |= 1
  514. }
  515. }
  516. if n < maxSmall || n >= 256 {
  517. panic(internalErrorf("encoding mistake: %d, %v, %v => %d", len(b), signed, negative, n))
  518. }
  519. w.data.WriteByte(byte(n))
  520. w.data.Write(b)
  521. }
  522. // mpfloat exports a multi-precision floating point number.
  523. //
  524. // The number's value is decomposed into mantissa × 2**exponent, where
  525. // mantissa is an integer. The value is written out as mantissa (as a
  526. // multi-precision integer) and then the exponent, except exponent is
  527. // omitted if mantissa is zero.
  528. func (w *exportWriter) mpfloat(f *big.Float, typ types.Type) {
  529. if f.IsInf() {
  530. panic("infinite constant")
  531. }
  532. // Break into f = mant × 2**exp, with 0.5 <= mant < 1.
  533. var mant big.Float
  534. exp := int64(f.MantExp(&mant))
  535. // Scale so that mant is an integer.
  536. prec := mant.MinPrec()
  537. mant.SetMantExp(&mant, int(prec))
  538. exp -= int64(prec)
  539. manti, acc := mant.Int(nil)
  540. if acc != big.Exact {
  541. panic(internalErrorf("mantissa scaling failed for %f (%s)", f, acc))
  542. }
  543. w.mpint(manti, typ)
  544. if manti.Sign() != 0 {
  545. w.int64(exp)
  546. }
  547. }
  548. func (w *exportWriter) bool(b bool) bool {
  549. var x uint64
  550. if b {
  551. x = 1
  552. }
  553. w.uint64(x)
  554. return b
  555. }
  556. func (w *exportWriter) int64(x int64) { w.data.int64(x) }
  557. func (w *exportWriter) uint64(x uint64) { w.data.uint64(x) }
  558. func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
  559. func (w *exportWriter) localIdent(obj types.Object) {
  560. // Anonymous parameters.
  561. if obj == nil {
  562. w.string("")
  563. return
  564. }
  565. name := obj.Name()
  566. if name == "_" {
  567. w.string("_")
  568. return
  569. }
  570. w.string(name)
  571. }
  572. type intWriter struct {
  573. bytes.Buffer
  574. }
  575. func (w *intWriter) int64(x int64) {
  576. var buf [binary.MaxVarintLen64]byte
  577. n := binary.PutVarint(buf[:], x)
  578. w.Write(buf[:n])
  579. }
  580. func (w *intWriter) uint64(x uint64) {
  581. var buf [binary.MaxVarintLen64]byte
  582. n := binary.PutUvarint(buf[:], x)
  583. w.Write(buf[:n])
  584. }
  585. func assert(cond bool) {
  586. if !cond {
  587. panic("internal error: assertion failed")
  588. }
  589. }
  590. // The below is copied from go/src/cmd/compile/internal/gc/syntax.go.
  591. // objQueue is a FIFO queue of types.Object. The zero value of objQueue is
  592. // a ready-to-use empty queue.
  593. type objQueue struct {
  594. ring []types.Object
  595. head, tail int
  596. }
  597. // empty returns true if q contains no Nodes.
  598. func (q *objQueue) empty() bool {
  599. return q.head == q.tail
  600. }
  601. // pushTail appends n to the tail of the queue.
  602. func (q *objQueue) pushTail(obj types.Object) {
  603. if len(q.ring) == 0 {
  604. q.ring = make([]types.Object, 16)
  605. } else if q.head+len(q.ring) == q.tail {
  606. // Grow the ring.
  607. nring := make([]types.Object, len(q.ring)*2)
  608. // Copy the old elements.
  609. part := q.ring[q.head%len(q.ring):]
  610. if q.tail-q.head <= len(part) {
  611. part = part[:q.tail-q.head]
  612. copy(nring, part)
  613. } else {
  614. pos := copy(nring, part)
  615. copy(nring[pos:], q.ring[:q.tail%len(q.ring)])
  616. }
  617. q.ring, q.head, q.tail = nring, 0, q.tail-q.head
  618. }
  619. q.ring[q.tail%len(q.ring)] = obj
  620. q.tail++
  621. }
  622. // popHead pops a node from the head of the queue. It panics if q is empty.
  623. func (q *objQueue) popHead() types.Object {
  624. if q.empty() {
  625. panic("dequeue empty")
  626. }
  627. obj := q.ring[q.head%len(q.ring)]
  628. q.head++
  629. return obj
  630. }