summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/jit/arm/generators.tab
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/jit/arm/generators.tab')
-rw-r--r--erts/emulator/beam/jit/arm/generators.tab141
1 files changed, 98 insertions, 43 deletions
diff --git a/erts/emulator/beam/jit/arm/generators.tab b/erts/emulator/beam/jit/arm/generators.tab
index b6ec48c678..2ae1582d4b 100644
--- a/erts/emulator/beam/jit/arm/generators.tab
+++ b/erts/emulator/beam/jit/arm/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,47 +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;
-
- return op;
- } else if (bits <= 1023) {
- $BeamOpNameArity(op, i_bs_get_fixed_integer, 6);
- op->a[0] = Ms;
- op->a[1] = Fail;
- op->a[2] = Live;
- op->a[3].type = TAG_u;
- op->a[3].val = Flags.val;
- op->a[4].type = TAG_u;
- op->a[4].val = bits;
- op->a[5] = Dst;
-
- return op;
- }
- }
-
- $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;
-}
-
gen.select_tuple_arity(Src, Fail, Size, Rest) {
BeamOp* op;
BeamOpArg *tmp;
@@ -330,7 +289,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;
@@ -567,6 +526,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) {
@@ -584,3 +565,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;
+}