diff options
Diffstat (limited to 'erts/emulator/beam')
31 files changed, 428 insertions, 1000 deletions
diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h index fbd0528009..ae60904785 100644 --- a/erts/emulator/beam/atom.h +++ b/erts/emulator/beam/atom.h @@ -21,10 +21,7 @@ #ifndef __ATOM_H__ #define __ATOM_H__ -#ifndef __INDEX_H__ #include "index.h" -#endif - #include "erl_atom_table.h" #define MAX_ATOM_CHARACTERS 255 diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 15e878ba65..92815b2bcd 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -37,6 +37,10 @@ #include "erl_bits.h" #include "erl_thr_progress.h" +#ifdef HIPE +# include "hipe_stack.h" +#endif + static void set_default_trace_pattern(Eterm module); static Eterm check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls); static void delete_code(Module* modp); @@ -916,6 +920,10 @@ check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls } if (any_heap_ref_ptrs(rp->stop, rp->hend, literals, lit_bsize)) goto try_literal_gc; +#ifdef HIPE + if (nstack_any_heap_ref_ptrs(rp, literals, lit_bsize)) + goto try_literal_gc; +#endif if (any_heap_refs(rp->heap, rp->htop, literals, lit_bsize)) goto try_literal_gc; if (any_heap_refs(rp->old_heap, rp->old_htop, literals, lit_bsize)) diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 8489897d3a..920c8b1ed0 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -858,7 +858,8 @@ erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr* I) if (flags & MATCH_SET_RX_TRACE) { erts_trace_return(p, ep->code, result, &ERTS_TRACER(p)); } - if (flags & MATCH_SET_RETURN_TO_TRACE) { + if (flags & MATCH_SET_RETURN_TO_TRACE && + IS_TRACED_FL(p, F_TRACE_RETURN_TO)) { /* can only happen if(local)*/ if (applying) { /* Apply of BIF, cp is in calling function */ diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 4716460a6b..8f90a999c4 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -2161,7 +2161,10 @@ void process_main(void) c_p->i = (BeamInstr *) Arg(0); /* L1 */ SWAPOUT; c_p->arity = 0; - erts_smp_atomic32_read_band_relb(&c_p->state, ~ERTS_PSFLG_ACTIVE); + + if (!ERTS_PTMR_IS_TIMED_OUT(c_p)) + erts_smp_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); c_p->current = NULL; @@ -2826,13 +2829,7 @@ do { \ goto context_switch3; } - if (ERTS_MSACC_IS_ENABLED_CACHED_X()) { - if (GET_BIF_MODULE(Arg(0)) == am_ets) { - ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_ETS); - } else { - ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_BIF); - } - } + ERTS_MSACC_SET_BIF_STATE_CACHED_X(GET_BIF_MODULE(Arg(0)), GET_BIF_ADDRESS(Arg(0))); bf = GET_BIF_ADDRESS(Arg(0)); @@ -3032,6 +3029,7 @@ do { \ if (i == 0) { StoreBifResult(4, Op1); } + ires = big_size(Op1); goto big_shift; } } else if (is_big(Op2)) { @@ -3047,7 +3045,6 @@ do { \ OpCase(i_bsl_jIssd): GetArg2(2, Op1, Op2); - do_bsl: if (is_small(Op2)) { i = signed_val(Op2); @@ -3073,16 +3070,12 @@ do { \ StoreBifResult(4, Op1); } } - Op1 = small_to_big(ires, tmp_big); -#ifdef TAG_LITERAL_PTR - Op1 |= TAG_LITERAL_PTR; -#endif + ires = 1; /* big_size(small_to_big(Op1)) */ big_shift: if (i > 0) { /* Left shift. */ - ires = big_size(Op1) + (i / D_EXP); + ires += (i / D_EXP); } else { /* Right shift. */ - ires = big_size(Op1); if (ires <= (-i / D_EXP)) ires = 3; /* ??? */ else @@ -3101,6 +3094,9 @@ do { \ goto lb_Cl_error; } TestHeapPreserve(ires+1, Arg(1), Op1); + if (is_small(Op1)) { + Op1 = small_to_big(signed_val(Op1), tmp_big); + } bigp = HTOP; Op1 = big_lshift(Op1, i, bigp); if (is_big(Op1)) { @@ -3123,6 +3119,7 @@ do { \ if (i == 0) { StoreBifResult(4, Op1); } + ires = big_size(Op1); goto big_shift; } } else if (is_big(Op2)) { @@ -3593,13 +3590,7 @@ do { \ goto context_switch; } - if (ERTS_MSACC_IS_ENABLED_CACHED_X()) { - if ((Eterm)I[-3] == am_ets) { - ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_ETS); - } else { - ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_BIF); - } - } + ERTS_MSACC_SET_BIF_STATE_CACHED_X((Eterm)I[-3], (BifFunction)Arg(0)); c_p->current = I-3; /* In case we apply process_info/1,2 or load_nif/1 */ c_p->i = I; /* In case we apply check_process_code/2. */ @@ -7017,7 +7008,11 @@ update_map_assoc(Process* p, Eterm* reg, Eterm map, BeamInstr* I) /* The expensive case, need to build a hashmap */ if (n > MAP_SMALL_MAP_LIMIT) { - res = erts_hashmap_from_ks_and_vs(p,flatmap_get_keys(mp),flatmap_get_values(mp),n); + ErtsHeapFactory factory; + erts_factory_proc_init(&factory, p); + res = erts_hashmap_from_ks_and_vs(&factory,flatmap_get_keys(mp), + flatmap_get_values(mp),n); + erts_factory_close(&factory); } return res; } diff --git a/erts/emulator/beam/benchmark.c b/erts/emulator/beam/benchmark.c deleted file mode 100644 index c8409784ef..0000000000 --- a/erts/emulator/beam/benchmark.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "sys.h" -#include "global.h" -#include "benchmark.h" - -#ifdef BM_COUNTERS -unsigned long long processes_busy; -unsigned long long processes_spawned; -unsigned long long messages_sent; -unsigned long long messages_copied; -unsigned long long messages_ego; -unsigned long long minor_gc; -unsigned long long major_gc; -#endif /* BM_COUNTERS */ - -#ifdef BM_TIMERS - -/* assuming Solaris */ -#include <time.h> -BM_TIMER_T system_clock; - -unsigned long local_pause_times[MAX_PAUSE_TIME]; -unsigned long pause_times[MAX_PAUSE_TIME]; -unsigned long pause_times_old[MAX_PAUSE_TIME]; - -BM_TIMER_T mmu; -BM_TIMER_T mmu_counter; - -BM_NEW_TIMER(timer); -BM_NEW_TIMER(system); -BM_NEW_TIMER(gc); -BM_NEW_TIMER(minor_gc); -BM_NEW_TIMER(major_gc); -BM_NEW_TIMER(minor_global_gc); -BM_NEW_TIMER(major_global_gc); -BM_NEW_TIMER(send); -BM_NEW_TIMER(copy); -BM_NEW_TIMER(size); -BM_NEW_TIMER(max_minor); -BM_NEW_TIMER(max_major); -BM_NEW_TIMER(max_global_minor); -BM_NEW_TIMER(max_global_major); -BM_NEW_TIMER(misc0); -BM_NEW_TIMER(misc1); -BM_NEW_TIMER(misc2); -#endif /* BM_TIMERS */ - -#ifdef BM_HEAP_SIZES -unsigned long long max_used_heap; -unsigned long long max_allocated_heap; -unsigned long long max_used_global_heap; -unsigned long long max_allocated_global_heap; -#endif /* BM_HEAP_SIZES */ - -#ifdef BM_MESSAGE_SIZES -unsigned long long words_sent; -unsigned long long words_copied; -unsigned long long words_prealloc; -unsigned long long message_sizes[1000]; -#endif /* BM_MESSAGE_SIZES */ - -/***** - * The following functions have to be defined, but they only have contents - * if certain keywords are defined. - */ - -void init_benchmarking() -{ -#ifdef BM_TIMERS - int i; - for (i = 0; i < 1000; i++) - { - BM_START_TIMER(system); - BM_STOP_TIMER(system); - } - timer_time = system_time / 1000; - - for (i = 0; i < MAX_PAUSE_TIME; i++) { - local_pause_times[i] = 0; - pause_times[i] = 0; - pause_times_old[i] = 0; - } - - mmu = 0; - mmu_counter = 0; - - BM_MMU_INIT(); -#endif /* BM_TIMERS */ - -#ifdef BM_COUNTERS - processes_busy = 0; - processes_spawned = 0; - messages_sent = 0; - messages_copied = 0; - messages_ego = 0; - minor_gc = 0; - major_gc = 0; -#endif /* BM_COUNTERS */ - -#ifdef BM_HEAP_SIZES - max_used_heap = 0; - max_allocated_heap = 0; - max_used_global_heap = 0; - max_allocated_global_heap = 0; -#endif /* BM_HEAP_SIZES */ - -#ifdef BM_MESSAGE_SIZES - words_sent = 0; - words_copied = 0; - words_prealloc = 0; - { - int i; - for (i = 0; i < 1000; i++) - message_sizes[i] = 0; - } -#endif /* BM_MESSAGE_SIZES */ -} - -void save_statistics() -{ -#ifdef BM_STATISTICS - FILE *file = fopen(BM_STATISTICS_FILE,"a"); - long i = 0; - - if (file) - { - erts_fprintf(file,"-------------------------------------------------------------------------\n"); - erts_fprintf(file,"The counters are reset at system start and are sums over the entire node.\n"); - erts_fprintf(file,"You may reset them manually using the BIFs in the module hipe_bifs.\n"); - erts_fprintf(file,"All times are given in milliseconds.\n"); - erts_fprintf(file,"-------------------------------------------------------------------------\n"); - - erts_fprintf(file,"Node: %T\n",erts_this_node->sysname); - -#ifdef BM_COUNTERS - erts_fprintf(file,"Number of processes spawned: %lld\n",processes_spawned); - erts_fprintf(file,"Number of local minor GCs: %lld\n",minor_gc); - erts_fprintf(file,"Number of local major GCs: %lld\n",major_gc); - erts_fprintf(file,"Number of messages sent: %lld\n",messages_sent); - erts_fprintf(file,"Number of messages copied: %lld\n",messages_copied); - erts_fprintf(file,"Number of messages sent to self: %lld\n",messages_ego); -#endif /* BM_COUNTERS */ - -#ifdef BM_MESSAGE_SIZES - erts_fprintf(file,"Number of words sent: %lld\n",words_sent); - erts_fprintf(file,"Number of words copied: %lld\n",words_copied); - erts_fprintf(file,"Number of words preallocated: %lld\n",words_prealloc); -#endif /* BM_MESSAGE_SIZES */ - -#ifdef BM_HEAP_SIZES - erts_fprintf(file,"Biggest local heap used (in words): %lld\n",max_used_heap); - erts_fprintf(file,"Biggest local heap allocated (in words): %lld\n",max_allocated_heap); - erts_fprintf(file,"Biggest global heap used (in words): %lld\n",max_used_global_heap); - erts_fprintf(file,"Biggest global heap allocated (in words): %lld\n",max_allocated_global_heap); -#endif /* BM_HEAP_SIZES */ - -#ifdef BM_TIMERS - erts_fprintf(file,"--- The total active system time is the sum of all times below ---\n"); - BM_TIME_PRINTER("Mutator time",system_time); - BM_TIME_PRINTER("Time spent in send (excluding size & copy)",send_time); - BM_TIME_PRINTER("Time spent in size",size_time); - BM_TIME_PRINTER("Time spent in copy",copy_time); - BM_TIME_PRINTER("Time spent in local minor GC",minor_gc_time); - BM_TIME_PRINTER("Time spent in local major GC",major_gc_time); - BM_TIME_PRINTER("Time spent in global minor GC",minor_global_gc_time); - BM_TIME_PRINTER("Time spent in global major GC",major_global_gc_time); - erts_fprintf(file,"---\n"); - BM_TIME_PRINTER("Maximum time spent in one separate local minor GC",max_minor_time); - BM_TIME_PRINTER("Maximum time spent in one separate local major GC",max_major_time); - BM_TIME_PRINTER("Maximum time spent in one separate global minor GC",max_global_minor_time); - BM_TIME_PRINTER("Maximum time spent in one separate global major GC",max_global_major_time); -#endif /* BM_TIMERS */ - -#if 0 - /* Save a log file for import into excel */ - - long long total_time, n; - long left, right, mid; - -#ifdef BM_COUNTERS - erts_fprintf(file,"Spawns\tLocalGC\tMAGC\tMessages\tMutator_t\tLocalGC_t\tMAGC_t\tLocMaxP\tLocMeanP\tLocGeoMP\tMAMaxP\tMAMeanP\tMAGeoMP\t\tCMAGC\tCMAGC_t\n"); - erts_fprintf(file,"%lld\t%lld\t%lld\t%lld\t", - processes_spawned, - minor_garbage_cols + major_garbage_cols, - minor_global_garbage_cols + major_global_garbage_cols, - messages_sent); -#endif /* BM_COUNTERS */ - -#ifdef BM_TIMERS - erts_fprintf(file,"%lld\t%lld\t%lld\t", - (long long)(system_time + send_time + size_time + copy_time), - (long long)(minor_gc_time + major_gc_time), - (long long)(minor_global_gc_time + major_global_gc_time)); - - total_time = 0; n = 0; - left = 0; right = 0; mid = 0; - for (i = 0; i < MAX_PAUSE_TIME; i++) { - total_time += local_pause_times[i] * i; - n += local_pause_times[i]; - if (i > mid) - right += local_pause_times[i]; - while(right > left) { - left += local_pause_times[mid++]; - right -= local_pause_times[mid]; - } - } - erts_fprintf(file,"%lld\t%lld\t%ld\t", - (long long)((max_minor_time > max_major_time ? - max_minor_time : - max_major_time)*1000), - total_time / n, - mid); - - total_time = 0; n = 0; - left = 0; right = 0; mid = 0; - for (i = 0; i < MAX_PAUSE_TIME; i++) { - if (pause_times[i] > 0) { - total_time += pause_times[i] * i; - n += pause_times[i]; - if (i > mid) - right += pause_times[i]; - while(right > left) { - left += pause_times[mid++]; - right -= pause_times[mid]; - } - } - } - erts_fprintf(file,"%lld\t%lld\t%ld\t", - (long long)((max_global_minor_time > max_global_major_time ? - max_global_minor_time : - max_global_major_time)*1000), - (n > 0 ? total_time / n : 0), - mid); - - erts_fprintf(file,"\t%lld\t%lld\n",n,total_time); - - erts_fprintf(file,"\nMinor:\n"); - for (i = 0; i < MAX_PAUSE_TIME; i++) { - if (i < 1000 || pause_times[i] > 0) { - erts_fprintf(file,"%d\t%ld\n",i,pause_times[i]); - } - } - - fprintf(file,"Major:\n"); - for (i = 0; i < MAX_PAUSE_TIME; i++) { - if (pause_times_old[i] > 0) { - fprintf(file,"%d\t%ld\n",i,pause_times_old[i]); - } - } -#endif /* BM_TIMERS */ - -#ifdef BM_TIMERS - total_time = 0; n = 0; - left = 0; right = 0; mid = 0; - fprintf(file,"\nLocal:\n"); - for (i = 0; i < MAX_PAUSE_TIME; i++) { - if (local_pause_times[i] > 0) { - erts_fprintf(file,"%d\t%ld\n",i,local_pause_times[i]); - total_time += local_pause_times[i] * i; - n += local_pause_times[i]; - if (i > mid) - right += local_pause_times[i]; - while(right > left) { - left += local_pause_times[mid++]; - right -= local_pause_times[mid]; - } - } - } - erts_fprintf(file,"Mid: %ld Mean: %ld\n",(long)mid, - (long)(n > 0 ? total_time / n : 0)); -#endif -#endif /* 0 */ - fclose(file); - } - else - fprintf(stderr,"Sorry... Can not write to %s!\n\r",BM_STATISTICS_FILE); -#endif /* BM_STATISTICS */ -} diff --git a/erts/emulator/beam/benchmark.h b/erts/emulator/beam/benchmark.h deleted file mode 100644 index 0272896f4f..0000000000 --- a/erts/emulator/beam/benchmark.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#ifndef __BENCHMARK_H__ -#define __BENCHMARK_H__ - -/* The define __BENCHMARK__ is the master switch to turn on and off - * benchmarking. This will enable the benchmark-BIFs in hipe_bif1.c. - * Documentation for the BIFs is in hipe_bif1.c, and that is where you - * will find the information about how to accually get some data out - * from these timers and counters. - */ -/* #define __BENCHMARK__ */ - -#ifdef __BENCHMARK__ -/* - * The defines below enables different parts of the benchmaring. - * Counters and timers that are disabled, always report zero in - * the BIFs. - */ - -/* BM_TIMERS keeps track of the time spent in diferent parts of the - * system. It only measures accual active time, not time spent in idle - * mode. Currently, the Solaris hrtime_t will be used. - * To add new timers look below. - */ -#define BM_TIMERS - -/* BM_COUNTERS count all kinds of events that occurs in the system. - * Among other things it counts the number of messages, then number of - * garbage collections, the number of processes spawned etc. - * To add new counters look below. - */ -#define BM_COUNTERS - -/* BM_MESSAGE_SIZES keeps a log of the size of all messages sent in - * the system. This introduce an overhead in time for the shared heap - * system since all message sizes have to be calculated at send. - */ -/* #define BM_MESSAGE_SIZES */ - -/* BM_HEAP_SIZES goes through all processes at garbage collection time - * to sum their allocated and used heap sizes. In anything else than a - * shared heap system, this will cost. - */ -/* #define BM_HEAP_SIZES */ - -/* BM_STATISTICS saves an entry in the file BM_STATISTICS_FILE. This - * is done for each erlang node at exit time. - */ -/* #define BM_STATISTICS */ - -#endif /* __BENCHMARK__ */ - - -#ifdef BM_STATISTICS -# define BM_STATISTICS_FILE "/tmp/erlang_statistics.joppe.log" -#endif /* BM_STATISTICS */ - - -/************ There are no more settings below this line *************/ - -/* - * Maintenance and how to add new stuff is documented by the code - * below ;-) - */ - -#ifdef BM_COUNTERS -/********************************************************************* - * To add new counters: - * - * Add the variable here AND in benchmark.c. Use the macro - * BM_COUNT(var) in the code where you want to increase it. - * - */ -extern unsigned long long processes_busy; -extern unsigned long long processes_spawned; -extern unsigned long long messages_sent; -extern unsigned long long messages_copied; -extern unsigned long long messages_ego; -extern unsigned long long minor_gc; -extern unsigned long long major_gc; - -#define BM_COUNT(var) (var)++; - -#define BM_EGO_COUNT(send,rec) { \ - if ((send) == (rec)) \ - BM_COUNT(messages_ego); } - -#define BM_LAZY_COPY_START long long gcs = minor_global_gc + major_global_gc; -#define BM_LAZY_COPY_STOP { gcs = (minor_global_gc + major_global_gc) - gcs; \ - if (gcs > gc_in_copy) gc_in_copy = gcs; } - -#else /* !BM_COUNTERS */ -# define BM_COUNT(var) -# define BM_EGO_COUNT(send,rec) -# define BM_LAZY_COPY_START -# define BM_LAZY_COPY_STOP -#endif /* BM_COUNTERS */ - - -#ifdef BM_TIMERS -/********************************************************************* - * To add new timers: - * - * Add the variable below using the form extern BM_TIMER_T blah_time. - * Also add them in benchmark.c using the macro NEW_TIMER(blah). Use - * the macro BM_SWAP_TIMER(from,blah) ... BM_SWAP_TIMER(blah,to) to - * start and stop the new timer. Note, that you have to know what - * timer is running at the place where you want to insert your new - * timer to be able to stop and start (from,to) it. - * - * You can use the macros BM_STOP_TIMER(blah) and BM_START_TIMER(blah) - * around code that should not be timed at all. As above, you have to - * know what timer to start and stop. The system timer is running at - * most places in the emulator. Only the garbage collector and the - * message sending has its own timers at the moment. - * - * The timer_time used when stopping timers is the time it takes to - * start and stop the timers, calculated in init_benchmarking(). If it - * is not there, the time it takes to do this will accually be - * substantial compared to some small times in the system we want to - * meassure (send time in shared heap for instance). - */ - -/* (Assuming Solaris) */ - -#define BM_TIMER_T ErtsMonotonicTime -#define BM_START_TIMER(t) system_clock = ERTS_MONOTONIC_TO_NSEC(erts_os_monotonic_time()) -#define BM_STOP_TIMER(t) do { \ - BM_TIMER_T tmp = (ERTS_MONOTONIC_TO_NSEC(erts_os_monotonic_time()) - system_clock) - timer_time; \ - t##_time += (tmp > 0 ? tmp : 0); \ -} while(0) - -#define BM_TIME_PRINTER(str,time) do { \ - int min,sec,milli,micro; \ - BM_TIMER_T tmp; \ - tmp = (time) / 1000; \ - micro = tmp % 1000; \ - tmp /= 1000; \ - milli = tmp % 1000; \ - tmp /= 1000; \ - sec = tmp % 60; \ - min = tmp / 60; \ - erts_fprintf(file,str": %d:%02d.%03d %03d\n",min,sec,milli,micro); \ -} while(0) - -extern BM_TIMER_T system_clock; - -extern BM_TIMER_T timer_time; -extern BM_TIMER_T system_time; -extern BM_TIMER_T gc_time; -extern BM_TIMER_T minor_gc_time; -extern BM_TIMER_T major_gc_time; -extern BM_TIMER_T minor_global_gc_time; -extern BM_TIMER_T major_global_gc_time; -extern BM_TIMER_T send_time; -extern BM_TIMER_T copy_time; -extern BM_TIMER_T size_time; -extern BM_TIMER_T max_minor_time; -extern BM_TIMER_T max_major_time; -extern BM_TIMER_T max_global_minor_time; -extern BM_TIMER_T max_global_major_time; -extern BM_TIMER_T misc0_time; -extern BM_TIMER_T misc1_time; -extern BM_TIMER_T misc2_time; - -#define MAX_PAUSE_TIME 500000 -extern unsigned long local_pause_times[MAX_PAUSE_TIME]; -extern unsigned long pause_times[MAX_PAUSE_TIME]; -extern unsigned long pause_times_old[MAX_PAUSE_TIME]; - -#define MMU_INTERVAL 5 /* milli seconds */ -extern BM_TIMER_T mmu_counter; -extern BM_TIMER_T mmu; - -#define BM_NEW_TIMER(t) BM_TIMER_T t##_time = 0; -#define BM_RESET_TIMER(t) t##_time = 0; -#define BM_SWAP_TIMER(t1,t2) do { BM_STOP_TIMER(t1); BM_START_TIMER(t2); } while(0) -#define BM_MMU_INIT() do { \ - BM_TIMER_T gc = gc_time; \ - while (gc > 0) { \ - if (gc > MMU_INTERVAL) { \ - gc -= MMU_INTERVAL - mmu_counter; \ - erts_printf("%d\n",(int)((mmu / MMU_INTERVAL) * 100)); \ - mmu_counter = 0; mmu = 0; \ - } else { \ - mmu_counter += gc; \ - if (mmu_counter >= MMU_INTERVAL) { \ - mmu_counter -= MMU_INTERVAL; \ - erts_printf("%d\n",(int)((mmu / MMU_INTERVAL) * 100)); \ - mmu = 0; \ - } \ - gc = 0; \ - } \ - } \ - BM_RESET_TIMER(system); \ - BM_RESET_TIMER(send); \ - BM_RESET_TIMER(copy); \ - BM_RESET_TIMER(size); \ -} while(0) - -#define BM_MMU_READ() do { \ - BM_TIMER_T mut = system_time + send_time + copy_time + size_time; \ - while (mut > 0) { \ - if (mut > MMU_INTERVAL) { \ - BM_TIMER_T tmp = MMU_INTERVAL - mmu_counter; \ - mmu += tmp; mut -= tmp; \ - erts_printf("%d\n",(int)((mmu / MMU_INTERVAL) * 100)); \ - mmu_counter = 0; mmu = 0; \ - } else { \ - mmu_counter += mut; mmu += mut; \ - if (mmu_counter >= MMU_INTERVAL) { \ - mmu_counter -= MMU_INTERVAL; \ - mmu -= mmu_counter; \ - erts_printf("%d\n",(int)((mmu / MMU_INTERVAL) * 100)); \ - mmu = mmu_counter; \ - } \ - mut = 0; \ - } \ - } \ -} while(0) - -#else /* !BM_TIMERS */ -# define BM_NEW_TIMER(t) -# define BM_START_TIMER(t) -# define BM_STOP_TIMER(t) -# define BM_RESET_TIMER(t) -# define BM_SWAP_TIMER(t1,t2) -# define BM_TIME_PRINTER(str,time) -# define BM_MMU_INIT() -# define BM_MMU_READ() -#endif /* BM_TIMERS */ - -#ifdef BM_HEAP_SIZES -extern unsigned long long max_used_heap; -extern unsigned long long max_allocated_heap; -extern unsigned long long max_used_global_heap; -extern unsigned long long max_allocated_global_heap; -#endif /* BM_HEAP_SIZES */ - -#ifdef BM_MESSAGE_SIZES -extern unsigned long long words_sent; -extern unsigned long long words_copied; -extern unsigned long long words_prealloc; -extern unsigned long long message_sizes[1000]; - -#define BM_MESSAGE_COPIED(size) { \ - words_copied += size; \ - BM_COUNT(messages_copied); } - -#define BM_PREALLOC_DATA(size) { \ - words_prealloc += size; } - -#define BM_MESSAGE(mess,send,rec) { \ - Uint msize = size_object(mess); \ - words_sent += msize; \ - if (msize < 1000) \ - message_sizes[msize]++; \ - else \ - message_sizes[999]++; \ - BM_EGO_COUNT(send,rec); \ - BM_COUNT(messages_sent); } - -#else /* !BM_MESSAGE_SIZES */ - -#define BM_MESSAGE_COPIED(size) BM_COUNT(messages_copied); -#define BM_PREALLOC_DATA(size) -#define BM_MESSAGE(mess,send,rec) { \ - BM_EGO_COUNT(send,rec); \ - BM_COUNT(messages_sent); } - -#endif /* BM_MESSAGE_SIZES */ - -void init_benchmarking(void); -void save_statistics(void); - -#endif /* _BENCHMARK_H_ */ diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index fc14061a44..d9048065c8 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -4305,8 +4305,9 @@ BIF_RETTYPE group_leader_2(BIF_ALIST_2) else { locks &= ~ERTS_PROC_LOCK_STATUS; erts_smp_proc_unlock(new_member, ERTS_PROC_LOCK_STATUS); - if (erts_smp_atomic32_read_nob(&new_member->state) - & !(ERTS_PSFLG_DIRTY_RUNNING|ERTS_PSFLG_DIRTY_RUNNING_SYS)) { + if (new_member == BIF_P + || !(erts_smp_atomic32_read_nob(&new_member->state) + & (ERTS_PSFLG_DIRTY_RUNNING|ERTS_PSFLG_DIRTY_RUNNING_SYS))) { new_member->group_leader = STORE_NC_IN_PROC(new_member, BIF_ARG_1); } @@ -4326,6 +4327,7 @@ BIF_RETTYPE group_leader_2(BIF_ALIST_2) BIF_ARG_1); bp->next = new_member->mbuf; new_member->mbuf = bp; + new_member->mbuf_sz += bp->used_size; } } } diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h index 464acd67f6..4a96d971c3 100644 --- a/erts/emulator/beam/big.h +++ b/erts/emulator/beam/big.h @@ -21,17 +21,8 @@ #ifndef __BIG_H__ #define __BIG_H__ -#ifndef __SYS_H__ #include "sys.h" -#endif - -#ifndef __CONFIG_H__ -#include "erl_vm.h" -#endif - -#ifndef __GLOBAL_H__ #include "global.h" -#endif typedef Uint ErtsDigit; diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index bad34211a5..128a7b3865 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -1094,7 +1094,7 @@ BIF_RETTYPE ets_insert_2(BIF_ALIST_2) CHECK_TABLES(); - /* Write lock table if more than one object to keep atomicy */ + /* Write lock table if more than one object to keep atomicity */ kind = ((is_list(BIF_ARG_2) && CDR(list_val(BIF_ARG_2)) != NIL) ? LCK_WRITE : LCK_WRITE_REC); @@ -1164,7 +1164,7 @@ BIF_RETTYPE ets_insert_new_2(BIF_ALIST_2) Eterm lookup_ret; DbTableMethod* meth; - /* More than one object, use LCK_WRITE to keep atomicy */ + /* More than one object, use LCK_WRITE to keep atomicity */ kind = LCK_WRITE; tb = db_get_table(BIF_P, BIF_ARG_1, DB_WRITE, kind); if (tb == NULL) { diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c index 74979f984a..5e6fe4f460 100644 --- a/erts/emulator/beam/erl_db_hash.c +++ b/erts/emulator/beam/erl_db_hash.c @@ -40,7 +40,7 @@ ** DB_FINE_LOCKED set. The table variable is_thread_safe will then indicate ** if operations need to obtain fine grained locks or not. Some operations ** will for example always use exclusive table lock to guarantee -** a higher level of atomicy. +** a higher level of atomicity. */ /* FIXATION: @@ -2866,15 +2866,7 @@ db_lookup_dbterm_hash(Process *p, DbTable *tbl, Eterm key, Eterm obj, q->hvalue = hval; q->next = NULL; *bp = b = q; - - { - int nitems = erts_smp_atomic_inc_read_nob(&tb->common.nitems); - int nactive = NACTIVE(tb); - - if (nitems > nactive * (CHAIN_LEN + 1) && !IS_FIXED(tb)) { - grow(tb, nactive); - } - } + flags |= DB_INC_TRY_GROW; } else { HashDbTerm *q, *next = b->next; @@ -2910,6 +2902,7 @@ db_finalize_dbterm_hash(int cret, DbUpdateHandle* handle) HashDbTerm **bp = (HashDbTerm **) handle->bp; HashDbTerm *b = *bp; erts_smp_rwmtx_t* lck = (erts_smp_rwmtx_t*) handle->lck; + HashDbTerm* free_me = NULL; ERTS_SMP_LC_ASSERT(IS_HASH_WLOCKED(tb, lck)); /* locked by db_lookup_dbterm_hash */ @@ -2921,21 +2914,34 @@ db_finalize_dbterm_hash(int cret, DbUpdateHandle* handle) b->hvalue = INVALID_HASH; } else { *bp = b->next; - free_term(tb, b); + free_me = b; } WUNLOCK_HASH(lck); erts_smp_atomic_dec_nob(&tb->common.nitems); try_shrink(tb); - } else if (handle->flags & DB_MUST_RESIZE) { - db_finalize_resize(handle, offsetof(HashDbTerm,dbterm)); - WUNLOCK_HASH(lck); - - free_term(tb, b); - } - else { - WUNLOCK_HASH(lck); + } else { + if (handle->flags & DB_MUST_RESIZE) { + db_finalize_resize(handle, offsetof(HashDbTerm,dbterm)); + free_me = b; + } + if (handle->flags & DB_INC_TRY_GROW) { + int nactive; + int nitems = erts_smp_atomic_inc_read_nob(&tb->common.nitems); + WUNLOCK_HASH(lck); + nactive = NACTIVE(tb); + + if (nitems > nactive * (CHAIN_LEN + 1) && !IS_FIXED(tb)) { + grow(tb, nactive); + } + } else { + WUNLOCK_HASH(lck); + } } + + if (free_me) + free_term(tb, free_me); + #ifdef DEBUG handle->dbterm = 0; #endif diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h index 60f7067d70..4acedbfed0 100644 --- a/erts/emulator/beam/erl_db_util.h +++ b/erts/emulator/beam/erl_db_util.h @@ -79,6 +79,7 @@ typedef union db_table DbTable; #define DB_MUST_RESIZE 1 #define DB_NEW_OBJECT 2 +#define DB_INC_TRY_GROW 4 /* Info about a database entry while it's being updated * (by update_counter or update_element) diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index d0d74bbf44..8b0dd9a5a6 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -672,6 +672,7 @@ do_major_collection: killed before a GC could be done. */ if (reds == -2) { ErtsProcLocks locks = ERTS_PROC_LOCKS_ALL; + int res; erts_smp_proc_lock(p, ERTS_PROC_LOCKS_ALL_MINOR); erts_send_exit_signal(p, p->common.id, p, &locks, @@ -683,7 +684,9 @@ do_major_collection: erts_smp_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_GC); /* We have to make sure that we have space for need on the heap */ - return delay_garbage_collection(p, live_hf_end, need, fcalls); + res = delay_garbage_collection(p, live_hf_end, need, fcalls); + ERTS_MSACC_POP_STATE_M(); + return res; } erts_smp_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_GC); @@ -882,6 +885,58 @@ erts_garbage_collect_hibernate(Process* p) } +/* + * HiPE native code stack scanning procedures: + * - fullsweep_nstack() + * - gensweep_nstack() + * - offset_nstack() + * - sweep_literals_nstack() + */ +#if defined(HIPE) + +#define GENSWEEP_NSTACK(p,old_htop,n_htop) \ + do { \ + Eterm *tmp_old_htop = old_htop; \ + Eterm *tmp_n_htop = n_htop; \ + gensweep_nstack((p), &tmp_old_htop, &tmp_n_htop); \ + old_htop = tmp_old_htop; \ + n_htop = tmp_n_htop; \ + } while(0) + +/* + * offset_nstack() can ignore the descriptor-based traversal the other + * nstack procedures use and simply call offset_heap_ptr() instead. + * This relies on two facts: + * 1. The only live non-Erlang terms on an nstack are return addresses, + * and they will be skipped thanks to the low/high range check. + * 2. Dead values, even if mistaken for pointers into the low/high area, + * can be offset safely since they won't be dereferenced. + * + * XXX: WARNING: If HiPE starts storing other non-Erlang values on the + * nstack, such as floats, then this will have to be changed. + */ +static ERTS_INLINE void offset_nstack(Process* p, Sint offs, + char* area, Uint area_size) +{ + if (p->hipe.nstack) { + ASSERT(p->hipe.nsp && p->hipe.nstend); + offset_heap_ptr(hipe_nstack_start(p), hipe_nstack_used(p), + offs, area, area_size); + } + else { + ASSERT(!p->hipe.nsp && !p->hipe.nstend); + } +} + +#else /* !HIPE */ + +#define fullsweep_nstack(p,n_htop) (n_htop) +#define GENSWEEP_NSTACK(p,old_htop,n_htop) do{}while(0) +#define offset_nstack(p,offs,area,area_size) do{}while(0) +#define sweep_literals_nstack(p,old_htop,area,area_size) (old_htop) + +#endif /* HIPE */ + void erts_garbage_collect_literals(Process* p, Eterm* literals, Uint byte_lit_size, @@ -944,7 +999,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, area_size = byte_lit_size; n = setup_rootset(p, p->arg_reg, p->arity, &rootset); roots = rootset.roots; - old_htop = p->old_htop; + old_htop = sweep_literals_nstack(p, p->old_htop, area, area_size); while (n--) { Eterm* g_ptr = roots->v; Uint g_sz = roots->sz; @@ -1211,56 +1266,6 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end, return -1; } -/* - * HiPE native code stack scanning procedures: - * - fullsweep_nstack() - * - gensweep_nstack() - * - offset_nstack() - */ -#if defined(HIPE) - -#define GENSWEEP_NSTACK(p,old_htop,n_htop) \ - do { \ - Eterm *tmp_old_htop = old_htop; \ - Eterm *tmp_n_htop = n_htop; \ - gensweep_nstack((p), &tmp_old_htop, &tmp_n_htop); \ - old_htop = tmp_old_htop; \ - n_htop = tmp_n_htop; \ - } while(0) - -/* - * offset_nstack() can ignore the descriptor-based traversal the other - * nstack procedures use and simply call offset_heap_ptr() instead. - * This relies on two facts: - * 1. The only live non-Erlang terms on an nstack are return addresses, - * and they will be skipped thanks to the low/high range check. - * 2. Dead values, even if mistaken for pointers into the low/high area, - * can be offset safely since they won't be dereferenced. - * - * XXX: WARNING: If HiPE starts storing other non-Erlang values on the - * nstack, such as floats, then this will have to be changed. - */ -static ERTS_INLINE void offset_nstack(Process* p, Sint offs, - char* area, Uint area_size) -{ - if (p->hipe.nstack) { - ASSERT(p->hipe.nsp && p->hipe.nstend); - offset_heap_ptr(hipe_nstack_start(p), hipe_nstack_used(p), - offs, area, area_size); - } - else { - ASSERT(!p->hipe.nsp && !p->hipe.nstend); - } -} - -#else /* !HIPE */ - -#define fullsweep_nstack(p,n_htop) (n_htop) -#define GENSWEEP_NSTACK(p,old_htop,n_htop) do{}while(0) -#define offset_nstack(p,offs,area,area_size) do{}while(0) - -#endif /* HIPE */ - static void do_minor(Process *p, ErlHeapFragment *live_hf_end, char *mature, Uint mature_size, diff --git a/erts/emulator/beam/erl_hl_timer.c b/erts/emulator/beam/erl_hl_timer.c index ebeff51aac..f1bef28186 100644 --- a/erts/emulator/beam/erl_hl_timer.c +++ b/erts/emulator/beam/erl_hl_timer.c @@ -735,7 +735,10 @@ proc_timeout_common(Process *proc, void *tmr) if (tmr == (void *) erts_smp_atomic_cmpxchg_mb(&proc->common.timer, ERTS_PTMR_TIMEDOUT, (erts_aint_t) tmr)) { - erts_aint32_t state = erts_smp_atomic32_read_acqb(&proc->state); + erts_aint32_t state; + erts_smp_proc_lock(proc, ERTS_PROC_LOCKS_MSG_RECEIVE); + state = erts_smp_atomic32_read_acqb(&proc->state); + erts_smp_proc_unlock(proc, ERTS_PROC_LOCKS_MSG_RECEIVE); if (!(state & (ERTS_PSFLG_ACTIVE|ERTS_PSFLG_EXITING))) erts_schedule_process(proc, state, 0); return 1; diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index fbdafec4ef..07cfacf14a 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -332,8 +332,6 @@ erl_init(int ncpu, int node_tab_delete_delay, ErtsDbSpinCount db_spin_count) { - init_benchmarking(); - erts_bif_unique_init(); erts_init_monitors(); erts_init_time(time_correction, time_warp_mode); @@ -2345,19 +2343,18 @@ erts_exit_vv(int n, int flush_async, char *fmt, va_list args1, va_list args2) { system_cleanup(flush_async); - save_statistics(); - if (erts_mtrace_enabled) erts_mtrace_exit((Uint32) n); + if (fmt != NULL && *fmt != '\0') + erl_error(fmt, args2); /* Print error message. */ + /* Produce an Erlang core dump if error */ if (((n == ERTS_ERROR_EXIT && erts_no_crash_dump == 0) || n == ERTS_DUMP_EXIT) && erts_initialized) { erl_crash_dump_v((char*) NULL, 0, fmt, args1); } - if (fmt != NULL && *fmt != '\0') - erl_error(fmt, args2); /* Print error message. */ sys_tty_reset(n); if (n == ERTS_INTR_EXIT) diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c index 8efc983f04..979a0040b0 100644 --- a/erts/emulator/beam/erl_map.c +++ b/erts/emulator/beam/erl_map.c @@ -497,18 +497,50 @@ Eterm erts_hashmap_from_array(ErtsHeapFactory* factory, Eterm *leafs, Uint n, return res; } +Eterm erts_map_from_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks0, Eterm *vs0, Uint n) +{ + if (n < MAP_SMALL_MAP_LIMIT) { + Eterm *ks, *vs, *hp; + flatmap_t *mp; + Eterm keys; -Eterm erts_hashmap_from_ks_and_vs_extra(Process *p, Eterm *ks, Eterm *vs, Uint n, + hp = erts_produce_heap(factory, 3 + 1 + (2 * n), 0); + keys = make_tuple(hp); + *hp++ = make_arityval(n); + ks = hp; + hp += n; + mp = (flatmap_t*)hp; + hp += MAP_HEADER_FLATMAP_SZ; + vs = hp; + + mp->thing_word = MAP_HEADER_FLATMAP; + mp->size = n; + mp->keys = keys; + + sys_memcpy(ks, ks0, n * sizeof(Eterm)); + sys_memcpy(vs, vs0, n * sizeof(Eterm)); + + erts_validate_and_sort_flatmap(mp); + + return make_flatmap(mp); + } else { + return erts_hashmap_from_ks_and_vs(factory, ks0, vs0, n); + } + return THE_NON_VALUE; +} + + +Eterm erts_hashmap_from_ks_and_vs_extra(ErtsHeapFactory *factory, + Eterm *ks, Eterm *vs, Uint n, Eterm key, Eterm value) { Uint32 sw, hx; Uint i,sz; hxnode_t *hxns; - ErtsHeapFactory factory; Eterm *hp, res; sz = (key == THE_NON_VALUE) ? n : (n + 1); ASSERT(sz > MAP_SMALL_MAP_LIMIT); - hp = HAlloc(p, 2 * sz); + hp = erts_produce_heap(factory, 2 * sz, 0); /* create tmp hx values and leaf ptrs */ hxns = (hxnode_t *)erts_alloc(ERTS_ALC_T_TMP, sz * sizeof(hxnode_t)); @@ -531,12 +563,9 @@ Eterm erts_hashmap_from_ks_and_vs_extra(Process *p, Eterm *ks, Eterm *vs, Uint n hxns[i].i = i; } - erts_factory_proc_init(&factory, p); - res = hashmap_from_unsorted_array(&factory, hxns, sz, 0); - erts_factory_close(&factory); + res = hashmap_from_unsorted_array(factory, hxns, sz, 0); erts_free(ERTS_ALC_T_TMP, (void *) hxns); - ERTS_VERIFY_UNUSED_TEMP_ALLOC(p); return res; } @@ -1780,11 +1809,14 @@ Eterm erts_maps_put(Process *p, Eterm key, Eterm value, Eterm map) { /* the map will grow */ if (n >= MAP_SMALL_MAP_LIMIT) { + ErtsHeapFactory factory; HRelease(p, shp + MAP_HEADER_FLATMAP_SZ + n, shp); ks = flatmap_get_keys(mp); vs = flatmap_get_values(mp); - res = erts_hashmap_from_ks_and_vs_extra(p,ks,vs,n,key,value); + erts_factory_proc_init(&factory, p); + res = erts_hashmap_from_ks_and_vs_extra(&factory,ks,vs,n,key,value); + erts_factory_close(&factory); return res; } diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h index 8b5c9582ba..61a841f7f0 100644 --- a/erts/emulator/beam/erl_map.h +++ b/erts/emulator/beam/erl_map.h @@ -98,10 +98,12 @@ Eterm* hashmap_iterator_prev(struct ErtsWStack_* s); int hashmap_key_hash_cmp(Eterm* ap, Eterm* bp); Eterm erts_hashmap_from_array(ErtsHeapFactory*, Eterm *leafs, Uint n, int reject_dupkeys); -#define erts_hashmap_from_ks_and_vs(P, KS, VS, N) \ - erts_hashmap_from_ks_and_vs_extra((P), (KS), (VS), (N), THE_NON_VALUE, THE_NON_VALUE); +#define erts_hashmap_from_ks_and_vs(F, KS, VS, N) \ + erts_hashmap_from_ks_and_vs_extra((F), (KS), (VS), (N), THE_NON_VALUE, THE_NON_VALUE); -Eterm erts_hashmap_from_ks_and_vs_extra(Process *p, Eterm *ks, Eterm *vs, Uint n, +Eterm erts_map_from_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks, Eterm *vs, Uint n); +Eterm erts_hashmap_from_ks_and_vs_extra(ErtsHeapFactory *factory, + Eterm *ks, Eterm *vs, Uint n, Eterm k, Eterm v); const Eterm *erts_maps_get(Eterm key, Eterm map); diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index 71ab92937d..91e06cde2d 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -697,9 +697,6 @@ erts_send_message(Process* sender, #ifdef SHCOPY_SEND erts_shcopy_t info; #endif - BM_STOP_TIMER(system); - BM_MESSAGE(message,sender,receiver); - BM_START_TIMER(send); #ifdef USE_VM_PROBES *sender_name = *receiver_name = '\0'; @@ -720,7 +717,6 @@ erts_send_message(Process* sender, #ifdef USE_VM_PROBES Uint dt_utag_size = 0; #endif - BM_SWAP_TIMER(send,size); /* SHCOPY corrupts the heap between * copy_shared_calculate, and @@ -747,8 +743,6 @@ erts_send_message(Process* sender, #else msize = size_object(message); #endif - BM_SWAP_TIMER(size,send); - mp = erts_alloc_message_heap_state(receiver, &receiver_state, receiver_locks, @@ -760,8 +754,6 @@ erts_send_message(Process* sender, &hp, &ohp); - BM_SWAP_TIMER(send,copy); - #ifdef SHCOPY_SEND if (is_not_immed(message)) message = copy_shared_perform(message, msize, &info, &hp, ohp); @@ -792,9 +784,6 @@ erts_send_message(Process* sender, msize, tok_label, tok_lastcnt, tok_serial); } #endif - BM_MESSAGE_COPIED(msize); - BM_SWAP_TIMER(copy,send); - } else { Eterm *hp; @@ -803,22 +792,18 @@ erts_send_message(Process* sender, msize = 0; } else { - BM_SWAP_TIMER(send,size); #ifdef SHCOPY_SEND INITIALIZE_SHCOPY(info); msize = copy_shared_calculate(message, &info); #else msize = size_object(message); #endif - BM_SWAP_TIMER(size,send); - mp = erts_alloc_message_heap_state(receiver, &receiver_state, receiver_locks, msize, &hp, &ohp); - BM_SWAP_TIMER(send,copy); #ifdef SHCOPY_SEND if (is_not_immed(message)) message = copy_shared_perform(message, msize, &info, &hp, ohp); @@ -827,8 +812,6 @@ erts_send_message(Process* sender, if (is_not_immed(message)) message = copy_struct(message, msize, &hp, ohp); #endif - BM_MESSAGE_COPIED(msz); - BM_SWAP_TIMER(copy,send); } #ifdef USE_VM_PROBES DTRACE6(message_send, sender_name, receiver_name, @@ -846,8 +829,6 @@ erts_send_message(Process* sender, mp, message, sender->common.id); - BM_SWAP_TIMER(send,system); - return res; } diff --git a/erts/emulator/beam/erl_msacc.c b/erts/emulator/beam/erl_msacc.c index 544bc8b983..421445fbad 100644 --- a/erts/emulator/beam/erl_msacc.c +++ b/erts/emulator/beam/erl_msacc.c @@ -40,10 +40,11 @@ #include "erl_bif_unique.h" #include "erl_map.h" #include "erl_msacc.h" +#include "erl_bif_table.h" #if ERTS_ENABLE_MSACC -static Eterm erts_msacc_gather_stats(ErtsMsAcc *msacc, Eterm **hpp, Uint *szp); +static Eterm erts_msacc_gather_stats(ErtsMsAcc *msacc, ErtsHeapFactory *factory); static void erts_msacc_reset(ErtsMsAcc *msacc); static ErtsMsAcc* get_msacc(void); @@ -52,7 +53,9 @@ erts_tsd_key_t ERTS_WRITE_UNLIKELY(erts_msacc_key); #else ErtsMsAcc *ERTS_WRITE_UNLIKELY(erts_msacc) = NULL; #endif +#ifndef ERTS_MSACC_ALWAYS_ON int ERTS_WRITE_UNLIKELY(erts_msacc_enabled); +#endif static Eterm *erts_msacc_state_atoms = NULL; static erts_rwmtx_t msacc_mutex; @@ -62,6 +65,12 @@ static ErtsMsAcc *msacc_unmanaged = NULL; static Uint msacc_unmanaged_count = 0; #endif +#if ERTS_MSACC_STATE_COUNT < MAP_SMALL_MAP_LIMIT +#define DEFAULT_MSACC_MSG_SIZE (3 + 1 + ERTS_MSACC_STATE_COUNT * 2 + 3 + REF_THING_SIZE) +#else +#define DEFAULT_MSACC_MSG_SIZE (3 + ERTS_MSACC_STATE_COUNT * 3 + 3 + REF_THING_SIZE) +#endif + /* we have to split initiation as atoms are not inited in early init */ void erts_msacc_early_init(void) { #ifndef ERTS_MSACC_ALWAYS_ON @@ -88,7 +97,8 @@ void erts_msacc_init(void) { void erts_msacc_init_thread(char *type, int id, int managed) { ErtsMsAcc *msacc; - msacc = erts_alloc(ERTS_ALC_T_MSACC, sizeof(ErtsMsAcc)); + msacc = erts_alloc(ERTS_ALC_T_MSACC, sizeof(ErtsMsAcc) + + sizeof(ErtsMsAccPerfCntr) * ERTS_MSACC_STATE_COUNT); msacc->type = strdup(type); msacc->id = make_small(id); @@ -122,79 +132,80 @@ void erts_msacc_init_thread(char *type, int id, int managed) { #endif } +#ifdef ERTS_MSACC_EXTENDED_STATES + +void erts_msacc_set_bif_state(ErtsMsAcc *__erts_msacc_cache, Eterm mod, void *fn) { + +#ifdef ERTS_MSACC_EXTENDED_BIFS +#define BIF_LIST(Mod,Func,Arity,FuncAddr,Num) \ + if (fn == &FuncAddr) { \ + ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATIC_STATE_COUNT + Num); \ + } else +#include "erl_bif_list.h" +#undef BIF_LIST + { /* The last else in the macro expansion, + this happens for internal bifs, i.e. traps etc */ + ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_BIF); + } +#else + if (mod == am_ets) { + ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_ETS); + } else { + ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_BIF); + } +#endif +} + +#endif + /* * Creates a structure looking like this * #{ type => scheduler, id => 1, counters => #{ State1 => Counter1 ... StateN => CounterN}} */ static -Eterm erts_msacc_gather_stats(ErtsMsAcc *msacc, Eterm **hpp, Uint *szp) { +Eterm erts_msacc_gather_stats(ErtsMsAcc *msacc, ErtsHeapFactory *factory) { + Uint sz = 0; + Eterm *hp, cvs[ERTS_MSACC_STATE_COUNT]; + Eterm key, state_map; int i; - Eterm *hp; - Eterm key, state_key, state_map; - Eterm res = THE_NON_VALUE; - flatmap_t *map; - - if (szp) { - *szp += MAP_HEADER_FLATMAP_SZ + 1 + 2*(3); - *szp += MAP_HEADER_FLATMAP_SZ + 1 + 2*(ERTS_MSACC_STATE_COUNT); - for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) { - (void)erts_bld_sint64(NULL,szp,(Sint64)msacc->perf_counters[i]); + flatmap_t *map; + + hp = erts_produce_heap(factory, 4, 0); + key = TUPLE3(hp,am_counters,am_id,am_type); + + for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) { + cvs[i] = erts_bld_sint64(NULL, &sz,(Sint64)msacc->counters[i].pc); #ifdef ERTS_MSACC_STATE_COUNTERS - (void)erts_bld_uint64(NULL,szp,msacc->state_counters[i]); - *szp += 3; /* tuple to put state+perf counter in */ + erts_bld_uint64(NULL,&sz,msacc->counters[i].sc); + sz += 3; #endif - } } - if (hpp) { - Eterm counters[ERTS_MSACC_STATE_COUNT]; - hp = *hpp; - for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) { - Eterm counter = erts_bld_sint64(&hp,NULL,(Sint64)msacc->perf_counters[i]); + hp = erts_produce_heap(factory, sz, 0); + + for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) { + cvs[i] = erts_bld_sint64(&hp,NULL,(Sint64)msacc->counters[i].pc); #ifdef ERTS_MSACC_STATE_COUNTERS - Eterm counter__ = erts_bld_uint64(&hp,NULL,msacc->state_counters[i]); - counters[i] = TUPLE2(hp,counter,counter__); - hp += 3; -#else - counters[i] = counter; + Eterm counter__ = erts_bld_uint64(&hp,NULL,msacc->counters[i].sc); + cvs[i] = TUPLE2(hp,cvs[i],counter__); + hp += 3; #endif - } - - key = TUPLE3(hp,am_counters,am_id,am_type); - hp += 4; - - state_key = make_tuple(hp); - hp[0] = make_arityval(ERTS_MSACC_STATE_COUNT); - - for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) - hp[1+i] = erts_msacc_state_atoms[i]; - hp += 1 + ERTS_MSACC_STATE_COUNT; - - map = (flatmap_t*)hp; - hp += MAP_HEADER_FLATMAP_SZ; - map->thing_word = MAP_HEADER_FLATMAP; - map->size = ERTS_MSACC_STATE_COUNT; - map->keys = state_key; - for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) - hp[i] = counters[i]; - hp += ERTS_MSACC_STATE_COUNT; - state_map = make_flatmap(map); - - map = (flatmap_t*)hp; - hp += MAP_HEADER_FLATMAP_SZ; - map->thing_word = MAP_HEADER_FLATMAP; - map->size = 3; - map->keys = key; - hp[0] = state_map; - hp[1] = msacc->id; - hp[2] = am_atom_put(msacc->type,strlen(msacc->type)); - hp += 3; - - *hpp = hp; - res = make_flatmap(map); } - return res; + state_map = erts_map_from_ks_and_vs(factory, erts_msacc_state_atoms, cvs, + ERTS_MSACC_STATE_COUNT); + + hp = erts_produce_heap(factory, MAP_HEADER_FLATMAP_SZ + 3, 0); + map = (flatmap_t*)hp; + hp += MAP_HEADER_FLATMAP_SZ; + map->thing_word = MAP_HEADER_FLATMAP; + map->size = 3; + map->keys = key; + hp[0] = state_map; + hp[1] = msacc->id; + hp[2] = am_atom_put(msacc->type,strlen(msacc->type)); + + return make_flatmap(map); } typedef struct { @@ -222,40 +233,31 @@ static void send_reply(ErtsMsAcc *msacc, ErtsMSAccReq *msaccrp) { ErtsSchedulerData *esdp = erts_get_scheduler_data(); Process *rp = msaccrp->proc; ErtsMessage *msgp = NULL; - Eterm **hpp, *hp; + Eterm *hp; Eterm ref_copy = NIL, msg; - Uint sz, *szp; - ErlOffHeap *ohp = NULL; ErtsProcLocks rp_locks = (esdp && msaccrp->req_sched == esdp->no ? ERTS_PROC_LOCK_MAIN : 0); + ErtsHeapFactory factory; - sz = 0; - hpp = NULL; - szp = &sz; - - if (msacc->unmanaged) erts_mtx_lock(&msacc->mtx); - - while (1) { - if (hpp) - ref_copy = STORE_NC(hpp, ohp, msaccrp->ref); - else - *szp += REF_THING_SIZE; - - if (msaccrp->action != ERTS_MSACC_GATHER) - msg = ref_copy; - else { - msg = erts_msacc_gather_stats(msacc, hpp, szp); - msg = erts_bld_tuple(hpp, szp, 2, ref_copy, msg); - } - if (hpp) - break; - - msgp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp); - hpp = &hp; - szp = NULL; - } + if (msaccrp->action == ERTS_MSACC_GATHER) { + + msgp = erts_factory_message_create(&factory, rp, &rp_locks, DEFAULT_MSACC_MSG_SIZE); + + if (msacc->unmanaged) erts_mtx_lock(&msacc->mtx); - if (msacc->unmanaged) erts_mtx_unlock(&msacc->mtx); + hp = erts_produce_heap(&factory, REF_THING_SIZE + 3 /* tuple */, 0); + ref_copy = STORE_NC(&hp, &msgp->hfrag.off_heap, msaccrp->ref); + msg = erts_msacc_gather_stats(msacc, &factory); + msg = TUPLE2(hp, ref_copy, msg); + + if (msacc->unmanaged) erts_mtx_unlock(&msacc->mtx); + + erts_factory_close(&factory); + } else { + ErlOffHeap *ohp = NULL; + msgp = erts_alloc_message_heap(rp, &rp_locks, REF_THING_SIZE, &hp, &ohp); + msg = STORE_NC(&hp, &msgp->hfrag.off_heap, msaccrp->ref); + } erts_queue_message(rp, rp_locks, msgp, msg, am_system); @@ -308,9 +310,9 @@ static void erts_msacc_reset(ErtsMsAcc *msacc) { if (msacc->unmanaged) erts_mtx_lock(&msacc->mtx); for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) { - msacc->perf_counters[i] = 0; + msacc->counters[i].pc = 0; #ifdef ERTS_MSACC_STATE_COUNTERS - msacc->state_counters[i] = 0; + msacc->counters[i].sc = 0; #endif } @@ -415,7 +417,7 @@ erts_msacc_request(Process *c_p, int action, Eterm *threads) ErtsSysPerfCounter perf_counter; /* if enabled update stats */ perf_counter = erts_sys_perf_counter(); - unmanaged[i]->perf_counters[unmanaged[i]->state] += + unmanaged[i]->counters[unmanaged[i]->state].pc += perf_counter - unmanaged[i]->perf_counter; unmanaged[i]->perf_counter = perf_counter; } @@ -454,7 +456,7 @@ erts_msacc_request(Process *c_p, int action, Eterm *threads) for (msacc = msacc_unmanaged; msacc != NULL; msacc = msacc->next) { erts_mtx_lock(&msacc->mtx); perf_counter = erts_sys_perf_counter(); - msacc->perf_counters[msacc->state] += perf_counter - msacc->perf_counter; + msacc->counters[msacc->state].pc += perf_counter - msacc->perf_counter; msacc->perf_counter = 0; erts_mtx_unlock(&msacc->mtx); } diff --git a/erts/emulator/beam/erl_msacc.h b/erts/emulator/beam/erl_msacc.h index 284388f7aa..ad7c8c5eee 100644 --- a/erts/emulator/beam/erl_msacc.h +++ b/erts/emulator/beam/erl_msacc.h @@ -35,6 +35,10 @@ this reduces overhead a little bit when profiling */ /* #define ERTS_MSACC_ALWAYS_ON 1 */ +/* Uncomment this to keep individual stats for all + of the bifs when extended states is enabled */ +/* #define ERTS_MSACC_EXTENDED_BIFS 1 */ + #define ERTS_MSACC_DISABLE 0 #define ERTS_MSACC_ENABLE 1 #define ERTS_MSACC_RESET 2 @@ -92,7 +96,13 @@ static char *erts_msacc_states[] = { #define ERTS_MSACC_STATE_SLEEP 13 #define ERTS_MSACC_STATE_TIMERS 14 -#define ERTS_MSACC_STATE_COUNT 15 +#define ERTS_MSACC_STATIC_STATE_COUNT 15 + +#ifdef ERTS_MSACC_EXTENDED_BIFS +#define ERTS_MSACC_STATE_COUNT (ERTS_MSACC_STATIC_STATE_COUNT + BIF_SIZE) +#else +#define ERTS_MSACC_STATE_COUNT ERTS_MSACC_STATIC_STATE_COUNT +#endif #if ERTS_MSACC_STATE_STRINGS static char *erts_msacc_states[] = { @@ -111,22 +121,26 @@ static char *erts_msacc_states[] = { "send", "sleep", "timers" +#ifdef ERTS_MSACC_EXTENDED_BIFS +#define BIF_LIST(Mod,Func,Arity,FuncAddr,Num) \ + ,"bif_" #Mod "_" #Func "_" #Arity +#include "erl_bif_list.h" +#undef BIF_LIST +#endif }; #endif #endif typedef struct erl_msacc_t_ ErtsMsAcc; - -struct erl_msacc_t_ { - - /* the the values below are protected by mtx iff unmanaged = 1 */ - ErtsSysPerfCounter perf_counter; - ErtsSysPerfCounter perf_counters[ERTS_MSACC_STATE_COUNT]; +typedef struct erl_msacc_p_cnt_t_ { + ErtsSysPerfCounter pc; #ifdef ERTS_MSACC_STATE_COUNTERS - Uint64 state_counters[ERTS_MSACC_STATE_COUNT]; + Uint64 sc; #endif - Uint state; +} ErtsMsAccPerfCntr; + +struct erl_msacc_t_ { /* protected by msacc_mutex in erl_msacc.c, and should be constant */ int unmanaged; @@ -135,12 +149,16 @@ struct erl_msacc_t_ { erts_tid_t tid; Eterm id; char *type; + + /* the the values below are protected by mtx iff unmanaged = 1 */ + ErtsSysPerfCounter perf_counter; + Uint state; + ErtsMsAccPerfCntr counters[]; + }; #if ERTS_ENABLE_MSACC -#define ERTS_MSACC_INLINE ERTS_GLB_INLINE - #ifdef USE_THREADS extern erts_tsd_key_t erts_msacc_key; #else @@ -276,20 +294,20 @@ void erts_msacc_init_thread(char *type, int id, int liberty); #define ERTS_MSACC_PUSH_AND_SET_STATE_M(state) \ ERTS_MSACC_PUSH_STATE_M(); ERTS_MSACC_SET_STATE_CACHED_M(state) -ERTS_MSACC_INLINE +ERTS_GLB_INLINE void erts_msacc_set_state_um__(ErtsMsAcc *msacc,Uint state,int increment); -ERTS_MSACC_INLINE +ERTS_GLB_INLINE void erts_msacc_set_state_m__(ErtsMsAcc *msacc,Uint state,int increment); -ERTS_MSACC_INLINE +ERTS_GLB_INLINE Uint erts_msacc_get_state_um__(ErtsMsAcc *msacc); -ERTS_MSACC_INLINE +ERTS_GLB_INLINE Uint erts_msacc_get_state_m__(ErtsMsAcc *msacc); #if ERTS_GLB_INLINE_INCL_FUNC_DEF -ERTS_MSACC_INLINE +ERTS_GLB_INLINE Uint erts_msacc_get_state_um__(ErtsMsAcc *msacc) { Uint state; if (msacc->unmanaged) @@ -300,12 +318,12 @@ Uint erts_msacc_get_state_um__(ErtsMsAcc *msacc) { return state; } -ERTS_MSACC_INLINE +ERTS_GLB_INLINE Uint erts_msacc_get_state_m__(ErtsMsAcc *msacc) { return msacc->state; } -ERTS_MSACC_INLINE +ERTS_GLB_INLINE void erts_msacc_set_state_um__(ErtsMsAcc *msacc, Uint new_state, int increment) { if (ERTS_UNLIKELY(msacc->unmanaged)) { erts_mtx_lock(&msacc->mtx); @@ -322,7 +340,7 @@ void erts_msacc_set_state_um__(ErtsMsAcc *msacc, Uint new_state, int increment) erts_mtx_unlock(&msacc->mtx); } -ERTS_MSACC_INLINE +ERTS_GLB_INLINE void erts_msacc_set_state_m__(ErtsMsAcc *msacc, Uint new_state, int increment) { ErtsSysPerfCounter prev_perf_counter; Sint64 diff; @@ -334,9 +352,9 @@ void erts_msacc_set_state_m__(ErtsMsAcc *msacc, Uint new_state, int increment) { msacc->perf_counter = erts_sys_perf_counter(); diff = msacc->perf_counter - prev_perf_counter; ASSERT(diff >= 0); - msacc->perf_counters[msacc->state] += diff; + msacc->counters[msacc->state].pc += diff; #ifdef ERTS_MSACC_STATE_COUNTERS - msacc->state_counters[new_state] += increment; + msacc->counters[new_state].sc += increment; #endif msacc->state = new_state; } @@ -364,7 +382,7 @@ void erts_msacc_set_state_m__(ErtsMsAcc *msacc, Uint new_state, int increment) { #define ERTS_MSACC_SET_STATE_CACHED_M(state) #define ERTS_MSACC_POP_STATE_M() #define ERTS_MSACC_PUSH_AND_SET_STATE_M(state) - +#define ERTS_MSACC_SET_BIF_STATE_CACHED_X(Mod,Addr) #endif /* ERTS_ENABLE_MSACC */ @@ -385,9 +403,13 @@ void erts_msacc_set_state_m__(ErtsMsAcc *msacc, Uint new_state, int increment) { #define ERTS_MSACC_SET_STATE_CACHED_M_X(state) #define ERTS_MSACC_POP_STATE_M_X() #define ERTS_MSACC_PUSH_AND_SET_STATE_M_X(state) +#define ERTS_MSACC_PUSH_AND_SET_STATE_CACHED_M_X(state) +#define ERTS_MSACC_SET_BIF_STATE_CACHED_X(Mod,Addr) #else +void erts_msacc_set_bif_state(ErtsMsAcc *msacc, Eterm mod, void *addr); + #define ERTS_MSACC_PUSH_STATE_X() ERTS_MSACC_PUSH_STATE() #define ERTS_MSACC_POP_STATE_X() ERTS_MSACC_POP_STATE() #define ERTS_MSACC_SET_STATE_X(state) ERTS_MSACC_SET_STATE(state) @@ -403,6 +425,9 @@ void erts_msacc_set_state_m__(ErtsMsAcc *msacc, Uint new_state, int increment) { #define ERTS_MSACC_SET_STATE_CACHED_M_X(state) ERTS_MSACC_SET_STATE_CACHED_M(state) #define ERTS_MSACC_POP_STATE_M_X() ERTS_MSACC_POP_STATE_M() #define ERTS_MSACC_PUSH_AND_SET_STATE_M_X(state) ERTS_MSACC_PUSH_AND_SET_STATE_M(state) +#define ERTS_MSACC_SET_BIF_STATE_CACHED_X(Mod,Addr) \ + if (ERTS_MSACC_IS_ENABLED_CACHED_X()) \ + erts_msacc_set_bif_state(__erts_msacc_cache, Mod, Addr) #endif /* !ERTS_MSACC_EXTENDED_STATES */ diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 23931f0e54..c6127a4967 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -3502,6 +3502,7 @@ Eterm erts_nif_call_function(Process *p, Process *tracee, struct enif_environment_t env; ErlHeapFragment *orig_hf = MBUF(p); ErlOffHeap orig_oh = MSO(p); + Eterm *orig_htop = HEAP_TOP(p); ASSERT(is_internal_pid(p->common.id)); MBUF(p) = NULL; clear_offheap(&MSO(p)); @@ -3523,6 +3524,7 @@ Eterm erts_nif_call_function(Process *p, Process *tracee, /* restore original heap fragment list */ MBUF(p) = orig_hf; MSO(p) = orig_oh; + HEAP_TOP(p) = orig_htop; } else { /* Nif call was done without a process context, so we create a phony one. */ diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 66f22979ad..b5d8c5bc75 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -8177,6 +8177,8 @@ sched_dirty_cpu_thread_func(void *vesdp) esdp->thr_id += erts_no_schedulers; + erts_msacc_init_thread("dirty_cpu_scheduler", no, 0); + erts_thr_progress_register_unmanaged_thread(&callbacks); #ifdef ERTS_ENABLE_LOCK_CHECK { @@ -8222,6 +8224,8 @@ sched_dirty_io_thread_func(void *vesdp) esdp->thr_id += erts_no_schedulers + erts_no_dirty_cpu_schedulers; + erts_msacc_init_thread("dirty_io_scheduler", no, 0); + erts_thr_progress_register_unmanaged_thread(&callbacks); #ifdef ERTS_ENABLE_LOCK_CHECK { @@ -9588,8 +9592,6 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls) erts_smp_runq_lock(rq); } } - BM_STOP_TIMER(system); - } ERTS_SMP_LC_ASSERT(!is_normal_sched || !erts_thr_progress_is_blocking()); @@ -9825,10 +9827,6 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls) goto check_activities_to_run; } - ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_EMULATOR); - - BM_START_TIMER(system); - /* * Take the chosen process out of the queue. */ @@ -9934,6 +9932,8 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls) } + ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_EMULATOR); + #ifdef ERTS_SMP if (flags & ERTS_RUNQ_FLG_PROTECTED) @@ -11154,18 +11154,11 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). || (erts_smp_atomic32_read_nob(&p->state) & ERTS_PSFLG_OFF_HEAP_MSGQ)); -#ifdef BM_COUNTERS - processes_busy++; -#endif - BM_COUNT(processes_spawned); - - BM_SWAP_TIMER(system,size); #ifdef SHCOPY_SPAWN arg_size = copy_shared_calculate(args, &info); #else arg_size = size_object(args); #endif - BM_SWAP_TIMER(size,system); heap_need = arg_size; p->flags = flags; @@ -11242,18 +11235,12 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->max_arg_reg = sizeof(p->def_arg_reg)/sizeof(p->def_arg_reg[0]); p->arg_reg[0] = mod; p->arg_reg[1] = func; - BM_STOP_TIMER(system); - BM_MESSAGE(args,p,parent); - BM_START_TIMER(system); - BM_SWAP_TIMER(system,copy); #ifdef SHCOPY_SPAWN p->arg_reg[2] = copy_shared_perform(args, arg_size, &info, &p->htop, &p->off_heap); DESTROY_SHCOPY(info); #else p->arg_reg[2] = copy_struct(args, arg_size, &p->htop, &p->off_heap); #endif - BM_MESSAGE_COPIED(arg_size); - BM_SWAP_TIMER(copy,system); p->arity = 3; p->fvalue = NIL; @@ -12826,9 +12813,6 @@ erts_continue_exit_process(Process *p) dep = (p->flags & F_DISTRIBUTION) ? erts_this_dist_entry : NULL; erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL); -#ifdef BM_COUNTERS - processes_busy--; -#endif if (dep) { erts_do_net_exits(dep, reason); diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 7c98b60647..714e63e986 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -989,8 +989,7 @@ struct process { Uint32 rcount; /* suspend count */ int schedule_count; /* Times left to reschedule a low prio process */ Uint reds; /* No of reductions for this process */ - Eterm group_leader; /* Pid in charge - (can be boxed) */ + Eterm group_leader; /* Pid in charge (can be boxed) */ Uint flags; /* Trap exit, etc (no trace flags anymore) */ Eterm fvalue; /* Exit & Throw value (failure reason) */ Uint freason; /* Reason for detected failure */ diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index 4cf38bf894..c4396488f5 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -493,8 +493,8 @@ erts_get_system_seq_tracer(void) if (st != erts_tracer_nil && call_enabled_tracer(st, NULL, TRACE_FUN_ENABLED, am_trace_status, am_undefined) == am_remove) { - erts_set_system_seq_tracer(NULL, 0, erts_tracer_nil); - st = erts_tracer_nil; + st = erts_set_system_seq_tracer(NULL, 0, erts_tracer_nil); + ERTS_TRACER_CLEAR(&st); } return st; @@ -3108,6 +3108,7 @@ erts_tracer_update(ErtsTracer *tracer, const ErtsTracer new_tracer) if (is_not_nil(*tracer)) { Uint offs = 2; UWord size = 2 * sizeof(Eterm) + sizeof(ErtsThrPrgrLaterOp); + ErtsThrPrgrLaterOp *lop; ASSERT(is_list(*tracer)); if (is_not_immed(ERTS_TRACER_STATE(*tracer))) { hf = (void*)(((char*)(ptr_val(*tracer)) - offsetof(ErlHeapFragment, mem))); @@ -3115,6 +3116,16 @@ erts_tracer_update(ErtsTracer *tracer, const ErtsTracer new_tracer) size = hf->alloc_size * sizeof(Eterm) + sizeof(ErlHeapFragment); ASSERT(offs == size_object(*tracer)); } + + /* sparc assumes that all structs are double word aligned, so we + have to align the ErtsThrPrgrLaterOp struct otherwise it may + segfault.*/ + if ((UWord)(ptr_val(*tracer) + offs) % (sizeof(UWord)*2) == sizeof(UWord)) + offs += 1; + + lop = (ErtsThrPrgrLaterOp*)(ptr_val(*tracer) + offs); + ASSERT((UWord)lop % (sizeof(UWord)*2) == 0); + /* We schedule the free:ing of the tracer until after a thread progress has been made so that we know that no schedulers have any references to it. Because we do this, it is possible to release all locks of a @@ -3122,9 +3133,7 @@ erts_tracer_update(ErtsTracer *tracer, const ErtsTracer new_tracer) without having to worry if it is free'd. */ erts_schedule_thr_prgr_later_cleanup_op( - free_tracer, (void*)(*tracer), - (ErtsThrPrgrLaterOp*)(ptr_val(*tracer) + offs), - size); + free_tracer, (void*)(*tracer), lop, size); } if (is_nil(new_tracer)) { @@ -3141,9 +3150,10 @@ erts_tracer_update(ErtsTracer *tracer, const ErtsTracer new_tracer) Eterm *hp, tracer_state = ERTS_TRACER_STATE(new_tracer), tracer_module = ERTS_TRACER_MODULE(new_tracer); Uint sz = size_object(tracer_state); - hf = new_message_buffer(sz + 2 /* cons cell */ + (sizeof(ErtsThrPrgrLaterOp)+sizeof(Eterm)-1)/sizeof(Eterm)); + hf = new_message_buffer(sz + 2 /* cons cell */ + + (sizeof(ErtsThrPrgrLaterOp)+sizeof(Eterm)-1)/sizeof(Eterm) + 1); hp = hf->mem + 2; - hf->used_size -= (sizeof(ErtsThrPrgrLaterOp)+sizeof(Eterm)-1)/sizeof(Eterm); + hf->used_size -= (sizeof(ErtsThrPrgrLaterOp)+sizeof(Eterm)-1)/sizeof(Eterm) + 1; *tracer = copy_struct(tracer_state, sz, &hp, &hf->off_heap); *tracer = CONS(hf->mem, tracer_module, *tracer); ASSERT((void*)(((char*)(ptr_val(*tracer)) - offsetof(ErlHeapFragment, mem))) == hf); diff --git a/erts/emulator/beam/export.h b/erts/emulator/beam/export.h index 8c81cbd410..1e7bb8514b 100644 --- a/erts/emulator/beam/export.h +++ b/erts/emulator/beam/export.h @@ -21,14 +21,8 @@ #ifndef __EXPORT_H__ #define __EXPORT_H__ -#ifndef __SYS_H__ #include "sys.h" -#endif - -#ifndef __INDEX_H__ #include "index.h" -#endif - #include "code_ix.h" /* diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index f3d4ac56cd..8933bcad16 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -35,7 +35,6 @@ #include "register.h" #include "erl_fun.h" #include "erl_node_tables.h" -#include "benchmark.h" #include "erl_process.h" #include "erl_sys_driver.h" #include "erl_debug.h" diff --git a/erts/emulator/beam/hash.c b/erts/emulator/beam/hash.c index e255b961f1..cd038d100b 100644 --- a/erts/emulator/beam/hash.c +++ b/erts/emulator/beam/hash.c @@ -35,9 +35,9 @@ static const int h_size_table[] = { 2, 5, 11, 23, 47, 97, 197, 397, 797, /* double upto here */ 1201, 1597, - 2411, 3203, + 2411, 3203, 4813, 6421, - 9643, 12853, + 9643, 12853, 19289, 25717, 51437, 102877, @@ -49,8 +49,8 @@ static const int h_size_table[] = { 6584983, 13169977, 26339969, - 52679969, - -1 + 52679969, + -1 }; /* @@ -69,7 +69,7 @@ void hash_get_info(HashInfo *hi, Hash *h) for (i = 0; i < size; i++) { int depth = 0; HashBucket* b = h->bucket[i]; - + while (b != (HashBucket*) 0) { objects++; depth++; @@ -112,7 +112,7 @@ void hash_info(int to, void *arg, Hash* h) /* * Returns size of table in bytes. Stored objects not included. */ -int +int hash_table_sz(Hash *h) { int i; @@ -190,7 +190,7 @@ void hash_delete(Hash* h) HashBucket* b = h->bucket[i]; while (b != (HashBucket*) 0) { HashBucket* b_next = b->next; - + h->fun.free((void*) b); b = b_next; } @@ -250,7 +250,7 @@ void* hash_get(Hash* h, void* tmpl) HashValue hval = h->fun.hash(tmpl); int ix = hval % h->size; HashBucket* b = h->bucket[ix]; - + while(b != (HashBucket*) 0) { if ((b->hvalue == hval) && (h->fun.cmp(tmpl, (void*)b) == 0)) return (void*) b; @@ -294,7 +294,7 @@ void* hash_erase(Hash* h, void* tmpl) int ix = hval % h->size; HashBucket* b = h->bucket[ix]; HashBucket* prev = 0; - + while(b != 0) { if ((b->hvalue == hval) && (h->fun.cmp(tmpl, (void*)b) == 0)) { if (prev != 0) @@ -326,7 +326,7 @@ hash_remove(Hash *h, void *tmpl) int ix = hval % h->size; HashBucket *b = h->bucket[ix]; HashBucket *prev = NULL; - + while (b) { if ((b->hvalue == hval) && (h->fun.cmp(tmpl, (void*)b) == 0)) { if (prev) @@ -355,4 +355,3 @@ void hash_foreach(Hash* h, void (*func)(void *, void *), void *func_arg2) } } } - diff --git a/erts/emulator/beam/hash.h b/erts/emulator/beam/hash.h index 9f773d8faa..4e769c0119 100644 --- a/erts/emulator/beam/hash.h +++ b/erts/emulator/beam/hash.h @@ -25,9 +25,7 @@ #ifndef __HASH_H__ #define __HASH_H__ -#ifndef __SYS_H__ #include "sys.h" -#endif typedef unsigned long HashValue; typedef struct hash Hash; diff --git a/erts/emulator/beam/index.h b/erts/emulator/beam/index.h index 218779c33b..0a109d8699 100644 --- a/erts/emulator/beam/index.h +++ b/erts/emulator/beam/index.h @@ -26,13 +26,8 @@ #ifndef __INDEX_H__ #define __INDEX_H__ -#ifndef __HASH_H__ #include "hash.h" -#endif - -#ifndef ERL_ALLOC_H__ #include "erl_alloc.h" -#endif typedef struct index_slot { diff --git a/erts/emulator/beam/module.h b/erts/emulator/beam/module.h index 4e12731d85..5a60bc90d9 100644 --- a/erts/emulator/beam/module.h +++ b/erts/emulator/beam/module.h @@ -21,9 +21,7 @@ #ifndef __MODULE_H__ #define __MODULE_H__ -#ifndef __INDEX_H__ #include "index.h" -#endif struct erl_module_instance { BeamCodeHeader* code_hdr; diff --git a/erts/emulator/beam/safe_hash.h b/erts/emulator/beam/safe_hash.h index 6910b33004..285103cb17 100644 --- a/erts/emulator/beam/safe_hash.h +++ b/erts/emulator/beam/safe_hash.h @@ -26,14 +26,9 @@ #ifndef __SAFE_HASH_H__ #define __SAFE_HASH_H__ - -#ifndef __SYS_H__ #include "sys.h" -#endif - #include "erl_alloc.h" - typedef unsigned long SafeHashValue; typedef int (*SHCMP_FUN)(void*, void*); diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 675fafa726..85647b8500 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -85,7 +85,7 @@ erts_heap_alloc(Process* p, Uint need, Uint xtra) && HEAP_TOP(p) >= p->space_verified_from && HEAP_TOP(p) + need <= p->space_verified_from + p->space_verified && HEAP_LIMIT(p) - HEAP_TOP(p) >= need) { - + Uint consumed = need + (HEAP_TOP(p) - p->space_verified_from); ASSERT(consumed <= p->space_verified); p->space_verified -= consumed; @@ -638,7 +638,7 @@ erts_bld_atom_uword_2tup_list(Uint **hpp, Uint *szp, ui = uint_to_big(uints[i], *hpp); *hpp += BIG_UINT_HEAP_SIZE; } - + res = CONS(*hpp+3, TUPLE2(*hpp, atoms[i], ui), res); *hpp += 5; } @@ -676,14 +676,14 @@ erts_bld_atom_2uint_3tup_list(Uint **hpp, Uint *szp, Sint length, ui1 = uint_to_big(uints1[i], *hpp); *hpp += BIG_UINT_HEAP_SIZE; } - + if (IS_USMALL(0, uints2[i])) ui2 = make_small(uints2[i]); else { ui2 = uint_to_big(uints2[i], *hpp); *hpp += BIG_UINT_HEAP_SIZE; } - + res = CONS(*hpp+4, TUPLE3(*hpp, atoms[i], ui1, ui2), res); *hpp += 6; } @@ -794,7 +794,7 @@ hash_binary_bytes(Eterm bin, Uint sz, Uint32 hash) Uint b; Uint lshift = bitoffs; Uint rshift = 8 - lshift; - + while (sz--) { b = (previous << lshift) & 0xFF; previous = *ptr++; @@ -805,7 +805,7 @@ hash_binary_bytes(Eterm bin, Uint sz, Uint32 hash) b = (previous << lshift) & 0xFF; previous = *ptr++; b |= previous >> rshift; - + b >>= 8 - bitsize; hash = (hash*FUNNY_NUMBER1 + b) * FUNNY_NUMBER12 + bitsize; } @@ -835,21 +835,21 @@ Uint32 make_hash(Eterm term_arg) do { \ Uint32 x = (Uint32) (Expr); \ hash = \ - (((((hash)*(Prime1) + (x & 0xFF)) * (Prime1) + \ - ((x >> 8) & 0xFF)) * (Prime1) + \ - ((x >> 16) & 0xFF)) * (Prime1) + \ + (((((hash)*(Prime1) + (x & 0xFF)) * (Prime1) + \ + ((x >> 8) & 0xFF)) * (Prime1) + \ + ((x >> 16) & 0xFF)) * (Prime1) + \ (x >> 24)); \ } while(0) -#define UINT32_HASH_RET(Expr, Prime1, Prime2) \ +#define UINT32_HASH_RET(Expr, Prime1, Prime2) \ UINT32_HASH_STEP(Expr, Prime1); \ hash = hash * (Prime2); \ - break - - + break + + /* * Significant additions needed for real 64 bit port with larger fixnums. - */ + */ /* * Note, for the simple 64bit port, not utilizing the @@ -864,7 +864,7 @@ tail_recur: hash = hash*FUNNY_NUMBER3 + 1; break; case ATOM_DEF: - hash = hash*FUNNY_NUMBER1 + + hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(term))->slot.bucket.hvalue); break; case SMALL_DEF: @@ -893,9 +893,9 @@ tail_recur: Export* ep = *((Export **) (export_val(term) + 1)); hash = hash * FUNNY_NUMBER11 + ep->code[2]; - hash = hash*FUNNY_NUMBER1 + + hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(ep->code[0]))->slot.bucket.hvalue); - hash = hash*FUNNY_NUMBER1 + + hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(ep->code[1]))->slot.bucket.hvalue); break; } @@ -906,7 +906,7 @@ tail_recur: Uint num_free = funp->num_free; hash = hash * FUNNY_NUMBER10 + num_free; - hash = hash*FUNNY_NUMBER1 + + hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(funp->fe->module))->slot.bucket.hvalue); hash = hash*FUNNY_NUMBER2 + funp->fe->old_index; hash = hash*FUNNY_NUMBER2 + funp->fe->old_uniq; @@ -931,7 +931,7 @@ tail_recur: UINT32_HASH_RET(internal_ref_numbers(term)[0],FUNNY_NUMBER9,FUNNY_NUMBER10); case EXTERNAL_REF_DEF: UINT32_HASH_RET(external_ref_numbers(term)[0],FUNNY_NUMBER9,FUNNY_NUMBER10); - case FLOAT_DEF: + case FLOAT_DEF: { FloatDef ff; GET_DOUBLE(term, ff); @@ -958,12 +958,12 @@ tail_recur: ** as multiplications on a Sparc is so slow. */ hash = hash*FUNNY_NUMBER2 + unsigned_val(*list); - + if (is_not_list(CDR(list))) { WSTACK_PUSH(stack, MAKE_HASH_CDR_POST_OP); term = CDR(list); goto tail_recur; - } + } list = list_val(CDR(list)); } WSTACK_PUSH2(stack, CDR(list), MAKE_HASH_CDR_PRE_OP); @@ -1004,17 +1004,17 @@ tail_recur: } hash *= is_neg ? FUNNY_NUMBER4 : FUNNY_NUMBER3; break; - } + } case MAP_DEF: hash = hash*FUNNY_NUMBER13 + FUNNY_NUMBER14 + make_hash2(term); break; - case TUPLE_DEF: + case TUPLE_DEF: { Eterm* ptr = tuple_val(term); Uint arity = arityval(*ptr); WSTACK_PUSH3(stack, (UWord) arity, (UWord)(ptr+1), (UWord) arity); - op = MAKE_HASH_TUPLE_OP; + op = MAKE_HASH_TUPLE_OP; }/*fall through*/ case MAKE_HASH_TUPLE_OP: case MAKE_HASH_TERM_ARRAY_OP: @@ -1031,8 +1031,8 @@ tail_recur: hash = hash*FUNNY_NUMBER9 + arity; } break; - } - + } + default: erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash(0x%X,0x%X)\n", term, op); return 0; @@ -1159,8 +1159,8 @@ make_hash2(Eterm term) if (y < 0) { \ UINT32_HASH(-y, AConst); \ /* Negative numbers are unnecessarily mixed twice. */ \ - } \ - UINT32_HASH(y, AConst); \ + } \ + UINT32_HASH(y, AConst); \ } while(0) #define IS_SSMALL28(x) (((Uint) (((x) >> (28-1)) + 1)) < 2) @@ -1242,7 +1242,7 @@ make_hash2(Eterm term) int arity = header_arity(hdr); Eterm* elem = tuple_val(term); UINT32_HASH(arity, HCONST_9); - if (arity == 0) /* Empty tuple */ + if (arity == 0) /* Empty tuple */ goto hash2_common; for (i = arity; ; i--) { term = elem[i]; @@ -1329,7 +1329,7 @@ make_hash2(Eterm term) { Export* ep = *((Export **) (export_val(term) + 1)); UINT32_HASH_2 - (ep->code[2], + (ep->code[2], atom_tab(atom_val(ep->code[0]))->slot.bucket.hvalue, HCONST); UINT32_HASH @@ -1343,7 +1343,7 @@ make_hash2(Eterm term) ErlFunThing* funp = (ErlFunThing *) fun_val(term); Uint num_free = funp->num_free; UINT32_HASH_2 - (num_free, + (num_free, atom_tab(atom_val(funp->fe->module))->slot.bucket.hvalue, HCONST); UINT32_HASH_2 @@ -1468,7 +1468,7 @@ make_hash2(Eterm term) goto hash2_common; } break; - + default: erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash2(0x%X)\n", term); } @@ -1541,7 +1541,7 @@ make_hash2(Eterm term) } case HASH_MAP_PAIR: hash_xor_pairs ^= hash; - hash = 0; + hash = 0; goto hash2_common; default: break; @@ -1678,17 +1678,22 @@ make_internal_hash(Eterm term) * the order in which keys and values are encountered. * We therefore calculate context independent hashes for all . * key-value pairs and then xor them together. + * + * We *do* need to use an initial seed for each pair, i.e. the + * hash value, so the hash value is reset for each pair with 'hash'. + * If we don't, no additional entropy is given to the system and the + * hash collision resolution in maps:from_list/1 would fail. */ ESTACK_PUSH(s, hash_xor_pairs); ESTACK_PUSH(s, hash); ESTACK_PUSH(s, HASH_MAP_TAIL); - hash = 0; - hash_xor_pairs = 0; for (i = size - 1; i >= 0; i--) { + ESTACK_PUSH(s, hash); /* initial seed for all pairs */ ESTACK_PUSH(s, HASH_MAP_PAIR); ESTACK_PUSH(s, vs[i]); ESTACK_PUSH(s, ks[i]); } + hash_xor_pairs = 0; goto pop_next; } case HAMT_SUBTAG_HEAD_ARRAY: @@ -1700,7 +1705,6 @@ make_internal_hash(Eterm term) ESTACK_PUSH(s, hash_xor_pairs); ESTACK_PUSH(s, hash); ESTACK_PUSH(s, HASH_MAP_TAIL); - hash = 0; hash_xor_pairs = 0; } switch (hdr & _HEADER_MAP_SUBTAG_MASK) { @@ -1717,6 +1721,7 @@ make_internal_hash(Eterm term) while (i) { if (is_list(*ptr)) { Eterm* cons = list_val(*ptr); + ESTACK_PUSH(s, hash); /* initial seed for all pairs */ ESTACK_PUSH(s, HASH_MAP_PAIR); ESTACK_PUSH(s, CDR(cons)); ESTACK_PUSH(s, CAR(cons)); @@ -1906,6 +1911,7 @@ make_internal_hash(Eterm term) pop_next: if (ESTACK_ISEMPTY(s)) { DESTROY_ESTACK(s); + return hash; } @@ -1920,7 +1926,7 @@ make_internal_hash(Eterm term) } case HASH_MAP_PAIR: hash_xor_pairs ^= hash; - hash = 0; + hash = (Uint32) ESTACK_POP(s); /* initial seed for all pairs */ goto pop_next; case HASH_CDR: @@ -1953,8 +1959,8 @@ Uint32 make_broken_hash(Eterm term) DECLARE_WSTACK(stack); unsigned op; tail_recur: - op = tag_val_def(term); - for (;;) { + op = tag_val_def(term); + for (;;) { switch (op) { case NIL_DEF: hash = hash*FUNNY_NUMBER3 + 1; @@ -1976,8 +1982,7 @@ tail_recur: { /* like a bignum */ Uint32 y4 = (Uint32) y2; hash = hash*FUNNY_NUMBER2 + ((y4 << 16) | (y4 >> 16)); - if (y3) - { + if (y3) { hash = hash*FUNNY_NUMBER2 + ((y3 << 16) | (y3 >> 16)); arity++; } @@ -2020,9 +2025,9 @@ tail_recur: Export* ep = *((Export **) (export_val(term) + 1)); hash = hash * FUNNY_NUMBER11 + ep->code[2]; - hash = hash*FUNNY_NUMBER1 + + hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(ep->code[0]))->slot.bucket.hvalue); - hash = hash*FUNNY_NUMBER1 + + hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(ep->code[1]))->slot.bucket.hvalue); break; } @@ -2033,7 +2038,7 @@ tail_recur: Uint num_free = funp->num_free; hash = hash * FUNNY_NUMBER10 + num_free; - hash = hash*FUNNY_NUMBER1 + + hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(funp->fe->module))->slot.bucket.hvalue); hash = hash*FUNNY_NUMBER2 + funp->fe->old_index; hash = hash*FUNNY_NUMBER2 + funp->fe->old_uniq; @@ -2065,7 +2070,7 @@ tail_recur: case EXTERNAL_REF_DEF: hash = hash*FUNNY_NUMBER9 + external_ref_numbers(term)[0]; break; - case FLOAT_DEF: + case FLOAT_DEF: { FloatDef ff; GET_DOUBLE(term, ff); @@ -2149,7 +2154,7 @@ tail_recur: } #else -#error "unsupported D_EXP size" +#error "unsupported D_EXP size" #endif hash = hash * (is_neg ? FUNNY_NUMBER3 : FUNNY_NUMBER2) + arity; } @@ -2158,14 +2163,14 @@ tail_recur: case MAP_DEF: hash = hash*FUNNY_NUMBER13 + FUNNY_NUMBER14 + make_hash2(term); break; - case TUPLE_DEF: + case TUPLE_DEF: { Eterm* ptr = tuple_val(term); Uint arity = arityval(*ptr); WSTACK_PUSH3(stack, (UWord) arity, (UWord) (ptr+1), (UWord) arity); op = MAKE_HASH_TUPLE_OP; - }/*fall through*/ + }/*fall through*/ case MAKE_HASH_TUPLE_OP: case MAKE_HASH_TERM_ARRAY_OP: { @@ -2193,7 +2198,7 @@ tail_recur: DESTROY_WSTACK(stack); return hash; - + #undef MAKE_HASH_TUPLE_OP #undef MAKE_HASH_TERM_ARRAY_OP #undef MAKE_HASH_CDR_PRE_OP @@ -2353,13 +2358,13 @@ static int do_send_term_to_logger(Eterm tag, Eterm gleader, } static ERTS_INLINE int -send_info_to_logger(Eterm gleader, char *buf, int len) +send_info_to_logger(Eterm gleader, char *buf, int len) { return do_send_to_logger(am_info_msg, gleader, buf, len); } static ERTS_INLINE int -send_warning_to_logger(Eterm gleader, char *buf, int len) +send_warning_to_logger(Eterm gleader, char *buf, int len) { Eterm tag; switch (erts_error_logger_warnings) { @@ -2371,7 +2376,7 @@ send_warning_to_logger(Eterm gleader, char *buf, int len) } static ERTS_INLINE int -send_error_to_logger(Eterm gleader, char *buf, int len) +send_error_to_logger(Eterm gleader, char *buf, int len) { return do_send_to_logger(am_error, gleader, buf, len); } @@ -2613,7 +2618,7 @@ tailrecur_ne: break; /* not equal */ case TAG_PRIMARY_BOXED: - { + { Eterm hdr = *boxed_val(a); switch (hdr & _TAG_HEADER_MASK) { case ARITYVAL_SUBTAG: @@ -2639,7 +2644,7 @@ tailrecur_ne: Uint b_bitsize; Uint a_bitoffs; Uint b_bitoffs; - + if (!is_binary(b)) { goto not_equal; } @@ -2671,7 +2676,7 @@ tailrecur_ne: { ErlFunThing* f1; ErlFunThing* f2; - + if (!is_fun(b)) goto not_equal; f1 = (ErlFunThing *) fun_val(a); @@ -2702,7 +2707,7 @@ tailrecur_ne: if(ap->header == bp->header && ap->node == bp->node) { ASSERT(1 == external_data_words(a)); ASSERT(1 == external_data_words(b)); - + if (ap->data.ui[0] == bp->data.ui[0]) goto pop_next; } break; /* not equal */ @@ -2759,7 +2764,7 @@ tailrecur_ne: if (alen == 3 && blen == 3) { /* Most refs are of length 3 */ if (anum[1] == bnum[1] && anum[2] == bnum[2]) { - goto pop_next; + goto pop_next; } else { goto not_equal; } @@ -2784,7 +2789,7 @@ tailrecur_ne: for (i = common_len; i < blen; i++) if (bnum[i] != 0) goto not_equal; - } + } } goto pop_next; } @@ -2792,7 +2797,7 @@ tailrecur_ne: case NEG_BIG_SUBTAG: { int i; - + if (!is_big(b)) goto not_equal; aa = big_val(a); @@ -2810,7 +2815,7 @@ tailrecur_ne: { FloatDef af; FloatDef bf; - + if (is_float(b)) { GET_DOUBLE(a, af); GET_DOUBLE(b, bf); @@ -2889,7 +2894,7 @@ term_array: /* arrays in 'aa' and 'bb', length in 'sz' */ } goto tailrecur_ne; } - + pop_next: if (!WSTACK_ISEMPTY(stack)) { UWord something = WSTACK_POP(stack); @@ -3093,7 +3098,7 @@ tailrecur_ne: } anode = erts_this_node; adata = internal_port_data(a); - + port_common: CMP_NODES(anode, bnode); ON_CMP_GOTO((Sint)(adata - bdata)); @@ -3111,7 +3116,7 @@ tailrecur_ne: } anode = erts_this_node; adata = internal_pid_data(a); - + pid_common: if (adata != bdata) { RETURN_NEQ(adata < bdata ? -1 : 1); @@ -3336,7 +3341,7 @@ tailrecur_ne: diff = f1->num_free - f2->num_free; if (diff != 0) { RETURN_NEQ(diff); - } + } i = f1->num_free; if (i == 0) goto pop_next; aa = f1->env; @@ -3397,10 +3402,10 @@ tailrecur_ne: anum = internal_thing_ref_numbers(athing); alen = internal_thing_ref_no_of_numbers(athing); } - + ref_common: CMP_NODES(anode, bnode); - + ASSERT(alen > 0 && blen > 0); if (alen != blen) { if (alen > blen) { @@ -3418,7 +3423,7 @@ tailrecur_ne: } while (alen < blen); } } - + ASSERT(alen == blen); for (i = (Sint) alen - 1; i >= 0; i--) if (anum[i] != bnum[i]) @@ -3633,8 +3638,8 @@ term_array: /* arrays in 'aa' and 'bb', length in 'i' */ } a = *aa; b = *bb; - goto tailrecur; - + goto tailrecur; + pop_next: if (!WSTACK_ISEMPTY(stack)) { UWord something = WSTACK_POP(stack); @@ -3897,19 +3902,19 @@ intlist_to_buf(Eterm list, char *buf, Sint len) Eterm* listptr; Sint sz = 0; - if (is_nil(list)) + if (is_nil(list)) return 0; if (is_not_list(list)) return -1; listptr = list_val(list); while (sz < len) { - if (!is_byte(*listptr)) + if (!is_byte(*listptr)) return -1; buf[sz++] = unsigned_val(*listptr); if (is_nil(*(listptr + 1))) return(sz); - if (is_not_list(*(listptr + 1))) + if (is_not_list(*(listptr + 1))) return -1; listptr = list_val(*(listptr + 1)); } @@ -4157,10 +4162,10 @@ do { \ } else if (yield_support && --yield_count <= 0) goto L_yield; } - + res = len; - L_return: + L_return: DESTROY_ESTACK(s); @@ -5053,7 +5058,7 @@ Process *p; if(p) print_process_info(ERTS_PRINT_STDERR, NULL, p); } - + void ppi(Eterm pid) { pp(erts_proc_lookup(pid)); @@ -5079,5 +5084,3 @@ ps(Process* p, Eterm* stop) } } #endif - - |