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