File 1181-Simplify-range-check-for-element-2-on-a-known-litera.patch of Package erlang
From 8faccec0379e4e40177985cc853c3ae4b1af7314 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Mon, 26 Aug 2024 07:36:33 +0200
Subject: [PATCH] Simplify range check for element/2 on a known literal tuple
This will improve code in the `json` and `base64` modules.
---
.../beam/jit/arm/instr_guard_bifs.cpp | 17 ++++-------
.../beam/jit/x86/instr_guard_bifs.cpp | 18 ++++-------
erts/emulator/test/guard_SUITE.erl | 30 +++++++++++++++++++
3 files changed, 41 insertions(+), 24 deletions(-)
diff --git a/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp b/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp
index 7f986daf09..0e66523d39 100644
--- a/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp
+++ b/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp
@@ -609,19 +609,12 @@ void BeamModuleAssembler::emit_bif_element(const ArgLabel &Fail,
a.asr(TMP3, pos.reg, imm(_TAG_IMMED1_SIZE));
- if (min >= 1) {
- comment("skipped check for position >= 1");
+ if (1 <= min && max <= size) {
+ comment("skipped check for known safe position");
} else {
- a.cmp(TMP3, imm(1));
- a.b_mi(fail);
- }
-
- if (size >= max) {
- comment("skipped check for position beyond tuple");
- } else {
- mov_imm(TMP2, size);
- a.cmp(TMP2, TMP3);
- a.b_lo(fail);
+ a.sub(TMP2, TMP3, imm(1));
+ cmp(TMP2, size);
+ a.b_hs(fail);
}
a.ldr(dst.reg, arm::Mem(TMP1, TMP3, arm::lsl(3)));
diff --git a/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp b/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
index 3898068237..c95bfcf69a 100644
--- a/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
+++ b/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
@@ -380,19 +380,13 @@ void BeamModuleAssembler::emit_bif_element(const ArgLabel &Fail,
a.mov(RET, ARG1);
a.sar(RET, imm(_TAG_IMMED1_SIZE));
- if (min >= 1) {
- comment("skipped check for position =:= 0 since it is always "
- ">= 1");
- } else {
- a.short_().jz(error);
- }
- if (min >= 0 && size >= max) {
- comment("skipped check for negative position and position "
- "beyond tuple");
+
+ if (1 <= min && max <= size) {
+ comment("skipped check for known safe position");
} else {
- /* Note: Also checks for negative size. */
- a.cmp(RET, imm(size));
- a.short_().ja(error);
+ a.lea(ARG3, x86::qword_ptr(RET, -1));
+ cmp(ARG3, size, ARG5);
+ a.short_().jae(error);
}
a.mov(RET, x86::qword_ptr(ARG4, RET, 3));
diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl
index 5bf6871f8c..29a716f50d 100644
--- a/erts/emulator/test/guard_SUITE.erl
+++ b/erts/emulator/test/guard_SUITE.erl
@@ -26,6 +26,7 @@
type_tests/1,guard_bif_binary_part/1]).
-include_lib("common_test/include/ct.hrl").
+-include_lib("stdlib/include/assert.hrl").
-export([init/3]).
-import(lists, [member/2]).
@@ -55,6 +56,19 @@ bad_tuple(Config) when is_list(Config) ->
error = bad_tuple1({a, b}),
x = bad_tuple1({x, b}),
y = bad_tuple1({a, b, y}),
+
+ ?assertError(badarg, int_to_atom_1(-1)),
+ ?assertError(badarg, int_to_atom_1(0)),
+ ?assertError(badarg, int_to_atom_1(4)),
+ ?assertError(badarg, int_to_atom_1(4.2)),
+ ?assertError(badarg, int_to_atom_1(x)),
+
+ ?assertError(badarg, int_to_atom_2(-1)),
+ ?assertError(badarg, int_to_atom_2(0)),
+ ?assertError(badarg, int_to_atom_2(4)),
+ ?assertError(badarg, int_to_atom_2(3.0)),
+ ?assertError(badarg, int_to_atom_2(x)),
+
ok.
bad_tuple1(T) when element(1, T) == x ->
@@ -64,6 +78,22 @@ bad_tuple1(T) when element(3, T) == y ->
bad_tuple1(_) ->
error.
+int_to_atom_1(N) ->
+ if
+ is_integer(N) ->
+ element(N, {a,b,c});
+ true ->
+ element(N, {a,b,c})
+ end.
+
+int_to_atom_2(N0) ->
+ case id(N0) of
+ N when is_integer(N) ->
+ element(N, {a,b,c});
+ Other ->
+ element(Other, {a,b,c})
+ end.
+
test_heap_guards(Config) when is_list(Config) ->
ct:timetrap({minutes, 2}),
--
2.43.0