summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/jit/x86/generators.tab
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/jit/x86/generators.tab')
-rw-r--r--erts/emulator/beam/jit/x86/generators.tab175
1 files changed, 98 insertions, 77 deletions
diff --git a/erts/emulator/beam/jit/x86/generators.tab b/erts/emulator/beam/jit/x86/generators.tab
index 4b0b2ad043..007344d17d 100644
--- a/erts/emulator/beam/jit/x86/generators.tab
+++ b/erts/emulator/beam/jit/x86/generators.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2020-2022. All Rights Reserved.
+// Copyright Ericsson AB 2020-2023. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,60 +19,6 @@
// %CopyrightEnd%
//
-// Generate the fastest instruction to fetch an integer from a binary.
-gen.get_integer2(Fail, Ms, Live, Size, Unit, Flags, Dst) {
- BeamOp* op;
- UWord bits;
-
- $NewBeamOp(S, op);
- $NativeEndian(Flags);
- if (Size.type == TAG_i) {
- if (!beam_load_safe_mul(Size.val, Unit.val, &bits)) {
- $BeamOpNameArity(op, jump, 1);
- op->a[0] = Fail;
- } else if (bits == 8) {
- $BeamOpNameArity(op, i_bs_get_integer_8, 4);
- op->a[0] = Ms;
- op->a[1] = Flags;
- op->a[2] = Fail;
- op->a[3] = Dst;
- } else if (bits == 16) {
- $BeamOpNameArity(op, i_bs_get_integer_16, 4);
- op->a[0] = Ms;
- op->a[1] = Flags;
- op->a[2] = Fail;
- op->a[3] = Dst;
- } else if (bits == 32) {
- $BeamOpNameArity(op, i_bs_get_integer_32, 4);
- op->a[0] = Ms;
- op->a[1] = Flags;
- op->a[2] = Fail;
- op->a[3] = Dst;
- } else if (bits == 64) {
- $BeamOpNameArity(op, i_bs_get_integer_64, 5);
- op->a[0] = Ms;
- op->a[1] = Flags;
- op->a[2] = Fail;
- op->a[3] = Live;
- op->a[4] = Dst;
- } else {
- goto generic;
- }
- } else {
- generic:
- $BeamOpNameArity(op, i_bs_get_integer, 6);
- op->a[0] = Ms;
- op->a[1] = Fail;
- op->a[2] = Live;
- op->a[3].type = TAG_u;
- op->a[3].val = (Unit.val << 3) | Flags.val;
- op->a[4] = Size;
- op->a[5] = Dst;
- return op;
- }
- return op;
-}
-
gen.select_tuple_arity(Src, Fail, Size, Rest) {
BeamOp* op;
BeamOpArg *tmp;
@@ -413,7 +359,7 @@ gen.new_small_map_lit(Dst, Live, Size, Rest) {
*dst++ = Rest[i + 1];
}
- lit = beamfile_add_literal(&S->beam, keys);
+ lit = beamfile_add_literal(&S->beam, keys, 1);
erts_free(ERTS_ALC_T_LOADER_TMP, tmp);
op->a[0] = Dst;
@@ -487,27 +433,6 @@ gen.combine_conses(Len, Dst, Hd) {
return cons;
}
-gen.is_eq_exact_literal(Fail, R, C) {
- BeamOp* op;
- Eterm literal;
- Uint tag_test;
-
- ASSERT(C.type == TAG_q);
- literal = beamfile_get_literal(&S->beam, C.val);
- ASSERT(is_boxed(literal) || is_list(literal));
- tag_test = _TAG_PRIMARY_MASK - (literal & _TAG_PRIMARY_MASK);
-
- $NewBeamOp(S, op);
- $BeamOpNameArity(op, i_is_eq_exact_literal, 4);
- op->a[0] = Fail;
- op->a[1] = R;
- op->a[2] = C;
- op->a[3].type = TAG_u;
- op->a[3].val = tag_test;
-
- return op;
-}
-
gen.allocate_heap_zero(Ns, Nh, Live) {
BeamOp* alloc;
BeamOp* init;
@@ -635,6 +560,28 @@ gen.create_bin(Fail, Alloc, Live, Unit, Dst, N, Segments) {
Flags.val = flags;
$NativeEndian(Flags);
op->a[i+fixed_args+3] = Flags;
+
+ /*
+ * Replace short string segments with integer segments.
+ * Integer segments can be combined with adjacent integer
+ * segments for better performance.
+ */
+ if (op->a[i+fixed_args+0].val == am_string) {
+ Sint num_chars = op->a[i+fixed_args+5].val;
+ if (num_chars <= 4) {
+ Sint index = op->a[i+fixed_args+4].val;
+ const byte* s = S->beam.strings.data + index;
+ Uint num = 0;
+ op->a[i+fixed_args+0].val = am_integer;
+ op->a[i+fixed_args+2].val = 8;
+ op->a[i+fixed_args+5].val = num_chars;
+ while (num_chars-- > 0) {
+ num = num << 8 | *s++;
+ }
+ op->a[i+fixed_args+4].type = TAG_i;
+ op->a[i+fixed_args+4].val = num;
+ }
+ }
}
if (op->a[4].val == am_private_append && Alloc.val != 0) {
@@ -652,3 +599,77 @@ gen.create_bin(Fail, Alloc, Live, Unit, Dst, N, Segments) {
return op;
}
+
+gen.bs_match(Fail, Ctx, N, List) {
+ BeamOp* op;
+ int fixed_args;
+ int i;
+
+ /*
+ * If a BEAM file produced by a later version of Erlang/OTP
+ * is accidentally loaded into an earlier version, ensure
+ * that the loading fails (as opposed to crashing the runtime)
+ * if there are any unknown sub commands.
+ */
+ i = 0;
+ while (i < N.val) {
+ BeamOpArg current = List[i++];
+
+ if (current.type != TAG_a) {
+ goto error;
+ }
+
+ switch (current.val) {
+ case am_ensure_exactly:
+ case am_skip:
+ i += 1;
+ break;
+ case am_ensure_at_least:
+ i += 2;
+ break;
+ case am_get_tail:
+ case am_Eq:
+ i += 3;
+ break;
+ case am_binary:
+ case am_integer:
+ i += 5;
+ break;
+ default: {
+ error:
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, bad_bs_match, 1);
+ op->a[0] = current;
+ return op;
+ }
+ }
+ }
+
+ /*
+ * Make sure that we don't attempt to pass any overflow tags to the JIT.
+ */
+
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, i_bs_match, 2);
+ fixed_args = op->arity;
+ $BeamOpArity(op, (N.val + fixed_args));
+
+ op->a[0] = Fail;
+ op->a[1] = Ctx;
+
+ for (i = 0; i < N.val; i++) {
+ BeamOpArg current;
+
+ current = List[i];
+ if (current.type == TAG_o) {
+ /* An overflow tag (in ensure_at_least or ensure_exactly)
+ * means that the match will always fail. */
+ $BeamOpNameArity(op, jump, 1);
+ op->a[0] = Fail;
+ return op;
+ }
+ op->a[i+fixed_args] = current;
+ }
+
+ return op;
+}