diff options
Diffstat (limited to 'erts/emulator/beam/erl_bits.h')
-rw-r--r-- | erts/emulator/beam/erl_bits.h | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/erts/emulator/beam/erl_bits.h b/erts/emulator/beam/erl_bits.h new file mode 100644 index 0000000000..e3f8e0b679 --- /dev/null +++ b/erts/emulator/beam/erl_bits.h @@ -0,0 +1,212 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1999-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifndef __ERL_BITS_H__ +#define __ERL_BITS_H__ + +/* + * This structure represents a binary to be matched. + */ + +typedef struct erl_bin_match_buffer { + Eterm orig; /* Original binary term. */ + byte* base; /* Current position in binary. */ + Uint offset; /* Offset in bits. */ + size_t size; /* Size of binary in bits. */ +} ErlBinMatchBuffer; + +struct erl_bits_state { + /* + * Used for building binaries. + */ + byte *byte_buf_; + int byte_buf_len_; + /* + * Used for building binaries using the new instruction set. + */ + byte* erts_current_bin_; /* Pointer to beginning of current binary. */ + /* + * Offset in bits into the current binary (new instruction set) or + * buffer (old instruction set). + */ + Uint erts_bin_offset_; + /* + * Whether the current binary is writable. + */ + unsigned erts_writable_bin_; +}; + +typedef struct erl_bin_match_struct{ + Eterm thing_word; + ErlBinMatchBuffer mb; /* Present match buffer */ + Eterm save_offset[1]; /* Saved offsets */ +} ErlBinMatchState; + +#define ERL_BIN_MATCHSTATE_SIZE(_Max) ((sizeof(ErlBinMatchState) + (_Max)*sizeof(Eterm))/sizeof(Eterm)) +#define HEADER_BIN_MATCHSTATE(_Max) _make_header(ERL_BIN_MATCHSTATE_SIZE((_Max))-1, _TAG_HEADER_BIN_MATCHSTATE) +#define HEADER_NUM_SLOTS(hdr) (header_arity(hdr)-sizeof(ErlBinMatchState)/sizeof(Eterm)+1) + +#define make_matchstate(_Ms) make_boxed((Eterm*)(_Ms)) +#define ms_matchbuffer(_Ms) &(((ErlBinMatchState*)(_Ms - TAG_PRIMARY_BOXED))->mb) + + +#if defined(ERTS_SMP) +#define ERL_BITS_REENTRANT +#else +/* uncomment to test the reentrant API in the non-SMP runtime system */ +/* #define ERL_BITS_REENTRANT */ +#endif + +#ifdef ERL_BITS_REENTRANT + +/* + * Reentrant API with the state passed as a parameter. + * (Except when the current Process* already is a parameter.) + */ +#ifdef ERTS_SMP +/* the state resides in the current process' scheduler data */ +#define ERL_BITS_DECLARE_STATEP struct erl_bits_state *EBS +#define ERL_BITS_RELOAD_STATEP(P) do{EBS = &(P)->scheduler_data->erl_bits_state;}while(0) +#define ERL_BITS_DEFINE_STATEP(P) struct erl_bits_state *EBS = &(P)->scheduler_data->erl_bits_state +#else +/* reentrant API but with a hidden single global state, for testing only */ +extern struct erl_bits_state ErlBitsState_; +#define ERL_BITS_DECLARE_STATEP struct erl_bits_state *EBS = &ErlBitsState_ +#define ERL_BITS_RELOAD_STATEP(P) do{}while(0) +#define ERL_BITS_DEFINE_STATEP(P) ERL_BITS_DECLARE_STATEP +#endif +#define ErlBitsState (*EBS) + +#define ERL_BITS_PROTO_0 struct erl_bits_state *EBS +#define ERL_BITS_PROTO_1(PARM1) struct erl_bits_state *EBS, PARM1 +#define ERL_BITS_PROTO_2(PARM1,PARM2) struct erl_bits_state *EBS, PARM1, PARM2 +#define ERL_BITS_PROTO_3(PARM1,PARM2,PARM3) struct erl_bits_state *EBS, PARM1, PARM2, PARM3 +#define ERL_BITS_ARGS_0 EBS +#define ERL_BITS_ARGS_1(ARG1) EBS, ARG1 +#define ERL_BITS_ARGS_2(ARG1,ARG2) EBS, ARG1, ARG2 +#define ERL_BITS_ARGS_3(ARG1,ARG2,ARG3) EBS, ARG1, ARG2, ARG3 + +#else /* ERL_BITS_REENTRANT */ + +/* + * Non-reentrant API with a single global state. + */ +extern struct erl_bits_state ErlBitsState; +#define ERL_BITS_DECLARE_STATEP /*empty*/ +#define ERL_BITS_RELOAD_STATEP(P) do{}while(0) +#define ERL_BITS_DEFINE_STATEP(P) /*empty*/ + +#define ERL_BITS_PROTO_0 void +#define ERL_BITS_PROTO_1(PARM1) PARM1 +#define ERL_BITS_PROTO_2(PARM1,PARM2) PARM1, PARM2 +#define ERL_BITS_PROTO_3(PARM1,PARM2,PARM3) PARM1, PARM2, PARM3 +#define ERL_BITS_ARGS_0 /*empty*/ +#define ERL_BITS_ARGS_1(ARG1) ARG1 +#define ERL_BITS_ARGS_2(ARG1,ARG2) ARG1, ARG2 +#define ERL_BITS_ARGS_3(ARG1,ARG2,ARG3) ARG1, ARG2, ARG3 + +#endif /* ERL_BITS_REENTRANT */ + +#define erts_bin_offset (ErlBitsState.erts_bin_offset_) +#define erts_current_bin (ErlBitsState.erts_current_bin_) +#define erts_writable_bin (ErlBitsState.erts_writable_bin_) + +#define copy_binary_to_buffer(DstBuffer, DstBufOffset, SrcBuffer, SrcBufferOffset, NumBits) \ + do { \ + if (BIT_OFFSET(DstBufOffset) == 0 && (SrcBufferOffset == 0) && \ + (BIT_OFFSET(NumBits)==0)) { \ + sys_memcpy(DstBuffer+BYTE_OFFSET(DstBufOffset), \ + SrcBuffer, NBYTES(NumBits)); \ + } else { \ + erts_copy_bits(SrcBuffer, SrcBufferOffset, 1, \ + (byte*)DstBuffer, DstBufOffset, 1, NumBits); \ + } \ + } while (0) + +void erts_init_bits(void); /* Initialization once. */ +#ifdef ERTS_SMP +void erts_bits_init_state(ERL_BITS_PROTO_0); +void erts_bits_destroy_state(ERL_BITS_PROTO_0); +#endif + + +/* + * NBYTES(x) returns the number of bytes needed to store x bits. + */ + +#define NBYTES(x) (((x) + 7) >> 3) +#define BYTE_OFFSET(ofs) ((Uint) (ofs) >> 3) +#define BIT_OFFSET(ofs) ((ofs) & 7) + +/* + * Return number of Eterm words needed for allocation with HAlloc(), + * given a number of bytes. + */ +#define WSIZE(n) ((n + sizeof(Eterm) - 1) / sizeof(Eterm)) + +/* + * Binary matching. + */ + +Eterm erts_bs_start_match_2(Process *p, Eterm Bin, Uint Max); +Eterm erts_bs_get_integer_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb); +Eterm erts_bs_get_binary_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb); +Eterm erts_bs_get_float_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb); +Eterm erts_bs_get_binary_all_2(Process *p, ErlBinMatchBuffer* mb); + +/* + * Binary construction, new instruction set. + */ + +int erts_new_bs_put_integer(ERL_BITS_PROTO_3(Eterm Integer, Uint num_bits, unsigned flags)); +int erts_bs_put_utf8(ERL_BITS_PROTO_1(Eterm Integer)); +int erts_bs_put_utf16(ERL_BITS_PROTO_2(Eterm Integer, Uint flags)); +int erts_new_bs_put_binary(ERL_BITS_PROTO_2(Eterm Bin, Uint num_bits)); +int erts_new_bs_put_binary_all(ERL_BITS_PROTO_2(Eterm Bin, Uint unit)); +int erts_new_bs_put_float(Process *c_p, Eterm Float, Uint num_bits, int flags); +void erts_new_bs_put_string(ERL_BITS_PROTO_2(byte* iptr, Uint num_bytes)); + +Uint erts_bits_bufs_size(void); +Uint32 erts_bs_get_unaligned_uint32(ErlBinMatchBuffer* mb); +void erts_align_utf8_bytes(ErlBinMatchBuffer* mb, byte* buf); +Eterm erts_bs_get_utf8(ErlBinMatchBuffer* mb); +Eterm erts_bs_get_utf16(ErlBinMatchBuffer* mb, Uint flags); +Eterm erts_bs_append(Process* p, Eterm* reg, Uint live, Eterm build_size_term, + Uint extra_words, Uint unit); +Eterm erts_bs_private_append(Process* p, Eterm bin, Eterm sz, Uint unit); +Eterm erts_bs_init_writable(Process* p, Eterm sz); + +/* + * Common utilities. + */ +void erts_copy_bits(byte* src, size_t soffs, int sdir, + byte* dst, size_t doffs,int ddir, size_t n); +int erts_cmp_bits(byte* a_ptr, size_t a_offs, byte* b_ptr, size_t b_offs, size_t size); + +/* + * Flags for bs_get_* / bs_put_* / bs_init* instructions. + */ + +#define BSF_ALIGNED 1 /* Field is guaranteed to be byte-aligned. */ +#define BSF_LITTLE 2 /* Field is little-endian (otherwise big-endian). */ +#define BSF_SIGNED 4 /* Field is signed (otherwise unsigned). */ +#define BSF_EXACT 8 /* Size in bs_init is exact. */ +#define BSF_NATIVE 16 /* Native endian. */ + +#endif /* __ERL_BITS_H__ */ |