You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-library/vendor/github.com/bytedance/sonic/internal/decoder/assembler_amd64_go116.go

2013 lines
91 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// +build go1.15,!go1.17
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package decoder
import (
`encoding/json`
`fmt`
`math`
`reflect`
`strconv`
`unsafe`
`github.com/bytedance/sonic/internal/caching`
`github.com/bytedance/sonic/internal/jit`
`github.com/bytedance/sonic/internal/native`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
`github.com/twitchyliquid64/golang-asm/obj`
`github.com/twitchyliquid64/golang-asm/obj/x86`
)
/** Register Allocations
*
* State Registers:
*
* %rbx : stack base
* %r12 : input pointer
* %r13 : input length
* %r14 : input cursor
* %r15 : value pointer
*
* Error Registers:
*
* %r10 : error type register
* %r11 : error pointer register
*/
/** Function Prototype & Stack Map
*
* func (s string, ic int, vp unsafe.Pointer, sb *_Stack, fv uint64, sv string) (rc int, err error)
*
* s.buf : (FP)
* s.len : 8(FP)
* ic : 16(FP)
* vp : 24(FP)
* sb : 32(FP)
* fv : 40(FP)
* sv : 56(FP)
* err.vt : 72(FP)
* err.vp : 80(FP)
*/
const (
_FP_args = 96 // 96 bytes to pass arguments and return values for this function
_FP_fargs = 80 // 80 bytes for passing arguments to other Go functions
_FP_saves = 40 // 40 bytes for saving the registers before CALL instructions
_FP_locals = 144 // 144 bytes for local variables
)
const (
_FP_offs = _FP_fargs + _FP_saves + _FP_locals
_FP_size = _FP_offs + 8 // 8 bytes for the parent frame pointer
_FP_base = _FP_size + 8 // 8 bytes for the return address
)
const (
_IM_null = 0x6c6c756e // 'null'
_IM_true = 0x65757274 // 'true'
_IM_alse = 0x65736c61 // 'alse' ('false' without the 'f')
)
const (
_BM_space = (1 << ' ') | (1 << '\t') | (1 << '\r') | (1 << '\n')
)
const (
_MODE_JSON = 1 << 3 // base64 mode
)
const (
_LB_error = "_error"
_LB_im_error = "_im_error"
_LB_eof_error = "_eof_error"
_LB_type_error = "_type_error"
_LB_field_error = "_field_error"
_LB_range_error = "_range_error"
_LB_stack_error = "_stack_error"
_LB_base64_error = "_base64_error"
_LB_unquote_error = "_unquote_error"
_LB_parsing_error = "_parsing_error"
_LB_parsing_error_v = "_parsing_error_v"
_LB_mismatch_error = "_mismatch_error"
)
const (
_LB_char_0_error = "_char_0_error"
_LB_char_1_error = "_char_1_error"
_LB_char_2_error = "_char_2_error"
_LB_char_3_error = "_char_3_error"
_LB_char_4_error = "_char_4_error"
_LB_char_m2_error = "_char_m2_error"
_LB_char_m3_error = "_char_m3_error"
)
const (
_LB_skip_one = "_skip_one"
_LB_skip_key_value = "_skip_key_value"
)
var (
_AX = jit.Reg("AX")
_CX = jit.Reg("CX")
_DX = jit.Reg("DX")
_DI = jit.Reg("DI")
_SI = jit.Reg("SI")
_BP = jit.Reg("BP")
_SP = jit.Reg("SP")
_R8 = jit.Reg("R8")
_R9 = jit.Reg("R9")
_X0 = jit.Reg("X0")
_X1 = jit.Reg("X1")
)
var (
_ST = jit.Reg("BX")
_IP = jit.Reg("R12")
_IL = jit.Reg("R13")
_IC = jit.Reg("R14")
_VP = jit.Reg("R15")
)
var (
_R10 = jit.Reg("R10") // used for gcWriteBarrier
_DF = jit.Reg("R10") // reuse R10 in generic decoder for flags
_ET = jit.Reg("R10")
_EP = jit.Reg("R11")
)
var (
_ARG_s = _ARG_sp
_ARG_sp = jit.Ptr(_SP, _FP_base)
_ARG_sl = jit.Ptr(_SP, _FP_base + 8)
_ARG_ic = jit.Ptr(_SP, _FP_base + 16)
_ARG_vp = jit.Ptr(_SP, _FP_base + 24)
_ARG_sb = jit.Ptr(_SP, _FP_base + 32)
_ARG_fv = jit.Ptr(_SP, _FP_base + 40)
)
var (
_VAR_sv = _VAR_sv_p
_VAR_sv_p = jit.Ptr(_SP, _FP_base + 48)
_VAR_sv_n = jit.Ptr(_SP, _FP_base + 56)
_VAR_vk = jit.Ptr(_SP, _FP_base + 64)
)
var (
_RET_rc = jit.Ptr(_SP, _FP_base + 72)
_RET_et = jit.Ptr(_SP, _FP_base + 80)
_RET_ep = jit.Ptr(_SP, _FP_base + 88)
)
var (
_VAR_st = _VAR_st_Vt
_VAR_sr = jit.Ptr(_SP, _FP_fargs + _FP_saves)
)
var (
_VAR_st_Vt = jit.Ptr(_SP, _FP_fargs + _FP_saves + 0)
_VAR_st_Dv = jit.Ptr(_SP, _FP_fargs + _FP_saves + 8)
_VAR_st_Iv = jit.Ptr(_SP, _FP_fargs + _FP_saves + 16)
_VAR_st_Ep = jit.Ptr(_SP, _FP_fargs + _FP_saves + 24)
_VAR_st_Db = jit.Ptr(_SP, _FP_fargs + _FP_saves + 32)
_VAR_st_Dc = jit.Ptr(_SP, _FP_fargs + _FP_saves + 40)
)
var (
_VAR_ss_AX = jit.Ptr(_SP, _FP_fargs + _FP_saves + 48)
_VAR_ss_CX = jit.Ptr(_SP, _FP_fargs + _FP_saves + 56)
_VAR_ss_SI = jit.Ptr(_SP, _FP_fargs + _FP_saves + 64)
_VAR_ss_R8 = jit.Ptr(_SP, _FP_fargs + _FP_saves + 72)
_VAR_ss_R9 = jit.Ptr(_SP, _FP_fargs + _FP_saves + 80)
)
var (
_VAR_bs_p = jit.Ptr(_SP, _FP_fargs + _FP_saves + 88)
_VAR_bs_n = jit.Ptr(_SP, _FP_fargs + _FP_saves + 96)
_VAR_bs_LR = jit.Ptr(_SP, _FP_fargs + _FP_saves + 104)
)
var _VAR_fl = jit.Ptr(_SP, _FP_fargs + _FP_saves + 112)
var (
_VAR_et = jit.Ptr(_SP, _FP_fargs + _FP_saves + 120) // save dismatched type
_VAR_ic = jit.Ptr(_SP, _FP_fargs + _FP_saves + 128) // save dismatched position
_VAR_pc = jit.Ptr(_SP, _FP_fargs + _FP_saves + 136) // save skip return pc
)
type _Assembler struct {
jit.BaseAssembler
p _Program
name string
}
func newAssembler(p _Program) *_Assembler {
return new(_Assembler).Init(p)
}
/** Assembler Interface **/
func (self *_Assembler) Load() _Decoder {
return ptodec(self.BaseAssembler.Load("decode_"+self.name, _FP_size, _FP_args, argPtrs, localPtrs))
}
func (self *_Assembler) Init(p _Program) *_Assembler {
self.p = p
self.BaseAssembler.Init(self.compile)
return self
}
func (self *_Assembler) compile() {
self.prologue()
self.instrs()
self.epilogue()
self.copy_string()
self.escape_string()
self.escape_string_twice()
self.skip_one()
self.skip_key_value()
self.mismatch_error()
self.type_error()
self.field_error()
self.range_error()
self.stack_error()
self.base64_error()
self.parsing_error()
}
/** Assembler Stages **/
var _OpFuncTab = [256]func(*_Assembler, *_Instr) {
_OP_any : (*_Assembler)._asm_OP_any,
_OP_dyn : (*_Assembler)._asm_OP_dyn,
_OP_str : (*_Assembler)._asm_OP_str,
_OP_bin : (*_Assembler)._asm_OP_bin,
_OP_bool : (*_Assembler)._asm_OP_bool,
_OP_num : (*_Assembler)._asm_OP_num,
_OP_i8 : (*_Assembler)._asm_OP_i8,
_OP_i16 : (*_Assembler)._asm_OP_i16,
_OP_i32 : (*_Assembler)._asm_OP_i32,
_OP_i64 : (*_Assembler)._asm_OP_i64,
_OP_u8 : (*_Assembler)._asm_OP_u8,
_OP_u16 : (*_Assembler)._asm_OP_u16,
_OP_u32 : (*_Assembler)._asm_OP_u32,
_OP_u64 : (*_Assembler)._asm_OP_u64,
_OP_f32 : (*_Assembler)._asm_OP_f32,
_OP_f64 : (*_Assembler)._asm_OP_f64,
_OP_unquote : (*_Assembler)._asm_OP_unquote,
_OP_nil_1 : (*_Assembler)._asm_OP_nil_1,
_OP_nil_2 : (*_Assembler)._asm_OP_nil_2,
_OP_nil_3 : (*_Assembler)._asm_OP_nil_3,
_OP_deref : (*_Assembler)._asm_OP_deref,
_OP_index : (*_Assembler)._asm_OP_index,
_OP_is_null : (*_Assembler)._asm_OP_is_null,
_OP_is_null_quote : (*_Assembler)._asm_OP_is_null_quote,
_OP_map_init : (*_Assembler)._asm_OP_map_init,
_OP_map_key_i8 : (*_Assembler)._asm_OP_map_key_i8,
_OP_map_key_i16 : (*_Assembler)._asm_OP_map_key_i16,
_OP_map_key_i32 : (*_Assembler)._asm_OP_map_key_i32,
_OP_map_key_i64 : (*_Assembler)._asm_OP_map_key_i64,
_OP_map_key_u8 : (*_Assembler)._asm_OP_map_key_u8,
_OP_map_key_u16 : (*_Assembler)._asm_OP_map_key_u16,
_OP_map_key_u32 : (*_Assembler)._asm_OP_map_key_u32,
_OP_map_key_u64 : (*_Assembler)._asm_OP_map_key_u64,
_OP_map_key_f32 : (*_Assembler)._asm_OP_map_key_f32,
_OP_map_key_f64 : (*_Assembler)._asm_OP_map_key_f64,
_OP_map_key_str : (*_Assembler)._asm_OP_map_key_str,
_OP_map_key_utext : (*_Assembler)._asm_OP_map_key_utext,
_OP_map_key_utext_p : (*_Assembler)._asm_OP_map_key_utext_p,
_OP_array_skip : (*_Assembler)._asm_OP_array_skip,
_OP_array_clear : (*_Assembler)._asm_OP_array_clear,
_OP_array_clear_p : (*_Assembler)._asm_OP_array_clear_p,
_OP_slice_init : (*_Assembler)._asm_OP_slice_init,
_OP_slice_append : (*_Assembler)._asm_OP_slice_append,
_OP_object_skip : (*_Assembler)._asm_OP_object_skip,
_OP_object_next : (*_Assembler)._asm_OP_object_next,
_OP_struct_field : (*_Assembler)._asm_OP_struct_field,
_OP_unmarshal : (*_Assembler)._asm_OP_unmarshal,
_OP_unmarshal_p : (*_Assembler)._asm_OP_unmarshal_p,
_OP_unmarshal_text : (*_Assembler)._asm_OP_unmarshal_text,
_OP_unmarshal_text_p : (*_Assembler)._asm_OP_unmarshal_text_p,
_OP_lspace : (*_Assembler)._asm_OP_lspace,
_OP_match_char : (*_Assembler)._asm_OP_match_char,
_OP_check_char : (*_Assembler)._asm_OP_check_char,
_OP_load : (*_Assembler)._asm_OP_load,
_OP_save : (*_Assembler)._asm_OP_save,
_OP_drop : (*_Assembler)._asm_OP_drop,
_OP_drop_2 : (*_Assembler)._asm_OP_drop_2,
_OP_recurse : (*_Assembler)._asm_OP_recurse,
_OP_goto : (*_Assembler)._asm_OP_goto,
_OP_switch : (*_Assembler)._asm_OP_switch,
_OP_check_char_0 : (*_Assembler)._asm_OP_check_char_0,
_OP_dismatch_err : (*_Assembler)._asm_OP_dismatch_err,
_OP_go_skip : (*_Assembler)._asm_OP_go_skip,
_OP_add : (*_Assembler)._asm_OP_add,
_OP_check_empty : (*_Assembler)._asm_OP_check_empty,
}
func (self *_Assembler) instr(v *_Instr) {
if fn := _OpFuncTab[v.op()]; fn != nil {
fn(self, v)
} else {
panic(fmt.Sprintf("invalid opcode: %d", v.op()))
}
}
func (self *_Assembler) instrs() {
for i, v := range self.p {
self.Mark(i)
self.instr(&v)
self.debug_instr(i, &v)
}
}
func (self *_Assembler) epilogue() {
self.Mark(len(self.p))
self.Emit("XORL", _EP, _EP) // XORL EP, EP
self.Emit("MOVQ", _VAR_et, _ET) // MOVQ VAR_et, ET
self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET
self.Sjmp("JNZ", _LB_mismatch_error) // JNZ _LB_mismatch_error
self.Link(_LB_error) // _error:
self.Emit("MOVQ", _IC, _RET_rc) // MOVQ IC, rc<>+40(FP)
self.Emit("MOVQ", _ET, _RET_et) // MOVQ ET, et<>+48(FP)
self.Emit("MOVQ", _EP, _RET_ep) // MOVQ EP, ep<>+56(FP)
self.Emit("MOVQ", jit.Ptr(_SP, _FP_offs), _BP) // MOVQ _FP_offs(SP), BP
self.Emit("ADDQ", jit.Imm(_FP_size), _SP) // ADDQ $_FP_size, SP
self.Emit("RET") // RET
}
func (self *_Assembler) prologue() {
self.Emit("SUBQ", jit.Imm(_FP_size), _SP) // SUBQ $_FP_size, SP
self.Emit("MOVQ", _BP, jit.Ptr(_SP, _FP_offs)) // MOVQ BP, _FP_offs(SP)
self.Emit("LEAQ", jit.Ptr(_SP, _FP_offs), _BP) // LEAQ _FP_offs(SP), BP
self.Emit("MOVQ", _ARG_sp, _IP) // MOVQ s.p<>+0(FP), IP
self.Emit("MOVQ", _ARG_sl, _IL) // MOVQ s.l<>+8(FP), IL
self.Emit("MOVQ", _ARG_ic, _IC) // MOVQ ic<>+16(FP), IC
self.Emit("MOVQ", _ARG_vp, _VP) // MOVQ vp<>+24(FP), VP
self.Emit("MOVQ", _ARG_sb, _ST) // MOVQ vp<>+32(FP), ST
// initialize digital buffer first
self.Emit("MOVQ", jit.Imm(_MaxDigitNums), _VAR_st_Dc) // MOVQ $_MaxDigitNums, ss.Dcap
self.Emit("LEAQ", jit.Ptr(_ST, _DbufOffset), _AX) // LEAQ _DbufOffset(ST), AX
self.Emit("MOVQ", _AX, _VAR_st_Db) // MOVQ AX, ss.Dbuf
self.Emit("XORL", _AX, _AX) // XORL AX, AX
self.Emit("MOVQ", _AX, _VAR_et) // MOVQ AX, ss.Dp
}
/** Function Calling Helpers **/
var _REG_go = []obj.Addr {
_ST,
_VP,
_IP,
_IL,
_IC,
}
func (self *_Assembler) save(r ...obj.Addr) {
for i, v := range r {
if i > _FP_saves / 8 - 1 {
panic("too many registers to save")
} else {
self.Emit("MOVQ", v, jit.Ptr(_SP, _FP_fargs + int64(i) * 8))
}
}
}
func (self *_Assembler) load(r ...obj.Addr) {
for i, v := range r {
if i > _FP_saves / 8 - 1 {
panic("too many registers to load")
} else {
self.Emit("MOVQ", jit.Ptr(_SP, _FP_fargs + int64(i) * 8), v)
}
}
}
func (self *_Assembler) call(fn obj.Addr) {
self.Emit("MOVQ", fn, _AX) // MOVQ ${fn}, AX
self.Rjmp("CALL", _AX) // CALL AX
}
func (self *_Assembler) call_go(fn obj.Addr) {
self.save(_REG_go...) // SAVE $REG_go
self.call(fn) // CALL ${fn}
self.load(_REG_go...) // LOAD $REG_go
}
func (self *_Assembler) call_sf(fn obj.Addr) {
self.Emit("LEAQ", _ARG_s, _DI) // LEAQ s<>+0(FP), DI
self.Emit("MOVQ", _IC, _ARG_ic) // MOVQ IC, ic<>+16(FP)
self.Emit("LEAQ", _ARG_ic, _SI) // LEAQ ic<>+16(FP), SI
self.Emit("LEAQ", jit.Ptr(_ST, _FsmOffset), _DX) // LEAQ _FsmOffset(ST), DX
self.Emit("MOVQ", _ARG_fv, _CX)
self.call(fn) // CALL ${fn}
self.Emit("MOVQ", _ARG_ic, _IC) // MOVQ ic<>+16(FP), IC
}
func (self *_Assembler) call_vf(fn obj.Addr) {
self.Emit("LEAQ", _ARG_s, _DI) // LEAQ s<>+0(FP), DI
self.Emit("MOVQ", _IC, _ARG_ic) // MOVQ IC, ic<>+16(FP)
self.Emit("LEAQ", _ARG_ic, _SI) // LEAQ ic<>+16(FP), SI
self.Emit("LEAQ", _VAR_st, _DX) // LEAQ st, DX
self.call(fn) // CALL ${fn}
self.Emit("MOVQ", _ARG_ic, _IC) // MOVQ ic<>+16(FP), IC
}
/** Assembler Error Handlers **/
var (
_F_convT64 = jit.Func(convT64)
_F_error_wrap = jit.Func(error_wrap)
_F_error_type = jit.Func(error_type)
_F_error_field = jit.Func(error_field)
_F_error_value = jit.Func(error_value)
_F_error_mismatch = jit.Func(error_mismatch)
)
var (
_I_int8 , _T_int8 = rtype(reflect.TypeOf(int8(0)))
_I_int16 , _T_int16 = rtype(reflect.TypeOf(int16(0)))
_I_int32 , _T_int32 = rtype(reflect.TypeOf(int32(0)))
_I_uint8 , _T_uint8 = rtype(reflect.TypeOf(uint8(0)))
_I_uint16 , _T_uint16 = rtype(reflect.TypeOf(uint16(0)))
_I_uint32 , _T_uint32 = rtype(reflect.TypeOf(uint32(0)))
_I_float32 , _T_float32 = rtype(reflect.TypeOf(float32(0)))
)
var (
_T_error = rt.UnpackType(errorType)
_I_base64_CorruptInputError = jit.Itab(_T_error, base64CorruptInputError)
)
var (
_V_stackOverflow = jit.Imm(int64(uintptr(unsafe.Pointer(&stackOverflow))))
_I_json_UnsupportedValueError = jit.Itab(_T_error, reflect.TypeOf(new(json.UnsupportedValueError)))
_I_json_MismatchTypeError = jit.Itab(_T_error, reflect.TypeOf(new(MismatchTypeError)))
)
func (self *_Assembler) type_error() {
self.Link(_LB_type_error) // _type_error:
self.Emit("MOVQ", _ET, jit.Ptr(_SP, 0)) // MOVQ ET, (SP)
self.call_go(_F_error_type) // CALL_GO error_type
self.Emit("MOVQ", jit.Ptr(_SP, 8), _ET) // MOVQ 8(SP), ET
self.Emit("MOVQ", jit.Ptr(_SP, 16), _EP) // MOVQ 16(SP), EP
self.Sjmp("JMP" , _LB_error) // JMP _error
}
func (self *_Assembler) mismatch_error() {
self.Link(_LB_mismatch_error) // _type_error:
self.Emit("MOVQ", _VAR_et, _ET) // MOVQ _VAR_et, ET
self.Emit("MOVQ", _VAR_ic, _EP) // MOVQ _VAR_ic, EP
self.Emit("MOVQ", _I_json_MismatchTypeError, _AX) // MOVQ _I_json_MismatchTypeError, AX
self.Emit("CMPQ", _ET, _AX) // CMPQ ET, AX
self.Sjmp("JE" , _LB_error) // JE _LB_error
self.Emit("MOVQ", _ARG_sp, _AX)
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
self.Emit("MOVQ", _ARG_sl, _CX)
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
self.Emit("MOVQ", _VAR_ic, _AX)
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 16)) // MOVQ AX, 16(SP)
self.Emit("MOVQ", _VAR_et, _CX)
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 24)) // MOVQ CX, 24(SP)
self.call_go(_F_error_mismatch) // CALL_GO error_type
self.Emit("MOVQ", jit.Ptr(_SP, 32), _ET) // MOVQ 32(SP), ET
self.Emit("MOVQ", jit.Ptr(_SP, 40), _EP) // MOVQ 40(SP), EP
self.Sjmp("JMP" , _LB_error) // JMP _error
}
func (self *_Assembler) _asm_OP_dismatch_err(p *_Instr) {
self.Emit("MOVQ", _IC, _VAR_ic)
self.Emit("MOVQ", jit.Type(p.vt()), _ET)
self.Emit("MOVQ", _ET, _VAR_et)
}
func (self *_Assembler) _asm_OP_go_skip(p *_Instr) {
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
self.Xref(p.vi(), 4)
self.Emit("MOVQ", _R9, _VAR_pc)
self.Sjmp("JMP" , _LB_skip_one) // JMP _skip_one
}
func (self *_Assembler) skip_one() {
self.Link(_LB_skip_one) // _skip:
self.Emit("MOVQ", _VAR_ic, _IC) // MOVQ _VAR_ic, IC
self.call_sf(_F_skip_one) // CALL_SF skip_one
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
self.Emit("MOVQ" , _VAR_pc, _R9) // MOVQ pc, R9
self.Rjmp("JMP" , _R9) // JMP (R9)
}
func (self *_Assembler) skip_key_value() {
self.Link(_LB_skip_key_value) // _skip:
// skip the key
self.Emit("MOVQ", _VAR_ic, _IC) // MOVQ _VAR_ic, IC
self.call_sf(_F_skip_one) // CALL_SF skip_one
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
// match char ':'
self.lspace("_global_1")
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(':'))
self.Sjmp("JNE" , _LB_parsing_error_v) // JNE _parse_error_v
self.Emit("ADDQ", jit.Imm(1), _IC) // ADDQ $1, IC
self.lspace("_global_2")
// skip the value
self.call_sf(_F_skip_one) // CALL_SF skip_one
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
// jump back to specified address
self.Emit("MOVQ" , _VAR_pc, _R9) // MOVQ pc, R9
self.Rjmp("JMP" , _R9) // JMP (R9)
}
func (self *_Assembler) field_error() {
self.Link(_LB_field_error) // _field_error:
self.Emit("MOVOU", _VAR_sv, _X0) // MOVOU sv, X0
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 0)) // MOVOU X0, (SP)
self.call_go(_F_error_field) // CALL_GO error_field
self.Emit("MOVQ" , jit.Ptr(_SP, 16), _ET) // MOVQ 16(SP), ET
self.Emit("MOVQ" , jit.Ptr(_SP, 24), _EP) // MOVQ 24(SP), EP
self.Sjmp("JMP" , _LB_error) // JMP _error
}
func (self *_Assembler) range_error() {
self.Link(_LB_range_error) // _range_error:
self.slice_from(_VAR_st_Ep, 0) // SLICE st.Ep, $0
self.Emit("MOVQ", _DI, jit.Ptr(_SP, 0)) // MOVQ DI, (SP)
self.Emit("MOVQ", _SI, jit.Ptr(_SP, 8)) // MOVQ SI, 8(SP)
self.Emit("MOVQ", _ET, jit.Ptr(_SP, 16)) // MOVQ ET, 16(SP)
self.Emit("MOVQ", _EP, jit.Ptr(_SP, 24)) // MOVQ EP, 24(SP)
self.call_go(_F_error_value) // CALL_GO error_value
self.Emit("MOVQ", jit.Ptr(_SP, 32), _ET) // MOVQ 32(SP), ET
self.Emit("MOVQ", jit.Ptr(_SP, 40), _EP) // MOVQ 40(SP), EP
self.Sjmp("JMP" , _LB_error) // JMP _error
}
func (self *_Assembler) stack_error() {
self.Link(_LB_stack_error) // _stack_error:
self.Emit("MOVQ", _V_stackOverflow, _EP) // MOVQ ${_V_stackOverflow}, EP
self.Emit("MOVQ", _I_json_UnsupportedValueError, _ET) // MOVQ ${_I_json_UnsupportedValueError}, ET
self.Sjmp("JMP" , _LB_error) // JMP _error
}
func (self *_Assembler) base64_error() {
self.Link(_LB_base64_error)
self.Emit("NEGQ", _AX) // NEGQ AX
self.Emit("SUBQ", jit.Imm(1), _AX) // SUBQ $1, AX
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
self.call_go(_F_convT64) // CALL_GO convT64
self.Emit("MOVQ", jit.Ptr(_SP, 8), _EP) // MOVQ 8(SP), EP
self.Emit("MOVQ", _I_base64_CorruptInputError, _ET) // MOVQ ${itab(base64.CorruptInputError)}, ET
self.Sjmp("JMP" , _LB_error) // JMP _error
}
func (self *_Assembler) parsing_error() {
self.Link(_LB_eof_error) // _eof_error:
self.Emit("MOVQ" , _IL, _IC) // MOVQ IL, IC
self.Emit("MOVL" , jit.Imm(int64(types.ERR_EOF)), _EP) // MOVL ${types.ERR_EOF}, EP
self.Sjmp("JMP" , _LB_parsing_error) // JMP _parsing_error
self.Link(_LB_unquote_error) // _unquote_error:
self.Emit("SUBQ" , _VAR_sr, _SI) // SUBQ sr, SI
self.Emit("SUBQ" , _SI, _IC) // SUBQ IL, IC
self.Link(_LB_parsing_error_v) // _parsing_error_v:
self.Emit("MOVQ" , _AX, _EP) // MOVQ AX, EP
self.Emit("NEGQ" , _EP) // NEGQ EP
self.Sjmp("JMP" , _LB_parsing_error) // JMP _parsing_error
self.Link(_LB_char_m3_error) // _char_m3_error:
self.Emit("SUBQ" , jit.Imm(1), _IC) // SUBQ $1, IC
self.Link(_LB_char_m2_error) // _char_m2_error:
self.Emit("SUBQ" , jit.Imm(2), _IC) // SUBQ $2, IC
self.Sjmp("JMP" , _LB_char_0_error) // JMP _char_0_error
self.Link(_LB_im_error) // _im_error:
self.Emit("CMPB" , _CX, jit.Sib(_IP, _IC, 1, 0)) // CMPB CX, (IP)(IC)
self.Sjmp("JNE" , _LB_char_0_error) // JNE _char_0_error
self.Emit("SHRL" , jit.Imm(8), _CX) // SHRL $8, CX
self.Emit("CMPB" , _CX, jit.Sib(_IP, _IC, 1, 1)) // CMPB CX, 1(IP)(IC)
self.Sjmp("JNE" , _LB_char_1_error) // JNE _char_1_error
self.Emit("SHRL" , jit.Imm(8), _CX) // SHRL $8, CX
self.Emit("CMPB" , _CX, jit.Sib(_IP, _IC, 1, 2)) // CMPB CX, 2(IP)(IC)
self.Sjmp("JNE" , _LB_char_2_error) // JNE _char_2_error
self.Sjmp("JMP" , _LB_char_3_error) // JNE _char_3_error
self.Link(_LB_char_4_error) // _char_4_error:
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
self.Link(_LB_char_3_error) // _char_3_error:
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
self.Link(_LB_char_2_error) // _char_2_error:
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
self.Link(_LB_char_1_error) // _char_1_error:
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
self.Link(_LB_char_0_error) // _char_0_error:
self.Emit("MOVL" , jit.Imm(int64(types.ERR_INVALID_CHAR)), _EP) // MOVL ${types.ERR_INVALID_CHAR}, EP
self.Link(_LB_parsing_error) // _parsing_error:
self.Emit("MOVOU", _ARG_s, _X0) // MOVOU s, X0
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 0)) // MOVOU X0, (SP)
self.Emit("MOVQ" , _IC, jit.Ptr(_SP, 16)) // MOVQ IC, 16(SP)
self.Emit("MOVQ" , _EP, jit.Ptr(_SP, 24)) // MOVQ EP, 24(SP)
self.call_go(_F_error_wrap) // CALL_GO error_wrap
self.Emit("MOVQ" , jit.Ptr(_SP, 32), _ET) // MOVQ 32(SP), ET
self.Emit("MOVQ" , jit.Ptr(_SP, 40), _EP) // MOVQ 40(SP), EP
self.Sjmp("JMP" , _LB_error) // JMP _error
}
/** Memory Management Routines **/
var (
_T_byte = jit.Type(byteType)
_F_mallocgc = jit.Func(mallocgc)
)
func (self *_Assembler) malloc(nb obj.Addr, ret obj.Addr) {
self.Emit("XORL", _AX, _AX) // XORL AX, AX
self.Emit("MOVQ", _T_byte, _CX) // MOVQ ${type(byte)}, CX
self.Emit("MOVQ", nb, jit.Ptr(_SP, 0)) // MOVQ ${nb}, (SP)
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 16)) // MOVQ AX, 16(SP)
self.call_go(_F_mallocgc) // CALL_GO mallocgc
self.Emit("MOVQ", jit.Ptr(_SP, 24), ret) // MOVQ 24(SP), ${ret}
}
func (self *_Assembler) valloc(vt reflect.Type, ret obj.Addr) {
self.Emit("MOVQ", jit.Imm(int64(vt.Size())), _AX) // MOVQ ${vt.Size()}, AX
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
self.Emit("MOVQ", jit.Type(vt), _AX) // MOVQ ${vt}, AX
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 8)) // MOVQ AX, 8(SP)
self.Emit("MOVB", jit.Imm(1), jit.Ptr(_SP, 16)) // MOVB $1, 16(SP)
self.call_go(_F_mallocgc) // CALL_GO mallocgc
self.Emit("MOVQ", jit.Ptr(_SP, 24), ret) // MOVQ 24(SP), ${ret}
}
func (self *_Assembler) vfollow(vt reflect.Type) {
self.Emit("MOVQ" , jit.Ptr(_VP, 0), _AX) // MOVQ (VP), AX
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JNZ" , "_end_{n}") // JNZ _end_{n}
self.valloc(vt, _AX) // VALLOC ${vt}, AX
self.WritePtrAX(1, jit.Ptr(_VP, 0), false) // MOVQ AX, (VP)
self.Link("_end_{n}") // _end_{n}:
self.Emit("MOVQ" , _AX, _VP) // MOVQ AX, VP
}
/** Value Parsing Routines **/
var (
_F_vstring = jit.Imm(int64(native.S_vstring))
_F_vnumber = jit.Imm(int64(native.S_vnumber))
_F_vsigned = jit.Imm(int64(native.S_vsigned))
_F_vunsigned = jit.Imm(int64(native.S_vunsigned))
)
func (self *_Assembler) check_err(vt reflect.Type, pin string, pin2 int) {
self.Emit("MOVQ" , _VAR_st_Vt, _AX) // MOVQ st.Vt, AX
self.Emit("TESTQ", _AX, _AX) // CMPQ AX, ${native.V_STRING}
// try to skip the value
if vt != nil {
self.Sjmp("JNS" , "_check_err_{n}") // JNE _parsing_error_v
self.Emit("MOVQ", jit.Type(vt), _ET)
self.Emit("MOVQ", _ET, _VAR_et)
if pin2 != -1 {
self.Emit("SUBQ", jit.Imm(1), _BP)
self.Emit("MOVQ", _BP, _VAR_ic)
self.Byte(0x4c , 0x8d, 0x0d) // LEAQ (PC), R9
self.Xref(pin2, 4)
self.Emit("MOVQ", _R9, _VAR_pc)
self.Sjmp("JMP" , _LB_skip_key_value)
} else {
self.Emit("MOVQ", _BP, _VAR_ic)
self.Byte(0x4c , 0x8d, 0x0d) // LEAQ (PC), R9
self.Sref(pin, 4)
self.Emit("MOVQ", _R9, _VAR_pc)
self.Sjmp("JMP" , _LB_skip_one)
}
self.Link("_check_err_{n}")
} else {
self.Sjmp("JS" , _LB_parsing_error_v) // JNE _parsing_error_v
}
}
func (self *_Assembler) check_eof(d int64) {
if d == 1 {
self.Emit("CMPQ", _IC, _IL) // CMPQ IC, IL
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
} else {
self.Emit("LEAQ", jit.Ptr(_IC, d), _AX) // LEAQ ${d}(IC), AX
self.Emit("CMPQ", _AX, _IL) // CMPQ AX, IL
self.Sjmp("JA" , _LB_eof_error) // JA _eof_error
}
}
func (self *_Assembler) parse_string() { // parse_string has a validate flag params in the last
self.Emit("MOVQ", _ARG_fv, _CX)
self.call_vf(_F_vstring)
self.check_err(nil, "", -1)
}
func (self *_Assembler) parse_number(vt reflect.Type, pin string, pin2 int) {
self.Emit("MOVQ", _IC, _BP)
self.call_vf(_F_vnumber) // call vnumber
self.check_err(vt, pin, pin2)
}
func (self *_Assembler) parse_signed(vt reflect.Type, pin string, pin2 int) {
self.Emit("MOVQ", _IC, _BP)
self.call_vf(_F_vsigned)
self.check_err(vt, pin, pin2)
}
func (self *_Assembler) parse_unsigned(vt reflect.Type, pin string, pin2 int) {
self.Emit("MOVQ", _IC, _BP)
self.call_vf(_F_vunsigned)
self.check_err(vt, pin, pin2)
}
// Pointer: DI, Size: SI, Return: R9
func (self *_Assembler) copy_string() {
self.Link("_copy_string")
self.Emit("MOVQ", _DI, _VAR_bs_p)
self.Emit("MOVQ", _SI, _VAR_bs_n)
self.Emit("MOVQ", _R9, _VAR_bs_LR)
self.malloc(_SI, _AX)
self.Emit("MOVQ", _AX, _VAR_sv_p)
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0))
self.Emit("MOVQ", _VAR_bs_p, _DI)
self.Emit("MOVQ", _DI, jit.Ptr(_SP, 8))
self.Emit("MOVQ", _VAR_bs_n, _SI)
self.Emit("MOVQ", _SI, jit.Ptr(_SP, 16))
self.call_go(_F_memmove)
self.Emit("MOVQ", _VAR_sv_p, _DI)
self.Emit("MOVQ", _VAR_bs_n, _SI)
self.Emit("MOVQ", _VAR_bs_LR, _R9)
self.Rjmp("JMP", _R9)
}
// Pointer: DI, Size: SI, Return: R9
func (self *_Assembler) escape_string() {
self.Link("_escape_string")
self.Emit("MOVQ" , _DI, _VAR_bs_p)
self.Emit("MOVQ" , _SI, _VAR_bs_n)
self.Emit("MOVQ" , _R9, _VAR_bs_LR)
self.malloc(_SI, _DX) // MALLOC SI, DX
self.Emit("MOVQ" , _DX, _VAR_sv_p)
self.Emit("MOVQ" , _VAR_bs_p, _DI)
self.Emit("MOVQ" , _VAR_bs_n, _SI)
self.Emit("LEAQ" , _VAR_sr, _CX) // LEAQ sr, CX
self.Emit("XORL" , _R8, _R8) // XORL R8, R8
self.Emit("BTQ" , jit.Imm(_F_disable_urc), _ARG_fv) // BTQ ${_F_disable_urc}, fv
self.Emit("SETCC", _R8) // SETCC R8
self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _R8) // SHLQ ${types.B_UNICODE_REPLACE}, R8
self.call(_F_unquote) // CALL unquote
self.Emit("MOVQ" , _VAR_bs_n, _SI) // MOVQ ${n}, SI
self.Emit("ADDQ" , jit.Imm(1), _SI) // ADDQ $1, SI
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_unquote_error) // JS _unquote_error
self.Emit("MOVQ" , _AX, _SI)
self.Emit("MOVQ" , _VAR_sv_p, _DI)
self.Emit("MOVQ" , _VAR_bs_LR, _R9)
self.Rjmp("JMP", _R9)
}
func (self *_Assembler) escape_string_twice() {
self.Link("_escape_string_twice")
self.Emit("MOVQ" , _DI, _VAR_bs_p)
self.Emit("MOVQ" , _SI, _VAR_bs_n)
self.Emit("MOVQ" , _R9, _VAR_bs_LR)
self.malloc(_SI, _DX) // MALLOC SI, DX
self.Emit("MOVQ" , _DX, _VAR_sv_p)
self.Emit("MOVQ" , _VAR_bs_p, _DI)
self.Emit("MOVQ" , _VAR_bs_n, _SI)
self.Emit("LEAQ" , _VAR_sr, _CX) // LEAQ sr, CX
self.Emit("MOVL" , jit.Imm(types.F_DOUBLE_UNQUOTE), _R8) // MOVL ${types.F_DOUBLE_UNQUOTE}, R8
self.Emit("BTQ" , jit.Imm(_F_disable_urc), _ARG_fv) // BTQ ${_F_disable_urc}, AX
self.Emit("XORL" , _AX, _AX) // XORL AX, AX
self.Emit("SETCC", _AX) // SETCC AX
self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _AX) // SHLQ ${types.B_UNICODE_REPLACE}, AX
self.Emit("ORQ" , _AX, _R8) // ORQ AX, R8
self.call(_F_unquote) // CALL unquote
self.Emit("MOVQ" , _VAR_bs_n, _SI) // MOVQ ${n}, SI
self.Emit("ADDQ" , jit.Imm(3), _SI) // ADDQ $3, SI
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_unquote_error) // JS _unquote_error
self.Emit("MOVQ" , _AX, _SI)
self.Emit("MOVQ" , _VAR_sv_p, _DI)
self.Emit("MOVQ" , _VAR_bs_LR, _R9)
self.Rjmp("JMP", _R9)
}
/** Range Checking Routines **/
var (
_V_max_f32 = jit.Imm(int64(uintptr(unsafe.Pointer(_Vp_max_f32))))
_V_min_f32 = jit.Imm(int64(uintptr(unsafe.Pointer(_Vp_min_f32))))
)
var (
_Vp_max_f32 = new(float64)
_Vp_min_f32 = new(float64)
)
func init() {
*_Vp_max_f32 = math.MaxFloat32
*_Vp_min_f32 = -math.MaxFloat32
}
func (self *_Assembler) range_single() {
self.Emit("MOVSD" , _VAR_st_Dv, _X0) // MOVSD st.Dv, X0
self.Emit("MOVQ" , _V_max_f32, _AX) // MOVQ _max_f32, AX
self.Emit("MOVQ" , jit.Gitab(_I_float32), _ET) // MOVQ ${itab(float32)}, ET
self.Emit("MOVQ" , jit.Gtype(_T_float32), _EP) // MOVQ ${type(float32)}, EP
self.Emit("UCOMISD" , jit.Ptr(_AX, 0), _X0) // UCOMISD (AX), X0
self.Sjmp("JA" , _LB_range_error) // JA _range_error
self.Emit("MOVQ" , _V_min_f32, _AX) // MOVQ _min_f32, AX
self.Emit("MOVSD" , jit.Ptr(_AX, 0), _X1) // MOVSD (AX), X1
self.Emit("UCOMISD" , _X0, _X1) // UCOMISD X0, X1
self.Sjmp("JA" , _LB_range_error) // JA _range_error
self.Emit("CVTSD2SS", _X0, _X0) // CVTSD2SS X0, X0
}
func (self *_Assembler) range_signed(i *rt.GoItab, t *rt.GoType, a int64, b int64) {
self.Emit("MOVQ", _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
self.Emit("MOVQ", jit.Gitab(i), _ET) // MOVQ ${i}, ET
self.Emit("MOVQ", jit.Gtype(t), _EP) // MOVQ ${t}, EP
self.Emit("CMPQ", _AX, jit.Imm(a)) // CMPQ AX, ${a}
self.Sjmp("JL" , _LB_range_error) // JL _range_error
self.Emit("CMPQ", _AX, jit.Imm(b)) // CMPQ AX, ${B}
self.Sjmp("JG" , _LB_range_error) // JG _range_error
}
func (self *_Assembler) range_unsigned(i *rt.GoItab, t *rt.GoType, v uint64) {
self.Emit("MOVQ" , _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
self.Emit("MOVQ" , jit.Gitab(i), _ET) // MOVQ ${i}, ET
self.Emit("MOVQ" , jit.Gtype(t), _EP) // MOVQ ${t}, EP
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_range_error) // JS _range_error
self.Emit("CMPQ" , _AX, jit.Imm(int64(v))) // CMPQ AX, ${a}
self.Sjmp("JA" , _LB_range_error) // JA _range_error
}
/** String Manipulating Routines **/
var (
_F_unquote = jit.Imm(int64(native.S_unquote))
)
func (self *_Assembler) slice_from(p obj.Addr, d int64) {
self.Emit("MOVQ", p, _SI) // MOVQ ${p}, SI
self.slice_from_r(_SI, d) // SLICE_R SI, ${d}
}
func (self *_Assembler) slice_from_r(p obj.Addr, d int64) {
self.Emit("LEAQ", jit.Sib(_IP, p, 1, 0), _DI) // LEAQ (IP)(${p}), DI
self.Emit("NEGQ", p) // NEGQ ${p}
self.Emit("LEAQ", jit.Sib(_IC, p, 1, d), _SI) // LEAQ d(IC)(${p}), SI
}
func (self *_Assembler) unquote_once(p obj.Addr, n obj.Addr, stack bool, copy bool) {
self.slice_from(_VAR_st_Iv, -1) // SLICE st.Iv, $-1
self.Emit("CMPQ" , _VAR_st_Ep, jit.Imm(-1)) // CMPQ st.Ep, $-1
self.Sjmp("JE" , "_noescape_{n}") // JE _noescape_{n}
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
self.Sref("_unquote_once_write_{n}", 4)
self.Sjmp("JMP" , "_escape_string")
self.Link("_noescape_{n}") // _noescape_{n}:
if copy {
self.Emit("BTQ" , jit.Imm(_F_copy_string), _ARG_fv)
self.Sjmp("JNC", "_unquote_once_write_{n}")
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
self.Sref("_unquote_once_write_{n}", 4)
self.Sjmp("JMP", "_copy_string")
}
self.Link("_unquote_once_write_{n}")
self.Emit("MOVQ" , _SI, n) // MOVQ SI, ${n}
if stack {
self.Emit("MOVQ", _DI, p)
} else {
self.WriteRecNotAX(10, _DI, p, false, false)
}
}
func (self *_Assembler) unquote_twice(p obj.Addr, n obj.Addr, stack bool) {
self.Emit("CMPQ" , _VAR_st_Ep, jit.Imm(-1)) // CMPQ st.Ep, $-1
self.Sjmp("JE" , _LB_eof_error) // JE _eof_error
self.Emit("CMPB" , jit.Sib(_IP, _IC, 1, -3), jit.Imm('\\')) // CMPB -3(IP)(IC), $'\\'
self.Sjmp("JNE" , _LB_char_m3_error) // JNE _char_m3_error
self.Emit("CMPB" , jit.Sib(_IP, _IC, 1, -2), jit.Imm('"')) // CMPB -2(IP)(IC), $'"'
self.Sjmp("JNE" , _LB_char_m2_error) // JNE _char_m2_error
self.slice_from(_VAR_st_Iv, -3) // SLICE st.Iv, $-3
self.Emit("MOVQ" , _SI, _AX) // MOVQ SI, AX
self.Emit("ADDQ" , _VAR_st_Iv, _AX) // ADDQ st.Iv, AX
self.Emit("CMPQ" , _VAR_st_Ep, _AX) // CMPQ st.Ep, AX
self.Sjmp("JE" , "_noescape_{n}") // JE _noescape_{n}
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
self.Sref("_unquote_twice_write_{n}", 4)
self.Sjmp("JMP" , "_escape_string_twice")
self.Link("_noescape_{n}") // _noescape_{n}:
self.Emit("BTQ" , jit.Imm(_F_copy_string), _ARG_fv)
self.Sjmp("JNC", "_unquote_twice_write_{n}")
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
self.Sref("_unquote_twice_write_{n}", 4)
self.Sjmp("JMP", "_copy_string")
self.Link("_unquote_twice_write_{n}")
self.Emit("MOVQ" , _SI, n) // MOVQ SI, ${n}
if stack {
self.Emit("MOVQ", _DI, p)
} else {
self.WriteRecNotAX(12, _DI, p, false, false)
}
}
/** Memory Clearing Routines **/
var (
_F_memclrHasPointers = jit.Func(memclrHasPointers)
_F_memclrNoHeapPointers = jit.Func(memclrNoHeapPointers)
)
func (self *_Assembler) mem_clear_fn(ptrfree bool) {
if !ptrfree {
self.call_go(_F_memclrHasPointers)
} else {
self.call_go(_F_memclrNoHeapPointers)
}
}
func (self *_Assembler) mem_clear_rem(size int64, ptrfree bool) {
self.Emit("MOVQ", jit.Imm(size), _CX) // MOVQ ${size}, CX
self.Emit("MOVQ", jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
self.Emit("MOVQ", jit.Sib(_ST, _AX, 1, 0), _AX) // MOVQ (ST)(AX), AX
self.Emit("SUBQ", _VP, _AX) // SUBQ VP, AX
self.Emit("ADDQ", _AX, _CX) // ADDQ AX, CX
self.Emit("MOVQ", _VP, jit.Ptr(_SP, 0)) // MOVQ VP, (SP)
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
self.mem_clear_fn(ptrfree) // CALL_GO memclr{Has,NoHeap}Pointers
}
/** Map Assigning Routines **/
var (
_F_mapassign = jit.Func(mapassign)
_F_mapassign_fast32 = jit.Func(mapassign_fast32)
_F_mapassign_faststr = jit.Func(mapassign_faststr)
_F_mapassign_fast64ptr = jit.Func(mapassign_fast64ptr)
)
var (
_F_decodeJsonUnmarshaler obj.Addr
_F_decodeTextUnmarshaler obj.Addr
)
func init() {
_F_decodeJsonUnmarshaler = jit.Func(decodeJsonUnmarshaler)
_F_decodeTextUnmarshaler = jit.Func(decodeTextUnmarshaler)
}
func (self *_Assembler) mapaccess_ptr(t reflect.Type) {
if rt.MapType(rt.UnpackType(t)).IndirectElem() {
self.vfollow(t.Elem())
}
}
func (self *_Assembler) mapassign_std(t reflect.Type, v obj.Addr) {
self.Emit("LEAQ", v, _AX) // LEAQ ${v}, AX
self.mapassign_call(t, _F_mapassign) // MAPASSIGN ${t}, mapassign
}
func (self *_Assembler) mapassign_str_fast(t reflect.Type, p obj.Addr, n obj.Addr) {
self.Emit("MOVQ", jit.Type(t), _AX) // MOVQ ${t}, AX
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
self.Emit("MOVQ", _VP, jit.Ptr(_SP, 8)) // MOVQ VP, 8(SP)
self.Emit("MOVQ", p, jit.Ptr(_SP, 16)) // MOVQ ${p}, 16(SP)
self.Emit("MOVQ", n, jit.Ptr(_SP, 24)) // MOVQ ${n}, 24(SP)
self.call_go(_F_mapassign_faststr) // CALL_GO ${fn}
self.Emit("MOVQ", jit.Ptr(_SP, 32), _VP) // MOVQ 32(SP), VP
self.mapaccess_ptr(t)
}
func (self *_Assembler) mapassign_call(t reflect.Type, fn obj.Addr) {
self.Emit("MOVQ", jit.Type(t), _SI) // MOVQ ${t}, SI
self.Emit("MOVQ", _SI, jit.Ptr(_SP, 0)) // MOVQ SI, (SP)
self.Emit("MOVQ", _VP, jit.Ptr(_SP, 8)) // MOVQ VP, 8(SP)
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 16)) // MOVQ AX, 16(SP)
self.call_go(fn) // CALL_GO ${fn}
self.Emit("MOVQ", jit.Ptr(_SP, 24), _VP) // MOVQ 24(SP), VP
}
func (self *_Assembler) mapassign_fastx(t reflect.Type, fn obj.Addr) {
self.mapassign_call(t, fn)
self.mapaccess_ptr(t)
}
func (self *_Assembler) mapassign_utext(t reflect.Type, addressable bool) {
pv := false
vk := t.Key()
tk := t.Key()
/* deref pointer if needed */
if vk.Kind() == reflect.Ptr {
pv = true
vk = vk.Elem()
}
/* addressable value with pointer receiver */
if addressable {
pv = false
tk = reflect.PtrTo(tk)
}
/* allocate the key, and call the unmarshaler */
self.valloc(vk, _DI) // VALLOC ${vk}, DI
// must spill vk pointer since next call_go may invoke GC
self.Emit("MOVQ" , _DI, _VAR_vk)
self.Emit("MOVQ" , jit.Type(tk), _AX) // MOVQ ${tk}, AX
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
self.Emit("MOVQ" , _DI, jit.Ptr(_SP, 8)) // MOVQ DI, 8(SP)
self.Emit("MOVOU", _VAR_sv, _X0) // MOVOU sv, X0
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 16)) // MOVOU X0, 16(SP)
self.call_go(_F_decodeTextUnmarshaler) // CALL_GO decodeTextUnmarshaler
self.Emit("MOVQ" , jit.Ptr(_SP, 32), _ET) // MOVQ 32(SP), ET
self.Emit("MOVQ" , jit.Ptr(_SP, 40), _EP) // MOVQ 40(SP), EP
self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET
self.Sjmp("JNZ" , _LB_error) // JNZ _error
self.Emit("MOVQ" , _VAR_vk, _AX)
/* select the correct assignment function */
if !pv {
self.mapassign_call(t, _F_mapassign)
} else {
self.mapassign_fastx(t, _F_mapassign_fast64ptr)
}
}
/** External Unmarshaler Routines **/
var (
_F_skip_one = jit.Imm(int64(native.S_skip_one))
_F_skip_number = jit.Imm(int64(native.S_skip_number))
)
func (self *_Assembler) unmarshal_json(t reflect.Type, deref bool) {
self.call_sf(_F_skip_one) // CALL_SF skip_one
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
self.slice_from_r(_AX, 0) // SLICE_R AX, $0
self.Emit("MOVQ" , _DI, _VAR_sv_p) // MOVQ DI, sv.p
self.Emit("MOVQ" , _SI, _VAR_sv_n) // MOVQ SI, sv.n
self.unmarshal_func(t, _F_decodeJsonUnmarshaler, deref) // UNMARSHAL json, ${t}, ${deref}
}
func (self *_Assembler) unmarshal_text(t reflect.Type, deref bool) {
self.parse_string() // PARSE STRING
self.unquote_once(_VAR_sv_p, _VAR_sv_n, true, true) // UNQUOTE once, sv.p, sv.n
self.unmarshal_func(t, _F_decodeTextUnmarshaler, deref) // UNMARSHAL text, ${t}, ${deref}
}
func (self *_Assembler) unmarshal_func(t reflect.Type, fn obj.Addr, deref bool) {
pt := t
vk := t.Kind()
/* allocate the field if needed */
if deref && vk == reflect.Ptr {
self.Emit("MOVQ" , _VP, _AX) // MOVQ VP, AX
self.Emit("MOVQ" , jit.Ptr(_AX, 0), _AX) // MOVQ (AX), AX
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JNZ" , "_deref_{n}") // JNZ _deref_{n}
self.valloc(t.Elem(), _AX) // VALLOC ${t.Elem()}, AX
self.WritePtrAX(3, jit.Ptr(_VP, 0), false) // MOVQ AX, (VP)
self.Link("_deref_{n}") // _deref_{n}:
}
/* set value type */
self.Emit("MOVQ", jit.Type(pt), _CX) // MOVQ ${pt}, CX
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 0)) // MOVQ CX, (SP)
/* set value pointer */
if deref && vk == reflect.Ptr {
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 8)) // MOVQ AX, 8(SP)
} else {
self.Emit("MOVQ", _VP, jit.Ptr(_SP, 8)) // MOVQ VP, 8(SP)
}
/* set the source string and call the unmarshaler */
self.Emit("MOVOU", _VAR_sv, _X0) // MOVOU sv, X0
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 16)) // MOVOU X0, 16(SP)
self.call_go(fn) // CALL_GO ${fn}
self.Emit("MOVQ" , jit.Ptr(_SP, 32), _ET) // MOVQ 32(SP), ET
self.Emit("MOVQ" , jit.Ptr(_SP, 40), _EP) // MOVQ 40(SP), EP
self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET
self.Sjmp("JNZ" , _LB_error) // JNZ _error
}
/** Dynamic Decoding Routine **/
var (
_F_decodeTypedPointer obj.Addr
)
func init() {
_F_decodeTypedPointer = jit.Func(decodeTypedPointer)
}
func (self *_Assembler) decode_dynamic(vt obj.Addr, vp obj.Addr) {
self.Emit("MOVQ" , _ARG_fv, _CX) // MOVQ fv, CX
self.Emit("MOVOU", _ARG_sp, _X0) // MOVOU sp, X0
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 0)) // MOVOU X0, (SP)
self.Emit("MOVQ" , _IC, jit.Ptr(_SP, 16)) // MOVQ IC, 16(SP)
self.Emit("MOVQ" , vt, jit.Ptr(_SP, 24)) // MOVQ ${vt}, 24(SP)
self.Emit("MOVQ" , vp, jit.Ptr(_SP, 32)) // MOVQ ${vp}, 32(SP)
self.Emit("MOVQ" , _ST, jit.Ptr(_SP, 40)) // MOVQ ST, 40(SP)
self.Emit("MOVQ" , _CX, jit.Ptr(_SP, 48)) // MOVQ CX, 48(SP)
self.call_go(_F_decodeTypedPointer) // CALL_GO decodeTypedPointer
self.Emit("MOVQ" , jit.Ptr(_SP, 64), _ET) // MOVQ 64(SP), ET
self.Emit("MOVQ" , jit.Ptr(_SP, 72), _EP) // MOVQ 72(SP), EP
self.Emit("MOVQ" , jit.Ptr(_SP, 56), _IC) // MOVQ 56(SP), IC
self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET
self.Sjmp("JE", "_decode_dynamic_end_{n}") // JE, _decode_dynamic_end_{n}
self.Emit("MOVQ", _I_json_MismatchTypeError, _AX) // MOVQ _I_json_MismatchTypeError, AX
self.Emit("CMPQ", _ET, _AX) // CMPQ ET, AX
self.Sjmp("JNE" , _LB_error) // JNE LB_error
self.Emit("MOVQ", _EP, _VAR_ic) // MOVQ EP, VAR_ic
self.Emit("MOVQ", _ET, _VAR_et) // MOVQ ET, VAR_et
self.Link("_decode_dynamic_end_{n}")
}
/** OpCode Assembler Functions **/
var (
_F_memequal = jit.Func(memequal)
_F_memmove = jit.Func(memmove)
_F_growslice = jit.Func(growslice)
_F_makeslice = jit.Func(makeslice)
_F_makemap_small = jit.Func(makemap_small)
_F_mapassign_fast64 = jit.Func(mapassign_fast64)
)
var (
_F_lspace = jit.Imm(int64(native.S_lspace))
_F_strhash = jit.Imm(int64(caching.S_strhash))
)
var (
_F_b64decode = jit.Imm(int64(_subr__b64decode))
_F_decodeValue = jit.Imm(int64(_subr_decode_value))
)
var (
_F_skip_array = jit.Imm(int64(native.S_skip_array))
_F_skip_object = jit.Imm(int64(native.S_skip_object))
)
var (
_F_FieldMap_GetCaseInsensitive obj.Addr
_Empty_Slice = make([]byte, 0)
_Zero_Base = int64(uintptr(((*rt.GoSlice)(unsafe.Pointer(&_Empty_Slice))).Ptr))
)
const (
_MODE_AVX2 = 1 << 2
)
const (
_Fe_ID = int64(unsafe.Offsetof(caching.FieldEntry{}.ID))
_Fe_Name = int64(unsafe.Offsetof(caching.FieldEntry{}.Name))
_Fe_Hash = int64(unsafe.Offsetof(caching.FieldEntry{}.Hash))
)
const (
_Vk_Ptr = int64(reflect.Ptr)
_Gt_KindFlags = int64(unsafe.Offsetof(rt.GoType{}.KindFlags))
)
func init() {
_F_FieldMap_GetCaseInsensitive = jit.Func((*caching.FieldMap).GetCaseInsensitive)
}
func (self *_Assembler) _asm_OP_any(_ *_Instr) {
self.Emit("MOVQ" , jit.Ptr(_VP, 8), _CX) // MOVQ 8(VP), CX
self.Emit("TESTQ" , _CX, _CX) // TESTQ CX, CX
self.Sjmp("JZ" , "_decode_{n}") // JZ _decode_{n}
self.Emit("CMPQ" , _CX, _VP) // CMPQ CX, VP
self.Sjmp("JE" , "_decode_{n}") // JE _decode_{n}
self.Emit("MOVQ" , jit.Ptr(_VP, 0), _AX) // MOVQ (VP), AX
self.Emit("MOVBLZX", jit.Ptr(_AX, _Gt_KindFlags), _DX) // MOVBLZX _Gt_KindFlags(AX), DX
self.Emit("ANDL" , jit.Imm(rt.F_kind_mask), _DX) // ANDL ${F_kind_mask}, DX
self.Emit("CMPL" , _DX, jit.Imm(_Vk_Ptr)) // CMPL DX, ${reflect.Ptr}
self.Sjmp("JNE" , "_decode_{n}") // JNE _decode_{n}
self.Emit("LEAQ" , jit.Ptr(_VP, 8), _DI) // LEAQ 8(VP), DI
self.decode_dynamic(_AX, _DI) // DECODE AX, DI
self.Sjmp("JMP" , "_decode_end_{n}") // JMP _decode_end_{n}
self.Link("_decode_{n}") // _decode_{n}:
self.Emit("MOVQ" , _ARG_fv, _DF) // MOVQ fv, DF
self.Emit("MOVQ" , _ST, jit.Ptr(_SP, 0)) // MOVQ _ST, (SP)
self.call(_F_decodeValue) // CALL decodeValue
self.Emit("TESTQ" , _EP, _EP) // TESTQ EP, EP
self.Sjmp("JNZ" , _LB_parsing_error) // JNZ _parsing_error
self.Link("_decode_end_{n}") // _decode_end_{n}:
}
func (self *_Assembler) _asm_OP_dyn(p *_Instr) {
self.Emit("MOVQ" , jit.Type(p.vt()), _ET) // MOVQ ${p.vt()}, ET
self.Emit("CMPQ" , jit.Ptr(_VP, 8), jit.Imm(0)) // CMPQ 8(VP), $0
self.Sjmp("JE" , _LB_type_error) // JE _type_error
self.Emit("MOVQ" , jit.Ptr(_VP, 0), _AX) // MOVQ (VP), AX
self.Emit("MOVQ" , jit.Ptr(_AX, 8), _AX) // MOVQ 8(AX), AX
self.Emit("MOVBLZX", jit.Ptr(_AX, _Gt_KindFlags), _DX) // MOVBLZX _Gt_KindFlags(AX), DX
self.Emit("ANDL" , jit.Imm(rt.F_kind_mask), _DX) // ANDL ${F_kind_mask}, DX
self.Emit("CMPL" , _DX, jit.Imm(_Vk_Ptr)) // CMPL DX, ${reflect.Ptr}
self.Sjmp("JNE" , _LB_type_error) // JNE _type_error
self.Emit("LEAQ" , jit.Ptr(_VP, 8), _DI) // LEAQ 8(VP), DI
self.decode_dynamic(_AX, _DI) // DECODE AX, DI
self.Link("_decode_end_{n}") // _decode_end_{n}:
}
func (self *_Assembler) _asm_OP_str(_ *_Instr) {
self.parse_string() // PARSE STRING
self.unquote_once(jit.Ptr(_VP, 0), jit.Ptr(_VP, 8), false, true) // UNQUOTE once, (VP), 8(VP)
}
func (self *_Assembler) _asm_OP_bin(_ *_Instr) {
self.parse_string() // PARSE STRING
self.slice_from(_VAR_st_Iv, -1) // SLICE st.Iv, $-1
self.Emit("MOVQ" , _DI, jit.Ptr(_VP, 0)) // MOVQ DI, (VP)
self.Emit("MOVQ" , _SI, jit.Ptr(_VP, 8)) // MOVQ SI, 8(VP)
self.Emit("SHRQ" , jit.Imm(2), _SI) // SHRQ $2, SI
self.Emit("LEAQ" , jit.Sib(_SI, _SI, 2, 0), _SI) // LEAQ (SI)(SI*2), SI
self.Emit("MOVQ" , _SI, jit.Ptr(_VP, 16)) // MOVQ SI, 16(VP)
self.malloc(_SI, _SI) // MALLOC SI, SI
// TODO: due to base64x's bug, only use AVX mode now
self.Emit("MOVL", jit.Imm(_MODE_JSON), _CX) // MOVL $_MODE_JSON, CX
/* call the decoder */
self.Emit("XORL" , _DX, _DX) // XORL DX, DX
self.Emit("MOVQ" , _VP, _DI) // MOVQ VP, DI
self.Emit("MOVQ" , jit.Ptr(_VP, 0), _R9) // MOVQ SI, VP)
self.WriteRecNotAX(4, _SI, jit.Ptr(_VP, 0), true, false) // XCHGQ SI, (VP)
self.Emit("MOVQ" , _R9, _SI)
self.Emit("XCHGQ", _DX, jit.Ptr(_VP, 8)) // XCHGQ DX, 8(VP)
self.call(_F_b64decode) // CALL b64decode
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_base64_error) // JS _base64_error
self.Emit("MOVQ" , _AX, jit.Ptr(_VP, 8)) // MOVQ AX, 8(VP)
}
func (self *_Assembler) _asm_OP_bool(_ *_Instr) {
self.Emit("LEAQ", jit.Ptr(_IC, 4), _AX) // LEAQ 4(IC), AX
self.Emit("CMPQ", _AX, _IL) // CMPQ AX, IL
self.Sjmp("JA" , _LB_eof_error) // JA _eof_error
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('f')) // CMPB (IP)(IC), $'f'
self.Sjmp("JE" , "_false_{n}") // JE _false_{n}
self.Emit("MOVL", jit.Imm(_IM_true), _CX) // MOVL $"true", CX
self.Emit("CMPL", _CX, jit.Sib(_IP, _IC, 1, 0)) // CMPL CX, (IP)(IC)
self.Sjmp("JE" , "_bool_true_{n}")
// try to skip the value
self.Emit("MOVQ", _IC, _VAR_ic)
self.Emit("MOVQ", _T_bool, _ET)
self.Emit("MOVQ", _ET, _VAR_et)
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
self.Sref("_end_{n}", 4)
self.Emit("MOVQ", _R9, _VAR_pc)
self.Sjmp("JMP" , _LB_skip_one)
self.Link("_bool_true_{n}")
self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC
self.Emit("MOVB", jit.Imm(1), jit.Ptr(_VP, 0)) // MOVB $1, (VP)
self.Sjmp("JMP" , "_end_{n}") // JMP _end_{n}
self.Link("_false_{n}") // _false_{n}:
self.Emit("ADDQ", jit.Imm(1), _AX) // ADDQ $1, AX
self.Emit("ADDQ", jit.Imm(1), _IC) // ADDQ $1, IC
self.Emit("CMPQ", _AX, _IL) // CMPQ AX, IL
self.Sjmp("JA" , _LB_eof_error) // JA _eof_error
self.Emit("MOVL", jit.Imm(_IM_alse), _CX) // MOVL $"alse", CX
self.Emit("CMPL", _CX, jit.Sib(_IP, _IC, 1, 0)) // CMPL CX, (IP)(IC)
self.Sjmp("JNE" , _LB_im_error) // JNE _im_error
self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC
self.Emit("XORL", _AX, _AX) // XORL AX, AX
self.Emit("MOVB", _AX, jit.Ptr(_VP, 0)) // MOVB AX, (VP)
self.Link("_end_{n}") // _end_{n}:
}
func (self *_Assembler) _asm_OP_num(_ *_Instr) {
self.Emit("MOVQ", jit.Imm(0), _VAR_fl)
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('"'))
self.Emit("MOVQ", _IC, _BP)
self.Sjmp("JNE", "_skip_number_{n}")
self.Emit("MOVQ", jit.Imm(1), _VAR_fl)
self.Emit("ADDQ", jit.Imm(1), _IC)
self.Link("_skip_number_{n}")
/* call skip_number */
self.call_sf(_F_skip_number) // CALL_SF skip_one
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JNS" , "_num_next_{n}")
/* call skip one */
self.Emit("MOVQ", _BP, _VAR_ic)
self.Emit("MOVQ", _T_number, _ET)
self.Emit("MOVQ", _ET, _VAR_et)
self.Byte(0x4c, 0x8d, 0x0d)
self.Sref("_num_end_{n}", 4)
self.Emit("MOVQ", _R9, _VAR_pc)
self.Sjmp("JMP" , _LB_skip_one)
/* assgin string */
self.Link("_num_next_{n}")
self.slice_from_r(_AX, 0)
self.Emit("BTQ", jit.Imm(_F_copy_string), _ARG_fv)
self.Sjmp("JNC", "_num_write_{n}")
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
self.Sref("_num_write_{n}", 4)
self.Sjmp("JMP", "_copy_string")
self.Link("_num_write_{n}")
self.Emit("MOVQ", _SI, jit.Ptr(_VP, 8)) // MOVQ SI, 8(VP)
self.WriteRecNotAX(13, _DI, jit.Ptr(_VP, 0), false, false)
/* check if quoted */
self.Emit("CMPQ", _VAR_fl, jit.Imm(1))
self.Sjmp("JNE", "_num_end_{n}")
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('"'))
self.Sjmp("JNE", _LB_char_0_error)
self.Emit("ADDQ", jit.Imm(1), _IC)
self.Link("_num_end_{n}")
}
func (self *_Assembler) _asm_OP_i8(ins *_Instr) {
var pin = "_i8_end_{n}"
self.parse_signed(int8Type, pin, -1) // PARSE int8
self.range_signed(_I_int8, _T_int8, math.MinInt8, math.MaxInt8) // RANGE int8
self.Emit("MOVB", _AX, jit.Ptr(_VP, 0)) // MOVB AX, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_i16(ins *_Instr) {
var pin = "_i16_end_{n}"
self.parse_signed(int16Type, pin, -1) // PARSE int16
self.range_signed(_I_int16, _T_int16, math.MinInt16, math.MaxInt16) // RANGE int16
self.Emit("MOVW", _AX, jit.Ptr(_VP, 0)) // MOVW AX, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_i32(ins *_Instr) {
var pin = "_i32_end_{n}"
self.parse_signed(int32Type, pin, -1) // PARSE int32
self.range_signed(_I_int32, _T_int32, math.MinInt32, math.MaxInt32) // RANGE int32
self.Emit("MOVL", _AX, jit.Ptr(_VP, 0)) // MOVL AX, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_i64(ins *_Instr) {
var pin = "_i64_end_{n}"
self.parse_signed(int64Type, pin, -1) // PARSE int64
self.Emit("MOVQ", _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
self.Emit("MOVQ", _AX, jit.Ptr(_VP, 0)) // MOVQ AX, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_u8(ins *_Instr) {
var pin = "_u8_end_{n}"
self.parse_unsigned(uint8Type, pin, -1) // PARSE uint8
self.range_unsigned(_I_uint8, _T_uint8, math.MaxUint8) // RANGE uint8
self.Emit("MOVB", _AX, jit.Ptr(_VP, 0)) // MOVB AX, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_u16(ins *_Instr) {
var pin = "_u16_end_{n}"
self.parse_unsigned(uint16Type, pin, -1) // PARSE uint16
self.range_unsigned(_I_uint16, _T_uint16, math.MaxUint16) // RANGE uint16
self.Emit("MOVW", _AX, jit.Ptr(_VP, 0)) // MOVW AX, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_u32(ins *_Instr) {
var pin = "_u32_end_{n}"
self.parse_unsigned(uint32Type, pin, -1) // PARSE uint32
self.range_unsigned(_I_uint32, _T_uint32, math.MaxUint32) // RANGE uint32
self.Emit("MOVL", _AX, jit.Ptr(_VP, 0)) // MOVL AX, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_u64(ins *_Instr) {
var pin = "_u64_end_{n}"
self.parse_unsigned(uint64Type, pin, -1) // PARSE uint64
self.Emit("MOVQ", _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
self.Emit("MOVQ", _AX, jit.Ptr(_VP, 0)) // MOVQ AX, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_f32(ins *_Instr) {
var pin = "_f32_end_{n}"
self.parse_number(float32Type, pin, -1) // PARSE NUMBER
self.range_single() // RANGE float32
self.Emit("MOVSS", _X0, jit.Ptr(_VP, 0)) // MOVSS X0, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_f64(ins *_Instr) {
var pin = "_f64_end_{n}"
self.parse_number(float64Type, pin, -1) // PARSE NUMBER
self.Emit("MOVSD", _VAR_st_Dv, _X0) // MOVSD st.Dv, X0
self.Emit("MOVSD", _X0, jit.Ptr(_VP, 0)) // MOVSD X0, (VP)
self.Link(pin)
}
func (self *_Assembler) _asm_OP_unquote(ins *_Instr) {
self.check_eof(2)
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('\\')) // CMPB (IP)(IC), $'\\'
self.Sjmp("JNE" , _LB_char_0_error) // JNE _char_0_error
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 1), jit.Imm('"')) // CMPB 1(IP)(IC), $'"'
self.Sjmp("JNE" , _LB_char_1_error) // JNE _char_1_error
self.Emit("ADDQ", jit.Imm(2), _IC) // ADDQ $2, IC
self.parse_string() // PARSE STRING
self.unquote_twice(jit.Ptr(_VP, 0), jit.Ptr(_VP, 8), false) // UNQUOTE twice, (VP), 8(VP)
}
func (self *_Assembler) _asm_OP_nil_1(_ *_Instr) {
self.Emit("XORL", _AX, _AX) // XORL AX, AX
self.Emit("MOVQ", _AX, jit.Ptr(_VP, 0)) // MOVQ AX, (VP)
}
func (self *_Assembler) _asm_OP_nil_2(_ *_Instr) {
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
self.Emit("MOVOU", _X0, jit.Ptr(_VP, 0)) // MOVOU X0, (VP)
}
func (self *_Assembler) _asm_OP_nil_3(_ *_Instr) {
self.Emit("XORL" , _AX, _AX) // XORL AX, AX
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
self.Emit("MOVOU", _X0, jit.Ptr(_VP, 0)) // MOVOU X0, (VP)
self.Emit("MOVQ" , _AX, jit.Ptr(_VP, 16)) // MOVOU X0, 16(VP)
}
func (self *_Assembler) _asm_OP_deref(p *_Instr) {
self.vfollow(p.vt())
}
func (self *_Assembler) _asm_OP_index(p *_Instr) {
self.Emit("MOVQ", jit.Imm(p.i64()), _AX) // MOVQ ${p.vi()}, AX
self.Emit("ADDQ", _AX, _VP) // ADDQ _AX, _VP
}
func (self *_Assembler) _asm_OP_is_null(p *_Instr) {
self.Emit("LEAQ" , jit.Ptr(_IC, 4), _AX) // LEAQ 4(IC), AX
self.Emit("CMPQ" , _AX, _IL) // CMPQ AX, IL
self.Sjmp("JA" , "_not_null_{n}") // JA _not_null_{n}
self.Emit("CMPL" , jit.Sib(_IP, _IC, 1, 0), jit.Imm(_IM_null)) // CMPL (IP)(IC), $"null"
self.Emit("CMOVQEQ", _AX, _IC) // CMOVQEQ AX, IC
self.Xjmp("JE" , p.vi()) // JE {p.vi()}
self.Link("_not_null_{n}") // _not_null_{n}:
}
func (self *_Assembler) _asm_OP_is_null_quote(p *_Instr) {
self.Emit("LEAQ" , jit.Ptr(_IC, 5), _AX) // LEAQ 4(IC), AX
self.Emit("CMPQ" , _AX, _IL) // CMPQ AX, IL
self.Sjmp("JA" , "_not_null_quote_{n}") // JA _not_null_quote_{n}
self.Emit("CMPL" , jit.Sib(_IP, _IC, 1, 0), jit.Imm(_IM_null)) // CMPL (IP)(IC), $"null"
self.Sjmp("JNE" , "_not_null_quote_{n}") // JNE _not_null_quote_{n}
self.Emit("CMPB" , jit.Sib(_IP, _IC, 1, 4), jit.Imm('"')) // CMPB 4(IP)(IC), $'"'
self.Emit("CMOVQEQ", _AX, _IC) // CMOVQEQ AX, IC
self.Xjmp("JE" , p.vi()) // JE {p.vi()}
self.Link("_not_null_quote_{n}") // _not_null_quote_{n}:
}
func (self *_Assembler) _asm_OP_map_init(_ *_Instr) {
self.Emit("MOVQ" , jit.Ptr(_VP, 0), _AX) // MOVQ (VP), AX
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JNZ" , "_end_{n}") // JNZ _end_{n}
self.call_go(_F_makemap_small) // CALL_GO makemap_small
self.Emit("MOVQ" , jit.Ptr(_SP, 0), _AX) // MOVQ (SP), AX
self.WritePtrAX(6, jit.Ptr(_VP, 0), false) // MOVQ AX, (VP)
self.Link("_end_{n}") // _end_{n}:
self.Emit("MOVQ" , _AX, _VP) // MOVQ AX, VP
}
func (self *_Assembler) _asm_OP_map_key_i8(p *_Instr) {
self.parse_signed(int8Type, "", p.vi()) // PARSE int8
self.range_signed(_I_int8, _T_int8, math.MinInt8, math.MaxInt8) // RANGE int8
self.match_char('"')
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN int8, mapassign, st.Iv
}
func (self *_Assembler) _asm_OP_map_key_i16(p *_Instr) {
self.parse_signed(int16Type, "", p.vi()) // PARSE int16
self.range_signed(_I_int16, _T_int16, math.MinInt16, math.MaxInt16) // RANGE int16
self.match_char('"')
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN int16, mapassign, st.Iv
}
func (self *_Assembler) _asm_OP_map_key_i32(p *_Instr) {
self.parse_signed(int32Type, "", p.vi()) // PARSE int32
self.range_signed(_I_int32, _T_int32, math.MinInt32, math.MaxInt32) // RANGE int32
self.match_char('"')
if vt := p.vt(); !mapfast(vt) {
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN int32, mapassign, st.Iv
} else {
self.mapassign_fastx(vt, _F_mapassign_fast32) // MAPASSIGN int32, mapassign_fast32
}
}
func (self *_Assembler) _asm_OP_map_key_i64(p *_Instr) {
self.parse_signed(int64Type, "", p.vi()) // PARSE int64
self.match_char('"')
if vt := p.vt(); !mapfast(vt) {
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN int64, mapassign, st.Iv
} else {
self.Emit("MOVQ", _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
self.mapassign_fastx(vt, _F_mapassign_fast64) // MAPASSIGN int64, mapassign_fast64
}
}
func (self *_Assembler) _asm_OP_map_key_u8(p *_Instr) {
self.parse_unsigned(uint8Type, "", p.vi()) // PARSE uint8
self.range_unsigned(_I_uint8, _T_uint8, math.MaxUint8) // RANGE uint8
self.match_char('"')
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN uint8, vt.Iv
}
func (self *_Assembler) _asm_OP_map_key_u16(p *_Instr) {
self.parse_unsigned(uint16Type, "", p.vi()) // PARSE uint16
self.range_unsigned(_I_uint16, _T_uint16, math.MaxUint16) // RANGE uint16
self.match_char('"')
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN uint16, vt.Iv
}
func (self *_Assembler) _asm_OP_map_key_u32(p *_Instr) {
self.parse_unsigned(uint32Type, "", p.vi()) // PARSE uint32
self.range_unsigned(_I_uint32, _T_uint32, math.MaxUint32) // RANGE uint32
self.match_char('"')
if vt := p.vt(); !mapfast(vt) {
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN uint32, vt.Iv
} else {
self.mapassign_fastx(vt, _F_mapassign_fast32) // MAPASSIGN uint32, mapassign_fast32
}
}
func (self *_Assembler) _asm_OP_map_key_u64(p *_Instr) {
self.parse_unsigned(uint64Type, "", p.vi()) // PARSE uint64
self.match_char('"')
if vt := p.vt(); !mapfast(vt) {
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN uint64, vt.Iv
} else {
self.Emit("MOVQ", _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
self.mapassign_fastx(vt, _F_mapassign_fast64) // MAPASSIGN uint64, mapassign_fast64
}
}
func (self *_Assembler) _asm_OP_map_key_f32(p *_Instr) {
self.parse_number(float32Type, "", p.vi()) // PARSE NUMBER
self.range_single() // RANGE float32
self.Emit("MOVSS", _X0, _VAR_st_Dv) // MOVSS X0, st.Dv
self.match_char('"')
self.mapassign_std(p.vt(), _VAR_st_Dv) // MAPASSIGN ${p.vt()}, mapassign, st.Dv
}
func (self *_Assembler) _asm_OP_map_key_f64(p *_Instr) {
self.parse_number(float64Type, "", p.vi()) // PARSE NUMBER
self.match_char('"')
self.mapassign_std(p.vt(), _VAR_st_Dv) // MAPASSIGN ${p.vt()}, mapassign, st.Dv
}
func (self *_Assembler) _asm_OP_map_key_str(p *_Instr) {
self.parse_string() // PARSE STRING
self.unquote_once(_VAR_sv_p, _VAR_sv_n, true, true) // UNQUOTE once, sv.p, sv.n
if vt := p.vt(); !mapfast(vt) {
self.valloc(vt.Key(), _DI)
self.Emit("MOVOU", _VAR_sv, _X0)
self.Emit("MOVOU", _X0, jit.Ptr(_DI, 0))
self.mapassign_std(vt, jit.Ptr(_DI, 0))
} else {
self.Emit("MOVQ", _VAR_sv_p, _DI) // MOVQ sv.p, DI
self.Emit("MOVQ", _VAR_sv_n, _SI) // MOVQ sv.n, SI
self.mapassign_str_fast(vt, _DI, _SI) // MAPASSIGN string, DI, SI
}
}
func (self *_Assembler) _asm_OP_map_key_utext(p *_Instr) {
self.parse_string() // PARSE STRING
self.unquote_once(_VAR_sv_p, _VAR_sv_n, true, true) // UNQUOTE once, sv.p, sv.n
self.mapassign_utext(p.vt(), false) // MAPASSIGN utext, ${p.vt()}, false
}
func (self *_Assembler) _asm_OP_map_key_utext_p(p *_Instr) {
self.parse_string() // PARSE STRING
self.unquote_once(_VAR_sv_p, _VAR_sv_n, true, false) // UNQUOTE once, sv.p, sv.n
self.mapassign_utext(p.vt(), true) // MAPASSIGN utext, ${p.vt()}, true
}
func (self *_Assembler) _asm_OP_array_skip(_ *_Instr) {
self.call_sf(_F_skip_array) // CALL_SF skip_array
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
}
func (self *_Assembler) _asm_OP_array_clear(p *_Instr) {
self.mem_clear_rem(p.i64(), true)
}
func (self *_Assembler) _asm_OP_array_clear_p(p *_Instr) {
self.mem_clear_rem(p.i64(), false)
}
func (self *_Assembler) _asm_OP_slice_init(p *_Instr) {
self.Emit("XORL" , _AX, _AX) // XORL AX, AX
self.Emit("MOVQ" , _AX, jit.Ptr(_VP, 8)) // MOVQ AX, 8(VP)
self.Emit("MOVQ" , jit.Ptr(_VP, 16), _AX) // MOVQ 16(VP), AX
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JNZ" , "_done_{n}") // JNZ _done_{n}
self.Emit("MOVQ" , jit.Imm(_MinSlice), _CX) // MOVQ ${_MinSlice}, CX
self.Emit("MOVQ" , _CX, jit.Ptr(_VP, 16)) // MOVQ CX, 16(VP)
self.Emit("MOVQ" , jit.Type(p.vt()), _DX) // MOVQ ${p.vt()}, DX
self.Emit("MOVQ" , _DX, jit.Ptr(_SP, 0)) // MOVQ DX, (SP)
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 8)) // MOVQ AX, 8(SP)
self.Emit("MOVQ" , _CX, jit.Ptr(_SP, 16)) // MOVQ CX, 16(SP)
self.call_go(_F_makeslice) // CALL_GO makeslice
self.Emit("MOVQ" , jit.Ptr(_SP, 24), _AX) // MOVQ 24(SP), AX
self.WritePtrAX(7, jit.Ptr(_VP, 0), false) // MOVQ AX, (VP)
self.Link("_done_{n}") // _done_{n}:
self.Emit("XORL" , _AX, _AX) // XORL AX, AX
self.Emit("MOVQ" , _AX, jit.Ptr(_VP, 8)) // MOVQ AX, 8(VP)
}
func (self *_Assembler) _asm_OP_check_empty(p *_Instr) {
rbracket := p.vb()
if rbracket == ']' {
self.check_eof(1)
self.Emit("LEAQ", jit.Ptr(_IC, 1), _AX) // LEAQ 1(IC), AX
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(rbracket))) // CMPB (IP)(IC), ']'
self.Sjmp("JNE" , "_not_empty_array_{n}") // JNE _not_empty_array_{n}
self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC
self.StorePtr(_Zero_Base, jit.Ptr(_VP, 0), _AX) // MOVQ $zerobase, (VP)
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
self.Emit("MOVOU", _X0, jit.Ptr(_VP, 8)) // MOVOU X0, 8(VP)
self.Xjmp("JMP" , p.vi()) // JMP {p.vi()}
self.Link("_not_empty_array_{n}")
} else {
panic("only implement check empty array here!")
}
}
func (self *_Assembler) _asm_OP_slice_append(p *_Instr) {
self.Emit("MOVQ" , jit.Ptr(_VP, 8), _AX) // MOVQ 8(VP), AX
self.Emit("CMPQ" , _AX, jit.Ptr(_VP, 16)) // CMPQ AX, 16(VP)
self.Sjmp("JB" , "_index_{n}") // JB _index_{n}
self.Emit("MOVQ" , jit.Type(p.vt()), _AX) // MOVQ ${p.vt()}, AX
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
self.Emit("MOVOU", jit.Ptr(_VP, 0), _X0) // MOVOU (VP), X0
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 8)) // MOVOU X0, 8(SP)
self.Emit("MOVQ" , jit.Ptr(_VP, 16), _AX) // MOVQ 16(VP), AX
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 24)) // MOVQ AX, 24(SP)
self.Emit("SHLQ" , jit.Imm(1), _AX) // SHLQ $1, AX
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 32)) // MOVQ AX, 32(SP)
self.call_go(_F_growslice) // CALL_GO growslice
self.Emit("MOVQ" , jit.Ptr(_SP, 40), _DI) // MOVQ 40(SP), DI
self.Emit("MOVQ" , jit.Ptr(_SP, 48), _AX) // MOVQ 48(SP), AX
self.Emit("MOVQ" , jit.Ptr(_SP, 56), _SI) // MOVQ 56(SP), SI
self.WriteRecNotAX(8, _DI, jit.Ptr(_VP, 0), true, true)// MOVQ DI, (VP)
self.Emit("MOVQ" , _AX, jit.Ptr(_VP, 8)) // MOVQ AX, 8(VP)
self.Emit("MOVQ" , _SI, jit.Ptr(_VP, 16)) // MOVQ SI, 16(VP)
// because growslice not zero memory {oldcap, newlen} when append et not has ptrdata.
// but we should zero it, avoid decode it as random values.
if rt.UnpackType(p.vt()).PtrData == 0 {
self.Emit("SUBQ" , _AX, _SI) // MOVQ AX, SI
self.Emit("ADDQ" , jit.Imm(1), jit.Ptr(_VP, 8)) // ADDQ $1, 8(VP)
self.Emit("MOVQ" , _DI, _VP) // MOVQ DI, VP
self.Emit("MOVQ" , jit.Imm(int64(p.vlen())), _CX) // MOVQ ${p.vlen()}, CX
self.From("MULQ" , _CX) // MULQ CX
self.Emit("ADDQ" , _AX, _VP) // ADDQ AX, VP
self.Emit("MOVQ" , _SI, _AX) // MOVQ SI, AX
self.From("MULQ" , _CX) // MULQ CX
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 8)) // MOVQ AX, 8(SP)
self.Emit("MOVQ" , _VP, jit.Ptr(_SP, 0)) // MOVQ VP, (SP)
self.mem_clear_fn(true) // CALL_GO memclr{Has,NoHeap}
self.Sjmp("JMP", "_append_slice_end_{n}") // JMP _append_slice_end_{n}
}
self.Link("_index_{n}") // _index_{n}:
self.Emit("ADDQ" , jit.Imm(1), jit.Ptr(_VP, 8)) // ADDQ $1, 8(VP)
self.Emit("MOVQ" , jit.Ptr(_VP, 0), _VP) // MOVQ (VP), VP
self.Emit("MOVQ" , jit.Imm(int64(p.vlen())), _CX) // MOVQ ${p.vlen()}, CX
self.From("MULQ" , _CX) // MULQ CX
self.Emit("ADDQ" , _AX, _VP) // ADDQ AX, VP
self.Link("_append_slice_end_{n}")
}
func (self *_Assembler) _asm_OP_object_skip(_ *_Instr) {
self.call_sf(_F_skip_object) // CALL_SF skip_object
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
}
func (self *_Assembler) _asm_OP_object_next(_ *_Instr) {
self.call_sf(_F_skip_one) // CALL_SF skip_one
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
}
func (self *_Assembler) _asm_OP_struct_field(p *_Instr) {
assert_eq(caching.FieldEntrySize, 32, "invalid field entry size")
self.Emit("MOVQ" , jit.Imm(-1), _AX) // MOVQ $-1, AX
self.Emit("MOVQ" , _AX, _VAR_sr) // MOVQ AX, sr
self.parse_string() // PARSE STRING
self.unquote_once(_VAR_sv_p, _VAR_sv_n, true, false) // UNQUOTE once, sv.p, sv.n
self.Emit("LEAQ" , _VAR_sv, _AX) // LEAQ sv, AX
self.Emit("XORL" , _CX, _CX) // XORL CX, CX
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
self.Emit("MOVQ" , _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
self.call_go(_F_strhash) // CALL_GO strhash
self.Emit("MOVQ" , jit.Ptr(_SP, 16), _AX) // MOVQ 16(SP), AX
self.Emit("MOVQ" , _AX, _R9) // MOVQ AX, R9
self.Emit("MOVQ" , jit.Imm(freezeFields(p.vf())), _CX) // MOVQ ${p.vf()}, CX
self.Emit("MOVQ" , jit.Ptr(_CX, caching.FieldMap_b), _SI) // MOVQ FieldMap.b(CX), SI
self.Emit("MOVQ" , jit.Ptr(_CX, caching.FieldMap_N), _CX) // MOVQ FieldMap.N(CX), CX
self.Emit("TESTQ", _CX, _CX) // TESTQ CX, CX
self.Sjmp("JZ" , "_try_lowercase_{n}") // JZ _try_lowercase_{n}
self.Link("_loop_{n}") // _loop_{n}:
self.Emit("XORL" , _DX, _DX) // XORL DX, DX
self.From("DIVQ" , _CX) // DIVQ CX
self.Emit("LEAQ" , jit.Ptr(_DX, 1), _AX) // LEAQ 1(DX), AX
self.Emit("SHLQ" , jit.Imm(5), _DX) // SHLQ $5, DX
self.Emit("LEAQ" , jit.Sib(_SI, _DX, 1, 0), _DI) // LEAQ (SI)(DX), DI
self.Emit("MOVQ" , jit.Ptr(_DI, _Fe_Hash), _R8) // MOVQ FieldEntry.Hash(DI), R8
self.Emit("TESTQ", _R8, _R8) // TESTQ R8, R8
self.Sjmp("JZ" , "_try_lowercase_{n}") // JZ _try_lowercase_{n}
self.Emit("CMPQ" , _R8, _R9) // CMPQ R8, R9
self.Sjmp("JNE" , "_loop_{n}") // JNE _loop_{n}
self.Emit("MOVQ" , jit.Ptr(_DI, _Fe_Name + 8), _DX) // MOVQ FieldEntry.Name+8(DI), DX
self.Emit("CMPQ" , _DX, _VAR_sv_n) // CMPQ DX, sv.n
self.Sjmp("JNE" , "_loop_{n}") // JNE _loop_{n}
self.Emit("MOVQ" , jit.Ptr(_DI, _Fe_ID), _R8) // MOVQ FieldEntry.ID(DI), R8
self.Emit("MOVQ" , _AX, _VAR_ss_AX) // MOVQ AX, ss.AX
self.Emit("MOVQ" , _CX, _VAR_ss_CX) // MOVQ CX, ss.CX
self.Emit("MOVQ" , _SI, _VAR_ss_SI) // MOVQ SI, ss.SI
self.Emit("MOVQ" , _R8, _VAR_ss_R8) // MOVQ R8, ss.R8
self.Emit("MOVQ" , _R9, _VAR_ss_R9) // MOVQ R9, ss.R9
self.Emit("MOVQ" , _VAR_sv_p, _AX) // MOVQ _VAR_sv_p, AX
self.Emit("MOVQ" , jit.Ptr(_DI, _Fe_Name), _CX) // MOVQ FieldEntry.Name(DI), CX
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
self.Emit("MOVQ" , _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
self.Emit("MOVQ" , _DX, jit.Ptr(_SP, 16)) // MOVQ DX, 16(SP)
self.call_go(_F_memequal) // CALL_GO memequal
self.Emit("MOVQ" , _VAR_ss_AX, _AX) // MOVQ ss.AX, AX
self.Emit("MOVQ" , _VAR_ss_CX, _CX) // MOVQ ss.CX, CX
self.Emit("MOVQ" , _VAR_ss_SI, _SI) // MOVQ ss.SI, SI
self.Emit("MOVQ" , _VAR_ss_R9, _R9) // MOVQ ss.R9, R9
self.Emit("MOVB" , jit.Ptr(_SP, 24), _DX) // MOVB 24(SP), DX
self.Emit("TESTB", _DX, _DX) // TESTB DX, DX
self.Sjmp("JZ" , "_loop_{n}") // JZ _loop_{n}
self.Emit("MOVQ" , _VAR_ss_R8, _R8) // MOVQ ss.R8, R8
self.Emit("MOVQ" , _R8, _VAR_sr) // MOVQ R8, sr
self.Sjmp("JMP" , "_end_{n}") // JMP _end_{n}
self.Link("_try_lowercase_{n}") // _try_lowercase_{n}:
self.Emit("MOVQ" , jit.Imm(referenceFields(p.vf())), _AX) // MOVQ ${p.vf()}, AX
self.Emit("MOVOU", _VAR_sv, _X0) // MOVOU sv, X0
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
self.Emit("MOVOU", _X0, jit.Ptr(_SP, 8)) // MOVOU X0, 8(SP)
self.call_go(_F_FieldMap_GetCaseInsensitive) // CALL_GO FieldMap::GetCaseInsensitive
self.Emit("MOVQ" , jit.Ptr(_SP, 24), _AX) // MOVQ 24(SP), AX
self.Emit("MOVQ" , _AX, _VAR_sr) // MOVQ AX, _VAR_sr
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
self.Sjmp("JNS" , "_end_{n}") // JNS _end_{n}
self.Emit("BTQ" , jit.Imm(_F_disable_unknown), _ARG_fv) // BTQ ${_F_disable_unknown}, fv
self.Sjmp("JC" , _LB_field_error) // JC _field_error
self.Link("_end_{n}") // _end_{n}:
}
func (self *_Assembler) _asm_OP_unmarshal(p *_Instr) {
self.unmarshal_json(p.vt(), true)
}
func (self *_Assembler) _asm_OP_unmarshal_p(p *_Instr) {
self.unmarshal_json(p.vt(), false)
}
func (self *_Assembler) _asm_OP_unmarshal_text(p *_Instr) {
self.unmarshal_text(p.vt(), true)
}
func (self *_Assembler) _asm_OP_unmarshal_text_p(p *_Instr) {
self.unmarshal_text(p.vt(), false)
}
func (self *_Assembler) _asm_OP_lspace(_ *_Instr) {
self.lspace("_{n}")
}
func (self *_Assembler) lspace(subfix string) {
var label = "_lspace" + subfix
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
self.Emit("MOVQ" , jit.Imm(_BM_space), _DX) // MOVQ _BM_space, DX
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
self.Sjmp("JA" , label) // JA _nospace_{n}
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
self.Sjmp("JNC" , label) // JNC _nospace_{n}
/* test up to 4 characters */
for i := 0; i < 3; i++ {
self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
self.Sjmp("JA" , label) // JA _nospace_{n}
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
self.Sjmp("JNC" , label) // JNC _nospace_{n}
}
/* handle over to the native function */
self.Emit("MOVQ" , _IP, _DI) // MOVQ IP, DI
self.Emit("MOVQ" , _IL, _SI) // MOVQ IL, SI
self.Emit("MOVQ" , _IC, _DX) // MOVQ IC, DX
self.call(_F_lspace) // CALL lspace
self.Emit("TESTQ" , _AX, _AX) // TESTQ AX, AX
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parsing_error_v
self.Emit("CMPQ" , _AX, _IL) // CMPQ AX, IL
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
self.Emit("MOVQ" , _AX, _IC) // MOVQ AX, IC
self.Link(label) // _nospace_{n}:
}
func (self *_Assembler) _asm_OP_match_char(p *_Instr) {
self.match_char(p.vb())
}
func (self *_Assembler) match_char(char byte) {
self.check_eof(1)
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(char))) // CMPB (IP)(IC), ${p.vb()}
self.Sjmp("JNE" , _LB_char_0_error) // JNE _char_0_error
self.Emit("ADDQ", jit.Imm(1), _IC) // ADDQ $1, IC
}
func (self *_Assembler) _asm_OP_check_char(p *_Instr) {
self.check_eof(1)
self.Emit("LEAQ" , jit.Ptr(_IC, 1), _AX) // LEAQ 1(IC), AX
self.Emit("CMPB" , jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(p.vb()))) // CMPB (IP)(IC), ${p.vb()}
self.Emit("CMOVQEQ", _AX, _IC) // CMOVQEQ AX, IC
self.Xjmp("JE" , p.vi()) // JE {p.vi()}
}
func (self *_Assembler) _asm_OP_check_char_0(p *_Instr) {
self.check_eof(1)
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(p.vb()))) // CMPB (IP)(IC), ${p.vb()}
self.Xjmp("JE" , p.vi()) // JE {p.vi()}
}
func (self *_Assembler) _asm_OP_add(p *_Instr) {
self.Emit("ADDQ", jit.Imm(int64(p.vi())), _IC) // ADDQ ${p.vi()}, IC
}
func (self *_Assembler) _asm_OP_load(_ *_Instr) {
self.Emit("MOVQ", jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
self.Emit("MOVQ", jit.Sib(_ST, _AX, 1, 0), _VP) // MOVQ (ST)(AX), VP
}
func (self *_Assembler) _asm_OP_save(_ *_Instr) {
self.Emit("MOVQ", jit.Ptr(_ST, 0), _CX) // MOVQ (ST), CX
self.Emit("CMPQ", _CX, jit.Imm(_MaxStackBytes)) // CMPQ CX, ${_MaxStackBytes}
self.Sjmp("JAE" , _LB_stack_error) // JA _stack_error
self.WriteRecNotAX(0 , _VP, jit.Sib(_ST, _CX, 1, 8), false, false) // MOVQ VP, 8(ST)(CX)
self.Emit("ADDQ", jit.Imm(8), _CX) // ADDQ $8, CX
self.Emit("MOVQ", _CX, jit.Ptr(_ST, 0)) // MOVQ CX, (ST)
}
func (self *_Assembler) _asm_OP_drop(_ *_Instr) {
self.Emit("MOVQ", jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
self.Emit("SUBQ", jit.Imm(8), _AX) // SUBQ $8, AX
self.Emit("MOVQ", jit.Sib(_ST, _AX, 1, 8), _VP) // MOVQ 8(ST)(AX), VP
self.Emit("MOVQ", _AX, jit.Ptr(_ST, 0)) // MOVQ AX, (ST)
self.Emit("XORL", _ET, _ET) // XORL ET, ET
self.Emit("MOVQ", _ET, jit.Sib(_ST, _AX, 1, 8)) // MOVQ ET, 8(ST)(AX)
}
func (self *_Assembler) _asm_OP_drop_2(_ *_Instr) {
self.Emit("MOVQ" , jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
self.Emit("SUBQ" , jit.Imm(16), _AX) // SUBQ $16, AX
self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 8), _VP) // MOVQ 8(ST)(AX), VP
self.Emit("MOVQ" , _AX, jit.Ptr(_ST, 0)) // MOVQ AX, (ST)
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
self.Emit("MOVOU", _X0, jit.Sib(_ST, _AX, 1, 8)) // MOVOU X0, 8(ST)(AX)
}
func (self *_Assembler) _asm_OP_recurse(p *_Instr) {
self.Emit("MOVQ", jit.Type(p.vt()), _AX) // MOVQ ${p.vt()}, AX
self.decode_dynamic(_AX, _VP) // DECODE AX, VP
}
func (self *_Assembler) _asm_OP_goto(p *_Instr) {
self.Xjmp("JMP", p.vi())
}
func (self *_Assembler) _asm_OP_switch(p *_Instr) {
self.Emit("MOVQ", _VAR_sr, _AX) // MOVQ sr, AX
self.Emit("CMPQ", _AX, jit.Imm(p.i64())) // CMPQ AX, ${len(p.vs())}
self.Sjmp("JAE" , "_default_{n}") // JAE _default_{n}
/* jump table selector */
self.Byte(0x48, 0x8d, 0x3d) // LEAQ ?(PC), DI
self.Sref("_switch_table_{n}", 4) // .... &_switch_table_{n}
self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, 0), _AX) // MOVLQSX (DI)(AX*4), AX
self.Emit("ADDQ" , _DI, _AX) // ADDQ DI, AX
self.Rjmp("JMP" , _AX) // JMP AX
self.Link("_switch_table_{n}") // _switch_table_{n}:
/* generate the jump table */
for i, v := range p.vs() {
self.Xref(v, int64(-i) * 4)
}
/* default case */
self.Link("_default_{n}")
self.NOP()
}
func (self *_Assembler) print_gc(i int, p1 *_Instr, p2 *_Instr) {
self.Emit("MOVQ", jit.Imm(int64(p2.op())), jit.Ptr(_SP, 16))// MOVQ $(p2.op()), 16(SP)
self.Emit("MOVQ", jit.Imm(int64(p1.op())), jit.Ptr(_SP, 8)) // MOVQ $(p1.op()), 8(SP)
self.Emit("MOVQ", jit.Imm(int64(i)), jit.Ptr(_SP, 0)) // MOVQ $(i), (SP)
self.call_go(_F_println)
}
var _runtime_writeBarrier uintptr = rt.GcwbAddr()
//go:linkname gcWriteBarrierAX runtime.gcWriteBarrier
func gcWriteBarrierAX()
var (
_V_writeBarrier = jit.Imm(int64(_runtime_writeBarrier))
_F_gcWriteBarrierAX = jit.Func(gcWriteBarrierAX)
)
func (self *_Assembler) WritePtrAX(i int, rec obj.Addr, saveDI bool) {
self.Emit("MOVQ", _V_writeBarrier, _R10)
self.Emit("CMPL", jit.Ptr(_R10, 0), jit.Imm(0))
self.Sjmp("JE", "_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
if saveDI {
self.save(_DI)
}
self.Emit("LEAQ", rec, _DI)
self.Emit("MOVQ", _F_gcWriteBarrierAX, _R10) // MOVQ ${fn}, AX
self.Rjmp("CALL", _R10)
if saveDI {
self.load(_DI)
}
self.Sjmp("JMP", "_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
self.Emit("MOVQ", _AX, rec)
self.Link("_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
}
func (self *_Assembler) WriteRecNotAX(i int, ptr obj.Addr, rec obj.Addr, saveDI bool, saveAX bool) {
if rec.Reg == x86.REG_AX || rec.Index == x86.REG_AX {
panic("rec contains AX!")
}
self.Emit("MOVQ", _V_writeBarrier, _R10)
self.Emit("CMPL", jit.Ptr(_R10, 0), jit.Imm(0))
self.Sjmp("JE", "_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
if saveAX {
self.Emit("XCHGQ", ptr, _AX)
} else {
self.Emit("MOVQ", ptr, _AX)
}
if saveDI {
self.save(_DI)
}
self.Emit("LEAQ", rec, _DI)
self.Emit("MOVQ", _F_gcWriteBarrierAX, _R10) // MOVQ ${fn}, AX
self.Rjmp("CALL", _R10)
if saveDI {
self.load(_DI)
}
if saveAX {
self.Emit("XCHGQ", ptr, _AX)
}
self.Sjmp("JMP", "_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
self.Link("_no_writeBarrier" + strconv.Itoa(i) + "_{n}")
self.Emit("MOVQ", ptr, rec)
self.Link("_end_writeBarrier" + strconv.Itoa(i) + "_{n}")
}