aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/beam_emu.c2
-rw-r--r--erts/emulator/beam/beam_load.c2
-rw-r--r--erts/emulator/beam/bif.tab1
-rw-r--r--erts/emulator/beam/erl_bif_guard.c23
-rw-r--r--erts/emulator/beam/erl_map.c23
-rwxr-xr-xerts/emulator/beam/global.h1
-rw-r--r--lib/stdlib/src/erl_internal.erl2
7 files changed, 52 insertions, 2 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 5c955b9566..1cad31be2c 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -5080,6 +5080,8 @@ translate_gc_bif(void* gcf)
return bit_size_1;
} else if (gcf == erts_gc_byte_size_1) {
return byte_size_1;
+ } else if (gcf == erts_gc_map_size_1) {
+ return map_size_1;
} else if (gcf == erts_gc_abs_1) {
return abs_1;
} else if (gcf == erts_gc_float_1) {
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 58207ec75b..b589d1c930 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -3783,6 +3783,8 @@ gen_guard_bif1(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
op->a[1].val = (BeamInstr) (void *) erts_gc_bit_size_1;
} else if (bf == byte_size_1) {
op->a[1].val = (BeamInstr) (void *) erts_gc_byte_size_1;
+ } else if (bf == map_size_1) {
+ op->a[1].val = (BeamInstr) (void *) erts_gc_map_size_1;
} else if (bf == abs_1) {
op->a[1].val = (BeamInstr) (void *) erts_gc_abs_1;
} else if (bf == float_1) {
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 42515d0494..a8623fcf61 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -579,6 +579,7 @@ bif os:unsetenv/1
bif re:inspect/2
ubif erlang:is_map/1
+ubif erlang:map_size/1
bif map:to_list/1
bif map:new/0
bif map:get/2
diff --git a/erts/emulator/beam/erl_bif_guard.c b/erts/emulator/beam/erl_bif_guard.c
index a715756c15..bbd8aa31d9 100644
--- a/erts/emulator/beam/erl_bif_guard.c
+++ b/erts/emulator/beam/erl_bif_guard.c
@@ -33,6 +33,7 @@
#include "bif.h"
#include "big.h"
#include "erl_binary.h"
+#include "erl_map.h"
static Eterm gc_double_to_integer(Process* p, double x, Eterm* reg, Uint live);
@@ -455,6 +456,28 @@ Eterm erts_gc_byte_size_1(Process* p, Eterm* reg, Uint live)
}
}
+Eterm erts_gc_map_size_1(Process* p, Eterm* reg, Uint live)
+{
+ Eterm arg = reg[live];
+ if (is_map(arg)) {
+ map_t *mp = (map_t*)map_val(arg);
+ Uint size = map_get_size(mp);
+ if (IS_USMALL(0, size)) {
+ return make_small(size);
+ } else {
+ Eterm* hp;
+ if (ERTS_NEED_GC(p, BIG_UINT_HEAP_SIZE)) {
+ erts_garbage_collect(p, BIG_UINT_HEAP_SIZE, reg, live);
+ }
+ hp = p->htop;
+ p->htop += BIG_UINT_HEAP_SIZE;
+ return uint_to_big(size, hp);
+ }
+ } else {
+ BIF_ERROR(p, BADARG);
+ }
+}
+
Eterm erts_gc_abs_1(Process* p, Eterm* reg, Uint live)
{
Eterm arg;
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 1fd7943c30..6a59fa29b8 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -30,10 +30,8 @@
#include "error.h"
#include "bif.h"
-
#include "erl_map.h"
-
BIF_RETTYPE map_to_list_1(BIF_ALIST_1) {
if (is_map(BIF_ARG_1)) {
Uint n;
@@ -58,6 +56,27 @@ BIF_RETTYPE map_to_list_1(BIF_ALIST_1) {
BIF_ERROR(BIF_P, BADARG);
}
+
+/* erlang:map_size/1
+ * the corresponding instruction is implemented in:
+ * beam/erl_bif_guard.c
+ */
+
+BIF_RETTYPE map_size_1(BIF_ALIST_1) {
+ if (is_map(BIF_ARG_1)) {
+ Eterm *hp;
+ Uint hsz = 0;
+ map_t *mp = (map_t*)map_val(BIF_ARG_1);
+ Uint n = map_get_size(mp);
+
+ erts_bld_uint(NULL, &hsz, n);
+ hp = HAlloc(BIF_P, hsz);
+ BIF_RET(erts_bld_uint(&hp, NULL, n));
+ }
+
+ BIF_ERROR(BIF_P, BADARG);
+}
+
BIF_RETTYPE map_new_0(BIF_ALIST_0) {
Eterm* hp;
Eterm tup;
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 83a8911a36..8fcb95d0e2 100755
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -998,6 +998,7 @@ Eterm erts_gc_length_1(Process* p, Eterm* reg, Uint live);
Eterm erts_gc_size_1(Process* p, Eterm* reg, Uint live);
Eterm erts_gc_bit_size_1(Process* p, Eterm* reg, Uint live);
Eterm erts_gc_byte_size_1(Process* p, Eterm* reg, Uint live);
+Eterm erts_gc_map_size_1(Process* p, Eterm* reg, Uint live);
Eterm erts_gc_abs_1(Process* p, Eterm* reg, Uint live);
Eterm erts_gc_float_1(Process* p, Eterm* reg, Uint live);
Eterm erts_gc_round_1(Process* p, Eterm* reg, Uint live);
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index 28de7205ea..480675554a 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -70,6 +70,7 @@ guard_bif(bit_size, 1) -> true;
guard_bif(byte_size, 1) -> true;
guard_bif(element, 2) -> true;
guard_bif(self, 0) -> true;
+guard_bif(map_size, 1) -> true;
guard_bif(node, 0) -> true;
guard_bif(node, 1) -> true;
guard_bif(tuple_size, 1) -> true;
@@ -335,6 +336,7 @@ bif(list_to_pid, 1) -> true;
bif(list_to_tuple, 1) -> true;
bif(load_module, 2) -> true;
bif(make_ref, 0) -> true;
+bif(map_size,1) -> true;
bif(max,2) -> true;
bif(min,2) -> true;
bif(module_loaded, 1) -> true;