gojit

package module
v0.0.0-...-5808a49 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2026 License: MIT Imports: 6 Imported by: 0

README

aabalke/gojit: Jit Compiler for Golang

aabalke/gojit is a revival of nelhage/gojit and rasky/gojit, providing jit compilation for Golang version 1.17+. The major functionality this fork adds is the ability for Go functions to be called from jit code, without causing errors from stack checks during garbage collection or stack growth.

Resources

Writeup

Video

Requirements

This jit compiler requires an amd64/arm64 system, and go version 1.17+. For handling in golang version 1.16 and earlier please read.

If a Go function is called from jit code, the Go functions must have a nosplit directive. If the JIT mutates variables though pointers, those variables must be heap allocated, and/or global.

Examples

See the example directory for basic examples, or see the Guac Emulator if you are interested in a real-life example. It includes the setup of multiple JIT pages, analysis and metrics for JIT compilation thresholds, invalidation, and an LRU cache for invalidating dead JIT compiler blocks.

Documentation

Overview

Package gojit contains basic support for writing JITs in golang. It contains functions for allocating byte slices in executable memory, and converting between such slices and golang function types.

Index

Constants

View Source
const (
	PREFIX_LOCK     = 0xF0
	PREFIX_REPNZ    = 0xF2
	PREFIX_REPZ     = 0xF3
	PREFIX_SEG_CS   = 0x2E
	PREFIX_SEG_SS   = 0x36
	PREFIX_SEG_DS   = 0x3E
	PREFIX_SEG_ES   = 0x26
	PREFIX_SEG_FS   = 0x64
	PREFIX_SEG_GS   = 0x65
	PREFIX_OPSIZE   = 0x66
	PREFIX_ADDRSIZE = 0x67

	MOD_INDIR        = 0x0
	MOD_INDIR_DISP8  = 0x1
	MOD_INDIR_DISP32 = 0x2
	MOD_REG          = 0x3

	SCALE_1 = 0x0
	SCALE_2 = 0x1
	SCALE_4 = 0x2
	SCALE_8 = 0x3

	/* overflow */
	CC_O  = 0x0
	CC_NO = 0x1
	/* unsigned comparisons */
	CC_B  = 0x2
	CC_AE = 0x3
	CC_BE = 0x6
	CC_A  = 0x7
	/* zero */
	CC_Z  = 0x4
	CC_NZ = 0x5
	/* sign */
	CC_S  = 0x8
	CC_NS = 0x9
	/* parity */
	CC_P  = 0xA
	CC_NP = 0xB
	/* unsigned comparisons */
	CC_L  = 0xC
	CC_GE = 0xD
	CC_LE = 0xE
	CC_G  = 0xF

	/* alternative mnemonics */
	CC_C  = CC_B
	CC_NC = CC_AE

	PFX_REX = 0x40
	REXW    = 0x08
	REXR    = 0x04
	REXX    = 0x02
	REXB    = 0x01

	REG_DISP32 = 5
	REG_SIB    = 4
)
View Source
const PageSize = 4096

PageSize is the size of a memory page. The len argument to Alloc should be an integer multiple of the page size.

Variables

