aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_bif_load.c29
-rw-r--r--erts/emulator/beam/beam_load.c79
-rw-r--r--erts/emulator/beam/beam_load.h2
-rw-r--r--erts/emulator/beam/erl_arith.c5
-rw-r--r--erts/emulator/beam/global.h3
-rw-r--r--erts/emulator/beam/utils.c12
6 files changed, 94 insertions, 36 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index df1983a83d..8c32fc7854 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -39,12 +39,9 @@ static void set_default_trace_pattern(Eterm module);
static Eterm check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp);
static void delete_code(Module* modp);
static void decrement_refc(BeamInstr* code);
-static int is_native(BeamInstr* code);
static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
static int any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
-
-
BIF_RETTYPE code_is_module_native_1(BIF_ALIST_1)
{
Module* modp;
@@ -59,8 +56,8 @@ BIF_RETTYPE code_is_module_native_1(BIF_ALIST_1)
return am_undefined;
}
erts_rlock_old_code(code_ix);
- res = ((modp->curr.code && is_native(modp->curr.code)) ||
- (modp->old.code != 0 && is_native(modp->old.code))) ?
+ res = (erts_is_module_native(modp->curr.code) ||
+ erts_is_module_native(modp->old.code)) ?
am_true : am_false;
erts_runlock_old_code(code_ix);
return res;
@@ -1106,25 +1103,3 @@ beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module)
}
return NIL;
}
-
-static int
-is_native(BeamInstr* code)
-{
- Uint i, num_functions = code[MI_NUM_FUNCTIONS];
-
- /* Check NativeAdress of first real function in module
- */
- for (i=0; i<num_functions; i++) {
- BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
- Eterm name = (Eterm) func_info[3];
-
- if (is_atom(name)) {
- return func_info[1] != 0;
- }
- else ASSERT(is_nil(name)); /* ignore BIF stubs */
- }
- /* Not a single non-BIF function? */
- return 0;
-}
-
-
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 282aa71109..0d40201934 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -530,6 +530,7 @@ static Eterm functions_in_module(Process* p, Eterm mod);
static Eterm attributes_for_module(Process* p, Eterm mod);
static Eterm compilation_info_for_module(Process* p, Eterm mod);
static Eterm md5_of_module(Process* p, Eterm mod);
+static Eterm has_native(Process* p, Eterm mod);
static Eterm native_addresses(Process* p, Eterm mod);
int patch_funentries(Eterm Patchlist);
int patch(Eterm Addresses, Uint fe);
@@ -5408,6 +5409,9 @@ erts_module_info_0(Process* p, Eterm module)
list = CONS(hp, tup, list)
BUILD_INFO(am_md5);
+#ifdef HIPE
+ BUILD_INFO(am_native);
+#endif
BUILD_INFO(am_compile);
BUILD_INFO(am_attributes);
BUILD_INFO(am_exports);
@@ -5433,6 +5437,8 @@ erts_module_info_1(Process* p, Eterm module, Eterm what)
return compilation_info_for_module(p, module);
} else if (what == am_native_addresses) {
return native_addresses(p, module);
+ } else if (what == am_native) {
+ return has_native(p, module);
}
return THE_NON_VALUE;
}
@@ -5493,6 +5499,53 @@ functions_in_module(Process* p, /* Process whose heap to use. */
}
/*
+ * Returns 'true' if mod has any native compiled functions, otherwise 'false'
+ */
+
+static Eterm
+has_native(Process* p, Eterm mod)
+{
+ Eterm result = am_false;
+#ifdef HIPE
+ Module* modp;
+
+ if (is_not_atom(mod)) {
+ return THE_NON_VALUE;
+ }
+
+ modp = erts_get_module(mod, erts_active_code_ix());
+ if (modp == NULL) {
+ return THE_NON_VALUE;
+ }
+
+ if (erts_is_module_native(modp->curr.code)) {
+ result = am_true;
+ }
+#endif
+ return result;
+}
+
+int
+erts_is_module_native(BeamInstr* code)
+{
+ Uint i, num_functions;
+
+ /* Check NativeAdress of first real function in module */
+ if (code != NULL) {
+ num_functions = code[MI_NUM_FUNCTIONS];
+ for (i=0; i<num_functions; i++) {
+ BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
+ Eterm name = (Eterm) func_info[3];
+ if (is_atom(name)) {
+ return func_info[1] != 0;
+ }
+ else ASSERT(is_nil(name)); /* ignore BIF stubs */
+ }
+ }
+ return 0;
+}
+
+/*
* Builds a list of all functions including native addresses.
* [{Name,Arity,NativeAddress},...]
*
@@ -5695,7 +5748,11 @@ md5_of_module(Process* p, /* Process whose heap to use. */
return THE_NON_VALUE;
}
code = modp->curr.code;
- res = new_binary(p, (byte *) code[MI_MD5_PTR], MD5_SIZE);
+ if (code[MI_MD5_PTR] != 0) {
+ res = new_binary(p, (byte *) code[MI_MD5_PTR], MD5_SIZE);
+ } else {
+ res = am_undefined;
+ }
return res;
}
@@ -6168,6 +6225,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
LoaderState* stp;
BeamInstr Funcs;
BeamInstr Patchlist;
+ Eterm MD5Bin;
Eterm* tp;
BeamInstr* code = NULL;
BeamInstr* ptrs;
@@ -6196,12 +6254,15 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
goto error;
}
tp = tuple_val(Info);
- if (tp[0] != make_arityval(2)) {
+ if (tp[0] != make_arityval(3)) {
goto error;
}
Funcs = tp[1];
- Patchlist = tp[2];
-
+ Patchlist = tp[2];
+ MD5Bin = tp[3];
+ if (is_not_binary(MD5Bin) || (binary_size(MD5Bin) != MD5_SIZE)) {
+ goto error;
+ }
if ((n = erts_list_length(Funcs)) < 0) {
goto error;
}
@@ -6251,6 +6312,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(BeamInstr);
code_size += stp->chunks[ATTR_CHUNK].size;
code_size += stp->chunks[COMPILE_CHUNK].size;
+ code_size += MD5_SIZE;
code = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size);
if (!code) {
goto error;
@@ -6357,6 +6419,15 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
if (info == NULL) {
goto error;
}
+ {
+ byte *tmp = NULL;
+ byte *md5 = NULL;
+ if ((md5 = erts_get_aligned_binary_bytes(MD5Bin, &tmp)) != NULL) {
+ sys_memcpy(info, md5, MD5_SIZE);
+ code[MI_MD5_PTR] = (BeamInstr) info;
+ }
+ erts_free_aligned_binary_bytes(tmp);
+ }
/*
* Insert the module in the module table.
diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h
index 0e3ca0bdb0..46b0c60ab0 100644
--- a/erts/emulator/beam/beam_load.h
+++ b/erts/emulator/beam/beam_load.h
@@ -23,10 +23,10 @@
#include "beam_opcodes.h"
#include "erl_process.h"
+int erts_is_module_native(BeamInstr* code);
Eterm beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks,
Eterm module);
-
typedef struct gen_op_entry {
char* name;
int arity;
diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c
index 5150a8a507..47d516534f 100644
--- a/erts/emulator/beam/erl_arith.c
+++ b/erts/emulator/beam/erl_arith.c
@@ -2048,3 +2048,8 @@ Eterm erts_gc_bnot(Process* p, Eterm* reg, Uint live)
}
return result;
}
+
+/* Needed to remove compiler optimization */
+double erts_get_positive_zero_float() {
+ return 0.0f;
+}
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 40b043d1cc..54fba9274f 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -867,6 +867,9 @@ void print_process_info(int, void *, Process*);
void info(int, void *);
void loaded(int, void *);
+/* erl_arith.c */
+double erts_get_positive_zero_float(void);
+
/* config.c */
__decl_noreturn void __noreturn erl_exit(int n, char*, ...);
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 8f6335d5dd..51de3528be 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -958,7 +958,8 @@ tail_recur:
FloatDef ff;
GET_DOUBLE(term, ff);
if (ff.fd == 0.0f) {
- ff.fd = 0.0f; /* ensure pos. 0.0 */
+ /* ensure positive 0.0 */
+ ff.fd = erts_get_positive_zero_float();
}
hash = hash*FUNNY_NUMBER6 + (ff.fw[0] ^ ff.fw[1]);
break;
@@ -1477,7 +1478,8 @@ make_hash2(Eterm term)
FloatDef ff;
GET_DOUBLE(term, ff);
if (ff.fd == 0.0f) {
- ff.fd = 0.0f; /* ensure pos. 0.0 */
+ /* ensure positive 0.0 */
+ ff.fd = erts_get_positive_zero_float();
}
#if defined(WORDS_BIGENDIAN) || defined(DOUBLE_MIDDLE_ENDIAN)
UINT32_HASH_2(ff.fw[0], ff.fw[1], HCONST_12);
@@ -1899,7 +1901,8 @@ make_internal_hash(Eterm term)
FloatDef ff;
GET_DOUBLE(term, ff);
if (ff.fd == 0.0f) {
- ff.fd = 0.0f; /* ensure pos. 0.0 */
+ /* ensure positive 0.0 */
+ ff.fd = erts_get_positive_zero_float();
}
UINT32_HASH_2(ff.fw[0], ff.fw[1], HCONST_12);
goto pop_next;
@@ -2087,7 +2090,8 @@ tail_recur:
FloatDef ff;
GET_DOUBLE(term, ff);
if (ff.fd == 0.0f) {
- ff.fd = 0.0f; /* ensure pos. 0.0 */
+ /* ensure positive 0.0 */
+ ff.fd = erts_get_positive_zero_float();
}
hash = hash*FUNNY_NUMBER6 + (ff.fw[0] ^ ff.fw[1]);
}