Repository: tetratelabs/wazero
Pull request #1469 (2023-05-15 08:25:57)

compiler: optimize struct layout to reduce memory footprint
This PR implements a few optimizations detected by https://pkg.go.dev/golang.org/x/tools@v0.9.1/go/analysis/passes/fieldalignment/cmd/fieldalignment

The one I was most interested in was reducing the size of `arm64.nodeImpl` because it represents a significant source of memory allocations since we create so many of those objects.

```
File: wazero
Type: alloc_space
Time: May 15, 2023 at 1:24am (PDT)
Showing nodes accounting for -8.79MB, 2.99% of 294.14MB total
Dropped 7 nodes (cum <= 1.47MB)
      flat  flat%   sum%        cum   cum%
   -5.57MB  1.89%  1.89%    -5.57MB  1.89%  github.com/tetratelabs/wazero/internal/asm/arm64.(*nodePool).allocNode (inline)
   -1.97MB  0.67%  2.56%    -5.52MB  1.88%  github.com/tetratelabs/wazero/internal/engine/compiler.compileWasmFunction
   -1.50MB  0.51%  3.07%    -1.50MB  0.51%  debug/dwarf.(*Data).parseAbbrev
    1.50MB  0.51%  2.56%     1.50MB  0.51%  github.com/tetratelabs/wazero/internal/engine/compiler.(*runtimeValueLocationStack).cloneFrom (inline)
    1.29MB  0.44%  2.13%     1.29MB  0.44%  github.com/tetratelabs/wazero/internal/engine/compiler.(*arm64Compiler).label
   -1.09MB  0.37%  2.49%    -1.09MB  0.37%  github.com/tetratelabs/wazero/internal/wasm/binary.decodeCode
   -1.01MB  0.34%  2.84%    -1.01MB  0.34%  github.com/tetratelabs/wazero/internal/engine/compiler.(*runtimeValueLocationStack).push (inline)
   -0.79MB  0.27%  3.11%    -0.79MB  0.27%  bytes.growSlice
    0.78MB  0.26%  2.84%     0.78MB  0.26%  github.com/tetratelabs/wazero/internal/wasm/binary.decodeDataSegment
    0.55MB  0.19%  2.66%     0.55MB  0.19%  github.com/tetratelabs/wazero/internal/asm/arm64.(*AssemblerImpl).encodeRelativeBranch
   -0.51MB  0.17%  2.83%    -0.51MB  0.17%  github.com/tetratelabs/wazero/internal/wasm/binary.decodeElementInitValueVector
   -0.47MB  0.16%  2.99%    -0.47MB  0.16%  github.com/tetratelabs/wazero/internal/wazeroir.(*Compiler).emit
```

Other optimizations in the assembler were automated by `fieldalignment -fix`.

achille-roussel: Thanks for pointing it out, apparently `fieldalignment -fix` removed the comments when it reodered the fields 🤦 