View Source
var (
	Al  = Register{0, 8}
	Ax  = Register{0, 16}
	Eax = Register{0, 32}
	Rax = Register{0, 64}
	Cl  = Register{1, 8}
	Cx  = Register{1, 16}
	Ecx = Register{1, 32}
	Rcx = Register{1, 64}
	Dl  = Register{2, 8}
	Dx  = Register{2, 16}
	Edx = Register{2, 32}
	Rdx = Register{2, 64}
	Bl  = Register{3, 8}
	Bx  = Register{3, 16}
	Ebx = Register{3, 32}
	Rbx = Register{3, 64}
	Esp = Register{4, 32}
	Rsp = Register{4, 64}
	Ebp = Register{5, 32}
	Rbp = Register{5, 64}
	Esi = Register{6, 32}
	Rsi = Register{6, 64}
	Di  = Register{7, 8}
	Edi = Register{7, 32}
	Rdi = Register{7, 64}

	R8d  = Register{8, 32}
	R8   = Register{8, 64}
	R9d  = Register{9, 32}
	R9   = Register{9, 64}
	R10d = Register{10, 32}
	R10  = Register{10, 64}
	R11d = Register{11, 32}
	R11  = Register{11, 64}
	R12d = Register{12, 32}
	R12  = Register{12, 64}
	R13d = Register{13, 32}
	R13  = Register{13, 64}
	R14d = Register{14, 32}
	R14  = Register{14, 64}
	R15d = Register{15, 32}
	R15  = Register{15, 64}
)
View Source
var (
	Scale1 = Scale{SCALE_1}
	Scale2 = Scale{SCALE_2}
	Scale4 = Scale{SCALE_4}
	Scale8 = Scale{SCALE_8}
)
View Source
var (
	InstAdd  = &Instruction{"add", nil, ImmRm{j{0x81}, 0}, ImmRm{j{0x83}, 0}, j{0x01}, j{0x03}, 64}
	InstAddb = &Instruction{"addb", nil, ImmRm{j{0x80}, 0}, ImmRm{}, j{0x00}, j{0x02}, 8}

	InstAdc  = &Instruction{"adc", nil, ImmRm{j{0x81}, 2}, ImmRm{j{0x83}, 2}, j{0x11}, j{0x13}, 64}
	InstAdcb = &Instruction{"adcb", nil, ImmRm{j{0x80}, 2}, ImmRm{}, j{0x10}, j{0x12}, 8}

	InstAnd  = &Instruction{"and", nil, ImmRm{j{0x81}, 4}, ImmRm{j{0x83}, 4}, j{0x21}, j{0x23}, 64}
	InstAndb = &Instruction{"andb", nil, ImmRm{j{0x80}, 4}, ImmRm{}, j{0x20}, j{0x22}, 8}

	InstCmp  = &Instruction{"cmp", nil, ImmRm{j{0x81}, 7}, ImmRm{j{0x83}, 7}, j{0x39}, j{0x3B}, 64}
	InstCmpb = &Instruction{"cmpb", nil, ImmRm{j{0x80}, 7}, ImmRm{}, j{0x38}, j{0x3A}, 8}

	InstOr  = &Instruction{"or", nil, ImmRm{j{0x81}, 1}, ImmRm{j{0x83}, 1}, j{0x09}, j{0x0B}, 64}
	InstOrb = &Instruction{"orb", nil, ImmRm{j{0x80}, 1}, ImmRm{}, j{0x08}, j{0x0A}, 8}

	InstSbb  = &Instruction{"sbb", nil, ImmRm{j{0x81}, 3}, ImmRm{j{0x83}, 3}, j{0x19}, j{0x1B}, 64}
	InstSbbb = &Instruction{"sbbb", nil, ImmRm{j{0x80}, 3}, ImmRm{}, j{0x18}, j{0x1A}, 8}

	InstSub  = &Instruction{"sub", nil, ImmRm{j{0x81}, 5}, ImmRm{j{0x83}, 5}, j{0x29}, j{0x2B}, 64}
	InstSubb = &Instruction{"subb", nil, ImmRm{j{0x80}, 5}, ImmRm{}, j{0x28}, j{0x2A}, 8}

	InstTest  = &Instruction{"test", nil, ImmRm{j{0xF7}, 0}, ImmRm{}, j{0x85}, nil, 64}
	InstTestb = &Instruction{"testb", nil, ImmRm{j{0xF6}, 0}, ImmRm{}, j{0x84}, nil, 8}

	InstXor  = &Instruction{"xor", nil, ImmRm{j{0x81}, 6}, ImmRm{}, j{0x31}, j{0x33}, 64}
	InstXorb = &Instruction{"xorb", nil, ImmRm{j{0x80}, 6}, ImmRm{}, j{0x30}, j{0x32}, 8}

	InstRol  = &Instruction{"rol", nil, ImmRm{}, ImmRm{j{0xC1}, 0}, nil, nil, 64}
	InstRolb = &Instruction{"rolb", nil, ImmRm{}, ImmRm{j{0xC0}, 0}, nil, nil, 8}
	InstRor  = &Instruction{"rol", nil, ImmRm{}, ImmRm{j{0xC1}, 1}, nil, nil, 64}
	InstRorb = &Instruction{"rolb", nil, ImmRm{}, ImmRm{j{0xC0}, 1}, nil, nil, 8}
	InstRcl  = &Instruction{"rcl", nil, ImmRm{}, ImmRm{j{0xC1}, 2}, nil, nil, 64}
	InstRclb = &Instruction{"rclb", nil, ImmRm{}, ImmRm{j{0xC0}, 2}, nil, nil, 8}
	InstRcr  = &Instruction{"rcl", nil, ImmRm{}, ImmRm{j{0xC1}, 3}, nil, nil, 64}
	InstRcrb = &Instruction{"rclb", nil, ImmRm{}, ImmRm{j{0xC0}, 3}, nil, nil, 8}

	InstShl  = &Instruction{"shl", nil, ImmRm{}, ImmRm{j{0xC1}, 4}, nil, nil, 64}
	InstShlb = &Instruction{"shlb", nil, ImmRm{}, ImmRm{j{0xC0}, 4}, nil, nil, 8}
	InstShr  = &Instruction{"shr", nil, ImmRm{}, ImmRm{j{0xC1}, 5}, nil, nil, 64}
	InstShrb = &Instruction{"shrb", nil, ImmRm{}, ImmRm{j{0xC0}, 5}, nil, nil, 8}
	InstSar  = &Instruction{"sar", nil, ImmRm{}, ImmRm{j{0xC1}, 7}, nil, nil, 64}
	InstSarb = &Instruction{"sarb", nil, ImmRm{}, ImmRm{j{0xC0}, 7}, nil, nil, 8}

	InstBt  = &Instruction{"bt", nil, ImmRm{j{0x0F, 0xBA}, 4}, ImmRm{}, j{0x0F, 0xA3}, nil, 8}
	InstBtc = &Instruction{"btc", nil, ImmRm{j{0x0F, 0xBA}, 7}, ImmRm{}, j{0x0F, 0xBB}, nil, 8}
	InstBtr = &Instruction{"btr", nil, ImmRm{j{0x0F, 0xBA}, 6}, ImmRm{}, j{0x0F, 0xB3}, nil, 8}
	InstBts = &Instruction{"bts", nil, ImmRm{j{0x0F, 0xBA}, 5}, ImmRm{}, j{0x0F, 0xAB}, nil, 8}

	InstLea = &Instruction{"lea", nil, ImmRm{nil, 0}, ImmRm{}, nil, j{0x8D}, 64}

	InstMov  = &Instruction{"mov", j{0xB8}, ImmRm{j{0xc7}, 0}, ImmRm{}, j{0x89}, j{0x8b}, 64}
	InstMovl = as32Bits(InstMov)
	InstMovb = &Instruction{"movb", j{0xB0}, ImmRm{j{0xc6}, 0}, ImmRm{}, j{0x88}, j{0x8a}, 8}

	InstBsr = &Instruction{"bsr", nil, ImmRm{}, ImmRm{}, nil, j{0x0F, 0xBD}, 64}
	InstBsf = &Instruction{"bsf", nil, ImmRm{}, ImmRm{}, nil, j{0x0F, 0xBC}, 64}

	InstLzcnt = &Instruction{"lzcnt", nil, ImmRm{}, ImmRm{}, nil, j{0xF3, 0x0F, 0xBD}, 64}
)
View Source
var ErrBufferTooSmall = errors.New("buffer is too small")

