mirror of
https://github.com/ii64/sonic.git
synced 2026-06-21 00:46:43 +08:00
419 lines
8.7 KiB
ArmAsm
419 lines
8.7 KiB
ArmAsm
//
|
||
// 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.
|
||
//
|
||
|
||
#include "go_asm.h"
|
||
#include "funcdata.h"
|
||
#include "textflag.h"
|
||
|
||
// Register Allocations:
|
||
// AX result index (if any), or negative for errors
|
||
// R9 result value (slice array pointer or map pointer)
|
||
// R12 parameter string buffer
|
||
// R13 parameter string length
|
||
// R14 parameter index
|
||
// R15 decoder flags
|
||
|
||
#define ST BX
|
||
#define RT R8
|
||
#define RV R9
|
||
#define RE R11
|
||
#define PS R12
|
||
#define PN R13
|
||
#define PI R14
|
||
#define FL R15
|
||
|
||
#define ERR_EOF $-1
|
||
#define ERR_INVALID_CHAR $-2
|
||
|
||
#define lspace(to) \
|
||
MOVQ PS, DI \
|
||
MOVQ PN, SI \
|
||
MOVQ PI, DX \
|
||
MOVQ github·com∕bytedance∕sonic∕internal∕native·S_lspace(SB), AX \
|
||
CALL AX \
|
||
MOVQ AX, PI \
|
||
TESTQ AX, AX \
|
||
JNS to \
|
||
RET \
|
||
to:
|
||
|
||
#define match_eof(to) \
|
||
MOVQ ERR_EOF, AX \
|
||
CMPQ PI, PN \
|
||
JBE to \
|
||
MOVQ PN, PI \
|
||
RET \
|
||
to:
|
||
|
||
#define match_empty(to, ch) \
|
||
CMPB (PS)(PI*1), ch \
|
||
JNE to \
|
||
XORQ AX, AX \
|
||
XORQ RV, RV \
|
||
ADDQ $1, PI \
|
||
RET \
|
||
to:
|
||
|
||
#define match_delim(done, next, ch) \
|
||
MOVBLZX (PS)(PI*1), AX \
|
||
ADDQ $1, PI \
|
||
CMPL AX, ch \
|
||
JE done \
|
||
CMPL AX, $',' \
|
||
JE next \
|
||
MOVQ ERR_INVALID_CHAR, AX \
|
||
SUBQ $1, PI \
|
||
RET \
|
||
done:
|
||
|
||
#define check_char(to, ch) \
|
||
MOVBLZX (PS)(PI*1), CX \
|
||
ADDQ $1, PI \
|
||
MOVQ ERR_INVALID_CHAR, AX \
|
||
CMPL CX, ch \
|
||
JE to \
|
||
SUBQ $1, PI \
|
||
RET \
|
||
to:
|
||
|
||
#define check_empty(to, ch) \
|
||
match_eof(_check_empty) \
|
||
match_empty(to, ch)
|
||
|
||
#define check_delim(done, next, ch) \
|
||
match_eof(_check_delim) \
|
||
match_delim(done, next, ch) \
|
||
|
||
// Generic Array Decoder
|
||
|
||
#define ARR_st fl-80(SP)
|
||
#define ARR_fl fl-72(SP)
|
||
#define ARR_ps ps-64(SP)
|
||
#define ARR_pn ps-56(SP)
|
||
#define ARR_pi pi-48(SP)
|
||
#define ARR_sp sp-40(SP)
|
||
#define ARR_sl sl-32(SP)
|
||
#define ARR_sc sc-24(SP)
|
||
#define ARR_rt sl-16(SP)
|
||
#define ARR_rv sc-8(SP)
|
||
|
||
TEXT ·decodeArray(SB), NOSPLIT, $144 - 8
|
||
NO_LOCAL_POINTERS
|
||
lspace(_check_array_empty)
|
||
check_empty(_make_slice, $']')
|
||
|
||
// set slice initial capacity to 16
|
||
XORQ CX, CX
|
||
MOVL $16, DX
|
||
MOVQ CX, ARR_sl
|
||
MOVQ DX, ARR_sc
|
||
|
||
// allocate memory for slice
|
||
MOVQ ST, ARR_st
|
||
MOVQ FL, ARR_fl
|
||
MOVQ PS, ARR_ps
|
||
MOVQ PN, ARR_pn
|
||
MOVQ PI, ARR_pi
|
||
MOVQ ·_type_eface(SB), AX
|
||
MOVQ AX, (SP)
|
||
MOVQ CX, 8(SP)
|
||
MOVQ DX, 16(SP)
|
||
CALL runtime·makeslice(SB)
|
||
MOVQ 24(SP), AX
|
||
MOVQ AX, ARR_sp
|
||
MOVQ AX, ret+0(FP)
|
||
MOVQ ARR_st, ST
|
||
MOVQ ARR_fl, FL
|
||
MOVQ ARR_ps, PS
|
||
MOVQ ARR_pn, PN
|
||
MOVQ ARR_pi, PI
|
||
GO_RESULTS_INITIALIZED
|
||
|
||
_parse_loop:
|
||
MOVQ ·_subr_decode_value(SB), AX
|
||
CALL AX
|
||
TESTQ RE, RE
|
||
JNZ _parsing_error
|
||
|
||
// check for slice space
|
||
MOVQ ARR_sp, DI
|
||
MOVQ ARR_sl, CX
|
||
CMPQ CX, ARR_sc
|
||
JAE _more_space
|
||
|
||
_append_slice:
|
||
LEAQ (DI)(CX*8), DI
|
||
LEAQ (DI)(CX*8), DI
|
||
MOVQ RT, (DI)
|
||
MOVQ RV, 8(DI)
|
||
ADDQ $1, CX
|
||
MOVQ CX, ARR_sl
|
||
|
||
// check for the delimiter
|
||
lspace(_check_array_delim)
|
||
check_delim(_done, _parse_loop, $']')
|
||
|
||
// set the result register and length
|
||
MOVQ ARR_sp, RV
|
||
MOVQ ARR_sl, AX
|
||
RET
|
||
|
||
_parsing_error:
|
||
MOVQ RE, AX
|
||
NEGQ AX
|
||
RET
|
||
|
||
_more_space:
|
||
MOVQ ST, ARR_st
|
||
MOVQ FL, ARR_fl
|
||
MOVQ PS, ARR_ps
|
||
MOVQ PN, ARR_pn
|
||
MOVQ PI, ARR_pi
|
||
MOVQ RT, ARR_rt
|
||
MOVQ RV, ARR_rv
|
||
MOVQ ARR_sc, DX
|
||
MOVQ ·_type_eface(SB), AX
|
||
MOVQ AX, (SP)
|
||
MOVQ DI, 8(SP)
|
||
MOVQ CX, 16(SP)
|
||
MOVQ DX, 24(SP)
|
||
SHLQ $1, DX
|
||
MOVQ DX, 32(SP)
|
||
CALL runtime·growslice(SB)
|
||
MOVQ 40(SP), DI
|
||
MOVQ 48(SP), CX
|
||
MOVQ 56(SP), DX
|
||
MOVQ DI, ARR_sp
|
||
MOVQ CX, ARR_sl
|
||
MOVQ DX, ARR_sc
|
||
MOVQ ARR_st, ST
|
||
MOVQ ARR_fl, FL
|
||
MOVQ ARR_ps, PS
|
||
MOVQ ARR_pn, PN
|
||
MOVQ ARR_pi, PI
|
||
MOVQ ARR_rt, RT
|
||
MOVQ ARR_rv, RV
|
||
JMP _append_slice
|
||
|
||
// Generic Object Decoder
|
||
|
||
#define OBJ_ss OBJ_ss_Sp
|
||
#define OBJ_ss_Sp ss_Sp-72(SP)
|
||
#define OBJ_ss_Sn ss_Sn-64(SP)
|
||
|
||
#define OBJ_st ps-56(SP)
|
||
#define OBJ_fl ps-48(SP)
|
||
#define OBJ_ps ps-40(SP)
|
||
#define OBJ_pn ps-32(SP)
|
||
#define OBJ_pi pi-24(SP)
|
||
#define OBJ_vp vp-16(SP)
|
||
#define OBJ_mp mp-8(SP)
|
||
|
||
TEXT ·decodeObject(SB), NOSPLIT, $104 - 8
|
||
NO_LOCAL_POINTERS
|
||
lspace(_check_object_empty)
|
||
check_empty(_make_map, $'}')
|
||
|
||
// create the result map
|
||
MOVQ ST, OBJ_st
|
||
MOVQ FL, OBJ_fl
|
||
MOVQ PS, OBJ_ps
|
||
MOVQ PN, OBJ_pn
|
||
MOVQ PI, OBJ_pi
|
||
CALL runtime·makemap_small(SB)
|
||
MOVQ (SP), AX
|
||
MOVQ AX, OBJ_mp
|
||
MOVQ AX, ret+0(FP)
|
||
MOVQ OBJ_st, ST
|
||
MOVQ OBJ_fl, FL
|
||
MOVQ OBJ_ps, PS
|
||
MOVQ OBJ_pn, PN
|
||
MOVQ OBJ_pi, PI
|
||
GO_RESULTS_INITIALIZED
|
||
|
||
_parse_loop:
|
||
CALL decodeObjectKey(SB)
|
||
MOVQ DI, OBJ_ss_Sp
|
||
MOVQ SI, OBJ_ss_Sn
|
||
TESTQ AX, AX
|
||
JNS _value_delim
|
||
RET
|
||
|
||
_value_delim:
|
||
lspace(_check_value_delim)
|
||
check_char(_parse_value, $':')
|
||
|
||
// allocate a new slot in the map
|
||
MOVQ ST, OBJ_st
|
||
MOVQ FL, OBJ_fl
|
||
MOVQ PS, OBJ_ps
|
||
MOVQ PN, OBJ_pn
|
||
MOVQ PI, OBJ_pi
|
||
MOVQ ·_type_strmap(SB), AX
|
||
MOVQ OBJ_mp, CX
|
||
MOVOU OBJ_ss, X0
|
||
MOVQ AX, (SP)
|
||
MOVQ CX, 8(SP)
|
||
MOVOU X0, 16(SP)
|
||
CALL runtime·mapassign_faststr(SB)
|
||
MOVQ 32(SP), AX
|
||
MOVQ AX, OBJ_vp
|
||
MOVQ OBJ_st, ST
|
||
MOVQ OBJ_fl, FL
|
||
MOVQ OBJ_ps, PS
|
||
MOVQ OBJ_pn, PN
|
||
MOVQ OBJ_pi, PI
|
||
|
||
// decode the value
|
||
MOVQ ·_subr_decode_value(SB), AX
|
||
CALL AX
|
||
TESTQ RE, RE
|
||
JNZ _value_error
|
||
|
||
// set the map value
|
||
MOVQ OBJ_vp, AX
|
||
MOVQ RT, (AX)
|
||
MOVQ RV, 8(AX)
|
||
|
||
// check for the delimiter
|
||
lspace(_check_object_delim)
|
||
check_delim(_done, _parse_loop, $'}')
|
||
|
||
// set the result register and clear the errors
|
||
XORQ AX, AX
|
||
MOVQ OBJ_mp, RV
|
||
RET
|
||
|
||
_value_error:
|
||
MOVQ RE, AX
|
||
NEGQ AX
|
||
RET
|
||
|
||
// Object Key Parsing Helper
|
||
|
||
#define V_STRING $7
|
||
#define F_DISABLE_URC $2
|
||
#define B_UNICODE_REPLACE $1
|
||
|
||
#define VAR_in VAR_in_PS
|
||
#define VAR_in_ST in_PS-88(SP)
|
||
#define VAR_in_FL in_PS-80(SP)
|
||
#define VAR_in_PS in_PS-72(SP)
|
||
#define VAR_in_PN in_PN-64(SP)
|
||
#define VAR_in_PI in_PI-56(SP)
|
||
|
||
#define VAR_ss VAR_ss_Sp
|
||
#define VAR_ss_Sp ss_Sp-48(SP)
|
||
#define VAR_ss_Sn ss_Sp-40(SP)
|
||
|
||
#define VAR_vv VAR_vv_Vt
|
||
#define VAR_vv_Vt vv_Vt-32(SP)
|
||
#define VAR_vv_Dv vv_Dv-24(SP)
|
||
#define VAR_vv_Iv vv_Iv-16(SP)
|
||
#define VAR_vv_Ep vv_Ep-8(SP)
|
||
|
||
TEXT decodeObjectKey(SB), NOSPLIT, $120 - 0
|
||
NO_LOCAL_POINTERS
|
||
lspace(_parse_key_begin)
|
||
check_char(_parse_key_body, $'"')
|
||
|
||
// parse the string
|
||
MOVQ PS, VAR_in_PS
|
||
MOVQ PN, VAR_in_PN
|
||
MOVQ PI, VAR_in_PI
|
||
LEAQ VAR_in, DI
|
||
LEAQ VAR_in_PI, SI
|
||
LEAQ VAR_vv, DX
|
||
MOVQ github·com∕bytedance∕sonic∕internal∕native·S_vstring(SB), AX
|
||
CALL AX
|
||
MOVQ VAR_in_PI, PI
|
||
|
||
// check for errors
|
||
MOVQ VAR_vv_Vt, AX
|
||
TESTQ AX, AX
|
||
JNS _check_quote
|
||
RET
|
||
|
||
_check_quote:
|
||
CMPQ AX, V_STRING
|
||
JNE _invalid_type
|
||
|
||
// extract the string
|
||
MOVQ VAR_vv_Iv, CX
|
||
MOVQ PS, DI
|
||
MOVQ PI, SI
|
||
ADDQ CX, DI
|
||
SUBQ CX, SI
|
||
SUBQ $1, SI
|
||
|
||
// check for quotes
|
||
CMPQ VAR_vv_Ep, $-1
|
||
JNE _unquote
|
||
MOVQ SI, AX
|
||
RET
|
||
|
||
_unquote:
|
||
XORQ AX, AX
|
||
MOVQ ST, VAR_in_ST
|
||
MOVQ FL, VAR_in_FL
|
||
MOVQ PS, VAR_in_PS
|
||
MOVQ PN, VAR_in_PN
|
||
MOVQ PI, VAR_in_PI
|
||
MOVQ ·_type_byte(SB), CX
|
||
MOVQ DI, VAR_ss_Sp
|
||
MOVQ SI, VAR_ss_Sn
|
||
|
||
// allocate space for unquoted string
|
||
MOVQ SI, (SP)
|
||
MOVQ CX, 8(SP)
|
||
MOVQ AX, 16(SP)
|
||
CALL runtime·mallocgc(SB)
|
||
MOVQ 24(SP), DX
|
||
MOVQ VAR_in_ST, ST
|
||
MOVQ VAR_in_FL, FL
|
||
MOVQ VAR_in_PS, PS
|
||
MOVQ VAR_in_PN, PN
|
||
MOVQ VAR_in_PI, PI
|
||
|
||
// unquote the string
|
||
MOVQ VAR_ss_Sp, DI
|
||
MOVQ VAR_ss_Sn, SI
|
||
MOVQ DX, VAR_ss_Sp
|
||
LEAQ VAR_vv_Ep, CX
|
||
XORQ R8, R8
|
||
BTQ F_DISABLE_URC, FL
|
||
SETCC R8
|
||
SHLQ B_UNICODE_REPLACE, R8
|
||
MOVQ github·com∕bytedance∕sonic∕internal∕native·S_unquote(SB), AX
|
||
CALL AX
|
||
TESTQ AX, AX
|
||
JS _escape_error
|
||
MOVQ AX, SI
|
||
MOVQ VAR_ss_Sp, DI
|
||
RET
|
||
|
||
_escape_error:
|
||
MOVQ VAR_ss_Sn, CX
|
||
SUBQ VAR_vv_Ep, CX
|
||
SUBQ CX, PI
|
||
SUBQ $1, PI
|
||
RET
|
||
|
||
_invalid_type:
|
||
MOVQ AX, (SP)
|
||
CALL ·throw_invalid_type(SB)
|
||
BYTE $0xcc
|
||
WORD $0xfdeb
|