aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--OTP_VERSION2
-rw-r--r--erts/configure.in1
-rw-r--r--erts/emulator/beam/beam_emu.c141
-rw-r--r--erts/emulator/beam/erl_process.c70
-rw-r--r--erts/emulator/beam/ops.tab94
-rw-r--r--erts/emulator/beam/sys.h2
-rw-r--r--lib/compiler/src/v3_core.erl45
-rw-r--r--lib/compiler/test/compile_SUITE.erl35
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl86
9 files changed, 209 insertions, 267 deletions
diff --git a/OTP_VERSION b/OTP_VERSION
index fcc01369af..06d4ac2bfd 100644
--- a/OTP_VERSION
+++ b/OTP_VERSION
@@ -1 +1 @@
-20.0.1
+21.0-rc0
diff --git a/erts/configure.in b/erts/configure.in
index 85351ab7c7..2579e39b29 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -640,6 +640,7 @@ case $chk_arch_ in
armv7l) ARCH=arm;;
armv7hl) ARCH=arm;;
tile) ARCH=tile;;
+ e2k) ARCH=e2k;;
*) ARCH=noarch;;
esac
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index bc83699951..872fba6899 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -3768,33 +3768,33 @@ do { \
Uint alloc;
Uint num_bytes;
- OpCase(i_bs_init_bits_heap_IIId): {
+ OpCase(i_bs_init_bits_heap_IIIx): {
num_bits = Arg(0);
alloc = Arg(1);
I++;
goto do_bs_init_bits_known;
}
- OpCase(i_bs_init_bits_IId): {
+ OpCase(i_bs_init_bits_IIx): {
num_bits = Arg(0);
alloc = 0;
goto do_bs_init_bits_known;
}
- OpCase(i_bs_init_bits_fail_heap_sIjId): {
+ OpCase(i_bs_init_bits_fail_heap_sIjIx): {
GetArg1(0, num_bits_term);
alloc = Arg(1);
I += 2;
goto do_bs_init_bits;
}
- OpCase(i_bs_init_bits_fail_yjId): {
+ OpCase(i_bs_init_bits_fail_yjIx): {
num_bits_term = yb(Arg(0));
I++;
alloc = 0;
goto do_bs_init_bits;
}
- OpCase(i_bs_init_bits_fail_xjId): {
+ OpCase(i_bs_init_bits_fail_xjIx): {
num_bits_term = xb(Arg(0));
I++;
alloc = 0;
@@ -3873,7 +3873,8 @@ do { \
new_binary = make_binary(sb);
}
HEAP_SPACE_VERIFIED(0);
- StoreBifResult(2, new_binary);
+ xb(Arg(2)) = new_binary;
+ Next(3);
} else {
Binary* bptr;
ProcBin* pb;
@@ -3908,21 +3909,21 @@ do { \
{
Eterm BsOp1, BsOp2;
- OpCase(i_bs_init_fail_heap_sIjId): {
+ OpCase(i_bs_init_fail_heap_sIjIx): {
GetArg1(0, BsOp1);
BsOp2 = Arg(1);
I += 2;
goto do_bs_init;
}
- OpCase(i_bs_init_fail_yjId): {
+ OpCase(i_bs_init_fail_yjIx): {
BsOp1 = yb(Arg(0));
BsOp2 = 0;
I++;
goto do_bs_init;
}
- OpCase(i_bs_init_fail_xjId): {
+ OpCase(i_bs_init_fail_xjIx): {
BsOp1 = xb(Arg(0));
BsOp2 = 0;
I++;
@@ -3954,14 +3955,14 @@ do { \
}
- OpCase(i_bs_init_heap_IIId): {
+ OpCase(i_bs_init_heap_IIIx): {
BsOp1 = Arg(0);
BsOp2 = Arg(1);
I++;
goto do_proc_bin_alloc;
}
- OpCase(i_bs_init_IId): {
+ OpCase(i_bs_init_IIx): {
BsOp1 = Arg(0);
BsOp2 = 0;
}
@@ -3996,17 +3997,18 @@ do { \
OH_OVERHEAD(&(MSO(c_p)), BsOp1 / sizeof(Eterm));
- StoreBifResult(2, make_binary(pb));
+ xb(Arg(2)) = make_binary(pb);
+ Next(3);
}
- OpCase(i_bs_init_heap_bin_heap_IIId): {
+ OpCase(i_bs_init_heap_bin_heap_IIIx): {
BsOp1 = Arg(0);
BsOp2 = Arg(1);
I++;
goto do_heap_bin_alloc;
}
- OpCase(i_bs_init_heap_bin_IId): {
+ OpCase(i_bs_init_heap_bin_IIx): {
BsOp1 = Arg(0);
BsOp2 = 0;
}
@@ -4026,11 +4028,12 @@ do { \
hb->size = BsOp1;
erts_current_bin = (byte *) hb->data;
BsOp1 = make_binary(hb);
- StoreBifResult(2, BsOp1);
+ xb(Arg(2)) = BsOp1;
+ Next(3);
}
}
- OpCase(bs_add_jssId): {
+ OpCase(bs_add_jssIx): {
Eterm Op1, Op2;
Uint Unit = Arg(3);
@@ -4060,7 +4063,8 @@ do { \
Op1 = erts_make_integer(Op1, c_p);
HTOP = HEAP_TOP(c_p);
}
- StoreBifResult(4, Op1);
+ xb(Arg(4)) = Op1;
+ Next(5);
}
goto badarg;
} else {
@@ -4129,7 +4133,7 @@ do { \
* Operands: Fail ExtraHeap Live Unit Size Dst
*/
- OpCase(i_bs_append_jIIIsd): {
+ OpCase(i_bs_append_jIIIsx): {
Uint live = Arg(2);
Uint res;
Eterm Size;
@@ -4143,13 +4147,14 @@ do { \
/* c_p->freason is already set (may be either BADARG or SYSTEM_LIMIT). */
goto lb_Cl_error;
}
- StoreBifResult(5, res);
+ xb(Arg(5)) = res;
+ Next(6);
}
/*
* Operands: Fail Size Src Unit Dst
*/
- OpCase(i_bs_private_append_jIssd): {
+ OpCase(i_bs_private_append_jIssx): {
Eterm res;
Eterm Size, Src;
@@ -4159,7 +4164,8 @@ do { \
/* c_p->freason is already set (may be either BADARG or SYSTEM_LIMIT). */
goto lb_Cl_error;
}
- StoreBifResult(4, res);
+ xb(Arg(4)) = res;
+ Next(5);
}
OpCase(bs_init_writable): {
@@ -4176,7 +4182,7 @@ do { \
* can get away with that because we KNOW that bs_put_utf8 will do
* full error checking.
*/
- OpCase(i_bs_utf8_size_sd): {
+ OpCase(i_bs_utf8_size_sx): {
Eterm arg;
Eterm result;
@@ -4190,7 +4196,8 @@ do { \
} else {
result = make_small(4);
}
- StoreBifResult(1, result);
+ xb(Arg(1)) = result;
+ Next(2);
}
OpCase(i_bs_put_utf8_js): {
@@ -4211,7 +4218,7 @@ do { \
* full error checking.
*/
- OpCase(i_bs_utf16_size_sd): {
+ OpCase(i_bs_utf16_size_sx): {
Eterm arg;
Eterm result = make_small(2);
@@ -4219,7 +4226,8 @@ do { \
if (arg >= make_small(0x10000UL)) {
result = make_small(4);
}
- StoreBifResult(1, result);
+ xb(Arg(1)) = result;
+ Next(2);
}
OpCase(bs_put_utf16_jIs): {
@@ -4313,7 +4321,7 @@ do { \
*HTOP = HEADER_BIN_MATCHSTATE(slots);
HTOP += wordsneeded;
HEAP_SPACE_VERIFIED(0);
- StoreResult(make_matchstate(dst), Arg(3));
+ xb(Arg(3)) = make_matchstate(dst);
}
} else if (is_binary_header(header)) {
Eterm result;
@@ -4330,19 +4338,19 @@ do { \
if (is_non_value(result)) {
ClauseFail();
} else {
- StoreResult(result, Arg(3));
+ xb(Arg(3)) = result;
}
} else {
ClauseFail();
}
NextPF(4, next);
- OpCase(i_bs_start_match2_xfIId): {
+ OpCase(i_bs_start_match2_xfIIx): {
context = xb(Arg(0));
I++;
goto do_start_match;
}
- OpCase(i_bs_start_match2_yfIId): {
+ OpCase(i_bs_start_match2_yfIIx): {
context = yb(Arg(0));
I++;
goto do_start_match;
@@ -4397,7 +4405,7 @@ do { \
{
Eterm bs_get_integer8_context;
- OpCase(i_bs_get_integer_8_xfd): {
+ OpCase(i_bs_get_integer_8_xfx): {
ErlBinMatchBuffer *_mb;
Eterm _result;
bs_get_integer8_context = xb(Arg(0));
@@ -4412,14 +4420,15 @@ do { \
_result = make_small(_mb->base[BYTE_OFFSET(_mb->offset)]);
_mb->offset += 8;
}
- StoreBifResult(1, _result);
+ xb(Arg(1)) = _result;
+ Next(2);
}
}
{
Eterm bs_get_integer_16_context;
- OpCase(i_bs_get_integer_16_xfd):
+ OpCase(i_bs_get_integer_16_xfx):
bs_get_integer_16_context = xb(Arg(0));
I++;
@@ -4436,14 +4445,15 @@ do { \
_result = make_small(get_int16(_mb->base+BYTE_OFFSET(_mb->offset)));
_mb->offset += 16;
}
- StoreBifResult(1, _result);
+ xb(Arg(1)) = _result;
+ Next(2);
}
}
{
Eterm bs_get_integer_32_context;
- OpCase(i_bs_get_integer_32_xfId):
+ OpCase(i_bs_get_integer_32_xfIx):
bs_get_integer_32_context = xb(Arg(0));
I++;
@@ -4471,7 +4481,8 @@ do { \
HEAP_SPACE_VERIFIED(0);
}
#endif
- StoreBifResult(2, _result);
+ xb(Arg(2)) = _result;
+ Next(3);
}
}
@@ -4479,7 +4490,7 @@ do { \
Eterm Ms, Sz;
/* Operands: x(Reg) Size Live Fail Flags Dst */
- OpCase(i_bs_get_integer_imm_xIIfId): {
+ OpCase(i_bs_get_integer_imm_xIIfIx): {
Uint wordsneeded;
Ms = xb(Arg(0));
Sz = Arg(1);
@@ -4491,7 +4502,7 @@ do { \
}
/* Operands: x(Reg) Size Fail Flags Dst */
- OpCase(i_bs_get_integer_small_imm_xIfId): {
+ OpCase(i_bs_get_integer_small_imm_xIfIx): {
Ms = xb(Arg(0));
Sz = Arg(1);
I += 2;
@@ -4516,14 +4527,15 @@ do { \
if (is_non_value(result)) {
ClauseFail();
}
- StoreBifResult(2, result);
+ xb(Arg(2)) = result;
+ Next(3);
}
}
/*
* Operands: Fail Live FlagsAndUnit Ms Sz Dst
*/
- OpCase(i_bs_get_integer_fIIssd): {
+ OpCase(i_bs_get_integer_fIIssx): {
Uint flags;
Uint size;
Eterm Ms;
@@ -4558,14 +4570,15 @@ do { \
if (is_non_value(result)) {
ClauseFail();
}
- StoreBifResult(5, result);
+ xb(Arg(5)) = result;
+ Next(6);
}
{
Eterm get_utf8_context;
/* Operands: MatchContext Fail Dst */
- OpCase(i_bs_get_utf8_xfd): {
+ OpCase(i_bs_get_utf8_xfx): {
get_utf8_context = xb(Arg(0));
I++;
}
@@ -4580,7 +4593,8 @@ do { \
if (is_non_value(result)) {
ClauseFail();
}
- StoreBifResult(1, result);
+ xb(Arg(1)) = result;
+ Next(2);
}
}
@@ -4588,7 +4602,7 @@ do { \
Eterm get_utf16_context;
/* Operands: MatchContext Fail Flags Dst */
- OpCase(i_bs_get_utf16_xfId): {
+ OpCase(i_bs_get_utf16_xfIx): {
get_utf16_context = xb(Arg(0));
I++;
}
@@ -4603,7 +4617,8 @@ do { \
if (is_non_value(result)) {
ClauseFail();
}
- StoreBifResult(2, result);
+ xb(Arg(2)) = result;
+ Next(3);
}
}
@@ -6354,7 +6369,7 @@ BeamInstr *I, Uint stack_offset)
{
int arity;
Export* ep;
- Eterm tmp, this;
+ Eterm tmp;
/*
* Check the arguments which should be of the form apply(Module,
@@ -6377,20 +6392,8 @@ BeamInstr *I, Uint stack_offset)
while (1) {
Eterm m, f, a;
- /* The module argument may be either an atom or an abstract module
- * (currently implemented using tuples, but this might change).
- */
- this = THE_NON_VALUE;
- if (is_not_atom(module)) {
- Eterm* tp;
-
- if (is_not_tuple(module)) goto error;
- tp = tuple_val(module);
- if (arityval(tp[0]) < 1) goto error;
- this = module;
- module = tp[1];
- if (is_not_atom(module)) goto error;
- }
+
+ if (is_not_atom(module)) goto error;
if (module != am_erlang || function != am_apply)
break;
@@ -6425,9 +6428,7 @@ BeamInstr *I, Uint stack_offset)
}
/*
* Walk down the 3rd parameter of apply (the argument list) and copy
- * the parameters to the x registers (reg[]). If the module argument
- * was an abstract module, add 1 to the function arity and put the
- * module argument in the n+1st x register as a THIS reference.
+ * the parameters to the x registers (reg[]).
*/
tmp = args;
@@ -6444,9 +6445,6 @@ BeamInstr *I, Uint stack_offset)
if (is_not_nil(tmp)) { /* Must be well-formed list */
goto error;
}
- if (this != THE_NON_VALUE) {
- reg[arity++] = this;
- }
/*
* Get the index into the export table, or failing that the export
@@ -6485,18 +6483,7 @@ fixed_apply(Process* p, Eterm* reg, Uint arity,
return 0;
}
- /* The module argument may be either an atom or an abstract module
- * (currently implemented using tuples, but this might change).
- */
- if (is_not_atom(module)) {
- Eterm* tp;
- if (is_not_tuple(module)) goto error;
- tp = tuple_val(module);
- if (arityval(tp[0]) < 1) goto error;
- module = tp[1];
- if (is_not_atom(module)) goto error;
- ++arity;
- }
+ if (is_not_atom(module)) goto error;
/* Handle apply of apply/3... */
if (module == am_erlang && function == am_apply && arity == 3)
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index fc2b34e70f..ae598e9663 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -1289,10 +1289,8 @@ reply_sched_wall_time(void *vswtrp)
ErlOffHeap *ohp = NULL;
ErtsMessage *mp = NULL;
- ASSERT(esdp);
-#ifdef ERTS_DIRTY_SCHEDULERS
- ASSERT(!ERTS_SCHEDULER_IS_DIRTY(esdp));
-#endif
+ ASSERT(esdp && !ERTS_SCHEDULER_IS_DIRTY(esdp));
+
if (swtrp->set) {
if (!swtrp->enable && esdp->sched_wall_time.enabled) {
esdp->sched_wall_time.u.need = erts_sched_balance_util;
@@ -1458,11 +1456,10 @@ erts_sched_wall_time_request(Process *c_p, int set, int enable,
ErtsSchedWallTimeReq *swtrp;
Eterm *hp;
+ ASSERT(esdp && !ERTS_SCHEDULER_IS_DIRTY(esdp));
+
if (!set && !esdp->sched_wall_time.enabled)
return THE_NON_VALUE;
-#ifdef ERTS_DIRTY_SCHEDULERS
- ASSERT(!ERTS_SCHEDULER_IS_DIRTY(esdp));
-#endif
swtrp = swtreq_alloc();
ref = erts_make_ref(c_p);
@@ -1509,10 +1506,7 @@ reply_system_check(void *vscrp)
ErlOffHeap *ohp = NULL;
ErtsMessage *mp = NULL;
- ASSERT(esdp);
-#ifdef ERTS_DIRTY_SCHEDULERS
- ASSERT(!ERTS_SCHEDULER_IS_DIRTY(esdp));
-#endif
+ ASSERT(esdp && !ERTS_SCHEDULER_IS_DIRTY(esdp));
sz = ERTS_REF_THING_SIZE;
mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp);
@@ -1778,9 +1772,9 @@ static ERTS_INLINE void
haw_thr_prgr_current_check_progress(ErtsAuxWorkData *awdp)
{
ErtsThrPrgrVal current = awdp->current_thr_prgr;
-#ifdef ERTS_DIRTY_SCHEDULERS
+
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
if (current != ERTS_THR_PRGR_INVALID
&& !erts_thr_progress_equal(current, erts_thr_progress_current())) {
/*
@@ -1797,9 +1791,7 @@ handle_delayed_aux_work_wakeup(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, in
{
int jix, max_jix;
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
ASSERT(awdp->delayed_wakeup.next != ERTS_DELAYED_WAKEUP_INFINITY);
@@ -1956,9 +1948,8 @@ handle_misc_aux_work_thr_prgr(ErtsAuxWorkData *awdp,
erts_aint32_t aux_work,
int waiting)
{
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
if (!erts_thr_progress_has_reached_this(haw_thr_prgr_current(awdp),
awdp->misc.thr_prgr))
return aux_work & ~ERTS_SSI_AUX_WORK_MISC_THR_PRGR;
@@ -2011,9 +2002,9 @@ erts_schedule_multi_misc_aux_work(int ignore_self,
if (ignore_self) {
ErtsSchedulerData *esdp = erts_get_scheduler_data();
-#ifdef ERTS_DIRTY_SCHEDULERS
+
ASSERT(!ERTS_SCHEDULER_IS_DIRTY(esdp));
-#endif
+
if (esdp)
self = (int) esdp->no;
}
@@ -2043,9 +2034,9 @@ handle_async_ready(ErtsAuxWorkData *awdp,
int waiting)
{
ErtsSchedulerSleepInfo *ssi = awdp->ssi;
-#ifdef ERTS_DIRTY_SCHEDULERS
+
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY);
if (erts_check_async_ready(awdp->async_ready.queue)) {
if (set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY)
@@ -2070,9 +2061,8 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp,
{
void *thr_prgr_p;
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
#ifdef ERTS_SMP
if (awdp->async_ready.need_thr_prgr
&& !erts_thr_progress_has_reached_this(haw_thr_prgr_current(awdp),
@@ -2110,9 +2100,8 @@ handle_fix_alloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting)
ErtsSchedulerSleepInfo *ssi = awdp->ssi;
erts_aint32_t res;
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
unset_aux_work_flags(ssi, (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
| ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC));
aux_work &= ~(ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
@@ -2160,9 +2149,9 @@ handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waitin
ErtsThrPrgrVal wakeup = ERTS_THR_PRGR_INVALID;
int more_work = 0;
ERTS_MSACC_PUSH_STATE_M_X();
-#ifdef ERTS_DIRTY_SCHEDULERS
+
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD);
ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_ALLOC);
erts_alloc_scheduler_handle_delayed_dealloc((void *) awdp->esdp,
@@ -2199,9 +2188,8 @@ handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, i
ErtsThrPrgrVal wakeup = ERTS_THR_PRGR_INVALID;
ErtsThrPrgrVal current = haw_thr_prgr_current(awdp);
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
if (!erts_thr_progress_has_reached_this(current, awdp->dd.thr_prgr))
return aux_work & ~ERTS_SSI_AUX_WORK_DD_THR_PRGR;
@@ -2258,9 +2246,8 @@ handle_canceled_timers(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waitin
ErtsThrPrgrVal wakeup = ERTS_THR_PRGR_INVALID;
int more_work = 0;
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_CNCLD_TMRS);
erts_handle_canceled_timers((void *) awdp->esdp,
&need_thr_progress,
@@ -2294,9 +2281,8 @@ handle_canceled_timers_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, i
ErtsThrPrgrVal wakeup = ERTS_THR_PRGR_INVALID;
ErtsThrPrgrVal current = haw_thr_prgr_current(awdp);
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
if (!erts_thr_progress_has_reached_this(current, awdp->cncld_tmrs.thr_prgr))
return aux_work & ~ERTS_SSI_AUX_WORK_CNCLD_TMRS_THR_PRGR;
@@ -2339,9 +2325,8 @@ handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int wait
int lops;
ErtsThrPrgrVal current = haw_thr_prgr_current(awdp);
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
+
for (lops = 0; lops < ERTS_MAX_THR_PRGR_LATER_OPS; lops++) {
ErtsThrPrgrLaterOp *lop = awdp->later_op.first;
@@ -2371,7 +2356,7 @@ enqueue_later_op(ErtsSchedulerData *esdp,
ErtsThrPrgrLaterOp *lop)
{
ErtsThrPrgrVal later = erts_thr_progress_later(esdp);
- ASSERT(esdp);
+ ASSERT(esdp && !ERTS_SCHEDULER_IS_DIRTY(esdp));
lop->func = later_func;
lop->data = later_data;
@@ -2424,9 +2409,7 @@ handle_debug_wait_completed(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int w
ErtsSchedulerSleepInfo *ssi = awdp->ssi;
erts_aint32_t saved_aux_work, flags;
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
-#endif
flags = awdp->debug.wait_completed.flags;
@@ -3008,9 +2991,9 @@ static ERTS_INLINE void
sched_active_sys(Uint no, ErtsRunQueue *rq)
{
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
-#ifdef ERTS_DIRTY_SCHEDULERS
+
ASSERT(!ERTS_RUNQ_IX_IS_DIRTY(rq->ix));
-#endif
+
ASSERT(rq->waiting < 0);
rq->waiting *= -1;
rq->waiting--;
@@ -3075,9 +3058,9 @@ static ERTS_INLINE void
sched_change_waiting_sys_to_waiting(Uint no, ErtsRunQueue *rq)
{
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
-#ifdef ERTS_DIRTY_SCHEDULERS
+
ASSERT(!ERTS_RUNQ_IX_IS_DIRTY(rq->ix));
-#endif
+
ASSERT(rq->waiting < 0);
rq->waiting *= -1;
}
@@ -3586,9 +3569,8 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
erts_smp_atomic32_set_relb(&function_calls, 0);
*fcalls = 0;
-#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!ERTS_SCHEDULER_IS_DIRTY(esdp));
-#endif
+
sched_waiting_sys(esdp->no, rq);
erts_smp_runq_unlock(rq);
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 44613c7d85..4ce86ce949 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -160,26 +160,19 @@ is_tuple Fail=f S | select_tuple_arity S=d Fail=f Size=u Rest=* => \
select_tuple_arity S=d Fail=f Size=u Rest=* => \
gen_select_tuple_arity(S, Fail, Size, Rest)
-i_select_val_bins x f I
-i_select_val_bins y f I
+i_select_val_bins xy f I
-i_select_val_lins x f I
-i_select_val_lins y f I
+i_select_val_lins xy f I
-i_select_val2 x f c c f f
-i_select_val2 y f c c f f
+i_select_val2 xy f c c f f
-i_select_tuple_arity x f I
-i_select_tuple_arity y f I
+i_select_tuple_arity xy f I
-i_select_tuple_arity2 x f A A f f
-i_select_tuple_arity2 y f A A f f
+i_select_tuple_arity2 xy f A A f f
-i_jump_on_val_zero x f I
-i_jump_on_val_zero y f I
+i_jump_on_val_zero xy f I
-i_jump_on_val x f I I
-i_jump_on_val y f I I
+i_jump_on_val xy f I I
%macro: get_list GetList -pack
get_list xy xy xy
@@ -448,19 +441,14 @@ is_ne_exact Lbl R=xy C=ian => i_is_ne_exact_immed Lbl R C
is_ne_exact Lbl R=xy C=q => i_is_ne_exact_literal Lbl R C
%macro: i_is_eq_exact_immed EqualImmed -fail_action
-i_is_eq_exact_immed f r c
-i_is_eq_exact_immed f x c
-i_is_eq_exact_immed f y c
-i_is_eq_exact_literal f x c
-i_is_eq_exact_literal f y c
+i_is_eq_exact_immed f rxy c
+i_is_eq_exact_literal f xy c
%macro: i_is_ne_exact_immed NotEqualImmed -fail_action
-i_is_ne_exact_immed f x c
-i_is_ne_exact_immed f y c
+i_is_ne_exact_immed f xy c
-i_is_ne_exact_literal f x c
-i_is_ne_exact_literal f y c
+i_is_ne_exact_literal f xy c
is_eq_exact Lbl Y=y X=x => is_eq_exact Lbl X Y
%macro: is_eq_exact EqualExact -fail_action -pack
@@ -508,8 +496,7 @@ i_put_tuple Dst Arity Puts=* | put S => \
i_put_tuple/2
%macro:i_put_tuple PutTuple -pack -goto:do_put_tuple
-i_put_tuple x I
-i_put_tuple y I
+i_put_tuple xy I
#
# The instruction "put_list Const [] Dst" were generated in rare
@@ -578,17 +565,12 @@ return_trace
move S x==0 | return => move_return S
%macro: move_return MoveReturn -nonext
-move_return x
-move_return c
-move_return n
+move_return xcn
move S x==0 | deallocate D | return => move_deallocate_return S D
%macro: move_deallocate_return MoveDeallocateReturn -pack -nonext
-move_deallocate_return x Q
-move_deallocate_return y Q
-move_deallocate_return c Q
-move_deallocate_return n Q
+move_deallocate_return xycn Q
deallocate D | return => deallocate_return D
@@ -1142,7 +1124,7 @@ func_info M F A => i_func_info u M F A
%cold
bs_start_match2 Fail=f ica X Y D => jump Fail
bs_start_match2 Fail Bin X Y D => i_bs_start_match2 Bin Fail X Y D
-i_bs_start_match2 xy f I I d
+i_bs_start_match2 xy f I I x
bs_save2 Reg Index => gen_bs_save(Reg, Index)
i_bs_save2 x I
@@ -1159,12 +1141,12 @@ i_bs_match_string x f I I
bs_get_integer2 Fail=f Ms=x Live=u Sz=sq Unit=u Flags=u Dst=d => \
gen_get_integer2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
-i_bs_get_integer_small_imm x I f I d
-i_bs_get_integer_imm x I I f I d
-i_bs_get_integer f I I s s d
-i_bs_get_integer_8 x f d
-i_bs_get_integer_16 x f d
-i_bs_get_integer_32 x f I d
+i_bs_get_integer_small_imm x I f I x
+i_bs_get_integer_imm x I I f I x
+i_bs_get_integer f I I s s x
+i_bs_get_integer_8 x f x
+i_bs_get_integer_16 x f x
+i_bs_get_integer_32 x f I x
# Fetching binaries from binaries.
bs_get_binary2 Fail=f Ms=x Live=u Sz=sq Unit=u Flags=u Dst=d => \
@@ -1222,14 +1204,14 @@ bs_context_to_binary x
# Utf8/utf16/utf32 support. (R12B-5)
#
bs_get_utf8 Fail=f Ms=x u u Dst=d => i_bs_get_utf8 Ms Fail Dst
-i_bs_get_utf8 x f d
+i_bs_get_utf8 x f x
bs_skip_utf8 Fail=f Ms=x u u => i_bs_get_utf8 Ms Fail x
bs_get_utf16 Fail=f Ms=x u Flags=u Dst=d => i_bs_get_utf16 Ms Fail Flags Dst
bs_skip_utf16 Fail=f Ms=x u Flags=u => i_bs_get_utf16 Ms Fail Flags x
-i_bs_get_utf16 x f I d
+i_bs_get_utf16 x f I x
bs_get_utf32 Fail=f Ms=x Live=u Flags=u Dst=d => \
bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst | \
@@ -1262,15 +1244,15 @@ bs_init2 Fail Sz Words=u==0 Regs Flags Dst => \
bs_init2 Fail Sz Words Regs Flags Dst => \
i_bs_init_fail_heap Sz Words Fail Regs Dst
-i_bs_init_fail xy j I d
+i_bs_init_fail xy j I x
-i_bs_init_fail_heap s I j I d
+i_bs_init_fail_heap s I j I x
-i_bs_init I I d
-i_bs_init_heap_bin I I d
+i_bs_init I I x
+i_bs_init_heap_bin I I x
-i_bs_init_heap I I I d
-i_bs_init_heap_bin_heap I I I d
+i_bs_init_heap I I I x
+i_bs_init_heap_bin_heap I I I x
bs_init_bits Fail Sz=o Words Regs Flags Dst => system_limit Fail
@@ -1283,16 +1265,16 @@ bs_init_bits Fail Sz Words=u==0 Regs Flags Dst => \
bs_init_bits Fail Sz Words Regs Flags Dst => \
i_bs_init_bits_fail_heap Sz Words Fail Regs Dst
-i_bs_init_bits_fail xy j I d
+i_bs_init_bits_fail xy j I x
-i_bs_init_bits_fail_heap s I j I d
+i_bs_init_bits_fail_heap s I j I x
-i_bs_init_bits I I d
-i_bs_init_bits_heap I I I d
+i_bs_init_bits I I x
+i_bs_init_bits_heap I I I x
bs_add Fail S1=i==0 S2 Unit=u==1 D => move S2 D
-bs_add j s s I d
+bs_add j s s I x
bs_append Fail Size Extra Live Unit Bin Flags Dst => \
move Bin x | i_bs_append Fail Extra Live Unit Size Dst
@@ -1302,8 +1284,8 @@ bs_private_append Fail Size Unit Bin Flags Dst => \
bs_init_writable
-i_bs_append j I I I s d
-i_bs_private_append j I s s d
+i_bs_append j I I I s x
+i_bs_private_append j I s s x
#
# Storing integers into binaries.
@@ -1324,11 +1306,11 @@ i_new_bs_put_integer_imm j I I s
bs_utf8_size j Src=s Dst=d => i_bs_utf8_size Src Dst
-i_bs_utf8_size s d
+i_bs_utf8_size s x
bs_utf16_size j Src=s Dst=d => i_bs_utf16_size Src Dst
-i_bs_utf16_size s d
+i_bs_utf16_size s x
bs_put_utf8 Fail u Src=s => i_bs_put_utf8 Fail Src
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index b6c77794d2..e8615d1140 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -21,7 +21,7 @@
#ifndef __SYS_H__
#define __SYS_H__
-#if !defined(__GNUC__)
+#if !defined(__GNUC__) || defined(__e2k__)
# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) 0
#elif !defined(__GNUC_MINOR__)
# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index ae650546e5..20cb3343fb 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -2505,8 +2505,46 @@ cexpr(#ifun{anno=#a{us=Us0}=A0,name={named,Name},fc=#iclause{pats=Ps}}=Fun0,
end;
cexpr(#iapply{anno=A,op=Op,args=Args}, _As, St) ->
{#c_apply{anno=A#a.anno,op=Op,args=Args},[],A#a.us,St};
-cexpr(#icall{anno=A,module=Mod,name=Name,args=Args}, _As, St) ->
- {#c_call{anno=A#a.anno,module=Mod,name=Name,args=Args},[],A#a.us,St};
+cexpr(#icall{anno=A,module=Mod,name=Name,args=Args}, _As, St0) ->
+ Anno = A#a.anno,
+ case (not cerl:is_c_atom(Mod)) andalso member(tuple_calls, St0#core.opts) of
+ true ->
+ GenAnno = [compiler_generated|Anno],
+
+ %% Generate the clause that matches on the tuple
+ {TupleVar,St1} = new_var(GenAnno, St0),
+ {TupleSizeVar, St2} = new_var(GenAnno, St1),
+ {TupleModVar, St3} = new_var(GenAnno, St2),
+ {TupleArgsVar, St4} = new_var(GenAnno, St3),
+ TryVar = cerl:c_var('Try'),
+
+ TupleGuardExpr =
+ cerl:c_let([TupleSizeVar],
+ c_call_erl(tuple_size, [TupleVar]),
+ c_call_erl('>', [TupleSizeVar, cerl:c_int(0)])),
+
+ TupleGuard =
+ cerl:c_try(TupleGuardExpr, [TryVar], TryVar,
+ [cerl:c_var('T'),cerl:c_var('R')], cerl:c_atom(false)),
+
+ TupleApply =
+ cerl:c_let([TupleModVar],
+ c_call_erl(element, [cerl:c_int(1),TupleVar]),
+ cerl:c_let([TupleArgsVar],
+ cerl:make_list(Args ++ [TupleVar]),
+ c_call_erl(apply, [TupleModVar,Name,TupleArgsVar]))),
+
+ TupleClause = cerl:ann_c_clause(GenAnno, [TupleVar], TupleGuard, TupleApply),
+
+ %% Generate the fallback clause
+ {OtherVar,St5} = new_var(GenAnno, St4),
+ OtherApply = cerl:ann_c_call(GenAnno, OtherVar, Name, Args),
+ OtherClause = cerl:ann_c_clause(GenAnno, [OtherVar], OtherApply),
+
+ {cerl:ann_c_case(GenAnno, Mod, [TupleClause,OtherClause]),[],A#a.us,St5};
+ false ->
+ {#c_call{anno=Anno,module=Mod,name=Name,args=Args},[],A#a.us,St0}
+ end;
cexpr(#iprimop{anno=A,name=Name,args=Args}, _As, St) ->
{#c_primop{anno=A#a.anno,name=Name,args=Args},[],A#a.us,St};
cexpr(#iprotect{anno=A,body=Es}, _As, St0) ->
@@ -2536,6 +2574,9 @@ cfun(#ifun{anno=A,id=Id,vars=Args,clauses=Lcs,fc=Lfc}, _As, St0) ->
clauses=Ccs ++ [Cfc]}},
[],A#a.us,St2}.
+c_call_erl(Fun, Args) ->
+ cerl:c_call(cerl:c_atom(erlang), cerl:c_atom(Fun), Args).
+
%% lit_vars(Literal) -> [Var].
lit_vars(Lit) -> lit_vars(Lit, []).
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index f647a4030d..aaa2005e73 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -32,7 +32,7 @@
binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1,
other_output/1, kernel_listing/1, encrypted_abstr/1,
strict_record/1, utf8_atoms/1, utf8_functions/1, extra_chunks/1,
- cover/1, env/1, core_pp/1,
+ cover/1, env/1, core_pp/1, tuple_calls/1,
core_roundtrip/1, asm/1, optimized_guards/1,
sys_pre_attributes/1, dialyzer/1,
warnings/1, pre_load_check/1, env_compiler_options/1,
@@ -49,7 +49,7 @@ all() ->
test_lib:recompile(?MODULE),
[app_test, appup_test, file_1, forms_2, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
- other_output, kernel_listing, encrypted_abstr,
+ other_output, kernel_listing, encrypted_abstr, tuple_calls,
strict_record, utf8_atoms, utf8_functions, extra_chunks,
cover, env, core_pp, core_roundtrip, asm, optimized_guards,
sys_pre_attributes, dialyzer, warnings, pre_load_check,
@@ -781,6 +781,37 @@ extra_chunks(Config) when is_list(Config) ->
{ok,{extra_chunks,[{"ExCh",<<"Contents">>}]}} =
beam_lib:chunks(ExtraChunksBinary, ["ExCh"]).
+tuple_calls(Config) when is_list(Config) ->
+ Anno = erl_anno:new(1),
+ Forms = [{attribute,Anno,export,[{size,1},{store,1}]},
+ {function,Anno,size,1,
+ [{clause,Anno,[{var,[],mod}],[],
+ [{call,[],{remote,[],{var,[],mod},{atom,[],size}},[]}]}]},
+ {function,Anno,store,1,
+ [{clause,Anno,[{var,[],mod}],[],
+ [{call,[],{remote,[],{var,[],mod},{atom,[],store}},[{atom,[],key},{atom,[],value}]}]}]}],
+
+ TupleCallsFalse = [{attribute,Anno,module,tuple_calls_false}|Forms],
+ {ok,_,TupleCallsFalseBinary} = compile:forms(TupleCallsFalse, [binary]),
+ code:load_binary(tuple_calls_false, "compile_SUITE.erl", TupleCallsFalseBinary),
+ {'EXIT',{badarg,_}} = (catch tuple_calls_false:store(dict())),
+ {'EXIT',{badarg,_}} = (catch tuple_calls_false:size(dict())),
+ {'EXIT',{badarg,_}} = (catch tuple_calls_false:size(empty_tuple())),
+
+ TupleCallsTrue = [{attribute,Anno,module,tuple_calls_true}|Forms],
+ {ok,_,TupleCallsTrueBinary} = compile:forms(TupleCallsTrue, [binary,tuple_calls]),
+ code:load_binary(tuple_calls_true, "compile_SUITE.erl", TupleCallsTrueBinary),
+ Dict = tuple_calls_true:store(dict()),
+ 1 = tuple_calls_true:size(Dict),
+ {'EXIT',{badarg,_}} = (catch tuple_calls_true:size(empty_tuple())),
+
+ ok.
+
+dict() ->
+ dict:new().
+empty_tuple() ->
+ {}.
+
env(Config) when is_list(Config) ->
{Simple,Target} = get_files(Config, simple, env),
{ok,Cwd} = file:get_cwd(),
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index 511a6d66bf..6e501f32b2 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -120,92 +120,10 @@ get_core_from_beam(File, Opts) ->
{error, " Could not get Core Erlang code for: " ++ File ++ "\n"}
end;
_ ->
- deprecated_get_core_from_beam(File, Opts)
+ {error, " Could not get Core Erlang code for: " ++ File ++ "\n" ++
+ " Recompile with +debug_info or analyze starting from source code"}
end.
-deprecated_get_core_from_beam(File, Opts) ->
- case get_abstract_code_from_beam(File) of
- error ->
- {error, " Could not get abstract code for: " ++ File ++ "\n" ++
- " Recompile with +debug_info or analyze starting from source code"};
- {ok, AbstrCode} ->
- case get_compile_options_from_beam(File) of
- error ->
- {error, " Could not get compile options for: " ++ File ++ "\n" ++
- " Recompile or analyze starting from source code"};
- {ok, CompOpts} ->
- case get_core_from_abstract_code(AbstrCode, Opts ++ CompOpts) of
- error ->
- {error, " Could not get core Erlang code for: " ++ File};
- {ok, _} = Core ->
- Core
- end
- end
- end.
-
-get_abstract_code_from_beam(File) ->
- case beam_lib:chunks(File, [abstract_code]) of
- {ok, {_, List}} ->
- case lists:keyfind(abstract_code, 1, List) of
- {abstract_code, {raw_abstract_v1, Abstr}} -> {ok, Abstr};
- _ -> error
- end;
- _ ->
- %% No or unsuitable abstract code.
- error
- end.
-
-get_compile_options_from_beam(File) ->
- case beam_lib:chunks(File, [compile_info]) of
- {ok, {_, List}} ->
- case lists:keyfind(compile_info, 1, List) of
- {compile_info, CompInfo} -> compile_info_to_options(CompInfo);
- _ -> error
- end;
- _ ->
- %% No or unsuitable compile info.
- error
- end.
-
-compile_info_to_options(CompInfo) ->
- case lists:keyfind(options, 1, CompInfo) of
- {options, CompOpts} -> {ok, CompOpts};
- _ -> error
- end.
-
-get_core_from_abstract_code(AbstrCode, Opts) ->
- %% We do not want the parse_transforms around since we already
- %% performed them. In some cases we end up in trouble when
- %% performing them again.
- AbstrCode1 = cleanup_parse_transforms(AbstrCode),
- %% Remove parse_transforms (and other options) from compile options.
- Opts2 = cleanup_compile_options(Opts),
- try compile:noenv_forms(AbstrCode1, Opts2 ++ src_compiler_opts()) of
- {ok, _, Core} -> {ok, Core};
- _What -> error
- catch
- error:_ -> error
- end.
-
-cleanup_parse_transforms([{attribute, _, compile, {parse_transform, _}}|Left]) ->
- cleanup_parse_transforms(Left);
-cleanup_parse_transforms([Other|Left]) ->
- [Other|cleanup_parse_transforms(Left)];
-cleanup_parse_transforms([]) ->
- [].
-
-cleanup_compile_options(Opts) ->
- lists:filter(fun keep_compile_option/1, Opts).
-
-%% Using abstract, not asm or core.
-keep_compile_option(from_asm) -> false;
-keep_compile_option(from_core) -> false;
-%% The parse transform will already have been applied, may cause
-%% problems if it is re-applied.
-keep_compile_option({parse_transform, _}) -> false;
-keep_compile_option(warnings_as_errors) -> false;
-keep_compile_option(_) -> true.
-
%% ============================================================================
%%
%% Typed Records