Functions

func Addr

func Addr(b []byte) uintptr

Addr returns the address in memory of a byte slice, as a uintptr

func Alloc

func Alloc(len int) ([]byte, error)

Alloc returns a byte slice of the specified length that is marked RWX -- i.e. the memory in it can be both written and executed. This is just a simple wrapper around syscall.Mmap.

len most likely needs to be a multiple of PageSize.

func CallJit

func CallJit(b uintptr)

func Release

func Release(b []byte) error

Release frees a buffer allocated by Alloc

func U32

func U32(u uint32) int32

Types

type Assembler

type Assembler struct {
	Buf []byte
	Off int
	// contains filtered or unexported fields
}

Assembler implements a simple amd64 assembler. All methods on Assembler will emit code to Buf[Off:] and advances Off. Buf will never be reallocated, and attempts to assemble off the end of Buf will panic.

func New

func New(size int) (*Assembler, error)

func (*Assembler) Adc

func (a *Assembler) Adc(src, dst Operand)

func (*Assembler) Adcb

func (a *Assembler) Adcb(src, dst Operand)

func (*Assembler) Add

func (a *Assembler) Add(src, dst Operand)

func (*Assembler) Addb

func (a *Assembler) Addb(src, dst Operand)

func (*Assembler) And

func (a *Assembler) And(src, dst Operand)

func (*Assembler) Andb

func (a *Assembler) Andb(src, dst Operand)

func (*Assembler) Arithmetic

func (asm *Assembler) Arithmetic(insn *Instruction, src, dst Operand)

