aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/erl_driver.h4
-rw-r--r--erts/emulator/beam/erl_map.c31
-rw-r--r--erts/emulator/beam/erl_map.h4
-rw-r--r--erts/emulator/beam/external.c31
-rw-r--r--erts/emulator/beam/io.c44
5 files changed, 81 insertions, 33 deletions
diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h
index 2bd3181bdc..ab9ee63104 100644
--- a/erts/emulator/beam/erl_driver.h
+++ b/erts/emulator/beam/erl_driver.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2014. 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
@@ -605,6 +605,8 @@ EXTERN int null_func(void);
#define ERL_DRV_INT64 ((ErlDrvTermData) 15) /* ErlDrvSInt64 * */
#define ERL_DRV_UINT64 ((ErlDrvTermData) 16) /* ErlDrvUInt64 * */
+#define ERL_DRV_MAP ((ErlDrvTermData) 17) /* ErlDrvUInt */
+
#ifndef ERL_DRIVER_TYPES_ONLY
/* make terms for driver_output_term and driver_send_term */
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 57f156509c..2fff7f9390 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -786,3 +786,34 @@ BIF_RETTYPE maps_values_1(BIF_ALIST_1) {
}
BIF_ERROR(BIF_P, BADARG);
}
+
+int erts_validate_and_sort_map(map_t* mp)
+{
+ Eterm *ks = map_get_keys(mp);
+ Eterm *vs = map_get_values(mp);
+ Uint sz = map_get_size(mp);
+ Uint ix,jx;
+ Eterm tmp;
+ int c;
+
+ /* sort */
+
+ for (ix = 1; ix < sz; ix++) {
+ jx = ix;
+ while( jx > 0 && (c = CMP_TERM(ks[jx],ks[jx-1])) <= 0 ) {
+ /* identical key -> error */
+ if (c == 0) return 0;
+
+ tmp = ks[jx];
+ ks[jx] = ks[jx - 1];
+ ks[jx - 1] = tmp;
+
+ tmp = vs[jx];
+ vs[jx] = vs[jx - 1];
+ vs[jx - 1] = tmp;
+
+ jx--;
+ }
+ }
+ return 1;
+}
diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h
index 616ecd24ce..cfacb2ec28 100644
--- a/erts/emulator/beam/erl_map.h
+++ b/erts/emulator/beam/erl_map.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2013. All Rights Reserved.
+ * Copyright Ericsson AB 2014. 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
@@ -67,6 +67,6 @@ int erts_maps_update(Process *p, Eterm key, Eterm value, Eterm map, Eterm *res
int erts_maps_find(Eterm key, Eterm map, Eterm *value);
int erts_maps_get(Eterm key, Eterm map, Eterm *value);
int erts_maps_remove(Process *p, Eterm key, Eterm map, Eterm *res);
-
+int erts_validate_and_sort_map(map_t* map);
#endif
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 57251286c8..a4cc3435c3 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -3795,37 +3795,10 @@ dec_term_atom_common:
*/
while (maps_head) {
- map_t *mp = (map_t*)maps_head;
- Eterm *ks = map_get_keys(mp);
- Eterm *vs = map_get_values(mp);
- Uint sz = map_get_size(mp);
- Uint ix,jx;
- Eterm tmp;
- int c;
-
next = (Eterm *)(EXPAND_POINTER(*maps_head));
-
- /* sort */
-
- for ( ix = 1; ix < sz; ix++) {
- jx = ix;
- while( jx > 0 && (c = CMP_TERM(ks[jx],ks[jx-1])) <= 0 ) {
- /* identical key -> error */
- if (c == 0) goto error;
-
- tmp = ks[jx];
- ks[jx] = ks[jx - 1];
- ks[jx - 1] = tmp;
-
- tmp = vs[jx];
- vs[jx] = vs[jx - 1];
- vs[jx - 1] = tmp;
-
- jx--;
- }
-
- }
*maps_head = MAP_HEADER;
+ if (!erts_validate_and_sort_map((map_t*)maps_head))
+ goto error;
maps_head = next;
}
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 49af86b36a..3b16cdeb4a 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2014. 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
@@ -46,6 +46,7 @@
#define ERTS_WANT_EXTERNAL_TAGS
#include "external.h"
#include "dtrace-wrapper.h"
+#include "erl_map.h"
extern ErlDrvEntry fd_driver_entry;
extern ErlDrvEntry vanilla_driver_entry;
@@ -5293,6 +5294,17 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
depth++;
break;
}
+ case ERL_DRV_MAP: { /* int */
+ ERTS_DDT_CHK_ENOUGH_ARGS(1);
+ if ((int) ptr[0] < 0) ERTS_DDT_FAIL;
+ need += MAP_HEADER_SIZE + 1 + 2*ptr[0];
+ depth -= 2*ptr[0];
+ if (depth < 0) ERTS_DDT_FAIL;
+ ptr++;
+ depth++;
+ break;
+ }
+
default:
ERTS_DDT_FAIL;
}
@@ -5529,6 +5541,36 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
ptr += 2;
break;
+ case ERL_DRV_MAP: { /* int */
+ int size = (int)ptr[0];
+ Eterm* tp = hp;
+ Eterm* vp;
+ map_t *mp;
+
+ *tp = make_arityval(size);
+
+ hp += 1 + size;
+ mp = (map_t*)hp;
+ mp->thing_word = MAP_HEADER;
+ mp->size = size;
+ mp->keys = make_tuple(tp);
+ mess = make_map(mp);
+
+ hp += MAP_HEADER_SIZE + size; /* advance "heap" pointer */
+
+ tp += size; /* point at last key */
+ vp = hp - 1; /* point at last value */
+
+ while(size--) {
+ *vp-- = ESTACK_POP(stack);
+ *tp-- = ESTACK_POP(stack);
+ }
+ if (!erts_validate_and_sort_map(mp))
+ ERTS_DDT_FAIL;
+ ptr++;
+ break;
+ }
+
}
ESTACK_PUSH(stack, mess);
}