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