aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_bp.c2
-rw-r--r--erts/emulator/beam/beam_emu.c21
-rw-r--r--erts/emulator/beam/beam_load.c14
-rw-r--r--erts/emulator/beam/erl_nif.c53
-rw-r--r--erts/emulator/beam/erl_process.c2
-rw-r--r--erts/emulator/beam/macros.tab9
-rw-r--r--erts/emulator/beam/map_instrs.tab8
-rw-r--r--erts/emulator/beam/ops.tab2
8 files changed, 64 insertions, 47 deletions
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index fe1e15701b..0832b3f374 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -998,7 +998,9 @@ do_call_trace(Process* c_p, ErtsCodeInfo* info, Eterm* reg,
fixup_cp_before_trace(c_p, &return_to_trace);
+ ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
flags = erts_call_trace(c_p, info, ms, reg, local, &tracer);
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
/* restore cp after potential fixup */
c_p->cp = cp_save;
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 60d0008d8f..bc95ccec52 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -400,12 +400,13 @@ static BeamInstr* apply_fun(Process* p, Eterm fun,
Eterm args, Eterm* reg) NOINLINE;
static Eterm new_fun(Process* p, Eterm* reg,
ErlFunEntry* fe, int num_free) NOINLINE;
-static Eterm new_map(Process* p, Eterm* reg, Uint live, Uint n, BeamInstr* ptr) NOINLINE;
-static Eterm new_small_map_lit(Process* p, Eterm* reg, Eterm keys_literal,
+static Eterm erts_gc_new_map(Process* p, Eterm* reg, Uint live,
+ Uint n, BeamInstr* ptr) NOINLINE;
+static Eterm erts_gc_new_small_map_lit(Process* p, Eterm* reg, Eterm keys_literal,
Uint live, BeamInstr* ptr) NOINLINE;
-static Eterm update_map_assoc(Process* p, Eterm* reg, Uint live,
+static Eterm erts_gc_update_map_assoc(Process* p, Eterm* reg, Uint live,
Uint n, BeamInstr* new_p) NOINLINE;
-static Eterm update_map_exact(Process* p, Eterm* reg, Uint live,
+static Eterm erts_gc_update_map_exact(Process* p, Eterm* reg, Uint live,
Uint n, Eterm* new_p) NOINLINE;
static Eterm get_map_element(Eterm map, Eterm key);
static Eterm get_map_element_hash(Eterm map, Eterm key, Uint32 hx);
@@ -2755,7 +2756,7 @@ do { \
static Eterm
-new_map(Process* p, Eterm* reg, Uint live, Uint n, BeamInstr* ptr)
+erts_gc_new_map(Process* p, Eterm* reg, Uint live, Uint n, BeamInstr* ptr)
{
Uint i;
Uint need = n + 1 /* hdr */ + 1 /*size*/ + 1 /* ptr */ + 1 /* arity */;
@@ -2812,7 +2813,8 @@ new_map(Process* p, Eterm* reg, Uint live, Uint n, BeamInstr* ptr)
}
static Eterm
-new_small_map_lit(Process* p, Eterm* reg, Eterm keys_literal, Uint live, BeamInstr* ptr)
+erts_gc_new_small_map_lit(Process* p, Eterm* reg, Eterm keys_literal,
+ Uint live, BeamInstr* ptr)
{
Eterm* keys = tuple_val(keys_literal);
Uint n = arityval(*keys);
@@ -2846,7 +2848,8 @@ new_small_map_lit(Process* p, Eterm* reg, Eterm keys_literal, Uint live, BeamIns
}
static Eterm
-update_map_assoc(Process* p, Eterm* reg, Uint live, Uint n, BeamInstr* new_p)
+erts_gc_update_map_assoc(Process* p, Eterm* reg, Uint live,
+ Uint n, BeamInstr* new_p)
{
Uint num_old;
Uint num_updates;
@@ -2892,7 +2895,7 @@ update_map_assoc(Process* p, Eterm* reg, Uint live, Uint n, BeamInstr* new_p)
*/
if (num_old == 0) {
- return new_map(p, reg, live, n, new_p);
+ return erts_gc_new_map(p, reg, live, n, new_p);
}
/*
@@ -3048,7 +3051,7 @@ update_map_assoc(Process* p, Eterm* reg, Uint live, Uint n, BeamInstr* new_p)
*/
static Eterm
-update_map_exact(Process* p, Eterm* reg, Uint live, Uint n, Eterm* new_p)
+erts_gc_update_map_exact(Process* p, Eterm* reg, Uint live, Uint n, Eterm* new_p)
{
Uint i;
Uint num_old;
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 7331c331a6..4fcfea527c 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -2384,8 +2384,18 @@ load_code(LoaderState* stp)
code[ci++] = NIL;
break;
case TAG_q:
- new_literal_patch(stp, ci);
- code[ci++] = tmp_op->a[arg].val;
+ {
+ BeamInstr val = tmp_op->a[arg].val;
+ Eterm term = stp->literals[val].term;
+ new_literal_patch(stp, ci);
+ code[ci++] = val;
+ switch (loader_tag(term)) {
+ case LOADER_X_REG:
+ case LOADER_Y_REG:
+ LoadError1(stp, "the term '%T' would be confused "
+ "with a register", term);
+ }
+ }
break;
default:
LoadError1(stp, "bad tag %d for general source",
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index f7f12efe28..c21b139cfa 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -3323,36 +3323,38 @@ static int examine_iovec_term(Eterm list, UWord max_length, iovec_slice_t *resul
size = binary_size(binary);
binary_header = binary_val(binary);
- /* If we're a sub-binary we'll need to check our underlying binary to
- * determine whether we're on-heap or not. */
- if(thing_subtag(*binary_header) == SUB_BINARY_SUBTAG) {
- ErlSubBin *sb = (ErlSubBin*)binary_header;
-
- /* Reject bitstrings */
- if((sb->bitoffs + sb->bitsize) > 0) {
- return 0;
+ if (size > 0) {
+ /* If we're a sub-binary we'll need to check our underlying binary
+ * to determine whether we're on-heap or not. */
+ if (thing_subtag(*binary_header) == SUB_BINARY_SUBTAG) {
+ ErlSubBin *sb = (ErlSubBin*)binary_header;
+
+ /* Reject bitstrings */
+ if((sb->bitoffs + sb->bitsize) > 0) {
+ return 0;
+ }
+
+ ASSERT(size <= binary_size(sb->orig));
+ binary_header = binary_val(sb->orig);
}
- ASSERT(size <= binary_size(sb->orig));
- binary_header = binary_val(sb->orig);
- }
-
- if(thing_subtag(*binary_header) == HEAP_BINARY_SUBTAG) {
- ASSERT(size <= ERL_ONHEAP_BIN_LIMIT);
+ if (thing_subtag(*binary_header) == HEAP_BINARY_SUBTAG) {
+ ASSERT(size <= ERL_ONHEAP_BIN_LIMIT);
- result->iovec_len += 1;
- result->onheap_size += size;
- } else {
- ASSERT(thing_subtag(*binary_header) == REFC_BINARY_SUBTAG);
+ result->iovec_len += 1;
+ result->onheap_size += size;
+ } else {
+ ASSERT(thing_subtag(*binary_header) == REFC_BINARY_SUBTAG);
- result->iovec_len += 1 + size / MAX_SYSIOVEC_IOVLEN;
- result->offheap_size += size;
+ result->iovec_len += 1 + size / MAX_SYSIOVEC_IOVLEN;
+ result->offheap_size += size;
+ }
}
result->sublist_length += 1;
lookahead = CDR(cell);
- if(result->sublist_length >= max_length) {
+ if (result->sublist_length >= max_length) {
break;
}
}
@@ -3385,6 +3387,10 @@ static void inspect_raw_binary_data(Eterm binary, ErlNifBinary *result) {
if (thing_subtag(*parent_header) == REFC_BINARY_SUBTAG) {
ProcBin *pb = (ProcBin*)parent_header;
+ if (pb->flags & (PB_IS_WRITABLE | PB_ACTIVE_WRITER)) {
+ erts_emasculate_writable_binary(pb);
+ }
+
ASSERT(pb->val != NULL);
ASSERT(byte_offset < pb->size);
ASSERT(&pb->bytes[byte_offset] >= (byte*)(pb->val)->orig_bytes);
@@ -3428,7 +3434,7 @@ static int fill_iovec_with_slice(ErlNifEnv *env,
/* If this isn't a refc binary, copy its contents to the onheap buffer
* and reference that instead. */
- if (raw_data.ref_bin == NULL) {
+ if (raw_data.size > 0 && raw_data.ref_bin == NULL) {
ASSERT(onheap_offset < onheap_data.size);
ASSERT(slice->onheap_size > 0);
@@ -3439,12 +3445,11 @@ static int fill_iovec_with_slice(ErlNifEnv *env,
raw_data.ref_bin = onheap_data.ref_bin;
}
- ASSERT(raw_data.ref_bin != NULL);
-
while (raw_data.size > 0) {
UWord chunk_len = MIN(raw_data.size, MAX_SYSIOVEC_IOVLEN);
ASSERT(iovec_idx < iovec->iovcnt);
+ ASSERT(raw_data.ref_bin != NULL);
iovec->iov[iovec_idx].iov_base = raw_data.data;
iovec->iov[iovec_idx].iov_len = chunk_len;
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 6654468fb6..3c0a126fe2 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -10824,7 +10824,7 @@ request_system_task(Process *c_p, Eterm requester, Eterm target,
goto badarg;
req_type = tp[1];
req_id = tp[2];
- req_id_sz = is_immed(req_id) ? req_id : size_object(req_id);
+ req_id_sz = is_immed(req_id) ? 0 : size_object(req_id);
tot_sz = req_id_sz;
for (i = 0; i < ERTS_MAX_PROC_SYS_TASK_ARGS; i++) {
int tix = 3 + i;
diff --git a/erts/emulator/beam/macros.tab b/erts/emulator/beam/macros.tab
index e0b5f56b53..494fe8961e 100644
--- a/erts/emulator/beam/macros.tab
+++ b/erts/emulator/beam/macros.tab
@@ -20,13 +20,12 @@
//
//
-// Use if there is a garbage collection before storing to a
-// general destination (either X or Y register).
+// Define a regular expression that will match instructions that
+// perform GC. That will allow beam_makeops to check for instructions
+// that don't use $REFRESH_GEN_DEST() when they should.
//
-REFRESH_GEN_DEST() {
- dst_ptr = REG_TARGET_PTR(dst);
-}
+GC_REGEXP=erts_garbage_collect|erts_gc|GcBifFunction;
// $Offset is relative to the start of the instruction (not to the
// location of the failure label reference). Since combined
diff --git a/erts/emulator/beam/map_instrs.tab b/erts/emulator/beam/map_instrs.tab
index bbb2f49b66..c594a87298 100644
--- a/erts/emulator/beam/map_instrs.tab
+++ b/erts/emulator/beam/map_instrs.tab
@@ -31,7 +31,7 @@ new_map(Dst, Live, N) {
Eterm res;
HEAVY_SWAPOUT;
- res = new_map(c_p, reg, $Live, $N, $NEXT_INSTRUCTION);
+ res = erts_gc_new_map(c_p, reg, $Live, $N, $NEXT_INSTRUCTION);
HEAVY_SWAPIN;
$REFRESH_GEN_DEST();
$Dst = res;
@@ -44,7 +44,7 @@ i_new_small_map_lit(Dst, Live, Keys) {
Eterm keys = $Keys;
HEAVY_SWAPOUT;
- res = new_small_map_lit(c_p, reg, keys, $Live, $NEXT_INSTRUCTION);
+ res = erts_gc_new_small_map_lit(c_p, reg, keys, $Live, $NEXT_INSTRUCTION);
HEAVY_SWAPIN;
$REFRESH_GEN_DEST();
$Dst = res;
@@ -133,7 +133,7 @@ update_map_assoc(Src, Dst, Live, N) {
reg[live] = $Src;
HEAVY_SWAPOUT;
- res = update_map_assoc(c_p, reg, live, $N, $NEXT_INSTRUCTION);
+ res = erts_gc_update_map_assoc(c_p, reg, live, $N, $NEXT_INSTRUCTION);
HEAVY_SWAPIN;
ASSERT(is_value(res));
$REFRESH_GEN_DEST();
@@ -147,7 +147,7 @@ update_map_exact(Fail, Src, Dst, Live, N) {
reg[live] = $Src;
HEAVY_SWAPOUT;
- res = update_map_exact(c_p, reg, live, $N, $NEXT_INSTRUCTION);
+ res = erts_gc_update_map_exact(c_p, reg, live, $N, $NEXT_INSTRUCTION);
HEAVY_SWAPIN;
if (is_value(res)) {
$REFRESH_GEN_DEST();
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 7a2c39b3a8..a560bde920 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -511,8 +511,6 @@ put_list y x x
put_list y y x
put_list x y x
-put_list y x x
-
# put_list SrcReg Constant Dst
put_list x c x