aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2016-05-19 17:38:54 +0200
committerSverker Eriksson <[email protected]>2016-10-14 14:29:15 +0200
commit39072836944d00c288beebfd98b14593f9609006 (patch)
treea1907dcf1915016488b28e65a2f0bae0d993136c /erts/emulator/beam
parent4d96d297044274c46deda1adfc567297449a9ba9 (diff)
downloadotp-39072836944d00c288beebfd98b14593f9609006.tar.gz
otp-39072836944d00c288beebfd98b14593f9609006.tar.bz2
otp-39072836944d00c288beebfd98b14593f9609006.zip
Add a loader state for HiPE code loading
Just like the BEAM loader state (as returned by erlang:prepare_loading/2), the HiPE loader state is contained in a magic binary. Eventually, we will separate HiPE loading into a prepare and a finalise phase, like the BEAM loader, where the prepare phase will be implemented by hipe_unified_loader and the finalise phase be implemented in C by hipe_load.c and beam_load.c, making prepare side-effect free and finalise atomic. The finalise phase will be exposed through the erlang:finish_loading/1 API, just like the BEAM loader, as this will allow HiPE and BEAM modules to be mixed in the same atomic "commit". The usage of a loader state makes it easier to keep track of all resources allocated during loading, and will not only make it easy to prevent leaks when hipe_unified_loader crashes, but also paves the way for proper, leak-free, unloading of HiPE modules.
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_bif_load.c14
-rw-r--r--erts/emulator/beam/beam_load.c69
-rw-r--r--erts/emulator/beam/module.c5
-rw-r--r--erts/emulator/beam/module.h9
4 files changed, 59 insertions, 38 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 237513095a..3302de0787 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -150,7 +150,13 @@ BIF_RETTYPE code_is_module_native_1(BIF_ALIST_1)
BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3)
{
Module* modp;
- Eterm res;
+ Eterm res, mod;
+
+ if (!ERTS_TERM_IS_MAGIC_BINARY(BIF_ARG_1) ||
+ is_not_atom(mod = erts_module_for_prepared_code
+ (((ProcBin*)binary_val(BIF_ARG_1))->val))) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
if (!erts_try_seize_code_write_permission(BIF_P)) {
ERTS_BIF_YIELD3(bif_export[BIF_code_make_stub_module_3],
@@ -160,7 +166,7 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3)
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_smp_thr_progress_block();
- modp = erts_get_module(BIF_ARG_1, erts_active_code_ix());
+ modp = erts_get_module(mod, erts_active_code_ix());
if (modp && modp->curr.num_breakpoints > 0) {
ASSERT(modp->curr.code_hdr != NULL);
@@ -172,12 +178,12 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3)
res = erts_make_stub_module(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
- if (res == BIF_ARG_1) {
+ if (res == mod) {
erts_end_staging_code_ix();
erts_commit_staging_code_ix();
#ifdef HIPE
if (!modp)
- modp = erts_get_module(BIF_ARG_1, erts_active_code_ix());
+ modp = erts_get_module(mod, erts_active_code_ix());
hipe_redirect_to_module(modp);
#endif
}
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 9b206f9a23..7d29f393e5 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -44,6 +44,7 @@
#include "hipe_bif0.h"
#include "hipe_mode_switch.h"
#include "hipe_arch.h"
+#include "hipe_load.h"
#endif
ErlDrvBinary* erts_gzinflate_buffer(char*, int);
@@ -482,8 +483,8 @@ static void free_literal_fragment(ErlHeapFragment*);
static void loader_state_dtor(Binary* magic);
static Eterm stub_insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
Eterm group_leader, Eterm module,
- BeamCodeHeader* code, Uint size,
- void* hipe_code_start, UWord hipe_code_size);
+ BeamCodeHeader* code_hdr, Uint size,
+ HipeModule *hipe_code);
static int init_iff_file(LoaderState* stp, byte* code, Uint size);
static int scan_iff_file(LoaderState* stp, Uint* chunk_types,
Uint num_types, Uint num_mandatory);
@@ -942,6 +943,13 @@ erts_module_for_prepared_code(Binary* magic)
LoaderState* stp;
if (ERTS_MAGIC_BIN_DESTRUCTOR(magic) != loader_state_dtor) {
+#ifdef HIPE
+ HipeLoaderState *hipe_stp;
+ if ((hipe_stp = hipe_get_loader_state(magic))
+ && hipe_stp->text_segment != 0) {
+ return hipe_stp->module;
+ }
+#endif
return NIL;
}
stp = ERTS_MAGIC_BIN_DATA(magic);
@@ -1094,7 +1102,7 @@ static Eterm
stub_insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
Eterm group_leader, Eterm module,
BeamCodeHeader* code_hdr, Uint size,
- void* hipe_code_start, UWord hipe_code_size)
+ HipeModule *hipe_code)
{
Module* modp;
Eterm retval;
@@ -1121,12 +1129,9 @@ stub_insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
DBG_TRACE_MFA(make_atom(modp->module), 0, 0, "insert_new_code new_hipe_refs = %p", modp->new_hipe_refs);
modp->curr.first_hipe_ref = modp->new_hipe_refs;
modp->curr.first_hipe_sdesc = modp->new_hipe_sdesc;
- modp->curr.hipe_code_start = hipe_code_start;
modp->new_hipe_refs = NULL;
modp->new_hipe_sdesc = NULL;
-# ifdef DEBUG
- modp->curr.hipe_code_size = hipe_code_size;
-# endif
+ modp->curr.hipe_code = hipe_code;
#endif
/*
@@ -6271,10 +6276,13 @@ patch_funentries(Eterm Patchlist)
*/
Eterm
-erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
+erts_make_stub_module(Process* p, Eterm hipe_magic_bin, Eterm Beam, Eterm Info)
{
Binary* magic;
+ Binary* hipe_magic;
LoaderState* stp;
+ HipeLoaderState* hipe_stp;
+ HipeModule *hipe_code;
BeamInstr Funcs;
BeamInstr Patchlist;
Eterm MD5Bin;
@@ -6290,7 +6298,6 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
byte* temp_alloc = NULL;
byte* bytes;
Uint size;
- UWord hipe_code_start = NULL, hipe_code_size = 0;
/*
* Must initialize stp->lambdas here because the error handling code
@@ -6298,15 +6305,19 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
*/
magic = erts_alloc_loader_state();
stp = ERTS_MAGIC_BIN_DATA(magic);
+ hipe_code = erts_alloc(ERTS_ALC_T_HIPE, sizeof(*hipe_code));
- if (is_not_atom(Mod)) {
+ if (!ERTS_TERM_IS_MAGIC_BINARY(hipe_magic_bin) ||
+ !(hipe_magic = ((ProcBin*)binary_val(hipe_magic_bin))->val,
+ hipe_stp = hipe_get_loader_state(hipe_magic)) ||
+ hipe_stp->module == NIL || hipe_stp->text_segment == 0) {
goto error;
}
if (is_not_tuple(Info)) {
goto error;
}
tp = tuple_val(Info);
- if (tp[0] != make_arityval(5)) {
+ if (tp[0] != make_arityval(3)) {
goto error;
}
Funcs = tp[1];
@@ -6323,20 +6334,11 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
}
size = binary_size(Beam);
-#ifdef HIPE
- if (!term_to_Uint(tp[4], &hipe_code_start))
- goto error;
-# ifdef DEBUG
- if (!term_to_Uint(tp[5], &hipe_code_size))
- goto error;
-# endif
-#endif
-
/*
* Scan the Beam binary and read the interesting sections.
*/
- stp->module = Mod;
+ stp->module = hipe_stp->module;
stp->group_leader = p->group_leader;
stp->num_functions = n;
if (!init_iff_file(stp, bytes, size)) {
@@ -6450,7 +6452,8 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
#else
op = (Eterm) BeamOpCode(op_move_return_n);
#endif
- fp = make_stub(fp, Mod, func, arity, (Uint)native_address, op);
+ fp = make_stub(fp, hipe_stp->module, func, arity, (Uint)native_address,
+ op);
}
/*
@@ -6490,12 +6493,18 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
}
/*
+ * Initialise HiPE module
+ */
+ hipe_code->text_segment = hipe_stp->text_segment;
+ hipe_code->text_segment_size = hipe_stp->text_segment_size;
+ hipe_code->data_segment = hipe_stp->data_segment;
+
+ /*
* Insert the module in the module table.
*/
- rval = stub_insert_new_code(p, 0, p->group_leader, Mod,
- code_hdr, code_size,
- (void*)hipe_code_start, hipe_code_size);
+ rval = stub_insert_new_code(p, 0, p->group_leader, hipe_stp->module,
+ code_hdr, code_size, hipe_code);
if (rval != NIL) {
goto error;
}
@@ -6511,12 +6520,20 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
}
if (patch_funentries(Patchlist)) {
+ Eterm mod = hipe_stp->module;
+ /* Prevent code from being freed */
+ hipe_stp->text_segment = 0;
+ hipe_stp->data_segment = 0;
+
erts_free_aligned_binary_bytes(temp_alloc);
free_loader_state(magic);
- return Mod;
+ hipe_free_loader_state(hipe_magic);
+
+ return mod;
}
error:
+ erts_free(ERTS_ALC_T_HIPE, hipe_code);
erts_free_aligned_binary_bytes(temp_alloc);
free_loader_state(magic);
BIF_ERROR(p, BADARG);
diff --git a/erts/emulator/beam/module.c b/erts/emulator/beam/module.c
index 93ce8fcf9f..5c56ad20df 100644
--- a/erts/emulator/beam/module.c
+++ b/erts/emulator/beam/module.c
@@ -79,10 +79,7 @@ void erts_module_instance_init(struct erl_module_instance* modi)
#ifdef HIPE
modi->first_hipe_ref = NULL;
modi->first_hipe_sdesc = NULL;
- modi->hipe_code_start = NULL;
-# ifdef DEBUG
- modi->hipe_code_size = 0;
-# endif
+ modi->hipe_code = NULL;
#endif
}
diff --git a/erts/emulator/beam/module.h b/erts/emulator/beam/module.h
index 694583597b..c3adaf12fc 100644
--- a/erts/emulator/beam/module.h
+++ b/erts/emulator/beam/module.h
@@ -23,6 +23,10 @@
#include "index.h"
+#ifdef HIPE
+#include "hipe_module.h"
+#endif
+
struct erl_module_instance {
BeamCodeHeader* code_hdr;
int code_length; /* Length of loaded code in bytes. */
@@ -33,10 +37,7 @@ struct erl_module_instance {
#ifdef HIPE
struct hipe_ref* first_hipe_ref; /* all external hipe calls from this module */
struct hipe_sdesc* first_hipe_sdesc; /* all stack descriptors for this module */
- void* hipe_code_start;
-# ifdef DEBUG
- UWord hipe_code_size;
-# endif
+ HipeModule *hipe_code;
#endif
};