Patch:
diff --git a/internal/asm/amd64/impl.go b/internal/asm/amd64/impl.go
index e2d45a54..a3a1c8dd 100644
--- a/internal/asm/amd64/impl.go
+++ b/internal/asm/amd64/impl.go
@@ -12,35 +12,37 @@ import (
 
 // nodeImpl implements asm.Node for amd64.
 type nodeImpl struct {
-	instruction asm.Instruction
-
-	offsetInBinary asm.NodeOffsetInBinary
-
 	// jumpTarget holds the target node in the linked for the jump-kind instruction.
 	jumpTarget *nodeImpl
-	flag       nodeFlag
+
 	// prev and next hold the prev/next node from this node in the assembled linked list.
 	prev, next *nodeImpl
 
-	types                    operandTypes
-	srcReg, dstReg           asm.Register
-	srcConst, dstConst       asm.ConstantValue
-	srcMemIndex, dstMemIndex asm.Register
-	srcMemScale, dstMemScale byte
+	// forwardJumpOrigins hold all the nodes trying to jump into this node as a
+	// singly linked list. In other words, all the nodes with .jumpTarget == this.
+	forwardJumpOrigins *nodeImpl
+
+	staticConst *asm.StaticConst
 
-	arg byte
+	dstConst       asm.ConstantValue
+	offsetInBinary asm.NodeOffsetInBinary
+	srcConst       asm.ConstantValue
+	instruction    asm.Instruction
 
 	// readInstructionAddressBeforeTargetInstruction holds the instruction right before the target of
 	// read instruction address instruction. See asm.assemblerBase.CompileReadInstructionAddress.
 	readInstructionAddressBeforeTargetInstruction asm.Instruction
+	flag                                          nodeFlag
+	types                                         operandTypes
+	srcReg, dstReg                                asm.Register
+	srcMemIndex, dstMemIndex                      asm.Register
+	srcMemScale, dstMemScale                      byte
+	arg                                           byte
 
-	// forwardJumpOrigins hold all the nodes trying to jump into this node as a singly linked list. In other words, all the nodes with .jumpTarget == this.
-	forwardJumpOrigins *nodeImpl
 	// staticConstReferrersAdded true if this node is already added into AssemblerImpl.staticConstReferrers.
 	// Only used when staticConst is not nil. Through re-assembly, we might end up adding multiple times which causes unnecessary
 	// allocations, so we use this flag to do it once.
 	staticConstReferrersAdded bool
-	staticConst               *asm.StaticConst
 }
 
 type nodeFlag byte
@@ -218,20 +220,24 @@ func (o operandTypes) String() (ret string) {
 type (
 	// AssemblerImpl implements Assembler.
 	AssemblerImpl struct {
-		nodePool nodePool
+		root    *nodeImpl
+		current *nodeImpl
+		buf     *bytes.Buffer
 		asm.BaseAssemblerImpl
-		root, current   *nodeImpl
-		buf             *bytes.Buffer
-		forceReAssemble bool
-		// MaxDisplacementForConstantPool is fixed to defaultMaxDisplacementForConstantPool
-		// but have it as an exported field here for testability.
-		MaxDisplacementForConstantPool int
-
 		readInstructionAddressNodes []*nodeImpl
+
 		// staticConstReferrers maintains the list of static const referrers which requires the
 		// offset resolution after finalizing the binary layout.
 		staticConstReferrers []staticConstReferrer
-		pool                 asm.StaticConstPool
+
+		nodePool nodePool
+		pool     asm.StaticConstPool
+
+		// MaxDisplacementForConstantPool is fixed to defaultMaxDisplacementForConstantPool
+		// but have it as an exported field here for testability.
+		MaxDisplacementForConstantPool int
+
+		forceReAssemble bool
 	}
 
 	// staticConstReferrer represents a referrer of a asm.StaticConst.
diff --git a/internal/asm/arm64/impl.go b/internal/asm/arm64/impl.go
index 69662d14..138cd871 100644
--- a/internal/asm/arm64/impl.go
+++ b/internal/asm/arm64/impl.go
@@ -10,27 +10,25 @@ import (
 )
 
 type nodeImpl struct {
-	instruction asm.Instruction
-
-	offsetInBinaryField asm.NodeOffsetInBinary // Field suffix to dodge conflict with OffsetInBinary
-
 	// jumpTarget holds the target node in the linked for the jump-kind instruction.
 	jumpTarget *nodeImpl
 	// next holds the next node from this node in the assembled linked list.
-	next *nodeImpl
+	next        *nodeImpl
+	staticConst *asm.StaticConst
 
+	instruction                      asm.Instruction
 	types                            operandTypes
 	srcReg, srcReg2, dstReg, dstReg2 asm.Register
 	srcConst, dstConst               asm.ConstantValue
 
-	vectorArrangement              VectorArrangement
-	srcVectorIndex, dstVectorIndex VectorIndex
+	offsetInBinary asm.NodeOffsetInBinary
 
 	// readInstructionAddressBeforeTargetInstruction holds the instruction right before the target of
 	// read instruction address instruction. See asm.assemblerBase.CompileReadInstructionAddress.
 	readInstructionAddressBeforeTargetInstruction asm.Instruction
 
-	staticConst *asm.StaticConst
+	vectorArrangement              VectorArrangement
+	srcVectorIndex, dstVectorIndex VectorIndex
 }
 
 // AssignJumpTarget implements the same method as documented on asm.Node.
@@ -50,7 +48,7 @@ func (n *nodeImpl) AssignSourceConstant(value asm.ConstantValue) {
 
 // OffsetInBinary implements the same method as documented on asm.Node.
 func (n *nodeImpl) OffsetInBinary() asm.NodeOffsetInBinary {
-	return n.offsetInBinaryField
+	return n.offsetInBinary
 }
 
 // String implements fmt.Stringer.
@@ -201,17 +199,21 @@ const (
 
 // AssemblerImpl implements Assembler.
 type AssemblerImpl struct {
-	nodePool nodePool
+	root    *nodeImpl
+	current *nodeImpl
+	buf     *bytes.Buffer
 	asm.BaseAssemblerImpl
-	root, current     *nodeImpl
-	buf               *bytes.Buffer
-	temporaryRegister asm.Register
-	nodeCount         int
-	pool              asm.StaticConstPool
+	relativeJumpNodes   []*nodeImpl
+	adrInstructionNodes []*nodeImpl
+	nodePool            nodePool
+	pool                asm.StaticConstPool
+	nodeCount           int
+
 	// MaxDisplacementForConstantPool is fixed to defaultMaxDisplacementForConstPool
 	// but have it as a field here for testability.
-	MaxDisplacementForConstantPool         int
-	relativeJumpNodes, adrInstructionNodes []*nodeImpl
+	MaxDisplacementForConstantPool int
+
+	temporaryRegister asm.Register
 }
 
 const nodePageSize = 128
@@ -338,7 +340,7 @@ func (a *AssemblerImpl) Assemble() ([]byte, error) {
 	a.buf.Grow(a.nodeCount * 8)
 
 	for n := a.root; n != nil; n = n.next {
-		n.offsetInBinaryField = uint64(a.buf.Len())
+		n.offsetInBinary = uint64(a.buf.Len())
 		if err := a.encodeNode(n); err != nil {
 			return nil, err
 		}
@@ -2876,8 +2878,8 @@ func (a *AssemblerImpl) encodeStaticConstToVectorRegister(n *nodeImpl) (err erro
 // advancedSIMDTwoRegisterMisc holds information to encode instructions as "Advanced SIMD two-register miscellaneous" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDTwoRegisterMisc = map[asm.Instruction]struct {
-	u, opcode byte
 	qAndSize  map[VectorArrangement]qAndSize
+	u, opcode byte
 }{
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/NOT--Bitwise-NOT--vector--?lang=en
 	NOT: {
@@ -3026,8 +3028,8 @@ var advancedSIMDTwoRegisterMisc = map[asm.Instruction]struct {
 // advancedSIMDThreeDifferent holds information to encode instructions as "Advanced SIMD three different" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDThreeDifferent = map[asm.Instruction]struct {
-	u, opcode byte
 	qAndSize  map[VectorArrangement]qAndSize
+	u, opcode byte
 }{
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UMLAL--UMLAL2--vector---Unsigned-Multiply-Add-Long--vector--?lang=en
 	VUMLAL: {u: 0b1, opcode: 0b1000, qAndSize: map[VectorArrangement]qAndSize{
@@ -3064,8 +3066,8 @@ var advancedSIMDThreeDifferent = map[asm.Instruction]struct {
 // advancedSIMDThreeSame holds information to encode instructions as "Advanced SIMD three same" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDThreeSame = map[asm.Instruction]struct {
-	u, opcode byte
 	qAndSize  map[VectorArrangement]qAndSize
+	u, opcode byte
 }{
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/AND--vector---Bitwise-AND--vector--?lang=en
 	VAND: {
@@ -3273,8 +3275,8 @@ var defaultQAndSize = map[VectorArrangement]qAndSize{
 // advancedSIMDAcrossLanes holds information to encode instructions as "Advanced SIMD across lanes" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDAcrossLanes = map[asm.Instruction]struct {
-	u, opcode byte
 	qAndSize  map[VectorArrangement]qAndSize
+	u, opcode byte
 }{
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/ADDV--Add-across-Vector-?lang=en
 	ADDV: {
@@ -3310,8 +3312,8 @@ var advancedSIMDAcrossLanes = map[asm.Instruction]struct {
 // advancedSIMDScalarPairwise holds information to encode instructions as "Advanced SIMD scalar pairwise" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDScalarPairwise = map[asm.Instruction]struct {
-	u, opcode byte
 	size      map[VectorArrangement]byte
+	u, opcode byte
 }{
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/ADDP--scalar---Add-Pair-of-elements--scalar--?lang=en
 	ADDP: {u: 0b0, opcode: 0b11011, size: map[VectorArrangement]byte{VectorArrangement2D: 0b11}},
@@ -3320,9 +3322,9 @@ var advancedSIMDScalarPairwise = map[asm.Instruction]struct {
 // advancedSIMDCopy holds information to encode instructions as "Advanced SIMD copy" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDCopy = map[asm.Instruction]struct {
-	op byte
 	// TODO: extract common implementation of resolver.
 	resolver func(srcIndex, dstIndex VectorIndex, arr VectorArrangement) (imm5, imm4, q byte, err error)
+	op       byte
 }{
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/DUP--element---Duplicate-vector-element-to-vector-or-scalar-?lang=en
 	DUPELEM: {op: 0, resolver: func(srcIndex, dstIndex VectorIndex, arr VectorArrangement) (imm5, imm4, q byte, err error) {
@@ -3463,8 +3465,8 @@ var advancedSIMDCopy = map[asm.Instruction]struct {
 // advancedSIMDTableLookup holds information to encode instructions as "Advanced SIMD table lookup" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDTableLookup = map[asm.Instruction]struct {
-	op, op2, Len byte
 	q            map[VectorArrangement]byte
+	op, op2, Len byte
 }{
 	TBL1: {op: 0, op2: 0, Len: 0b00, q: map[VectorArrangement]byte{VectorArrangement16B: 0b1, VectorArrangement8B: 0b0}},
 	TBL2: {op: 0, op2: 0, Len: 0b01, q: map[VectorArrangement]byte{VectorArrangement16B: 0b1, VectorArrangement8B: 0b0}},
@@ -3473,9 +3475,9 @@ var advancedSIMDTableLookup = map[asm.Instruction]struct {
 // advancedSIMDShiftByImmediate holds information to encode instructions as "Advanced SIMD shift by immediate" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDShiftByImmediate = map[asm.Instruction]struct {
-	U, opcode   byte
 	q           map[VectorArrangement]byte
 	immResolver func(shiftAmount int64, arr VectorArrangement) (immh, immb byte, err error)
+	U, opcode   byte
 }{
 	// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/SSHLL--SSHLL2--Signed-Shift-Left-Long--immediate--
 	SSHLL: {
diff --git a/internal/asm/assembler.go b/internal/asm/assembler.go
index 9d2dd79a..79ecfefd 100644
--- a/internal/asm/assembler.go
+++ b/internal/asm/assembler.go
@@ -52,11 +52,12 @@ type ConstantValue = int64
 // StaticConst represents an arbitrary constant bytes which are pooled and emitted by assembler into the binary.
 // These constants can be referenced by instructions.
 type StaticConst struct {
+	// offsetFinalizedCallbacks holds callbacks which are called when .OffsetInBinary is finalized by assembler implementation.
+	offsetFinalizedCallbacks []func(offsetOfConstInBinary uint64)
+
 	Raw []byte
 	// OffsetInBinary is the offset of this static const in the result binary.
 	OffsetInBinary uint64
-	// offsetFinalizedCallbacks holds callbacks which are called when .OffsetInBinary is finalized by assembler implementation.
-	offsetFinalizedCallbacks []func(offsetOfConstInBinary uint64)
 }
 
 // NewStaticConst returns the pointer to the new NewStaticConst for given bytes.
@@ -79,13 +80,14 @@ func (s *StaticConst) SetOffsetInBinary(offset uint64) {
 
 // StaticConstPool holds a bulk of StaticConst which are yet to be emitted into the binary.
 type StaticConstPool struct {
-	// FirstUseOffsetInBinary holds the offset of the first instruction which accesses this const pool .
-	FirstUseOffsetInBinary NodeOffsetInBinary
-	Consts                 []*StaticConst
 	// addedConsts is used to deduplicate the consts to reduce the final size of binary.
 	// Note: we can use map on .consts field and remove this field,
 	// but we have the separate field for deduplication in order to have deterministic assembling behavior.
 	addedConsts map[*StaticConst]struct{}
+
+	Consts []*StaticConst
+	// FirstUseOffsetInBinary holds the offset of the first instruction which accesses this const pool .
+	FirstUseOffsetInBinary NodeOffsetInBinary
 	// PoolSizeInBytes is the current size of the pool in bytes.
 	PoolSizeInBytes int
 }


Test patch:
diff --git a/internal/asm/arm64/impl_1_test.go b/internal/asm/arm64/impl_1_test.go
index 68cf8034..c3696fec 100644
--- a/internal/asm/arm64/impl_1_test.go
+++ b/internal/asm/arm64/impl_1_test.go
@@ -589,9 +589,11 @@ func Test_CompileStaticConstToRegister(t *testing.T) {
 
 func Test_checkRegisterToRegisterType(t *testing.T) {
 	tests := []struct {
-		src, dst                     asm.Register
-		requireSrcInt, requireDstInt bool
-		expErr                       string
+		expErr        string
+		src           asm.Register
+		dst           asm.Register
+		requireSrcInt bool
+		requireDstInt bool
 	}{
 		{src: RegR10, dst: RegR30, requireSrcInt: true, requireDstInt: true, expErr: ""},
 		{src: RegR10, dst: RegR30, requireSrcInt: false, requireDstInt: true, expErr: "src requires float register but got R10"},
@@ -652,8 +654,8 @@ func TestAssemblerImpl_encodeNoneToNone(t *testing.T) {
 
 func Test_validateMemoryOffset(t *testing.T) {
 	tests := []struct {
-		offset int64
 		expErr string
+		offset int64
 	}{
 		{offset: 0},
 		{offset: -256},
@@ -1065,13 +1067,15 @@ func TestAssemblerImpl_EncodeMemoryToVectorRegister(t *testing.T) {
 
 func TestAssemblerImpl_EncodeVectorRegisterToVectorRegister(t *testing.T) {
 	tests := []struct {
-		name               string
-		x1, x2             asm.Register
-		inst               asm.Instruction
-		c                  asm.ConstantValue
-		arr                VectorArrangement
-		srcIndex, dstIndex VectorIndex
-		exp                []byte
+		name     string
+		exp      []byte
+		c        asm.ConstantValue
+		inst     asm.Instruction
+		x1       asm.Register
+		x2       asm.Register
+		arr      VectorArrangement
+		srcIndex VectorIndex
+		dstIndex VectorIndex
 	}{
 		{
 			inst: XTN,
@@ -2818,8 +2822,8 @@ func TestAssemblerImpl_EncodeThreeRegistersToRegister(t *testing.T) {
 
 	tests := []struct {
 		name string
-		inst asm.Instruction
 		exp  []byte
+		inst asm.Instruction
 	}{
 		{
 			name: "MSUB/src1=R1,src2=R10,src3=R30,dst=R11",
@@ -3988,9 +3992,9 @@ func TestAssemblerImpl_encodeADR_staticConst(t *testing.T) {
 
 	tests := []struct {
 		name                   string
-		reg                    asm.Register
-		offsetOfConstInBinary  uint64
 		expADRInstructionBytes []byte
+		offsetOfConstInBinary  uint64
+		reg                    asm.Register
 	}{
 		{
 			// #8 = offsetOfConstInBinary - beforeADRByteNum.
diff --git a/internal/asm/arm64/impl_3_test.go b/internal/asm/arm64/impl_3_test.go
index 4a1d398c..6852272f 100644
--- a/internal/asm/arm64/impl_3_test.go
+++ b/internal/asm/arm64/impl_3_test.go
@@ -32,10 +32,12 @@ func TestAssemblerImpl_EncodeTwoRegistersToRegister(t *testing.T) {
 	})
 
 	tests := []struct {
-		name           string
-		inst           asm.Instruction
-		src, src2, dst asm.Register
-		exp            []byte
+		name string
+		exp  []byte
+		inst asm.Instruction
+		src  asm.Register
+		src2 asm.Register
+		dst  asm.Register
 	}{
 		{name: "src=RZR,src2=RZR,dst=RZR", inst: AND, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0x1f, 0x8a}},
 		{name: "src=RZR,src2=RZR,dst=R10", inst: AND, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0x1f, 0x8a}},
@@ -646,10 +648,10 @@ func TestAssemblerImpl_EncodeRegisterAndConstToNone(t *testing.T) {
 
 	tests := []struct {
 		name string
+		exp  []byte
+		c    int64
 		inst asm.Instruction
 		reg  asm.Register
-		c    int64
-		exp  []byte
 	}{
 		{name: "R1, 0", inst: CMP, reg: RegR1, c: 0, exp: []byte{0x3f, 0x0, 0x0, 0xf1}},
 		{name: "R1, 10", inst: CMP, reg: RegR1, c: 10, exp: []byte{0x3f, 0x28, 0x0, 0xf1}},
@@ -704,10 +706,11 @@ func TestAssemblerImpl_EncodeRegisterToRegister(t *testing.T) {
 	})
 
 	tests := []struct {
-		name     string
-		inst     asm.Instruction
-		src, dst asm.Register
-		exp      []byte
+		name string
+		exp  []byte
+		inst asm.Instruction
+		src  asm.Register
+		dst  asm.Register
 	}{
 		{name: "MOV/src=RegSP,dst=R10", inst: MOVD, src: RegSP, dst: RegR10, exp: []byte{0xea, 0x3, 0x0, 0x91}},
 		{name: "MOV/src=RegSP,dst=R30", inst: MOVD, src: RegSP, dst: RegR30, exp: []byte{0xfe, 0x3, 0x0, 0x91}},
diff --git a/internal/asm/arm64/impl_4_test.go b/internal/asm/arm64/impl_4_test.go
index 27de54e6..d54fbc8e 100644
--- a/internal/asm/arm64/impl_4_test.go
+++ b/internal/asm/arm64/impl_4_test.go
@@ -40,9 +40,9 @@ func TestAssemblerImpl_encodeJumpToRegister(t *testing.T) {
 
 	tests := []struct {
 		name   string
+		expHex string
 		inst   asm.Instruction
 		reg    asm.Register
-		expHex string
 	}{
 		{
 			name:   "B",
@@ -665,8 +665,8 @@ func TestAssemblerImpl_encodeReadInstructionAddress(t *testing.T) {
 	t.Run("ok", func(t *testing.T) {
 		tests := []struct {
 			name                   string
-			numDummyInstructions   int
 			expADRInstructionBytes []byte
+			numDummyInstructions   int
 		}{
 			{
 				name:                   "< 8-bit offset",
@@ -718,7 +718,7 @@ func TestAssemblerImpl_encodeReadInstructionAddress(t *testing.T) {
 					actual[pos:pos+4], hex.EncodeToString(actual))
 
 				require.Equal(t, uint64(4+tc.numDummyInstructions*4+4),
-					target.offsetInBinaryField-adrInst.offsetInBinaryField)
+					target.offsetInBinary-adrInst.offsetInBinary)
 			})
 		}
 	})
@@ -744,14 +744,14 @@ func TestAssemblerImpl_encodeReadInstructionAddress(t *testing.T) {
 				a.CompileConstToRegister(MOVD, 1000, RegR10)
 
 				for n := a.root; n != nil; n = n.next {
-					n.offsetInBinaryField = uint64(a.buf.Len())
+					n.offsetInBinary = uint64(a.buf.Len())
 
 					err := a.encodeNode(n)
 					require.NoError(t, err)
 				}
 
 				targetNode := a.current
-				targetNode.offsetInBinaryField = u64
+				targetNode.offsetInBinary = u64
 
 				n := a.adrInstructionNodes[0]
 				err := a.finalizeADRInstructionNode(nil, n)
diff --git a/internal/asm/arm64/impl_6_test.go b/internal/asm/arm64/impl_6_test.go
index 4c678755..45d16c6d 100644
--- a/internal/asm/arm64/impl_6_test.go
+++ b/internal/asm/arm64/impl_6_test.go
@@ -35,7 +35,7 @@ func TestAssemblerImpl_EncodeRelativeJump(t *testing.T) {
 			tc := tt
 			t.Run(tc.name, func(t *testing.T) {
 				a := NewAssembler(asm.NilRegister)
-				n := &nodeImpl{instruction: tc.inst, types: operandTypesNoneToBranch, offsetInBinaryField: 0, jumpTarget: &nodeImpl{offsetInBinaryField: tc.offset}}
+				n := &nodeImpl{instruction: tc.inst, types: operandTypesNoneToBranch, offsetInBinary: 0, jumpTarget: &nodeImpl{offsetInBinary: tc.offset}}
 				err := a.encodeRelativeBranch(n)
 				require.NoError(t, err)
 				_, err = a.Assemble()
@@ -58,11 +58,11 @@ func TestAssemblerImpl_EncodeRelativeJump(t *testing.T) {
 				expErr: "SUB is unsupported for NoneToBranch type",
 			},
 			{
-				n:      &nodeImpl{instruction: B, types: operandTypesNoneToBranch, offsetInBinaryField: 0, jumpTarget: &nodeImpl{offsetInBinaryField: uint64(maxSignedInt26)*4 + 4}},
+				n:      &nodeImpl{instruction: B, types: operandTypesNoneToBranch, offsetInBinary: 0, jumpTarget: &nodeImpl{offsetInBinary: uint64(maxSignedInt26)*4 + 4}},
 				expErr: fmt.Sprintf("relative jump offset %d/4 must be within %d and %d", maxSignedInt26*4+4, minSignedInt26, maxSignedInt26),
 			},
 			{
-				n:      &nodeImpl{instruction: BCONDEQ, types: operandTypesNoneToBranch, offsetInBinaryField: 0, jumpTarget: &nodeImpl{offsetInBinaryField: uint64(maxSignedInt19)*4 + 4}},
+				n:      &nodeImpl{instruction: BCONDEQ, types: operandTypesNoneToBranch, offsetInBinary: 0, jumpTarget: &nodeImpl{offsetInBinary: uint64(maxSignedInt19)*4 + 4}},
 				expErr: fmt.Sprintf("BUG: relative jump offset %d/4(=%d) must be within %d and %d", maxSignedInt19*4+4, maxSignedInt19+1, minSignedInt19, maxSignedInt19),
 			},
 		}
@@ -83,11 +83,13 @@ func TestAssemblerImpl_EncodeRelativeJump(t *testing.T) {
 	})
 
 	tests := []struct {
-		name                                                                      string
-		inst                                                                      asm.Instruction
-		forward                                                                   bool
-		instructionsInPreamble, instructionsBeforeBranch, instructionsAfterBranch int
-		expHex                                                                    string
+		name                     string
+		expHex                   string
+		instructionsInPreamble   int
+		instructionsBeforeBranch int
+		instructionsAfterBranch  int
+		inst                     asm.Instruction
+		forward                  bool
 	}{
 		{name: "B/forward=true(before=0,after=10)", inst: B, forward: true, instructionsInPreamble: 0, instructionsBeforeBranch: 0, instructionsAfterBranch: 10, expHex: "0b0000140a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d2"},
 		{name: "B/forward=true(before=10,after=10)", inst: B, forward: true, instructionsInPreamble: 0, instructionsBeforeBranch: 10, instructionsAfterBranch: 10, expHex: "0a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20b0000140a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d20a7d80d2"},