func (*Assembler) Bsf

func (a *Assembler) Bsf(src, dst Operand)

func (*Assembler) Bsr

func (a *Assembler) Bsr(src, dst Operand)

func (*Assembler) Bt

func (a *Assembler) Bt(src, dst Operand)

func (*Assembler) Btc

func (a *Assembler) Btc(src, dst Operand)

func (*Assembler) Btr

func (a *Assembler) Btr(src, dst Operand)

func (*Assembler) Bts

func (a *Assembler) Bts(src, dst Operand)

func (*Assembler) Call

func (a *Assembler) Call(dst Operand)

func (*Assembler) CallRel

func (a *Assembler) CallRel(dst uintptr)

func (*Assembler) Clc

func (a *Assembler) Clc()

func (*Assembler) Cld

func (a *Assembler) Cld()

func (*Assembler) Cli

func (a *Assembler) Cli()

func (*Assembler) Cmc

func (a *Assembler) Cmc()

func (*Assembler) Cmovcc

func (a *Assembler) Cmovcc(cc byte, src Operand, dst Register)

func (*Assembler) Cmp

func (a *Assembler) Cmp(src, dst Operand)

func (*Assembler) Cmpb

func (a *Assembler) Cmpb(src, dst Operand)

func (*Assembler) Dec

func (a *Assembler) Dec(o Operand)

func (*Assembler) Decb

func (a *Assembler) Decb(o Operand)

func (*Assembler) Error

func (a *Assembler) Error() error

func (*Assembler) Exit

func (asm *Assembler) Exit()

func (*Assembler) Imul

func (a *Assembler) Imul(o Operand)

func (*Assembler) Inc

func (a *Assembler) Inc(o Operand)

func (*Assembler) Incb

func (a *Assembler) Incb(o Operand)

func (*Assembler) Int3

func (a *Assembler) Int3()

func (*Assembler) InternalCallFunc

func (a *Assembler) InternalCallFunc(f any)

func (*Assembler) JccForward

func (a *Assembler) JccForward(cc byte) func()

func (*Assembler) JccRel

func (a *Assembler) JccRel(cc byte, dst uintptr)

func (*Assembler) JccShort

func (a *Assembler) JccShort(cc byte, off int8)

func (*Assembler) JccShortForward

func (a *Assembler) JccShortForward(cc byte) func()

Like JccShort, but the offset is calculated with a closure function Use like this:

closejcc := a.JccShortDelayed(CC_EQ)
// [emit code]
closejcc()  // jump here

func (*Assembler) Jmp

func (a *Assembler) Jmp(src Operand)

func (*Assembler) JmpForward

func (a *Assembler) JmpForward() func()

func (*Assembler) JmpRel

func (a *Assembler) JmpRel(dst uintptr)

func (*Assembler) Lea

func (a *Assembler) Lea(src, dst Operand)

func (*Assembler) Lzcnt

func (a *Assembler) Lzcnt(src, dst Operand)

func (*Assembler) Mov

func (a *Assembler) Mov(src, dst Operand)

func (*Assembler) MovAbs

func (a *Assembler) MovAbs(src uint64, dst Register)

func (*Assembler) Movb

func (a *Assembler) Movb(src, dst Operand)

func (*Assembler) Movl

func (a *Assembler) Movl(src, dst Operand)

func (*Assembler) Movsx

func (a *Assembler) Movsx(src, dst Operand)

func (*Assembler) Movsxd

func (a *Assembler) Movsxd(src, dst Operand)

func (*Assembler) Mul

func (a *Assembler) Mul(o Operand)

func (*Assembler) Neg

func (a *Assembler) Neg(o Operand)

func (*Assembler) Negb

func (a *Assembler) Negb(o Operand)

func (*Assembler) Not

func (a *Assembler) Not(o Operand)

func (*Assembler) Notb

func (a *Assembler) Notb(o Operand)

func (*Assembler) Or

func (a *Assembler) Or(src, dst Operand)

func (*Assembler) Orb

func (a *Assembler) Orb(src, dst Operand)

func (*Assembler) Pop

func (a *Assembler) Pop(dst Operand)

func (*Assembler) Popf

func (a *Assembler) Popf()

func (*Assembler) Push

func (a *Assembler) Push(src Operand)

func (*Assembler) Pushf

func (a *Assembler) Pushf()

func (*Assembler) Rcl

func (a *Assembler) Rcl(src, dst Operand)

