pcdata.go raw

   1  /**
   2   * Copyright 2023 ByteDance Inc.
   3   *
   4   * Licensed under the Apache License, Version 2.0 (the "License");
   5   * you may not use this file except in compliance with the License.
   6   * You may obtain a copy of the License at
   7   *
   8   *     http://www.apache.org/licenses/LICENSE-2.0
   9   *
  10   * Unless required by applicable law or agreed to in writing, software
  11   * distributed under the License is distributed on an "AS IS" BASIS,
  12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13   * See the License for the specific language governing permissions and
  14   * limitations under the License.
  15   */
  16  
  17  package loader
  18  
  19  import (
  20      `encoding/binary`
  21  )
  22  
  23  const (
  24      _N_PCDATA   = 4
  25  
  26      _PCDATA_UnsafePoint   = 0
  27      _PCDATA_StackMapIndex = 1
  28      _PCDATA_InlTreeIndex  = 2
  29      _PCDATA_ArgLiveIndex  = 3
  30  
  31      _PCDATA_INVALID_OFFSET = 0
  32  )
  33  
  34  const (
  35      // PCDATA_UnsafePoint values.
  36      PCDATA_UnsafePointSafe   = -1 // Safe for async preemption
  37      PCDATA_UnsafePointUnsafe = -2 // Unsafe for async preemption
  38  
  39      // PCDATA_Restart1(2) apply on a sequence of instructions, within
  40      // which if an async preemption happens, we should back off the PC
  41      // to the start of the sequence when resume.
  42      // We need two so we can distinguish the start/end of the sequence
  43      // in case that two sequences are next to each other.
  44      PCDATA_Restart1 = -3
  45      PCDATA_Restart2 = -4
  46  
  47      // Like PCDATA_RestartAtEntry, but back to function entry if async
  48      // preempted.
  49      PCDATA_RestartAtEntry = -5
  50  
  51      _PCDATA_START_VAL = -1
  52  )
  53  
  54  var emptyByte byte
  55  
  56  // Pcvalue is the program count corresponding to the value Val
  57  //   WARN: we use relative value here (to function entry)
  58  type Pcvalue struct {
  59      PC  uint32 // program count relative to function entry
  60      Val int32  // value relative to the value in function entry
  61  }
  62  
  63  // Pcdata represents pc->value mapping table.
  64  //   WARN: we use ** [Pcdata[i].PC, Pcdata[i+1].PC) **
  65  //   as the range where the Pcdata[i].Val is effective.
  66  type Pcdata []Pcvalue
  67  
  68  // see https://docs.google.com/document/d/1lyPIbmsYbXnpNj57a261hgOYVpNRcgydurVQIyZOz_o/pub
  69  func (self Pcdata) MarshalBinary() (data []byte, err error) {
  70      // delta value always starts from -1
  71      sv := int32(_PCDATA_START_VAL)
  72      sp := uint32(0)
  73      buf := make([]byte, binary.MaxVarintLen32)
  74      for _, v := range self {
  75          if v.PC < sp {
  76              panic("PC must be in ascending order!")
  77          }
  78          dp := uint64(v.PC - sp)
  79          dv := int64(v.Val - sv)
  80          if dv == 0 || dp == 0 {
  81              continue
  82          }
  83          n := binary.PutVarint(buf, dv)
  84          data = append(data, buf[:n]...)
  85          n2 := binary.PutUvarint(buf, dp)
  86          data = append(data, buf[:n2]...)
  87          sp = v.PC
  88          sv = v.Val
  89      }
  90      // put 0 to indicate ends
  91      data = append(data, 0)
  92      return
  93  }
  94