diff options
Diffstat (limited to 'erts/emulator/beam/beam_emu.c')
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 425 |
1 files changed, 211 insertions, 214 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index bc83699951..25e16764ab 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -62,33 +62,27 @@ #endif #ifdef ERTS_ENABLE_LOCK_CHECK -# ifdef ERTS_SMP # define PROCESS_MAIN_CHK_LOCKS(P) \ do { \ if ((P)) \ erts_proc_lc_chk_only_proc_main((P)); \ - ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking()); \ + ERTS_LC_ASSERT(!erts_thr_progress_is_blocking()); \ } while (0) -# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P) \ +# define ERTS_REQ_PROC_MAIN_LOCK(P) \ do { \ if ((P)) \ erts_proc_lc_require_lock((P), ERTS_PROC_LOCK_MAIN, \ __FILE__, __LINE__); \ } while (0) -# define ERTS_SMP_UNREQ_PROC_MAIN_LOCK(P) \ +# define ERTS_UNREQ_PROC_MAIN_LOCK(P) \ do { \ if ((P)) \ erts_proc_lc_unrequire_lock((P), ERTS_PROC_LOCK_MAIN); \ } while (0) -# else -# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P) -# define ERTS_SMP_UNREQ_PROC_MAIN_LOCK(P) -# define PROCESS_MAIN_CHK_LOCKS(P) erts_lc_check_exact(NULL, 0) -# endif #else # define PROCESS_MAIN_CHK_LOCKS(P) -# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P) -# define ERTS_SMP_UNREQ_PROC_MAIN_LOCK(P) +# define ERTS_REQ_PROC_MAIN_LOCK(P) +# define ERTS_UNREQ_PROC_MAIN_LOCK(P) #endif /* @@ -204,6 +198,21 @@ do { \ #define ISCATCHEND(instr) ((Eterm *) *(instr) == OpCode(catch_end_y)) +#define BIF_ERROR_ARITY_1(Op1, BIF) \ + if (Arg(0) != 0) goto jump_f; \ + reg[0] = Op1; \ + SWAPOUT; \ + I = handle_error(c_p, I, reg, &bif_export[BIF]->info.mfa); \ + goto post_error_handling + +#define BIF_ERROR_ARITY_2(Op1, Op2, BIF) \ + if (Arg(0) != 0) goto jump_f; \ + reg[0] = Op1; \ + reg[1] = Op2; \ + SWAPOUT; \ + I = handle_error(c_p, I, reg, &bif_export[BIF]->info.mfa); \ + goto post_error_handling + /* * Special Beam instructions. */ @@ -285,7 +294,7 @@ void** beam_ops; HEAP_TOP((P)) = HTOP; \ (P)->stop = E; \ PROCESS_MAIN_CHK_LOCKS((P)); \ - ERTS_SMP_UNREQ_PROC_MAIN_LOCK((P)) + ERTS_UNREQ_PROC_MAIN_LOCK((P)) #define db(N) (N) #define tb(N) (N) @@ -1080,6 +1089,7 @@ static BeamInstr* apply_fun(Process* p, Eterm fun, static Eterm new_fun(Process* p, Eterm* reg, ErlFunEntry* fe, int num_free) NOINLINE; static Eterm new_map(Process* p, Eterm* reg, BeamInstr* I) NOINLINE; +static Eterm new_small_map_lit(Process* p, Eterm* reg, Uint* n_exp, BeamInstr* I) NOINLINE; static Eterm update_map_assoc(Process* p, Eterm* reg, Eterm map, BeamInstr* I) NOINLINE; static Eterm update_map_exact(Process* p, Eterm* reg, @@ -1348,16 +1358,16 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) } PROCESS_MAIN_CHK_LOCKS(c_p); - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); c_p = erts_schedule(NULL, c_p, reds_used); ASSERT(!(c_p->flags & F_HIPE_MODE)); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); start_time = 0; #ifdef DEBUG - pid = c_p->common.id; /* Save for debugging purpouses */ + pid = c_p->common.id; /* Save for debugging purposes */ #endif - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); ERTS_MSACC_UPDATE_CACHE_X(); @@ -1485,7 +1495,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) goto find_func_info; } -#define DO_OUTLINED_ARITH_2(name, Op1, Op2) \ +#define DO_OUTLINED_ARITH_2(name, Op1, Op2, BIF)\ do { \ Eterm result; \ Uint live = Arg(1); \ @@ -1499,7 +1509,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) if (is_value(result)) { \ StoreBifResult(4, result); \ } \ - goto lb_Cl_error; \ + BIF_ERROR_ARITY_2(reg[live], reg[live+1], BIF);\ } while (0) { @@ -1529,7 +1539,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) StoreBifResult(4, result); } } - DO_OUTLINED_ARITH_2(mixed_plus, PlusOp1, PlusOp2); + DO_OUTLINED_ARITH_2(mixed_plus, PlusOp1, PlusOp2, BIF_splus_2); } { @@ -1554,7 +1564,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) StoreBifResult(4, result); } } - DO_OUTLINED_ARITH_2(mixed_minus, MinusOp1, MinusOp2); + DO_OUTLINED_ARITH_2(mixed_minus, MinusOp1, MinusOp2, BIF_sminus_2); } { @@ -1730,7 +1740,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) result = erl_send(c_p, r(0), x(1)); PreFetch(0, next); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); HTOP = HEAP_TOP(c_p); FCALLS = c_p->fcalls; @@ -1770,8 +1780,9 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) StoreBifResult(3, result); } } + c_p->freason = BADARG; + BIF_ERROR_ARITY_2(element_index, element_tuple, BIF_element_2); } - /* Fall through */ OpCase(badarg_j): badarg: @@ -1798,7 +1809,8 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) StoreBifResult(3, result); } } - goto badarg; + c_p->freason = BADARG; + BIF_ERROR_ARITY_2(make_small(Arg(2)), fast_element_tuple, BIF_element_2); } OpCase(catch_yf): @@ -1925,22 +1937,20 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) msgp = PEEK_MESSAGE(c_p); if (!msgp) { -#ifdef ERTS_SMP - erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); /* Make sure messages wont pass exit signals... */ if (ERTS_PROC_PENDING_EXIT(c_p)) { - erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); SWAPOUT; c_p->flags &= ~F_DELAY_GC; c_p->arity = 0; goto do_schedule; /* Will be rescheduled for exit */ } - ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p); + ERTS_MSGQ_MV_INQ2PRIVQ(c_p); msgp = PEEK_MESSAGE(c_p); if (msgp) - erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); else -#endif { c_p->flags &= ~F_DELAY_GC; SET_I((BeamInstr *) Arg(0)); @@ -2105,7 +2115,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) OpCase(i_wait_timeout_fs): { - erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); /* Fall through */ } @@ -2138,7 +2148,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) } else { /* Wrong time */ OpCase(i_wait_error_locked): { - erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); /* Fall through */ } OpCase(i_wait_error): { @@ -2162,46 +2172,29 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) OpCase(wait_f): wait2: { -#ifndef ERTS_SMP - if (ERTS_PROC_IS_EXITING(c_p)) { - /* - * I non smp case: - * - * Currently executing process might be sent an exit - * signal if it is traced by a port that it also is - * linked to, and the port terminates during the - * trace. In this case we do *not* want to clear - * the active flag, which will make the process hang - * in limbo forever. - */ - SWAPOUT; - c_p->arity = 0; - goto do_schedule; - } -#endif c_p->i = (BeamInstr *) Arg(0); /* L1 */ SWAPOUT; c_p->arity = 0; if (!ERTS_PTMR_IS_TIMED_OUT(c_p)) - erts_smp_atomic32_read_band_relb(&c_p->state, + erts_atomic32_read_band_relb(&c_p->state, ~ERTS_PSFLG_ACTIVE); ASSERT(!ERTS_PROC_IS_EXITING(c_p)); - erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); c_p->current = NULL; goto do_schedule; } OpCase(wait_unlocked_f): { - erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); goto wait2; } } - erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); Next(2); } OpCase(i_wait_timeout_fI): { - erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); } OpCase(i_wait_timeout_locked_fI): @@ -2223,7 +2216,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) * receive statement will examine the first message first. */ OpCase(timeout_locked): { - erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); + erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); } OpCase(timeout): { @@ -2461,6 +2454,17 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) Next(3+Arg(2)); } + OpCase(i_new_small_map_lit_dIq): { + Eterm res; + Uint n; + + HEAVY_SWAPOUT; + res = new_small_map_lit(c_p, reg, &n, I-1); + HEAVY_SWAPIN; + StoreResult(res, Arg(0)); + Next(3+n); + } + #define PUT_TERM_REG(term, desc) \ do { \ switch (loader_tag(desc)) { \ @@ -2668,12 +2672,12 @@ do { \ c_p->fcalls = FCALLS; SWAPOUT; PROCESS_MAIN_CHK_LOCKS(c_p); - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); ERTS_CHK_MBUF_SZ(c_p); result = (*bf)(c_p, reg, live); ERTS_CHK_MBUF_SZ(c_p); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); SWAPIN; ERTS_HOLE_CHECK(c_p); @@ -2711,12 +2715,12 @@ do { \ c_p->fcalls = FCALLS; SWAPOUT; PROCESS_MAIN_CHK_LOCKS(c_p); - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); ERTS_CHK_MBUF_SZ(c_p); result = (*bf)(c_p, reg, live); ERTS_CHK_MBUF_SZ(c_p); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); SWAPIN; ERTS_HOLE_CHECK(c_p); @@ -2756,12 +2760,12 @@ do { \ c_p->fcalls = FCALLS; SWAPOUT; PROCESS_MAIN_CHK_LOCKS(c_p); - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); ERTS_CHK_MBUF_SZ(c_p); result = (*bf)(c_p, reg, live); ERTS_CHK_MBUF_SZ(c_p); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); SWAPIN; ERTS_HOLE_CHECK(c_p); @@ -2886,7 +2890,7 @@ do { \ ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result)); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); ERTS_HOLE_CHECK(c_p); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); if (ERTS_IS_GC_DESIRED(c_p)) { Uint arity = GET_BIF_ARITY(export); result = erts_gc_after_bif_call_lhf(c_p, live_hf_end, result, reg, arity); @@ -2929,14 +2933,14 @@ do { \ { Eterm Op1, Op2; GetArg2(2, Op1, Op2); - DO_OUTLINED_ARITH_2(mixed_times, Op1, Op2); + DO_OUTLINED_ARITH_2(mixed_times, Op1, Op2, BIF_stimes_2); } OpCase(i_m_div_jIssd): { Eterm Op1, Op2; GetArg2(2, Op1, Op2); - DO_OUTLINED_ARITH_2(mixed_div, Op1, Op2); + DO_OUTLINED_ARITH_2(mixed_div, Op1, Op2, BIF_div_2); } OpCase(i_int_div_jIssd): @@ -2945,7 +2949,8 @@ do { \ GetArg2(2, Op1, Op2); if (Op2 == SMALL_ZERO) { - goto badarith; + c_p->freason = BADARITH; + BIF_ERROR_ARITY_2(Op1, Op2, BIF_intdiv_2); } else if (is_both_small(Op1, Op2)) { Sint ires = signed_val(Op1) / signed_val(Op2); if (MY_IS_SSMALL(ires)) { @@ -2953,7 +2958,7 @@ do { \ StoreBifResult(4, result); } } - DO_OUTLINED_ARITH_2(int_div, Op1, Op2); + DO_OUTLINED_ARITH_2(int_div, Op1, Op2, BIF_intdiv_2); } { @@ -2970,12 +2975,13 @@ do { \ do_rem: if (RemOp2 == SMALL_ZERO) { - goto badarith; + c_p->freason = BADARITH; + BIF_ERROR_ARITY_2(RemOp1, RemOp2, BIF_rem_2); } else if (is_both_small(RemOp1, RemOp2)) { Eterm result = make_small(signed_val(RemOp1) % signed_val(RemOp2)); StoreBifResult(4, result); } else { - DO_OUTLINED_ARITH_2(int_rem, RemOp1, RemOp2); + DO_OUTLINED_ARITH_2(int_rem, RemOp1, RemOp2, BIF_rem_2); } } @@ -2999,7 +3005,7 @@ do { \ Eterm result = BandOp1 & BandOp2; StoreBifResult(4, result); } - DO_OUTLINED_ARITH_2(band, BandOp1, BandOp2); + DO_OUTLINED_ARITH_2(band, BandOp1, BandOp2, BIF_band_2); } /* @@ -3032,7 +3038,7 @@ do { \ Eterm result = Op1 | Op2; StoreBifResult(4, result); } - DO_OUTLINED_ARITH_2(bor, Op1, Op2); + DO_OUTLINED_ARITH_2(bor, Op1, Op2, BIF_bor_2); } OpCase(i_bxor_jIssd): @@ -3050,7 +3056,7 @@ do { \ Eterm result = (Op1 ^ Op2) | make_small(0); StoreBifResult(4, result); } - DO_OUTLINED_ARITH_2(bxor, Op1, Op2); + DO_OUTLINED_ARITH_2(bxor, Op1, Op2, BIF_bxor_2); } { @@ -3081,8 +3087,9 @@ do { \ Op2 = make_small(bignum_header_is_neg(*big_val(Op2)) ? MAX_SMALL : MIN_SMALL); goto do_bsl; - } - goto badarith; + } + c_p->freason = BADARITH; + BIF_ERROR_ARITY_2(Op1, Op2, BIF_bsr_2); OpCase(i_bsl_jIssd): GetArg2(2, Op1, Op2); @@ -3182,10 +3189,8 @@ do { \ } /* Fall through if the left argument is not an integer. */ } - /* - * One or more non-integer arguments. - */ - goto badarith; + c_p->freason = BADARITH; + BIF_ERROR_ARITY_2(Op1, Op2, BIF_bsl_2); } OpCase(i_int_bnot_jsId): @@ -3203,16 +3208,12 @@ do { \ HEAVY_SWAPIN; ERTS_HOLE_CHECK(c_p); if (is_nil(bnot_val)) { - goto lb_Cl_error; + BIF_ERROR_ARITY_1(reg[live], BIF_bnot_1); } } StoreBifResult(3, bnot_val); } - badarith: - c_p->freason = BADARITH; - goto lb_Cl_error; - OpCase(i_apply): { BeamInstr *next; HEAVY_SWAPOUT; @@ -3399,7 +3400,7 @@ do { \ Eterm* argp; int i; - if (erts_smp_atomic32_read_nob(&c_p->state) & ERTS_PSFLG_EXITING) { + if (erts_atomic32_read_nob(&c_p->state) & ERTS_PSFLG_EXITING) { c_p->i = beam_exit; c_p->arity = 0; c_p->current = NULL; @@ -3475,16 +3476,16 @@ do { \ SWAPOUT; c_p->freason = EXC_NORMAL; c_p->arity = 0; /* In case this process will never be garbed again. */ - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); erts_do_exit_process(c_p, am_normal); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); goto do_schedule; } OpCase(continue_exit): { - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); erts_continue_exit_process(c_p); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); goto do_schedule; } @@ -3589,16 +3590,14 @@ do { \ PROCESS_MAIN_CHK_LOCKS(c_p); bif_nif_arity = codemfa->arity; - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); ASSERT(!ERTS_PROC_IS_EXITING(c_p)); { typedef Eterm NifF(struct enif_environment_t*, int argc, Eterm argv[]); NifF* fp = vbf = (NifF*) I[1]; struct enif_environment_t env; -#ifdef ERTS_SMP ASSERT(c_p->scheduler_data); -#endif live_hf_end = c_p->mbuf; ERTS_CHK_MBUF_SZ(c_p); erts_pre_nif(&env, c_p, (struct erl_module_nif*)I[2], NULL); @@ -3656,7 +3655,7 @@ do { \ PROCESS_MAIN_CHK_LOCKS(c_p); bif_nif_arity = codemfa->arity; ASSERT(bif_nif_arity <= 4); - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); { ErtsBifFunc bf = vbf; @@ -3679,7 +3678,7 @@ do { \ DTRACE_BIF_RETURN(c_p, codemfa); apply_bif_or_nif_epilogue: - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); ERTS_HOLE_CHECK(c_p); if (ERTS_IS_GC_DESIRED(c_p)) { nif_bif_result = erts_gc_after_bif_call_lhf(c_p, live_hf_end, @@ -3768,33 +3767,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 +3872,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 +3908,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 +3954,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 +3996,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 +4027,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 +4062,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 +4132,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 +4146,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 +4163,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 +4181,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 +4195,8 @@ do { \ } else { result = make_small(4); } - StoreBifResult(1, result); + xb(Arg(1)) = result; + Next(2); } OpCase(i_bs_put_utf8_js): { @@ -4211,7 +4217,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 +4225,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 +4320,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 +4337,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 +4404,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 +4419,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 +4444,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 +4480,8 @@ do { \ HEAP_SPACE_VERIFIED(0); } #endif - StoreBifResult(2, _result); + xb(Arg(2)) = _result; + Next(3); } } @@ -4479,7 +4489,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 +4501,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 +4526,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 +4569,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 +4592,8 @@ do { \ if (is_non_value(result)) { ClauseFail(); } - StoreBifResult(1, result); + xb(Arg(1)) = result; + Next(2); } } @@ -4588,7 +4601,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 +4616,8 @@ do { \ if (is_non_value(result)) { ClauseFail(); } - StoreBifResult(2, result); + xb(Arg(2)) = result; + Next(3); } } @@ -4737,9 +4751,9 @@ do { \ ErtsCodeMFA* mfa = (ErtsCodeMFA *)(E[0]); SWAPOUT; /* Needed for shared heap */ - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); erts_trace_return(c_p, mfa, r(0), ERTS_TRACER_FROM_ETERM(E+1)/* tracer */); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); SWAPIN; c_p->cp = NULL; SET_I((BeamInstr *) cp_val(E[2])); @@ -4780,9 +4794,9 @@ do { \ } else break; } SWAPOUT; /* Needed for shared heap */ - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); erts_trace_return_to(c_p, cp_val(*cpp)); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); SWAPIN; } c_p->cp = NULL; @@ -5317,7 +5331,7 @@ void erts_dirty_process_main(ErtsSchedulerData *esdp) } PROCESS_MAIN_CHK_LOCKS(c_p); - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); c_p = erts_schedule(esdp, c_p, reds_used); @@ -5331,7 +5345,7 @@ void erts_dirty_process_main(ErtsSchedulerData *esdp) #ifdef DEBUG pid = c_p->common.id; /* Save for debugging purposes */ #endif - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); ASSERT(!(c_p->flags & F_HIPE_MODE)); @@ -5346,7 +5360,7 @@ void erts_dirty_process_main(ErtsSchedulerData *esdp) else c_p->fcalls = CONTEXT_REDS; - if (erts_smp_atomic32_read_nob(&c_p->state) & ERTS_PSFLG_DIRTY_RUNNING_SYS) { + if (erts_atomic32_read_nob(&c_p->state) & ERTS_PSFLG_DIRTY_RUNNING_SYS) { erts_execute_dirty_system_task(c_p); goto do_dirty_schedule; } @@ -5417,7 +5431,7 @@ void erts_dirty_process_main(ErtsSchedulerData *esdp) c_p->current = codemfa; SWAPOUT; PROCESS_MAIN_CHK_LOCKS(c_p); - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); ASSERT(!ERTS_PROC_IS_EXITING(c_p)); if (em_apply_bif == (BeamInstr *) *I) { @@ -5431,7 +5445,7 @@ void erts_dirty_process_main(ErtsSchedulerData *esdp) ASSERT(!(c_p->flags & F_HIBERNATE_SCHED)); PROCESS_MAIN_CHK_LOCKS(c_p); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_EMULATOR); if (exiting) @@ -5610,9 +5624,9 @@ handle_error(Process* c_p, BeamInstr* pc, Eterm* reg, ErtsCodeMFA *bif_mfa) } if (c_p->catches > 0) erts_exit(ERTS_ERROR_EXIT, "Catch not found"); } - ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); + ERTS_UNREQ_PROC_MAIN_LOCK(c_p); terminate_proc(c_p, Value); - ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); return NULL; } @@ -6354,7 +6368,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 +6391,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 +6427,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 +6444,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 +6482,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) @@ -6526,22 +6512,6 @@ erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* re int arity; Eterm tmp; -#ifndef ERTS_SMP - if (ERTS_PROC_IS_EXITING(c_p)) { - /* - * I non smp case: - * - * Currently executing process might be sent an exit - * signal if it is traced by a port that it also is - * linked to, and the port terminates during the - * trace. In this case we do *not* want to clear - * the active flag, which will make the process hang - * in limbo forever. Get out of here and terminate - * the process... - */ - return -1; - } -#endif if (is_not_atom(module) || is_not_atom(function)) { /* @@ -6609,33 +6579,22 @@ erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* re * If there are no waiting messages, garbage collect and * shrink the heap. */ - erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); - ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p); + erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); + ERTS_MSGQ_MV_INQ2PRIVQ(c_p); if (!c_p->msg.len) { - erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); + erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); c_p->fvalue = NIL; PROCESS_MAIN_CHK_LOCKS(c_p); erts_garbage_collect_hibernate(c_p); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); - erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); -#ifndef ERTS_SMP - if (ERTS_PROC_IS_EXITING(c_p)) { - /* - * See comment in the beginning of the function... - * - * This second test is needed since gc might be traced. - */ - return -1; - } -#else /* ERTS_SMP */ - ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p); + erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); + ERTS_MSGQ_MV_INQ2PRIVQ(c_p); if (!c_p->msg.len) -#endif - erts_smp_atomic32_read_band_relb(&c_p->state, ~ERTS_PSFLG_ACTIVE); + erts_atomic32_read_band_relb(&c_p->state, ~ERTS_PSFLG_ACTIVE); ASSERT(!ERTS_PROC_IS_EXITING(c_p)); } - erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); + erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); c_p->current = &bif_export[BIF_hibernate_3]->info.mfa; c_p->flags |= F_HIBERNATE_SCHED; /* Needed also when woken! */ return 1; @@ -6725,7 +6684,7 @@ call_fun(Process* p, /* Current process. */ module = fe->module; - ERTS_SMP_READ_MEMORY_BARRIER; + ERTS_THR_READ_MEMORY_BARRIER; if (fe->pend_purge_address) { /* * The system is currently trying to purge the @@ -6856,7 +6815,7 @@ new_fun(Process* p, Eterm* reg, ErlFunEntry* fe, int num_free) p->htop = hp + needed; funp = (ErlFunThing *) hp; hp = funp->env; - erts_smp_refc_inc(&fe->refc, 2); + erts_refc_inc(&fe->refc, 2); funp->thing_word = HEADER_FUN; funp->next = MSO(p).first; MSO(p).first = (struct erl_off_heap_header*) funp; @@ -7020,6 +6979,44 @@ new_map(Process* p, Eterm* reg, BeamInstr* I) } static Eterm +new_small_map_lit(Process* p, Eterm* reg, Uint* n_exp, BeamInstr* I) +{ + Eterm* keys = tuple_val(Arg(3)); + Uint n = arityval(*keys); + Uint need = n + 1 /* hdr */ + 1 /*size*/ + 1 /* ptr */ + 1 /* arity */; + Uint i; + BeamInstr *ptr; + flatmap_t *mp; + Eterm *mhp; + Eterm *E; + + *n_exp = n; + ptr = &Arg(4); + + ASSERT(n <= MAP_SMALL_MAP_LIMIT); + + if (HeapWordsLeft(p) < need) { + erts_garbage_collect(p, need, reg, Arg(2)); + } + + mhp = p->htop; + E = p->stop; + + mp = (flatmap_t *)mhp; mhp += MAP_HEADER_FLATMAP_SZ; + mp->thing_word = MAP_HEADER_FLATMAP; + mp->size = n; + mp->keys = Arg(3); + + for (i = 0; i < n; i++) { + GET_TERM(*ptr++, *mhp++); + } + + p->htop = mhp; + + return make_flatmap(mp); +} + +static Eterm update_map_assoc(Process* p, Eterm* reg, Eterm map, BeamInstr* I) { Uint n; |