func (*Assembler) RclCl

func (a *Assembler) RclCl(o Operand)

func (*Assembler) Rclb

func (a *Assembler) Rclb(src, dst Operand)

func (*Assembler) Rcr

func (a *Assembler) Rcr(src, dst Operand)

func (*Assembler) RcrCl

func (a *Assembler) RcrCl(o Operand)

func (*Assembler) Rcrb

func (a *Assembler) Rcrb(src, dst Operand)

func (*Assembler) Release

func (a *Assembler) Release()

func (*Assembler) Ret

func (a *Assembler) Ret()

func (*Assembler) Rol

func (a *Assembler) Rol(src, dst Operand)

func (*Assembler) RolCl

func (a *Assembler) RolCl(o Operand)

func (*Assembler) Rolb

func (a *Assembler) Rolb(src, dst Operand)

func (*Assembler) Ror

func (a *Assembler) Ror(src, dst Operand)

func (*Assembler) RorCl

func (a *Assembler) RorCl(o Operand)

func (*Assembler) Rorb

func (a *Assembler) Rorb(src, dst Operand)

func (*Assembler) SETcc

func (a *Assembler) SETcc(cc byte, dst Operand)

func (*Assembler) Sar

func (a *Assembler) Sar(src, dst Operand)

func (*Assembler) SarCl

func (a *Assembler) SarCl(o Operand)

func (*Assembler) Sarb

func (a *Assembler) Sarb(src, dst Operand)

func (*Assembler) Sbb

func (a *Assembler) Sbb(src, dst Operand)

func (*Assembler) Sbbb

func (a *Assembler) Sbbb(src, dst Operand)

func (*Assembler) Shl

func (a *Assembler) Shl(src, dst Operand)

func (*Assembler) ShlCl

func (a *Assembler) ShlCl(o Operand)

func (*Assembler) Shlb

func (a *Assembler) Shlb(src, dst Operand)

func (*Assembler) Shr

func (a *Assembler) Shr(src, dst Operand)

func (*Assembler) ShrCl

func (a *Assembler) ShrCl(o Operand)

func (*Assembler) Shrb

func (a *Assembler) Shrb(src, dst Operand)

func (*Assembler) Sub

func (a *Assembler) Sub(src, dst Operand)

func (*Assembler) Subb

func (a *Assembler) Subb(src, dst Operand)

func (*Assembler) Test

func (a *Assembler) Test(src, dst Operand)

func (*Assembler) Testb

func (a *Assembler) Testb(src, dst Operand)

func (*Assembler) Xor

func (a *Assembler) Xor(src, dst Operand)

func (*Assembler) Xorb

func (a *Assembler) Xorb(src, dst Operand)

type Imm

type Imm int32

func (Imm) ModRM

func (i Imm) ModRM(asm *Assembler, reg Register)

func (Imm) Rex

func (i Imm) Rex(asm *Assembler, reg Register)

type ImmRm

type ImmRm struct {
	// contains filtered or unexported fields
}

type Indirect

type Indirect struct {
	Base   Register
	Offset int32
	Bits   byte
}

func (Indirect) ModRM

func (i Indirect) ModRM(asm *Assembler, reg Register)

func (Indirect) Rex

func (i Indirect) Rex(asm *Assembler, reg Register)

type Instruction

type Instruction struct {
	Mnemonic string
	// contains filtered or unexported fields
}

type Operand

type Operand interface {
	Rex(asm *Assembler, reg Register)
	ModRM(asm *Assembler, reg Register)
	// contains filtered or unexported methods
}

type PCRel

type PCRel struct {
	Addr uintptr
}

func (PCRel) ModRM

func (i PCRel) ModRM(asm *Assembler, reg Register)

func (PCRel) Rex

func (i PCRel) Rex(asm *Assembler, reg Register)

type Register

type Register struct {
	Val  byte
	Bits byte
}

func (Register) ModRM

func (r Register) ModRM(asm *Assembler, reg Register)

func (Register) Rex

func (i Register) Rex(asm *Assembler, reg Register)

type SIB

type SIB struct {
	Offset      int32
	Base, Index Register
	Scale       Scale
}

func (SIB) ModRM

func (s SIB) ModRM(asm *Assembler, reg Register)

func (SIB) Rex

func (s SIB) Rex(asm *Assembler, reg Register)

type Scale

type Scale struct {
	// contains filtered or unexported fields
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL