diff options
author | Erlang/OTP <[email protected]> | 2010-03-22 14:51:35 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2010-03-22 15:56:43 +0100 |
commit | a4b4d36cdbbd692123443a1d3f19f1c452963201 (patch) | |
tree | 218002c4a2b38f69eb67d6388c8034820812fd47 | |
parent | 835dba95f810cc925ac856171014b9dbea8c90be (diff) | |
parent | 24095d93fb28bdd60abe771a426e39c6ff0f72c7 (diff) | |
download | otp-a4b4d36cdbbd692123443a1d3f19f1c452963201.tar.gz otp-a4b4d36cdbbd692123443a1d3f19f1c452963201.tar.bz2 otp-a4b4d36cdbbd692123443a1d3f19f1c452963201.zip |
Merge branch 'pan/otp_8332_halfword' into dev
* pan/otp_8332_halfword:
Teach testcase in driver_suite the new prototype for driver_async
wx: Correct usage of driver callbacks from wx thread
Adopt the new (R13B04) Nif functionality to the halfword codebase
Support monitoring and demonitoring from driver threads
Fix further test-suite problems
Correct the VM to work for more test suites
Teach {wordsize,internal|external} to system_info/1
Make tracing and distribution work
Turn on instruction packing in the loader and virtual machine
Add the BeamInstr data type for loaded BEAM code
Fix the BEAM dissambler for the half-word emulator
Store pointers to heap data in 32-bit words
Add a custom mmap wrapper to force heaps into the lower address range
Fit all heap data into the 32-bit address range
95 files changed, 3791 insertions, 1821 deletions
diff --git a/configure.in b/configure.in index 4591df1099..9c815414da 100644 --- a/configure.in +++ b/configure.in @@ -195,6 +195,10 @@ AC_ARG_ENABLE(threads, [ --enable-threads enable async thread support --disable-threads disable async thread support]) +AC_ARG_ENABLE(halfword-emulator, +[ --enable-halfword-emulator enable halfword emulator (only for 64bit builds) + --disable-halfword-emulator disable halfword emulator (only for 64bit builds)]) + AC_ARG_ENABLE(smp-support, [ --enable-smp-support enable smp support --disable-smp-support disable smp support]) diff --git a/erts/configure.in b/erts/configure.in index 5fa1245b13..6823133936 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -123,6 +123,14 @@ AC_ARG_ENABLE(threads, *) enable_threads=yes ;; esac ], enable_threads=unknown) +AC_ARG_ENABLE(halfword-emulator, +[ --enable-halfword-emulator enable halfword emulator (only for 64bit builds) + --disable-halfword-emulator disable halfword emulator (only for 64bit builds)], +[ case "$enableval" in + no) enable_halfword_emualtor=no ;; + *) enable_halfword_emulator=yes ;; + esac ], enable_halfword_emulator=unknown) + AC_ARG_ENABLE(smp-support, [ --enable-smp-support enable smp support --disable-smp-support disable smp support], @@ -749,6 +757,25 @@ esac AC_SUBST(LIBCARBON) +dnl Check if we should/can build a halfword emulator + +AC_MSG_CHECKING(if we are building a halfword emulator (32bit heap on 64bit machine)) +if test "$enable_halfword_emulator" = "yes"; then + if test "$ARCH" = "amd64"; then + AC_DEFINE(HALFWORD_HEAP_EMULATOR, [1], + [Define if building a halfword-heap 64bit emulator]) + AC_MSG_RESULT([yes]) + else + AC_MSG_ERROR(no; halfword emulator not supported on this architecture) + fi +else + AC_MSG_RESULT([no]) +fi + + + + + dnl some tests below will call this if we haven't already - and autoconf dnl can't handle those tests being done conditionally at runtime AC_PROG_CPP diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index c4751d7463..c95a7005ec 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -5850,9 +5850,23 @@ true</pre> </item> <tag><c>wordsize</c></tag> <item> - <p>Returns the word size in bytes as an integer, i.e. on a - 32-bit architecture 4 is returned, and on a 64-bit - architecture 8 is returned.</p> + <p>Same as <c>{wordsize, internal}</c></p> + </item> + <tag><c>{wordsize, internal}</c></tag> + <item> + <p>Returns the size of Erlang term words in bytes as an + integer, i.e. on a 32-bit architecture 4 is returned, + and on a pure 64-bit architecture 8 is returned. On a + halfword 64-bit emulator, 4 is returned, as the Erlang + terms are stored using a virtual wordsize of half the + systems wordsize.</p> + </item> + <tag><c>{wordsize, external}</c></tag> + <item> + <p>Returns the true wordsize of the emulator, i.e. the size + of a pointer, in bytes as an integer. On a pure 32-bit + architecture 4 is returned, on both a halfword and pure + 64-bit architecture, 8 is returned.</p> </item> </taglist> <note> diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index 57c8b08223..9ce21089ba 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -256,6 +256,7 @@ atom info atom info_msg atom initial_call atom input +atom internal atom internal_error atom internal_status atom instruction_counts diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index b1feec7074..8462f1c7fd 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -39,10 +39,10 @@ static Eterm check_process_code(Process* rp, Module* modp); static void delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp); static void delete_export_references(Eterm module); static int purge_module(int module); -static int is_native(Eterm* code); +static int is_native(BeamInstr* code); static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size); static int any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size); -static void remove_from_address_table(Eterm* code); +static void remove_from_address_table(BeamInstr* code); Eterm load_module_2(BIF_ALIST_2) @@ -344,8 +344,8 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2) modp->code[MI_ON_LOAD_FUNCTION_PTR] = 0; set_default_trace_pattern(BIF_ARG_1); } else if (BIF_ARG_2 == am_false) { - Eterm* code; - Eterm* end; + BeamInstr* code; + BeamInstr* end; /* * The on_load function failed. Remove the loaded code. @@ -354,7 +354,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2) */ erts_total_code_size -= modp->code_length; code = modp->code; - end = (Eterm *)((char *)code + modp->code_length); + end = (BeamInstr *)((char *)code + modp->code_length); erts_cleanup_funs_on_purge(code, end); beam_catches_delmod(modp->catches, code, modp->code_length); erts_free(ERTS_ALC_T_CODE, (void *) code); @@ -397,10 +397,10 @@ set_default_trace_pattern(Eterm module) static Eterm check_process_code(Process* rp, Module* modp) { - Eterm* start; + BeamInstr* start; char* mod_start; Uint mod_size; - Eterm* end; + BeamInstr* end; Eterm* sp; #ifndef HYBRID /* FIND ME! */ ErlFunThing* funp; @@ -418,7 +418,7 @@ check_process_code(Process* rp, Module* modp) * Pick up limits for the module. */ start = modp->old_code; - end = (Eterm *)((char *)start + modp->old_code_length); + end = (BeamInstr *)((char *)start + modp->old_code_length); mod_start = (char *) start; mod_size = modp->old_code_length; @@ -472,11 +472,11 @@ check_process_code(Process* rp, Module* modp) #ifndef HYBRID /* FIND ME! */ rescan: for (funp = MSO(rp).funs; funp; funp = funp->next) { - Eterm* fun_code; + BeamInstr* fun_code; fun_code = funp->fe->address; - if (INSIDE((Eterm *) funp->fe->address)) { + if (INSIDE((BeamInstr *) funp->fe->address)) { if (done_gc) { return am_true; } else { @@ -576,7 +576,7 @@ any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size) switch (primary_tag(val)) { case TAG_PRIMARY_BOXED: case TAG_PRIMARY_LIST: - if (in_area(val, mod_start, mod_size)) { + if (in_area(EXPAND_POINTER(val), mod_start, mod_size)) { return 1; } break; @@ -596,7 +596,7 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size) switch (primary_tag(val)) { case TAG_PRIMARY_BOXED: case TAG_PRIMARY_LIST: - if (in_area(val, mod_start, mod_size)) { + if (in_area(EXPAND_POINTER(val), mod_start, mod_size)) { return 1; } break; @@ -617,8 +617,8 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size) static int purge_module(int module) { - Eterm* code; - Eterm* end; + BeamInstr* code; + BeamInstr* end; Module* modp; /* @@ -653,7 +653,7 @@ purge_module(int module) ASSERT(erts_total_code_size >= modp->old_code_length); erts_total_code_size -= modp->old_code_length; code = modp->old_code; - end = (Eterm *)((char *)code + modp->old_code_length); + end = (BeamInstr *)((char *)code + modp->old_code_length); erts_cleanup_funs_on_purge(code, end); beam_catches_delmod(modp->old_catches, code, modp->old_code_length); erts_free(ERTS_ALC_T_CODE, (void *) code); @@ -665,7 +665,7 @@ purge_module(int module) } static void -remove_from_address_table(Eterm* code) +remove_from_address_table(BeamInstr* code) { int i; @@ -738,11 +738,11 @@ delete_export_references(Eterm module) Export *ep = export_list(i); if (ep != NULL && (ep->code[0] == module)) { if (ep->address == ep->code+3 && - (ep->code[3] == (Eterm) em_apply_bif)) { + (ep->code[3] == (BeamInstr) em_apply_bif)) { continue; } ep->address = ep->code+3; - ep->code[3] = (Uint) em_call_error_handler; + ep->code[3] = (BeamInstr) em_call_error_handler; ep->code[4] = 0; MatchSetUnref(ep->match_prog_set); ep->match_prog_set = NULL; @@ -774,7 +774,7 @@ beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module) } static int -is_native(Eterm* code) +is_native(BeamInstr* code) { return ((Eterm *)code[MI_FUNCTIONS])[1] != 0; } diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 1abf1dc10c..6278ff6bad 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2000-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -109,23 +109,23 @@ do { \ */ static int set_break(Eterm mfa[3], int specified, - Binary *match_spec, Uint break_op, + Binary *match_spec, BeamInstr break_op, enum erts_break_op count_op, Eterm tracer_pid); static int set_module_break(Module *modp, Eterm mfa[3], int specified, - Binary *match_spec, Uint break_op, + Binary *match_spec, BeamInstr break_op, enum erts_break_op count_op, Eterm tracer_pid); -static int set_function_break(Module *modp, Uint *pc, - Binary *match_spec, Uint break_op, +static int set_function_break(Module *modp, BeamInstr *pc, + Binary *match_spec, BeamInstr break_op, enum erts_break_op count_op, Eterm tracer_pid); static int clear_break(Eterm mfa[3], int specified, - Uint break_op); + BeamInstr break_op); static int clear_module_break(Module *modp, Eterm mfa[3], int specified, - Uint break_op); -static int clear_function_break(Module *modp, Uint *pc, - Uint break_op); + BeamInstr break_op); +static int clear_function_break(Module *modp, BeamInstr *pc, + BeamInstr break_op); -static BpData *is_break(Uint *pc, Uint break_op); +static BpData *is_break(BeamInstr *pc, BeamInstr break_op); @@ -145,7 +145,7 @@ erts_set_trace_break(Eterm mfa[3], int specified, Binary *match_spec, Eterm tracer_pid) { ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); return set_break(mfa, specified, match_spec, - (Uint) BeamOp(op_i_trace_breakpoint), 0, tracer_pid); + (BeamInstr) BeamOp(op_i_trace_breakpoint), 0, tracer_pid); } int @@ -153,11 +153,11 @@ erts_set_mtrace_break(Eterm mfa[3], int specified, Binary *match_spec, Eterm tracer_pid) { ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); return set_break(mfa, specified, match_spec, - (Uint) BeamOp(op_i_mtrace_breakpoint), 0, tracer_pid); + (BeamInstr) BeamOp(op_i_mtrace_breakpoint), 0, tracer_pid); } void -erts_set_mtrace_bif(Uint *pc, Binary *match_spec, Eterm tracer_pid) { +erts_set_mtrace_bif(BeamInstr *pc, Binary *match_spec, Eterm tracer_pid) { BpDataTrace *bdt; ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); @@ -173,7 +173,7 @@ erts_set_mtrace_bif(Uint *pc, Binary *match_spec, Eterm tracer_pid) { MatchSetRef(match_spec); bdt->match_spec = match_spec; bdt->tracer_pid = tracer_pid; - pc[-4] = (Uint) bdt; + pc[-4] = (BeamInstr) bdt; } } @@ -181,14 +181,14 @@ int erts_set_debug_break(Eterm mfa[3], int specified) { ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); return set_break(mfa, specified, NULL, - (Uint) BeamOp(op_i_debug_breakpoint), 0, NIL); + (BeamInstr) BeamOp(op_i_debug_breakpoint), 0, NIL); } int erts_set_count_break(Eterm mfa[3], int specified, enum erts_break_op count_op) { ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); return set_break(mfa, specified, NULL, - (Uint) BeamOp(op_i_count_breakpoint), count_op, NIL); + (BeamInstr) BeamOp(op_i_count_breakpoint), count_op, NIL); } @@ -197,18 +197,18 @@ int erts_clear_trace_break(Eterm mfa[3], int specified) { ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); return clear_break(mfa, specified, - (Uint) BeamOp(op_i_trace_breakpoint)); + (BeamInstr) BeamOp(op_i_trace_breakpoint)); } int erts_clear_mtrace_break(Eterm mfa[3], int specified) { ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); return clear_break(mfa, specified, - (Uint) BeamOp(op_i_mtrace_breakpoint)); + (BeamInstr) BeamOp(op_i_mtrace_breakpoint)); } void -erts_clear_mtrace_bif(Uint *pc) { +erts_clear_mtrace_bif(BeamInstr *pc) { BpDataTrace *bdt; ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); @@ -219,21 +219,21 @@ erts_clear_mtrace_bif(Uint *pc) { } Free(bdt); } - pc[-4] = (Uint) NULL; + pc[-4] = (BeamInstr) NULL; } int erts_clear_debug_break(Eterm mfa[3], int specified) { ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); return clear_break(mfa, specified, - (Uint) BeamOp(op_i_debug_breakpoint)); + (BeamInstr) BeamOp(op_i_debug_breakpoint)); } int erts_clear_count_break(Eterm mfa[3], int specified) { ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); return clear_break(mfa, specified, - (Uint) BeamOp(op_i_count_breakpoint)); + (BeamInstr) BeamOp(op_i_count_breakpoint)); } int @@ -250,7 +250,7 @@ erts_clear_module_break(Module *modp) { } int -erts_clear_function_break(Module *modp, Uint *pc) { +erts_clear_function_break(Module *modp, BeamInstr *pc) { ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)); ASSERT(modp); return clear_function_break(modp, pc, 0); @@ -261,13 +261,13 @@ erts_clear_function_break(Module *modp, Uint *pc) { /* * SMP NOTE: Process p may have become exiting on return! */ -Uint -erts_trace_break(Process *p, Uint *pc, Eterm *args, +BeamInstr +erts_trace_break(Process *p, BeamInstr *pc, Eterm *args, Uint32 *ret_flags, Eterm *tracer_pid) { Eterm tpid1, tpid2; BpDataTrace *bdt = (BpDataTrace *) pc[-4]; - - ASSERT(pc[-5] == (Uint) BeamOp(op_i_func_info_IaaI)); + + ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); ASSERT(bdt); bdt = (BpDataTrace *) bdt->next; ASSERT(bdt); @@ -286,7 +286,7 @@ erts_trace_break(Process *p, Uint *pc, Eterm *args, bdt->tracer_pid = tpid2; ErtsSmpBPUnlock(bdt); } - pc[-4] = (Uint) bdt; + pc[-4] = (BeamInstr) bdt; return bdt->orig_instr; } @@ -296,10 +296,10 @@ erts_trace_break(Process *p, Uint *pc, Eterm *args, * SMP NOTE: Process p may have become exiting on return! */ Uint32 -erts_bif_mtrace(Process *p, Uint *pc, Eterm *args, int local, +erts_bif_mtrace(Process *p, BeamInstr *pc, Eterm *args, int local, Eterm *tracer_pid) { BpDataTrace *bdt = (BpDataTrace *) pc[-4]; - + ASSERT(tracer_pid); if (bdt) { Eterm tpid1, tpid2; @@ -326,9 +326,9 @@ erts_bif_mtrace(Process *p, Uint *pc, Eterm *args, int local, int -erts_is_trace_break(Uint *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) { +erts_is_trace_break(BeamInstr *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) { BpDataTrace *bdt = - (BpDataTrace *) is_break(pc, (Uint) BeamOp(op_i_trace_breakpoint)); + (BpDataTrace *) is_break(pc, (BeamInstr) BeamOp(op_i_trace_breakpoint)); if (bdt) { if (match_spec_ret) { @@ -345,9 +345,9 @@ erts_is_trace_break(Uint *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) { } int -erts_is_mtrace_break(Uint *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) { +erts_is_mtrace_break(BeamInstr *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) { BpDataTrace *bdt = - (BpDataTrace *) is_break(pc, (Uint) BeamOp(op_i_mtrace_breakpoint)); + (BpDataTrace *) is_break(pc, (BeamInstr) BeamOp(op_i_mtrace_breakpoint)); if (bdt) { if (match_spec_ret) { @@ -364,7 +364,7 @@ erts_is_mtrace_break(Uint *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) { } int -erts_is_mtrace_bif(Uint *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) { +erts_is_mtrace_bif(BeamInstr *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) { BpDataTrace *bdt = (BpDataTrace *) pc[-4]; if (bdt) { @@ -382,20 +382,20 @@ erts_is_mtrace_bif(Uint *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) { } int -erts_is_native_break(Uint *pc) { +erts_is_native_break(BeamInstr *pc) { #ifdef HIPE - ASSERT(pc[-5] == (Uint) BeamOp(op_i_func_info_IaaI)); - return pc[0] == (Uint) BeamOp(op_hipe_trap_call) - || pc[0] == (Uint) BeamOp(op_hipe_trap_call_closure); + ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); + return pc[0] == (BeamInstr) BeamOp(op_hipe_trap_call) + || pc[0] == (BeamInstr) BeamOp(op_hipe_trap_call_closure); #else return 0; #endif } int -erts_is_count_break(Uint *pc, Sint *count_ret) { +erts_is_count_break(BeamInstr *pc, Sint *count_ret) { BpDataCount *bdc = - (BpDataCount *) is_break(pc, (Uint) BeamOp(op_i_count_breakpoint)); + (BpDataCount *) is_break(pc, (BeamInstr) BeamOp(op_i_count_breakpoint)); if (bdc) { if (count_ret) { @@ -408,24 +408,24 @@ erts_is_count_break(Uint *pc, Sint *count_ret) { return 0; } -Uint * +BeamInstr * erts_find_local_func(Eterm mfa[3]) { Module *modp; - Uint** code_base; - Uint* code_ptr; + BeamInstr** code_base; + BeamInstr* code_ptr; Uint i,n; if ((modp = erts_get_module(mfa[0])) == NULL) return NULL; - if ((code_base = (Uint **) modp->code) == NULL) + if ((code_base = (BeamInstr **) modp->code) == NULL) return NULL; - n = (Uint) code_base[MI_NUM_FUNCTIONS]; + n = (BeamInstr) code_base[MI_NUM_FUNCTIONS]; for (i = 0; i < n; ++i) { code_ptr = code_base[MI_FUNCTIONS+i]; - ASSERT(((Uint) BeamOp(op_i_func_info_IaaI)) == code_ptr[0]); + ASSERT(((BeamInstr) BeamOp(op_i_func_info_IaaI)) == code_ptr[0]); ASSERT(mfa[0] == ((Eterm) code_ptr[2])); if (mfa[1] == ((Eterm) code_ptr[3]) && - ((Uint) mfa[2]) == code_ptr[4]) { + ((BeamInstr) mfa[2]) == code_ptr[4]) { return code_ptr + 5; } } @@ -440,7 +440,7 @@ erts_find_local_func(Eterm mfa[3]) { static int set_break(Eterm mfa[3], int specified, - Binary *match_spec, Eterm break_op, + Binary *match_spec, BeamInstr break_op, enum erts_break_op count_op, Eterm tracer_pid) { Module *modp; @@ -470,26 +470,26 @@ static int set_break(Eterm mfa[3], int specified, } static int set_module_break(Module *modp, Eterm mfa[3], int specified, - Binary *match_spec, Uint break_op, + Binary *match_spec, BeamInstr break_op, enum erts_break_op count_op, Eterm tracer_pid) { - Uint** code_base; - Uint* code_ptr; + BeamInstr** code_base; + BeamInstr* code_ptr; int num_processed = 0; Uint i,n; ASSERT(break_op); ASSERT(modp); - code_base = (Uint **) modp->code; + code_base = (BeamInstr **) modp->code; if (code_base == NULL) { return 0; } - n = (Uint) code_base[MI_NUM_FUNCTIONS]; + n = (BeamInstr) code_base[MI_NUM_FUNCTIONS]; for (i = 0; i < n; ++i) { code_ptr = code_base[MI_FUNCTIONS+i]; - ASSERT(code_ptr[0] == (Uint) BeamOp(op_i_func_info_IaaI)); + ASSERT(code_ptr[0] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); if ((specified < 2 || mfa[1] == ((Eterm) code_ptr[3])) && (specified < 3 || ((int) mfa[2]) == ((int) code_ptr[4]))) { - Uint *pc = code_ptr+5; + BeamInstr *pc = code_ptr+5; num_processed += set_function_break(modp, pc, match_spec, @@ -499,16 +499,16 @@ static int set_module_break(Module *modp, Eterm mfa[3], int specified, return num_processed; } -static int set_function_break(Module *modp, Uint *pc, - Binary *match_spec, Uint break_op, +static int set_function_break(Module *modp, BeamInstr *pc, + Binary *match_spec, BeamInstr break_op, enum erts_break_op count_op, Eterm tracer_pid) { BpData *bd, **r; size_t size; - Uint **code_base = (Uint **)modp->code; + BeamInstr **code_base = (BeamInstr **)modp->code; ASSERT(code_base); - ASSERT(code_base <= (Uint **)pc); - ASSERT((Uint **)pc < code_base + (modp->code_length/sizeof(Uint *))); + ASSERT(code_base <= (BeamInstr **)pc); + ASSERT((BeamInstr **)pc < code_base + (modp->code_length/sizeof(BeamInstr *))); /* * Currently no trace support for native code. */ @@ -517,8 +517,8 @@ static int set_function_break(Module *modp, Uint *pc, } /* Do not allow two breakpoints of the same kind */ if ( (bd = is_break(pc, break_op))) { - if (break_op == (Uint) BeamOp(op_i_trace_breakpoint) - || break_op == (Uint) BeamOp(op_i_mtrace_breakpoint)) { + if (break_op == (BeamInstr) BeamOp(op_i_trace_breakpoint) + || break_op == (BeamInstr) BeamOp(op_i_mtrace_breakpoint)) { BpDataTrace *bdt = (BpDataTrace *) bd; Binary *old_match_spec; @@ -533,7 +533,7 @@ static int set_function_break(Module *modp, Uint *pc, } else { ASSERT(! match_spec); ASSERT(is_nil(tracer_pid)); - if (break_op == (Uint) BeamOp(op_i_count_breakpoint)) { + if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) { BpDataCount *bdc = (BpDataCount *) bd; ErtsSmpBPLock(bdc); @@ -551,13 +551,13 @@ static int set_function_break(Module *modp, Uint *pc, } return 1; } - if (break_op == (Uint) BeamOp(op_i_trace_breakpoint) || - break_op == (Uint) BeamOp(op_i_mtrace_breakpoint)) { + if (break_op == (BeamInstr) BeamOp(op_i_trace_breakpoint) || + break_op == (BeamInstr) BeamOp(op_i_mtrace_breakpoint)) { size = sizeof(BpDataTrace); } else { ASSERT(! match_spec); ASSERT(is_nil(tracer_pid)); - if (break_op == (Uint) BeamOp(op_i_count_breakpoint)) { + if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) { if (count_op == erts_break_reset || count_op == erts_break_stop) { /* Do not insert a new breakpoint */ @@ -566,27 +566,27 @@ static int set_function_break(Module *modp, Uint *pc, size = sizeof(BpDataCount); } else { ASSERT(! count_op); - ASSERT(break_op == (Uint) BeamOp(op_i_debug_breakpoint)); + ASSERT(break_op == (BeamInstr) BeamOp(op_i_debug_breakpoint)); size = sizeof(BpDataDebug); } } r = (BpData **) (pc-4); if (! *r) { - ASSERT(*pc != (Uint) BeamOp(op_i_trace_breakpoint)); - ASSERT(*pc != (Uint) BeamOp(op_i_mtrace_breakpoint)); - ASSERT(*pc != (Uint) BeamOp(op_i_debug_breakpoint)); - ASSERT(*pc != (Uint) BeamOp(op_i_count_breakpoint)); + ASSERT(*pc != (BeamInstr) BeamOp(op_i_trace_breakpoint)); + ASSERT(*pc != (BeamInstr) BeamOp(op_i_mtrace_breakpoint)); + ASSERT(*pc != (BeamInstr) BeamOp(op_i_debug_breakpoint)); + ASSERT(*pc != (BeamInstr) BeamOp(op_i_count_breakpoint)); /* First breakpoint; create singleton ring */ bd = Alloc(size); BpInit(bd, *pc); *pc = break_op; *r = bd; } else { - ASSERT(*pc == (Uint) BeamOp(op_i_trace_breakpoint) || - *pc == (Uint) BeamOp(op_i_mtrace_breakpoint) || - *pc == (Uint) BeamOp(op_i_debug_breakpoint) || - *pc == (Uint) BeamOp(op_i_count_breakpoint)); - if (*pc == (Uint) BeamOp(op_i_debug_breakpoint)) { + ASSERT(*pc == (BeamInstr) BeamOp(op_i_trace_breakpoint) || + *pc == (BeamInstr) BeamOp(op_i_mtrace_breakpoint) || + *pc == (BeamInstr) BeamOp(op_i_debug_breakpoint) || + *pc == (BeamInstr) BeamOp(op_i_count_breakpoint)); + if (*pc == (BeamInstr) BeamOp(op_i_debug_breakpoint)) { /* Debug bp must be last, so if it is also first; * it must be singleton. */ ASSERT(BpSingleton(*r)); @@ -595,7 +595,7 @@ static int set_function_break(Module *modp, Uint *pc, BpInitAndSpliceNext(bd, *pc, *r); *pc = break_op; } else if ((*r)->prev->orig_instr - == (Uint) BeamOp(op_i_debug_breakpoint)) { + == (BeamInstr) BeamOp(op_i_debug_breakpoint)) { /* Debug bp last in the ring; insert new second to last. */ bd = Alloc(size); BpInitAndSplicePrev(bd, (*r)->prev->orig_instr, *r); @@ -609,24 +609,24 @@ static int set_function_break(Module *modp, Uint *pc, } } /* Init the bp type specific data */ - if (break_op == (Uint) BeamOp(op_i_trace_breakpoint) || - break_op == (Uint) BeamOp(op_i_mtrace_breakpoint)) { + if (break_op == (BeamInstr) BeamOp(op_i_trace_breakpoint) || + break_op == (BeamInstr) BeamOp(op_i_mtrace_breakpoint)) { BpDataTrace *bdt = (BpDataTrace *) bd; MatchSetRef(match_spec); bdt->match_spec = match_spec; bdt->tracer_pid = tracer_pid; - } else if (break_op == (Uint) BeamOp(op_i_count_breakpoint)) { + } else if (break_op == (BeamInstr) BeamOp(op_i_count_breakpoint)) { BpDataCount *bdc = (BpDataCount *) bd; bdc->count = 0; } - ++(*(Uint*)&code_base[MI_NUM_BREAKPOINTS]); + ++(*(BeamInstr*)&code_base[MI_NUM_BREAKPOINTS]); return 1; } -static int clear_break(Eterm mfa[3], int specified, Uint break_op) +static int clear_break(Eterm mfa[3], int specified, BeamInstr break_op) { int num_processed = 0; Module *modp; @@ -652,23 +652,24 @@ static int clear_break(Eterm mfa[3], int specified, Uint break_op) } static int clear_module_break(Module *m, Eterm mfa[3], int specified, - Uint break_op) { - Uint** code_base; - Uint* code_ptr; + BeamInstr break_op) { + BeamInstr** code_base; + BeamInstr* code_ptr; int num_processed = 0; - Uint i,n; + Uint i; + BeamInstr n; ASSERT(m); - code_base = (Uint **) m->code; + code_base = (BeamInstr **) m->code; if (code_base == NULL) { return 0; } - n = (Uint) code_base[MI_NUM_FUNCTIONS]; + n = (BeamInstr) code_base[MI_NUM_FUNCTIONS]; for (i = 0; i < n; ++i) { code_ptr = code_base[MI_FUNCTIONS+i]; if ((specified < 2 || mfa[1] == ((Eterm) code_ptr[3])) && (specified < 3 || ((int) mfa[2]) == ((int) code_ptr[4]))) { - Uint *pc = code_ptr + 5; + BeamInstr *pc = code_ptr + 5; num_processed += clear_function_break(m, pc, break_op); @@ -677,13 +678,13 @@ static int clear_module_break(Module *m, Eterm mfa[3], int specified, return num_processed; } -static int clear_function_break(Module *m, Uint *pc, Uint break_op) { +static int clear_function_break(Module *m, BeamInstr *pc, BeamInstr break_op) { BpData *bd; - Uint **code_base = (Uint **)m->code; + BeamInstr **code_base = (BeamInstr **)m->code; ASSERT(code_base); - ASSERT(code_base <= (Uint **)pc); - ASSERT((Uint **)pc < code_base + (m->code_length/sizeof(Uint *))); + ASSERT(code_base <= (BeamInstr **)pc); + ASSERT((BeamInstr **)pc < code_base + (m->code_length/sizeof(BeamInstr *))); /* * Currently no trace support for native code. */ @@ -695,7 +696,7 @@ static int clear_function_break(Module *m, Uint *pc, Uint break_op) { * There should be only one of each type, * but break_op may be 0 which matches any type. */ - Uint op; + BeamInstr op; BpData **r = (BpData **) (pc-4); ASSERT(*r); @@ -731,16 +732,16 @@ static int clear_function_break(Module *m, Uint *pc, Uint break_op) { bd_prev->orig_instr = bd->orig_instr; } } - if (op == (Uint) BeamOp(op_i_trace_breakpoint) || - op == (Uint) BeamOp(op_i_mtrace_breakpoint)) { + if (op == (BeamInstr) BeamOp(op_i_trace_breakpoint) || + op == (BeamInstr) BeamOp(op_i_mtrace_breakpoint)) { BpDataTrace *bdt = (BpDataTrace *) bd; - + MatchSetUnref(bdt->match_spec); } Free(bd); - ASSERT(((Uint) code_base[MI_NUM_BREAKPOINTS]) > 0); - --(*(Uint*)&code_base[MI_NUM_BREAKPOINTS]); + ASSERT(((BeamInstr) code_base[MI_NUM_BREAKPOINTS]) > 0); + --(*(BeamInstr*)&code_base[MI_NUM_BREAKPOINTS]); } return 1; } @@ -754,8 +755,8 @@ static int clear_function_break(Module *m, Uint *pc, Uint break_op) { ** returned. The program counter must point to the first executable ** (breakpoint) instruction of the function. */ -static BpData *is_break(Uint *pc, Uint break_op) { - ASSERT(pc[-5] == (Uint) BeamOp(op_i_func_info_IaaI)); +static BpData *is_break(BeamInstr *pc, BeamInstr break_op) { + ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); if (! erts_is_native_break(pc)) { BpData *bd = (BpData *) pc[-4]; diff --git a/erts/emulator/beam/beam_bp.h b/erts/emulator/beam/beam_bp.h index 44e6b294d8..786cbbe9d9 100644 --- a/erts/emulator/beam/beam_bp.h +++ b/erts/emulator/beam/beam_bp.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2000-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -48,7 +48,7 @@ typedef struct bp_data { struct bp_data *next; /* Doubly linked ring pointers */ struct bp_data *prev; /* -"- */ - Uint orig_instr; /* The original instruction to execute */ + BeamInstr orig_instr; /* The original instruction to execute */ } BpData; /* ** All the following bp_data_.. structs must begin the same way @@ -57,21 +57,21 @@ typedef struct bp_data { typedef struct bp_data_trace { struct bp_data *next; struct bp_data *prev; - Uint orig_instr; + BeamInstr orig_instr; Binary *match_spec; - Eterm tracer_pid; + Eterm tracer_pid; } BpDataTrace; typedef struct bp_data_debug { struct bp_data *next; struct bp_data *prev; - Uint orig_instr; + BeamInstr orig_instr; } BpDataDebug; typedef struct bp_data_count { /* Call count */ struct bp_data *next; struct bp_data *prev; - Uint orig_instr; + BeamInstr orig_instr; Sint count; } BpDataCount; @@ -89,11 +89,11 @@ extern erts_smp_spinlock_t erts_bp_lock; do { \ BpDataCount *bdc = (BpDataCount *) (pc)[-4]; \ \ - ASSERT((pc)[-5] == (Uint) BeamOp(op_i_func_info_IaaI)); \ + ASSERT((pc)[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); \ ASSERT(bdc); \ bdc = (BpDataCount *) bdc->next; \ ASSERT(bdc); \ - (pc)[-4] = (Uint) bdc; \ + (pc)[-4] = (BeamInstr) bdc; \ ErtsSmpBPLock(bdc); \ if (bdc->count >= 0) bdc->count++; \ ErtsSmpBPUnlock(bdc); \ @@ -104,11 +104,11 @@ do { \ do { \ BpData *bd = (BpData *) (pc)[-4]; \ \ - ASSERT((pc)[-5] == (Uint) BeamOp(op_i_func_info_IaaI)); \ + ASSERT((pc)[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); \ ASSERT(bd); \ bd = bd->next; \ ASSERT(bd); \ - (pc)[-4] = (Uint) bd; \ + (pc)[-4] = (BeamInstr) bd; \ *(instr_result) = bd->orig_instr; \ } while (0) @@ -133,9 +133,9 @@ int erts_clear_trace_break(Eterm mfa[3], int specified); int erts_set_mtrace_break(Eterm mfa[3], int specified, Binary *match_spec, Eterm tracer_pid); int erts_clear_mtrace_break(Eterm mfa[3], int specified); -void erts_set_mtrace_bif(Uint *pc, Binary *match_spec, +void erts_set_mtrace_bif(BeamInstr *pc, Binary *match_spec, Eterm tracer_pid); -void erts_clear_mtrace_bif(Uint *pc); +void erts_clear_mtrace_bif(BeamInstr *pc); int erts_set_debug_break(Eterm mfa[3], int specified); int erts_clear_debug_break(Eterm mfa[3], int specified); int erts_set_count_break(Eterm mfa[3], int specified, enum erts_break_op); @@ -144,22 +144,22 @@ int erts_clear_count_break(Eterm mfa[3], int specified); int erts_clear_break(Eterm mfa[3], int specified); int erts_clear_module_break(Module *modp); -int erts_clear_function_break(Module *modp, Uint *pc); +int erts_clear_function_break(Module *modp, BeamInstr *pc); -Uint erts_trace_break(Process *p, Uint *pc, Eterm *args, +BeamInstr erts_trace_break(Process *p, BeamInstr *pc, Eterm *args, Uint32 *ret_flags, Eterm *tracer_pid); -Uint32 erts_bif_mtrace(Process *p, Uint *pc, Eterm *args, +Uint32 erts_bif_mtrace(Process *p, BeamInstr *pc, Eterm *args, int local, Eterm *tracer_pid); -int erts_is_trace_break(Uint *pc, Binary **match_spec_ret, +int erts_is_trace_break(BeamInstr *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret); -int erts_is_mtrace_break(Uint *pc, Binary **match_spec_ret, +int erts_is_mtrace_break(BeamInstr *pc, Binary **match_spec_ret, Eterm *tracer_pid_rte); -int erts_is_mtrace_bif(Uint *pc, Binary **match_spec_ret, +int erts_is_mtrace_bif(BeamInstr *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret); -int erts_is_native_break(Uint *pc); -int erts_is_count_break(Uint *pc, Sint *count_ret); +int erts_is_native_break(BeamInstr *pc); +int erts_is_count_break(BeamInstr *pc, Sint *count_ret); -Uint *erts_find_local_func(Eterm mfa[3]); +BeamInstr *erts_find_local_func(Eterm mfa[3]); #endif /* _BEAM_BP_H */ diff --git a/erts/emulator/beam/beam_catches.c b/erts/emulator/beam/beam_catches.c index d5cef1cad2..e795b4efbd 100644 --- a/erts/emulator/beam/beam_catches.c +++ b/erts/emulator/beam/beam_catches.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2000-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -26,7 +26,7 @@ /* XXX: should use dynamic reallocation */ #define TABSIZ (16*1024) static struct { - Eterm *cp; + BeamInstr *cp; unsigned cdr; } beam_catches[TABSIZ]; @@ -39,7 +39,7 @@ void beam_catches_init(void) high_mark = 0; } -unsigned beam_catches_cons(Eterm *cp, unsigned cdr) +unsigned beam_catches_cons(BeamInstr *cp, unsigned cdr) { int i; @@ -65,7 +65,7 @@ unsigned beam_catches_cons(Eterm *cp, unsigned cdr) return i; } -Eterm *beam_catches_car(unsigned i) +BeamInstr *beam_catches_car(unsigned i) { if( i >= TABSIZ ) { fprintf(stderr, @@ -75,7 +75,7 @@ Eterm *beam_catches_car(unsigned i) return beam_catches[i].cp; } -void beam_catches_delmod(unsigned head, Eterm *code, unsigned code_bytes) +void beam_catches_delmod(unsigned head, BeamInstr *code, unsigned code_bytes) { unsigned i, cdr; diff --git a/erts/emulator/beam/beam_catches.h b/erts/emulator/beam/beam_catches.h index ccf33d5e86..6223427f0d 100644 --- a/erts/emulator/beam/beam_catches.h +++ b/erts/emulator/beam/beam_catches.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2000-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -23,9 +23,9 @@ #define BEAM_CATCHES_NIL (-1) void beam_catches_init(void); -unsigned beam_catches_cons(Eterm* cp, unsigned cdr); -Eterm *beam_catches_car(unsigned i); -void beam_catches_delmod(unsigned head, Eterm* code, unsigned code_bytes); +unsigned beam_catches_cons(BeamInstr* cp, unsigned cdr); +BeamInstr *beam_catches_car(unsigned i); +void beam_catches_delmod(unsigned head, BeamInstr* code, unsigned code_bytes); #define catch_pc(x) beam_catches_car(catch_val((x))) diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c index 4242a4161e..23b267d5cd 100644 --- a/erts/emulator/beam/beam_debug.c +++ b/erts/emulator/beam/beam_debug.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -43,12 +43,13 @@ #else # define HEXF "%08bpX" #endif +#define TermWords(t) (((t) / (sizeof(BeamInstr)/sizeof(Eterm))) + !!((t) % (sizeof(BeamInstr)/sizeof(Eterm)))) void dbg_bt(Process* p, Eterm* sp); -void dbg_where(Eterm* addr, Eterm x0, Eterm* reg); +void dbg_where(BeamInstr* addr, Eterm x0, Eterm* reg); static void print_big(int to, void *to_arg, Eterm* addr); -static int print_op(int to, void *to_arg, int op, int size, Eterm* addr); +static int print_op(int to, void *to_arg, int op, int size, BeamInstr* addr); Eterm erts_debug_same_2(Process* p, Eterm term1, Eterm term2) { @@ -124,6 +125,38 @@ erts_debug_breakpoint_2(Process* p, Eterm MFA, Eterm bool) BIF_ERROR(p, BADARG); } +#if 0 /* XXX:PaN - not used */ +void debug_dump_code(BeamInstr *I, int num) +{ + BeamInstr *code_ptr = I; + BeamInstr *end = code_ptr + num; + erts_dsprintf_buf_t *dsbufp; + BeamInstr instr; + int i; + + dsbufp = erts_create_tmp_dsbuf(0); + while (code_ptr < end) { + erts_print(ERTS_PRINT_DSBUF, (void *) dsbufp, HEXF ": ", code_ptr); + instr = (BeamInstr) code_ptr[0]; + for (i = 0; i < NUM_SPECIFIC_OPS; i++) { + if (instr == (BeamInstr) BeamOp(i) && opc[i].name[0] != '\0') { + code_ptr += print_op(ERTS_PRINT_DSBUF, (void *) dsbufp, + i, opc[i].sz-1, code_ptr+1) + 1; + break; + } + } + if (i >= NUM_SPECIFIC_OPS) { + erts_print(ERTS_PRINT_DSBUF, (void *) dsbufp, + "unknown " HEXF "\n", instr); + code_ptr++; + } + } + dsbufp->str[dsbufp->str_len] = 0; + erts_fprintf(stderr,"%s", dsbufp->str); + erts_destroy_tmp_dsbuf(dsbufp); +} +#endif + Eterm erts_debug_disassemble_1(Process* p, Eterm addr) { @@ -132,16 +165,16 @@ erts_debug_disassemble_1(Process* p, Eterm addr) Eterm* tp; Eterm bin; Eterm mfa; - Eterm* funcinfo = NULL; /* Initialized to eliminate warning. */ - Uint* code_base; - Uint* code_ptr = NULL; /* Initialized to eliminate warning. */ - Uint instr; - Uint uaddr; + BeamInstr* funcinfo = NULL; /* Initialized to eliminate warning. */ + BeamInstr* code_base; + BeamInstr* code_ptr = NULL; /* Initialized to eliminate warning. */ + BeamInstr instr; + BeamInstr uaddr; Uint hsz; int i; - if (term_to_Uint(addr, &uaddr)) { - code_ptr = (Uint *) uaddr; + if (term_to_UWord(addr, &uaddr)) { + code_ptr = (BeamInstr *) uaddr; if ((funcinfo = find_function_from_pc(code_ptr)) == NULL) { BIF_RET(am_false); } @@ -180,14 +213,14 @@ erts_debug_disassemble_1(Process* p, Eterm addr) * But this code_ptr will point to the start of the Export, * not the function's func_info instruction. BOOM !? */ - code_ptr = ((Eterm *) ep->address) - 5; + code_ptr = ((BeamInstr *) ep->address) - 5; funcinfo = code_ptr+2; } else if (modp == NULL || (code_base = modp->code) == NULL) { BIF_RET(am_undef); } else { n = code_base[MI_NUM_FUNCTIONS]; for (i = 0; i < n; i++) { - code_ptr = (Uint *) code_base[MI_FUNCTIONS+i]; + code_ptr = (BeamInstr *) code_base[MI_FUNCTIONS+i]; if (code_ptr[3] == name && code_ptr[4] == arity) { funcinfo = code_ptr+2; break; @@ -203,9 +236,9 @@ erts_debug_disassemble_1(Process* p, Eterm addr) dsbufp = erts_create_tmp_dsbuf(0); erts_print(ERTS_PRINT_DSBUF, (void *) dsbufp, HEXF ": ", code_ptr); - instr = (Uint) code_ptr[0]; + instr = (BeamInstr) code_ptr[0]; for (i = 0; i < NUM_SPECIFIC_OPS; i++) { - if (instr == (Uint) BeamOp(i) && opc[i].name[0] != '\0') { + if (instr == (BeamInstr) BeamOp(i) && opc[i].name[0] != '\0') { code_ptr += print_op(ERTS_PRINT_DSBUF, (void *) dsbufp, i, opc[i].sz-1, code_ptr+1) + 1; break; @@ -219,12 +252,12 @@ erts_debug_disassemble_1(Process* p, Eterm addr) bin = new_binary(p, (byte *) dsbufp->str, (int) dsbufp->str_len); erts_destroy_tmp_dsbuf(dsbufp); hsz = 4+4; - (void) erts_bld_uint(NULL, &hsz, (Uint) code_ptr); + (void) erts_bld_uword(NULL, &hsz, (BeamInstr) code_ptr); hp = HAlloc(p, hsz); - addr = erts_bld_uint(&hp, NULL, (Uint) code_ptr); + addr = erts_bld_uword(&hp, NULL, (BeamInstr) code_ptr); ASSERT(is_atom(funcinfo[0])); ASSERT(is_atom(funcinfo[1])); - mfa = TUPLE3(hp, funcinfo[0], funcinfo[1], make_small(funcinfo[2])); + mfa = TUPLE3(hp, (Eterm) funcinfo[0], (Eterm) funcinfo[1], make_small((Eterm) funcinfo[2])); hp += 4; return TUPLE3(hp, addr, bin, mfa); } @@ -236,20 +269,20 @@ dbg_bt(Process* p, Eterm* sp) while (sp < stack) { if (is_CP(*sp)) { - Eterm* addr = find_function_from_pc(cp_val(*sp)); + BeamInstr* addr = find_function_from_pc(cp_val(*sp)); if (addr) erts_fprintf(stderr, HEXF ": %T:%T/%bpu\n", - addr, addr[0], addr[1], addr[2]); + addr, (Eterm) addr[0], (Eterm) addr[1], (Uint) addr[2]); } sp++; } } void -dbg_where(Eterm* addr, Eterm x0, Eterm* reg) +dbg_where(BeamInstr* addr, Eterm x0, Eterm* reg) { - Eterm* f = find_function_from_pc(addr); + BeamInstr* f = find_function_from_pc(addr); if (f == NULL) { erts_fprintf(stderr, "???\n"); @@ -259,7 +292,7 @@ dbg_where(Eterm* addr, Eterm x0, Eterm* reg) addr = f; arity = addr[2]; - erts_fprintf(stderr, HEXF ": %T:%T(", addr, addr[0], addr[1]); + erts_fprintf(stderr, HEXF ": %T:%T(", addr, (Eterm) addr[0], (Eterm) addr[1]); for (i = 0; i < arity; i++) erts_fprintf(stderr, i ? ", %T" : "%T", i ? reg[i] : x0); erts_fprintf(stderr, ")\n"); @@ -267,18 +300,18 @@ dbg_where(Eterm* addr, Eterm x0, Eterm* reg) } static int -print_op(int to, void *to_arg, int op, int size, Eterm* addr) +print_op(int to, void *to_arg, int op, int size, BeamInstr* addr) { int i; - Uint tag; + BeamInstr tag; char* sign; char* start_prog; /* Start of program for packer. */ char* prog; /* Current position in packer program. */ - Uint stack[8]; /* Stack for packer. */ - Uint* sp = stack; /* Points to next free position. */ - Uint packed = 0; /* Accumulator for packed operations. */ - Uint args[8]; /* Arguments for this instruction. */ - Uint* ap; /* Pointer to arguments. */ + BeamInstr stack[8]; /* Stack for packer. */ + BeamInstr* sp = stack; /* Points to next free position. */ + BeamInstr packed = 0; /* Accumulator for packed operations. */ + BeamInstr args[8]; /* Arguments for this instruction. */ + BeamInstr* ap; /* Pointer to arguments. */ start_prog = opc[op].pack; @@ -288,7 +321,7 @@ print_op(int to, void *to_arg, int op, int size, Eterm* addr) * Avoid copying because instructions containing bignum operands * are bigger than actually declared. */ - ap = (Uint *) addr; + ap = (BeamInstr *) addr; } else { /* * Copy all arguments to a local buffer for the unpacking. @@ -324,8 +357,8 @@ print_op(int to, void *to_arg, int op, int size, Eterm* addr) packed >>= BEAM_TIGHT_SHIFT; break; case '6': /* Shift 16 steps */ - *ap++ = packed & 0xffff; - packed >>= 16; + *ap++ = packed & BEAM_LOOSE_MASK; + packed >>= BEAM_LOOSE_SHIFT; break; case 'p': *sp++ = *--ap; @@ -390,11 +423,11 @@ print_op(int to, void *to_arg, int op, int size, Eterm* addr) case 'i': /* Tagged integer */ case 'c': /* Tagged constant */ case 'q': /* Tagged literal */ - erts_print(to, to_arg, "%T", *ap); + erts_print(to, to_arg, "%T", (Eterm) *ap); ap++; break; case 'A': - erts_print(to, to_arg, "%d", arityval(ap[0])); + erts_print(to, to_arg, "%d", arityval( (Eterm) ap[0])); ap++; break; case 'd': /* Destination (x(0), x(N), y(N)) */ @@ -421,30 +454,36 @@ print_op(int to, void *to_arg, int op, int size, Eterm* addr) ap++; break; case 'f': /* Destination label */ - erts_print(to, to_arg, "f(%X)", *ap); - ap++; + { + BeamInstr* f = find_function_from_pc((BeamInstr *)*ap); + if (f+3 != (BeamInstr *) *ap) { + erts_print(to, to_arg, "f(" HEXF ")", *ap); + } else { + erts_print(to, to_arg, "%T:%T/%bpu", (Eterm) f[0], (Eterm) f[1], (Eterm) f[2]); + } + ap++; + } break; case 'p': /* Pointer (to label) */ { - Eterm* f = find_function_from_pc((Eterm *)*ap); - - if (f+3 != (Eterm *) *ap) { - erts_print(to, to_arg, "p(%X)", *ap); + BeamInstr* f = find_function_from_pc((BeamInstr *)*ap); + if (f+3 != (BeamInstr *) *ap) { + erts_print(to, to_arg, "p(" HEXF ")", *ap); } else { - erts_print(to, to_arg, "%T:%T/%bpu", f[0], f[1], f[2]); + erts_print(to, to_arg, "%T:%T/%bpu", (Eterm) f[0], (Eterm) f[1], (Eterm) f[2]); } ap++; } break; case 'j': /* Pointer (to label) */ - erts_print(to, to_arg, "j(%X)", *ap); + erts_print(to, to_arg, "j(" HEXF ")", *ap); ap++; break; case 'e': /* Export entry */ { Export* ex = (Export *) *ap; erts_print(to, to_arg, - "%T:%T/%bpu", ex->code[0], ex->code[1], ex->code[2]); + "%T:%T/%bpu", (Eterm) ex->code[0], (Eterm) ex->code[1], (Uint) ex->code[2]); ap++; } break; @@ -467,7 +506,7 @@ print_op(int to, void *to_arg, int op, int size, Eterm* addr) ap++; break; case 'P': /* Byte offset into tuple (see beam_load.c) */ - erts_print(to, to_arg, "%d", (*ap / sizeof(Eterm*)) - 1); + erts_print(to, to_arg, "%d", (*ap / sizeof(Eterm)) - 1); ap++; break; case 'l': /* fr(N) */ @@ -494,7 +533,7 @@ print_op(int to, void *to_arg, int op, int size, Eterm* addr) int n = ap[-1]; while (n > 0) { - erts_print(to, to_arg, "%T f(%X) ", ap[0], ap[1]); + erts_print(to, to_arg, "%T f(" HEXF ") ", (Eterm) ap[0], ap[1]); ap += 2; size += 2; n--; @@ -505,7 +544,7 @@ print_op(int to, void *to_arg, int op, int size, Eterm* addr) { int n; for (n = ap[-2]; n > 0; n--) { - erts_print(to, to_arg, "f(%X) ", ap[0]); + erts_print(to, to_arg, "f(" HEXF ") ", ap[0]); ap++; size++; } @@ -513,11 +552,12 @@ print_op(int to, void *to_arg, int op, int size, Eterm* addr) break; case op_i_select_big_sf: while (ap[0]) { - int arity = thing_arityval(ap[0]); - print_big(to, to_arg, ap); - size += arity+1; - ap += arity+1; - erts_print(to, to_arg, " f(%X) ", ap[0]); + Eterm *bigp = (Eterm *) ap; + int arity = thing_arityval(*bigp); + print_big(to, to_arg, bigp); + size += TermWords(arity+1); + ap += TermWords(arity+1); + erts_print(to, to_arg, " f(" HEXF ") ", ap[0]); ap++; size++; } @@ -541,8 +581,8 @@ print_big(int to, void *to_arg, Eterm* addr) erts_print(to, to_arg, "-#integer(%d) = {", i); else erts_print(to, to_arg, "#integer(%d) = {", i); - erts_print(to, to_arg, "%d", BIG_DIGIT(addr, 0)); + erts_print(to, to_arg, "0x%x", BIG_DIGIT(addr, 0)); for (k = 1; k < i; k++) - erts_print(to, to_arg, ",%d", BIG_DIGIT(addr, k)); + erts_print(to, to_arg, ",0x%x", BIG_DIGIT(addr, k)); erts_print(to, to_arg, "}"); } diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 2f7f48193d..834cc8df61 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -117,6 +117,7 @@ do { \ #endif #define GET_BIF_ADDRESS(p) ((BifFunction) (((Export *) p)->code[4])) +#define TermWords(t) (((t) / (sizeof(BeamInstr)/sizeof(Eterm))) + !!((t) % (sizeof(BeamInstr)/sizeof(Eterm)))) /* @@ -138,8 +139,8 @@ do { \ #define VALID_INSTR(IP) (0 <= (int)(IP) && ((int)(IP) < (NUMBER_OF_OPCODES*2+10))) #else #define VALID_INSTR(IP) \ - ((Sint)LabelAddr(emulator_loop) <= (Sint)(IP) && \ - (Sint)(IP) < (Sint)LabelAddr(end_emulator_loop)) + ((SWord)LabelAddr(emulator_loop) <= (SWord)(IP) && \ + (SWord)(IP) < (SWord)LabelAddr(end_emulator_loop)) #endif /* NO_JUMP_TABLE */ #define SET_CP(p, ip) \ @@ -181,11 +182,11 @@ do { \ #define StoreBifResult(Dst, Result) \ do { \ - Eterm* stb_next; \ + BeamInstr* stb_next; \ Eterm stb_reg; \ stb_reg = Arg(Dst); \ I += (Dst) + 2; \ - stb_next = (Eterm *) *I; \ + stb_next = (BeamInstr *) *I; \ CHECK_TERM(Result); \ switch (beam_reg_tag(stb_reg)) { \ case R_REG_DEF: \ @@ -205,7 +206,7 @@ do { \ c_p->cp = 0; \ } while(0) -#define RESTORE_CP(X) SET_CP(c_p, cp_val(*(X))) +#define RESTORE_CP(X) SET_CP(c_p, (BeamInstr *) cp_val(*(X))) #define ISCATCHEND(instr) ((Eterm *) *(instr) == OpCode(catch_end_y)) @@ -213,13 +214,13 @@ do { \ * Special Beam instructions. */ -Eterm beam_apply[2]; -Eterm beam_exit[1]; -Eterm beam_continue_exit[1]; +BeamInstr beam_apply[2]; +BeamInstr beam_exit[1]; +BeamInstr beam_continue_exit[1]; -Eterm* em_call_error_handler; -Eterm* em_apply_bif; -Eterm* em_call_traced_function; +BeamInstr* em_call_error_handler; +BeamInstr* em_apply_bif; +BeamInstr* em_call_traced_function; /* NOTE These should be the only variables containing trace instructions. @@ -227,9 +228,9 @@ Eterm* em_call_traced_function; ** for the refering variable (one of these), and rouge references ** will most likely cause chaos. */ -Eterm beam_return_to_trace[1]; /* OpCode(i_return_to_trace) */ -Eterm beam_return_trace[1]; /* OpCode(i_return_trace) */ -Eterm beam_exception_trace[1]; /* UGLY also OpCode(i_return_trace) */ +BeamInstr beam_return_to_trace[1]; /* OpCode(i_return_to_trace) */ +BeamInstr beam_return_trace[1]; /* OpCode(i_return_trace) */ +BeamInstr beam_exception_trace[1]; /* UGLY also OpCode(i_return_trace) */ /* * All Beam instructions in numerical order. @@ -522,8 +523,8 @@ extern int count_instructions; #define DispatchMacro() \ do { \ - Eterm* dis_next; \ - dis_next = (Eterm *) *I; \ + BeamInstr* dis_next; \ + dis_next = (BeamInstr *) *I; \ CHECK_ARGS(I); \ if (FCALLS > 0 || FCALLS > neg_o_reds) { \ FCALLS--; \ @@ -535,8 +536,8 @@ extern int count_instructions; #define DispatchMacroFun() \ do { \ - Eterm* dis_next; \ - dis_next = (Eterm *) *I; \ + BeamInstr* dis_next; \ + dis_next = (BeamInstr *) *I; \ CHECK_ARGS(I); \ if (FCALLS > 0 || FCALLS > neg_o_reds) { \ FCALLS--; \ @@ -590,7 +591,7 @@ extern int count_instructions; ASSERT(VALID_INSTR(*I)); \ Goto(*I) -#define PreFetch(N, Dst) do { Dst = (Eterm *) *(I + N + 1); } while (0) +#define PreFetch(N, Dst) do { Dst = (BeamInstr *) *(I + N + 1); } while (0) #define NextPF(N, Dst) \ I += N + 1; \ ASSERT(VALID_INSTR(Dst)); \ @@ -644,7 +645,7 @@ extern int count_instructions; #define DeallocateReturn(Deallocate) \ do { \ int words_to_pop = (Deallocate); \ - SET_I(cp_val(*E)); \ + SET_I((BeamInstr *) cp_val(*E)); \ E = ADD_BYTE_OFFSET(E, words_to_pop); \ CHECK_TERM(r(0)); \ Goto(*I); \ @@ -657,19 +658,19 @@ extern int count_instructions; #define MoveCall(Src, Dest, CallDest, Size) \ (Dest) = (Src); \ SET_CP(c_p, I+Size+1); \ - SET_I((Eterm *) CallDest); \ + SET_I((BeamInstr *) CallDest); \ Dispatch(); #define MoveCallLast(Src, Dest, CallDest, Deallocate) \ (Dest) = (Src); \ RESTORE_CP(E); \ E = ADD_BYTE_OFFSET(E, (Deallocate)); \ - SET_I((Eterm *) CallDest); \ + SET_I((BeamInstr *) CallDest); \ Dispatch(); #define MoveCallOnly(Src, Dest, CallDest) \ (Dest) = (Src); \ - SET_I((Eterm *) CallDest); \ + SET_I((BeamInstr *) CallDest); \ Dispatch(); #define GetList(Src, H, T) do { \ @@ -677,47 +678,48 @@ extern int count_instructions; H = CAR(tmp_ptr); \ T = CDR(tmp_ptr); } while (0) -#define GetTupleElement(Src, Element, Dest) \ - do { \ - tmp_arg1 = (Eterm) (((unsigned char *) tuple_val(Src)) + (Element)); \ - (Dest) = (*(Eterm *)tmp_arg1); \ +#define GetTupleElement(Src, Element, Dest) \ + do { \ + tmp_arg1 = (Eterm) COMPRESS_POINTER(((unsigned char *) tuple_val(Src)) + \ + (Element)); \ + (Dest) = (*(Eterm *) EXPAND_POINTER(tmp_arg1)); \ } while (0) -#define ExtractNextElement(Dest) \ - tmp_arg1 += sizeof(Eterm); \ - (Dest) = (* (Eterm *) (((unsigned char *) tmp_arg1))) +#define ExtractNextElement(Dest) \ + tmp_arg1 += sizeof(Eterm); \ + (Dest) = (* (Eterm *) (((unsigned char *) EXPAND_POINTER(tmp_arg1)))) -#define ExtractNextElement2(Dest) \ - do { \ - Eterm* ene_dstp = &(Dest); \ - ene_dstp[0] = ((Eterm *) tmp_arg1)[1]; \ - ene_dstp[1] = ((Eterm *) tmp_arg1)[2]; \ - tmp_arg1 += sizeof(Eterm) + sizeof(Eterm); \ +#define ExtractNextElement2(Dest) \ + do { \ + Eterm* ene_dstp = &(Dest); \ + ene_dstp[0] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[1]; \ + ene_dstp[1] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[2]; \ + tmp_arg1 += sizeof(Eterm) + sizeof(Eterm); \ } while (0) #define ExtractNextElement3(Dest) \ do { \ Eterm* ene_dstp = &(Dest); \ - ene_dstp[0] = ((Eterm *) tmp_arg1)[1]; \ - ene_dstp[1] = ((Eterm *) tmp_arg1)[2]; \ - ene_dstp[2] = ((Eterm *) tmp_arg1)[3]; \ + ene_dstp[0] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[1]; \ + ene_dstp[1] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[2]; \ + ene_dstp[2] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[3]; \ tmp_arg1 += 3*sizeof(Eterm); \ } while (0) #define ExtractNextElement4(Dest) \ do { \ Eterm* ene_dstp = &(Dest); \ - ene_dstp[0] = ((Eterm *) tmp_arg1)[1]; \ - ene_dstp[1] = ((Eterm *) tmp_arg1)[2]; \ - ene_dstp[2] = ((Eterm *) tmp_arg1)[3]; \ - ene_dstp[3] = ((Eterm *) tmp_arg1)[4]; \ + ene_dstp[0] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[1]; \ + ene_dstp[1] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[2]; \ + ene_dstp[2] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[3]; \ + ene_dstp[3] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[4]; \ tmp_arg1 += 4*sizeof(Eterm); \ } while (0) #define ExtractElement(Element, Dest) \ do { \ tmp_arg1 += (Element); \ - (Dest) = (* (Eterm *) tmp_arg1); \ + (Dest) = (* (Eterm *) EXPAND_POINTER(tmp_arg1)); \ } while (0) #define PutTuple(Arity, Src, Dest) \ @@ -759,8 +761,13 @@ extern int count_instructions; #define IsTuple(X, Action) if (is_not_tuple(X)) Action -#define IsArity(Pointer, Arity, Fail) \ - if (*(Eterm *)(tmp_arg1 = (Eterm)tuple_val(Pointer)) != (Arity)) { Fail; } +#define IsArity(Pointer, Arity, Fail) \ + if (*(Eterm *) \ + EXPAND_POINTER(tmp_arg1 = (Eterm) \ + COMPRESS_POINTER(tuple_val(Pointer))) != (Arity)) \ + { \ + Fail; \ + } #define IsFunction(X, Action) \ do { \ @@ -776,11 +783,14 @@ extern int count_instructions; } \ } while (0) -#define IsTupleOfArity(Src, Arity, Fail) \ - do { \ - if (is_not_tuple(Src) || *(Eterm *)(tmp_arg1 = (Eterm) tuple_val(Src)) != Arity) { \ - Fail; \ - } \ +#define IsTupleOfArity(Src, Arity, Fail) \ + do { \ + if (is_not_tuple(Src) || \ + *(Eterm *) \ + EXPAND_POINTER(tmp_arg1 = \ + (Eterm) COMPRESS_POINTER(tuple_val(Src))) != Arity) { \ + Fail; \ + } \ } while (0) #define IsBoolean(X, Fail) if ((X) != am_true && (X) != am_false) { Fail; } @@ -791,7 +801,7 @@ extern int count_instructions; #define IsBitstring(Src, Fail) \ if (is_not_binary(Src)) { Fail; } -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP #define BsSafeMul(A, B, Fail, Target) \ do { Uint64 _res = (A) * (B); \ if (_res / B != A) { Fail; } \ @@ -974,23 +984,23 @@ extern int count_instructions; #define IsRef(Src, Fail) if (is_not_ref(Src)) { Fail; } static BifFunction translate_gc_bif(void* gcf); -static Eterm* handle_error(Process* c_p, Eterm* pc, Eterm* reg, BifFunction bf); -static Eterm* next_catch(Process* c_p, Eterm *reg); +static BeamInstr* handle_error(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf); +static BeamInstr* next_catch(Process* c_p, Eterm *reg); static void terminate_proc(Process* c_p, Eterm Value); static Eterm add_stacktrace(Process* c_p, Eterm Value, Eterm exc); -static void save_stacktrace(Process* c_p, Eterm* pc, Eterm* reg, +static void save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf, Eterm args); static struct StackTrace * get_trace_from_exc(Eterm exc); static Eterm make_arglist(Process* c_p, Eterm* reg, int a); -static Eterm call_error_handler(Process* p, Eterm* ip, Eterm* reg); -static Eterm call_breakpoint_handler(Process* p, Eterm* fi, Eterm* reg); -static Uint* fixed_apply(Process* p, Eterm* reg, Uint arity); -static Eterm* apply(Process* p, Eterm module, Eterm function, +static Eterm call_error_handler(Process* p, BeamInstr* ip, Eterm* reg); +static Eterm call_breakpoint_handler(Process* p, BeamInstr* fi, Eterm* reg); +static BeamInstr* fixed_apply(Process* p, Eterm* reg, Uint arity); +static BeamInstr* apply(Process* p, Eterm module, Eterm function, Eterm args, Eterm* reg); static int hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* reg); -static Eterm* call_fun(Process* p, int arity, Eterm* reg, Eterm args); -static Eterm* apply_fun(Process* p, Eterm fun, Eterm args, Eterm* reg); +static BeamInstr* call_fun(Process* p, int arity, Eterm* reg, Eterm args); +static BeamInstr* apply_fun(Process* p, Eterm fun, Eterm args, Eterm* reg); static Eterm new_fun(Process* p, Eterm* reg, ErlFunEntry* fe, int num_free); #if defined(_OSE_) || defined(VXWORKS) @@ -1078,7 +1088,7 @@ void process_main(void) /* * Pointer to next threaded instruction. */ - register Eterm *I REG_I = NULL; + register BeamInstr *I REG_I = NULL; /* Number of reductions left. This function * returns to the scheduler when FCALLS reaches zero. @@ -1090,9 +1100,14 @@ void process_main(void) */ register Eterm tmp_arg1 REG_tmp_arg1 = NIL; register Eterm tmp_arg2 REG_tmp_arg2 = NIL; - Eterm tmp_big[2]; /* Temporary buffer for small bignums. */ +#if HEAP_ON_C_STACK + Eterm tmp_big[2]; /* Temporary buffer for small bignums if HEAP_ON_C_STACK. */ +#else + Eterm *tmp_big; /* Temporary buffer for small bignums if !HEAP_ON_C_STACK. */ +#endif #ifndef ERTS_SMP +#if !HALFWORD_HEAP static Eterm save_reg[ERTS_X_REGS_ALLOCATED]; /* X registers -- not used directly, but * through 'reg', because using it directly @@ -1100,7 +1115,7 @@ void process_main(void) * while using it through reg needs only * one. */ - +#endif /* * Floating point registers. */ @@ -1141,13 +1156,17 @@ void process_main(void) * Note: c_p->arity must be set to reflect the number of useful terms in * c_p->arg_reg before calling the scheduler. */ - if (!init_done) { init_done = 1; goto init_emulator; } #ifndef ERTS_SMP +#if !HALFWORD_HEAP reg = save_reg; /* XXX: probably wastes a register on x86 */ +#else + /* Registers need to be heap allocated (correct memory range) for tracing to work */ + reg = erts_alloc(ERTS_ALC_T_BEAM_REGISTER, ERTS_X_REGS_ALLOCATED * sizeof(Eterm)); +#endif #endif c_p = NULL; reds_used = 0; @@ -1168,11 +1187,14 @@ void process_main(void) reg = c_p->scheduler_data->save_reg; freg = c_p->scheduler_data->freg; #endif +#if !HEAP_ON_C_STACK + tmp_big = ERTS_PROC_GET_SCHDATA(c_p)->beam_emu_tmp_heap; +#endif ERL_BITS_RELOAD_STATEP(c_p); { int reds; Eterm* argp; - Eterm* next; + BeamInstr *next; int i; argp = c_p->arg_reg; @@ -1199,7 +1221,7 @@ void process_main(void) FCALLS = REDS_IN(c_p) = reds; } - next = (Eterm *) *I; + next = (BeamInstr *) *I; r(0) = c_p->arg_reg[0]; #ifdef HARDDEBUG if (c_p->arity > 0) { @@ -1291,7 +1313,7 @@ void process_main(void) } /* FALL THROUGH */ OpCase(i_call_only_f): { - SET_I((Eterm *) Arg(0)); + SET_I((BeamInstr *) Arg(0)); Dispatch(); } @@ -1302,7 +1324,7 @@ void process_main(void) OpCase(i_call_last_fP): { RESTORE_CP(E); E = ADD_BYTE_OFFSET(E, Arg(1)); - SET_I((Eterm *) Arg(0)); + SET_I((BeamInstr *) Arg(0)); Dispatch(); } @@ -1313,7 +1335,7 @@ void process_main(void) /* FALL THROUGH */ OpCase(i_call_f): { SET_CP(c_p, I+2); - SET_I((Eterm *) Arg(0)); + SET_I((BeamInstr *) Arg(0)); Dispatch(); } @@ -1349,7 +1371,7 @@ void process_main(void) Dispatchx(); OpCase(init_y): { - Eterm* next; + BeamInstr *next; PreFetch(1, next); make_blank(yb(Arg(0))); @@ -1357,7 +1379,7 @@ void process_main(void) } OpCase(i_trim_I): { - Eterm* next; + BeamInstr *next; Uint words; Uint cp; @@ -1383,7 +1405,7 @@ void process_main(void) } OpCase(test_heap_1_put_list_Iy): { - Eterm* next; + BeamInstr *next; PreFetch(2, next); TestHeap(Arg(0), 1); @@ -1414,7 +1436,7 @@ void process_main(void) */ OpCase(send): { - Eterm* next; + BeamInstr *next; Eterm result; PRE_BIF_SWAPOUT(c_p); @@ -1429,7 +1451,7 @@ void process_main(void) NextPF(0, next); } else if (c_p->freason == TRAP) { SET_CP(c_p, I+1); - SET_I((Eterm *) c_p->def_arg_reg[3]); + SET_I(*((BeamInstr **) (BeamInstr) ((c_p)->def_arg_reg + 3))); SWAPIN; r(0) = c_p->def_arg_reg[0]; x(1) = c_p->def_arg_reg[1]; @@ -1555,7 +1577,7 @@ void process_main(void) */ OpCase(i_loop_rec_fr): { - Eterm* next; + BeamInstr *next; ErlMessage* msgp; loop_rec__: @@ -1579,7 +1601,7 @@ void process_main(void) erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); else { #endif - SET_I((Eterm *) Arg(0)); + SET_I((BeamInstr *) Arg(0)); Goto(*I); /* Jump to a wait or wait_timeout instruction */ #ifdef ERTS_SMP } @@ -1615,7 +1637,7 @@ void process_main(void) * Remove a (matched) message from the message queue. */ OpCase(remove_message): { - Eterm* next; + BeamInstr *next; ErlMessage* msgp; PROCESS_MAIN_CHK_LOCKS(c_p); @@ -1660,7 +1682,7 @@ void process_main(void) * message didn't match), then jump to the loop_rec instruction. */ OpCase(loop_rec_end_f): { - SET_I((Eterm *) Arg(0)); + SET_I((BeamInstr *) Arg(0)); SAVE_MESSAGE(c_p); goto loop_rec__; } @@ -1690,12 +1712,12 @@ void process_main(void) } GetArg1(1, timeout_value); if (timeout_value != make_small(0)) { -#if !defined(ARCH_64) +#if !defined(ARCH_64) || HALFWORD_HEAP Uint time_val; #endif if (is_small(timeout_value) && signed_val(timeout_value) > 0 && -#if defined(ARCH_64) +#if defined(ARCH_64) && !HALFWORD_HEAP ((unsigned_val(timeout_value) >> 32) == 0) #else 1 @@ -1706,14 +1728,16 @@ void process_main(void) * c_p->def_arg_reg[0]. Note that it is safe to use this * location because there are no living x registers in * a receive statement. + * Note that for the halfword emulator, the two first elements + * of the array are used. */ - c_p->def_arg_reg[0] = (Eterm) (I+3); + *((BeamInstr **) (UWord) c_p->def_arg_reg) = I+3; set_timer(c_p, unsigned_val(timeout_value)); } else if (timeout_value == am_infinity) { c_p->flags |= F_TIMO; -#if !defined(ARCH_64) +#if !defined(ARCH_64) || HALFWORD_HEAP } else if (term_to_Uint(timeout_value, &time_val)) { - c_p->def_arg_reg[0] = (Eterm) (I+3); + *((BeamInstr **) (UWord) c_p->def_arg_reg) = I+3; set_timer(c_p, time_val); #endif } else { /* Wrong time */ @@ -1742,7 +1766,7 @@ void process_main(void) wait2: { ASSERT(!ERTS_PROC_IS_EXITING(c_p)); - c_p->i = (Eterm *) Arg(0); /* L1 */ + c_p->i = (BeamInstr *) Arg(0); /* L1 */ SWAPOUT; c_p->arity = 0; c_p->status = P_WAITING; @@ -1770,7 +1794,7 @@ void process_main(void) * we must test the F_INSLPQUEUE flag as well as the F_TIMO flag. */ if ((c_p->flags & (F_INSLPQUEUE | F_TIMO)) == 0) { - c_p->def_arg_reg[0] = (Eterm) (I+3); + *((BeamInstr **) (UWord) c_p->def_arg_reg) = I+3; set_timer(c_p, Arg(1)); } goto wait2; @@ -1785,7 +1809,7 @@ void process_main(void) } OpCase(timeout): { - Eterm* next; + BeamInstr *next; PreFetch(0, next); if (IS_TRACED_FL(c_p, F_TRACE_RECEIVE)) { @@ -1805,8 +1829,8 @@ void process_main(void) do_binary_search: { struct Pairs { - Eterm val; - Eterm* addr; + BeamInstr val; + BeamInstr* addr; }; struct Pairs* low; struct Pairs* high; @@ -1846,7 +1870,7 @@ void process_main(void) Goto(*I); } } - SET_I((Eterm *) Arg(1)); + SET_I((BeamInstr *) Arg(1)); Goto(*I); } @@ -1858,11 +1882,11 @@ void process_main(void) if (is_small(index)) { index = signed_val(index); if (index < Arg(2)) { - SET_I((Eterm *) (&Arg(3))[index]); + SET_I((BeamInstr *) (&Arg(3))[index]); Goto(*I); } } - SET_I((Eterm *) Arg(1)); + SET_I((BeamInstr *) Arg(1)); Goto(*I); } @@ -1874,11 +1898,11 @@ void process_main(void) if (is_small(index)) { index = (Uint) (signed_val(index) - Arg(3)); if (index < Arg(2)) { - SET_I((Eterm *) (&Arg(4))[index]); + SET_I((BeamInstr *) (&Arg(4))[index]); Goto(*I); } } - SET_I((Eterm *) Arg(1)); + SET_I((BeamInstr *) Arg(1)); Goto(*I); } @@ -1915,7 +1939,7 @@ void process_main(void) if (is_value(result)) { StoreBifResult(3, result); } - SET_I((Eterm *) Arg(0)); + SET_I((BeamInstr *) Arg(0)); Goto(*I); } @@ -1955,7 +1979,7 @@ void process_main(void) GcBifFunction bf; Eterm arg; Eterm result; - Uint live = Arg(3); + Uint live = (Uint) Arg(3); GetArg1(2, arg); reg[0] = r(0); @@ -1976,7 +2000,7 @@ void process_main(void) StoreBifResult(4, result); } if (Arg(0) != 0) { - SET_I((Eterm *) Arg(0)); + SET_I((BeamInstr *) Arg(0)); Goto(*I); } reg[0] = arg; @@ -2004,7 +2028,7 @@ void process_main(void) if (is_value(result)) { StoreBifResult(2, result); } - SET_I((Eterm *) Arg(0)); + SET_I((BeamInstr *) Arg(0)); Goto(*I); } @@ -2040,7 +2064,7 @@ void process_main(void) */ OpCase(call_bif0_e): { - Eterm (*bf)(Process*, Uint*) = GET_BIF_ADDRESS(Arg(0)); + Eterm (*bf)(Process*, BeamInstr*) = GET_BIF_ADDRESS(Arg(0)); PRE_BIF_SWAPOUT(c_p); c_p->fcalls = FCALLS - 1; @@ -2073,9 +2097,9 @@ void process_main(void) OpCase(call_bif1_e): { - Eterm (*bf)(Process*, Eterm, Uint*) = GET_BIF_ADDRESS(Arg(0)); + Eterm (*bf)(Process*, Eterm, BeamInstr*) = GET_BIF_ADDRESS(Arg(0)); Eterm result; - Eterm* next; + BeamInstr *next; c_p->fcalls = FCALLS - 1; if (FCALLS <= 0) { @@ -2108,9 +2132,9 @@ void process_main(void) OpCase(call_bif2_e): { - Eterm (*bf)(Process*, Eterm, Eterm, Uint*) = GET_BIF_ADDRESS(Arg(0)); + Eterm (*bf)(Process*, Eterm, Eterm, BeamInstr*) = GET_BIF_ADDRESS(Arg(0)); Eterm result; - Eterm* next; + BeamInstr *next; PRE_BIF_SWAPOUT(c_p); c_p->fcalls = FCALLS - 1; @@ -2145,9 +2169,9 @@ void process_main(void) OpCase(call_bif3_e): { - Eterm (*bf)(Process*, Eterm, Eterm, Eterm, Uint*) = GET_BIF_ADDRESS(Arg(0)); + Eterm (*bf)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = GET_BIF_ADDRESS(Arg(0)); Eterm result; - Eterm* next; + BeamInstr *next; PRE_BIF_SWAPOUT(c_p); c_p->fcalls = FCALLS - 1; @@ -2168,7 +2192,7 @@ void process_main(void) } else if (c_p->freason == TRAP) { call_bif_trap3: SET_CP(c_p, I+2); - SET_I((Eterm *)c_p->def_arg_reg[3]); + SET_I(*((BeamInstr **) (UWord) ((c_p)->def_arg_reg + 3))); SWAPIN; r(0) = c_p->def_arg_reg[0]; x(1) = c_p->def_arg_reg[1]; @@ -2276,7 +2300,7 @@ void process_main(void) lb_Cl_error: { if (Arg(0) != 0) { OpCase(jump_f): { - SET_I((Eterm *) Arg(0)); + SET_I((BeamInstr *) Arg(0)); Goto(*I); } } @@ -2468,7 +2492,7 @@ void process_main(void) goto lb_Cl_error; OpCase(i_apply): { - Eterm* next; + BeamInstr *next; SWAPOUT; next = apply(c_p, r(0), x(1), x(2), reg); SWAPIN; @@ -2483,13 +2507,13 @@ void process_main(void) } OpCase(i_apply_last_P): { - Eterm* next; + BeamInstr *next; SWAPOUT; next = apply(c_p, r(0), x(1), x(2), reg); SWAPIN; if (next != NULL) { r(0) = reg[0]; - SET_CP(c_p, (Eterm *) E[0]); + SET_CP(c_p, (BeamInstr *) EXPAND_POINTER(E[0])); E = ADD_BYTE_OFFSET(E, Arg(0)); SET_I(next); Dispatch(); @@ -2499,7 +2523,7 @@ void process_main(void) } OpCase(i_apply_only): { - Eterm* next; + BeamInstr *next; SWAPOUT; next = apply(c_p, r(0), x(1), x(2), reg); SWAPIN; @@ -2513,7 +2537,7 @@ void process_main(void) } OpCase(apply_I): { - Eterm* next; + BeamInstr *next; reg[0] = r(0); SWAPOUT; @@ -2530,7 +2554,7 @@ void process_main(void) } OpCase(apply_last_IP): { - Eterm* next; + BeamInstr *next; reg[0] = r(0); SWAPOUT; @@ -2538,7 +2562,7 @@ void process_main(void) SWAPIN; if (next != NULL) { r(0) = reg[0]; - SET_CP(c_p, (Eterm *) E[0]); + SET_CP(c_p, (BeamInstr *) EXPAND_POINTER(E[0])); E = ADD_BYTE_OFFSET(E, Arg(1)); SET_I(next); Dispatch(); @@ -2548,7 +2572,7 @@ void process_main(void) } OpCase(i_apply_fun): { - Eterm* next; + BeamInstr *next; SWAPOUT; next = apply_fun(c_p, r(0), x(1), reg); @@ -2563,14 +2587,14 @@ void process_main(void) } OpCase(i_apply_fun_last_P): { - Eterm* next; + BeamInstr *next; SWAPOUT; next = apply_fun(c_p, r(0), x(1), reg); SWAPIN; if (next != NULL) { r(0) = reg[0]; - SET_CP(c_p, (Eterm *) E[0]); + SET_CP(c_p, (BeamInstr *) EXPAND_POINTER(E[0])); E = ADD_BYTE_OFFSET(E, Arg(0)); SET_I(next); Dispatchfun(); @@ -2579,7 +2603,7 @@ void process_main(void) } OpCase(i_apply_fun_only): { - Eterm* next; + BeamInstr *next; SWAPOUT; next = apply_fun(c_p, r(0), x(1), reg); @@ -2593,10 +2617,11 @@ void process_main(void) } OpCase(i_call_fun_I): { - Eterm* next; + BeamInstr *next; SWAPOUT; reg[0] = r(0); + next = call_fun(c_p, Arg(0), reg, THE_NON_VALUE); SWAPIN; if (next != NULL) { @@ -2609,7 +2634,7 @@ void process_main(void) } OpCase(i_call_fun_last_IP): { - Eterm* next; + BeamInstr *next; SWAPOUT; reg[0] = r(0); @@ -2617,7 +2642,7 @@ void process_main(void) SWAPIN; if (next != NULL) { r(0) = reg[0]; - SET_CP(c_p, (Eterm *) E[0]); + SET_CP(c_p, (BeamInstr *) EXPAND_POINTER(E[0])); E = ADD_BYTE_OFFSET(E, Arg(1)); SET_I(next); Dispatchfun(); @@ -2722,7 +2747,7 @@ void process_main(void) tmp_arg1 = *tuple_val(tmp_arg1); goto do_binary_search; } - SET_I((Eterm *) Arg(1)); + SET_I((BeamInstr *) Arg(1)); Goto(*I); } @@ -2748,16 +2773,18 @@ void process_main(void) given = big_val(tmp_arg1); given_arity = given[0]; given_size = thing_arityval(given_arity); - bigp = &Arg(2); + bigp = (Eterm *) &Arg(2); while ((arity = bigp[0]) > given_arity) { - bigp += thing_arityval(arity) + 2; + bigp += (TermWords(thing_arityval(arity) + 1) + 1) * (sizeof(BeamInstr)/sizeof(Eterm)); } while (bigp[0] == given_arity) { if (memcmp(bigp+1, given+1, sizeof(Eterm)*given_size) == 0) { - SET_I((Eterm *) bigp[given_size+1]); + BeamInstr *tmp = + ((BeamInstr *) (UWord) bigp) + TermWords(given_size + 1); + SET_I((BeamInstr *) *tmp); Goto(*I); } - bigp += thing_arityval(arity) + 2; + bigp += (TermWords(thing_arityval(arity) + 1) + 1) * (sizeof(BeamInstr)/sizeof(Eterm)); } } @@ -2765,18 +2792,18 @@ void process_main(void) * Failed. */ - SET_I((Eterm *) Arg(1)); + SET_I((BeamInstr *) Arg(1)); Goto(*I); } -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP OpCase(i_select_float_sfI): { Uint f; int n; struct ValLabel { Uint f; - Eterm* addr; + BeamInstr* addr; }; struct ValLabel* ptr; @@ -2804,7 +2831,7 @@ void process_main(void) struct ValLabel { Uint fpart1; Uint fpart2; - Eterm* addr; + BeamInstr* addr; }; struct ValLabel* ptr; @@ -2822,7 +2849,7 @@ void process_main(void) } ptr++; } - SET_I((Eterm *) Arg(1)); + SET_I((BeamInstr *) Arg(1)); Goto(*I); } #endif @@ -2830,7 +2857,7 @@ void process_main(void) OpCase(set_tuple_element_sdP): { Eterm element; Eterm tuple; - Eterm* next; + BeamInstr *next; Eterm* p; PreFetch(3, next); @@ -3025,7 +3052,7 @@ void process_main(void) switch (tmp_arg2) { case 3: { - Eterm (*bf)(Process*, Eterm, Eterm, Eterm, Uint*) = vbf; + Eterm (*bf)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = vbf; ASSERT(!ERTS_PROC_IS_EXITING(c_p)); tmp_arg1 = (*bf)(c_p, r(0), x(1), x(2), I); ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(tmp_arg1)); @@ -3034,7 +3061,7 @@ void process_main(void) break; case 2: { - Eterm (*bf)(Process*, Eterm, Eterm, Uint*) = vbf; + Eterm (*bf)(Process*, Eterm, Eterm, BeamInstr*) = vbf; ASSERT(!ERTS_PROC_IS_EXITING(c_p)); tmp_arg1 = (*bf)(c_p, r(0), x(1), I); ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(tmp_arg1)); @@ -3043,7 +3070,7 @@ void process_main(void) break; case 1: { - Eterm (*bf)(Process*, Eterm, Uint*) = vbf; + Eterm (*bf)(Process*, Eterm, BeamInstr*) = vbf; ASSERT(!ERTS_PROC_IS_EXITING(c_p)); tmp_arg1 = (*bf)(c_p, r(0), I); ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(tmp_arg1)); @@ -3052,7 +3079,7 @@ void process_main(void) break; case 0: { - Eterm (*bf)(Process*, Uint*) = vbf; + Eterm (*bf)(Process*, BeamInstr*) = vbf; ASSERT(!ERTS_PROC_IS_EXITING(c_p)); tmp_arg1 = (*bf)(c_p, I); ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(tmp_arg1)); @@ -3076,7 +3103,7 @@ apply_bif_or_nif_epilogue: SET_I(c_p->cp); Goto(*I); } else if (c_p->freason == TRAP) { - SET_I((Eterm *)c_p->def_arg_reg[3]); + SET_I(*((BeamInstr **) (UWord) ((c_p)->def_arg_reg + 3))); r(0) = c_p->def_arg_reg[0]; x(1) = c_p->def_arg_reg[1]; x(2) = c_p->def_arg_reg[2]; @@ -3534,7 +3561,7 @@ apply_bif_or_nif_epilogue: OpCase(bs_put_string_II): { - Eterm* next; + BeamInstr *next; PreFetch(2, next); erts_new_bs_put_string(ERL_BITS_ARGS_2((byte *) Arg(1), Arg(0))); NextPF(2, next); @@ -3705,7 +3732,7 @@ apply_bif_or_nif_epilogue: { Eterm header; - Eterm* next; + BeamInstr *next; Uint slots; OpCase(i_bs_start_match2_rfIId): { @@ -3771,7 +3798,7 @@ apply_bif_or_nif_epilogue: } OpCase(bs_test_zero_tail2_fr): { - Eterm* next; + BeamInstr *next; ErlBinMatchBuffer *_mb; PreFetch(1, next); @@ -3783,7 +3810,7 @@ apply_bif_or_nif_epilogue: } OpCase(bs_test_zero_tail2_fx): { - Eterm* next; + BeamInstr *next; ErlBinMatchBuffer *_mb; PreFetch(2, next); @@ -3795,7 +3822,7 @@ apply_bif_or_nif_epilogue: } OpCase(bs_test_tail_imm2_frI): { - Eterm* next; + BeamInstr *next; ErlBinMatchBuffer *_mb; PreFetch(2, next); _mb = ms_matchbuffer(r(0)); @@ -3805,7 +3832,7 @@ apply_bif_or_nif_epilogue: NextPF(2, next); } OpCase(bs_test_tail_imm2_fxI): { - Eterm* next; + BeamInstr *next; ErlBinMatchBuffer *_mb; PreFetch(3, next); _mb = ms_matchbuffer(xb(Arg(1))); @@ -3816,7 +3843,7 @@ apply_bif_or_nif_epilogue: } OpCase(bs_test_unit_frI): { - Eterm* next; + BeamInstr *next; ErlBinMatchBuffer *_mb; PreFetch(2, next); _mb = ms_matchbuffer(r(0)); @@ -3826,7 +3853,7 @@ apply_bif_or_nif_epilogue: NextPF(2, next); } OpCase(bs_test_unit_fxI): { - Eterm* next; + BeamInstr *next; ErlBinMatchBuffer *_mb; PreFetch(3, next); _mb = ms_matchbuffer(xb(Arg(1))); @@ -3837,7 +3864,7 @@ apply_bif_or_nif_epilogue: } OpCase(bs_test_unit8_fr): { - Eterm* next; + BeamInstr *next; ErlBinMatchBuffer *_mb; PreFetch(1, next); _mb = ms_matchbuffer(r(0)); @@ -3847,7 +3874,7 @@ apply_bif_or_nif_epilogue: NextPF(1, next); } OpCase(bs_test_unit8_fx): { - Eterm* next; + BeamInstr *next; ErlBinMatchBuffer *_mb; PreFetch(2, next); _mb = ms_matchbuffer(xb(Arg(1))); @@ -3931,11 +3958,11 @@ apply_bif_or_nif_epilogue: _integer = get_int32(_mb->base + _mb->offset/8); } _mb->offset += 32; -#ifndef ARCH_64 +#if !defined(ARCH_64) || HALFWORD_HEAP if (IS_USMALL(0, _integer)) { #endif _result = make_small(_integer); -#ifndef ARCH_64 +#if !defined(ARCH_64) || HALFWORD_HEAP } else { TestHeap(BIG_UINT_HEAP_SIZE, Arg(1)); _result = uint_to_big((Uint) _integer, HTOP); @@ -4172,7 +4199,7 @@ apply_bif_or_nif_epilogue: do_bs_match_string: { - Eterm* next; + BeamInstr *next; byte* bytes; Uint bits; ErlBinMatchBuffer* mb; @@ -4199,7 +4226,7 @@ apply_bif_or_nif_epilogue: } OpCase(i_bs_save2_rI): { - Eterm* next; + BeamInstr *next; ErlBinMatchState *_ms; PreFetch(1, next); _ms = (ErlBinMatchState*) boxed_val((Eterm) r(0)); @@ -4207,7 +4234,7 @@ apply_bif_or_nif_epilogue: NextPF(1, next); } OpCase(i_bs_save2_xI): { - Eterm* next; + BeamInstr *next; ErlBinMatchState *_ms; PreFetch(2, next); _ms = (ErlBinMatchState*) boxed_val((Eterm) xb(Arg(0))); @@ -4216,7 +4243,7 @@ apply_bif_or_nif_epilogue: } OpCase(i_bs_restore2_rI): { - Eterm* next; + BeamInstr *next; ErlBinMatchState *_ms; PreFetch(1, next); _ms = (ErlBinMatchState*) boxed_val((Eterm) r(0)); @@ -4224,7 +4251,7 @@ apply_bif_or_nif_epilogue: NextPF(1, next); } OpCase(i_bs_restore2_xI): { - Eterm* next; + BeamInstr *next; ErlBinMatchState *_ms; PreFetch(2, next); _ms = (ErlBinMatchState*) boxed_val((Eterm) xb(Arg(0))); @@ -4241,7 +4268,7 @@ apply_bif_or_nif_epilogue: * deallocate not followed by a return, and that should work. */ OpCase(deallocate_I): { - Eterm* next; + BeamInstr *next; PreFetch(1, next); D(Arg(0)); @@ -4264,7 +4291,7 @@ apply_bif_or_nif_epilogue: */ OpCase(call_traced_function): { if (IS_TRACED_FL(c_p, F_TRACE_CALLS)) { - unsigned offset = offsetof(Export, code) + 3*sizeof(Eterm); + unsigned offset = offsetof(Export, code) + 3*sizeof(BeamInstr); Export* ep = (Export *) (((char *)I)-offset); Uint32 flags; @@ -4291,26 +4318,25 @@ apply_bif_or_nif_epilogue: } E -= 3; ASSERT(c_p->htop <= E && E <= c_p->hend); - ASSERT(is_CP((Eterm)(ep->code))); + ASSERT(is_CP((BeamInstr)(ep->code))); ASSERT(is_internal_pid(c_p->tracer_proc) || is_internal_port(c_p->tracer_proc)); - E[2] = make_cp(c_p->cp); + E[2] = make_cp(c_p->cp); /* XXX:PaN - code in lower range on halfword */ E[1] = am_true; /* Process tracer */ E[0] = make_cp(ep->code); - c_p->cp = (Eterm*) - make_cp(flags & MATCH_SET_EXCEPTION_TRACE - ? beam_exception_trace : beam_return_trace); + c_p->cp = (flags & MATCH_SET_EXCEPTION_TRACE) + ? beam_exception_trace : beam_return_trace; erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR); c_p->trace_flags |= F_EXCEPTION_TRACE; erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR); } } - SET_I((Uint *) Arg(0)); + SET_I((BeamInstr *)Arg(0)); Dispatch(); } OpCase(return_trace): { - Uint* code = (Uint *) E[0]; + BeamInstr* code = (BeamInstr *) (UWord) E[0]; SWAPOUT; /* Needed for shared heap */ ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); @@ -4318,24 +4344,24 @@ apply_bif_or_nif_epilogue: ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); SWAPIN; c_p->cp = NULL; - SET_I((Eterm *) E[2]); + SET_I((BeamInstr *) cp_val(E[2])); E += 3; Goto(*I); } OpCase(i_count_breakpoint): { - Uint real_I; + BeamInstr real_I; - ErtsCountBreak((Uint *) I, &real_I); + ErtsCountBreak((BeamInstr *) I, &real_I); ASSERT(VALID_INSTR(real_I)); Goto(real_I); } OpCase(i_trace_breakpoint): if (! IS_TRACED_FL(c_p, F_TRACE_CALLS)) { - Uint real_I; + BeamInstr real_I; - ErtsBreakSkip((Uint *) I, &real_I); + ErtsBreakSkip((BeamInstr *) I, &real_I); Goto(real_I); } /* Fall through to next case */ @@ -4349,11 +4375,10 @@ apply_bif_or_nif_epilogue: SWAPOUT; reg[0] = r(0); - if (*cp_val((Eterm)c_p->cp) - == (Uint) OpCode(return_trace)) { + if (*(c_p->cp) == (BeamInstr) OpCode(return_trace)) { cpp = (Uint*)&E[2]; - } else if (*cp_val((Eterm)c_p->cp) - == (Uint) OpCode(i_return_to_trace)) { + } else if (*(c_p->cp) + == (BeamInstr) OpCode(i_return_to_trace)) { return_to_trace = !0; cpp = (Uint*)&E[0]; } else { @@ -4364,19 +4389,19 @@ apply_bif_or_nif_epilogue: * return_trace and/or i_return_to_trace stackframes * on the stack, they are not intermixed with y registers */ - Eterm *cp_save = c_p->cp; + BeamInstr *cp_save = c_p->cp; for (;;) { ASSERT(is_CP(*cpp)); - if (*cp_val(*cpp) == (Uint) OpCode(return_trace)) { + if (*cp_val(*cpp) == (BeamInstr) OpCode(return_trace)) { cpp += 3; - } else if (*cp_val(*cpp) == (Uint) OpCode(i_return_to_trace)) { + } else if (*cp_val(*cpp) == (BeamInstr) OpCode(i_return_to_trace)) { return_to_trace = !0; cpp += 1; } else break; } - c_p->cp = (Eterm *) *cpp; - ASSERT(is_CP((Eterm)c_p->cp)); + c_p->cp = (BeamInstr *) cp_val(*cpp); + ASSERT(is_CP(*cpp)); ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); real_I = erts_trace_break(c_p, I, reg, &flags, &tracer_pid); ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); @@ -4412,12 +4437,12 @@ apply_bif_or_nif_epilogue: E -= 1; ASSERT(c_p->htop <= E && E <= c_p->hend); E[0] = make_cp(c_p->cp); - c_p->cp = (Eterm *) make_cp(beam_return_to_trace); + c_p->cp = (BeamInstr *) beam_return_to_trace; } if (flags & MATCH_SET_RX_TRACE) { E -= 3; ASSERT(c_p->htop <= E && E <= c_p->hend); - ASSERT(is_CP((Eterm) (I - 3))); + ASSERT(is_CP((Eterm) (UWord) (I - 3))); ASSERT(am_true == tracer_pid || is_internal_pid(tracer_pid) || is_internal_port(tracer_pid)); E[2] = make_cp(c_p->cp); @@ -4425,9 +4450,9 @@ apply_bif_or_nif_epilogue: E[0] = make_cp(I - 3); /* We ARE at the beginning of an instruction, the funcinfo is above i. */ - c_p->cp = (Eterm*) - make_cp(flags & MATCH_SET_EXCEPTION_TRACE - ? beam_exception_trace : beam_return_trace); + c_p->cp = + (flags & MATCH_SET_EXCEPTION_TRACE) + ? beam_exception_trace : beam_return_trace; erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR); c_p->trace_flags |= F_EXCEPTION_TRACE; erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR); @@ -4440,10 +4465,10 @@ apply_bif_or_nif_epilogue: Uint *cpp = (Uint*) E; for(;;) { ASSERT(is_CP(*cpp)); - if (*cp_val(*cpp) == (Uint) OpCode(return_trace)) { + if (*cp_val(*cpp) == (BeamInstr) OpCode(return_trace)) { do ++cpp; while(is_not_CP(*cpp)); cpp += 2; - } else if (*cp_val(*cpp) == (Uint) OpCode(i_return_to_trace)) { + } else if (*cp_val(*cpp) == (BeamInstr) OpCode(i_return_to_trace)) { do ++cpp; while(is_not_CP(*cpp)); } else break; } @@ -4454,7 +4479,7 @@ apply_bif_or_nif_epilogue: SWAPIN; } c_p->cp = NULL; - SET_I((Eterm *) E[0]); + SET_I((BeamInstr *) cp_val(E[0])); E += 1; Goto(*I); } @@ -4465,7 +4490,7 @@ apply_bif_or_nif_epilogue: OpCase(i_global_cons): { - Eterm *next; + BeamInstr *next; #ifdef HYBRID Eterm *hp; @@ -4487,7 +4512,7 @@ apply_bif_or_nif_epilogue: OpCase(i_global_tuple): { - Eterm *next; + BeamInstr *next; int len; #ifdef HYBRID Eterm list; @@ -4522,7 +4547,7 @@ apply_bif_or_nif_epilogue: OpCase(i_global_copy): { - Eterm *next; + BeamInstr *next; PreFetch(0,next); #ifdef HYBRID if (!IS_CONST(r(0))) @@ -4551,7 +4576,7 @@ apply_bif_or_nif_epilogue: OpCase(fmove_ql): { Eterm fr = Arg(1); - Eterm* next; + BeamInstr *next; PreFetch(2, next); GET_DOUBLE(Arg(0), *(FloatDef*)ADD_BYTE_OFFSET(freg, fr)); @@ -4561,7 +4586,7 @@ apply_bif_or_nif_epilogue: OpCase(fmove_dl): { Eterm targ1; Eterm fr = Arg(1); - Eterm* next; + BeamInstr *next; PreFetch(2, next); GetR(0, targ1); @@ -4582,7 +4607,7 @@ apply_bif_or_nif_epilogue: OpCase(fconv_dl): { Eterm targ1; Eterm fr = Arg(1); - Eterm* next; + BeamInstr *next; GetR(0, targ1); PreFetch(2, next); @@ -4611,7 +4636,7 @@ apply_bif_or_nif_epilogue: erl_exit(1, "fclearerror/i_fcheckerror without fpe signals (beam_emu)"); #else OpCase(fclearerror): { - Eterm* next; + BeamInstr *next; PreFetch(0, next); ERTS_FP_CHECK_INIT(c_p); @@ -4619,7 +4644,7 @@ apply_bif_or_nif_epilogue: } OpCase(i_fcheckerror): { - Eterm* next; + BeamInstr *next; PreFetch(0, next); ERTS_FP_ERROR(c_p, freg[0].fd, goto fbadarith); @@ -4633,7 +4658,7 @@ apply_bif_or_nif_epilogue: OpCase(i_fadd_lll): { - Eterm* next; + BeamInstr *next; PreFetch(3, next); ERTS_FP_CHECK_INIT(c_p); @@ -4642,7 +4667,7 @@ apply_bif_or_nif_epilogue: NextPF(3, next); } OpCase(i_fsub_lll): { - Eterm* next; + BeamInstr *next; PreFetch(3, next); ERTS_FP_CHECK_INIT(c_p); @@ -4651,7 +4676,7 @@ apply_bif_or_nif_epilogue: NextPF(3, next); } OpCase(i_fmul_lll): { - Eterm* next; + BeamInstr *next; PreFetch(3, next); ERTS_FP_CHECK_INIT(c_p); @@ -4660,7 +4685,7 @@ apply_bif_or_nif_epilogue: NextPF(3, next); } OpCase(i_fdiv_lll): { - Eterm* next; + BeamInstr *next; PreFetch(3, next); ERTS_FP_CHECK_INIT(c_p); @@ -4669,7 +4694,7 @@ apply_bif_or_nif_epilogue: NextPF(3, next); } OpCase(i_fnegate_ll): { - Eterm* next; + BeamInstr *next; PreFetch(2, next); ERTS_FP_CHECK_INIT(c_p); @@ -4736,7 +4761,7 @@ apply_bif_or_nif_epilogue: neg_o_reds = -c_p->def_arg_reg[4]; FCALLS = c_p->fcalls; SWAPIN; - switch( c_p->def_arg_reg[3] ) { + switch( c_p->def_arg_reg[3] ) { /* XXX:PaN - Halfword wont work with hipe yet... */ case HIPE_MODE_SWITCH_RES_RETURN: ASSERT(is_value(reg[0])); MoveReturn(reg[0], r(0)); @@ -4748,7 +4773,7 @@ apply_bif_or_nif_epilogue: /* This can be used to call any function value, but currently it's only used to call closures referring to unloaded modules. */ { - Eterm *next; + BeamInstr *next; next = call_fun(c_p, c_p->arity - 1, reg, THE_NON_VALUE); SWAPIN; @@ -4881,13 +4906,13 @@ apply_bif_or_nif_epilogue: em_call_error_handler = OpCode(call_error_handler); em_call_traced_function = OpCode(call_traced_function); em_apply_bif = OpCode(apply_bif); - beam_apply[0] = (Eterm) OpCode(i_apply); - beam_apply[1] = (Eterm) OpCode(normal_exit); - beam_exit[0] = (Eterm) OpCode(error_action_code); - beam_continue_exit[0] = (Eterm) OpCode(continue_exit); - beam_return_to_trace[0] = (Eterm) OpCode(i_return_to_trace); - beam_return_trace[0] = (Eterm) OpCode(return_trace); - beam_exception_trace[0] = (Eterm) OpCode(return_trace); /* UGLY */ + beam_apply[0] = (BeamInstr) OpCode(i_apply); + beam_apply[1] = (BeamInstr) OpCode(normal_exit); + beam_exit[0] = (BeamInstr) OpCode(error_action_code); + beam_continue_exit[0] = (BeamInstr) OpCode(continue_exit); + beam_return_to_trace[0] = (BeamInstr) OpCode(i_return_to_trace); + beam_return_trace[0] = (BeamInstr) OpCode(return_trace); + beam_exception_trace[0] = (BeamInstr) OpCode(return_trace); /* UGLY */ /* * Enter all BIFs into the export table. @@ -4897,8 +4922,8 @@ apply_bif_or_nif_epilogue: bif_table[i].name, bif_table[i].arity); bif_export[i] = ep; - ep->code[3] = (Eterm) OpCode(apply_bif); - ep->code[4] = (Eterm) bif_table[i].f; + ep->code[3] = (BeamInstr) OpCode(apply_bif); + ep->code[4] = (BeamInstr) bif_table[i].f; } return; @@ -5001,8 +5026,8 @@ Eterm error_atom[NUMBER_EXIT_CODES] = { * at the point of the original exception. */ -static Eterm* -handle_error(Process* c_p, Eterm* pc, Eterm* reg, BifFunction bf) +static BeamInstr* +handle_error(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf) { Eterm* hp; Eterm Value = c_p->fvalue; @@ -5056,7 +5081,7 @@ handle_error(Process* c_p, Eterm* pc, Eterm* reg, BifFunction bf) /* Find a handler or die */ if ((c_p->catches > 0 || IS_TRACED_FL(c_p, F_EXCEPTION_TRACE)) && !(c_p->freason & EXF_PANIC)) { - Eterm *new_pc; + BeamInstr *new_pc; /* The Beam handler code (catch_end or try_end) checks reg[0] for THE_NON_VALUE to see if the previous code finished abnormally. If so, reg[1], reg[2] and reg[3] should hold the @@ -5082,13 +5107,13 @@ handle_error(Process* c_p, Eterm* pc, Eterm* reg, BifFunction bf) /* * Find the nearest catch handler */ -static Eterm* +static BeamInstr* next_catch(Process* c_p, Eterm *reg) { int active_catches = c_p->catches > 0; int have_return_to_trace = 0; Eterm *ptr, *prev, *return_to_trace_ptr = NULL; - Uint i_return_trace = beam_return_trace[0]; - Uint i_return_to_trace = beam_return_to_trace[0]; + BeamInstr i_return_trace = beam_return_trace[0]; + BeamInstr i_return_to_trace = beam_return_to_trace[0]; ptr = prev = c_p->stop; ASSERT(is_CP(*ptr)); ASSERT(ptr <= STACK_START(c_p)); @@ -5097,9 +5122,9 @@ next_catch(Process* c_p, Eterm *reg) { *cp_val(*ptr) != i_return_to_trace)) && c_p->cp) { /* Can not follow cp here - code may be unloaded */ - Uint *cpp = cp_val((Eterm) c_p->cp); + BeamInstr *cpp = c_p->cp; if (cpp == beam_exception_trace) { - erts_trace_exception(c_p, (Eterm*) ptr[0], + erts_trace_exception(c_p, cp_val(ptr[0]), reg[1], reg[2], ptr+1); /* Skip return_trace parameters */ ptr += 2; @@ -5123,7 +5148,7 @@ next_catch(Process* c_p, Eterm *reg) { if (is_catch(*ptr) && active_catches) goto found_catch; } if (cp_val(*prev) == beam_exception_trace) { - erts_trace_exception(c_p, (Eterm*) ptr[0], + erts_trace_exception(c_p, cp_val(ptr[0]), reg[1], reg[2], ptr+1); } /* Skip return_trace parameters */ @@ -5252,7 +5277,7 @@ expand_error_value(Process* c_p, Uint freason, Eterm Value) { */ static void -save_stacktrace(Process* c_p, Eterm* pc, Eterm* reg, BifFunction bf, +save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf, Eterm args) { struct StackTrace* s; int sz; @@ -5263,7 +5288,7 @@ save_stacktrace(Process* c_p, Eterm* pc, Eterm* reg, BifFunction bf, } /* Create a container for the exception data */ - sz = (offsetof(struct StackTrace, trace) + sizeof(Eterm)*depth + sz = (offsetof(struct StackTrace, trace) + sizeof(BeamInstr *)*depth + sizeof(Eterm) - 1) / sizeof(Eterm); s = (struct StackTrace *) HAlloc(c_p, 1 + sz); /* The following fields are inside the bignum */ @@ -5350,9 +5375,10 @@ save_stacktrace(Process* c_p, Eterm* pc, Eterm* reg, BifFunction bf, /* Save the actual stack trace */ if (depth > 0) { - Eterm *ptr, *prev = s->depth ? s->trace[s->depth-1] : NULL; - Uint i_return_trace = beam_return_trace[0]; - Uint i_return_to_trace = beam_return_to_trace[0]; + Eterm *ptr; + BeamInstr *prev = s->depth ? s->trace[s->depth-1] : NULL; + BeamInstr i_return_trace = beam_return_trace[0]; + BeamInstr i_return_to_trace = beam_return_to_trace[0]; /* * Traverse the stack backwards and add all unique continuation * pointers to the buffer, up to the maximum stack trace size. @@ -5365,7 +5391,7 @@ save_stacktrace(Process* c_p, Eterm* pc, Eterm* reg, BifFunction bf, *cp_val(*ptr) != i_return_to_trace)) && c_p->cp) { /* Can not follow cp here - code may be unloaded */ - Uint *cpp = cp_val((Eterm) c_p->cp); + BeamInstr *cpp = c_p->cp; if (cpp == beam_exception_trace || cpp == beam_return_trace) { /* Skip return_trace parameters */ ptr += 2; @@ -5385,7 +5411,7 @@ save_stacktrace(Process* c_p, Eterm* pc, Eterm* reg, BifFunction bf, /* Skip stack frame variables */ do ++ptr; while (is_not_CP(*ptr)); } else { - Eterm *cp = (Eterm *)(*ptr); + BeamInstr *cp = cp_val(*ptr); if (cp != prev) { /* Record non-duplicates only */ prev = cp; @@ -5457,9 +5483,12 @@ build_stacktrace(Process* c_p, Eterm exc) { struct StackTrace* s; Eterm args; int depth; - Eterm* current; + BeamInstr* current; +#if HALFWORD_HEAP + BeamInstr current_buff[3]; +#endif Eterm Where = NIL; - Eterm* next_p = &Where; + Eterm *next_p = &Where; if (! (s = get_trace_from_exc(exc))) { return NIL; @@ -5487,7 +5516,14 @@ build_stacktrace(Process* c_p, Eterm exc) { * (e.g. spawn_link(erlang, abs, [1])). */ if (current == NULL) { +#if HALFWORD_HEAP + current = current_buff; + current[0] = (BeamInstr) c_p->initial[0]; + current[1] = (BeamInstr) c_p->initial[1]; + current[2] = (BeamInstr) c_p->initial[2]; +#else current = c_p->initial; +#endif args = am_true; /* Just in case */ } else { args = get_args_from_exc(exc); @@ -5523,7 +5559,7 @@ build_stacktrace(Process* c_p, Eterm exc) { * Finally, we go through the saved continuation pointers. */ for (i = 0; i < depth; i++) { - Eterm *fi = find_function_from_pc((Eterm *) s->trace[i]); + BeamInstr *fi = find_function_from_pc((BeamInstr *) s->trace[i]); if (fi == NULL) continue; mfa = TUPLE3(hp, fi[0], fi[1], make_small(fi[2])); hp += 4; @@ -5540,7 +5576,7 @@ build_stacktrace(Process* c_p, Eterm exc) { static Eterm -call_error_handler(Process* p, Eterm* fi, Eterm* reg) +call_error_handler(Process* p, BeamInstr* fi, Eterm* reg) { Eterm* hp; Export* ep; @@ -5588,7 +5624,7 @@ call_error_handler(Process* p, Eterm* fi, Eterm* reg) } static Eterm -call_breakpoint_handler(Process* p, Eterm* fi, Eterm* reg) +call_breakpoint_handler(Process* p, BeamInstr* fi, Eterm* reg) { Eterm* hp; Export* ep; @@ -5681,7 +5717,7 @@ apply_setup_error_handler(Process* p, Eterm module, Eterm function, Uint arity, return ep; } -static Uint* +static BeamInstr* apply(Process* p, Eterm module, Eterm function, Eterm args, Eterm* reg) { int arity; @@ -5763,7 +5799,7 @@ apply(Process* p, Eterm module, Eterm function, Eterm args, Eterm* reg) return ep->address; } -static Uint* +static BeamInstr* fixed_apply(Process* p, Eterm* reg, Uint arity) { Export* ep; @@ -5869,7 +5905,7 @@ hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* reg) c_p->stop = STACK_START(c_p); c_p->catches = 0; c_p->i = beam_apply; - c_p->cp = (Eterm *) beam_apply+1; + c_p->cp = (BeamInstr *) beam_apply+1; /* * If there are no waiting messages, garbage collect and @@ -5899,7 +5935,7 @@ hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* reg) return 1; } -static Uint* +static BeamInstr* call_fun(Process* p, /* Current process. */ int arity, /* Number of arguments for Fun. */ Eterm* reg, /* Contents of registers. */ @@ -5919,7 +5955,7 @@ call_fun(Process* p, /* Current process. */ if (is_fun_header(hdr)) { ErlFunThing* funp = (ErlFunThing *) fun_val(fun); ErlFunEntry* fe; - Eterm* code_ptr; + BeamInstr* code_ptr; Eterm* var_ptr; int actual_arity; unsigned num_free; @@ -6014,8 +6050,12 @@ call_fun(Process* p, /* Current process. */ } } } else if (is_export_header(hdr)) { - Export* ep = (Export *) (export_val(fun))[1]; - int actual_arity = (int) ep->code[2]; + Export *ep; + int actual_arity; + + ep = *((Export **) (export_val(fun) + 1)); + actual_arity = (int) ep->code[2]; + if (arity == actual_arity) { return ep->address; } else { @@ -6082,7 +6122,7 @@ call_fun(Process* p, /* Current process. */ } } -static Eterm* +static BeamInstr* apply_fun(Process* p, Eterm fun, Eterm args, Eterm* reg) { int arity; @@ -6176,7 +6216,7 @@ erts_is_builtin(Eterm Mod, Eterm Name, int arity) if ((ep = export_get(&e)) == NULL) { return 0; } - return ep->address == ep->code+3 && (ep->code[3] == (Uint) em_apply_bif); + return ep->address == ep->code+3 && (ep->code[3] == (BeamInstr) em_apply_bif); } diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 99fab28dce..bbfeac5397 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -51,9 +51,9 @@ ErlDrvBinary* erts_gzinflate_buffer(char*, int); #define EXPORTED 2 #ifdef NO_JUMP_TABLE -# define BeamOpCode(Op) ((Uint)(Op)) +# define BeamOpCode(Op) ((BeamInstr)(Op)) #else -# define BeamOpCode(Op) ((Eterm)beam_ops[Op]) +# define BeamOpCode(Op) ((BeamInstr)beam_ops[Op]) #endif #if defined(WORDS_BIGENDIAN) @@ -94,7 +94,7 @@ typedef struct { typedef struct { unsigned type; /* Type of operand. */ - Uint val; /* Value of operand. */ + BeamInstr val; /* Value of operand. */ Uint bigarity; /* Arity for bignumbers (only). */ } GenOpArg; @@ -142,7 +142,7 @@ typedef struct { typedef struct { Eterm function; /* Tagged atom for function. */ int arity; /* Arity. */ - Eterm* address; /* Address to function in code. */ + BeamInstr* address; /* Address to function in code. */ } ExportEntry; #define MakeIffId(a, b, c, d) \ @@ -274,13 +274,13 @@ typedef struct { int num_functions; /* Number of functions in module. */ int num_labels; /* Number of labels. */ int code_buffer_size; /* Size of code buffer in words. */ - Eterm* code; /* Loaded code. */ + BeamInstr* code; /* Loaded code. */ int ci; /* Current index into loaded code. */ Label* labels; - Uint put_strings; /* Linked list of put_string instructions. */ - Uint new_bs_put_strings; /* Linked list of i_new_bs_put_string instructions. */ + BeamInstr put_strings; /* Linked list of put_string instructions. */ + BeamInstr new_bs_put_strings; /* Linked list of i_new_bs_put_string instructions. */ StringPatch* string_patches; /* Linked list of position into string table to patch. */ - Uint catches; /* Linked list of catch_yf instructions. */ + BeamInstr catches; /* Linked list of catch_yf instructions. */ unsigned loaded_size; /* Final size of code when loaded. */ byte mod_md5[16]; /* MD5 for module code. */ int may_load_nif; /* true if NIFs may later be loaded for this module */ @@ -341,7 +341,7 @@ typedef struct { #define GetTagAndValue(Stp, Tag, Val) \ do { \ - Uint __w; \ + BeamInstr __w; \ GetByte(Stp, __w); \ Tag = __w & 0x07; \ if ((__w & 0x08) == 0) { \ @@ -388,7 +388,7 @@ typedef struct { goto load_error; \ } else { \ int __n = (N); \ - Uint __result = 0; \ + BeamInstr __result = 0; \ Stp->file_left -= (unsigned) __n; \ while (__n-- > 0) { \ __result = __result << 8 | *Stp->file_p++; \ @@ -465,7 +465,7 @@ static int bin_load(Process *c_p, ErtsProcLocks c_p_locks, static void init_state(LoaderState* stp); static int insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm module, - Eterm* code, Uint size, Uint catches); + BeamInstr* code, Uint size, BeamInstr catches); static int scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory); static int load_atom_table(LoaderState* stp); @@ -499,8 +499,8 @@ static void load_printf(int line, LoaderState* context, char *fmt, ...); static int transform_engine(LoaderState* st); static void id_to_string(Uint id, char* s); static void new_genop(LoaderState* stp); -static int get_int_val(LoaderState* stp, Uint len_code, Uint* result); -static int get_erlang_integer(LoaderState* stp, Uint len_code, Uint* result); +static int get_int_val(LoaderState* stp, Uint len_code, BeamInstr* result); +static int get_erlang_integer(LoaderState* stp, Uint len_code, BeamInstr* result); static int new_label(LoaderState* stp); static void new_literal_patch(LoaderState* stp, int pos); static void new_string_patch(LoaderState* stp, int pos); @@ -513,7 +513,7 @@ static Eterm compilation_info_for_module(Process* p, Eterm mod); static Eterm native_addresses(Process* p, Eterm mod); int patch_funentries(Eterm Patchlist); int patch(Eterm Addresses, Uint fe); -static int safe_mul(Uint a, Uint b, Uint* resp); +static int safe_mul(UWord a, UWord b, UWord* resp); static int must_swap_floats; @@ -591,7 +591,18 @@ erts_load_module(Process *c_p, } return result; } - +/* #define LOAD_MEMORY_HARD_DEBUG 1*/ + +#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) +/* Requires allocators ERTS_ALLOC_UTIL_HARD_DEBUG also set in erl_alloc_util.h */ +extern void check_allocators(void); +extern void check_allocated_block(Uint type, void *blk); +#define CHKALLOC() check_allocators() +#define CHKBLK(TYPE,BLK) if ((BLK) != NULL) check_allocated_block((TYPE),(BLK)) +#else +#define CHKALLOC() /* nothing */ +#define CHKBLK(TYPE,BLK) /* nothing */ +#endif static int bin_load(Process *c_p, ErtsProcLocks c_p_locks, @@ -608,6 +619,12 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Scan the IFF file. */ +#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) + erts_fprintf(stderr,"Loading a module\n"); +#endif + + CHKALLOC(); + CHKBLK(ERTS_ALC_T_CODE,state.code); state.file_name = "IFF header for Beam file"; state.file_p = bytes; state.file_left = unloaded_size; @@ -619,6 +636,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the header for the code chunk. */ + CHKBLK(ERTS_ALC_T_CODE,state.code); define_file(&state, "code chunk header", CODE_CHUNK); if (!read_code_header(&state)) { goto load_error; @@ -628,6 +646,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the atom table. */ + CHKBLK(ERTS_ALC_T_CODE,state.code); define_file(&state, "atom table", ATOM_CHUNK); if (!load_atom_table(&state)) { goto load_error; @@ -637,6 +656,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the import table. */ + CHKBLK(ERTS_ALC_T_CODE,state.code); define_file(&state, "import table", IMP_CHUNK); if (!load_import_table(&state)) { goto load_error; @@ -646,6 +666,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the lambda (fun) table. */ + CHKBLK(ERTS_ALC_T_CODE,state.code); if (state.chunks[LAMBDA_CHUNK].size > 0) { define_file(&state, "lambda (fun) table", LAMBDA_CHUNK); if (!read_lambda_table(&state)) { @@ -657,6 +678,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the literal table. */ + CHKBLK(ERTS_ALC_T_CODE,state.code); if (state.chunks[LITERAL_CHUNK].size > 0) { define_file(&state, "literals table (constant pool)", LITERAL_CHUNK); if (!read_literal_table(&state)) { @@ -668,18 +690,25 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Load the code chunk. */ + CHKBLK(ERTS_ALC_T_CODE,state.code); state.file_name = "code chunk"; state.file_p = state.code_start; state.file_left = state.code_size; - if (!load_code(&state) || !freeze_code(&state)) { + if (!load_code(&state)) { goto load_error; } + CHKBLK(ERTS_ALC_T_CODE,state.code); + if (!freeze_code(&state)) { + goto load_error; + } + /* * Read and validate the export table. (This must be done after * loading the code, because it contains labels.) */ + CHKBLK(ERTS_ALC_T_CODE,state.code); define_file(&state, "export table", EXP_CHUNK); if (!read_export_table(&state)) { goto load_error; @@ -690,16 +719,25 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * exported and imported functions. This can't fail. */ + CHKBLK(ERTS_ALC_T_CODE,state.code); rval = insert_new_code(c_p, c_p_locks, state.group_leader, state.module, state.code, state.loaded_size, state.catches); if (rval < 0) { goto load_error; } + CHKBLK(ERTS_ALC_T_CODE,state.code); final_touch(&state); /* * Loading succeded. */ + CHKBLK(ERTS_ALC_T_CODE,state.code); +#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) + erts_fprintf(stderr,"Loaded %T\n",*modp); +#if 0 + debug_dump_code(state.code,state.ci); +#endif +#endif rval = 0; state.code = NULL; /* Prevent code from being freed. */ *modp = state.module; @@ -791,7 +829,7 @@ init_state(LoaderState* stp) static int insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, - Eterm group_leader, Eterm module, Eterm* code, Uint size, Uint catches) + Eterm group_leader, Eterm module, BeamInstr* code, Uint size, BeamInstr catches) { Module* modp; int rval; @@ -833,7 +871,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, modules[i] = modules[i-1]; } modules[i].start = code; - modules[i].end = (Eterm *) (((byte *)code) + size); + modules[i].end = (BeamInstr *) (((byte *)code) + size); num_loaded_modules++; mid_module = &modules[num_loaded_modules/2]; return 0; @@ -1083,7 +1121,7 @@ load_import_table(LoaderState* stp) * the BIF function. */ if ((e = erts_find_export_entry(mod, func, arity)) != NULL) { - if (e->code[3] == (Uint) em_apply_bif) { + if (e->code[3] == (BeamInstr) em_apply_bif) { stp->import[i].bf = (BifFunction) e->code[4]; if (func == am_load_nif && mod == am_erlang && arity == 2) { stp->may_load_nif = 1; @@ -1151,7 +1189,7 @@ read_export_table(LoaderState* stp) * redefine). */ if ((e = erts_find_export_entry(stp->module, func, arity)) != NULL) { - if (e->code[3] == (Uint) em_apply_bif) { + if (e->code[3] == (BeamInstr) em_apply_bif) { int j; for (j = 0; j < sizeof(allow_redef)/sizeof(allow_redef[0]); j++) { @@ -1220,7 +1258,7 @@ static int read_literal_table(LoaderState* stp) { int i; - Uint uncompressed_sz; + BeamInstr uncompressed_sz; byte* uncompressed = 0; GetInt(stp, 4, uncompressed_sz); @@ -1338,8 +1376,8 @@ read_code_header(LoaderState* stp) * Initialize code area. */ stp->code_buffer_size = erts_next_heap_size(2048 + stp->num_functions, 0); - stp->code = (Eterm*) erts_alloc(ERTS_ALC_T_CODE, - sizeof(Eterm) * stp->code_buffer_size); + stp->code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE, + sizeof(BeamInstr) * stp->code_buffer_size); stp->code[MI_NUM_FUNCTIONS] = stp->num_functions; stp->ci = MI_FUNCTIONS + stp->num_functions + 1; @@ -1365,16 +1403,18 @@ read_code_header(LoaderState* stp) LoadError2(Stp, "bad tag %d; expected %d", Actual, Expected); \ } else {} -#define Need(w) \ - ASSERT(ci <= code_buffer_size); \ - if (code_buffer_size < ci+(w)) { \ - code_buffer_size = erts_next_heap_size(ci+(w), 0); \ - stp->code = code \ - = (Eterm *) erts_realloc(ERTS_ALC_T_CODE, \ - (void *) code, \ - code_buffer_size * sizeof(Eterm)); \ - } +#define CodeNeed(w) do { \ + ASSERT(ci <= code_buffer_size); \ + if (code_buffer_size < ci+(w)) { \ + code_buffer_size = erts_next_heap_size(ci+(w), 0); \ + stp->code = code \ + = (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, \ + (void *) code, \ + code_buffer_size * sizeof(BeamInstr)); \ + } \ +} while (0) +#define TermWords(t) (((t) / (sizeof(BeamInstr)/sizeof(Eterm))) + !!((t) % (sizeof(BeamInstr)/sizeof(Eterm)))) static int @@ -1387,7 +1427,7 @@ load_code(LoaderState* stp) char* sign; int arg; /* Number of current argument. */ int num_specific; /* Number of specific ops for current. */ - Eterm* code; + BeamInstr* code; int code_buffer_size; int specific; Uint last_label = 0; /* Number of last label. */ @@ -1446,7 +1486,7 @@ load_code(LoaderState* stp) if (((First) & 0x08) == 0) { \ Val = (First) >> 4; \ } else if (((First) & 0x10) == 0) { \ - Uint __w; \ + BeamInstr __w; \ GetByte(Stp, __w); \ Val = (((First) >> 5) << 8) | __w; \ } else { \ @@ -1455,7 +1495,7 @@ load_code(LoaderState* stp) } while (0) for (arg = 0; arg < arity; arg++) { - Uint first; + BeamInstr first; GetByte(stp, first); last_op->a[arg].type = first & 0x07; @@ -1464,7 +1504,7 @@ load_code(LoaderState* stp) if ((first & 0x08) == 0) { last_op->a[arg].val = first >> 4; } else if ((first & 0x10) == 0) { - Uint w; + BeamInstr w; GetByte(stp, w); ASSERT(first < 0x800); last_op->a[arg].val = ((first >> 5) << 8) | w; @@ -1523,7 +1563,7 @@ load_code(LoaderState* stp) break; case TAG_z: { - Uint ext_tag; + BeamInstr ext_tag; unsigned tag; GetValue(stp, first, ext_tag); @@ -1531,14 +1571,14 @@ load_code(LoaderState* stp) case 0: /* Floating point number */ { Eterm* hp; -# ifndef ARCH_64 +#if !defined(ARCH_64) || HALFWORD_HEAP /* XXX:PaN - Should use ARCH_64 variant instead */ Uint high, low; # endif last_op->a[arg].val = new_literal(stp, &hp, FLOAT_SIZE_OBJECT); hp[0] = HEADER_FLONUM; last_op->a[arg].type = TAG_q; -# ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP GetInt(stp, 8, hp[1]); # else GetInt(stp, 4, high); @@ -1575,10 +1615,10 @@ load_code(LoaderState* stp) break; case 3: /* Allocation list. */ { - Uint n; - Uint type; - Uint val; - Uint words = 0; + BeamInstr n; + BeamInstr type; + BeamInstr val; + BeamInstr words = 0; stp->new_float_instructions = 1; GetTagAndValue(stp, tag, n); @@ -1607,7 +1647,7 @@ load_code(LoaderState* stp) } case 4: /* Literal. */ { - Uint val; + BeamInstr val; GetTagAndValue(stp, tag, val); VerifyTag(stp, tag, TAG_u); @@ -1734,7 +1774,7 @@ load_code(LoaderState* stp) } stp->specific_op = specific; - Need(opc[stp->specific_op].sz+2); /* Extra margin for packing */ + CodeNeed(opc[stp->specific_op].sz+2); /* Extra margin for packing */ code[ci++] = BeamOpCode(stp->specific_op); } @@ -1772,7 +1812,7 @@ load_code(LoaderState* stp) case 'c': /* Tagged constant */ switch (tag) { case TAG_i: - code[ci++] = make_small(tmp_op->a[arg].val); + code[ci++] = (BeamInstr) make_small((Uint) tmp_op->a[arg].val); break; case TAG_a: code[ci++] = tmp_op->a[arg].val; @@ -1802,7 +1842,7 @@ load_code(LoaderState* stp) code[ci++] = make_yreg(tmp_op->a[arg].val); break; case TAG_i: - code[ci++] = make_small(tmp_op->a[arg].val); + code[ci++] = (BeamInstr) make_small((Uint)tmp_op->a[arg].val); break; case TAG_a: code[ci++] = tmp_op->a[arg].val; @@ -1896,12 +1936,12 @@ load_code(LoaderState* stp) if (stp->import[i].bf == NULL) { LoadError1(stp, "not a BIF: import table index %d", i); } - code[ci++] = (Eterm) stp->import[i].bf; + code[ci++] = (BeamInstr) stp->import[i].bf; break; - case 'P': /* Byte offset into tuple */ + case 'P': /* Byte offset into tuple */ /* XXX:PaN - * sizeof(Eterm or Eterm *) ? */ VerifyTag(stp, tag, TAG_u); tmp = tmp_op->a[arg].val; - code[ci++] = (Eterm) ((tmp_op->a[arg].val+1) * sizeof(Eterm *)); + code[ci++] = (BeamInstr) ((tmp_op->a[arg].val+1) * sizeof(Eterm)); break; case 'l': /* Floating point register. */ VerifyTag(stp, tag_to_letter[tag], *sign); @@ -1925,17 +1965,17 @@ load_code(LoaderState* stp) for ( ; arg < tmp_op->arity; arg++) { switch (tmp_op->a[arg].type) { case TAG_i: - Need(1); + CodeNeed(1); code[ci++] = make_small(tmp_op->a[arg].val); break; case TAG_u: case TAG_a: case TAG_v: - Need(1); + CodeNeed(1); code[ci++] = tmp_op->a[arg].val; break; case TAG_f: - Need(1); + CodeNeed(1); code[ci] = stp->labels[tmp_op->a[arg].val].patches; stp->labels[tmp_op->a[arg].val].patches = ci; ci++; @@ -1947,24 +1987,41 @@ load_code(LoaderState* stp) lit = stp->literals[tmp_op->a[arg].val].term; if (is_big(lit)) { Eterm* bigp; + Eterm *tmp; Uint size; + Uint term_size; bigp = big_val(lit); - size = bignum_header_arity(*bigp); - Need(size+1); - code[ci++] = *bigp++; - while (size-- > 0) { - code[ci++] = *bigp++; + term_size = bignum_header_arity(*bigp); + size = TermWords(term_size + 1); + CodeNeed(size); + tmp = (Eterm *) (code + ci); + *tmp++ = *bigp++; + while (term_size-- > 0) { + *tmp++ = *bigp++; } + ci +=size; } else if (is_float(lit)) { -#ifdef ARCH_64 - Need(1); +#if defined(ARCH_64) && !HALFWORD_HEAP + CodeNeed(1); code[ci++] = float_val(stp->literals[tmp_op->a[arg].val].term)[1]; +#elif HALFWORD_HEAP + Eterm* fptr; + Uint size; + Eterm *tmp; + + fptr = float_val(stp->literals[tmp_op->a[arg].val].term)+1; + size = TermWords(2); + CodeNeed(size); + tmp = (Eterm *) (code + ci); + *tmp++ = *fptr++; + *tmp = *fptr; + ci += size; #else Eterm* fptr; fptr = float_val(stp->literals[tmp_op->a[arg].val].term)+1; - Need(2); + CodeNeed(2); code[ci++] = *fptr++; code[ci++] = *fptr; #endif @@ -1984,10 +2041,10 @@ load_code(LoaderState* stp) */ if (opc[stp->specific_op].pack[0]) { char* prog; /* Program for packing engine. */ - Uint stack[8]; /* Stack. */ - Uint* sp = stack; /* Points to next free position. */ - Uint packed = 0; /* Accumulator for packed operations. */ - + BeamInstr stack[8]; /* Stack. */ + BeamInstr* sp = stack; /* Points to next free position. */ + BeamInstr packed = 0; /* Accumulator for packed operations. */ + for (prog = opc[stp->specific_op].pack; *prog; prog++) { switch (*prog) { case 'g': /* Get instruction; push on stack. */ @@ -2000,7 +2057,7 @@ load_code(LoaderState* stp) packed = (packed << BEAM_TIGHT_SHIFT) | code[--ci]; break; case '6': /* Shift 16 steps */ - packed = (packed << 16) | code[--ci]; + packed = (packed << BEAM_LOOSE_SHIFT) | code[--ci]; break; case 'p': /* Put instruction (from stack). */ code[ci++] = *--sp; @@ -2037,9 +2094,9 @@ load_code(LoaderState* stp) /* Must make room for call_nif op */ int pad = MIN_FUNC_SZ - (finfo_ix - last_func_start); ASSERT(pad > 0 && pad < MIN_FUNC_SZ); - Need(pad); - sys_memmove(&code[finfo_ix+pad], &code[finfo_ix], FINFO_SZ*sizeof(Eterm)); - sys_memset(&code[finfo_ix], 0, pad*sizeof(Eterm)); + CodeNeed(pad); + sys_memmove(&code[finfo_ix+pad], &code[finfo_ix], FINFO_SZ*sizeof(BeamInstr)); + sys_memset(&code[finfo_ix], 0, pad*sizeof(BeamInstr)); ci += pad; stp->labels[last_label].value += pad; } @@ -2050,6 +2107,7 @@ load_code(LoaderState* stp) */ stp->function = code[ci-2]; stp->arity = code[ci-1]; + ASSERT(stp->labels[last_label].value == ci - FINFO_SZ); offset = MI_FUNCTIONS + function_number; code[offset] = stp->labels[last_label].patches; @@ -2161,7 +2219,6 @@ load_code(LoaderState* stp) } } -#undef Need load_error: return 0; @@ -2373,7 +2430,7 @@ gen_get_integer2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live, GenOpArg Flags, GenOpArg Dst) { GenOp* op; - Uint bits; + UWord bits; NEW_GENOP(stp, op); @@ -2838,14 +2895,14 @@ gen_literal_timeout(LoaderState* stp, GenOpArg Fail, GenOpArg Time) op->a[1].type = TAG_u; if (Time.type == TAG_i && (timeout = Time.val) >= 0 && -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP (timeout >> 32) == 0 #else 1 #endif ) { op->a[1].val = timeout; -#if !defined(ARCH_64) +#if !defined(ARCH_64) || HALFWORD_HEAP } else if (Time.type == TAG_q) { Eterm big; @@ -2856,11 +2913,13 @@ gen_literal_timeout(LoaderState* stp, GenOpArg Fail, GenOpArg Time) if (big_arity(big) > 1 || big_sign(big)) { goto error; } else { - (void) term_to_Uint(big, &op->a[1].val); + Uint u; + (void) term_to_Uint(big, &u); + op->a[1].val = (BeamInstr) u; } #endif } else { -#if !defined(ARCH_64) +#if !defined(ARCH_64) || HALFWORD_HEAP error: #endif op->op = genop_i_wait_error_0; @@ -2883,14 +2942,14 @@ gen_literal_timeout_locked(LoaderState* stp, GenOpArg Fail, GenOpArg Time) op->a[1].type = TAG_u; if (Time.type == TAG_i && (timeout = Time.val) >= 0 && -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP (timeout >> 32) == 0 #else 1 #endif ) { op->a[1].val = timeout; -#ifndef ARCH_64 +#if !defined(ARCH_64) || HALFWORD_HEAP } else if (Time.type == TAG_q) { Eterm big; @@ -2901,11 +2960,13 @@ gen_literal_timeout_locked(LoaderState* stp, GenOpArg Fail, GenOpArg Time) if (big_arity(big) > 1 || big_sign(big)) { goto error; } else { - (void) term_to_Uint(big, &op->a[1].val); + Uint u; + (void) term_to_Uint(big, &u); + op->a[1].val = (BeamInstr) u; } #endif } else { -#ifndef ARCH_64 +#if !defined(ARCH_64) || HALFWORD_HEAP error: #endif op->op = genop_i_wait_error_locked_0; @@ -3321,7 +3382,7 @@ gen_make_fun2(LoaderState* stp, GenOpArg idx) op->op = genop_i_make_fun_2; op->arity = 2; op->a[0].type = TAG_u; - op->a[0].val = (Uint) fe; + op->a[0].val = (BeamInstr) fe; op->a[1].type = TAG_u; op->a[1].val = stp->lambdas[idx.val].num_free; op->next = NULL; @@ -3342,21 +3403,21 @@ gen_guard_bif(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif, op->a[1].type = TAG_u; bf = stp->import[Bif.val].bf; if (bf == length_1) { - op->a[1].val = (Uint) (void *) erts_gc_length_1; + op->a[1].val = (BeamInstr) (void *) erts_gc_length_1; } else if (bf == size_1) { - op->a[1].val = (Uint) (void *) erts_gc_size_1; + op->a[1].val = (BeamInstr) (void *) erts_gc_size_1; } else if (bf == bit_size_1) { - op->a[1].val = (Uint) (void *) erts_gc_bit_size_1; + op->a[1].val = (BeamInstr) (void *) erts_gc_bit_size_1; } else if (bf == byte_size_1) { - op->a[1].val = (Uint) (void *) erts_gc_byte_size_1; + op->a[1].val = (BeamInstr) (void *) erts_gc_byte_size_1; } else if (bf == abs_1) { - op->a[1].val = (Uint) (void *) erts_gc_abs_1; + op->a[1].val = (BeamInstr) (void *) erts_gc_abs_1; } else if (bf == float_1) { - op->a[1].val = (Uint) (void *) erts_gc_float_1; + op->a[1].val = (BeamInstr) (void *) erts_gc_float_1; } else if (bf == round_1) { - op->a[1].val = (Uint) (void *) erts_gc_round_1; + op->a[1].val = (BeamInstr) (void *) erts_gc_round_1; } else if (bf == trunc_1) { - op->a[1].val = (Uint) (void *) erts_gc_trunc_1; + op->a[1].val = (BeamInstr) (void *) erts_gc_trunc_1; } else { abort(); } @@ -3376,7 +3437,8 @@ gen_guard_bif(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif, static int freeze_code(LoaderState* stp) { - Eterm* code = stp->code; + BeamInstr* code = stp->code; + Uint *literal_end = NULL; Uint index; int i; byte* str_table; @@ -3401,46 +3463,49 @@ freeze_code(LoaderState* stp) * Calculate the final size of the code. */ - size = (stp->ci + stp->total_literal_size) * sizeof(Eterm) + + size = (stp->ci * sizeof(BeamInstr)) + (stp->total_literal_size * sizeof(Eterm)) + strtab_size + attr_size + compile_size; /* * Move the code to its final location. */ - code = (Eterm *) erts_realloc(ERTS_ALC_T_CODE, (void *) code, size); - + code = (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, (void *) code, size); + CHKBLK(ERTS_ALC_T_CODE,code); /* * Place a pointer to the op_int_code_end instruction in the * function table in the beginning of the file. */ - code[MI_FUNCTIONS+stp->num_functions] = (Eterm) (code + stp->ci - 1); + code[MI_FUNCTIONS+stp->num_functions] = (BeamInstr) (code + stp->ci - 1); + CHKBLK(ERTS_ALC_T_CODE,code); /* * Store the pointer to the on_load function. */ if (stp->on_load) { - code[MI_ON_LOAD_FUNCTION_PTR] = (Eterm) (code + stp->on_load); + code[MI_ON_LOAD_FUNCTION_PTR] = (BeamInstr) (code + stp->on_load); } else { code[MI_ON_LOAD_FUNCTION_PTR] = 0; } + CHKBLK(ERTS_ALC_T_CODE,code); + literal_end = (Uint *) (code+stp->ci); /* * Place the literal heap directly after the code and fix up all * put_literal instructions that refer to it. */ { - Eterm* ptr; - Eterm* low; - Eterm* high; + Uint* ptr; + Uint* low; + Uint* high; LiteralPatch* lp; - low = code+stp->ci; + low = (Uint *) (code+stp->ci); high = low + stp->total_literal_size; - code[MI_LITERALS_START] = (Eterm) low; - code[MI_LITERALS_END] = (Eterm) high; + code[MI_LITERALS_START] = (BeamInstr) low; + code[MI_LITERALS_END] = (BeamInstr) high; ptr = low; for (i = 0; i < stp->num_literals; i++) { Uint offset; @@ -3472,7 +3537,7 @@ freeze_code(LoaderState* stp) } lp = stp->literal_patches; while (lp != 0) { - Uint* op_ptr; + BeamInstr* op_ptr; Uint literal; Literal* lit; @@ -3485,38 +3550,48 @@ freeze_code(LoaderState* stp) op_ptr[0] = literal; lp = lp->next; } - stp->ci += stp->total_literal_size; + literal_end += stp->total_literal_size; } /* * Place the string table and, optionally, attributes, after the literal heap. */ + CHKBLK(ERTS_ALC_T_CODE,code); - sys_memcpy(code+stp->ci, stp->chunks[STR_CHUNK].start, strtab_size); - str_table = (byte *) (code+stp->ci); + sys_memcpy(literal_end, stp->chunks[STR_CHUNK].start, strtab_size); + CHKBLK(ERTS_ALC_T_CODE,code); + str_table = (byte *) literal_end; if (attr_size) { byte* attr = str_table + strtab_size; sys_memcpy(attr, stp->chunks[ATTR_CHUNK].start, stp->chunks[ATTR_CHUNK].size); - code[MI_ATTR_PTR] = (Eterm) attr; - code[MI_ATTR_SIZE] = (Eterm) stp->chunks[ATTR_CHUNK].size; + code[MI_ATTR_PTR] = (BeamInstr) attr; + code[MI_ATTR_SIZE] = (BeamInstr) stp->chunks[ATTR_CHUNK].size; decoded_size = erts_decode_ext_size(attr, attr_size, 0); if (decoded_size < 0) { LoadError0(stp, "bad external term representation of module attributes"); } code[MI_ATTR_SIZE_ON_HEAP] = decoded_size; } + CHKBLK(ERTS_ALC_T_CODE,code); if (compile_size) { byte* compile_info = str_table + strtab_size + attr_size; + CHKBLK(ERTS_ALC_T_CODE,code); sys_memcpy(compile_info, stp->chunks[COMPILE_CHUNK].start, stp->chunks[COMPILE_CHUNK].size); - code[MI_COMPILE_PTR] = (Eterm) compile_info; - code[MI_COMPILE_SIZE] = (Eterm) stp->chunks[COMPILE_CHUNK].size; + CHKBLK(ERTS_ALC_T_CODE,code); + code[MI_COMPILE_PTR] = (BeamInstr) compile_info; + CHKBLK(ERTS_ALC_T_CODE,code); + code[MI_COMPILE_SIZE] = (BeamInstr) stp->chunks[COMPILE_CHUNK].size; + CHKBLK(ERTS_ALC_T_CODE,code); decoded_size = erts_decode_ext_size(compile_info, compile_size, 0); + CHKBLK(ERTS_ALC_T_CODE,code); if (decoded_size < 0) { LoadError0(stp, "bad external term representation of compilation information"); } + CHKBLK(ERTS_ALC_T_CODE,code); code[MI_COMPILE_SIZE_ON_HEAP] = decoded_size; } + CHKBLK(ERTS_ALC_T_CODE,code); /* @@ -3529,9 +3604,10 @@ freeze_code(LoaderState* stp) while (index != 0) { Uint next = code[index]; code[index] = BeamOpCode(op_put_string_IId); - code[index+2] = (Uint) (str_table + code[index+2] + code[index+1] - 1); + code[index+2] = (BeamInstr) (str_table + code[index+2] + code[index+1] - 1); index = next; } + CHKBLK(ERTS_ALC_T_CODE,code); /* * Go through all i_new_bs_put_strings instructions, restore the pointer to @@ -3543,23 +3619,25 @@ freeze_code(LoaderState* stp) while (index != 0) { Uint next = code[index]; code[index] = BeamOpCode(op_bs_put_string_II); - code[index+2] = (Uint) (str_table + code[index+2]); + code[index+2] = (BeamInstr) (str_table + code[index+2]); index = next; } + CHKBLK(ERTS_ALC_T_CODE,code); { StringPatch* sp = stp->string_patches; while (sp != 0) { - Uint* op_ptr; + BeamInstr* op_ptr; byte* strp; op_ptr = code + sp->pos; strp = str_table + op_ptr[0]; - op_ptr[0] = (Eterm) strp; + op_ptr[0] = (BeamInstr) strp; sp = sp->next; } } + CHKBLK(ERTS_ALC_T_CODE,code); /* * Resolve all labels. @@ -3579,10 +3657,11 @@ freeze_code(LoaderState* stp) ASSERT(this_patch < stp->ci); next_patch = code[this_patch]; ASSERT(next_patch < stp->ci); - code[this_patch] = (Uint) (code + value); + code[this_patch] = (BeamInstr) (code + value); this_patch = next_patch; } } + CHKBLK(ERTS_ALC_T_CODE,code); /* * Fix all catch_yf instructions. @@ -3590,13 +3669,14 @@ freeze_code(LoaderState* stp) index = stp->catches; catches = BEAM_CATCHES_NIL; while (index != 0) { - Uint next = code[index]; + BeamInstr next = code[index]; code[index] = BeamOpCode(op_catch_yf); - catches = beam_catches_cons((Uint*)code[index+2], catches); + catches = beam_catches_cons((BeamInstr *)code[index+2], catches); code[index+2] = make_catch(catches); index = next; } stp->catches = catches; + CHKBLK(ERTS_ALC_T_CODE,code); /* * Save the updated code pointer and code size. @@ -3605,6 +3685,7 @@ freeze_code(LoaderState* stp) stp->code = code; stp->loaded_size = size; + CHKBLK(ERTS_ALC_T_CODE,code); return 1; load_error: @@ -3638,7 +3719,7 @@ final_touch(LoaderState* stp) * callable yet. */ ep->address = ep->code+3; - ep->code[4] = (Eterm) stp->export[i].address; + ep->code[4] = (BeamInstr) stp->export[i].address; } } @@ -3650,14 +3731,14 @@ final_touch(LoaderState* stp) Eterm mod; Eterm func; Uint arity; - Uint import; + BeamInstr import; Uint current; Uint next; mod = stp->import[i].module; func = stp->import[i].function; arity = stp->import[i].arity; - import = (Uint) erts_export_put(mod, func, arity); + import = (BeamInstr) erts_export_put(mod, func, arity); current = stp->import[i].patches; while (current != 0) { ASSERT(current < stp->ci); @@ -3675,7 +3756,7 @@ final_touch(LoaderState* stp) for (i = 0; i < stp->num_lambdas; i++) { unsigned entry_label = stp->lambdas[i].label; ErlFunEntry* fe = stp->lambdas[i].fe; - Eterm* code_ptr = (Eterm *) (stp->code + stp->labels[entry_label].value); + BeamInstr* code_ptr = (BeamInstr *) (stp->code + stp->labels[entry_label].value); if (fe->address[0] != 0) { /* @@ -3807,7 +3888,7 @@ transform_engine(LoaderState* st) if (i >= st->num_imports || st->import[i].bf == NULL) goto restart; if (bif_number != -1 && - bif_export[bif_number]->code[4] != (Uint) st->import[i].bf) { + bif_export[bif_number]->code[4] != (BeamInstr) st->import[i].bf) { goto restart; } } @@ -4071,7 +4152,7 @@ load_printf(int line, LoaderState* context, char *fmt,...) static int -get_int_val(LoaderState* stp, Uint len_code, Uint* result) +get_int_val(LoaderState* stp, Uint len_code, BeamInstr* result) { Uint count; Uint val; @@ -4103,7 +4184,7 @@ get_int_val(LoaderState* stp, Uint len_code, Uint* result) static int -get_erlang_integer(LoaderState* stp, Uint len_code, Uint* result) +get_erlang_integer(LoaderState* stp, Uint len_code, BeamInstr* result) { Uint count; Sint val; @@ -4124,11 +4205,12 @@ get_erlang_integer(LoaderState* stp, Uint len_code, Uint* result) count = len_code + 2; } else { Uint tag; + UWord len_word; ASSERT(len_code == 7); - GetTagAndValue(stp, tag, len_code); + GetTagAndValue(stp, tag, len_word); VerifyTag(stp, TAG_u, tag); - count = len_code + 9; + count = len_word + 9; } /* @@ -4376,7 +4458,7 @@ functions_in_module(Process* p, /* Process whose heap to use. */ Eterm mod) /* Tagged atom for module. */ { Module* modp; - Eterm* code; + BeamInstr* code; int i; Uint num_functions; Eterm* hp; @@ -4394,9 +4476,9 @@ functions_in_module(Process* p, /* Process whose heap to use. */ num_functions = code[MI_NUM_FUNCTIONS]; hp = HAlloc(p, 5*num_functions); for (i = num_functions-1; i >= 0 ; i--) { - Eterm* func_info = (Eterm *) code[MI_FUNCTIONS+i]; - Eterm name = func_info[3]; - int arity = func_info[4]; + BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i]; + Eterm name = (Eterm) func_info[3]; + int arity = (int) func_info[4]; Eterm tuple; ASSERT(is_atom(name)); @@ -4419,7 +4501,7 @@ static Eterm native_addresses(Process* p, Eterm mod) { Module* modp; - Eterm* code; + BeamInstr* code; int i; Eterm* hp; Uint num_functions; @@ -4442,9 +4524,9 @@ native_addresses(Process* p, Eterm mod) hp = HAlloc(p, need); hp_end = hp + need; for (i = num_functions-1; i >= 0 ; i--) { - Eterm* func_info = (Eterm *) code[MI_FUNCTIONS+i]; - Eterm name = func_info[3]; - int arity = func_info[4]; + BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i]; + Eterm name = (Eterm) func_info[3]; + int arity = (int) func_info[4]; Eterm tuple; ASSERT(is_atom(name)); @@ -4486,7 +4568,7 @@ exported_from_module(Process* p, /* Process whose heap to use. */ Eterm tuple; if (ep->address == ep->code+3 && - ep->code[3] == (Eterm) em_call_error_handler) { + ep->code[3] == (BeamInstr) em_call_error_handler) { /* There is a call to the function, but it does not exist. */ continue; } @@ -4519,7 +4601,7 @@ attributes_for_module(Process* p, /* Process whose heap to use. */ { Module* modp; - Eterm* code; + BeamInstr* code; Eterm* hp; byte* ext; Eterm result = NIL; @@ -4559,7 +4641,7 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */ Eterm mod) /* Tagged atom for module. */ { Module* modp; - Eterm* code; + BeamInstr* code; Eterm* hp; byte* ext; Eterm result = NIL; @@ -4591,8 +4673,8 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */ /* * Returns a pointer to {module, function, arity}, or NULL if not found. */ -Eterm* -find_function_from_pc(Eterm* pc) +BeamInstr * +find_function_from_pc(BeamInstr* pc) { Range* low = modules; Range* high = low + num_loaded_modules; @@ -4604,9 +4686,9 @@ find_function_from_pc(Eterm* pc) } else if (pc > mid->end) { low = mid + 1; } else { - Eterm** low1 = (Eterm **) (mid->start + MI_FUNCTIONS); - Eterm** high1 = low1 + mid->start[MI_NUM_FUNCTIONS]; - Eterm** mid1; + BeamInstr** low1 = (BeamInstr **) (mid->start + MI_FUNCTIONS); + BeamInstr** high1 = low1 + mid->start[MI_NUM_FUNCTIONS]; + BeamInstr** mid1; while (low1 < high1) { mid1 = low1 + (high1-low1) / 2; @@ -4719,10 +4801,10 @@ code_module_md5_1(Process* p, Eterm Bin) #define WORDS_PER_FUNCTION 6 -static Eterm* -make_stub(Eterm* fp, Eterm mod, Eterm func, Uint arity, Uint native, Eterm OpCode) +static BeamInstr* +make_stub(BeamInstr* fp, Eterm mod, Eterm func, Uint arity, Uint native, BeamInstr OpCode) { - fp[0] = (Eterm) BeamOp(op_i_func_info_IaaI); + fp[0] = (BeamInstr) BeamOp(op_i_func_info_IaaI); fp[1] = native; fp[2] = mod; fp[3] = func; @@ -4741,14 +4823,14 @@ static byte* stub_copy_info(LoaderState* stp, int chunk, /* Chunk: ATTR_CHUNK or COMPILE_CHUNK */ byte* info, /* Where to store info. */ - Eterm* ptr_word, /* Where to store pointer into info. */ - Eterm* size_word) /* Where to store size of info. */ + BeamInstr* ptr_word, /* Where to store pointer into info. */ + BeamInstr* size_word) /* Where to store size of info. */ { Sint decoded_size; Uint size = stp->chunks[chunk].size; if (size != 0) { memcpy(info, stp->chunks[chunk].start, size); - *ptr_word = (Eterm) info; + *ptr_word = (BeamInstr) info; decoded_size = erts_decode_ext_size(info, size, 0); if (decoded_size < 0) { return 0; @@ -4791,7 +4873,7 @@ stub_read_export_table(LoaderState* stp) } static void -stub_final_touch(LoaderState* stp, Eterm* fp) +stub_final_touch(LoaderState* stp, BeamInstr* fp) { int i; int n = stp->num_exps; @@ -4978,12 +5060,12 @@ Eterm erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) { LoaderState state; - Eterm Funcs; - Eterm Patchlist; + BeamInstr Funcs; + BeamInstr Patchlist; Eterm* tp; - Eterm* code = NULL; - Eterm* ptrs; - Eterm* fp; + BeamInstr* code = NULL; + BeamInstr* ptrs; + BeamInstr* fp; byte* info; Uint ci; int n; @@ -5072,7 +5154,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) * Allocate memory for the stub module. */ - code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(Eterm); + code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(BeamInstr); code_size += state.chunks[ATTR_CHUNK].size; code_size += state.chunks[COMPILE_CHUNK].size; code = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size); @@ -5141,7 +5223,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) * Set the pointer and make the stub. Put a return instruction * as the body until we know what kind of trap we should put there. */ - ptrs[i] = (Eterm) fp; + ptrs[i] = (BeamInstr) fp; #ifdef HIPE op = (Eterm) BeamOpCode(op_hipe_trap_call); /* Might be changed later. */ #else @@ -5154,8 +5236,8 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) * Insert the last pointer and the int_code_end instruction. */ - ptrs[i] = (Eterm) fp; - *fp++ = (Eterm) BeamOp(op_int_code_end); + ptrs[i] = (BeamInstr) fp; + *fp++ = (BeamInstr) BeamOp(op_int_code_end); /* * Copy attributes and compilation information. @@ -5222,9 +5304,9 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) #undef WORDS_PER_FUNCTION -static int safe_mul(Uint a, Uint b, Uint* resp) +static int safe_mul(UWord a, UWord b, UWord* resp) { - Uint res = a * b; + Uint res = a * b; /* XXX:Pan - used in bit syntax, the multiplication has to be stored in Uint */ *resp = res; if (b == 0) { diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h index c17844a553..26e3054c4b 100644 --- a/erts/emulator/beam/beam_load.h +++ b/erts/emulator/beam/beam_load.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1999-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1999-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -44,13 +44,13 @@ extern void** beam_ops; #endif -extern Eterm beam_debug_apply[]; -extern Eterm* em_call_error_handler; -extern Eterm* em_apply_bif; -extern Eterm* em_call_traced_function; +extern BeamInstr beam_debug_apply[]; +extern BeamInstr* em_call_error_handler; +extern BeamInstr* em_apply_bif; +extern BeamInstr* em_call_traced_function; typedef struct { - Eterm* start; /* Pointer to start of module. */ - Eterm* end; /* Points one word beyond last function in module. */ + BeamInstr* start; /* Pointer to start of module. */ + BeamInstr* end; /* Points one word beyond last function in module. */ } Range; /* diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 1b670585a7..85bf584337 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -616,13 +616,15 @@ local_name_monitor(Process *p, Eterm target_name) rp = erts_whereis_process(p, p_locks, target_name, ERTS_PROC_LOCK_LINK, ERTS_P2P_FLG_ALLOW_OTHER_X); if (!rp) { - Eterm lhp[3]; + DeclareTmpHeap(lhp,3,p); Eterm item; + UseTmpHeap(3,p); erts_smp_proc_unlock(p, ERTS_PROC_LOCK_LINK); p_locks &= ~ERTS_PROC_LOCK_LINK; item = TUPLE2(lhp, target_name, erts_this_dist_entry->sysname); erts_queue_monitor_message(p, &p_locks, mon_ref, am_process, item, am_noproc); + UnUseTmpHeap(3,p); } else if (rp != p) { erts_add_monitor(&(p->monitors), MON_ORIGIN, mon_ref, rp->id, @@ -3466,9 +3468,16 @@ BIF_RETTYPE make_fun_3(BIF_ALIST_3) if (arity < 0) { goto error; } +#if HALFWORD_HEAP + hp = HAlloc(BIF_P, 3); + hp[0] = HEADER_EXPORT; + /* Yes, May be misaligned, but X86_64 will fix it... */ + *((Export **) (hp+1)) = erts_export_get_or_make_stub(BIF_ARG_1, BIF_ARG_2, (Uint) arity); +#else hp = HAlloc(BIF_P, 2); hp[0] = HEADER_EXPORT; hp[1] = (Eterm) erts_export_get_or_make_stub(BIF_ARG_1, BIF_ARG_2, (Uint) arity); +#endif BIF_RET(make_export(hp)); } @@ -3884,7 +3893,7 @@ BIF_RETTYPE hash_2(BIF_ALIST_2) if ((range = signed_val(BIF_ARG_2)) <= 0) { /* [1..MAX_SMALL] */ BIF_ERROR(BIF_P, BADARG); } -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP if (range > ((1L << 27) - 1)) BIF_ERROR(BIF_P, BADARG); #endif @@ -3956,7 +3965,7 @@ BIF_RETTYPE phash2_2(BIF_ALIST_2) /* * Return either a small or a big. Use the heap for bigs if there is room. */ -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP BIF_RET(make_small(final_hash)); #else if (IS_USMALL(0, final_hash)) { @@ -4118,8 +4127,8 @@ void erts_init_bif(void) #else bif_return_trap_export.code[2] = 1; #endif - bif_return_trap_export.code[3] = (Eterm) em_apply_bif; - bif_return_trap_export.code[4] = (Eterm) &bif_return_trap; + bif_return_trap_export.code[3] = (BeamInstr) em_apply_bif; + bif_return_trap_export.code[4] = (BeamInstr) &bif_return_trap; flush_monitor_message_trap = erts_export_put(am_erlang, am_flush_monitor_message, diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h index 05e9b78c28..50f5f4fbd6 100644 --- a/erts/emulator/beam/bif.h +++ b/erts/emulator/beam/bif.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -125,7 +125,7 @@ do { \ #define ERTS_BIF_PREP_TRAP0(Ret, Trap, Proc) \ do { \ (Proc)->arity = 0; \ - (Proc)->def_arg_reg[3] = (Eterm) (Trap->address); \ + *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \ (Proc)->freason = TRAP; \ (Ret) = THE_NON_VALUE; \ } while (0) @@ -134,7 +134,8 @@ do { \ do { \ (Proc)->arity = 1; \ (Proc)->def_arg_reg[0] = (Eterm) (A0); \ - (Proc)->def_arg_reg[3] = (Eterm) ((Trap)->address); \ + *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \ + (Proc)->def_arg_reg[3] = (UWord) ((Trap)->address); \ (Proc)->freason = TRAP; \ (Ret) = THE_NON_VALUE; \ } while (0) @@ -144,7 +145,8 @@ do { \ (Proc)->arity = 2; \ (Proc)->def_arg_reg[0] = (Eterm) (A0); \ (Proc)->def_arg_reg[1] = (Eterm) (A1); \ - (Proc)->def_arg_reg[3] = (Eterm) ((Trap)->address); \ + *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \ + (Proc)->def_arg_reg[3] = (UWord) ((Trap)->address); \ (Proc)->freason = TRAP; \ (Ret) = THE_NON_VALUE; \ } while (0) @@ -155,14 +157,15 @@ do { \ (Proc)->def_arg_reg[0] = (Eterm) (A0); \ (Proc)->def_arg_reg[1] = (Eterm) (A1); \ (Proc)->def_arg_reg[2] = (Eterm) (A2); \ - (Proc)->def_arg_reg[3] = (Eterm) ((Trap)->address); \ + *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \ + (Proc)->def_arg_reg[3] = (UWord) ((Trap)->address); \ (Proc)->freason = TRAP; \ (Ret) = THE_NON_VALUE; \ } while (0) #define BIF_TRAP0(p, Trap_) do { \ (p)->arity = 0; \ - (p)->def_arg_reg[3] = (Eterm) ((Trap_)->address); \ + *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \ (p)->freason = TRAP; \ return THE_NON_VALUE; \ } while(0) @@ -170,7 +173,7 @@ do { \ #define BIF_TRAP1(Trap_, p, A0) do { \ (p)->arity = 1; \ (p)->def_arg_reg[0] = (A0); \ - (p)->def_arg_reg[3] = (Eterm) ((Trap_)->address); \ + *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \ (p)->freason = TRAP; \ return THE_NON_VALUE; \ } while(0) @@ -179,7 +182,7 @@ do { \ (p)->arity = 2; \ (p)->def_arg_reg[0] = (A0); \ (p)->def_arg_reg[1] = (A1); \ - (p)->def_arg_reg[3] = (Eterm) ((Trap_)->address); \ + *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \ (p)->freason = TRAP; \ return THE_NON_VALUE; \ } while(0) @@ -189,14 +192,14 @@ do { \ (p)->def_arg_reg[0] = (A0); \ (p)->def_arg_reg[1] = (A1); \ (p)->def_arg_reg[2] = (A2); \ - (p)->def_arg_reg[3] = (Eterm) ((Trap_)->address); \ + *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \ (p)->freason = TRAP; \ return THE_NON_VALUE; \ } while(0) #define BIF_TRAP_CODE_PTR_0(p, Code_) do { \ (p)->arity = 0; \ - (p)->def_arg_reg[3] = (Eterm) (Code_); \ + *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) (Code_); \ (p)->freason = TRAP; \ return THE_NON_VALUE; \ } while(0) diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index 03c88da8c6..90d3a0304a 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -1459,7 +1459,31 @@ Eterm uint_to_big(Uint x, Eterm *y) BIG_DIGIT(y, 0) = x; return make_big(y); } +/* +** convert UWord to bigint +** (must only be used if x is to big to be stored as a small) +** Allocation is tricky, the heap need has to be calculated +** with the macro BIG_UWORD_HEAP_SIZE(x) +*/ +Eterm uword_to_big(UWord x, Eterm *y) +{ +#if HALFWORD_HEAP + Uint upper = x >> 32; + Uint lower = x & 0xFFFFFFFFUL; + if (upper == 0) { + *y = make_pos_bignum_header(1); + } else { + *y = make_pos_bignum_header(2); + BIG_DIGIT(y, 1) = upper; + } + BIG_DIGIT(y, 0) = lower; +#else + *y = make_pos_bignum_header(1); + BIG_DIGIT(y, 0) = x; +#endif + return make_big(y); +} /* ** convert signed int to bigint @@ -1480,7 +1504,7 @@ Eterm small_to_big(Sint x, Eterm *y) Eterm erts_uint64_to_big(Uint64 x, Eterm **hpp) { Eterm *hp = *hpp; -#ifdef ARCH_32 +#if defined(ARCH_32) || HALFWORD_HEAP if (x >= (((Uint64) 1) << 32)) { *hp = make_pos_bignum_header(2); BIG_DIGIT(hp, 0) = (Uint) (x & ((Uint) 0xffffffff)); @@ -1507,7 +1531,7 @@ Eterm erts_sint64_to_big(Sint64 x, Eterm **hpp) neg = 1; x = -x; } -#ifdef ARCH_32 +#if defined(ARCH_32) || HALFWORD_HEAP if (x >= (((Uint64) 1) << 32)) { if (neg) *hp = make_neg_bignum_header(2); @@ -1854,6 +1878,42 @@ term_to_Uint(Eterm term, Uint *up) } } +int +term_to_UWord(Eterm term, UWord *up) +{ + if (is_small(term)) { + Sint i = signed_val(term); + if (i < 0) { + *up = BADARG; + return 0; + } + *up = (UWord) i; + return 1; + } else if (is_big(term)) { + ErtsDigit* xr = big_v(term); + dsize_t xl = big_size(term); + UWord uval = 0; + int n = 0; + + if (big_sign(term)) { + *up = BADARG; + return 0; + } else if (xl*D_EXP > sizeof(UWord)*8) { + *up = SYSTEM_LIMIT; + return 0; + } + while (xl-- > 0) { + uval |= ((Uint)(*xr++)) << n; + n += D_EXP; + } + *up = uval; + return 1; + } else { + *up = BADARG; + return 0; + } +} + int term_to_Sint(Eterm term, Sint *sp) { if (is_small(term)) { diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h index b8e38d482c..56f3be372a 100644 --- a/erts/emulator/beam/big.h +++ b/erts/emulator/beam/big.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -34,7 +34,7 @@ typedef Uint ErtsDigit; -#if (SIZEOF_VOID_P == 4) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) +#if ((SIZEOF_VOID_P == 4) || HALFWORD_HEAP) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) /* Assume 32-bit machine with long long support */ typedef Uint64 ErtsDoubleDigit; typedef Uint16 ErtsHalfDigit; @@ -58,7 +58,7 @@ typedef Uint32 ErtsHalfDigit; typedef Uint dsize_t; /* Vector size type */ -#define D_EXP (SIZEOF_VOID_P*8) +#define D_EXP (ERTS_SIZEOF_ETERM*8) #define D_MASK ((ErtsDigit)(-1)) /* D_BASE-1 */ /* macros for bignum objects */ @@ -88,7 +88,13 @@ typedef Uint dsize_t; /* Vector size type */ #define BIG_UINT_HEAP_SIZE (1 + 1) /* always, since sizeof(Uint) <= sizeof(Eterm) */ -#ifdef ARCH_32 +#if HALFWORD_HEAP +#define BIG_UWORD_HEAP_SIZE(UW) (((UW) >> (sizeof(Uint) * 8)) ? 3 : 2) +#else +#define BIG_UWORD_HEAP_SIZE(UW) BIG_UINT_HEAP_SIZE +#endif + +#if defined(ARCH_32) || HALFWORD_HEAP #define ERTS_UINT64_BIG_HEAP_SIZE__(X) \ ((X) >= (((Uint64) 1) << 32) ? (1 + 2) : (1 + 1)) @@ -136,6 +142,7 @@ int big_ucomp (Eterm, Eterm); int big_to_double(Eterm x, double* resp); Eterm small_to_big(Sint, Eterm*); Eterm uint_to_big(Uint, Eterm*); +Eterm uword_to_big(UWord, Eterm*); Eterm erts_make_integer(Uint, Process *); dsize_t big_bytes(Eterm); @@ -143,6 +150,7 @@ Eterm bytes_to_big(byte*, dsize_t, int, Eterm*); byte* big_to_bytes(Eterm, byte*); int term_to_Uint(Eterm, Uint*); +int term_to_UWord(Eterm, UWord*); int term_to_Sint(Eterm, Sint*); Uint32 big_to_uint32(Eterm b); diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c index 08c64610a2..59c20398d5 100644 --- a/erts/emulator/beam/binary.c +++ b/erts/emulator/beam/binary.c @@ -42,7 +42,7 @@ void erts_init_binary(void) { /* Verify Binary alignment... */ - if ((((Uint) &((Binary *) 0)->orig_bytes[0]) % ((Uint) 8)) != 0) { + if ((((UWord) &((Binary *) 0)->orig_bytes[0]) % ((UWord) 8)) != 0) { /* I assume that any compiler should be able to optimize this away. If not, this test is not very expensive... */ erl_exit(ERTS_ABORT_EXIT, diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c index cc69977b79..d93c031db2 100644 --- a/erts/emulator/beam/break.c +++ b/erts/emulator/beam/break.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ /* This File contains functions which are called if a user hits ^C */ @@ -381,7 +381,7 @@ loaded(int to, void *to_arg) int i; int old = 0; int cur = 0; - Eterm* code; + BeamInstr* code; /* * Calculate and print totals. diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index e3094404e2..d465017949 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -228,6 +228,7 @@ int is_node_name_atom(Eterm a) typedef struct { DistEntry *dep; + Eterm *lhp; } NetExitsContext; /* @@ -253,8 +254,9 @@ static void doit_monitor_net_exits(ErtsMonitor *mon, void *vnecp) erts_destroy_monitor(rmon); } } else { - Eterm lhp[3]; + DeclareTmpHeapNoproc(lhp,3); Eterm watched; + UseTmpHeapNoproc(3); ASSERT(mon->type == MON_TARGET); rmon = erts_remove_monitor(&(rp->monitors),mon->ref); /* ASSERT(rmon != NULL); can happen during process exit */ @@ -271,6 +273,7 @@ static void doit_monitor_net_exits(ErtsMonitor *mon, void *vnecp) watched, am_noconnection); erts_destroy_monitor(rmon); } + UnUseTmpHeapNoproc(3); } erts_smp_proc_unlock(rp, rp_locks); done: @@ -632,19 +635,27 @@ static void clear_dist_entry(DistEntry *dep) int erts_dsig_send_link(ErtsDSigData *dsdp, Eterm local, Eterm remote) { - Eterm ctl_heap[4]; + DeclareTmpHeapNoproc(ctl_heap,4); Eterm ctl = TUPLE3(&ctl_heap[0], make_small(DOP_LINK), local, remote); + int res; + UseTmpHeapNoproc(4); - return dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + res = dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + UnUseTmpHeapNoproc(4); + return res; } int erts_dsig_send_unlink(ErtsDSigData *dsdp, Eterm local, Eterm remote) { - Eterm ctl_heap[4]; + DeclareTmpHeapNoproc(ctl_heap,4); Eterm ctl = TUPLE3(&ctl_heap[0], make_small(DOP_UNLINK), local, remote); + int res; - return dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + UseTmpHeapNoproc(4); + res = dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + UnUseTmpHeapNoproc(4); + return res; } @@ -656,7 +667,10 @@ erts_dsig_send_m_exit(ErtsDSigData *dsdp, Eterm watcher, Eterm watched, Eterm ref, Eterm reason) { Eterm ctl; - Eterm ctl_heap[6]; + DeclareTmpHeapNoproc(ctl_heap,6); + int res; + + UseTmpHeapNoproc(6); ctl = TUPLE5(&ctl_heap[0], make_small(DOP_MONITOR_P_EXIT), watched, watcher, ref, reason); @@ -667,7 +681,9 @@ erts_dsig_send_m_exit(ErtsDSigData *dsdp, Eterm watcher, Eterm watched, erts_smp_de_links_unlock(dsdp->dep); #endif - return dsig_send(dsdp, ctl, THE_NON_VALUE, 1); + res = dsig_send(dsdp, ctl, THE_NON_VALUE, 1); + UnUseTmpHeapNoproc(6); + return res; } /* We want to monitor a process (named or unnamed) on another node, we send: @@ -678,13 +694,17 @@ erts_dsig_send_monitor(ErtsDSigData *dsdp, Eterm watcher, Eterm watched, Eterm ref) { Eterm ctl; - Eterm ctl_heap[5]; + DeclareTmpHeapNoproc(ctl_heap,5); + int res; + UseTmpHeapNoproc(5); ctl = TUPLE4(&ctl_heap[0], make_small(DOP_MONITOR_P), watcher, watched, ref); - return dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + res = dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + UnUseTmpHeapNoproc(5); + return res; } /* A local process monitoring a remote one wants to stop monitoring, either @@ -696,23 +716,29 @@ erts_dsig_send_demonitor(ErtsDSigData *dsdp, Eterm watcher, Eterm watched, Eterm ref, int force) { Eterm ctl; - Eterm ctl_heap[5]; + DeclareTmpHeapNoproc(ctl_heap,5); + int res; + UseTmpHeapNoproc(5); ctl = TUPLE4(&ctl_heap[0], make_small(DOP_DEMONITOR_P), watcher, watched, ref); - return dsig_send(dsdp, ctl, THE_NON_VALUE, force); + res = dsig_send(dsdp, ctl, THE_NON_VALUE, force); + UnUseTmpHeapNoproc(5); + return res; } int erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message) { Eterm ctl; - Eterm ctl_heap[5]; + DeclareTmpHeapNoproc(ctl_heap,5); Eterm token = NIL; Process *sender = dsdp->proc; + int res; + UseTmpHeapNoproc(5); if (SEQ_TRACE_TOKEN(sender) != NIL) { seq_trace_update_send(sender); token = SEQ_TRACE_TOKEN(sender); @@ -724,17 +750,21 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message) make_small(DOP_SEND_TT), am_Cookie, remote, token); else ctl = TUPLE3(&ctl_heap[0], make_small(DOP_SEND), am_Cookie, remote); - return dsig_send(dsdp, ctl, message, 0); + res = dsig_send(dsdp, ctl, message, 0); + UnUseTmpHeapNoproc(5); + return res; } int erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) { Eterm ctl; - Eterm ctl_heap[6]; + DeclareTmpHeapNoproc(ctl_heap,6); Eterm token = NIL; Process *sender = dsdp->proc; + int res; + UseTmpHeapNoproc(6); if (SEQ_TRACE_TOKEN(sender) != NIL) { seq_trace_update_send(sender); token = SEQ_TRACE_TOKEN(sender); @@ -747,7 +777,9 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) else ctl = TUPLE4(&ctl_heap[0], make_small(DOP_REG_SEND), sender->id, am_Cookie, remote_name); - return dsig_send(dsdp, ctl, message, 0); + res = dsig_send(dsdp, ctl, message, 0); + UnUseTmpHeapNoproc(6); + return res; } /* local has died, deliver the exit signal to remote */ @@ -756,8 +788,10 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, Eterm reason, Eterm token) { Eterm ctl; - Eterm ctl_heap[6]; + DeclareTmpHeapNoproc(ctl_heap,6); + int res; + UseTmpHeapNoproc(6); if (token != NIL) { seq_trace_update_send(dsdp->proc); seq_trace_output_exit(token, reason, SEQ_TRACE_SEND, remote, local); @@ -767,38 +801,58 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, ctl = TUPLE4(&ctl_heap[0], make_small(DOP_EXIT), local, remote, reason); } /* forced, i.e ignore busy */ - return dsig_send(dsdp, ctl, THE_NON_VALUE, 1); + res = dsig_send(dsdp, ctl, THE_NON_VALUE, 1); + UnUseTmpHeapNoproc(6); + return res; } int erts_dsig_send_exit(ErtsDSigData *dsdp, Eterm local, Eterm remote, Eterm reason) { - Eterm ctl_heap[5]; - Eterm ctl = TUPLE4(&ctl_heap[0], - make_small(DOP_EXIT), local, remote, reason); + DeclareTmpHeapNoproc(ctl_heap,5); + int res; + Eterm ctl; + + UseTmpHeapNoproc(5); + ctl = TUPLE4(&ctl_heap[0], + make_small(DOP_EXIT), local, remote, reason); /* forced, i.e ignore busy */ - return dsig_send(dsdp, ctl, THE_NON_VALUE, 1); + res = dsig_send(dsdp, ctl, THE_NON_VALUE, 1); + UnUseTmpHeapNoproc(5); + return res; } int erts_dsig_send_exit2(ErtsDSigData *dsdp, Eterm local, Eterm remote, Eterm reason) { - Eterm ctl_heap[5]; - Eterm ctl = TUPLE4(&ctl_heap[0], - make_small(DOP_EXIT2), local, remote, reason); + DeclareTmpHeapNoproc(ctl_heap,5); + int res; + Eterm ctl; + + UseTmpHeapNoproc(5); + ctl = TUPLE4(&ctl_heap[0], + make_small(DOP_EXIT2), local, remote, reason); - return dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + res = dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + UnUseTmpHeapNoproc(5); + return res; } int erts_dsig_send_group_leader(ErtsDSigData *dsdp, Eterm leader, Eterm remote) { - Eterm ctl_heap[4]; - Eterm ctl = TUPLE3(&ctl_heap[0], - make_small(DOP_GROUP_LEADER), leader, remote); + DeclareTmpHeapNoproc(ctl_heap,4); + int res; + Eterm ctl; - return dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + UseTmpHeapNoproc(4); + ctl = TUPLE3(&ctl_heap[0], + make_small(DOP_GROUP_LEADER), leader, remote); + + res = dsig_send(dsdp, ctl, THE_NON_VALUE, 0); + UnUseTmpHeapNoproc(4); + return res; } #if defined(PURIFY) @@ -832,6 +886,7 @@ erts_dsig_send_group_leader(ErtsDSigData *dsdp, Eterm leader, Eterm remote) ** ** assert hlen == 0 !!! */ + int erts_net_message(Port *prt, DistEntry *dep, byte *hbuf, @@ -839,6 +894,7 @@ int erts_net_message(Port *prt, byte *buf, int len) { +#define DIST_CTL_DEFAULT_SIZE 64 ErtsDistExternal ede; byte *t; Sint ctl_len; @@ -850,7 +906,7 @@ int erts_net_message(Port *prt, Eterm *tuple; Eterm reason; Process* rp; - Eterm ctl_default[64]; + DeclareTmpHeapNoproc(ctl_default,DIST_CTL_DEFAULT_SIZE); Eterm* ctl = ctl_default; ErlOffHeap off_heap; Eterm* hp; @@ -864,6 +920,7 @@ int erts_net_message(Port *prt, int orig_len = len; #endif + UseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE); /* Thanks to Luke Gorrie */ off_heap.mso = NULL; #ifndef HYBRID /* FIND ME! */ @@ -876,12 +933,16 @@ int erts_net_message(Port *prt, ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)); - if (!erts_is_alive) + if (!erts_is_alive) { + UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE); return 0; + } if (hlen > 0) goto data_error; - if (len == 0) /* HANDLE TICK !!! */ + if (len == 0) { /* HANDLE TICK !!! */ + UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE); return 0; + } #ifdef ERTS_RAW_DIST_MSG_DBG erts_fprintf(stderr, "<< "); @@ -922,7 +983,8 @@ int erts_net_message(Port *prt, goto data_error; } orig_ctl_len = ctl_len; - if (ctl_len > sizeof(ctl_default)/sizeof(ctl_default[0])) { + + if (ctl_len > DIST_CTL_DEFAULT_SIZE) { ctl = erts_alloc(ERTS_ALC_T_DCTRL_BUF, ctl_len * sizeof(Eterm)); } hp = ctl; @@ -1202,7 +1264,7 @@ int erts_net_message(Port *prt, {DOP_MONITOR_P_EXIT, Remote pid or name, Local pid, ref, reason} */ - Eterm lhp[3]; + DeclareTmpHeapNoproc(lhp,3); Eterm sysname; ErtsProcLocks rp_locks = ERTS_PROC_LOCKS_MSG_SEND|ERTS_PROC_LOCK_LINK; @@ -1237,6 +1299,7 @@ int erts_net_message(Port *prt, erts_smp_proc_unlock(rp, rp_locks); break; } + UseTmpHeapNoproc(3); watched = (is_not_nil(mon->name) ? TUPLE2(&lhp[0], mon->name, sysname) @@ -1246,6 +1309,7 @@ int erts_net_message(Port *prt, ref, am_process, watched, reason); erts_smp_proc_unlock(rp, rp_locks); erts_destroy_monitor(mon); + UnUseTmpHeapNoproc(3); break; } @@ -1384,6 +1448,7 @@ int erts_net_message(Port *prt, erts_free(ERTS_ALC_T_DCTRL_BUF, (void *) ctl); } #endif + UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE); ERTS_SMP_CHK_NO_PROC_LOCKS; return 0; @@ -1402,6 +1467,7 @@ int erts_net_message(Port *prt, erts_free(ERTS_ALC_T_DCTRL_BUF, (void *) ctl); } #endif + UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE); erts_do_exit_port(prt, dep->cid, am_killed); ERTS_SMP_CHK_NO_PROC_LOCKS; return -1; @@ -1554,9 +1620,9 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy) */ data_size >>= (10-4); -#if defined(ARCH_64) +#if defined(ARCH_64) && !HALFWORD_HEAP data_size &= 0x003fffffffffffff; -#elif defined(ARCH_32) +#elif defined(ARCH_32) || HALFWORD_HEAP data_size &= 0x003fffff; #else # error "Ohh come on ... !?!" @@ -1640,9 +1706,9 @@ dist_port_commandv(Port *prt, ErtsDistOutputBuf *obuf) } -#if defined(ARCH_64) +#if defined(ARCH_64) && !HALFWORD_HEAP #define ERTS_PORT_REDS_MASK__ 0x003fffffffffffffL -#elif defined(ARCH_32) +#elif defined(ARCH_32) || HALFWORD_HEAP #define ERTS_PORT_REDS_MASK__ 0x003fffff #else # error "Ohh come on ... !?!" @@ -2547,12 +2613,15 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1) int visible = 0; int hidden = 0; int this = 0; - Uint buf[2]; /* For one cons-cell */ + DeclareTmpHeap(buf,2,BIF_P); /* For one cons-cell */ DistEntry *dep; Eterm arg_list = BIF_ARG_1; #ifdef DEBUG Eterm* endp; #endif + + UseTmpHeap(2,BIF_P); + if (is_atom(BIF_ARG_1)) arg_list = CONS(buf, BIF_ARG_1, NIL); @@ -2563,13 +2632,14 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1) case am_known: visible = hidden = not_connected = this = 1; break; case am_this: this = 1; break; case am_connected: visible = hidden = 1; break; - default: BIF_ERROR(BIF_P, BADARG); break; + default: goto error; break; } arg_list = CDR(list_val(arg_list)); } - if (is_not_nil(arg_list)) - BIF_ERROR(BIF_P, BADARG); + if (is_not_nil(arg_list)) { + goto error; + } length = 0; @@ -2591,7 +2661,7 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1) if (length == 0) { erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx); - BIF_RET(result); + goto done; } hp = HAlloc(BIF_P, 2*length); @@ -2620,7 +2690,14 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1) } ASSERT(endp == hp); erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx); + +done: + UnUseTmpHeap(2,BIF_P); BIF_RET(result); + +error: + UnUseTmpHeap(2,BIF_P); + BIF_ERROR(BIF_P,BADARG); } /**********************************************************************/ diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h index ea1abcaeed..fa19c7fb45 100644 --- a/erts/emulator/beam/dist.h +++ b/erts/emulator/beam/dist.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -287,4 +287,5 @@ extern void erts_kill_dist_connection(DistEntry *dep, Uint32); extern Uint erts_dist_cache_size(void); + #endif diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index b853ec0f01..f8823b85fe 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2002-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -220,7 +220,7 @@ set_default_ll_alloc_opts(struct au_init *ip) ip->init.util.ramv = 0; ip->init.util.mmsbc = 0; ip->init.util.mmmbc = 0; - ip->init.util.sbct = ~((Uint) 0); + ip->init.util.sbct = ~((UWord) 0); ip->init.util.name_prefix = "ll_"; ip->init.util.alloc_no = ERTS_ALC_A_LONG_LIVED; #ifndef SMALL_MEMORY @@ -394,7 +394,7 @@ static void init_thr_ix(int static_ixs); void erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) { - Uint extra_block_size = 0; + UWord extra_block_size = 0; int i; erts_alc_hndl_args_init_t init = { 0, @@ -542,7 +542,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold); sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad); - if (erts_allctrs_info[ERTS_FIX_CORE_ALLOCATOR].enabled) erts_fix_core_allocator_ix = ERTS_FIX_CORE_ALLOCATOR; else @@ -719,8 +718,8 @@ start_au_allocator(ErtsAlcType_t alctr_n, init->init.util.name_prefix); tspec->allctr = (Allctr_t **) states; states = ((char *) states) + sizeof(Allctr_t *) * (tspec->size + 1); - states = ((((Uint) states) & ERTS_CACHE_LINE_MASK) - ? (void *) ((((Uint) states) & ~ERTS_CACHE_LINE_MASK) + states = ((((UWord) states) & ERTS_CACHE_LINE_MASK) + ? (void *) ((((UWord) states) & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE) : (void *) states); tspec->allctr[0] = init->thr_spec > 0 ? (Allctr_t *) state : (Allctr_t *) NULL; @@ -1605,12 +1604,13 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg) } else { - Eterm tmp_heap[2]; + DeclareTmpHeapNoproc(tmp_heap,2); Eterm wanted_list; if (is_nil(earg)) return NIL; + UseTmpHeapNoproc(2); if (is_not_atom(earg)) wanted_list = earg; else { @@ -1690,15 +1690,18 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg) atoms[length] = am_maximum; uintps[length++] = &size.maximum; } - } - else + } else { + UnUseTmpHeapNoproc(2); return am_badarg; + } break; default: + UnUseTmpHeapNoproc(2); return am_badarg; } wanted_list = CDR(list_val(wanted_list)); } + UnUseTmpHeapNoproc(2); if (is_not_nil(wanted_list)) return am_badarg; } @@ -2285,8 +2288,8 @@ erts_allocator_info_term(void *proc, Eterm which_alloc, int only_sz) SysAllocStat sas; Eterm opts_am; Eterm opts; - Eterm as[4]; - Eterm ts[4]; + Eterm as[4]; /* Ok even if !HEAP_ON_C_STACK, not really heap data on stack */ + Eterm ts[4]; /* Ok even if !HEAP_ON_C_STACK, not really heap data on stack */ int l; if (only_sz) @@ -2944,9 +2947,9 @@ unsigned long erts_alc_test(unsigned long op, #endif -#define FENCE_SZ (3*sizeof(Uint)) +#define FENCE_SZ (3*sizeof(UWord)) -#ifdef ARCH_64 +#if defined(ARCH_64) #define FENCE_PATTERN 0xABCDEF97ABCDEF97 #else #define FENCE_PATTERN 0xABCDEF97 @@ -2956,7 +2959,7 @@ unsigned long erts_alc_test(unsigned long op, #define TYPE_PATTERN_SHIFT 16 #define FIXED_FENCE_PATTERN_MASK \ - (~((Uint) (TYPE_PATTERN_MASK << TYPE_PATTERN_SHIFT))) + (~((UWord) (TYPE_PATTERN_MASK << TYPE_PATTERN_SHIFT))) #define FIXED_FENCE_PATTERN \ (FENCE_PATTERN & FIXED_FENCE_PATTERN_MASK) @@ -2967,21 +2970,60 @@ unsigned long erts_alc_test(unsigned long op, (((P) >> TYPE_PATTERN_SHIFT) & TYPE_PATTERN_MASK) +#ifdef ERTS_ALLOC_UTIL_HARD_DEBUG +static void *check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func); + +void check_allocated_block( Uint type, void *blk) +{ + Uint dummy; + check_memory_fence(blk, &dummy, ERTS_ALC_T2N(type), ERTS_ALC_O_FREE); +} + +void check_allocators(void) +{ + int i; + if (!erts_initialized) + return; + for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; ++i) { + if (erts_allctrs_info[i].alloc_util) { + ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) erts_allctrs[i].extra; + Allctr_t *allctr = real_af->extra; + Carrier_t *ct; +#ifdef USE_THREADS + if (allctr->thread_safe) + erts_mtx_lock(&allctr->mutex); +#endif + + if (allctr->check_mbc) { + for (ct = allctr->mbc_list.first; ct; ct = ct->next) { + fprintf(stderr,"Checking allocator %d\r\n",i); + allctr->check_mbc(allctr,ct); + } + } +#ifdef USE_THREADS + if (allctr->thread_safe) + erts_mtx_unlock(&allctr->mutex); +#endif + } + } +} +#endif + static void * set_memory_fence(void *ptr, Uint sz, ErtsAlcType_t n) { - Uint *ui_ptr; - Uint pattern; + UWord *ui_ptr; + UWord pattern; if (!ptr) return NULL; - ui_ptr = (Uint *) ptr; + ui_ptr = (UWord *) ptr; pattern = MK_PATTERN(n); *(ui_ptr++) = sz; *(ui_ptr++) = pattern; - memcpy((void *) (((char *) ui_ptr)+sz), (void *) &pattern, sizeof(Uint)); + memcpy((void *) (((char *) ui_ptr)+sz), (void *) &pattern, sizeof(UWord)); return (void *) ui_ptr; } @@ -2991,14 +3033,14 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func) { Uint sz; Uint found_type; - Uint pre_pattern; - Uint post_pattern; - Uint *ui_ptr; + UWord pre_pattern; + UWord post_pattern; + UWord *ui_ptr; if (!ptr) return NULL; - ui_ptr = (Uint *) ptr; + ui_ptr = (UWord *) ptr; pre_pattern = *(--ui_ptr); *size = sz = *(--ui_ptr); @@ -3011,7 +3053,7 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func) (unsigned long) ptr); } - memcpy((void *) &post_pattern, (void *) (((char *)ptr)+sz), sizeof(Uint)); + memcpy((void *) &post_pattern, (void *) (((char *)ptr)+sz), sizeof(UWord)); if (post_pattern != MK_PATTERN(n) || pre_pattern != post_pattern) { diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h index e7a203002f..3e96c76dbf 100644 --- a/erts/emulator/beam/erl_alloc.h +++ b/erts/emulator/beam/erl_alloc.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2002-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -238,7 +238,7 @@ void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size) #ifndef ERTS_CACHE_LINE_SIZE /* Assume a cache line size of 64 bytes */ -# define ERTS_CACHE_LINE_SIZE ((Uint) 64) +# define ERTS_CACHE_LINE_SIZE ((UWord) 64) # define ERTS_CACHE_LINE_MASK (ERTS_CACHE_LINE_SIZE - 1) #endif @@ -486,9 +486,9 @@ init_##NAME##_alloc(void) \ qa_data_##NAME##__ = erts_alloc(ERTS_ALC_T_PRE_ALLOC_DATA,tot_size);\ chunk_start = (((char *) qa_data_##NAME##__) \ + sizeof(erts_sched_pref_quick_alloc_data_t)); \ - if ((((Uint) chunk_start) & ERTS_CACHE_LINE_MASK) != ((Uint) 0)) \ + if ((((UWord) chunk_start) & ERTS_CACHE_LINE_MASK) != ((UWord) 0)) \ chunk_start = ((char *) \ - ((((Uint) chunk_start) & ~ERTS_CACHE_LINE_MASK) \ + ((((UWord) chunk_start) & ~ERTS_CACHE_LINE_MASK) \ + ERTS_CACHE_LINE_SIZE)); \ qa_data_##NAME##__->chunks_mem_size = chunk_mem_size; \ qa_data_##NAME##__->start = (void *) chunk_start; \ @@ -553,7 +553,7 @@ NAME##_free(TYPE *p) \ } #ifdef DEBUG -#define ERTS_ALC_DBG_BLK_SZ(PTR) (*(((Uint *) (PTR)) - 2)) +#define ERTS_ALC_DBG_BLK_SZ(PTR) (*(((UWord *) (PTR)) - 2)) #endif /* #ifdef DEBUG */ #undef ERTS_ALC_INLINE diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types index f701f71c7d..5d2872a4e3 100644 --- a/erts/emulator/beam/erl_alloc.types +++ b/erts/emulator/beam/erl_alloc.types @@ -1,19 +1,19 @@ # # %CopyrightBegin% -# -# Copyright Ericsson AB 2003-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 2003-2010. All Rights Reserved. +# # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in # compliance with the License. You should have received a copy of the # Erlang Public License along with this software. If not, it can be # retrieved online at http://www.erlang.org/. -# +# # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. -# +# # %CopyrightEnd% # @@ -138,6 +138,7 @@ type PEND_SUSPEND SHORT_LIVED PROCESSES pending_suspend type PROC_LIST SHORT_LIVED PROCESSES proc_list type FUN_ENTRY FIXED_SIZE CODE fun_entry type ATOM_TXT LONG_LIVED ATOM atom_text +type BEAM_REGISTER EHEAP PROCESSES beam_register type HEAP EHEAP PROCESSES heap type OLD_HEAP EHEAP PROCESSES old_heap type HEAP_FRAG EHEAP PROCESSES heap_frag @@ -322,6 +323,9 @@ type SSB SHORT_LIVED PROCESSES ssb # Types used by system specific code # +type TEMP_TERM TEMPORARY SYSTEM temp_term +type LL_TEMP_TERM LONG_LIVED SYSTEM ll_temp_term + type DRV_TAB LONG_LIVED SYSTEM drv_tab type DRV_EV_STATE LONG_LIVED SYSTEM driver_event_state type DRV_EV_D_STATE FIXED_SIZE SYSTEM driver_event_data_state diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c index 9b7bc24c1c..8b184899c9 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2002-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -69,14 +69,14 @@ static int initialized = 0; #if HAVE_ERTS_MSEG -#define INV_MSEG_UNIT_MASK ((Uint) (mseg_unit_size - 1)) +#define INV_MSEG_UNIT_MASK ((UWord) (mseg_unit_size - 1)) #define MSEG_UNIT_MASK (~INV_MSEG_UNIT_MASK) #define MSEG_UNIT_FLOOR(X) ((X) & MSEG_UNIT_MASK) #define MSEG_UNIT_CEILING(X) MSEG_UNIT_FLOOR((X) + INV_MSEG_UNIT_MASK) #endif -#define INV_SYS_ALLOC_CARRIER_MASK ((Uint) (sys_alloc_carrier_size - 1)) +#define INV_SYS_ALLOC_CARRIER_MASK ((UWord) (sys_alloc_carrier_size - 1)) #define SYS_ALLOC_CARRIER_MASK (~INV_SYS_ALLOC_CARRIER_MASK) #define SYS_ALLOC_CARRIER_FLOOR(X) ((X) & SYS_ALLOC_CARRIER_MASK) #define SYS_ALLOC_CARRIER_CEILING(X) \ @@ -85,7 +85,7 @@ static int initialized = 0; #undef ASSERT #define ASSERT ASSERT_EXPR -#define ERTS_ALCU_FLG_FAIL_REALLOC_MOVE ((Uint) 1) +#define ERTS_ALCU_FLG_FAIL_REALLOC_MOVE ((UWord) 1) #if 0 /* Can be useful for debugging */ @@ -114,12 +114,12 @@ static Uint mseg_unit_size; /* Blocks ... */ -#define SBC_BLK_FTR_FLG (((Uint) 1) << 0) -#define UNUSED1_BLK_FTR_FLG (((Uint) 1) << 1) -#define UNUSED2_BLK_FTR_FLG (((Uint) 1) << 2) +#define SBC_BLK_FTR_FLG (((UWord) 1) << 0) +#define UNUSED1_BLK_FTR_FLG (((UWord) 1) << 1) +#define UNUSED2_BLK_FTR_FLG (((UWord) 1) << 2) #define ABLK_HDR_SZ (sizeof(Block_t)) -#define FBLK_FTR_SZ (sizeof(Uint)) +#define FBLK_FTR_SZ (sizeof(UWord)) #define UMEMSZ2BLKSZ(AP, SZ) \ (ABLK_HDR_SZ + (SZ) <= (AP)->min_block_size \ @@ -130,14 +130,14 @@ static Uint mseg_unit_size; #define BLK2UMEM(P) ((void *) (((char *) (P)) + ABLK_HDR_SZ)) #define PREV_BLK_SZ(B) \ - ((Uint) (*(((Uint *) (B)) - 1) & SZ_MASK)) + ((UWord) (*(((UWord *) (B)) - 1) & SZ_MASK)) #define SET_BLK_SZ_FTR(B, SZ) \ - (*((Uint *) (((char *) (B)) + (SZ) - sizeof(Uint))) = (SZ)) + (*((UWord *) (((char *) (B)) + (SZ) - sizeof(UWord))) = (SZ)) -#define THIS_FREE_BLK_HDR_FLG (((Uint) 1) << 0) -#define PREV_FREE_BLK_HDR_FLG (((Uint) 1) << 1) -#define LAST_BLK_HDR_FLG (((Uint) 1) << 2) +#define THIS_FREE_BLK_HDR_FLG (((UWord) 1) << 0) +#define PREV_FREE_BLK_HDR_FLG (((UWord) 1) << 1) +#define LAST_BLK_HDR_FLG (((UWord) 1) << 2) #define SET_BLK_SZ(B, SZ) \ (ASSERT(((SZ) & FLG_MASK) == 0), \ @@ -156,11 +156,11 @@ static Uint mseg_unit_size; (*((Block_t *) (B)) &= ~LAST_BLK_HDR_FLG) #define SBH_THIS_FREE THIS_FREE_BLK_HDR_FLG -#define SBH_THIS_ALLOCED ((Uint) 0) +#define SBH_THIS_ALLOCED ((UWord) 0) #define SBH_PREV_FREE PREV_FREE_BLK_HDR_FLG -#define SBH_PREV_ALLOCED ((Uint) 0) +#define SBH_PREV_ALLOCED ((UWord) 0) #define SBH_LAST_BLK LAST_BLK_HDR_FLG -#define SBH_NOT_LAST_BLK ((Uint) 0) +#define SBH_NOT_LAST_BLK ((UWord) 0) #define SET_BLK_HDR(B, Sz, F) \ (ASSERT(((Sz) & FLG_MASK) == 0), *((Block_t *) (B)) = ((Sz) | (F))) @@ -200,7 +200,7 @@ static Uint mseg_unit_size; ((FTR) = 0) #define IS_SBC_BLK(B) \ - (IS_PREV_BLK_FREE((B)) && (((Uint *) (B))[-1] & SBC_BLK_FTR_FLG)) + (IS_PREV_BLK_FREE((B)) && (((UWord *) (B))[-1] & SBC_BLK_FTR_FLG)) #define IS_MBC_BLK(B) \ (!IS_SBC_BLK((B))) @@ -211,8 +211,8 @@ static Uint mseg_unit_size; /* Carriers ... */ -#define MSEG_CARRIER_HDR_FLAG (((Uint) 1) << 0) -#define SBC_CARRIER_HDR_FLAG (((Uint) 1) << 1) +#define MSEG_CARRIER_HDR_FLAG (((UWord) 1) << 0) +#define SBC_CARRIER_HDR_FLAG (((UWord) 1) << 1) #define SCH_SYS_ALLOC 0 #define SCH_MSEG MSEG_CARRIER_HDR_FLAG @@ -407,18 +407,18 @@ do { \ /* Debug stuff... */ #ifdef DEBUG -static Uint carrier_alignment; +static UWord carrier_alignment; #define DEBUG_SAVE_ALIGNMENT(C) \ do { \ - Uint algnmnt__ = sizeof(Unit_t) - (((Uint) (C)) % sizeof(Unit_t)); \ + UWord algnmnt__ = sizeof(Unit_t) - (((UWord) (C)) % sizeof(Unit_t)); \ carrier_alignment = MIN(carrier_alignment, algnmnt__); \ - ASSERT(((Uint) (C)) % sizeof(Uint) == 0); \ + ASSERT(((UWord) (C)) % sizeof(UWord) == 0); \ } while (0) #define DEBUG_CHECK_ALIGNMENT(P) \ do { \ - ASSERT(sizeof(Unit_t) - (((Uint) (P)) % sizeof(Unit_t)) \ + ASSERT(sizeof(Unit_t) - (((UWord) (P)) % sizeof(Unit_t)) \ >= carrier_alignment); \ - ASSERT(((Uint) (P)) % sizeof(Uint) == 0); \ + ASSERT(((UWord) (P)) % sizeof(UWord) == 0); \ } while (0) #else @@ -610,7 +610,7 @@ unlink_carrier(CarrierList_t *cl, Carrier_t *crr) } -static Block_t *create_carrier(Allctr_t *, Uint, Uint); +static Block_t *create_carrier(Allctr_t *, Uint, UWord); static void destroy_carrier(Allctr_t *, Block_t *); /* Multi block carrier alloc/realloc/free ... */ @@ -630,6 +630,11 @@ mbc_alloc_block(Allctr_t *allctr, Uint size, Uint *blk_szp) blk = (*allctr->get_free_block)(allctr, *blk_szp, NULL, 0); +#if HALFWORD_HEAP + if (!blk) { + blk = create_carrier(allctr, *blk_szp, CFLG_MBC|CFLG_FORCE_MSEG); + } +#else if (!blk) { blk = create_carrier(allctr, *blk_szp, CFLG_MBC); if (!blk) { @@ -640,6 +645,7 @@ mbc_alloc_block(Allctr_t *allctr, Uint size, Uint *blk_szp) CFLG_SBC|CFLG_FORCE_SIZE|CFLG_FORCE_SYS_ALLOC); } } +#endif #ifdef ERTS_ALLOC_UTIL_HARD_DEBUG if (IS_MBC_BLK(blk)) { @@ -656,14 +662,14 @@ static ERTS_INLINE void mbc_alloc_finalize(Allctr_t *allctr, Block_t *blk, Uint org_blk_sz, - Uint flags, + UWord flags, Uint want_blk_sz, int valid_blk_info) { Uint blk_sz; Uint nxt_blk_sz; Block_t *nxt_blk; - Uint prev_free_flg = flags & PREV_FREE_BLK_HDR_FLG; + UWord prev_free_flg = flags & PREV_FREE_BLK_HDR_FLG; ASSERT(org_blk_sz >= want_blk_sz); ASSERT(blk); @@ -853,7 +859,7 @@ mbc_free(Allctr_t *allctr, void *p) } static void * -mbc_realloc(Allctr_t *allctr, void *p, Uint size, Uint flgs) +mbc_realloc(Allctr_t *allctr, void *p, Uint size, UWord flgs) { void *new_p; Uint old_blk_sz; @@ -1144,7 +1150,7 @@ mbc_realloc(Allctr_t *allctr, void *p, Uint size, Uint flgs) } else { Uint new_blk_sz; - Uint new_blk_flgs; + UWord new_blk_flgs; Uint prev_blk_sz; Uint blk_cpy_sz; @@ -1239,7 +1245,7 @@ do { \ static Block_t * -create_carrier(Allctr_t *allctr, Uint umem_sz, Uint flags) +create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags) { Block_t *blk; Carrier_t *crr; @@ -1283,8 +1289,8 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, Uint flags) if (crr_sz < allctr->mbc_header_size + blk_sz) crr_sz = allctr->mbc_header_size + blk_sz; #ifdef ERTS_ALLOC_UTIL_HARD_DEBUG - if (sizeof(Unit_t) == sizeof(Uint)) - crr_sz += sizeof(Uint); + if (sizeof(Unit_t) == sizeof(UWord)) + crr_sz += sizeof(UWord); #endif } crr_sz = MSEG_UNIT_CEILING(crr_sz); @@ -1324,8 +1330,8 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, Uint flags) && bcrr_sz < allctr->smallest_mbc_size) bcrr_sz = allctr->smallest_mbc_size; #ifdef ERTS_ALLOC_UTIL_HARD_DEBUG - if (sizeof(Unit_t) == sizeof(Uint)) - bcrr_sz += sizeof(Uint); + if (sizeof(Unit_t) == sizeof(UWord)) + bcrr_sz += sizeof(UWord); #endif } @@ -1360,7 +1366,7 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, Uint flags) blk = SBC2BLK(allctr, crr); - SET_SBC_BLK_FTR(((Uint *) blk)[-1]); + SET_SBC_BLK_FTR(((UWord *) blk)[-1]); SET_BLK_HDR(blk, blk_sz, SBH_THIS_ALLOCED|SBH_PREV_FREE|SBH_LAST_BLK); link_carrier(&allctr->sbc_list, crr); @@ -1379,13 +1385,13 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, Uint flags) blk = MBC2FBLK(allctr, crr); #ifdef ERTS_ALLOC_UTIL_HARD_DEBUG - if (sizeof(Unit_t) == sizeof(Uint)) - crr_sz -= sizeof(Uint); + if (sizeof(Unit_t) == sizeof(UWord)) + crr_sz -= sizeof(UWord); #endif blk_sz = UNIT_FLOOR(crr_sz - allctr->mbc_header_size); - SET_MBC_BLK_FTR(((Uint *) blk)[-1]); + SET_MBC_BLK_FTR(((UWord *) blk)[-1]); SET_BLK_HDR(blk, blk_sz, SBH_THIS_FREE|SBH_PREV_FREE|SBH_LAST_BLK); #ifdef ERTS_ALLOC_UTIL_HARD_DEBUG @@ -1400,13 +1406,13 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, Uint flags) link_carrier(&allctr->mbc_list, crr); #ifdef ERTS_ALLOC_UTIL_HARD_DEBUG - if (sizeof(Unit_t) == sizeof(Uint)) - crr_sz += sizeof(Uint); + if (sizeof(Unit_t) == sizeof(UWord)) + crr_sz += sizeof(UWord); #endif CHECK_1BLK_CARRIER(allctr, 0, is_mseg, crr, crr_sz, blk, blk_sz); #ifdef ERTS_ALLOC_UTIL_HARD_DEBUG - if (sizeof(Unit_t) == sizeof(Uint)) - crr_sz -= sizeof(Uint); + if (sizeof(Unit_t) == sizeof(UWord)) + crr_sz -= sizeof(UWord); #endif if (allctr->creating_mbc) (*allctr->creating_mbc)(allctr, crr); @@ -1418,11 +1424,12 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, Uint flags) } static Block_t * -resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, Uint flags) +resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags) { Block_t *new_blk; Carrier_t *new_crr, *old_crr; - Uint create_flags, old_crr_sz, old_blk_sz, new_blk_sz, new_crr_sz; + UWord create_flags; + Uint old_crr_sz, old_blk_sz, new_blk_sz, new_crr_sz; Uint new_bcrr_sz; if (flags & CFLG_MBC) { @@ -2522,7 +2529,12 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size) INC_CC(allctr->calls.this_alloc); if (size >= allctr->sbc_threshold) { +#if HALFWORD_HEAP + Block_t *blk = create_carrier(allctr, size, + CFLG_SBC | CFLG_FORCE_MSEG); +#else Block_t *blk = create_carrier(allctr, size, CFLG_SBC); +#endif res = blk ? BLK2UMEM(blk) : NULL; } else @@ -2594,16 +2606,16 @@ erts_alcu_alloc_thr_pref(ErtsAlcType_t type, void *extra, Uint size) Allctr_t *allctr; void *res; - ASSERT(sizeof(Uint) == sizeof(Allctr_t *)); + ASSERT(sizeof(UWord) == sizeof(Allctr_t *)); ASSERT(ix > 0); if (ix >= tspec->size) ix = (ix % (tspec->size - 1)) + 1; allctr = tspec->allctr[ix]; erts_mtx_lock(&allctr->mutex); - res = do_erts_alcu_alloc(type, allctr, size + sizeof(Uint)); + res = do_erts_alcu_alloc(type, allctr, size + sizeof(UWord)); if (res) { *((Allctr_t **) res) = allctr; - res = (void *) (((char *) res) + sizeof(Uint)); + res = (void *) (((char *) res) + sizeof(UWord)); } erts_mtx_unlock(&allctr->mutex); DEBUG_CHECK_ALIGNMENT(res); @@ -2681,7 +2693,7 @@ void erts_alcu_free_thr_pref(ErtsAlcType_t type, void *unused, void *p) { if (p) { - void *ptr = (void *) (((char *) p) - sizeof(Uint)); + void *ptr = (void *) (((char *) p) - sizeof(UWord)); Allctr_t *allctr = *((Allctr_t **) ptr); erts_mtx_lock(&allctr->mutex); do_erts_alcu_free(type, allctr, ptr); @@ -2698,7 +2710,7 @@ do_erts_alcu_realloc(ErtsAlcType_t type, void *extra, void *p, Uint size, - Uint flgs) + UWord flgs) { Allctr_t *allctr = (Allctr_t *) extra; Block_t *blk; @@ -2780,13 +2792,21 @@ do_erts_alcu_realloc(ErtsAlcType_t type, Block_t *new_blk; if(IS_SBC_BLK(blk)) { do_carrier_resize: +#if HALFWORD_HEAP + new_blk = resize_carrier(allctr, blk, size, CFLG_SBC | CFLG_FORCE_MSEG); +#else new_blk = resize_carrier(allctr, blk, size, CFLG_SBC); +#endif res = new_blk ? BLK2UMEM(new_blk) : NULL; } else if (flgs & ERTS_ALCU_FLG_FAIL_REALLOC_MOVE) return NULL; else { +#if HALFWORD_HEAP + new_blk = create_carrier(allctr, size, CFLG_SBC | CFLG_FORCE_MSEG); +#else new_blk = create_carrier(allctr, size, CFLG_SBC); +#endif if (new_blk) { res = BLK2UMEM(new_blk); sys_memcpy((void *) res, @@ -2962,7 +2982,7 @@ erts_alcu_realloc_thr_pref(ErtsAlcType_t type, void *extra, void *p, Uint size) if (!p) return erts_alcu_alloc_thr_pref(type, extra, size); - ptr = (void *) (((char *) p) - sizeof(Uint)); + ptr = (void *) (((char *) p) - sizeof(UWord)); used_allctr = *((Allctr_t **) ptr); ix = erts_alc_get_thr_ix(); @@ -2976,32 +2996,32 @@ erts_alcu_realloc_thr_pref(ErtsAlcType_t type, void *extra, void *p, Uint size) res = do_erts_alcu_realloc(type, used_allctr, ptr, - size + sizeof(Uint), + size + sizeof(UWord), (pref_allctr != used_allctr ? ERTS_ALCU_FLG_FAIL_REALLOC_MOVE : 0)); erts_mtx_unlock(&used_allctr->mutex); if (res) { ASSERT(used_allctr == *((Allctr_t **) res)); - res = (void *) (((char *) res) + sizeof(Uint)); + res = (void *) (((char *) res) + sizeof(UWord)); DEBUG_CHECK_ALIGNMENT(res); } else { erts_mtx_lock(&pref_allctr->mutex); - res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(Uint)); + res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(UWord)); erts_mtx_unlock(&pref_allctr->mutex); if (res) { Block_t *blk; size_t cpy_size; *((Allctr_t **) res) = pref_allctr; - res = (void *) (((char *) res) + sizeof(Uint)); + res = (void *) (((char *) res) + sizeof(UWord)); DEBUG_CHECK_ALIGNMENT(res); erts_mtx_lock(&used_allctr->mutex); blk = UMEM2BLK(ptr); - cpy_size = BLK_SZ(blk) - ABLK_HDR_SZ - sizeof(Uint); + cpy_size = BLK_SZ(blk) - ABLK_HDR_SZ - sizeof(UWord); if (cpy_size > size) cpy_size = size; sys_memcpy(res, p, cpy_size); @@ -3026,7 +3046,7 @@ erts_alcu_realloc_mv_thr_pref(ErtsAlcType_t type, void *extra, if (!p) return erts_alcu_alloc_thr_pref(type, extra, size); - ptr = (void *) (((char *) p) - sizeof(Uint)); + ptr = (void *) (((char *) p) - sizeof(UWord)); used_allctr = *((Allctr_t **) ptr); ix = erts_alc_get_thr_ix(); @@ -3037,7 +3057,7 @@ erts_alcu_realloc_mv_thr_pref(ErtsAlcType_t type, void *extra, ASSERT(used_allctr && pref_allctr); erts_mtx_lock(&pref_allctr->mutex); - res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(Uint)); + res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(UWord)); if (!res) { erts_mtx_unlock(&pref_allctr->mutex); res = erts_alcu_realloc_thr_pref(type, extra, p, size); @@ -3048,7 +3068,7 @@ erts_alcu_realloc_mv_thr_pref(ErtsAlcType_t type, void *extra, Allctr_t *allctr; *((Allctr_t **) res) = pref_allctr; - res = (void *) (((char *) res) + sizeof(Uint)); + res = (void *) (((char *) res) + sizeof(UWord)); DEBUG_CHECK_ALIGNMENT(res); @@ -3061,7 +3081,7 @@ erts_alcu_realloc_mv_thr_pref(ErtsAlcType_t type, void *extra, } blk = UMEM2BLK(ptr); - cpy_size = BLK_SZ(blk) - ABLK_HDR_SZ - sizeof(Uint); + cpy_size = BLK_SZ(blk) - ABLK_HDR_SZ - sizeof(UWord); if (cpy_size > size) cpy_size = size; sys_memcpy(res, p, cpy_size); @@ -3138,11 +3158,11 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init) if (allctr->min_block_size < ABLK_HDR_SZ) goto error; allctr->min_block_size = UNIT_CEILING(allctr->min_block_size - + sizeof(Uint)); + + sizeof(UWord)); #if HAVE_ERTS_MSEG - if (allctr->mseg_opt.abs_shrink_th > ~((Uint) 0) / 100) - allctr->mseg_opt.abs_shrink_th = ~((Uint) 0) / 100; + if (allctr->mseg_opt.abs_shrink_th > ~((UWord) 0) / 100) + allctr->mseg_opt.abs_shrink_th = ~((UWord) 0) / 100; #endif #ifdef USE_THREADS @@ -3182,15 +3202,15 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init) allctr->mbc_header_size = (UNIT_CEILING(allctr->mbc_header_size + FBLK_FTR_SZ + ABLK_HDR_SZ - + sizeof(Uint)) + + sizeof(UWord)) - ABLK_HDR_SZ - - sizeof(Uint)); + - sizeof(UWord)); allctr->sbc_header_size = (UNIT_CEILING(sizeof(Carrier_t) + FBLK_FTR_SZ + ABLK_HDR_SZ - + sizeof(Uint)) + + sizeof(UWord)) - ABLK_HDR_SZ - - sizeof(Uint)); + - sizeof(UWord)); } else #endif @@ -3208,12 +3228,21 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init) if (allctr->main_carrier_size) { Block_t *blk; +#if HALFWORD_HEAP + blk = create_carrier(allctr, + allctr->main_carrier_size, + CFLG_MBC + | CFLG_FORCE_SIZE + | CFLG_FORCE_MSEG + | CFLG_MAIN_CARRIER); +#else blk = create_carrier(allctr, allctr->main_carrier_size, CFLG_MBC | CFLG_FORCE_SIZE | CFLG_FORCE_SYS_ALLOC | CFLG_MAIN_CARRIER); +#endif if (!blk) goto error; @@ -3409,7 +3438,7 @@ check_blk_carrier(Allctr_t *allctr, Block_t *iblk) is_free_blk = (int) IS_FREE_BLK(blk); if(is_free_blk) { if (IS_NOT_LAST_BLK(blk)) - ASSERT(*((Uint *) (((char *) blk)+blk_sz-sizeof(Uint))) + ASSERT(*((UWord *) (((char *) blk)+blk_sz-sizeof(UWord))) == blk_sz); } @@ -3417,7 +3446,7 @@ check_blk_carrier(Allctr_t *allctr, Block_t *iblk) (*allctr->check_block)(allctr, blk, (int) is_free_blk); if (IS_LAST_BLK(blk)) { - carrier_end = ((char *) NXT_BLK(blk)) + sizeof(Uint); + carrier_end = ((char *) NXT_BLK(blk)) + sizeof(UWord); mbc = *((Carrier_t **) NXT_BLK(blk)); prev_blk = NULL; blk = MBC2FBLK(allctr, mbc); @@ -3433,7 +3462,7 @@ check_blk_carrier(Allctr_t *allctr, Block_t *iblk) ASSERT((((char *) mbc) + allctr->mbc_header_size + tot_blk_sz - + sizeof(Uint)) == carrier_end); + + sizeof(UWord)) == carrier_end); ASSERT(((char *) mbc) + CARRIER_SZ(mbc) == carrier_end); if (allctr->check_mbc) diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h index 10b11661e6..f2b951bca6 100644 --- a/erts/emulator/beam/erl_alloc_util.h +++ b/erts/emulator/beam/erl_alloc_util.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2002-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -27,8 +27,8 @@ typedef struct Allctr_t_ Allctr_t; typedef struct { - Uint ycs; - Uint mmc; + UWord ycs; + UWord mmc; } AlcUInit_t; typedef struct { @@ -38,22 +38,22 @@ typedef struct { int tspec; int tpref; int ramv; - Uint sbct; - Uint asbcst; - Uint rsbcst; - Uint rsbcmt; - Uint rmbcmt; - Uint mmbcs; - Uint mmsbc; - Uint mmmbc; - Uint lmbcs; - Uint smbcs; - Uint mbcgs; + UWord sbct; + UWord asbcst; + UWord rsbcst; + UWord rsbcmt; + UWord rmbcmt; + UWord mmbcs; + UWord mmsbc; + UWord mmmbc; + UWord lmbcs; + UWord smbcs; + UWord mbcgs; } AllctrInit_t; typedef struct { - Uint blocks; - Uint carriers; + UWord blocks; + UWord carriers; } AllctrSize_t; #ifndef SMALL_MEMORY @@ -163,19 +163,19 @@ void erts_alcu_current_size(Allctr_t *, AllctrSize_t *); #define CEILING(X, I) ((((X) - 1)/(I) + 1)*(I)) #undef WORD_MASK -#define INV_WORD_MASK ((Uint) (sizeof(Uint) - 1)) +#define INV_WORD_MASK ((UWord) (sizeof(UWord) - 1)) #define WORD_MASK (~INV_WORD_MASK) #define WORD_FLOOR(X) ((X) & WORD_MASK) #define WORD_CEILING(X) WORD_FLOOR((X) + INV_WORD_MASK) #undef UNIT_MASK -#define INV_UNIT_MASK ((Uint) (sizeof(Unit_t) - 1)) +#define INV_UNIT_MASK ((UWord) (sizeof(Unit_t) - 1)) #define UNIT_MASK (~INV_UNIT_MASK) #define UNIT_FLOOR(X) ((X) & UNIT_MASK) #define UNIT_CEILING(X) UNIT_FLOOR((X) + INV_UNIT_MASK) -#define SZ_MASK (~((Uint) 0) << 3) +#define SZ_MASK (~((UWord) 0) << 3) #define FLG_MASK (~(SZ_MASK)) @@ -189,7 +189,7 @@ typedef union {char c[8]; long l; double d;} Unit_t; typedef struct Carrier_t_ Carrier_t; struct Carrier_t_ { - Uint chdr; + UWord chdr; Carrier_t *next; Carrier_t *prev; }; @@ -199,17 +199,17 @@ typedef struct { Carrier_t *last; } CarrierList_t; -typedef Uint Block_t; -typedef Uint FreeBlkFtr_t; +typedef UWord Block_t; +typedef UWord FreeBlkFtr_t; typedef struct { - Uint giga_no; - Uint no; + UWord giga_no; + UWord no; } CallCounter_t; typedef struct { - Uint no; - Uint size; + UWord no; + UWord size; } StatValues_t; typedef struct { diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c index 126ec7cc73..64fad9fe0e 100644 --- a/erts/emulator/beam/erl_arith.c +++ b/erts/emulator/beam/erl_arith.c @@ -41,6 +41,16 @@ # define MAX(x, y) (((x) > (y)) ? (x) : (y)) #endif +#if !HEAP_ON_C_STACK +# define DECLARE_TMP(VariableName,N,P) \ + Eterm *VariableName = ((ERTS_PROC_GET_SCHDATA(P)->erl_arith_tmp_heap) + (2 * N)) +#else +# define DECLARE_TMP(VariableName,N,P) \ + Eterm VariableName[2] +#endif +# define ARG_IS_NOT_TMP(Arg,Tmp) ((Arg) != make_big((Tmp))) + + static Eterm shift(Process* p, Eterm arg1, Eterm arg2, int right); static ERTS_INLINE void maybe_shrink(Process* p, Eterm* hp, Eterm res, Uint alloc) @@ -169,7 +179,7 @@ shift(Process* p, Eterm arg1, Eterm arg2, int right) { Sint i; Sint ires; - Eterm tmp_big1[2]; + DECLARE_TMP(tmp_big1,0,p); Eterm* bigp; Uint need; @@ -312,8 +322,8 @@ BIF_RETTYPE bnot_1(BIF_ALIST_1) Eterm erts_mixed_plus(Process* p, Eterm arg1, Eterm arg2) { - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); Eterm res; Eterm hdr; FloatDef f1, f2; @@ -458,8 +468,8 @@ erts_mixed_plus(Process* p, Eterm arg1, Eterm arg2) Eterm erts_mixed_minus(Process* p, Eterm arg1, Eterm arg2) { - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); Eterm hdr; Eterm res; FloatDef f1, f2; @@ -602,8 +612,8 @@ erts_mixed_minus(Process* p, Eterm arg1, Eterm arg2) Eterm erts_mixed_times(Process* p, Eterm arg1, Eterm arg2) { - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); Eterm hdr; Eterm res; FloatDef f1, f2; @@ -627,8 +637,8 @@ erts_mixed_times(Process* p, Eterm arg1, Eterm arg2) } else if (arg2 == SMALL_ONE) { return(arg1); } else { - Eterm big_res[3]; - + DeclareTmpHeap(big_res,3,p); + UseTmpHeap(3,p); /* * The following code is optimized for the case that * result is small (which should be the most common case @@ -636,6 +646,7 @@ erts_mixed_times(Process* p, Eterm arg1, Eterm arg2) */ res = small_times(signed_val(arg1), signed_val(arg2), big_res); if (is_small(res)) { + UnUseTmpHeap(3,p); return res; } else { /* @@ -657,6 +668,7 @@ erts_mixed_times(Process* p, Eterm arg1, Eterm arg2) if (arity > 1) { *hp = big_res[2]; } + UnUseTmpHeap(3,p); return res; } } @@ -915,8 +927,8 @@ erts_mixed_div(Process* p, Eterm arg1, Eterm arg2) Eterm erts_int_div(Process* p, Eterm arg1, Eterm arg2) { - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); int ires; switch (NUMBER_CODE(arg1, arg2)) { @@ -967,8 +979,8 @@ erts_int_div(Process* p, Eterm arg1, Eterm arg2) Eterm erts_int_rem(Process* p, Eterm arg1, Eterm arg2) { - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); int ires; switch (NUMBER_CODE(arg1, arg2)) { @@ -979,7 +991,8 @@ erts_int_rem(Process* p, Eterm arg1, Eterm arg2) if (arg1 != make_small(MIN_SMALL)) { return arg1; } else { - Eterm tmp = small_to_big(signed_val(arg1), tmp_big1); + Eterm tmp; + tmp = small_to_big(signed_val(arg1), tmp_big1); if ((ires = big_ucomp(tmp, arg2)) == 0) { return SMALL_ZERO; } else { @@ -1013,8 +1026,8 @@ erts_int_rem(Process* p, Eterm arg1, Eterm arg2) Eterm erts_band(Process* p, Eterm arg1, Eterm arg2) { - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); Eterm* hp; int need; @@ -1041,8 +1054,8 @@ Eterm erts_band(Process* p, Eterm arg1, Eterm arg2) Eterm erts_bor(Process* p, Eterm arg1, Eterm arg2) { - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); Eterm* hp; int need; @@ -1069,8 +1082,8 @@ Eterm erts_bor(Process* p, Eterm arg1, Eterm arg2) Eterm erts_bxor(Process* p, Eterm arg1, Eterm arg2) { - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); Eterm* hp; int need; @@ -1148,8 +1161,8 @@ erts_gc_mixed_plus(Process* p, Eterm* reg, Uint live) { Eterm arg1; Eterm arg2; - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); Eterm res; Eterm hdr; FloatDef f1, f2; @@ -1237,10 +1250,10 @@ erts_gc_mixed_plus(Process* p, Eterm* reg, Uint live) need_heap = BIG_NEED_SIZE(sz); if (ERTS_NEED_GC(p, need_heap)) { erts_garbage_collect(p, need_heap, reg, live+2); - if (arg1 != make_big(tmp_big1)) { + if (ARG_IS_NOT_TMP(arg1,tmp_big1)) { arg1 = reg[live]; } - if (arg2 != make_big(tmp_big2)) { + if (ARG_IS_NOT_TMP(arg2,tmp_big2)) { arg2 = reg[live+1]; } } @@ -1316,8 +1329,8 @@ erts_gc_mixed_minus(Process* p, Eterm* reg, Uint live) { Eterm arg1; Eterm arg2; - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); Eterm hdr; Eterm res; FloatDef f1, f2; @@ -1394,10 +1407,10 @@ erts_gc_mixed_minus(Process* p, Eterm* reg, Uint live) need_heap = BIG_NEED_SIZE(sz); if (ERTS_NEED_GC(p, need_heap)) { erts_garbage_collect(p, need_heap, reg, live+2); - if (arg1 != make_big(tmp_big1)) { + if (ARG_IS_NOT_TMP(arg1,tmp_big1)) { arg1 = reg[live]; } - if (arg2 != make_big(tmp_big2)) { + if (ARG_IS_NOT_TMP(arg2,tmp_big2)) { arg2 = reg[live+1]; } } @@ -1482,8 +1495,8 @@ erts_gc_mixed_times(Process* p, Eterm* reg, Uint live) { Eterm arg1; Eterm arg2; - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); Eterm hdr; Eterm res; FloatDef f1, f2; @@ -1509,7 +1522,8 @@ erts_gc_mixed_times(Process* p, Eterm* reg, Uint live) } else if (arg2 == SMALL_ONE) { return(arg1); } else { - Eterm big_res[3]; + DeclareTmpHeap(big_res,3,p); + UseTmpHeap(3,p); /* * The following code is optimized for the case that @@ -1519,6 +1533,7 @@ erts_gc_mixed_times(Process* p, Eterm* reg, Uint live) res = small_times(signed_val(arg1), signed_val(arg2), big_res); if (is_small(res)) { + UnUseTmpHeap(3,p); return res; } else { /* @@ -1546,6 +1561,7 @@ erts_gc_mixed_times(Process* p, Eterm* reg, Uint live) if (arity > 1) { *hp = big_res[2]; } + UnUseTmpHeap(3,p); return res; } } @@ -1609,17 +1625,17 @@ erts_gc_mixed_times(Process* p, Eterm* reg, Uint live) need_heap = BIG_NEED_SIZE(sz); if (ERTS_NEED_GC(p, need_heap)) { erts_garbage_collect(p, need_heap, reg, live+2); - if (arg1 != make_big(tmp_big1)) { + if (ARG_IS_NOT_TMP(arg1,tmp_big1)) { arg1 = reg[live]; } - if (arg2 != make_big(tmp_big2)) { + if (ARG_IS_NOT_TMP(arg2,tmp_big2)) { arg2 = reg[live+1]; } } hp = p->htop; p->htop += need_heap; res = big_times(arg1, arg2, hp); - trim_heap(p, hp, res); + trim_heap(p, hp, res); /* * Note that the result must be big in this case, since @@ -1828,8 +1844,8 @@ erts_gc_int_div(Process* p, Eterm* reg, Uint live) { Eterm arg1; Eterm arg2; - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); int ires; arg1 = reg[live]; @@ -1866,10 +1882,10 @@ erts_gc_int_div(Process* p, Eterm* reg, Uint live) need = BIG_NEED_SIZE(i-ires+1) + BIG_NEED_SIZE(i); if (ERTS_NEED_GC(p, need)) { erts_garbage_collect(p, need, reg, live+2); - if (arg1 != make_big(tmp_big1)) { + if (ARG_IS_NOT_TMP(arg1,tmp_big1)) { arg1 = reg[live]; } - if (arg2 != make_big(tmp_big2)) { + if (ARG_IS_NOT_TMP(arg2,tmp_big2)) { arg2 = reg[live+1]; } } @@ -1894,8 +1910,8 @@ erts_gc_int_rem(Process* p, Eterm* reg, Uint live) { Eterm arg1; Eterm arg2; - Eterm tmp_big1[2]; - Eterm tmp_big2[2]; + DECLARE_TMP(tmp_big1,0,p); + DECLARE_TMP(tmp_big2,1,p); int ires; arg1 = reg[live]; @@ -1908,7 +1924,8 @@ erts_gc_int_rem(Process* p, Eterm* reg, Uint live) if (arg1 != make_small(MIN_SMALL)) { return arg1; } else { - Eterm tmp = small_to_big(signed_val(arg1), tmp_big1); + Eterm tmp; + tmp = small_to_big(signed_val(arg1), tmp_big1); if ((ires = big_ucomp(tmp, arg2)) == 0) { return SMALL_ZERO; } else { @@ -1928,10 +1945,10 @@ erts_gc_int_rem(Process* p, Eterm* reg, Uint live) if (ERTS_NEED_GC(p, need)) { erts_garbage_collect(p, need, reg, live+2); - if (arg1 != make_big(tmp_big1)) { + if (ARG_IS_NOT_TMP(arg1,tmp_big1)) { arg1 = reg[live]; } - if (arg2 != make_big(tmp_big2)) { + if (ARG_IS_NOT_TMP(arg2,tmp_big2)) { arg2 = reg[live+1]; } } @@ -1956,8 +1973,8 @@ Eterm erts_gc_##func(Process* p, Eterm* reg, Uint live) \ { \ Eterm arg1; \ Eterm arg2; \ - Eterm tmp_big1[2]; \ - Eterm tmp_big2[2]; \ + DECLARE_TMP(tmp_big1,0,p); \ + DECLARE_TMP(tmp_big2,1,p); \ Eterm* hp; \ int need; \ \ diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c index b090564649..f2a581fdf4 100644 --- a/erts/emulator/beam/erl_async.c +++ b/erts/emulator/beam/erl_async.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2000-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ #ifdef HAVE_CONFIG_H @@ -390,14 +390,14 @@ int check_async_ready(void) ** async_data data to pass to invoke function ** async_free function for relase async_data in case of failure */ -long driver_async(ErlDrvPort ix, unsigned int* key, +long driver_async(ErlDrvPort ix, unsigned long* key, void (*async_invoke)(void*), void* async_data, void (*async_free)(void*)) { ErlAsync* a = (ErlAsync*) erts_alloc(ERTS_ALC_T_ASYNC, sizeof(ErlAsync)); Port* prt = erts_drvport2port(ix); long id; - unsigned int qix; + unsigned long qix; if (!prt) diff --git a/erts/emulator/beam/erl_bif_chksum.c b/erts/emulator/beam/erl_bif_chksum.c index 445ba00ca7..06b7ffdf32 100644 --- a/erts/emulator/beam/erl_bif_chksum.c +++ b/erts/emulator/beam/erl_bif_chksum.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2008-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2008-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -49,9 +49,9 @@ void erts_init_bif_chksum(void) chksum_md5_2_exp.code[1] = am_atom_put("md5_trap",8); chksum_md5_2_exp.code[2] = 2; chksum_md5_2_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; chksum_md5_2_exp.code[4] = - (Eterm) &md5_2; + (BeamInstr) &md5_2; } diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index a34d400ed8..18cb09d8cd 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -59,12 +59,19 @@ /* Keep erts_system_version as a global variable for easy access from a core */ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE " (erts-" ERLANG_VERSION ")" +#if !HEAP_ON_C_STACK && !HALFWORD_HEAP + " [no-c-stack-objects]" +#endif #ifndef OTP_RELEASE " [source]" #endif #ifdef ARCH_64 +#if HALFWORD_HEAP + " [64-bit halfword]" +#else " [64-bit]" #endif +#endif #ifdef ERTS_SMP " [smp:%bpu:%bpu]" #endif @@ -121,7 +128,7 @@ bld_bin_list(Uint **hpp, Uint *szp, ProcBin* pb) Eterm tuple; for (; pb; pb = pb->next) { - Eterm val = erts_bld_uint(hpp, szp, (Uint) pb->val); + Eterm val = erts_bld_uword(hpp, szp, (UWord) pb->val); Eterm orig_size = erts_bld_uint(hpp, szp, pb->val->orig_size); if (szp) @@ -624,12 +631,18 @@ static Eterm pi_1_keys[] = { #define ERTS_PI_1_NO_OF_KEYS (sizeof(pi_1_keys)/sizeof(Eterm)) static Eterm pi_1_keys_list; -static Uint pi_1_keys_list_heap[2*ERTS_PI_1_NO_OF_KEYS]; +#if HEAP_ON_C_STACK +static Eterm pi_1_keys_list_heap[2*ERTS_PI_1_NO_OF_KEYS]; +#endif static void process_info_init(void) { +#if HEAP_ON_C_STACK Eterm *hp = &pi_1_keys_list_heap[0]; +#else + Eterm *hp = erts_alloc(ERTS_ALC_T_LL_TEMP_TERM,sizeof(Eterm)*2*ERTS_PI_1_NO_OF_KEYS); +#endif int i; pi_1_keys_list = NIL; @@ -998,7 +1011,7 @@ process_info_aux(Process *BIF_P, hp = HAlloc(BIF_P, 3); res = am_undefined; } else { - Eterm* current; + BeamInstr* current; if (rp->current[0] == am_erlang && rp->current[1] == am_process_info && @@ -1622,6 +1635,14 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */ if (sel == am_allocator_sizes && arity == 2) { return erts_allocator_info_term(BIF_P, *tp, 1); + } else if (sel == am_wordsize && arity == 2) { + if (tp[0] == am_internal) { + return make_small(sizeof(Eterm)); + } + if (tp[0] == am_external) { + return make_small(sizeof(UWord)); + } + goto badarg; } else if (sel == am_allocated) { if (arity == 2) { Eterm res = THE_NON_VALUE; @@ -2817,7 +2838,7 @@ fun_info_2(Process* p, Eterm fun, Eterm what) goto error; } } else if (is_export(fun)) { - Export* exp = (Export *) (export_val(fun))[1]; + Export* exp = (Export *) ((UWord) (export_val(fun))[1]); switch (what) { case am_type: hp = HAlloc(p, 3); @@ -3010,11 +3031,11 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1) res = erts_run_queues_len(NULL); BIF_RET(make_small(res)); } else if (BIF_ARG_1 == am_wall_clock) { - Uint w1, w2; + UWord w1, w2; Eterm b1, b2; wall_clock_elapsed_time_both(&w1, &w2); - b1 = erts_make_integer(w1,BIF_P); - b2 = erts_make_integer(w2,BIF_P); + b1 = erts_make_integer((Uint) w1,BIF_P); + b2 = erts_make_integer((Uint) w2,BIF_P); hp = HAlloc(BIF_P,3); res = TUPLE2(hp, b1, b2); BIF_RET(res); diff --git a/erts/emulator/beam/erl_bif_lists.c b/erts/emulator/beam/erl_bif_lists.c index a9e8dd86f7..ce13469801 100644 --- a/erts/emulator/beam/erl_bif_lists.c +++ b/erts/emulator/beam/erl_bif_lists.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1999-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1999-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -89,13 +89,14 @@ BIF_RETTYPE append_2(BIF_ALIST_2) BIF_RET(copy); } +#define SMALL_VEC_SIZE 10 BIF_RETTYPE subtract_2(BIF_ALIST_2) { Eterm list; Eterm* hp; Uint need; Eterm res; - Eterm small_vec[10]; /* Preallocated memory for small lists */ + Eterm small_vec[SMALL_VEC_SIZE]; /* Preallocated memory for small lists */ Eterm* vec_p; Eterm* vp; int i; @@ -115,7 +116,7 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2) BIF_RET(BIF_ARG_1); /* allocate element vector */ - if (n <= sizeof(small_vec)/sizeof(small_vec[0])) + if (n <= SMALL_VEC_SIZE) vec_p = small_vec; else vec_p = (Eterm*) erts_alloc(ERTS_ALC_T_TMP, n * sizeof(Eterm)); diff --git a/erts/emulator/beam/erl_bif_op.c b/erts/emulator/beam/erl_bif_op.c index 6da72dcef9..deda7adc1f 100644 --- a/erts/emulator/beam/erl_bif_op.c +++ b/erts/emulator/beam/erl_bif_op.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1999-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1999-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -251,7 +251,7 @@ BIF_RETTYPE is_function_2(BIF_ALIST_2) BIF_RET(am_true); } } else if (is_export(BIF_ARG_1)) { - Export* exp = (Export *) (export_val(BIF_ARG_1))[1]; + Export* exp = (Export *) EXPAND_POINTER((export_val(BIF_ARG_1))[1]); if (exp->code[2] == (Uint) arity) { BIF_RET(am_true); diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index f454f2e12d..0389177fbe 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2001-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -716,15 +716,17 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_nump) } } else if (option == am_cd) { Eterm iolist; - Eterm heap[4]; + DeclareTmpHeap(heap,4,p); int r; + UseTmpHeap(4,p); heap[0] = *tp; heap[1] = make_list(heap+2); heap[2] = make_small(0); heap[3] = NIL; iolist = make_list(heap); r = io_list_to_buf(iolist, (char*) dir, MAXPATHLEN); + UnUseTmpHeap(4,p); if (r < 0) { goto badarg; } diff --git a/erts/emulator/beam/erl_bif_re.c b/erts/emulator/beam/erl_bif_re.c index c027cd5984..d4a8a3aaa7 100644 --- a/erts/emulator/beam/erl_bif_re.c +++ b/erts/emulator/beam/erl_bif_re.c @@ -76,8 +76,8 @@ void erts_init_bif_re(void) re_exec_trap_export.code[0] = am_erlang; re_exec_trap_export.code[1] = am_re_run_trap; re_exec_trap_export.code[2] = 3; - re_exec_trap_export.code[3] = (Eterm) em_apply_bif; - re_exec_trap_export.code[4] = (Eterm) &re_exec_trap; + re_exec_trap_export.code[3] = (BeamInstr) em_apply_bif; + re_exec_trap_export.code[4] = (BeamInstr) &re_exec_trap; grun_trap_exportp = erts_export_put(am_re,am_grun,3); urun_trap_exportp = erts_export_put(am_re,am_urun,3); @@ -103,7 +103,7 @@ Sint erts_re_set_loop_limit(Sint limit) static int term_to_int(Eterm term, int *sp) { -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP if (is_small(term)) { Uint x = signed_val(term); @@ -154,7 +154,7 @@ static int term_to_int(Eterm term, int *sp) static Eterm make_signed_integer(int x, Process *p) { -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP return make_small(x); #else Eterm* hp; diff --git a/erts/emulator/beam/erl_bif_timer.c b/erts/emulator/beam/erl_bif_timer.c index 172bb37952..eb40c75110 100644 --- a/erts/emulator/beam/erl_bif_timer.c +++ b/erts/emulator/beam/erl_bif_timer.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2005-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2005-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -155,7 +155,7 @@ create_ref(Uint *hp, Uint32 *ref_numbers, Uint32 len) erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__); } -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP hp[0] = make_ref_thing_header(len/2 + 1); datap = (Uint32 *) &hp[1]; *(datap++) = len; @@ -173,13 +173,13 @@ create_ref(Uint *hp, Uint32 *ref_numbers, Uint32 len) static int eq_non_standard_ref_numbers(Uint32 *rn1, Uint32 len1, Uint32 *rn2, Uint32 len2) { -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP #define MAX_REF_HEAP_SZ (1+(ERTS_MAX_REF_NUMBERS/2+1)) #else #define MAX_REF_HEAP_SZ (1+ERTS_MAX_REF_NUMBERS) #endif - Uint r1_hp[MAX_REF_HEAP_SZ]; - Uint r2_hp[MAX_REF_HEAP_SZ]; + DeclareTmpHeapNoproc(r1_hp,(MAX_REF_HEAP_SZ * 2)); + Eterm *r2_hp = r1_hp +MAX_REF_HEAP_SZ; return eq(create_ref(r1_hp, rn1, len1), create_ref(r2_hp, rn2, len2)); #undef MAX_REF_HEAP_SZ @@ -398,7 +398,7 @@ setup_bif_timer(Uint32 xflags, if (!term_to_Uint(time, &timeout)) return THE_NON_VALUE; -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP if ((timeout >> 32) != 0) return THE_NON_VALUE; #endif diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c index 7dff5e0eeb..7fe4410e0d 100644 --- a/erts/emulator/beam/erl_bif_trace.c +++ b/erts/emulator/beam/erl_bif_trace.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1999-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1999-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -86,7 +86,7 @@ trace_pattern_2(Process* p, Eterm MFA, Eterm Pattern) Eterm trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) { - Eterm mfa[3]; + DeclareTmpHeap(mfa,3,p); /* Not really heap here, but might be when setting pattern */ int i; int matches = 0; int specified = 0; @@ -101,6 +101,7 @@ trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN); erts_smp_block_system(0); + UseTmpHeap(3,p); /* * Check and compile the match specification. */ @@ -312,7 +313,7 @@ trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) MatchSetUnref(match_prog_set); done: - + UnUseTmpHeap(3,p); erts_smp_release_system(); erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN); @@ -322,6 +323,7 @@ trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) MatchSetUnref(match_prog_set); + UnUseTmpHeap(3,p); erts_smp_release_system(); erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN); BIF_ERROR(p, BADARG); @@ -952,7 +954,7 @@ static int function_is_traced(Eterm mfa[3], Export e; Export* ep; int i; - Uint *code; + BeamInstr *code; /* First look for an export entry */ e.code[0] = mfa[0]; @@ -960,12 +962,12 @@ static int function_is_traced(Eterm mfa[3], e.code[2] = mfa[2]; if ((ep = export_get(&e)) != NULL) { if (ep->address == ep->code+3 && - ep->code[3] != (Uint) em_call_error_handler) { - if (ep->code[3] == (Uint) em_call_traced_function) { + ep->code[3] != (BeamInstr) em_call_error_handler) { + if (ep->code[3] == (BeamInstr) em_call_traced_function) { *ms = ep->match_prog_set; return FUNC_TRACE_GLOBAL_TRACE; } - if (ep->code[3] == (Uint) em_apply_bif) { + if (ep->code[3] == (BeamInstr) em_apply_bif) { for (i = 0; i < BIF_SIZE; ++i) { if (bif_export[i] == ep) { int r = 0; @@ -1011,7 +1013,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) { Eterm* tp; Eterm* hp; - Eterm mfa[3]; + DeclareTmpHeap(mfa,3,p); /* Not really heap here, but might be when setting pattern */ Binary *ms = NULL, *ms_meta = NULL; Sint count = 0; Eterm traced = am_false; @@ -1020,6 +1022,9 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) Eterm meta = am_false; int r; + + UseTmpHeap(3,p); + if (!is_tuple(func_spec)) { goto error; } @@ -1037,9 +1042,11 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) r = function_is_traced(mfa, &ms, &ms_meta, &meta, &count); switch (r) { case FUNC_TRACE_NOEXIST: + UnUseTmpHeap(3,p); hp = HAlloc(p, 3); return TUPLE2(hp, key, am_undefined); case FUNC_TRACE_UNTRACED: + UnUseTmpHeap(3,p); hp = HAlloc(p, 3); return TUPLE2(hp, key, am_false); case FUNC_TRACE_GLOBAL_TRACE: @@ -1120,10 +1127,12 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) default: goto error; } + UnUseTmpHeap(3,p); hp = HAlloc(p, 3); return TUPLE2(hp, key, retval); error: + UnUseTmpHeap(3,p); BIF_ERROR(p, BADARG); } @@ -1312,7 +1321,7 @@ erts_set_trace_pattern(Eterm* mfa, int specified, if (erts_bif_trace_flags[i] & BIF_TRACE_AS_META) { ASSERT(ExportIsBuiltIn(bif_export[i])); erts_clear_mtrace_bif - ((Uint *)bif_export[i]->code + 3); + ((BeamInstr *)bif_export[i]->code + 3); erts_bif_trace_flags[i] &= ~BIF_TRACE_AS_META; } set_trace_bif(i, match_prog_set); @@ -1341,7 +1350,7 @@ erts_set_trace_pattern(Eterm* mfa, int specified, } if (flags.meta) { erts_set_mtrace_bif - ((Uint *)bif_export[i]->code + 3, + ((BeamInstr *)bif_export[i]->code + 3, meta_match_prog_set, meta_tracer_pid); erts_bif_trace_flags[i] |= BIF_TRACE_AS_META; erts_bif_trace_flags[i] &= ~BIF_TRACE_AS_GLOBAL; @@ -1361,7 +1370,7 @@ erts_set_trace_pattern(Eterm* mfa, int specified, if (flags.meta) { if (erts_bif_trace_flags[i] & BIF_TRACE_AS_META) { erts_clear_mtrace_bif - ((Uint *)bif_export[i]->code + 3); + ((BeamInstr *)bif_export[i]->code + 3); erts_bif_trace_flags[i] &= ~BIF_TRACE_AS_META; } m = 1; @@ -1430,9 +1439,9 @@ static int setup_func_trace(Export* ep, void* match_prog) { if (ep->address == ep->code+3) { - if (ep->code[3] == (Uint) em_call_error_handler) { + if (ep->code[3] == (BeamInstr) em_call_error_handler) { return 0; - } else if (ep->code[3] == (Uint) em_call_traced_function) { + } else if (ep->code[3] == (BeamInstr) em_call_traced_function) { MatchSetUnref(ep->match_prog_set); ep->match_prog_set = match_prog; MatchSetRef(ep->match_prog_set); @@ -1452,8 +1461,8 @@ setup_func_trace(Export* ep, void* match_prog) return 0; } - ep->code[3] = (Uint) em_call_traced_function; - ep->code[4] = (Uint) ep->address; + ep->code[3] = (BeamInstr) em_call_traced_function; + ep->code[4] = (BeamInstr) ep->address; ep->address = ep->code+3; ep->match_prog_set = match_prog; MatchSetRef(ep->match_prog_set); @@ -1465,7 +1474,7 @@ static void setup_bif_trace(int bif_index) { ASSERT(ExportIsBuiltIn(ep)); ASSERT(ep->code[4]); - ep->code[4] = (Uint) bif_table[bif_index].traced; + ep->code[4] = (BeamInstr) bif_table[bif_index].traced; } static void set_trace_bif(int bif_index, void* match_prog) { @@ -1492,9 +1501,9 @@ static int reset_func_trace(Export* ep) { if (ep->address == ep->code+3) { - if (ep->code[3] == (Uint) em_call_error_handler) { + if (ep->code[3] == (BeamInstr) em_call_error_handler) { return 0; - } else if (ep->code[3] == (Uint) em_call_traced_function) { + } else if (ep->code[3] == (BeamInstr) em_call_traced_function) { ep->address = (Uint *) ep->code[4]; MatchSetUnref(ep->match_prog_set); ep->match_prog_set = NULL; @@ -1527,8 +1536,8 @@ static void reset_bif_trace(int bif_index) { ASSERT(ExportIsBuiltIn(ep)); ASSERT(ep->code[4]); ASSERT(! ep->match_prog_set); - ASSERT(! erts_is_mtrace_bif((Uint *)ep->code+3, NULL, NULL)); - ep->code[4] = (Uint) bif_table[bif_index].f; + ASSERT(! erts_is_mtrace_bif((BeamInstr *)ep->code+3, NULL, NULL)); + ep->code[4] = (BeamInstr) bif_table[bif_index].f; } static void clear_trace_bif(int bif_index) { diff --git a/erts/emulator/beam/erl_binary.h b/erts/emulator/beam/erl_binary.h index 1f948a9684..5b0b3bcec2 100644 --- a/erts/emulator/beam/erl_binary.h +++ b/erts/emulator/beam/erl_binary.h @@ -164,7 +164,7 @@ byte* erts_get_aligned_binary_bytes_extra(Eterm, byte**, unsigned extra); #endif #define ERTS_CHK_BIN_ALIGNMENT(B) \ - do { ASSERT(!(B) || (((Uint) &((Binary *)(B))->orig_bytes[0]) & ERTS_BIN_ALIGNMENT_MASK) == ((Uint) 0)) } while(0) + do { ASSERT(!(B) || (((UWord) &((Binary *)(B))->orig_bytes[0]) & ERTS_BIN_ALIGNMENT_MASK) == ((UWord) 0)) } while(0) ERTS_GLB_INLINE byte* erts_get_aligned_binary_bytes(Eterm bin, byte** base_ptr); ERTS_GLB_INLINE void erts_free_aligned_binary_bytes(byte* buf); diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c index e4f5d50ddf..defe18c92b 100644 --- a/erts/emulator/beam/erl_bits.c +++ b/erts/emulator/beam/erl_bits.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1999-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1999-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -255,7 +255,7 @@ erts_bs_get_integer_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuff * Simply shift whole bytes into the result. */ switch (BYTE_OFFSET(n)) { -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP case 7: w = (w << 8) | *bp++; case 6: w = (w << 8) | *bp++; case 5: w = (w << 8) | *bp++; @@ -360,7 +360,7 @@ erts_bs_get_integer_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuff case 3: v32 = LSB[0] + (LSB[1]<<8) + (LSB[2]<<16); goto big_small; -#if !defined(ARCH_64) +#if !defined(ARCH_64) || HALFWORD_HEAP case 4: v32 = (LSB[0] + (LSB[1]<<8) + (LSB[2]<<16) + (LSB[3]<<24)); if (!IS_USMALL(sgn, v32)) { diff --git a/erts/emulator/beam/erl_bits.h b/erts/emulator/beam/erl_bits.h index e3f8e0b679..0f67733fa4 100644 --- a/erts/emulator/beam/erl_bits.h +++ b/erts/emulator/beam/erl_bits.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1999-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1999-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -63,7 +63,7 @@ typedef struct erl_bin_match_struct{ #define HEADER_NUM_SLOTS(hdr) (header_arity(hdr)-sizeof(ErlBinMatchState)/sizeof(Eterm)+1) #define make_matchstate(_Ms) make_boxed((Eterm*)(_Ms)) -#define ms_matchbuffer(_Ms) &(((ErlBinMatchState*)(_Ms - TAG_PRIMARY_BOXED))->mb) +#define ms_matchbuffer(_Ms) &(((ErlBinMatchState*) boxed_val(_Ms))->mb) #if defined(ERTS_SMP) diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index 15b1c6bb56..cbdaa459de 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -87,7 +87,7 @@ static union { static struct { union { DbTable *tb; /* Only directly readable if slot is ALIVE */ - Uint next_free; /* (index<<2)|1 if slot is FREE */ + UWord next_free; /* (index<<2)|1 if slot is FREE */ }u; } *meta_main_tab; @@ -187,7 +187,7 @@ static Eterm ms_delete_all_buff[8]; /* To compare with for deletion static void fix_table_locked(Process* p, DbTable* tb); static void unfix_table_locked(Process* p, DbTable* tb, db_lock_kind_t* kind); -static void set_heir(Process* me, DbTable* tb, Eterm heir, Eterm heir_data); +static void set_heir(Process* me, DbTable* tb, Eterm heir, UWord heir_data); static void free_heir_data(DbTable*); static void free_fixations_locked(DbTable *tb); @@ -704,12 +704,13 @@ BIF_RETTYPE ets_update_element_3(BIF_ALIST_3) int cret = DB_ERROR_BADITEM; Eterm list; Eterm iter; - Eterm cell[2]; + DeclareTmpHeap(cell,2,BIF_P); DbUpdateHandle handle; if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_WRITE, LCK_WRITE_REC)) == NULL) { BIF_ERROR(BIF_P, BADARG); } + UseTmpHeap(2,BIF_P); if (!(tb->common.status & (DB_SET | DB_ORDERED_SET))) { goto bail_out; } @@ -762,6 +763,7 @@ finalize: tb->common.meth->db_finalize_dbterm(&handle); bail_out: + UnUseTmpHeap(2,BIF_P); db_unlock(tb, LCK_WRITE_REC); switch (cret) { @@ -794,8 +796,8 @@ BIF_RETTYPE ets_update_counter_3(BIF_ALIST_3) Eterm* ret_list_currp = NULL; Eterm* ret_list_prevp = NULL; Eterm iter; - Eterm cell[2]; - Eterm tuple[3]; + DeclareTmpHeap(cell,5,BIF_P); + Eterm *tuple = cell+2; DbUpdateHandle handle; Uint halloc_size = 0; /* overestimated heap usage */ Eterm* htop; /* actual heap usage */ @@ -805,6 +807,9 @@ BIF_RETTYPE ets_update_counter_3(BIF_ALIST_3) if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_WRITE, LCK_WRITE_REC)) == NULL) { BIF_ERROR(BIF_P, BADARG); } + + UseTmpHeap(5,BIF_P); + if (!(tb->common.status & (DB_SET | DB_ORDERED_SET))) { goto bail_out; } @@ -951,6 +956,7 @@ finalize: tb->common.meth->db_finalize_dbterm(&handle); bail_out: + UnUseTmpHeap(5,BIF_P); db_unlock(tb, LCK_WRITE_REC); switch (cret) { @@ -1180,12 +1186,12 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) Eterm val; Eterm ret; Eterm heir; - Eterm heir_data; + UWord heir_data; Uint32 status; Sint keypos; int is_named, is_fine_locked; int cret; - Eterm meta_tuple[3]; + DeclareTmpHeap(meta_tuple,3,BIF_P); DbTableMethod* meth; if (is_not_atom(BIF_ARG_1)) { @@ -1200,7 +1206,7 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) is_named = 0; is_fine_locked = 0; heir = am_none; - heir_data = am_undefined; + heir_data = (UWord) am_undefined; list = BIF_ARG_2; while(is_list(list)) { @@ -1375,6 +1381,8 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) erts_smp_atomic_read(&meta_pid_to_fixed_tab->common.memory_size)); #endif + UseTmpHeap(3,BIF_P); + db_meta_lock(meta_pid_to_tab, LCK_WRITE_REC); if (db_put_hash(meta_pid_to_tab, TUPLE2(meta_tuple, BIF_P->id, make_small(slot)), @@ -1383,6 +1391,8 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) } db_meta_unlock(meta_pid_to_tab, LCK_WRITE_REC); + UnUseTmpHeap(3,BIF_P); + BIF_RET(ret); } @@ -1519,7 +1529,7 @@ BIF_RETTYPE ets_delete_1(BIF_ALIST_1) } if (tb->common.owner != BIF_P->id) { - Eterm meta_tuple[3]; + DeclareTmpHeap(meta_tuple,3,BIF_P); /* * The table is being deleted by a process other than its owner. @@ -1527,6 +1537,7 @@ BIF_RETTYPE ets_delete_1(BIF_ALIST_1) * current process will be killed (e.g. by an EXIT signal), we will * now transfer the ownership to the current process. */ + UseTmpHeap(3,BIF_P); db_meta_lock(meta_pid_to_tab, LCK_WRITE_REC); db_erase_bag_exact2(meta_pid_to_tab, tb->common.owner, make_small(tb->common.slot)); @@ -1538,6 +1549,7 @@ BIF_RETTYPE ets_delete_1(BIF_ALIST_1) TUPLE2(meta_tuple,BIF_P->id,make_small(tb->common.slot)), 0); db_meta_unlock(meta_pid_to_tab, LCK_WRITE_REC); + UnUseTmpHeap(3,BIF_P); } /* disable inheritance */ free_heir_data(tb); @@ -1554,9 +1566,15 @@ BIF_RETTYPE ets_delete_1(BIF_ALIST_1) * (it looks like an continuation pointer), but that is will crash the * emulator if this BIF is call traced. */ +#if HALFWORD_HEAP + Eterm *hp = HAlloc(BIF_P, 3); + hp[0] = make_pos_bignum_header(2); + *((UWord *) (UWord) (hp+1)) = (UWord) tb; +#else Eterm *hp = HAlloc(BIF_P, 2); hp[0] = make_pos_bignum_header(1); hp[1] = (Eterm) tb; +#endif BIF_TRAP1(&ets_delete_continue_exp, BIF_P, make_big(hp)); } else { @@ -1571,7 +1589,7 @@ BIF_RETTYPE ets_give_away_3(BIF_ALIST_3) { Process* to_proc = NULL; ErtsProcLocks to_locks = ERTS_PROC_LOCK_MAIN; - Eterm buf[5]; + DeclareTmpHeap(buf,5,BIF_P); Eterm to_pid = BIF_ARG_2; Eterm from_pid; DbTable* tb = NULL; @@ -1593,6 +1611,7 @@ BIF_RETTYPE ets_give_away_3(BIF_ALIST_3) goto badarg; /* or should we be idempotent? return false maybe */ } + UseTmpHeap(5,BIF_P); db_meta_lock(meta_pid_to_tab, LCK_WRITE_REC); db_erase_bag_exact2(meta_pid_to_tab, tb->common.owner, make_small(tb->common.slot)); @@ -1610,6 +1629,7 @@ BIF_RETTYPE ets_give_away_3(BIF_ALIST_3) TUPLE4(buf, am_ETS_TRANSFER, tb->common.id, from_pid, BIF_ARG_3), 0); erts_smp_proc_unlock(to_proc, to_locks); + UnUseTmpHeap(5,BIF_P); BIF_RET(am_true); badarg: @@ -1624,11 +1644,12 @@ BIF_RETTYPE ets_setopts_2(BIF_ALIST_2) Eterm* tp; Eterm opt; Eterm heir = THE_NON_VALUE; - Eterm heir_data = THE_NON_VALUE; + UWord heir_data = (UWord) THE_NON_VALUE; Uint32 protection = 0; - Eterm fakelist[2]; + DeclareTmpHeap(fakelist,2,BIF_P); Eterm tail; + UseTmpHeap(2,BIF_P); for (tail = is_tuple(BIF_ARG_2) ? CONS(fakelist, BIF_ARG_2, NIL) : BIF_ARG_2; is_list(tail); tail = CDR(list_val(tail))) { @@ -1681,9 +1702,11 @@ BIF_RETTYPE ets_setopts_2(BIF_ALIST_2) } db_unlock (tb,LCK_WRITE); + UnUseTmpHeap(2,BIF_P); BIF_RET(am_true); badarg: + UnUseTmpHeap(2,BIF_P); if (tb != NULL) { db_unlock(tb,LCK_WRITE); } @@ -1949,29 +1972,37 @@ BIF_RETTYPE ets_match_1(BIF_ALIST_1) BIF_RETTYPE ets_match_2(BIF_ALIST_2) { Eterm ms; - Eterm buff[8]; + DeclareTmpHeap(buff,8,BIF_P); Eterm *hp = buff; - /*hp = HAlloc(BIF_P, 8);*/ + Eterm res; + + UseTmpHeap(8,BIF_P); ms = CONS(hp, am_DollarDollar, NIL); hp += 2; ms = TUPLE3(hp, BIF_ARG_2, NIL, ms); hp += 4; ms = CONS(hp, ms, NIL); - return ets_select_2(BIF_P, BIF_ARG_1, ms); + res = ets_select_2(BIF_P, BIF_ARG_1, ms); + UnUseTmpHeap(8,BIF_P); + return res; } BIF_RETTYPE ets_match_3(BIF_ALIST_3) { Eterm ms; - Eterm buff[8]; + DeclareTmpHeap(buff,8,BIF_P); Eterm *hp = buff; - /*hp = HAlloc(BIF_P, 8);*/ + Eterm res; + + UseTmpHeap(8,BIF_P); ms = CONS(hp, am_DollarDollar, NIL); hp += 2; ms = TUPLE3(hp, BIF_ARG_2, NIL, ms); hp += 4; ms = CONS(hp, ms, NIL); - return ets_select_3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3); + res = ets_select_3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3); + UnUseTmpHeap(8,BIF_P); + return res; } @@ -2385,29 +2416,37 @@ BIF_RETTYPE ets_match_object_1(BIF_ALIST_1) BIF_RETTYPE ets_match_object_2(BIF_ALIST_2) { Eterm ms; - Eterm buff[8]; + DeclareTmpHeap(buff,8,BIF_P); Eterm *hp = buff; - /*hp = HAlloc(BIF_P, 8);*/ + Eterm res; + + UseTmpHeap(8,BIF_P); ms = CONS(hp, am_DollarUnderscore, NIL); hp += 2; ms = TUPLE3(hp, BIF_ARG_2, NIL, ms); hp += 4; ms = CONS(hp, ms, NIL); - return ets_select_2(BIF_P, BIF_ARG_1, ms); + res = ets_select_2(BIF_P, BIF_ARG_1, ms); + UnUseTmpHeap(8,BIF_P); + return res; } BIF_RETTYPE ets_match_object_3(BIF_ALIST_3) { Eterm ms; - Eterm buff[8]; + DeclareTmpHeap(buff,8,BIF_P); Eterm *hp = buff; - /*hp = HAlloc(BIF_P, 8);*/ + Eterm res; + + UseTmpHeap(8,BIF_P); ms = CONS(hp, am_DollarUnderscore, NIL); hp += 2; ms = TUPLE3(hp, BIF_ARG_2, NIL, ms); hp += 4; ms = CONS(hp, ms, NIL); - return ets_select_3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3); + res = ets_select_3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3); + UnUseTmpHeap(8,BIF_P); + return res; } /* @@ -2558,7 +2597,7 @@ BIF_RETTYPE ets_match_spec_run_r_3(BIF_ALIST_3) BIF_TRAP3(bif_export[BIF_ets_match_spec_run_r_3], BIF_P,lst,BIF_ARG_2,ret); } - res = db_prog_match(BIF_P, mp, CAR(list_val(lst)), 0, &dummy); + res = db_prog_match(BIF_P, mp, CAR(list_val(lst)), NULL, 0, &dummy); if (is_value(res)) { sz = size_object(res); hp = HAlloc(BIF_P, sz + 2); @@ -2585,7 +2624,7 @@ void init_db(void) { DbTable init_tb; int i; - extern Eterm* em_apply_bif; + extern BeamInstr* em_apply_bif; Eterm *hp; unsigned bits; size_t size; @@ -2714,9 +2753,9 @@ void init_db(void) ets_select_delete_continue_exp.code[1] = am_atom_put("delete_trap",11); ets_select_delete_continue_exp.code[2] = 1; ets_select_delete_continue_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; ets_select_delete_continue_exp.code[4] = - (Eterm) &ets_select_delete_1; + (BeamInstr) &ets_select_delete_1; /* Non visual BIF to trap to. */ memset(&ets_select_count_continue_exp, 0, sizeof(Export)); @@ -2726,9 +2765,9 @@ void init_db(void) ets_select_count_continue_exp.code[1] = am_atom_put("count_trap",11); ets_select_count_continue_exp.code[2] = 1; ets_select_count_continue_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; ets_select_count_continue_exp.code[4] = - (Eterm) &ets_select_count_1; + (BeamInstr) &ets_select_count_1; /* Non visual BIF to trap to. */ memset(&ets_select_continue_exp, 0, sizeof(Export)); @@ -2738,9 +2777,9 @@ void init_db(void) ets_select_continue_exp.code[1] = am_atom_put("select_trap",11); ets_select_continue_exp.code[2] = 1; ets_select_continue_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; ets_select_continue_exp.code[4] = - (Eterm) &ets_select_trap_1; + (BeamInstr) &ets_select_trap_1; /* Non visual BIF to trap to. */ memset(&ets_delete_continue_exp, 0, sizeof(Export)); @@ -2748,8 +2787,8 @@ void init_db(void) ets_delete_continue_exp.code[0] = am_ets; ets_delete_continue_exp.code[1] = am_atom_put("delete_trap",11); ets_delete_continue_exp.code[2] = 1; - ets_delete_continue_exp.code[3] = (Eterm) em_apply_bif; - ets_delete_continue_exp.code[4] = (Eterm) &ets_delete_trap; + ets_delete_continue_exp.code[3] = (BeamInstr) em_apply_bif; + ets_delete_continue_exp.code[4] = (BeamInstr) &ets_delete_trap; hp = ms_delete_all_buff; ms_delete_all = CONS(hp, am_true, NIL); @@ -2843,9 +2882,9 @@ static int give_away_to_heir(Process* p, DbTable* tb) { Process* to_proc; ErtsProcLocks to_locks = ERTS_PROC_LOCK_MAIN; - Eterm buf[5]; + DeclareTmpHeap(buf,5,p); Eterm to_pid; - Eterm heir_data; + UWord heir_data; ASSERT(tb->common.owner == p->id); ASSERT(is_internal_pid(tb->common.heir)); @@ -2888,6 +2927,7 @@ retry: erts_smp_proc_unlock(to_proc, to_locks); return 0; /* heir dead and pid reused, table still mine */ } + UseTmpHeap(5,p); db_meta_lock(meta_pid_to_tab, LCK_WRITE_REC); db_erase_bag_exact2(meta_pid_to_tab, tb->common.owner, make_small(tb->common.slot)); @@ -2899,7 +2939,7 @@ retry: TUPLE2(buf,to_pid,make_small(tb->common.slot)), 0); db_meta_unlock(meta_pid_to_tab, LCK_WRITE_REC); - + UnUseTmpHeap(5,p); db_unlock(tb,LCK_WRITE); heir_data = tb->common.heir_data; if (!is_immed(heir_data)) { @@ -3145,7 +3185,7 @@ erts_db_process_exiting(Process *c_p, ErtsProcLocks c_p_locks) static void fix_table_locked(Process* p, DbTable* tb) { DbFixation *fix; - Eterm meta_tuple[3]; + DeclareTmpHeap(meta_tuple,3,p); #ifdef ERTS_SMP erts_smp_mtx_lock(&tb->common.fixlock); @@ -3179,12 +3219,15 @@ static void fix_table_locked(Process* p, DbTable* tb) erts_smp_mtx_unlock(&tb->common.fixlock); #endif p->flags |= F_USING_DB; + UseTmpHeap(3,p); db_meta_lock(meta_pid_to_fixed_tab, LCK_WRITE_REC); if (db_put_hash(meta_pid_to_fixed_tab, TUPLE2(meta_tuple, p->id, make_small(tb->common.slot)), 0) != DB_ERROR_NONE) { + UnUseTmpHeap(3,p); erl_exit(1,"Could not insert ets metadata in safe_fixtable."); } + UnUseTmpHeap(3,p); db_meta_unlock(meta_pid_to_fixed_tab, LCK_WRITE_REC); } @@ -3264,7 +3307,7 @@ static void free_fixations_locked(DbTable *tb) tb->common.fixations = NULL; } -static void set_heir(Process* me, DbTable* tb, Eterm heir, Eterm heir_data) +static void set_heir(Process* me, DbTable* tb, Eterm heir, UWord heir_data) { tb->common.heir = heir; if (heir == am_none) { @@ -3285,10 +3328,13 @@ static void set_heir(Process* me, DbTable* tb, Eterm heir, Eterm heir_data) } if (!is_immed(heir_data)) { - Eterm tmp[2]; + DeclareTmpHeap(tmp,2,me); + + UseTmpHeap(2,me); /* Make a dummy 1-tuple around data to use db_get_term() */ - heir_data = (Eterm) db_get_term(&tb->common, NULL, 0, + heir_data = (UWord) db_get_term(&tb->common, NULL, 0, TUPLE1(tmp,heir_data)); + UnUseTmpHeap(2,me); ASSERT(!is_immed(heir_data)); } tb->common.heir_data = heir_data; @@ -3311,10 +3357,13 @@ static BIF_RETTYPE ets_delete_trap(Process *p, Eterm cont) { int trap; Eterm* ptr = big_val(cont); - DbTable *tb = (DbTable *) ptr[1]; + DbTable *tb = *((DbTable **) (UWord) (ptr + 1)); +#if HALFWORD_HEAP + ASSERT(*ptr == make_pos_bignum_header(2)); +#else ASSERT(*ptr == make_pos_bignum_header(1)); - +#endif db_lock(tb, LCK_WRITE); trap = free_table_cont(p, tb, 0, 1); db_unlock(tb, LCK_WRITE); diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c index 4141f9766b..124129a371 100644 --- a/erts/emulator/beam/erl_db_hash.c +++ b/erts/emulator/beam/erl_db_hash.c @@ -1284,7 +1284,7 @@ static int db_select_continue_hash(Process *p, (match_res = db_prog_match(p,mp, make_tuple(current->dbterm.tpl), - 0,&dummy), + NULL,0,&dummy), is_value(match_res))) { if (all_objects) { hp = HAlloc(p, current->dbterm.size + 2); @@ -1462,7 +1462,7 @@ static int db_select_chunk_hash(Process *p, DbTable *tbl, if (current->hvalue != INVALID_HASH) { match_res = db_prog_match(p,mpi.mp, make_tuple(current->dbterm.tpl), - 0,&dummy); + NULL,0,&dummy); if (is_value(match_res)) { if (mpi.all_objects) { hp = HAlloc(p, current->dbterm.size + 2); @@ -1641,7 +1641,7 @@ static int db_select_count_hash(Process *p, if (current != NULL) { if (current->hvalue != INVALID_HASH) { if (db_prog_match(p, mpi.mp, make_tuple(current->dbterm.tpl), - 0, &dummy) == am_true) { + NULL,0, &dummy) == am_true) { ++got; } --num_left; @@ -1792,7 +1792,7 @@ static int db_select_delete_hash(Process *p, int did_erase = 0; if ((db_prog_match(p,mpi.mp, make_tuple((*current)->dbterm.tpl), - 0,&dummy)) == am_true) { + NULL,0,&dummy)) == am_true) { if (NFIXED(tb) > fixated_by_me) { /* fixated by others? */ if (slot_ix != last_pseudo_delete) { add_fixed_deletion(tb, slot_ix); @@ -1904,7 +1904,7 @@ static int db_select_delete_continue_hash(Process *p, else { int did_erase = 0; if ((db_prog_match(p,mp,make_tuple((*current)->dbterm.tpl), - 0,&dummy)) == am_true) { + NULL,0,&dummy)) == am_true) { if (NFIXED(tb) > fixated_by_me) { /* fixated by others? */ if (slot_ix != last_pseudo_delete) { add_fixed_deletion(tb, slot_ix); @@ -2005,7 +2005,7 @@ static int db_select_count_continue_hash(Process *p, continue; } if (db_prog_match(p, mp, make_tuple(current->dbterm.tpl), - 0,&dummy) == am_true) { + NULL,0,&dummy) == am_true) { ++got; } --num_left; diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c index b421da591b..b6b3cabafe 100644 --- a/erts/emulator/beam/erl_db_tree.c +++ b/erts/emulator/beam/erl_db_tree.c @@ -443,9 +443,9 @@ void db_initialize_tree(void) ets_select_reverse_exp.code[1] = am_reverse; ets_select_reverse_exp.code[2] = 3; ets_select_reverse_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; ets_select_reverse_exp.code[4] = - (Eterm) &ets_select_reverse; + (BeamInstr) &ets_select_reverse; return; }; @@ -3023,7 +3023,7 @@ static int doit_select(DbTableTree *tb, TreeDbTerm *this, void *ptr, } ret = db_prog_match(sc->p, sc->mp, make_tuple(this->dbterm.tpl), - 0, &dummy); + NULL,0, &dummy); if (is_value(ret)) { Uint sz; Eterm *hp; @@ -3072,7 +3072,7 @@ static int doit_select_count(DbTableTree *tb, TreeDbTerm *this, void *ptr, } ret = db_prog_match(sc->p, sc->mp, make_tuple(this->dbterm.tpl), - 0, &dummy); + NULL,0, &dummy); if (ret == am_true) { ++(sc->got); } @@ -3105,7 +3105,7 @@ static int doit_select_chunk(DbTableTree *tb, TreeDbTerm *this, void *ptr, ret = db_prog_match(sc->p, sc->mp, make_tuple(this->dbterm.tpl), - 0, &dummy); + NULL,0, &dummy); if (is_value(ret)) { Uint sz; Eterm *hp; @@ -3158,7 +3158,7 @@ static int doit_select_delete(DbTableTree *tb, TreeDbTerm *this, void *ptr, return 0; ret = db_prog_match(sc->p, sc->mp, make_tuple(this->dbterm.tpl), - 0, &dummy); + NULL,0, &dummy); if (ret == am_true) { key = GETKEY(sc->tb, this->dbterm.tpl); linkout_tree(sc->tb, key); diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index 8c373451fd..fd7de98ac9 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -117,6 +117,10 @@ do { \ erts_free(ERTS_ALC_T_DB_MC_STK, (Name).data); \ } while (0) + +#define TermWords(t) (((t) / (sizeof(UWord)/sizeof(Eterm))) + !!((t) % (sizeof(UWord)/sizeof(Eterm)))) + + static ERTS_INLINE Process * get_proc(Process *cp, Uint32 cp_locks, Eterm id, Uint32 id_locks) { @@ -281,7 +285,7 @@ typedef struct dmc_guard_bif { */ DMC_DECLARE_STACK_TYPE(Eterm); -DMC_DECLARE_STACK_TYPE(Uint); +DMC_DECLARE_STACK_TYPE(UWord); DMC_DECLARE_STACK_TYPE(unsigned); @@ -382,7 +386,7 @@ cleanup_match_pseudo_process(ErtsMatchPseudoProcess *mpsp, int keep_heap) else { int i; for (i = 0; i < ERTS_DEFAULT_MS_HEAP_SIZE; i++) { -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP mpsp->default_heap[i] = (Eterm) 0xdeadbeefdeadbeef; #else mpsp->default_heap[i] = (Eterm) 0xdeadbeef; @@ -830,42 +834,42 @@ static Uint my_size_object(Eterm t); static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap); /* Guard compilation */ -static void do_emit_constant(DMCContext *context, DMC_STACK_TYPE(Uint) *text, +static void do_emit_constant(DMCContext *context, DMC_STACK_TYPE(UWord) *text, Eterm t); static DMCRet dmc_list(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant); static DMCRet dmc_tuple(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant); static DMCRet dmc_variable(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant); static DMCRet dmc_fun(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant); static DMCRet dmc_expr(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant); static DMCRet compile_guard_expr(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t); /* match expression subroutine */ static DMCRet dmc_one_term(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(Eterm) *stack, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm c); @@ -1185,7 +1189,7 @@ Eterm erts_match_set_run(Process *p, Binary *mpsp, Eterm ret; ret = db_prog_match(p, mpsp, - (Eterm) args, + NIL, args, num_args, return_flags); #if defined(HARDDEBUG) if (is_non_value(ret)) { @@ -1204,6 +1208,32 @@ Eterm erts_match_set_run(Process *p, Binary *mpsp, */ } +static Eterm erts_match_set_run_ets(Process *p, Binary *mpsp, + Eterm args, int num_args, + Uint32 *return_flags) +{ + Eterm ret; + + ret = db_prog_match(p, mpsp, + args, NULL, + num_args, return_flags); +#if defined(HARDDEBUG) + if (is_non_value(ret)) { + erts_fprintf(stderr, "Failed\n"); + } else { + erts_fprintf(stderr, "Returning : %T\n", ret); + } +#endif + return ret; + /* Returns + * THE_NON_VALUE if no match + * am_false if {message,false} has been called, + * am_true if {message,_} has not been called or + * if {message,true} has been called, + * Msg if {message,Msg} has been called. + */ +} + /* ** API Used by other erl_db modules. */ @@ -1245,7 +1275,7 @@ Binary *db_match_compile(Eterm *matchexpr, { DMCHeap heap; DMC_STACK_TYPE(Eterm) stack; - DMC_STACK_TYPE(Uint) text; + DMC_STACK_TYPE(UWord) text; DMCContext context; MatchProg *ret = NULL; Eterm t; @@ -1380,7 +1410,7 @@ restart: /* ** There is one single top variable in the match expression - ** iff the text is tho Uint's and the single instruction + ** iff the text is two Uint's and the single instruction ** is 'matchBind' or it is only a skip. */ context.special = @@ -1491,8 +1521,8 @@ restart: ** A special case is when the match expression is a single binding ** (i.e '$1'), then the field single_variable is set to 1. */ - bp = erts_create_magic_binary(((sizeof(MatchProg) - sizeof(Uint)) + - (DMC_STACK_NUM(text) * sizeof(Uint))), + bp = erts_create_magic_binary(((sizeof(MatchProg) - sizeof(UWord)) + + (DMC_STACK_NUM(text) * sizeof(UWord))), erts_db_match_prog_destructor); ret = Binary2MatchProg(bp); ret->saved_program_buf = NULL; @@ -1501,7 +1531,7 @@ restart: ret->num_bindings = heap.used; ret->single_variable = context.special; sys_memcpy(ret->text, DMC_STACK_DATA(text), - DMC_STACK_NUM(text) * sizeof(Uint)); + DMC_STACK_NUM(text) * sizeof(UWord)); ret->heap_size = ((heap.used * sizeof(Eterm)) + (max_eheap_need * sizeof(Eterm)) + (context.stack_need * sizeof(Eterm *)) + @@ -1591,6 +1621,7 @@ static Eterm dpm_array_to_list(Process *psp, Eterm *arr, int arity) ** i.e. 'DCOMP_TRACE' was specified */ Eterm db_prog_match(Process *c_p, Binary *bprog, Eterm term, + Eterm *termp, int arity, Uint32 *return_flags) { @@ -1601,7 +1632,8 @@ Eterm db_prog_match(Process *c_p, Binary *bprog, Eterm term, Eterm **sp; Eterm *esp; Eterm *hp; - Uint *pc = prog->text; + BeamInstr *cp; + UWord *pc = prog->text; Eterm *ehp; Eterm ret; Uint n = 0; /* To avoid warning. */ @@ -1616,9 +1648,9 @@ Eterm db_prog_match(Process *c_p, Binary *bprog, Eterm term, int fail_label; int atomic_trace; #ifdef DMC_DEBUG - unsigned long *heap_fence; - unsigned long *eheap_fence; - unsigned long *stack_fence; + Uint *heap_fence; + Uint *eheap_fence; + Uint *stack_fence; Uint save_op; #endif /* DMC_DEBUG */ @@ -1654,9 +1686,9 @@ Eterm db_prog_match(Process *c_p, Binary *bprog, Eterm term, #ifdef DMC_DEBUG save_op = 0; - heap_fence = (unsigned long *) mpsp->heap + prog->eheap_offset - 1; - eheap_fence = (unsigned long *) mpsp->heap + prog->stack_offset - 1; - stack_fence = (unsigned long *) mpsp->heap + prog->heap_size - 1; + heap_fence = (Uint *) mpsp->heap + prog->eheap_offset - 1; + eheap_fence = (Uint *) mpsp->heap + prog->stack_offset - 1; + stack_fence = (Uint *) mpsp->heap + prog->heap_size - 1; *heap_fence = FENCE_PATTERN; *eheap_fence = FENCE_PATTERN; *stack_fence = FENCE_PATTERN; @@ -1709,11 +1741,12 @@ restart: n = *pc++; if ((int) n != arity) FAIL(); - ep = (Eterm *) *ep; + ep = termp; break; - case matchArrayBind: /* When the array size is unknown. */ + case matchArrayBind: /* When the array size is unknown. */ /* XXX:PaN - where does + this array come from? */ n = *pc++; - hp[n] = dpm_array_to_list(psp, (Eterm *) term, arity); + hp[n] = dpm_array_to_list(psp, termp, arity); break; case matchTuple: /* *ep is a tuple of arity n */ if (!is_tuple(*ep)) @@ -1770,29 +1803,34 @@ restart: FAIL(); if (memcmp(float_val(*ep) + 1, pc, sizeof(double))) FAIL(); - pc += 2; + pc += TermWords(2); ++ep; break; case matchEqRef: if (!is_ref(*ep)) FAIL(); - if (!eq(*ep, make_internal_ref(pc))) + if (!eq(*ep, make_internal_ref((Uint *) pc))) FAIL(); - i = thing_arityval(*pc); - pc += i+1; + i = thing_arityval(*((Uint *) pc)); + pc += TermWords(i+1); ++ep; break; case matchEqBig: if (!is_big(*ep)) FAIL(); tp = big_val(*ep); - if (*tp != *pc) - FAIL(); - i = BIG_ARITY(pc); - while(i--) - if (*++tp != *++pc) + { + Eterm *epc = (Eterm *) pc; + if (*tp != *epc) FAIL(); - ++pc; + i = BIG_ARITY(epc); + pc += TermWords(i+1); + while(i--) { + if (*++tp != *++epc) { + FAIL(); + } + } + } ++ep; break; case matchEq: @@ -1884,7 +1922,7 @@ restart: break; case matchPushArrayAsList: n = arity; /* Only happens when 'term' is an array */ - tp = (Eterm *) term; + tp = termp; *esp++ = make_list(ehp); while (n--) { *ehp++ = *tp++; @@ -1897,7 +1935,7 @@ restart: break; case matchPushArrayAsListU: /* This instruction is NOT efficient. */ - *esp++ = dpm_array_to_list(psp, (Eterm *) term, arity); + *esp++ = dpm_array_to_list(psp, termp, arity); break; case matchTrue: if (*--esp != am_true) @@ -2095,17 +2133,17 @@ restart: } break; case matchCaller: - if (!(c_p->cp) || !(hp = find_function_from_pc(c_p->cp))) { + if (!(c_p->cp) || !(cp = find_function_from_pc(c_p->cp))) { *esp++ = am_undefined; } else { *esp++ = make_tuple(ehp); - ehp[0] = make_arityval(3); - ehp[1] = hp[0]; - ehp[2] = hp[1]; - ehp[3] = make_small(hp[2]); - ehp += 4; - } - break; + ehp[0] = make_arityval(3); + ehp[1] = cp[0]; + ehp[2] = cp[1]; + ehp[3] = make_small((Uint) cp[2]); + ehp += 4; + } + break; case matchSilent: --esp; if (*esp == am_true) { @@ -2300,7 +2338,7 @@ void db_free_dmc_err_info(DMCErrInfo *ei){ */ Eterm db_add_counter(Eterm** hpp, Eterm counter, Eterm incr) { - Eterm big_tmp[2]; + DeclareTmpHeapNoproc(big_tmp,2); Eterm res; Sint ires; Eterm arg1; @@ -2318,6 +2356,7 @@ Eterm db_add_counter(Eterm** hpp, Eterm counter, Eterm incr) } } else { + UseTmpHeapNoproc(2); switch(NUMBER_CODE(counter, incr)) { case SMALL_BIG: arg1 = small_to_big(signed_val(counter), big_tmp); @@ -2332,12 +2371,14 @@ Eterm db_add_counter(Eterm** hpp, Eterm counter, Eterm incr) arg2 = counter; break; default: + UnUseTmpHeapNoproc(2); return THE_NON_VALUE; } res = big_plus(arg1, arg2, *hpp); if (is_big(res)) { *hpp += BIG_NEED_SIZE(big_size(res)); } + UnUseTmpHeapNoproc(2); return res; } } @@ -2606,7 +2647,7 @@ static void add_dmc_err(DMCErrInfo *err_info, static DMCRet dmc_one_term(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(Eterm) *stack, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm c) { Sint n; @@ -2704,27 +2745,80 @@ static DMCRet dmc_one_term(DMCContext *context, DMC_PUSH(*stack, c); break; case (_TAG_HEADER_REF >> _TAG_PRIMARY_SIZE): - n = thing_arityval(*internal_ref_val(c)); DMC_PUSH(*text, matchEqRef); +#if HALFWORD_HEAP + { + union { + UWord u; + Uint t[2]; + } fiddle; + ASSERT(thing_arityval(*internal_ref_val(c)) == 3); + fiddle.t[0] = *internal_ref_val(c); + fiddle.t[1] = (Uint) internal_ref_val(c)[1]; + DMC_PUSH(*text, fiddle.u); + fiddle.t[0] = (Uint) internal_ref_val(c)[2]; + fiddle.t[1] = (Uint) internal_ref_val(c)[3]; + DMC_PUSH(*text, fiddle.u); + } +#else + n = thing_arityval(*internal_ref_val(c)); DMC_PUSH(*text, *internal_ref_val(c)); for (i = 1; i <= n; ++i) { DMC_PUSH(*text, (Uint) internal_ref_val(c)[i]); } +#endif break; case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): n = thing_arityval(*big_val(c)); DMC_PUSH(*text, matchEqBig); +#if HALFWORD_HEAP + { + union { + UWord u; + Uint t[2]; + } fiddle; + ASSERT(n >= 1); + fiddle.t[0] = *big_val(c); + fiddle.t[1] = big_val(c)[1]; + DMC_PUSH(*text, fiddle.u); + for (i = 2; i <= n; ++i) { + fiddle.t[0] = big_val(c)[i]; + if (++i <= n) { + fiddle.t[1] = big_val(c)[i]; + } else { + fiddle.t[1] = (Uint) 0; + } + DMC_PUSH(*text, fiddle.u); + } + } +#else DMC_PUSH(*text, *big_val(c)); for (i = 1; i <= n; ++i) { DMC_PUSH(*text, (Uint) big_val(c)[i]); } +#endif break; case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): DMC_PUSH(*text,matchEqFloat); +#if HALFWORD_HEAP + { + union { + UWord u; + Uint t[2]; + } fiddle; + fiddle.t[0] = float_val(c)[1]; + fiddle.t[1] = float_val(c)[2]; + DMC_PUSH(*text, fiddle.u); + } +#else DMC_PUSH(*text, (Uint) float_val(c)[1]); - /* XXX: this reads and pushes random junk on ARCH_64 */ +#ifdef ARCH_64 + DMC_PUSH(*text, (Uint) 0); +#else DMC_PUSH(*text, (Uint) float_val(c)[2]); +#endif +#endif break; default: /* BINARY, FUN, VECTOR, or EXTERNAL */ /* @@ -2753,7 +2847,7 @@ static DMCRet dmc_one_term(DMCContext *context, ** Match guard compilation */ -static void do_emit_constant(DMCContext *context, DMC_STACK_TYPE(Uint) *text, +static void do_emit_constant(DMCContext *context, DMC_STACK_TYPE(UWord) *text, Eterm t) { int sz; @@ -2807,7 +2901,7 @@ add_dmc_err((ContextP)->err_info, String, -1, T, dmcWarning) static DMCRet dmc_list(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -2843,11 +2937,11 @@ static DMCRet dmc_list(DMCContext *context, static DMCRet dmc_tuple(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { - DMC_STACK_TYPE(Uint) instr_save; + DMC_STACK_TYPE(UWord) instr_save; int all_constant = 1; int textpos = DMC_STACK_NUM(*text); Eterm *p = tuple_val(t); @@ -2903,7 +2997,7 @@ static DMCRet dmc_tuple(DMCContext *context, static DMCRet dmc_whole_expression(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -2931,7 +3025,7 @@ static DMCRet dmc_whole_expression(DMCContext *context, static DMCRet dmc_variable(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -2952,7 +3046,7 @@ static DMCRet dmc_variable(DMCContext *context, static DMCRet dmc_all_bindings(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -2979,7 +3073,7 @@ static DMCRet dmc_all_bindings(DMCContext *context, static DMCRet dmc_const(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -2996,7 +3090,7 @@ static DMCRet dmc_const(DMCContext *context, static DMCRet dmc_and(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3025,7 +3119,7 @@ static DMCRet dmc_and(DMCContext *context, static DMCRet dmc_or(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3055,7 +3149,7 @@ static DMCRet dmc_or(DMCContext *context, static DMCRet dmc_andalso(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3104,7 +3198,7 @@ static DMCRet dmc_andalso(DMCContext *context, static DMCRet dmc_orelse(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3152,7 +3246,7 @@ static DMCRet dmc_orelse(DMCContext *context, static DMCRet dmc_message(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3194,7 +3288,7 @@ static DMCRet dmc_message(DMCContext *context, static DMCRet dmc_self(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3214,7 +3308,7 @@ static DMCRet dmc_self(DMCContext *context, static DMCRet dmc_return_trace(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3244,7 +3338,7 @@ static DMCRet dmc_return_trace(DMCContext *context, static DMCRet dmc_exception_trace(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3276,7 +3370,7 @@ static DMCRet dmc_exception_trace(DMCContext *context, static DMCRet dmc_is_seq_trace(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3302,7 +3396,7 @@ static DMCRet dmc_is_seq_trace(DMCContext *context, static DMCRet dmc_set_seq_token(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3351,7 +3445,7 @@ static DMCRet dmc_set_seq_token(DMCContext *context, static DMCRet dmc_get_seq_token(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3388,7 +3482,7 @@ static DMCRet dmc_get_seq_token(DMCContext *context, static DMCRet dmc_display(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3428,7 +3522,7 @@ static DMCRet dmc_display(DMCContext *context, static DMCRet dmc_process_dump(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3458,7 +3552,7 @@ static DMCRet dmc_process_dump(DMCContext *context, static DMCRet dmc_enable_trace(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3518,7 +3612,7 @@ static DMCRet dmc_enable_trace(DMCContext *context, static DMCRet dmc_disable_trace(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3578,7 +3672,7 @@ static DMCRet dmc_disable_trace(DMCContext *context, static DMCRet dmc_trace(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3652,7 +3746,7 @@ static DMCRet dmc_trace(DMCContext *context, static DMCRet dmc_caller(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3685,7 +3779,7 @@ static DMCRet dmc_caller(DMCContext *context, static DMCRet dmc_silent(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3727,7 +3821,7 @@ static DMCRet dmc_silent(DMCContext *context, static DMCRet dmc_fun(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3844,7 +3938,7 @@ static DMCRet dmc_fun(DMCContext *context, erl_exit(1,"ets:match() internal error, " "guard with more than 3 arguments."); } - DMC_PUSH(*text, (Uint) b->biff); + DMC_PUSH(*text, (UWord) b->biff); context->stack_used -= (((int) a) - 2); if (context->stack_used > context->stack_need) context->stack_need = context->stack_used; @@ -3853,7 +3947,7 @@ static DMCRet dmc_fun(DMCContext *context, static DMCRet dmc_expr(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm t, int *constant) { @@ -3916,7 +4010,7 @@ static DMCRet dmc_expr(DMCContext *context, static DMCRet compile_guard_expr(DMCContext *context, DMCHeap *heap, - DMC_STACK_TYPE(Uint) *text, + DMC_STACK_TYPE(UWord) *text, Eterm l) { DMCRet ret; @@ -4230,7 +4324,7 @@ static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace) Eterm l; Uint32 ret_flags; Uint sz; - Eterm *save_cp; + BeamInstr *save_cp; if (trace && !(is_list(against) || against == NIL)) { return THE_NON_VALUE; @@ -4271,17 +4365,18 @@ static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace) ++n; l = CDR(list_val(l)); } + save_cp = p->cp; + p->cp = NULL; + res = erts_match_set_run(p, mps, arr, n, &ret_flags); + p->cp = save_cp; } else { n = 0; - arr = (Eterm *) against; + arr = NULL; + res = erts_match_set_run_ets(p, mps, against, n, &ret_flags); } /* We are in the context of a BIF, {caller} should return 'undefined' */ - save_cp = p->cp; - p->cp = NULL; - res = erts_match_set_run(p, mps, arr, n, &ret_flags); - p->cp = save_cp; if (is_non_value(res)) { res = am_false; } @@ -4324,7 +4419,7 @@ static Eterm seq_trace_fake(Process *p, Eterm arg1) static void db_match_dis(Binary *bp) { MatchProg *prog = Binary2MatchProg(bp); - Uint *t = prog->text; + UWord *t = prog->text; Uint n; Eterm p; int first; @@ -4390,41 +4485,48 @@ static void db_match_dis(Binary *bp) break; case matchEqRef: ++t; - n = thing_arityval(*t); - ++t; - erts_printf("EqRef\t(%d) {", (int) n); - first = 1; - while (n--) { - if (first) - first = 0; - else - erts_printf(", "); -#ifdef ARCH_64 - erts_printf("0x%016bpx", *t); + { + RefThing *rt = (RefThing *) t; + int ri; + n = thing_arityval(rt->header); + erts_printf("EqRef\t(%d) {", (int) n); + first = 1; + for (ri = 0; ri < n; ++ri) { + if (first) + first = 0; + else + erts_printf(", "); +#if defined(ARCH_64) && !HALFWORD_HEAP + erts_printf("0x%016bpx", rt->data.ui[ri]); #else - erts_printf("0x%08bpx", *t); + erts_printf("0x%08bpx", rt->data.ui[ri]); #endif - ++t; + } } + t += TermWords(REF_THING_SIZE); erts_printf("}\n"); break; case matchEqBig: ++t; n = thing_arityval(*t); - ++t; - erts_printf("EqBig\t(%d) {", (int) n); - first = 1; - while (n--) { - if (first) - first = 0; - else - erts_printf(", "); -#ifdef ARCH_64 - erts_printf("0x%016bpx", *t); + { + Eterm *et = (Eterm *) t; + t += TermWords(n+1); + erts_printf("EqBig\t(%d) {", (int) n); + first = 1; + ++n; + while (n--) { + if (first) + first = 0; + else + erts_printf(", "); +#if defined(ARCH_64) && !HALFWORD_HEAP + erts_printf("0x%016bpx", *et); #else - erts_printf("0x%08bpx", *t); + erts_printf("0x%08bpx", *et); #endif - ++t; + ++et; + } } erts_printf("}\n"); break; @@ -4432,8 +4534,8 @@ static void db_match_dis(Binary *bp) ++t; { double num; - memcpy(&num,t, 2 * sizeof(*t)); - t += 2; + memcpy(&num,t,sizeof(double)); + t += TermWords(2); erts_printf("EqFloat\t%f\n", num); } break; diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h index 4fc7b4f52e..382e5dceb5 100644 --- a/erts/emulator/beam/erl_db_util.h +++ b/erts/emulator/beam/erl_db_util.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -212,7 +212,7 @@ typedef struct db_table_common { #endif Eterm owner; /* Pid of the creator */ Eterm heir; /* Pid of the heir */ - Eterm heir_data; /* To send in ETS-TRANSFER (is_immed or (DbTerm*) */ + UWord heir_data; /* To send in ETS-TRANSFER (is_immed or (DbTerm*) */ SysTimeval heir_started; /* To further identify the heir */ Eterm the_name; /* an atom */ Eterm id; /* atom | integer */ @@ -304,9 +304,9 @@ typedef struct match_prog { Uint eheap_offset; Uint stack_offset; #ifdef DMC_DEBUG - Uint* prog_end; /* End of program */ + UWord* prog_end; /* End of program */ #endif - Uint text[1]; /* Beginning of program */ + UWord text[1]; /* Beginning of program */ } MatchProg; /* @@ -366,7 +366,7 @@ Binary *db_match_compile(Eterm *matchexpr, Eterm *guards, Uint flags, DMCErrInfo *err_info); /* Returns newly allocated MatchProg binary with refc == 0*/ -Eterm db_prog_match(Process *p, Binary *prog, Eterm term, int arity, +Eterm db_prog_match(Process *p, Binary *prog, Eterm term, Eterm *termp, int arity, Uint32 *return_flags /* Zeroed on enter */); /* returns DB_ERROR_NONE if matches, 1 if not matches and some db error on error. */ diff --git a/erts/emulator/beam/erl_debug.c b/erts/emulator/beam/erl_debug.c index e5c3c76fdd..9c7a47da0a 100644 --- a/erts/emulator/beam/erl_debug.c +++ b/erts/emulator/beam/erl_debug.c @@ -235,9 +235,9 @@ pps(Process* p, Eterm* stop) } while(sp >= stop) { - erts_print(to, to_arg, "%0*lx: ", PTR_SIZE, (Eterm) sp); + erts_print(to, to_arg, "%0*lx: ", PTR_SIZE, (UWord) sp); if (is_catch(*sp)) { - erts_print(to, to_arg, "catch %d", (Uint)catch_pc(*sp)); + erts_print(to, to_arg, "catch %ld", (UWord)catch_pc(*sp)); } else { paranoid_display(to, to_arg, p, *sp); } @@ -895,5 +895,29 @@ void print_memory_info(Process *p) #endif erts_printf("+-----------------%s-%s-%s-%s-+\n",dashes,dashes,dashes,dashes); } +#if !HEAP_ON_C_STACK && defined(DEBUG) +Eterm *erts_debug_allocate_tmp_heap(int size, Process *p) +{ + ErtsSchedulerData *sd = ((p == NULL) ? erts_get_scheduler_data() : ERTS_PROC_GET_SCHDATA(p)); + int offset = sd->num_tmp_heap_used; + + ASSERT(offset+size <= TMP_HEAP_SIZE); + return (sd->tmp_heap)+offset; +} +void erts_debug_use_tmp_heap(int size, Process *p) +{ + ErtsSchedulerData *sd = ((p == NULL) ? erts_get_scheduler_data() : ERTS_PROC_GET_SCHDATA(p)); + + sd->num_tmp_heap_used += size; + ASSERT(sd->num_tmp_heap_used <= TMP_HEAP_SIZE); +} +void erts_debug_unuse_tmp_heap(int size, Process *p) +{ + ErtsSchedulerData *sd = ((p == NULL) ? erts_get_scheduler_data() : ERTS_PROC_GET_SCHDATA(p)); + + sd->num_tmp_heap_used -= size; + ASSERT(sd->num_tmp_heap_used >= 0); +} +#endif #endif diff --git a/erts/emulator/beam/erl_debug.h b/erts/emulator/beam/erl_debug.h index 74f4a00b63..bdfbaddbbf 100644 --- a/erts/emulator/beam/erl_debug.h +++ b/erts/emulator/beam/erl_debug.h @@ -1,26 +1,27 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2004-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2004-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ #ifndef _ERL_DEBUG_H_ #define _ERL_DEBUG_H_ - #ifdef DEBUG +#include "erl_term.h" + #ifdef HIPE #include "hipe_debug.h" #endif @@ -92,6 +93,11 @@ extern void print_tagged_memory(Eterm *start, Eterm *end); extern void print_untagged_memory(Eterm *start, Eterm *end); extern void print_memory(Process *p); extern void print_memory_info(Process *p); +#if defined(DEBUG) && !HEAP_ON_C_STACK +extern Eterm *erts_debug_allocate_tmp_heap(int, Process *); +extern void erts_debug_use_tmp_heap(int, Process *); +extern void erts_debug_unuse_tmp_heap(int, Process *); +#endif #ifdef HYBRID extern void print_ma_info(void); diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h index 489e74d960..15a4f44a7d 100644 --- a/erts/emulator/beam/erl_driver.h +++ b/erts/emulator/beam/erl_driver.h @@ -48,6 +48,10 @@ # define SIZEOF_LONG_LONG_SAVED__ SIZEOF_LONG_LONG # undef SIZEOF_LONG_LONG #endif +#ifdef HALFWORD_HEAP_EMULATOR +# define HALFWORD_HEAP_EMULATOR_SAVED__ HALFWORD_HEAP_EMULATOR +# undef HALFWORD_HEAP_EMULATOR +#endif #include "erl_int_sizes_config.h" #if defined(SIZEOF_CHAR_SAVED__) && SIZEOF_CHAR_SAVED__ != SIZEOF_CHAR # error SIZEOF_CHAR mismatch @@ -65,6 +69,11 @@ # error SIZEOF_LONG_LONG mismatch #endif +/* This is OK to override by the NIF/driver implementor */ +#if defined(HALFWORD_HEAP_EMULATOR_SAVED__) && !defined(HALFWORD_HEAP_EMULATOR) +#define HALFWORD_HEAP_EMULATOR HALFWORD_HEAP_EMULATOR_SAVED__ +#endif + #include "erl_drv_nif.h" #include <stdlib.h> @@ -567,7 +576,7 @@ EXTERN int driver_send_term(ErlDrvPort ix, ErlDrvTermData to, /* Async IO functions */ EXTERN long driver_async(ErlDrvPort ix, - unsigned int* key, + unsigned long* key, void (*async_invoke)(void*), void* async_data, void (*async_free)(void*)); diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c index 79e844b315..15d9538301 100644 --- a/erts/emulator/beam/erl_fun.c +++ b/erts/emulator/beam/erl_fun.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2000-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -50,8 +50,8 @@ static void fun_free(ErlFunEntry* obj); * to unloaded_fun[]. The -1 in unloaded_fun[0] will be interpreted * as an illegal arity when attempting to call a fun. */ -static Eterm unloaded_fun_code[3] = {NIL, -1, 0}; -static Eterm* unloaded_fun = unloaded_fun_code + 2; +static BeamInstr unloaded_fun_code[3] = {NIL, -1, 0}; +static BeamInstr* unloaded_fun = unloaded_fun_code + 2; void erts_init_fun_table(void) @@ -207,7 +207,7 @@ erts_cleanup_funs(ErlFunThing* funp) #endif void -erts_cleanup_funs_on_purge(Eterm* start, Eterm* end) +erts_cleanup_funs_on_purge(BeamInstr* start, BeamInstr* end) { int limit; HashBucket** bucket; @@ -222,7 +222,7 @@ erts_cleanup_funs_on_purge(Eterm* start, Eterm* end) while (b) { ErlFunEntry* fe = (ErlFunEntry *) b; - Eterm* addr = fe->address; + BeamInstr* addr = fe->address; if (start <= addr && addr < end) { fe->address = unloaded_fun; diff --git a/erts/emulator/beam/erl_fun.h b/erts/emulator/beam/erl_fun.h index fb5e75649b..944d4b3df5 100644 --- a/erts/emulator/beam/erl_fun.h +++ b/erts/emulator/beam/erl_fun.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2000-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -33,10 +33,10 @@ typedef struct erl_fun_entry { int index; /* New style index. */ int old_uniq; /* Unique number (old_style) */ int old_index; /* Old style index */ - Eterm* address; /* Pointer to code for fun */ + BeamInstr* address; /* Pointer to code for fun */ #ifdef HIPE - Eterm* native_address; /* Native entry code for fun. */ + UWord* native_address; /* Native entry code for fun. */ #endif Uint arity; /* The arity of the fun. */ @@ -58,7 +58,7 @@ typedef struct erl_fun_thing { #endif ErlFunEntry* fe; /* Pointer to fun entry. */ #ifdef HIPE - Eterm* native_address; /* Native code for the fun. */ + UWord* native_address; /* Native code for the fun. */ #endif Uint arity; /* The arity of the fun. */ Uint num_free; /* Number of free variables (in env). */ @@ -86,7 +86,7 @@ void erts_erase_fun_entry(ErlFunEntry* fe); #ifndef HYBRID /* FIND ME! */ void erts_cleanup_funs(ErlFunThing* funp); #endif -void erts_cleanup_funs_on_purge(Eterm* start, Eterm* end); +void erts_cleanup_funs_on_purge(BeamInstr* start, BeamInstr* end); void erts_dump_fun_entries(int, void *); #endif diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index e9bf37a173..9ed566e66e 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -126,7 +126,7 @@ static void disallow_heap_frag_ref_in_old_heap(Process* p); static void disallow_heap_frag_ref(Process* p, Eterm* n_htop, Eterm* objv, int nobj); #endif -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP # define MAX_HEAP_SIZES 154 #else # define MAX_HEAP_SIZES 55 @@ -1551,7 +1551,7 @@ disallow_heap_frag_ref_in_old_heap(Process* p) val = *hp++; switch (primary_tag(val)) { case TAG_PRIMARY_BOXED: - ptr = (Eterm *) val; + ptr = (Eterm *) EXPAND_POINTER(val); if (!in_area(ptr, old_heap, old_heap_size)) { if (in_area(ptr, new_heap, new_heap_size)) { abort(); @@ -1564,7 +1564,7 @@ disallow_heap_frag_ref_in_old_heap(Process* p) } break; case TAG_PRIMARY_LIST: - ptr = (Eterm *) val; + ptr = (Eterm *) EXPAND_POINTER(val); if (!in_area(ptr, old_heap, old_heap_size)) { if (in_area(ptr, new_heap, new_heap_size)) { abort(); diff --git a/erts/emulator/beam/erl_goodfit_alloc.c b/erts/emulator/beam/erl_goodfit_alloc.c index ea2ba4d55c..76b206d76f 100644 --- a/erts/emulator/beam/erl_goodfit_alloc.c +++ b/erts/emulator/beam/erl_goodfit_alloc.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2003-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -49,30 +49,30 @@ #define MIN_MBC_FIRST_FREE_SZ (4*1024) #define MAX_SUB_MASK_IX \ - ((((Uint)1) << (NO_OF_BKT_IX_BITS - SUB_MASK_IX_SHIFT)) - 1) -#define MAX_SUB_BKT_IX ((((Uint)1) << SUB_MASK_IX_SHIFT) - 1) + ((((UWord)1) << (NO_OF_BKT_IX_BITS - SUB_MASK_IX_SHIFT)) - 1) +#define MAX_SUB_BKT_IX ((((UWord)1) << SUB_MASK_IX_SHIFT) - 1) #define MAX_BKT_IX (NO_OF_BKTS - 1) -#define MIN_BLK_SZ UNIT_CEILING(sizeof(GFFreeBlock_t) + sizeof(Uint)) +#define MIN_BLK_SZ UNIT_CEILING(sizeof(GFFreeBlock_t) + sizeof(UWord)) -#define IX2SBIX(IX) ((IX) & (~(~((Uint)0) << SUB_MASK_IX_SHIFT))) +#define IX2SBIX(IX) ((IX) & (~(~((UWord)0) << SUB_MASK_IX_SHIFT))) #define IX2SMIX(IX) ((IX) >> SUB_MASK_IX_SHIFT) #define MAKE_BKT_IX(SMIX, SBIX) \ - ((((Uint)(SMIX)) << SUB_MASK_IX_SHIFT) | ((Uint)(SBIX))) + ((((UWord)(SMIX)) << SUB_MASK_IX_SHIFT) | ((UWord)(SBIX))) #define SET_BKT_MASK_IX(BM, IX) \ do { \ int sub_mask_ix__ = IX2SMIX((IX)); \ - (BM).main |= (((Uint) 1) << sub_mask_ix__); \ - (BM).sub[sub_mask_ix__] |= (((Uint)1) << IX2SBIX((IX))); \ + (BM).main |= (((UWord) 1) << sub_mask_ix__); \ + (BM).sub[sub_mask_ix__] |= (((UWord)1) << IX2SBIX((IX))); \ } while (0) #define UNSET_BKT_MASK_IX(BM, IX) \ do { \ int sub_mask_ix__ = IX2SMIX((IX)); \ - (BM).sub[sub_mask_ix__] &= ~(((Uint)1) << IX2SBIX((IX))); \ + (BM).sub[sub_mask_ix__] &= ~(((UWord)1) << IX2SBIX((IX))); \ if (!(BM).sub[sub_mask_ix__]) \ - (BM).main &= ~(((Uint)1) << sub_mask_ix__); \ + (BM).main &= ~(((UWord)1) << sub_mask_ix__); \ } while (0) /* Buckets ... */ @@ -263,8 +263,8 @@ find_bucket(BucketMask_t *bmask, int min_index) while(max != min) { \ mid = ((max - min) >> 1) + min; \ if((BitMask) \ - & (~(~((Uint) 0) << (mid + 1))) \ - & (~((Uint) 0) << min)) \ + & (~(~((UWord) 0) << (mid + 1))) \ + & (~((UWord) 0) << min)) \ max = mid; \ else \ min = mid + 1; \ @@ -272,21 +272,21 @@ find_bucket(BucketMask_t *bmask, int min_index) (MinBit) = min - ASSERT(bmask->main < (((Uint) 1) << (MAX_SUB_MASK_IX+1))); + ASSERT(bmask->main < (((UWord) 1) << (MAX_SUB_MASK_IX+1))); sub_mask_ix = IX2SMIX(min_index); - if ((bmask->main & (~((Uint) 0) << sub_mask_ix)) == 0) + if ((bmask->main & (~((UWord) 0) << sub_mask_ix)) == 0) return -1; /* There exists a non empty bucket; find it... */ - if (bmask->main & (((Uint) 1) << sub_mask_ix)) { + if (bmask->main & (((UWord) 1) << sub_mask_ix)) { sub_bkt_ix = IX2SBIX(min_index); - if ((bmask->sub[sub_mask_ix] & (~((Uint) 0) << sub_bkt_ix)) == 0) { + if ((bmask->sub[sub_mask_ix] & (~((UWord) 0) << sub_bkt_ix)) == 0) { sub_mask_ix++; sub_bkt_ix = 0; - if ((bmask->main & (~((Uint) 0)<< sub_mask_ix)) == 0) + if ((bmask->main & (~((UWord) 0)<< sub_mask_ix)) == 0) return -1; } else @@ -299,17 +299,17 @@ find_bucket(BucketMask_t *bmask, int min_index) ASSERT(sub_mask_ix <= MAX_SUB_MASK_IX); /* Has to be a bit > sub_mask_ix */ - ASSERT(bmask->main & (~((Uint) 0) << (sub_mask_ix))); + ASSERT(bmask->main & (~((UWord) 0) << (sub_mask_ix))); GET_MIN_BIT(sub_mask_ix, bmask->main, sub_mask_ix, MAX_SUB_MASK_IX); find_sub_bkt_ix: ASSERT(sub_mask_ix <= MAX_SUB_MASK_IX); ASSERT(sub_bkt_ix <= MAX_SUB_BKT_IX); - if ((bmask->sub[sub_mask_ix] & (((Uint) 1) << sub_bkt_ix)) == 0) { + if ((bmask->sub[sub_mask_ix] & (((UWord) 1) << sub_bkt_ix)) == 0) { ASSERT(sub_mask_ix + 1 <= MAX_SUB_BKT_IX); /* Has to be a bit > sub_bkt_ix */ - ASSERT(bmask->sub[sub_mask_ix] & (~((Uint) 0) << sub_bkt_ix)); + ASSERT(bmask->sub[sub_mask_ix] & (~((UWord) 0) << sub_bkt_ix)); GET_MIN_BIT(sub_bkt_ix, bmask->sub[sub_mask_ix], @@ -336,7 +336,7 @@ search_bucket(Allctr_t *allctr, int ix, Uint size) Uint min_sz; Uint blk_sz; Uint cand_sz = 0; - Uint max_blk_search; + UWord max_blk_search; GFFreeBlock_t *blk; GFFreeBlock_t *cand = NULL; int blk_on_lambc; @@ -615,9 +615,9 @@ check_block(Allctr_t *allctr, Block_t * blk, int free_block) Uint blk_sz = BLK_SZ(blk); bi = BKT_IX(gfallctr, blk_sz); - ASSERT(gfallctr->bucket_mask.main & (((Uint) 1) << IX2SMIX(bi))); + ASSERT(gfallctr->bucket_mask.main & (((UWord) 1) << IX2SMIX(bi))); ASSERT(gfallctr->bucket_mask.sub[IX2SMIX(bi)] - & (((Uint) 1) << IX2SBIX(bi))); + & (((UWord) 1) << IX2SBIX(bi))); found = 0; for (fblk = gfallctr->buckets[bi]; fblk; fblk = fblk->next) @@ -648,9 +648,9 @@ check_mbc(Allctr_t *allctr, Carrier_t *mbc) int bi; for(bi = 0; bi < NO_OF_BKTS; bi++) { - if ((gfallctr->bucket_mask.main & (((Uint) 1) << IX2SMIX(bi))) + if ((gfallctr->bucket_mask.main & (((UWord) 1) << IX2SMIX(bi))) && (gfallctr->bucket_mask.sub[IX2SMIX(bi)] - & (((Uint) 1) << IX2SBIX(bi)))) { + & (((UWord) 1) << IX2SBIX(bi)))) { ASSERT(gfallctr->buckets[bi] != NULL); } else { diff --git a/erts/emulator/beam/erl_goodfit_alloc.h b/erts/emulator/beam/erl_goodfit_alloc.h index 3d1b8c01f6..a554a6f466 100644 --- a/erts/emulator/beam/erl_goodfit_alloc.h +++ b/erts/emulator/beam/erl_goodfit_alloc.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2003-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -28,7 +28,7 @@ typedef struct GFAllctr_t_ GFAllctr_t; typedef struct { - Uint mbsd; + UWord mbsd; } GFAllctrInit_t; #define ERTS_DEFAULT_GF_ALLCTR_INIT { \ @@ -49,18 +49,18 @@ Allctr_t *erts_gfalc_start(GFAllctr_t *, GFAllctrInit_t *, AllctrInit_t *); #include "erl_alloc_util.h" #define NO_OF_BKT_IX_BITS (8) -#ifdef ARCH_64 +#if defined(ARCH_64) # define SUB_MASK_IX_SHIFT (6) #else # define SUB_MASK_IX_SHIFT (5) #endif -#define NO_OF_BKTS (((Uint) 1) << NO_OF_BKT_IX_BITS) -#define NO_OF_SUB_MASKS (NO_OF_BKTS/(((Uint) 1) << SUB_MASK_IX_SHIFT)) +#define NO_OF_BKTS (((UWord) 1) << NO_OF_BKT_IX_BITS) +#define NO_OF_SUB_MASKS (NO_OF_BKTS/(((UWord) 1) << SUB_MASK_IX_SHIFT)) typedef struct { - Uint main; - Uint sub[NO_OF_SUB_MASKS]; -} BucketMask_t; + UWord main; + UWord sub[NO_OF_SUB_MASKS]; +} BucketMask_t; typedef struct GFFreeBlock_t_ GFFreeBlock_t; struct GFFreeBlock_t_ { @@ -74,11 +74,11 @@ struct GFAllctr_t_ { char * last_aux_mbc_start; char * last_aux_mbc_end; - Uint bkt_max_size_d; - Uint bkt_intrvl_d; + UWord bkt_max_size_d; + UWord bkt_intrvl_d; BucketMask_t bucket_mask; GFFreeBlock_t * buckets[NO_OF_BKTS]; - Uint max_blk_search; + UWord max_blk_search; }; diff --git a/erts/emulator/beam/erl_instrument.c b/erts/emulator/beam/erl_instrument.c index 3f022f92b8..f3f3c22933 100644 --- a/erts/emulator/beam/erl_instrument.c +++ b/erts/emulator/beam/erl_instrument.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2003-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -540,18 +540,18 @@ static void dump_memory_map_to_stream(FILE *fp) if (is_internal_pid(bp->pid)) fprintf(fp, "{%lu, %lu, %lu, {%lu,%lu,%lu}}.\n", - (Uint) bp->type_no, - (Uint) bp->mem, - (Uint) bp->size, - (Uint) pid_channel_no(bp->pid), - (Uint) pid_number(bp->pid), - (Uint) pid_serial(bp->pid)); + (UWord) bp->type_no, + (UWord) bp->mem, + (UWord) bp->size, + (UWord) pid_channel_no(bp->pid), + (UWord) pid_number(bp->pid), + (UWord) pid_serial(bp->pid)); else fprintf(fp, "{%lu, %lu, %lu, undefined}.\n", - (Uint) bp->type_no, - (Uint) bp->mem, - (Uint) bp->size); + (UWord) bp->type_no, + (UWord) bp->mem, + (UWord) bp->size); } if (lock) @@ -638,7 +638,7 @@ Eterm erts_instr_get_memory_map(Process *proc) hsz += 4; } - if ((Uint) bp->mem > MAX_SMALL) + if ((UWord) bp->mem > MAX_SMALL) hsz += BIG_UINT_HEAP_SIZE; if (bp->size > MAX_SMALL) hsz += BIG_UINT_HEAP_SIZE; @@ -749,12 +749,12 @@ Eterm erts_instr_get_memory_map(Process *proc) #endif type = make_small(bp->type_no); - if ((Uint) bp->mem > MAX_SMALL) { - ptr = uint_to_big((Uint) bp->mem, hp); + if ((UWord) bp->mem > MAX_SMALL) { + ptr = uint_to_big((UWord) bp->mem, hp); hp += BIG_UINT_HEAP_SIZE; } else - ptr = make_small((Uint) bp->mem); + ptr = make_small((UWord) bp->mem); if (bp->size > MAX_SMALL) { size = uint_to_big(bp->size, hp); @@ -962,12 +962,12 @@ dump_stat_to_stream(FILE *fp, int begin_max_period) fprintf(fp, "{total,[{total,[{sizes,%lu,%lu,%lu},{blocks,%lu,%lu,%lu}]}]}.\n", - stats->tot.size, - stats->tot.max_size, - stats->tot.max_size_ever, - stats->tot.blocks, - stats->tot.max_blocks, - stats->tot.max_blocks_ever); + (UWord) stats->tot.size, + (UWord) stats->tot.max_size, + (UWord) stats->tot.max_size_ever, + (UWord) stats->tot.blocks, + (UWord) stats->tot.max_blocks, + (UWord) stats->tot.max_blocks_ever); a_max = 0; a_min = ~0; @@ -992,12 +992,12 @@ dump_stat_to_stream(FILE *fp, int begin_max_period) "%s{%s,[{sizes,%lu,%lu,%lu},{blocks,%lu,%lu,%lu}]}%s", i == a_min ? "{allocators,\n [" : " ", ERTS_ALC_A2AD(i), - stats->a[i].size, - stats->a[i].max_size, - stats->a[i].max_size_ever, - stats->a[i].blocks, - stats->a[i].max_blocks, - stats->a[i].max_blocks_ever, + (UWord) stats->a[i].size, + (UWord) stats->a[i].max_size, + (UWord) stats->a[i].max_size_ever, + (UWord) stats->a[i].blocks, + (UWord) stats->a[i].max_blocks, + (UWord) stats->a[i].max_blocks_ever, i == a_max ? "]}.\n" : ",\n"); } } @@ -1009,12 +1009,12 @@ dump_stat_to_stream(FILE *fp, int begin_max_period) "%s{%s,[{sizes,%lu,%lu,%lu},{blocks,%lu,%lu,%lu}]}%s", i == ERTS_ALC_C_MIN ? "{classes,\n [" : " ", ERTS_ALC_C2CD(i), - stats->c[i].size, - stats->c[i].max_size, - stats->c[i].max_size_ever, - stats->c[i].blocks, - stats->c[i].max_blocks, - stats->c[i].max_blocks_ever, + (UWord) stats->c[i].size, + (UWord) stats->c[i].max_size, + (UWord) stats->c[i].max_size_ever, + (UWord) stats->c[i].blocks, + (UWord) stats->c[i].max_blocks, + (UWord) stats->c[i].max_blocks_ever, i == ERTS_ALC_C_MAX ? "]}.\n" : ",\n" ); } @@ -1025,12 +1025,12 @@ dump_stat_to_stream(FILE *fp, int begin_max_period) "%s{%s,[{sizes,%lu,%lu,%lu},{blocks,%lu,%lu,%lu}]}%s", i == ERTS_ALC_N_MIN ? "{types,\n [" : " ", ERTS_ALC_N2TD(i), - stats->n[i].size, - stats->n[i].max_size, - stats->n[i].max_size_ever, - stats->n[i].blocks, - stats->n[i].max_blocks, - stats->n[i].max_blocks_ever, + (UWord) stats->n[i].size, + (UWord) stats->n[i].max_size, + (UWord) stats->n[i].max_size_ever, + (UWord) stats->n[i].blocks, + (UWord) stats->n[i].max_blocks, + (UWord) stats->n[i].max_blocks_ever, i == ERTS_ALC_N_MAX ? "]}.\n" : ",\n" ); } diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c index 074b08ea57..6ff5c1b9da 100644 --- a/erts/emulator/beam/erl_lock_check.c +++ b/erts/emulator/beam/erl_lock_check.c @@ -155,6 +155,9 @@ static erts_lc_lock_order_t erts_lock_order[] = { { "fix_alloc", "index" }, { "alcu_allocator", "index" }, { "mseg", NULL }, +#ifdef HALFWORD_HEAP + { "pmmap", NULL }, +#endif #ifdef ERTS_SMP { "port_task_pre_alloc_lock", "address" }, { "port_taskq_pre_alloc_lock", "address" }, @@ -1231,6 +1234,8 @@ void erts_lc_init_lock(erts_lc_lock_t *lck, char *name, Uint16 flags) { lck->id = erts_lc_get_lock_order_id(name); + + /* XXX:PaN What to do with the extra information? */ lck->extra = make_boxed(&lck->extra); lck->flags = flags; lck->inited = ERTS_LC_INITITALIZED; diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h index 5cf7c209bd..459c6363aa 100644 --- a/erts/emulator/beam/erl_message.h +++ b/erts/emulator/beam/erl_message.h @@ -49,7 +49,7 @@ typedef struct erl_heap_fragment ErlHeapFragment; struct erl_heap_fragment { ErlHeapFragment* next; /* Next heap fragment */ ErlOffHeap off_heap; /* Offset heap data. */ - unsigned size; /* Size in words of mem */ + unsigned size; /* Size in (half)words of mem */ unsigned used_size; /* With terms to be moved to heap by GC */ Eterm mem[1]; /* Data */ }; diff --git a/erts/emulator/beam/erl_mtrace.c b/erts/emulator/beam/erl_mtrace.c index 8b8ac2ec80..9cf55ee319 100644 --- a/erts/emulator/beam/erl_mtrace.c +++ b/erts/emulator/beam/erl_mtrace.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2003-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -79,7 +79,7 @@ static erts_mtx_t mtrace_buf_mutex; #define UI16_SZ (2) #define UI32_SZ (4) #define UI64_SZ (8) -#ifdef ARCH_64 +#ifdef ARCH_64 /* XXX:PaN Halfword? (whole file...) */ # define UI_SZ UI64_SZ #else # define UI_SZ UI32_SZ @@ -188,7 +188,7 @@ check_alloc_entry(byte *sp, byte *ep, byte tag, Uint16 ct_no, int ct_no_n, Uint16 type, int type_n, - Uint res, int res_n, + UWord res, int res_n, Uint size, int size_n, Uint32 ti,int ti_n); void @@ -196,8 +196,8 @@ check_realloc_entry(byte *sp, byte *ep, byte tag, Uint16 ct_no, int ct_no_n, Uint16 type, int type_n, - Uint res, int res_n, - Uint ptr, int ptr_n, + UWord res, int res_n, + UWord ptr, int ptr_n, Uint size, int size_n, Uint32 ti,int ti_n); void @@ -205,7 +205,7 @@ check_free_entry(byte *sp, byte *ep, byte tag, Uint16 ct_no, int ct_no_n, Uint16 t_no, int t_no_n, - Uint ptr, int ptr_n, + UWord ptr, int ptr_n, Uint32 ti,int ti_n); void check_time_inc_entry(byte *sp, byte *ep, @@ -785,7 +785,7 @@ write_alloc_entry(byte tag, tag, ct_no, ct_no_n, t_no, t_no_n, - (Uint) res, res_n, + (UWord) res, res_n, size, size_n, ti, ti_n); #endif @@ -865,8 +865,8 @@ write_realloc_entry(byte tag, tag, ct_no, ct_no_n, t_no, t_no_n, - (Uint) res, res_n, - (Uint) ptr, ptr_n, + (UWord) res, res_n, + (UWord) ptr, ptr_n, size, size_n, ti, ti_n); #endif @@ -934,7 +934,7 @@ write_free_entry(byte tag, tag, ct_no, ct_no_n, t_no, t_no_n, - (Uint) ptr, ptr_n, + (UWord) ptr, ptr_n, ti, ti_n); #endif } @@ -1135,7 +1135,7 @@ check_alloc_entry(byte *sp, byte *ep, byte tag, Uint16 ct_no, int ct_no_n, Uint16 t_no, int t_no_n, - Uint res, int res_n, + UWord res, int res_n, Uint size, int size_n, Uint32 ti,int ti_n) { @@ -1163,8 +1163,8 @@ check_realloc_entry(byte *sp, byte *ep, byte tag, Uint16 ct_no, int ct_no_n, Uint16 t_no, int t_no_n, - Uint res, int res_n, - Uint ptr, int ptr_n, + UWord res, int res_n, + UWord ptr, int ptr_n, Uint size, int size_n, Uint32 ti,int ti_n) { @@ -1193,7 +1193,7 @@ check_free_entry(byte *sp, byte *ep, byte tag, Uint16 ct_no, int ct_no_n, Uint16 t_no, int t_no_n, - Uint ptr, int ptr_n, + UWord ptr, int ptr_n, Uint32 ti,int ti_n) { byte *p = sp; diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 585a6c1fdf..41a9e17c86 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -496,9 +496,9 @@ int enif_get_atom(ErlNifEnv* env, Eterm atom, char* buf, unsigned len) int enif_get_int(ErlNifEnv* env, Eterm term, int* ip) { -#if SIZEOF_INT == SIZEOF_VOID_P +#if SIZEOF_INT == ERTS_SIZEOF_ETERM return term_to_Sint(term, (Sint*)ip); -#elif SIZEOF_LONG == SIZEOF_VOID_P +#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM Sint i; if (!term_to_Sint(term, &i) || i < INT_MIN || i > INT_MAX) { return 0; @@ -512,9 +512,9 @@ int enif_get_int(ErlNifEnv* env, Eterm term, int* ip) int enif_get_uint(ErlNifEnv* env, Eterm term, unsigned* ip) { -#if SIZEOF_INT == SIZEOF_VOID_P +#if SIZEOF_INT == ERTS_SIZEOF_ETERM return term_to_Uint(term, (Uint*)ip); -#elif SIZEOF_LONG == SIZEOF_VOID_P +#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM Uint i; if (!term_to_Uint(term, &i) || i > UINT_MAX) { return 0; @@ -526,8 +526,13 @@ int enif_get_uint(ErlNifEnv* env, Eterm term, unsigned* ip) int enif_get_long(ErlNifEnv* env, Eterm term, long* ip) { -#if SIZEOF_LONG == SIZEOF_VOID_P +#if SIZEOF_LONG == ERTS_SIZEOF_ETERM return term_to_Sint(term, ip); +#elif SIZEOF_INT == ERTS_SIZEOF_ETERM + Uint u; + term_to_Sint(term, u); + *ip = (long) u; + return 1; #else # error Unknown long word size #endif @@ -535,8 +540,14 @@ int enif_get_long(ErlNifEnv* env, Eterm term, long* ip) int enif_get_ulong(ErlNifEnv* env, Eterm term, unsigned long* ip) { -#if SIZEOF_LONG == SIZEOF_VOID_P +#if SIZEOF_LONG == ERTS_SIZEOF_ETERM return term_to_Uint(term, ip); +#elif SIZEOF_INT == ERTS_SIZEOF_ETERM + Uint u; + int r; + r = term_to_Uint(term, &u); + *ip = (unsigned long) u; + return r; #else # error Unknown long word size #endif @@ -565,27 +576,24 @@ int enif_get_list_cell(ErlNifEnv* env, Eterm term, Eterm* head, Eterm* tail) ERL_NIF_TERM enif_make_int(ErlNifEnv* env, int i) { -#if SIZEOF_INT == SIZEOF_VOID_P +#if SIZEOF_INT == ERTS_SIZEOF_ETERM return IS_SSMALL(i) ? make_small(i) : small_to_big(i,alloc_heap(env,2)); -#elif SIZEOF_LONG == SIZEOF_VOID_P +#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM return make_small(i); #endif } ERL_NIF_TERM enif_make_uint(ErlNifEnv* env, unsigned i) { -#if SIZEOF_INT == SIZEOF_VOID_P +#if SIZEOF_INT == ERTS_SIZEOF_ETERM return IS_USMALL(0,i) ? make_small(i) : uint_to_big(i,alloc_heap(env,2)); -#elif SIZEOF_LONG == SIZEOF_VOID_P +#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM return make_small(i); #endif } ERL_NIF_TERM enif_make_long(ErlNifEnv* env, long i) { -#if SIZEOF_LONG != SIZEOF_VOID_P -# error Unknown long word size -#endif return IS_SSMALL(i) ? make_small(i) : small_to_big(i, alloc_heap(env,2)); } @@ -967,34 +975,34 @@ unsigned enif_sizeof_resource(ErlNifEnv* env, void* obj) ***************************************************************************/ -static Uint** get_func_pp(Eterm* mod_code, Eterm f_atom, unsigned arity) +static BeamInstr** get_func_pp(BeamInstr* mod_code, Eterm f_atom, unsigned arity) { int n = (int) mod_code[MI_NUM_FUNCTIONS]; int j; for (j = 0; j < n; ++j) { - Uint* code_ptr = (Uint*) mod_code[MI_FUNCTIONS+j]; - ASSERT(code_ptr[0] == (Uint) BeamOp(op_i_func_info_IaaI)); + BeamInstr* code_ptr = (BeamInstr*) mod_code[MI_FUNCTIONS+j]; + ASSERT(code_ptr[0] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); if (f_atom == ((Eterm) code_ptr[3]) && arity == ((unsigned) code_ptr[4])) { - return (Uint**) &mod_code[MI_FUNCTIONS+j]; + return (BeamInstr**) &mod_code[MI_FUNCTIONS+j]; } } return NULL; } -/*static void refresh_cached_nif_data(Eterm* mod_code, +/*static void refresh_cached_nif_data(BeamInstr* mod_code, struct erl_module_nif* mod_nif) { int i; for (i=0; i < mod_nif->entry->num_of_funcs; i++) { Eterm f_atom; ErlNifFunc* func = &mod_nif->entry->funcs[i]; - Uint* code_ptr; + BeamInstr* code_ptr; erts_atom_get(func->name, sys_strlen(func->name), &f_atom); code_ptr = *get_func_pp(mod_code, f_atom, func->arity); - code_ptr[5+2] = (Uint) mod_nif->priv_data; + code_ptr[5+2] = ((BeamInstr) mod_nif->priv_data; } }*/ @@ -1098,7 +1106,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) Module* mod; Eterm mod_atom; Eterm f_atom; - Eterm* caller; + BeamInstr* caller; ErtsSysDdllError errdesc = ERTS_SYS_DDLL_ERROR_INIT; Eterm ret = am_ok; int veto; @@ -1165,7 +1173,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) /*erts_fprintf(stderr, "Found module %T\r\n", mod_atom);*/ for (i=0; i < entry->num_of_funcs && ret==am_ok; i++) { - Uint** code_pp; + BeamInstr** code_pp; ErlNifFunc* f = &entry->funcs[i]; if (!erts_atom_get(f->name, sys_strlen(f->name), &f_atom) || (code_pp = get_func_pp(mod->code, f_atom, f->arity))==NULL) { @@ -1268,22 +1276,22 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) mod->nif = lib; for (i=0; i < entry->num_of_funcs; i++) { - Uint* code_ptr; + BeamInstr* code_ptr; erts_atom_get(entry->funcs[i].name, sys_strlen(entry->funcs[i].name), &f_atom); code_ptr = *get_func_pp(mod->code, f_atom, entry->funcs[i].arity); if (code_ptr[1] == 0) { - code_ptr[5+0] = (Uint) BeamOp(op_call_nif); + code_ptr[5+0] = (BeamInstr) BeamOp(op_call_nif); } else { /* Function traced, patch the original instruction word */ BpData* bp = (BpData*) code_ptr[1]; - bp->orig_instr = (Uint) BeamOp(op_call_nif); + bp->orig_instr = (BeamInstr) BeamOp(op_call_nif); } - code_ptr[5+1] = (Uint) entry->funcs[i].fptr; - code_ptr[5+2] = (Uint) lib; + code_ptr[5+1] = (BeamInstr) entry->funcs[i].fptr; + code_ptr[5+2] = (BeamInstr) lib; } } - else { + else { error: ASSERT(ret != am_ok); if (lib != NULL) { diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index 1ccf00293e..d0f6424724 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -34,7 +34,37 @@ #include <stdlib.h> +#ifdef SIZEOF_CHAR +# define SIZEOF_CHAR_SAVED__ SIZEOF_CHAR +# undef SIZEOF_CHAR +#endif +#ifdef SIZEOF_SHORT +# define SIZEOF_SHORT_SAVED__ SIZEOF_SHORT +# undef SIZEOF_SHORT +#endif +#ifdef SIZEOF_INT +# define SIZEOF_INT_SAVED__ SIZEOF_INT +# undef SIZEOF_INT +#endif +#ifdef SIZEOF_LONG +# define SIZEOF_LONG_SAVED__ SIZEOF_LONG +# undef SIZEOF_LONG +#endif +#ifdef SIZEOF_LONG_LONG +# define SIZEOF_LONG_LONG_SAVED__ SIZEOF_LONG_LONG +# undef SIZEOF_LONG_LONG +#endif +#ifdef HALFWORD_HEAP_EMULATOR +# define HALFWORD_HEAP_EMULATOR_SAVED__ HALFWORD_HEAP_EMULATOR +# undef HALFWORD_HEAP_EMULATOR +#endif +#include "erl_int_sizes_config.h" + +#ifdef HALFWORD_HEAP_EMULATOR +typedef unsigned int ERL_NIF_TERM; +#else typedef unsigned long ERL_NIF_TERM; +#endif struct enif_environment_t; typedef struct enif_environment_t ErlNifEnv; diff --git a/erts/emulator/beam/erl_node_container_utils.h b/erts/emulator/beam/erl_node_container_utils.h index 87dbfc2a04..ae1316eba2 100644 --- a/erts/emulator/beam/erl_node_container_utils.h +++ b/erts/emulator/beam/erl_node_container_utils.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2001-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -251,7 +251,7 @@ extern int erts_use_r9_pids_ports; * Refs * \* */ -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP #define internal_ref_no_of_numbers(x) \ (internal_ref_data((x))[0]) diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c index 42b28d987c..5865d33138 100644 --- a/erts/emulator/beam/erl_node_tables.c +++ b/erts/emulator/beam/erl_node_tables.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2001-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -1109,10 +1109,23 @@ insert_offheap(ErlOffHeap *oh, int type, Eterm id) break; } if (insert_bin) { - Uint id_heap[BIG_UINT_HEAP_SIZE]; +#if HALFWORD_HEAP + UWord val = (UWord) pb->val; + DeclareTmpHeapNoproc(id_heap,BIG_UINT_HEAP_SIZE*2); /* extra place allocated */ +#else + DeclareTmpHeapNoproc(id_heap,BIG_UINT_HEAP_SIZE); +#endif Uint *hp = &id_heap[0]; InsertedBin *nib; +#if HALFWORD_HEAP + int actual_need = BIG_UWORD_HEAP_SIZE(val); + ASSERT(actual_need <= (BIG_UINT_HEAP_SIZE*2)); + UseTmpHeapNoproc(actual_need); + a.id = erts_bld_uword(&hp, NULL, (UWord) val); +#else + UseTmpHeapNoproc(BIG_UINT_HEAP_SIZE); a.id = erts_bld_uint(&hp, NULL, (Uint) pb->val); +#endif erts_match_prog_foreach_offheap(pb->val, insert_offheap2, (void *) &a); @@ -1120,6 +1133,11 @@ insert_offheap(ErlOffHeap *oh, int type, Eterm id) nib->bin_val = pb->val; nib->next = inserted_bins; inserted_bins = nib; +#if HALFWORD_HEAP + UnUseTmpHeapNoproc(actual_need); +#else + UnUseTmpHeapNoproc(BIG_UINT_HEAP_SIZE); +#endif } } } @@ -1190,12 +1208,15 @@ static void insert_bif_timer(Eterm receiver, Eterm msg, ErlHeapFragment *bp, void *arg) { if (bp) { - Eterm heap[3]; + DeclareTmpHeapNoproc(heap,3); + + UseTmpHeapNoproc(3); insert_offheap(&bp->off_heap, TIMER_REF, (is_internal_pid(receiver) ? receiver : TUPLE2(&heap[0], AM_process, receiver))); + UnUseTmpHeapNoproc(3); } } @@ -1230,7 +1251,7 @@ setup_reference_table(void) DistEntry *dep; HashInfo hi; int i; - Eterm heap[3]; + DeclareTmpHeapNoproc(heap,3); inserted_bins = NULL; @@ -1251,6 +1272,7 @@ setup_reference_table(void) /* Go through the hole system, and build a table of all references to ErlNode and DistEntry structures */ + UseTmpHeapNoproc(3); insert_node(erts_this_node, SYSTEM_REF, TUPLE2(&heap[0], AM_system, am_undefined)); @@ -1261,6 +1283,7 @@ setup_reference_table(void) HEAP_REF, TUPLE2(&heap[0], AM_processes, am_undefined)); #endif + UnUseTmpHeapNoproc(3); /* Insert all processes */ for (i = 0; i < erts_max_processes; i++) diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h index c48dac6219..eb759b87e9 100644 --- a/erts/emulator/beam/erl_node_tables.h +++ b/erts/emulator/beam/erl_node_tables.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2001-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -61,7 +61,7 @@ #define ERTS_DE_QFLGS_ALL (ERTS_DE_QFLG_BUSY \ | ERTS_DE_QFLG_EXIT) -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP #define ERTS_DIST_OUTPUT_BUF_DBG_PATTERN ((Uint) 0xf713f713f713f713UL) #else #define ERTS_DIST_OUTPUT_BUF_DBG_PATTERN ((Uint) 0xf713f713) diff --git a/erts/emulator/beam/erl_printf_term.c b/erts/emulator/beam/erl_printf_term.c index 7fe3f3bca5..d9f132f067 100644 --- a/erts/emulator/beam/erl_printf_term.c +++ b/erts/emulator/beam/erl_printf_term.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2005-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2005-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -246,7 +246,7 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount) if (is_CP(obj)) { PRINT_STRING(res, fn, arg, "<cp/header:"); - PRINT_POINTER(res, fn, arg, obj); + PRINT_POINTER(res, fn, arg, cp_val(obj)); PRINT_CHAR(res, fn, arg, '>'); return res; } @@ -406,7 +406,7 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount) break; case EXPORT_DEF: { - Export* ep = (Export *) (export_val(obj))[1]; + Export* ep = *((Export **) (export_val(obj) + 1)); Atom* module = atom_tab(atom_val(ep->code[0])); Atom* name = atom_tab(atom_val(ep->code[1])); @@ -438,7 +438,7 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount) break; default: PRINT_STRING(res, fn, arg, "<unknown:"); - PRINT_POINTER(res, fn, arg, obj); + PRINT_POINTER(res, fn, arg, (UWord) obj); PRINT_CHAR(res, fn, arg, '>'); break; } diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 996806fc75..11ca85a41c 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -91,9 +91,9 @@ do { \ #define ERTS_EMPTY_RUNQ(RQ) \ ((RQ)->len == 0 && (RQ)->misc.start == NULL) -extern Eterm beam_apply[]; -extern Eterm beam_exit[]; -extern Eterm beam_continue_exit[]; +extern BeamInstr beam_apply[]; +extern BeamInstr beam_exit[]; +extern BeamInstr beam_continue_exit[]; static Sint p_last; static Sint p_next; @@ -334,7 +334,7 @@ do { \ static void init_processes_bif(void); static void save_terminating_process(Process *p); static void exec_misc_ops(ErtsRunQueue *); -static void print_function_from_pc(int to, void *to_arg, Eterm* x); +static void print_function_from_pc(int to, void *to_arg, BeamInstr* x); static int stack_element_dump(int to, void *to_arg, Process* p, Eterm* sp, int yreg); #ifdef ERTS_SMP @@ -2078,9 +2078,9 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) erts_aligned_run_queues = erts_alloc(ERTS_ALC_T_RUNQS, (sizeof(ErtsAlignedRunQueue)*(n+1))); - if ((((Uint) erts_aligned_run_queues) & ERTS_CACHE_LINE_MASK) == 0) + if ((((UWord) erts_aligned_run_queues) & ERTS_CACHE_LINE_MASK) == 0) erts_aligned_run_queues = ((ErtsAlignedRunQueue *) - ((((Uint) erts_aligned_run_queues) + ((((UWord) erts_aligned_run_queues) & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE)); @@ -2175,9 +2175,9 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) erts_aligned_scheduler_data = erts_alloc(ERTS_ALC_T_SCHDLR_DATA, (sizeof(ErtsAlignedSchedulerData) *(n+1))); - if ((((Uint) erts_aligned_scheduler_data) & ERTS_CACHE_LINE_MASK) == 0) + if ((((UWord) erts_aligned_scheduler_data) & ERTS_CACHE_LINE_MASK) == 0) erts_aligned_scheduler_data = ((ErtsAlignedSchedulerData *) - ((((Uint) erts_aligned_scheduler_data) + ((((UWord) erts_aligned_scheduler_data) & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE)); for (ix = 0; ix < n; ix++) { @@ -2186,6 +2186,13 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) erts_bits_init_state(&esdp->erl_bits_state); esdp->match_pseudo_process = NULL; esdp->free_process = NULL; +#if HALFWORD_HEAP + /* Registers need to be heap allocated (correct memory range) for tracing to work */ + esdp->save_reg = erts_alloc(ERTS_ALC_T_BEAM_REGISTER, ERTS_X_REGS_ALLOCATED * sizeof(Eterm)); +#endif +#endif +#if !HEAP_ON_C_STACK + esdp->num_tmp_heap_used = 0; #endif esdp->no = (Uint) ix+1; esdp->current_process = NULL; @@ -4481,7 +4488,7 @@ add_pend_suspend(Process *suspendee, sizeof(ErtsPendingSuspend)); psp->next = NULL; #ifdef DEBUG -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP psp->end = (ErtsPendingSuspend *) 0xdeaddeaddeaddead; #else psp->end = (ErtsPendingSuspend *) 0xdeaddead; @@ -6231,10 +6238,10 @@ Process *schedule(Process *p, int calls) erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN|ERTS_PROC_LOCK_STATUS); if (erts_sched_stat.enabled) { - Uint old = ERTS_PROC_SCHED_ID(p, + UWord old = ERTS_PROC_SCHED_ID(p, (ERTS_PROC_LOCK_MAIN | ERTS_PROC_LOCK_STATUS), - esdp->no); + (UWord) esdp->no); int migrated = old && old != esdp->no; erts_smp_spin_lock(&erts_sched_stat.lock); @@ -6762,8 +6769,8 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->current = p->initial+INITIAL_MOD; - p->i = (Eterm *) beam_apply; - p->cp = (Eterm *) beam_apply+1; + p->i = (BeamInstr *) beam_apply; + p->cp = (BeamInstr *) beam_apply+1; p->arg_reg = p->def_arg_reg; p->max_arg_reg = sizeof(p->def_arg_reg)/sizeof(p->def_arg_reg[0]); @@ -7348,7 +7355,7 @@ set_proc_exiting(Process *p, Eterm reason, ErlHeapFragment *bp) p->freason = EXTAG_EXIT; KILL_CATCHES(p); cancel_timer(p); - p->i = (Eterm *) beam_exit; + p->i = (BeamInstr *) beam_exit; } @@ -7778,9 +7785,10 @@ static void doit_exit_monitor(ErtsMonitor *mon, void *vpcontext) erts_port_release(prt); } else if (is_internal_pid(mon->pid)) {/* local by name or pid */ Eterm watched; - Eterm lhp[3]; + DeclareTmpHeapNoproc(lhp,3); ErtsProcLocks rp_locks = (ERTS_PROC_LOCK_LINK | ERTS_PROC_LOCKS_MSG_SEND); + UseTmpHeapNoproc(3); rp = erts_pid2proc(NULL, 0, mon->pid, rp_locks); if (rp == NULL) { goto done; @@ -7795,6 +7803,7 @@ static void doit_exit_monitor(ErtsMonitor *mon, void *vpcontext) erts_queue_monitor_message(rp, &rp_locks, mon->ref, am_process, watched, pcontext->reason); } + UnUseTmpHeapNoproc(3); /* else: demonitor while we exited, i.e. do nothing... */ erts_smp_proc_unlock(rp, rp_locks); } else { /* external by pid or name */ @@ -8228,11 +8237,12 @@ continue_exit_process(Process *p * Pre-build the EXIT tuple if there are any links. */ if (lnk) { - Eterm tmp_heap[4]; + DeclareTmpHeap(tmp_heap,4,p); Eterm exit_tuple; Uint exit_tuple_sz; Eterm* hp; + UseTmpHeap(4,p); hp = &tmp_heap[0]; exit_tuple = TUPLE3(hp, am_EXIT, p->id, reason); @@ -8243,11 +8253,13 @@ continue_exit_process(Process *p ExitLinkContext context = {p, reason, exit_tuple, exit_tuple_sz}; erts_sweep_links(lnk, &doit_exit_link, &context); } + UnUseTmpHeap(4,p); } { ExitMonitorContext context = {reason, p}; - erts_sweep_monitors(mon,&doit_exit_monitor,&context); + erts_sweep_monitors(mon,&doit_exit_monitor,&context); /* Allocates TmpHeap, but we + have none here */ } if (scb) @@ -8271,7 +8283,7 @@ continue_exit_process(Process *p ASSERT(p->status == P_EXITING); - p->i = (Eterm *) beam_continue_exit; + p->i = (BeamInstr *) beam_continue_exit; if (!(curr_locks & ERTS_PROC_LOCK_STATUS)) { erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS); @@ -8291,7 +8303,7 @@ continue_exit_process(Process *p static void timeout_proc(Process* p) { - p->i = (Eterm *) p->def_arg_reg[0]; + p->i = *((BeamInstr **) (UWord) p->def_arg_reg); p->flags |= F_TIMO; p->flags &= ~F_INSLPQUEUE; @@ -8390,9 +8402,9 @@ erts_program_counter_info(int to, void *to_arg, Process *p) } static void -print_function_from_pc(int to, void *to_arg, Eterm* x) +print_function_from_pc(int to, void *to_arg, BeamInstr* x) { - Eterm* addr = find_function_from_pc(x); + BeamInstr* addr = find_function_from_pc(x); if (addr == NULL) { if (x == beam_exit) { erts_print(to, to_arg, "<terminate process>"); @@ -8426,7 +8438,7 @@ stack_element_dump(int to, void *to_arg, Process* p, Eterm* sp, int yreg) } if (is_CP(x)) { - erts_print(to, to_arg, "Return addr %p (", (Eterm *) x); + erts_print(to, to_arg, "Return addr %p (", (Eterm *) EXPAND_POINTER(x)); print_function_from_pc(to, to_arg, cp_val(x)); erts_print(to, to_arg, ")\n"); yreg = 0; @@ -9255,8 +9267,8 @@ init_processes_bif(void) processes_trap_export.code[0] = am_erlang; processes_trap_export.code[1] = am_processes_trap; processes_trap_export.code[2] = 2; - processes_trap_export.code[3] = (Eterm) em_apply_bif; - processes_trap_export.code[4] = (Eterm) &processes_trap; + processes_trap_export.code[3] = (BeamInstr) em_apply_bif; + processes_trap_export.code[4] = (BeamInstr) &processes_trap; #if ERTS_PROCESSES_BIF_DEBUGLEVEL >= ERTS_PROCS_DBGLVL_CHK_TERM_PROC_LIST erts_get_emu_time(&debug_tv_start); diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index f58b6932b3..cbcdec4ba7 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -179,7 +179,7 @@ extern int erts_sched_thread_suggested_stack_size; #ifdef DEBUG -# ifdef ARCH_64 +# if defined(ARCH_64) && !HALFWORD_HEAP # define ERTS_DBG_SET_INVALID_RUNQP(RQP, N) \ (*((char **) &(RQP)) = (char *) (0xdeadbeefdead0003 | ((N) << 4))) # define ERTS_DBG_VERIFY_VALID_RUNQP(RQP) \ @@ -194,8 +194,8 @@ do { \ # define ERTS_DBG_VERIFY_VALID_RUNQP(RQP) \ do { \ ASSERT((RQP) != NULL); \ - ASSERT(((((Uint) (RQP)) & ((Uint) 1))) == ((Uint) 0)); \ - ASSERT((((Uint) (RQP)) & ~((Uint) 0xffff)) != ((Uint) 0xdead0000)); \ + ASSERT(((((UWord) (RQP)) & ((UWord) 1))) == ((UWord) 0)); \ + ASSERT((((UWord) (RQP)) & ~((UWord) 0xffff)) != ((UWord) 0xdead0000)); \ } while (0) # endif #else @@ -344,13 +344,24 @@ struct ErtsSchedulerData_ { * numbered registers as possible in the same cache * line). */ +#if !HALFWORD_HEAP Eterm save_reg[ERTS_X_REGS_ALLOCATED]; /* X registers */ +#else + Eterm *save_reg; +#endif FloatDef freg[MAX_REG]; /* Floating point registers. */ ethr_tid tid; /* Thread id */ struct erl_bits_state erl_bits_state; /* erl_bits.c state */ void *match_pseudo_process; /* erl_db_util.c:db_prog_match() */ Process *free_process; #endif +#if !HEAP_ON_C_STACK + Eterm tmp_heap[TMP_HEAP_SIZE]; + int num_tmp_heap_used; + Eterm beam_emu_tmp_heap[BEAM_EMU_TMP_HEAP_SIZE]; + Eterm cmp_tmp_heap[CMP_TMP_HEAP_SIZE]; + Eterm erl_arith_tmp_heap[ERL_ARITH_TMP_HEAP_SIZE]; +#endif Process *current_process; Uint no; /* Scheduler number */ @@ -518,8 +529,8 @@ struct process { unsigned max_arg_reg; /* Maximum number of argument registers available. */ Eterm def_arg_reg[6]; /* Default array for argument registers. */ - Eterm* cp; /* Continuation pointer (for threaded code). */ - Eterm* i; /* Program counter for threaded code. */ + BeamInstr* cp; /* (untagged) Continuation pointer (for threaded code). */ + BeamInstr* i; /* Program counter for threaded code. */ Sint catches; /* Number of catches on stack */ Sint fcalls; /* * Number of reductions left to execute. @@ -566,11 +577,12 @@ struct process { Uint seq_trace_lastcnt; Eterm seq_trace_token; /* Sequential trace token (tuple size 5 see below) */ - Eterm initial[3]; /* Initial module(0), function(1), arity(2) */ - Eterm* current; /* Current Erlang function: + BeamInstr initial[3]; /* Initial module(0), function(1), arity(2), often used instead + of pointer to funcinfo instruction, hence the BeamInstr datatype */ + BeamInstr* current; /* Current Erlang function, part of the funcinfo: * module(0), function(1), arity(2) * (module and functions are tagged atoms; - * arity an untagged integer). + * arity an untagged integer). BeamInstr * because it references code */ /* @@ -1184,7 +1196,7 @@ erts_psd_set(Process *p, ErtsProcLocks plocks, int ix, void *data) #endif #define ERTS_PROC_SCHED_ID(P, L, ID) \ - ((Uint) erts_psd_set((P), (L), ERTS_PSD_SCHED_ID, (void *) (ID))) + ((UWord) erts_psd_set((P), (L), ERTS_PSD_SCHED_ID, (void *) (ID))) #define ERTS_PROC_GET_DIST_ENTRY(P) \ ((DistEntry *) erts_psd_get((P), ERTS_PSD_DIST_ENTRY)) @@ -1209,8 +1221,8 @@ erts_proc_get_error_handler(Process *p) if (!val) return am_error_handler; else { - ASSERT(is_atom(((Eterm) val))); - return (Eterm) val; + ASSERT(is_atom(((Eterm) (UWord) val))); + return (Eterm) (UWord) val; } } @@ -1220,13 +1232,13 @@ erts_proc_set_error_handler(Process *p, ErtsProcLocks plocks, Eterm handler) void *old_val; void *new_val; ASSERT(is_atom(handler)); - new_val = handler == am_error_handler ? NULL : (void *) handler; + new_val = (handler == am_error_handler) ? NULL : (void *) (UWord) handler; old_val = erts_psd_set(p, plocks, ERTS_PSD_ERROR_HANDLER, new_val); if (!old_val) return am_error_handler; else { - ASSERT(is_atom(((Eterm) old_val))); - return (Eterm) old_val; + ASSERT(is_atom(((Eterm) (UWord) old_val))); + return (Eterm) (UWord) old_val; } } diff --git a/erts/emulator/beam/erl_process_dump.c b/erts/emulator/beam/erl_process_dump.c index 1666509c72..7a7042abe4 100644 --- a/erts/emulator/beam/erl_process_dump.c +++ b/erts/emulator/beam/erl_process_dump.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2003-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -45,16 +45,16 @@ static void dump_dist_ext(int to, void *to_arg, ErtsDistExternal *edep); static void dump_element_nl(int to, void *to_arg, Eterm x); static int stack_element_dump(int to, void *to_arg, Process* p, Eterm* sp, int yreg); -static void print_function_from_pc(int to, void *to_arg, Eterm* x); +static void print_function_from_pc(int to, void *to_arg, BeamInstr* x); static void heap_dump(int to, void *to_arg, Eterm x); static void dump_binaries(int to, void *to_arg, Binary* root); static void dump_externally(int to, void *to_arg, Eterm term); static Binary* all_binaries; -extern Eterm beam_apply[]; -extern Eterm beam_exit[]; -extern Eterm beam_continue_exit[]; +extern BeamInstr beam_apply[]; +extern BeamInstr beam_exit[]; +extern BeamInstr beam_continue_exit[]; void @@ -223,7 +223,7 @@ stack_element_dump(int to, void *to_arg, Process* p, Eterm* sp, int yreg) } if (is_CP(x)) { - erts_print(to, to_arg, "SReturn addr 0x%X (", (Eterm *) x); + erts_print(to, to_arg, "SReturn addr 0x%X (", cp_val(x)); print_function_from_pc(to, to_arg, cp_val(x)); erts_print(to, to_arg, ")\n"); yreg = 0; @@ -239,9 +239,9 @@ stack_element_dump(int to, void *to_arg, Process* p, Eterm* sp, int yreg) } static void -print_function_from_pc(int to, void *to_arg, Eterm* x) +print_function_from_pc(int to, void *to_arg, BeamInstr* x) { - Eterm* addr = find_function_from_pc(x); + BeamInstr* addr = find_function_from_pc(x); if (addr == NULL) { if (x == beam_exit) { erts_print(to, to_arg, "<terminate process>"); @@ -273,7 +273,7 @@ heap_dump(int to, void *to_arg, Eterm x) if (x == OUR_NIL) { /* We are done. */ return; } if (is_CP(x)) { - next = (Eterm *) x; + next = (Eterm *) EXPAND_POINTER(x); } else if (is_list(x)) { ptr = list_val(x); if (ptr[0] != OUR_NIL) { @@ -286,7 +286,7 @@ heap_dump(int to, void *to_arg, Eterm x) ptr[1] = make_small(0); } x = ptr[0]; - ptr[0] = (Eterm) next; + ptr[0] = (Eterm) COMPRESS_POINTER(next); next = ptr + 1; goto again; } @@ -316,7 +316,7 @@ heap_dump(int to, void *to_arg, Eterm x) ptr[0] = OUR_NIL; } else { x = ptr[arity]; - ptr[0] = (Eterm) next; + ptr[0] = (Eterm) COMPRESS_POINTER(next); next = ptr + arity - 1; goto again; } @@ -351,7 +351,7 @@ heap_dump(int to, void *to_arg, Eterm x) Binary* val = pb->val; if (erts_smp_atomic_xchg(&val->refc, 0) != 0) { - val->flags = (Uint) all_binaries; + val->flags = (UWord) all_binaries; all_binaries = val; } erts_print(to, to_arg, "Yc%X:%X:%X", val, diff --git a/erts/emulator/beam/erl_term.c b/erts/emulator/beam/erl_term.c index 2924abbd51..c6458a0e45 100644 --- a/erts/emulator/beam/erl_term.c +++ b/erts/emulator/beam/erl_term.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2000-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -68,7 +68,9 @@ unsigned tag_val_def(Eterm x) static char msg[32]; switch (x & _TAG_PRIMARY_MASK) { - case TAG_PRIMARY_LIST: return LIST_DEF; + case TAG_PRIMARY_LIST: + ET_ASSERT(_list_precond(x),file,line); + return LIST_DEF; case TAG_PRIMARY_BOXED: { Eterm hdr = *boxed_val(x); ET_ASSERT(is_header(hdr),file,line); @@ -103,7 +105,7 @@ unsigned tag_val_def(Eterm x) break; } } - sprintf(msg, "tag_val_def: %#lx", x); + sprintf(msg, "tag_val_def: %#lx", (unsigned long) x); et_abort(msg, file, line); #undef file #undef line @@ -121,12 +123,12 @@ FUNTY checked_##FUN(ARGTY x, const char *file, unsigned line) \ return _unchecked_##FUN(x); \ } -ET_DEFINE_CHECKED(Eterm,make_boxed,Eterm*,_is_aligned); +ET_DEFINE_CHECKED(Eterm,make_boxed,Eterm*,_is_taggable_pointer); ET_DEFINE_CHECKED(int,is_boxed,Eterm,!is_header); -ET_DEFINE_CHECKED(Eterm*,boxed_val,Eterm,is_boxed); -ET_DEFINE_CHECKED(Eterm,make_list,Eterm*,_is_aligned); +ET_DEFINE_CHECKED(Eterm*,boxed_val,Eterm,_boxed_precond); +ET_DEFINE_CHECKED(Eterm,make_list,Eterm*,_is_taggable_pointer); ET_DEFINE_CHECKED(int,is_not_list,Eterm,!is_header); -ET_DEFINE_CHECKED(Eterm*,list_val,Eterm,is_list); +ET_DEFINE_CHECKED(Eterm*,list_val,Eterm,_list_precond); ET_DEFINE_CHECKED(Uint,unsigned_val,Eterm,is_small); ET_DEFINE_CHECKED(Sint,signed_val,Eterm,is_small); ET_DEFINE_CHECKED(Uint,atom_val,Eterm,is_atom); @@ -163,8 +165,8 @@ ET_DEFINE_CHECKED(Uint32*,external_ref_data,Eterm,is_external_ref); ET_DEFINE_CHECKED(struct erl_node_*,external_ref_node,Eterm,is_external_ref); ET_DEFINE_CHECKED(Eterm*,export_val,Eterm,is_export); -ET_DEFINE_CHECKED(Eterm,make_cp,Uint*,_is_aligned); -ET_DEFINE_CHECKED(Uint*,cp_val,Eterm,is_CP); +ET_DEFINE_CHECKED(Eterm,make_cp,UWord *,_is_taggable_pointer); +ET_DEFINE_CHECKED(UWord *,cp_val,Eterm,is_CP); ET_DEFINE_CHECKED(Uint,catch_val,Eterm,is_catch); ET_DEFINE_CHECKED(Uint,x_reg_offset,Uint,_is_xreg); ET_DEFINE_CHECKED(Uint,y_reg_offset,Uint,_is_yreg); diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h index a6596558fa..3a8c30fe6a 100644 --- a/erts/emulator/beam/erl_term.h +++ b/erts/emulator/beam/erl_term.h @@ -20,6 +20,32 @@ #ifndef __ERL_TERM_H #define __ERL_TERM_H +#include "sys.h" /* defines HALFWORD_HEAP */ + +#if HALFWORD_HEAP +# define HEAP_ON_C_STACK 0 +# if HALFWORD_ASSERT +# ifdef ET_DEBUG +# undef ET_DEBUG +# endif +# define ET_DEBUG 1 +# endif +# if 1 +# define CHECK_POINTER_MASK 0xFFFFFFFF00000000UL +# define COMPRESS_POINTER(APointer) ((Eterm) (UWord) (APointer)) +# define EXPAND_POINTER(AnEterm) ((UWord) (AnEterm)) +# else +# define CHECK_POINTER_MASK 0x0UL +# define COMPRESS_POINTER(AnUint) (AnUint) +# define EXPAND_POINTER(APointer) (APointer) +# endif +#else +# define HEAP_ON_C_STACK 1 +# define CHECK_POINTER_MASK 0x0UL +# define COMPRESS_POINTER(AnUint) (AnUint) +# define EXPAND_POINTER(APointer) (APointer) +#endif + struct erl_node_; /* Declared in erl_node_tables.h */ /* @@ -158,9 +184,16 @@ struct erl_node_; /* Declared in erl_node_tables.h */ /* boxed object access methods */ +#if HALFWORD_HEAP +#define _is_taggable_pointer(x) (((UWord)(x) & (CHECK_POINTER_MASK | 0x3)) == 0) +#define _boxed_precond(x) (is_boxed(x)) +#else +#define _is_taggable_pointer(x) (((Uint)(x) & 0x3) == 0) +#define _boxed_precond(x) (is_boxed(x)) +#endif #define _is_aligned(x) (((Uint)(x) & 0x3) == 0) -#define _unchecked_make_boxed(x) ((Uint)(x) + TAG_PRIMARY_BOXED) -_ET_DECLARE_CHECKED(Eterm,make_boxed,Eterm*) +#define _unchecked_make_boxed(x) ((Uint) COMPRESS_POINTER(x) + TAG_PRIMARY_BOXED) +_ET_DECLARE_CHECKED(Eterm,make_boxed,Eterm*); #define make_boxed(x) _ET_APPLY(make_boxed,(x)) #if 1 #define _is_not_boxed(x) ((x) & (_TAG_PRIMARY_MASK-TAG_PRIMARY_BOXED)) @@ -170,13 +203,13 @@ _ET_DECLARE_CHECKED(int,is_boxed,Eterm) #else #define is_boxed(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_BOXED) #endif -#define _unchecked_boxed_val(x) ((Eterm*)((x) - TAG_PRIMARY_BOXED)) -_ET_DECLARE_CHECKED(Eterm*,boxed_val,Eterm) +#define _unchecked_boxed_val(x) ((Eterm*) EXPAND_POINTER(((x) - TAG_PRIMARY_BOXED))) +_ET_DECLARE_CHECKED(Eterm*,boxed_val,Eterm); #define boxed_val(x) _ET_APPLY(boxed_val,(x)) /* cons cell ("list") access methods */ -#define _unchecked_make_list(x) ((Uint)(x) + TAG_PRIMARY_LIST) -_ET_DECLARE_CHECKED(Eterm,make_list,Eterm*) +#define _unchecked_make_list(x) ((Uint) COMPRESS_POINTER(x) + TAG_PRIMARY_LIST) +_ET_DECLARE_CHECKED(Eterm,make_list,Eterm*); #define make_list(x) _ET_APPLY(make_list,(x)) #if 1 #define _unchecked_is_not_list(x) ((x) & (_TAG_PRIMARY_MASK-TAG_PRIMARY_LIST)) @@ -187,8 +220,13 @@ _ET_DECLARE_CHECKED(int,is_not_list,Eterm) #define is_list(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_LIST) #define is_not_list(x) (!is_list((x))) #endif -#define _unchecked_list_val(x) ((Eterm*)((x) - TAG_PRIMARY_LIST)) -_ET_DECLARE_CHECKED(Eterm*,list_val,Eterm) +#if HALFWORD_HEAP +#define _list_precond(x) (is_list(x)) +#else +#define _list_precond(x) (is_list(x)) +#endif +#define _unchecked_list_val(x) ((Eterm*) EXPAND_POINTER((x) - TAG_PRIMARY_LIST)) +_ET_DECLARE_CHECKED(Eterm*,list_val,Eterm); #define list_val(x) _ET_APPLY(list_val,(x)) #define CONS(hp, car, cdr) \ @@ -198,13 +236,13 @@ _ET_DECLARE_CHECKED(Eterm*,list_val,Eterm) #define CDR(x) ((x)[1]) /* generic tagged pointer (boxed or list) access methods */ -#define _unchecked_ptr_val(x) ((Eterm*)((x) & ~((Uint) 0x3))) +#define _unchecked_ptr_val(x) ((Eterm*) EXPAND_POINTER((x) & ~((Uint) 0x3))) #define ptr_val(x) _unchecked_ptr_val((x)) /*XXX*/ #define _unchecked_offset_ptr(x,offs) ((x)+((offs)*sizeof(Eterm))) #define offset_ptr(x,offs) _unchecked_offset_ptr(x,offs) /*XXX*/ /* fixnum ("small") access methods */ -#if defined(ARCH_64) +#if defined(ARCH_64) && !HALFWORD_HEAP #define SMALL_BITS (64-4) #define SMALL_DIGITS (17) #else @@ -329,7 +367,11 @@ _ET_DECLARE_CHECKED(Eterm*,fun_val,Eterm) _ET_DECLARE_CHECKED(Eterm*,export_val,Eterm) #define export_val(x) _ET_APPLY(export_val,(x)) #define is_export_header(x) ((x) == HEADER_EXPORT) +#if HALFWORD_HEAP +#define HEADER_EXPORT _make_header(2,_TAG_HEADER_EXPORT) +#else #define HEADER_EXPORT _make_header(1,_TAG_HEADER_EXPORT) +#endif /* bignum access methods */ #define make_pos_bignum_header(sz) _make_header((sz),_TAG_HEADER_POS_BIG) @@ -353,7 +395,7 @@ _ET_DECLARE_CHECKED(Eterm*,big_val,Eterm) #define big_val(x) _ET_APPLY(big_val,(x)) /* flonum ("float") access methods */ -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP #define HEADER_FLONUM _make_header(1,_TAG_HEADER_FLOAT) #else #define HEADER_FLONUM _make_header(2,_TAG_HEADER_FLOAT) @@ -374,12 +416,12 @@ typedef union float_def byte fb[sizeof(ieee754_8)]; Uint16 fs[sizeof(ieee754_8) / sizeof(Uint16)]; Uint32 fw[sizeof(ieee754_8) / sizeof(Uint32)]; -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP Uint fdw; #endif } FloatDef; -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP #define GET_DOUBLE(x, f) (f).fdw = *(float_val(x)+1) #define PUT_DOUBLE(f, x) *(x) = HEADER_FLONUM, \ @@ -679,7 +721,7 @@ _ET_DECLARE_CHECKED(struct erl_node_*,internal_port_node,Eterm) #define ERTS_MAX_REF_NUMBERS 3 #define ERTS_REF_NUMBERS ERTS_MAX_REF_NUMBERS -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP # define ERTS_REF_WORDS (ERTS_REF_NUMBERS/2 + 1) # define ERTS_REF_32BIT_WORDS (ERTS_REF_NUMBERS+1) #else @@ -701,7 +743,7 @@ typedef struct { #define make_ref_thing_header(DW) \ _make_header((DW)+REF_THING_HEAD_SIZE-1,_TAG_HEADER_REF) -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP /* * Ref layout on a 64-bit little endian machine: @@ -807,6 +849,11 @@ _ET_DECLARE_CHECKED(struct erl_node_*,internal_ref_node,Eterm) * */ +/* XXX:PaN - this structure is not perfect for halfword heap, it takes + a lot of memory due to padding, and the array will not begin at the end of the + structure, as otherwise expected. Be sure to access data.ui32 array and not try + to do pointer manipulation on an Eterm * to reach the actual data... */ + typedef struct external_thing_ { /* ----+ */ Eterm header; /* | */ @@ -944,15 +991,15 @@ _ET_DECLARE_CHECKED(struct erl_node_*,external_ref_node,Eterm) #error "fix yer arch, like" #endif -#define _unchecked_make_cp(x) ((Eterm)(x)) -_ET_DECLARE_CHECKED(Eterm,make_cp,Uint*) +#define _unchecked_make_cp(x) ((Eterm) COMPRESS_POINTER(x)) +_ET_DECLARE_CHECKED(Eterm,make_cp,BeamInstr*); #define make_cp(x) _ET_APPLY(make_cp,(x)) #define is_not_CP(x) ((x) & _CPMASK) #define is_CP(x) (!is_not_CP(x)) -#define _unchecked_cp_val(x) ((Uint*)(x)) -_ET_DECLARE_CHECKED(Uint*,cp_val,Eterm) +#define _unchecked_cp_val(x) ((BeamInstr*) EXPAND_POINTER(x)) +_ET_DECLARE_CHECKED(BeamInstr*,cp_val,Eterm); #define cp_val(x) _ET_APPLY(cp_val,(x)) #define make_catch(x) (((x) << _TAG_IMMED2_SIZE) | _TAG_IMMED2_CATCH) diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index 2842c2361a..8addfcf5ad 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -397,11 +397,13 @@ WRITE_SYS_MSG_TO_PORT(Eterm unused_to, */ static void do_send_schedfix_to_port(Port *trace_port, Eterm pid, Eterm timestamp) { - Eterm local_heap[4+5+5]; +#define LOCAL_HEAP_SIZE (4+5+5) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); Eterm message; Eterm *hp; Eterm mfarity; + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); ASSERT(is_pid(pid)); ASSERT(is_tuple(timestamp)); ASSERT(*tuple_val(timestamp) == make_arityval(3)); @@ -426,6 +428,8 @@ do_send_schedfix_to_port(Port *trace_port, Eterm pid, Eterm timestamp) { pid, SYS_MSG_TYPE_UNDEFINED, message); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE } #endif @@ -442,7 +446,9 @@ send_to_port(Process *c_p, Eterm message, Eterm *tracer_pid, Uint *tracee_flags) { Port* trace_port; #ifndef ERTS_SMP - Eterm ts, local_heap[4], *hp; +#define LOCAL_HEAP_SIZE (4) + Eterm ts, *hp; + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); #endif ASSERT(is_internal_port(*tracer_pid)); @@ -486,6 +492,8 @@ send_to_port(Process *c_p, Eterm message, * (e.g. getting_linked) need not be the current process. That other * process might not have timestamps enabled. */ + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + if (*tracee_flags & F_TIMESTAMP) { ASSERT(is_tuple(message)); hp = tuple_val(message); @@ -522,6 +530,8 @@ send_to_port(Process *c_p, Eterm message, */ do_send_schedfix_to_port(trace_port, c_p->id, ts); } + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE #endif } @@ -589,7 +599,10 @@ seq_trace_send_to_port(Process *c_p, { Port* trace_port; #ifndef ERTS_SMP - Eterm ts, local_heap[4], *hp; + Eterm ts, *hp; +#define LOCAL_HEAP_SIZE (4) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); #endif ASSERT(is_internal_port(seq_tracer)); @@ -607,6 +620,9 @@ seq_trace_send_to_port(Process *c_p, if (INVALID_TRACER_PORT(trace_port, seq_tracer)) { invalid_tracer_port: system_seq_tracer = am_false; +#ifndef ERTS_SMP + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#endif return; } @@ -620,6 +636,7 @@ seq_trace_send_to_port(Process *c_p, message); #ifndef ERTS_SMP + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); return; } /* Make a fake schedule only if the current process is traced @@ -660,6 +677,8 @@ seq_trace_send_to_port(Process *c_p, */ do_send_schedfix_to_port(trace_port, c_p->id, ts); } + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE #endif } @@ -719,7 +738,8 @@ send_to_tracer(Process *tracee, static void trace_sched_aux(Process *p, Eterm what, int never_fake_sched) { - Eterm local_heap[5+4+1+TS_HEAP_WORDS]; +#define LOCAL_HEAP_SIZE (5+4+1+TS_HEAP_WORDS) + DeclareTmpHeap(local_heap,LOCAL_HEAP_SIZE,p); Eterm tmp, mess, *hp; ErlHeapFragment *bp = NULL; ErlOffHeap *off_heap; @@ -768,8 +788,10 @@ trace_sched_aux(Process *p, Eterm what, int never_fake_sched) curr_func = p->current != NULL; } + UseTmpHeap(LOCAL_HEAP_SIZE,p); + if (to_port) - hp = &local_heap[0]; + hp = local_heap; else { Uint size = 5; if (curr_func) @@ -802,6 +824,8 @@ trace_sched_aux(Process *p, Eterm what, int never_fake_sched) } send_to_tracer(p, tracer_ref, mess, &hp, bp, no_fake_sched); + UnUseTmpHeap(LOCAL_HEAP_SIZE,p); +#undef LOCAL_HEAP_SIZE } /* Send {trace_ts, Pid, What, {Mod, Func, Arity}, Timestamp} @@ -848,7 +872,10 @@ trace_send(Process *p, Eterm to, Eterm msg) } if (is_internal_port(p->tracer_proc)) { - Eterm local_heap[11]; +#define LOCAL_HEAP_SIZE (11) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; mess = TUPLE5(hp, am_trace, p->id, operation, msg, to); hp += 6; @@ -857,6 +884,8 @@ trace_send(Process *p, Eterm to, Eterm msg) hp = patch_ts(mess, hp); } send_to_port(p, mess, &p->tracer_proc, &p->trace_flags); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { Uint need; @@ -908,7 +937,10 @@ trace_receive(Process *rp, Eterm msg) Eterm* hp; if (is_internal_port(rp->tracer_proc)) { - Eterm local_heap[10]; +#define LOCAL_HEAP_SIZE (10) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; mess = TUPLE4(hp, am_trace, rp->id, am_receive, msg); hp += 5; @@ -917,6 +949,8 @@ trace_receive(Process *rp, Eterm msg) hp = patch_ts(mess, hp); } send_to_port(rp, mess, &rp->tracer_proc, &rp->trace_flags); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { Uint hsz; @@ -1018,7 +1052,10 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type, } if (is_internal_port(seq_tracer)) { - Eterm local_heap[64]; +#define LOCAL_HEAP_SIZE (64) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; label = SEQ_TRACE_T_LABEL(token); lastcnt_serial = TUPLE2(hp, SEQ_TRACE_T_LASTCNT(token), @@ -1043,6 +1080,8 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type, mess = TUPLE4(hp, am_seq_trace, label, mess, ts); seq_trace_send_to_port(process, seq_tracer, mess, ts); } + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { #ifndef ERTS_SMP @@ -1143,14 +1182,18 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type, * or {trace, Pid, return_to, {Mod, Func, Arity}} */ void -erts_trace_return_to(Process *p, Uint *pc) +erts_trace_return_to(Process *p, BeamInstr *pc) { +#define LOCAL_HEAP_SIZE (4+5+5) Eterm* hp; Eterm mfa; Eterm mess; - Eterm local_heap[4+5+5]; + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); - Eterm *code_ptr = find_function_from_pc(pc); + BeamInstr *code_ptr = find_function_from_pc(pc); + + + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); hp = local_heap; @@ -1196,6 +1239,8 @@ erts_trace_return_to(Process *p, Uint *pc) mess = copy_struct(mess, size, &hp, off_heap); ERTS_ENQ_TRACE_MSG(p->id, tracer_ref, mess, bp); } + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } @@ -1204,7 +1249,7 @@ erts_trace_return_to(Process *p, Uint *pc) * or {trace, Pid, return_from, {Mod, Name, Arity}, Retval} */ void -erts_trace_return(Process* p, Eterm* fi, Eterm retval, Eterm *tracer_pid) +erts_trace_return(Process* p, BeamInstr* fi, Eterm retval, Eterm *tracer_pid) { Eterm* hp; Eterm mfa; @@ -1262,7 +1307,9 @@ erts_trace_return(Process* p, Eterm* fi, Eterm retval, Eterm *tracer_pid) arity = fi[2]; if (is_internal_port(*tracer_pid)) { - Eterm local_heap[4+6+5]; +#define LOCAL_HEAP_SIZE (4+6+5) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); hp = local_heap; mfa = TUPLE3(hp, mod, name, make_small(arity)); hp += 4; @@ -1273,6 +1320,8 @@ erts_trace_return(Process* p, Eterm* fi, Eterm retval, Eterm *tracer_pid) hp = patch_ts(mess, hp); } send_to_port(p, mess, tracer_pid, tracee_flags); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { ErlHeapFragment *bp; @@ -1331,7 +1380,7 @@ erts_trace_return(Process* p, Eterm* fi, Eterm retval, Eterm *tracer_pid) * Where Class is atomic but Value is any term. */ void -erts_trace_exception(Process* p, Eterm mfa[3], Eterm class, Eterm value, +erts_trace_exception(Process* p, BeamInstr mfa[3], Eterm class, Eterm value, Eterm *tracer_pid) { Eterm* hp; @@ -1385,21 +1434,26 @@ erts_trace_exception(Process* p, Eterm mfa[3], Eterm class, Eterm value, } if (is_internal_port(*tracer_pid)) { - Eterm local_heap[4+3+6+5]; +#define LOCAL_HEAP_SIZE (4+3+6+5) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; - mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], make_small(mfa[2])); + mfa_tuple = TUPLE3(hp, (Eterm) mfa[0], (Eterm) mfa[1], make_small((Eterm)mfa[2])); hp += 4; cv = TUPLE2(hp, class, value); hp += 3; mess = TUPLE5(hp, am_trace, p->id, am_exception_from, mfa_tuple, cv); hp += 6; - ASSERT((hp - local_heap)*sizeof(*hp) <= sizeof(local_heap)); + ASSERT((hp - local_heap) <= LOCAL_HEAP_SIZE); erts_smp_mtx_lock(&smq_mtx); if (*tracee_flags & F_TIMESTAMP) { hp = patch_ts(mess, hp); /* hp += 5 */ - ASSERT((hp - local_heap)*sizeof(*hp) == sizeof(local_heap)); + ASSERT((hp - local_heap) == LOCAL_HEAP_SIZE); } send_to_port(p, mess, tracer_pid, tracee_flags); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { ErlHeapFragment *bp; @@ -1431,7 +1485,7 @@ erts_trace_exception(Process* p, Eterm mfa[3], Eterm class, Eterm value, * Build the trace tuple and put it into receive queue of the tracer process. */ - mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], make_small(mfa[2])); + mfa_tuple = TUPLE3(hp, (Eterm) mfa[0], (Eterm) mfa[1], make_small((Eterm) mfa[2])); hp += 4; value = copy_struct(value, value_size, &hp, off_heap); cv = TUPLE2(hp, class, value); @@ -1468,7 +1522,7 @@ erts_trace_exception(Process* p, Eterm mfa[3], Eterm class, Eterm value, * if it is a pid or port we do a meta trace. */ Uint32 -erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, +erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec, Eterm* args, int local, Eterm *tracer_pid) { Eterm* hp; @@ -1483,7 +1537,8 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, Eterm tracee; #endif Eterm transformed_args[MAX_ARG]; - ErlSubBin sub_bin_heap; + DeclareTmpHeap(sub_bin_heap_et,ERL_SUB_BIN_SIZE,p); + ErlSubBin *sub_bin_heap = (ErlSubBin *) sub_bin_heap_et; ASSERT(tracer_pid); if (*tracer_pid == am_true) { @@ -1534,19 +1589,20 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, * such as size_object() and copy_struct(), we must make sure that we * temporarily convert any match contexts to sub binaries. */ - arity = mfa[2]; + arity = (Eterm) mfa[2]; + UseTmpHeap(ERL_SUB_BIN_SIZE,p); #ifdef DEBUG - sub_bin_heap.thing_word = 0; + sub_bin_heap->thing_word = 0; #endif for (i = 0; i < arity; i++) { Eterm arg = args[i]; if (is_boxed(arg) && header_is_bin_matchstate(*boxed_val(arg))) { ErlBinMatchState* ms = (ErlBinMatchState *) boxed_val(arg); ErlBinMatchBuffer* mb = &ms->mb; - ErlSubBin* sb = &sub_bin_heap; + ErlSubBin* sb = sub_bin_heap; Uint bit_size; - ASSERT(sub_bin_heap.thing_word == 0); /* At most one of match context */ + ASSERT(sub_bin_heap->thing_word == 0); /* At most one of match context */ bit_size = mb->size - mb->offset; sb->thing_word = HEADER_SUB_BIN; @@ -1564,7 +1620,12 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, args = transformed_args; if (is_internal_port(*tracer_pid)) { +#if HEAP_ON_C_STACK Eterm local_heap[64+MAX_ARG]; +#else + Eterm *local_heap = erts_alloc(ERTS_ALC_T_TEMP_TERM, + sizeof(Eterm)*(64+MAX_ARG)); +#endif hp = local_heap; if (!erts_is_valid_tracer_port(*tracer_pid)) { @@ -1579,6 +1640,10 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, if (is_not_nil(tracee)) erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR); #endif +#if !HEAP_ON_C_STACK + erts_free(ERTS_ALC_T_TEMP_TERM,local_heap); +#endif + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return 0; } @@ -1605,6 +1670,10 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, &return_flags); if (is_non_value(pam_result)) { erts_match_set_release_result(p); +#if !HEAP_ON_C_STACK + erts_free(ERTS_ALC_T_TEMP_TERM,local_heap); +#endif + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return 0; } } @@ -1612,16 +1681,28 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, /* Meta trace */ if (pam_result == am_false) { erts_match_set_release_result(p); +#if !HEAP_ON_C_STACK + erts_free(ERTS_ALC_T_TEMP_TERM,local_heap); +#endif + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return return_flags; } } else { /* Non-meta trace */ if (*tracee_flags & F_TRACE_SILENT) { erts_match_set_release_result(p); +#if !HEAP_ON_C_STACK + erts_free(ERTS_ALC_T_TEMP_TERM,local_heap); +#endif + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return 0; } if (pam_result == am_false) { erts_match_set_release_result(p); +#if !HEAP_ON_C_STACK + erts_free(ERTS_ALC_T_TEMP_TERM,local_heap); +#endif + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return return_flags; } if (local && (*tracee_flags & F_TRACE_RETURN_TO)) { @@ -1644,7 +1725,7 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, hp += 2; } } - mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], mfa_tuple); + mfa_tuple = TUPLE3(hp, (Eterm) mfa[0], (Eterm) mfa[1], mfa_tuple); hp += 4; /* @@ -1664,6 +1745,10 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, send_to_port(p, mess, tracer_pid, tracee_flags); erts_smp_mtx_unlock(&smq_mtx); erts_match_set_release_result(p); +#if !HEAP_ON_C_STACK + erts_free(ERTS_ALC_T_TEMP_TERM,local_heap); +#endif + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return *tracer_pid == NIL ? 0 : return_flags; } else { @@ -1706,6 +1791,7 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, if (is_not_nil(tracee)) erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR); #endif + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return 0; } @@ -1731,6 +1817,7 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, &return_flags); if (is_non_value(pam_result)) { erts_match_set_release_result(p); + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return 0; } } @@ -1738,16 +1825,19 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, /* Meta trace */ if (pam_result == am_false) { erts_match_set_release_result(p); + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return return_flags; } } else { /* Non-meta trace */ if (*tracee_flags & F_TRACE_SILENT) { erts_match_set_release_result(p); + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return 0; } if (pam_result == am_false) { erts_match_set_release_result(p); + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return return_flags; } if (local && (*tracee_flags & F_TRACE_RETURN_TO)) { @@ -1798,7 +1888,7 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, hp += 2; } } - mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], mfa_tuple); + mfa_tuple = TUPLE3(hp, (Eterm) mfa[0], (Eterm) mfa[1], mfa_tuple); hp += 4; /* @@ -1831,6 +1921,7 @@ erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, ASSERT(hp == limit); ERTS_ENQ_TRACE_MSG(tracee, tracer_ref, mess, bp); erts_smp_mtx_unlock(&smq_mtx); + UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); return return_flags; } } @@ -1851,7 +1942,10 @@ trace_proc(Process *c_p, Process *t_p, Eterm what, Eterm data) int need; if (is_internal_port(t_p->tracer_proc)) { - Eterm local_heap[5+5]; +#define LOCAL_HEAP_SIZE (5+5) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; mess = TUPLE4(hp, am_trace, t_p->id, what, data); hp += 5; @@ -1868,6 +1962,8 @@ trace_proc(Process *c_p, Process *t_p, Eterm what, Eterm data) c_p, #endif mess, &t_p->tracer_proc, &t_p->trace_flags); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { Eterm tmp; @@ -1919,7 +2015,10 @@ trace_proc_spawn(Process *p, Eterm pid, Eterm* hp; if (is_internal_port(p->tracer_proc)) { - Eterm local_heap[4+6+5]; +#define LOCAL_HEAP_SIZE (4+6+5) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; mfa = TUPLE3(hp, mod, func, args); hp += 4; @@ -1930,6 +2029,8 @@ trace_proc_spawn(Process *p, Eterm pid, hp = patch_ts(mess, hp); } send_to_port(p, mess, &p->tracer_proc, &p->trace_flags); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { Eterm tmp; @@ -1991,7 +2092,7 @@ void save_calls(Process *p, Export *e) */ Eterm erts_bif_trace(int bif_index, Process* p, - Eterm arg1, Eterm arg2, Eterm arg3, Uint *I) + Eterm arg1, Eterm arg2, Eterm arg3, BeamInstr *I) { Eterm result; int meta = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_META); @@ -2005,10 +2106,10 @@ erts_bif_trace(int bif_index, Process* p, * no tracing will occur. Doing the whole else branch will * also do nothing, only slower. */ - Eterm (*func)(Process*, Eterm, Eterm, Eterm, Uint*) = bif_table[bif_index].f; + Eterm (*func)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = bif_table[bif_index].f; result = func(p, arg1, arg2, arg3, I); } else { - Eterm (*func)(Process*, Eterm, Eterm, Eterm, Uint*); + Eterm (*func)(Process*, Eterm, Eterm, Eterm, BeamInstr*); Export* ep = bif_export[bif_index]; Uint32 flags = 0, flags_meta = 0; int global = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_GLOBAL); @@ -2017,16 +2118,9 @@ erts_bif_trace(int bif_index, Process* p, int applying = (I == &(ep->code[3])); /* Yup, the apply code for a bif * is actually in the * export entry */ - Eterm *cp = p->cp; + BeamInstr *cp = p->cp; -#ifndef _OSE_ Eterm args[3] = {arg1, arg2, arg3}; -#else - Eterm args[3]; - args[0] = arg1; - args[1] = arg2; - args[2] = arg3; -#endif /* * Make continuation pointer OK, it is not during direct BIF calls, @@ -2056,12 +2150,11 @@ erts_bif_trace(int bif_index, Process* p, Eterm *cpp; /* Maybe advance cp to skip trace stack frames */ for (cpp = p->stop; ; cp = cp_val(*cpp++)) { - ASSERT(is_CP((Eterm) cp)); - if (*cp_val((Eterm) cp) == i_return_trace) { + if (*cp == i_return_trace) { /* Skip stack frame variables */ while (is_not_CP(*cpp)) cpp++; cpp += 2; /* Skip return_trace parameters */ - } else if (*cp_val((Eterm) cp) == i_return_to_trace) { + } else if (*cp == i_return_to_trace) { /* A return_to trace message is going to be generated * by normal means, so we do not have to. */ @@ -2078,7 +2171,8 @@ erts_bif_trace(int bif_index, Process* p, if (reason != TRAP) { Eterm class; Eterm value = p->fvalue; - Eterm nocatch[3]; + DeclareTmpHeapNoproc(nocatch,3); + UseTmpHeapNoproc(3); /* Expand error value like in handle_error() */ if (reason & EXF_ARGLIST) { Eterm *tp; @@ -2126,6 +2220,7 @@ erts_bif_trace(int bif_index, Process* p, } } } + UnUseTmpHeapNoproc(3); if ((flags_meta|flags) & MATCH_SET_EXCEPTION_TRACE) { erts_smp_proc_lock(p, ERTS_PROC_LOCKS_ALL_MINOR); p->trace_flags |= F_EXCEPTION_TRACE; @@ -2213,15 +2308,19 @@ trace_gc(Process *p, Eterm what) BIN_OLD_VHEAP(p), BIN_OLD_VHEAP_SZ(p) }; - Eterm local_heap[(sizeof(values)/sizeof(Uint)) - *(2/*cons*/ + 3/*2-tuple*/ + BIG_UINT_HEAP_SIZE) - + 5/*4-tuple */ + TS_HEAP_WORDS]; +#define LOCAL_HEAP_SIZE \ + (sizeof(values)/sizeof(Eterm)) * \ + (2/*cons*/ + 3/*2-tuple*/ + BIG_UINT_HEAP_SIZE) + \ + 5/*4-tuple */ + TS_HEAP_WORDS + DeclareTmpHeap(local_heap,LOCAL_HEAP_SIZE,p); #ifdef DEBUG Eterm* limit; #endif ASSERT(sizeof(values)/sizeof(Uint) == sizeof(tags)/sizeof(Eterm)); + UseTmpHeap(LOCAL_HEAP_SIZE,p); + if (is_internal_port(p->tracer_proc)) { hp = local_heap; #ifdef DEBUG @@ -2252,7 +2351,7 @@ trace_gc(Process *p, Eterm what) #ifdef DEBUG limit = hp + size; - ASSERT(size <= sizeof(local_heap)/sizeof(Eterm)); + ASSERT(size <= LOCAL_HEAP_SIZE); #endif msg = erts_bld_atom_uint_2tup_list(&hp, @@ -2275,6 +2374,8 @@ trace_gc(Process *p, Eterm what) else ERTS_ENQ_TRACE_MSG(p->id, tracer_ref, msg, bp); erts_smp_mtx_unlock(&smq_mtx); + UnUseTmpHeap(LOCAL_HEAP_SIZE,p); +#undef LOCAL_HEAP_SIZE } @@ -2465,7 +2566,9 @@ profile_scheduler(Eterm scheduler_id, Eterm state) { Uint Ms, s, us; #ifndef ERTS_SMP - Eterm local_heap[4 + 7]; +#define LOCAL_HEAP_SIZE (4 + 7) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); hp = local_heap; #else ErlHeapFragment *bp; @@ -2498,6 +2601,8 @@ profile_scheduler(Eterm scheduler_id, Eterm state) { #ifndef ERTS_SMP profile_send(msg); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE #else enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp); #endif @@ -2510,7 +2615,10 @@ profile_scheduler_q(Eterm scheduler_id, Eterm state, Eterm no_schedulers, Uint M Eterm *hp, msg, timestamp; #ifndef ERTS_SMP - Eterm local_heap[4 + 7]; +#define LOCAL_HEAP_SIZE (4 + 7) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; #else ErlHeapFragment *bp; @@ -2528,6 +2636,8 @@ profile_scheduler_q(Eterm scheduler_id, Eterm state, Eterm no_schedulers, Uint M msg = TUPLE6(hp, am_profile, am_scheduler, scheduler_id, state, no_schedulers, timestamp); hp += 7; #ifndef ERTS_SMP profile_send(msg); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE #else enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp); #endif @@ -2558,7 +2668,10 @@ trace_port_open(Port *p, Eterm calling_pid, Eterm drv_name) { Eterm* hp; if (is_internal_port(p->tracer_proc)) { - Eterm local_heap[5+6]; +#define LOCAL_HEAP_SIZE (5+6) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; mess = TUPLE5(hp, am_trace, calling_pid, am_open, p->id, drv_name); @@ -2569,6 +2682,8 @@ trace_port_open(Port *p, Eterm calling_pid, Eterm drv_name) { } /* No fake schedule */ send_to_port(NULL, mess, &p->tracer_proc, &p->trace_flags); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { ErlHeapFragment *bp; @@ -2613,7 +2728,10 @@ trace_port(Port *t_p, Eterm what, Eterm data) { Eterm* hp; if (is_internal_port(t_p->tracer_proc)) { - Eterm local_heap[5+5]; +#define LOCAL_HEAP_SIZE (5+5) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; mess = TUPLE4(hp, am_trace, t_p->id, what, data); hp += 5; @@ -2623,6 +2741,8 @@ trace_port(Port *t_p, Eterm what, Eterm data) { } /* No fake schedule */ send_to_port(NULL, mess, &t_p->tracer_proc, &t_p->trace_flags); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { ErlHeapFragment *bp; @@ -2674,7 +2794,10 @@ trace_sched_ports_where(Port *p, Eterm what, Eterm where) { Eterm sched_id = am_undefined; if (is_internal_port(p->tracer_proc)) { - Eterm local_heap[5+6]; +#define LOCAL_HEAP_SIZE (5+6) + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; if (IS_TRACED_FL(p, F_TRACE_SCHED_NO)) { @@ -2700,6 +2823,8 @@ trace_sched_ports_where(Port *p, Eterm what, Eterm where) { /* No fake scheduling */ send_to_port(NULL, mess, &p->tracer_proc, &p->trace_flags); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE erts_smp_mtx_unlock(&smq_mtx); } else { ErlHeapFragment *bp; @@ -2750,7 +2875,11 @@ profile_runnable_port(Port *p, Eterm status) { Eterm count = make_small(0); #ifndef ERTS_SMP - Eterm local_heap[4 + 6]; +#define LOCAL_HEAP_SIZE (4 + 6) + + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; #else @@ -2771,6 +2900,8 @@ profile_runnable_port(Port *p, Eterm status) { #ifndef ERTS_SMP profile_send(msg); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE #else enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp); #endif @@ -2785,7 +2916,11 @@ profile_runnable_proc(Process *p, Eterm status){ Eterm where = am_undefined; #ifndef ERTS_SMP - Eterm local_heap[4 + 6 + 4]; +#define LOCAL_HEAP_SIZE (4 + 6 + 4) + + DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); + UseTmpHeapNoproc(LOCAL_HEAP_SIZE); + hp = local_heap; #else ErlHeapFragment *bp; @@ -2818,6 +2953,8 @@ profile_runnable_proc(Process *p, Eterm status){ msg = TUPLE5(hp, am_profile, p->id, status, where, timestamp); hp += 6; #ifndef ERTS_SMP profile_send(msg); + UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); +#undef LOCAL_HEAP_SIZE #else enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp); #endif diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c index ab5811c70f..d01a3661f9 100644 --- a/erts/emulator/beam/erl_unicode.c +++ b/erts/emulator/beam/erl_unicode.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2008-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2008-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -90,9 +90,9 @@ void erts_init_unicode(void) am_atom_put("characters_to_utf8_trap",23); characters_to_utf8_trap_exp.code[2] = 3; characters_to_utf8_trap_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; characters_to_utf8_trap_exp.code[4] = - (Eterm) &characters_to_utf8_trap; + (BeamInstr) &characters_to_utf8_trap; memset(&characters_to_list_trap_1_exp, 0, sizeof(Export)); characters_to_list_trap_1_exp.address = @@ -102,9 +102,9 @@ void erts_init_unicode(void) am_atom_put("characters_to_list_trap_1",25); characters_to_list_trap_1_exp.code[2] = 3; characters_to_list_trap_1_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; characters_to_list_trap_1_exp.code[4] = - (Eterm) &characters_to_list_trap_1; + (BeamInstr) &characters_to_list_trap_1; memset(&characters_to_list_trap_2_exp, 0, sizeof(Export)); characters_to_list_trap_2_exp.address = @@ -114,9 +114,9 @@ void erts_init_unicode(void) am_atom_put("characters_to_list_trap_2",25); characters_to_list_trap_2_exp.code[2] = 3; characters_to_list_trap_2_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; characters_to_list_trap_2_exp.code[4] = - (Eterm) &characters_to_list_trap_2; + (BeamInstr) &characters_to_list_trap_2; memset(&characters_to_list_trap_3_exp, 0, sizeof(Export)); @@ -127,9 +127,9 @@ void erts_init_unicode(void) am_atom_put("characters_to_list_trap_3",25); characters_to_list_trap_3_exp.code[2] = 3; characters_to_list_trap_3_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; characters_to_list_trap_3_exp.code[4] = - (Eterm) &characters_to_list_trap_3; + (BeamInstr) &characters_to_list_trap_3; memset(&characters_to_list_trap_4_exp, 0, sizeof(Export)); characters_to_list_trap_4_exp.address = @@ -139,9 +139,9 @@ void erts_init_unicode(void) am_atom_put("characters_to_list_trap_4",25); characters_to_list_trap_4_exp.code[2] = 1; characters_to_list_trap_4_exp.code[3] = - (Eterm) em_apply_bif; + (BeamInstr) em_apply_bif; characters_to_list_trap_4_exp.code[4] = - (Eterm) &characters_to_list_trap_4; + (BeamInstr) &characters_to_list_trap_4; c_to_b_int_trap_exportp = erts_export_put(am_unicode,am_characters_to_binary_int,2); c_to_l_int_trap_exportp = erts_export_put(am_unicode,am_characters_to_list_int,2); diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h index 50b3e5b61c..235bd7931d 100644 --- a/erts/emulator/beam/erl_vm.h +++ b/erts/emulator/beam/erl_vm.h @@ -50,6 +50,15 @@ #define MAX_ARG 256 /* Max number of arguments allowed */ #define MAX_REG 1024 /* Max number of x(N) registers used */ +/* Scheduler stores data for temporary heaps if + !HEAP_ON_C_STACK. Macros (*TmpHeap*) in global.h selects if we put temporary + heap data on the C stack or if we use the buffers in the scheduler data. */ +#define TMP_HEAP_SIZE 128 /* Number of Eterm in the schedulers + small heap for transient heap data */ +#define CMP_TMP_HEAP_SIZE 2 /* cmp wants its own tmp-heap... */ +#define ERL_ARITH_TMP_HEAP_SIZE 4 /* as does erl_arith... */ +#define BEAM_EMU_TMP_HEAP_SIZE 2 /* and beam_emu... */ + /* * The new arithmetic operations need some extra X registers in the register array. */ @@ -130,8 +139,12 @@ #define HeapWordsLeft(p) (HEAP_LIMIT(p) - HEAP_TOP(p)) #if defined(DEBUG) || defined(CHECK_FOR_HOLES) +#if HALFWORD_HEAP +# define ERTS_HOLE_MARKER (0xaf5e78ccU) +#else # define ERTS_HOLE_MARKER (((0xaf5e78ccUL << 24) << 8) | 0xaf5e78ccUL) #endif +#endif /* * Allocate heap memory on the ordinary heap, NEVER in a heap diff --git a/erts/emulator/beam/error.h b/erts/emulator/beam/error.h index 4930def4ed..ddc2c1396d 100644 --- a/erts/emulator/beam/error.h +++ b/erts/emulator/beam/error.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -187,10 +187,10 @@ extern Eterm exception_tag[NUMBER_EXC_TAGS]; struct StackTrace { Eterm header; /* bignum header - must be first in struct */ Eterm freason; /* original exception reason is saved in the struct */ - Eterm* pc; - Eterm* current; + BeamInstr* pc; + BeamInstr* current; int depth; /* number of saved pointers in trace[] */ - Eterm *trace[1]; /* varying size - must be last in struct */ + BeamInstr *trace[1]; /* varying size - must be last in struct */ }; #endif /* __ERROR_H__ */ diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c index 271b40cf0f..66b05c0e9d 100644 --- a/erts/emulator/beam/export.c +++ b/erts/emulator/beam/export.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -46,8 +46,8 @@ static erts_smp_rwmtx_t export_table_lock; /* Locks the secondary export table. #define export_init_lock() erts_smp_rwmtx_init(&export_table_lock, \ "export_tab") -extern Eterm* em_call_error_handler; -extern Uint* em_call_traced_function; +extern BeamInstr* em_call_error_handler; +extern BeamInstr* em_call_traced_function; void export_info(int to, void *to_arg) @@ -93,7 +93,7 @@ export_alloc(Export* tmpl) obj->code[2] = tmpl->code[2]; obj->slot.index = -1; obj->address = obj->code+3; - obj->code[3] = (Eterm) em_call_error_handler; + obj->code[3] = (BeamInstr) em_call_error_handler; obj->code[4] = 0; obj->match_prog_set = NULL; return obj; @@ -140,7 +140,7 @@ init_export_table(void) Export* erts_find_export_entry(Eterm m, Eterm f, unsigned int a) { - HashValue hval = EXPORT_HASH(m, f, a); + HashValue hval = EXPORT_HASH((BeamInstr) m, (BeamInstr) f, (BeamInstr) a); int ix; HashBucket* b; @@ -185,7 +185,7 @@ erts_find_function(Eterm m, Eterm f, unsigned int a) ep = hash_get(&export_table.htable, (void*) &e); if (ep != NULL && ep->address == ep->code+3 && - ep->code[3] != (Uint) em_call_traced_function) { + ep->code[3] != (BeamInstr) em_call_traced_function) { ep = NULL; } return ep; diff --git a/erts/emulator/beam/export.h b/erts/emulator/beam/export.h index cd6af6dd85..87c1d483f4 100644 --- a/erts/emulator/beam/export.h +++ b/erts/emulator/beam/export.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -52,7 +52,11 @@ typedef struct export * on_load function that has not been run yet. * Otherwise: 0. */ +#if HALFWORD_HEAP + BeamInstr code[5]; +#else Eterm code[5]; +#endif } Export; @@ -74,6 +78,6 @@ Export *export_get(Export*); #include "beam_load.h" /* For em_* extern declarations */ #define ExportIsBuiltIn(EntryPtr) \ (((EntryPtr)->address == (EntryPtr)->code + 3) && \ - ((EntryPtr)->code[3] == (Uint) em_apply_bif)) + ((EntryPtr)->code[3] == (BeamInstr) em_apply_bif)) #endif diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 099eddd195..f41b61d73d 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -1489,20 +1489,28 @@ dec_pid(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Ete static byte* enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags) { - DECLARE_ESTACK(s); + DECLARE_WSTACK(s); Uint n; Uint i; Uint j; Uint* ptr; Eterm val; FloatDef f; +#if HALFWORD_HEAP + UWord wobj; +#endif + goto L_jump_start; outer_loop: - while (!ESTACK_ISEMPTY(s)) { - obj = ESTACK_POP(s); - switch (val = ESTACK_POP(s)) { + while (!WSTACK_ISEMPTY(s)) { +#if HALFWORD_HEAP + obj = (Eterm) (wobj = WSTACK_POP(s)); +#else + obj = WSTACK_POP(s); +#endif + switch (val = WSTACK_POP(s)) { case ENC_TERM: break; case ENC_ONE_CONS: @@ -1513,29 +1521,40 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags) obj = CAR(cons); tl = CDR(cons); - ESTACK_PUSH(s, is_list(tl) ? ENC_ONE_CONS : ENC_TERM); - ESTACK_PUSH(s, tl); + WSTACK_PUSH(s, is_list(tl) ? ENC_ONE_CONS : ENC_TERM); + WSTACK_PUSH(s, tl); } break; case ENC_PATCH_FUN_SIZE: { +#if HALFWORD_HEAP + byte* size_p = (byte *) wobj; +#else byte* size_p = (byte *) obj; - +#endif put_int32(ep - size_p, size_p); } goto outer_loop; case ENC_LAST_ARRAY_ELEMENT: { +#if HALFWORD_HEAP + Eterm* ptr = (Eterm *) wobj; +#else Eterm* ptr = (Eterm *) obj; +#endif obj = *ptr; } break; default: /* ENC_LAST_ARRAY_ELEMENT+1 and upwards */ { +#if HALFWORD_HEAP + Eterm* ptr = (Eterm *) wobj; +#else Eterm* ptr = (Eterm *) obj; +#endif obj = *ptr++; - ESTACK_PUSH(s, val-1); - ESTACK_PUSH(s, (Eterm) ptr); + WSTACK_PUSH(s, val-1); + WSTACK_PUSH(s, (UWord) ptr); } break; } @@ -1563,8 +1582,10 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags) put_int32(val, ep); ep += 4; } else { - Eterm tmp_big[2]; - Eterm big = small_to_big(val, tmp_big); + DeclareTmpHeapNoproc(tmp_big,2); + Eterm big; + UseTmpHeapNoproc(2); + big = small_to_big(val, tmp_big); *ep++ = SMALL_BIG_EXT; n = big_bytes(big); ASSERT(n < 256); @@ -1572,6 +1593,7 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags) ep += 1; *ep++ = big_sign(big); ep = big_to_bytes(big, ep); + UnUseTmpHeapNoproc(2); } } break; @@ -1662,8 +1684,8 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags) ep += 4; } if (i > 0) { - ESTACK_PUSH(s, ENC_LAST_ARRAY_ELEMENT+i-1); - ESTACK_PUSH(s, (Eterm) ptr); + WSTACK_PUSH(s, ENC_LAST_ARRAY_ELEMENT+i-1); + WSTACK_PUSH(s, (UWord) ptr); } break; @@ -1741,7 +1763,7 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags) } case EXPORT_DEF: { - Export* exp = (Export *) (export_val(obj))[1]; + Export* exp = *((Export **) (export_val(obj) + 1)); if ((dflags & DFLAG_EXPORT_PTR_TAG) != 0) { *ep++ = EXPORT_EXT; ep = enc_atom(acmp, exp->code[0], ep, dflags); @@ -1770,8 +1792,8 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags) int ei; *ep++ = NEW_FUN_EXT; - ESTACK_PUSH(s, ENC_PATCH_FUN_SIZE); - ESTACK_PUSH(s, (Eterm) ep); /* Position for patching in size */ + WSTACK_PUSH(s, ENC_PATCH_FUN_SIZE); + WSTACK_PUSH(s, (UWord) ep); /* Position for patching in size */ ep += 4; *ep = funp->arity; ep += 1; @@ -1788,8 +1810,8 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags) fun_env: for (ei = funp->num_free-1; ei > 0; ei--) { - ESTACK_PUSH(s, ENC_TERM); - ESTACK_PUSH(s, funp->env[ei]); + WSTACK_PUSH(s, ENC_TERM); + WSTACK_PUSH(s, (UWord) funp->env[ei]); } if (funp->num_free != 0) { obj = funp->env[0]; @@ -1832,7 +1854,7 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags) break; } } - DESTROY_ESTACK(s); + DESTROY_WSTACK(s); return ep; } @@ -1952,11 +1974,11 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et register Eterm* hp = *hpp; /* Please don't take the address of hp */ Eterm* next = objp; - *next = (Eterm) NULL; + *next = (Eterm) (UWord) NULL; while (next != NULL) { objp = next; - next = (Eterm *) (*objp); + next = (Eterm *) EXPAND_POINTER(*objp); switch (*ep++) { case INTEGER_EXT: @@ -1964,7 +1986,7 @@ dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Et Sint sn = get_int32(ep); ep += 4; -#if defined(ARCH_64) +#if defined(ARCH_64) && !HALFWORD_HEAP *objp = make_small(sn); #else if (MY_IS_SSMALL(sn)) { @@ -2061,7 +2083,7 @@ dec_term_atom_common: hp += n; objp = hp - 1; while (n-- > 0) { - objp[0] = (Eterm) next; + objp[0] = (Eterm) COMPRESS_POINTER(next); next = objp; objp--; } @@ -2079,12 +2101,12 @@ dec_term_atom_common: *objp = make_list(hp); hp += 2*n; objp = hp - 2; - objp[0] = (Eterm) (objp+1); - objp[1] = (Eterm) next; + objp[0] = (Eterm) COMPRESS_POINTER((objp+1)); + objp[1] = (Eterm) COMPRESS_POINTER(next); next = objp; objp -= 2; while (--n > 0) { - objp[0] = (Eterm) next; + objp[0] = (Eterm) COMPRESS_POINTER(next); objp[1] = make_list(objp + 2); next = objp; objp -= 2; @@ -2238,19 +2260,26 @@ dec_term_atom_common: node = erts_find_or_insert_node(sysname, cre); if(node == erts_this_node) { RefThing *rtp = (RefThing *) hp; - hp += REF_THING_HEAD_SIZE; -#ifdef ARCH_64 + ref_num = (Uint32 *) (hp + REF_THING_HEAD_SIZE); + +#if defined(ARCH_64) && !HALFWORD_HEAP + hp += REF_THING_HEAD_SIZE + ref_words/2 + 1; rtp->header = make_ref_thing_header(ref_words/2 + 1); #else + hp += REF_THING_HEAD_SIZE + ref_words; rtp->header = make_ref_thing_header(ref_words); #endif *objp = make_internal_ref(rtp); } else { ExternalThing *etp = (ExternalThing *) hp; - hp += EXTERNAL_THING_HEAD_SIZE; - -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP + hp += EXTERNAL_THING_HEAD_SIZE + ref_words/2 + 1; +#else + hp += EXTERNAL_THING_HEAD_SIZE + ref_words; +#endif + +#if defined(ARCH_64) && !HALFWORD_HEAP etp->header = make_external_ref_header(ref_words/2 + 1); #else etp->header = make_external_ref_header(ref_words); @@ -2260,10 +2289,10 @@ dec_term_atom_common: off_heap->externals = etp; *objp = make_external_ref(etp); + ref_num = &(etp->data.ui32[0]); } - ref_num = (Uint32 *) hp; -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP *(ref_num++) = ref_words /* 32-bit arity */; #endif ref_num[0] = r0; @@ -2271,12 +2300,9 @@ dec_term_atom_common: ref_num[i] = get_int32(ep); ep += 4; } -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP if ((1 + ref_words) % 2) ref_num[ref_words] = 0; - hp += ref_words/2 + 1; -#else - hp += ref_words; #endif break; } @@ -2398,7 +2424,12 @@ dec_term_atom_common: } *objp = make_export(hp); *hp++ = HEADER_EXPORT; +#if HALFWORD_HEAP + *((UWord *) (UWord) hp) = (UWord) erts_export_get_or_make_stub(mod, name, arity); + hp += 2; +#else *hp++ = (Eterm) erts_export_get_or_make_stub(mod, name, arity); +#endif break; } break; @@ -2474,11 +2505,11 @@ dec_term_atom_common: /* Environment */ for (i = num_free-1; i >= 0; i--) { - funp->env[i] = (Eterm) next; + funp->env[i] = (Eterm) COMPRESS_POINTER(next); next = funp->env + i; } /* Creator */ - funp->creator = (Eterm) next; + funp->creator = (Eterm) COMPRESS_POINTER(next); next = &(funp->creator); break; } @@ -2549,7 +2580,7 @@ dec_term_atom_common: /* Environment */ for (i = num_free-1; i >= 0; i--) { - funp->env[i] = (Eterm) next; + funp->env[i] = (Eterm) COMPRESS_POINTER(next); next = funp->env + i; } break; @@ -2580,26 +2611,35 @@ dec_term_atom_common: static Uint encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags) { - DECLARE_ESTACK(s); + DECLARE_WSTACK(s); Uint m, i, arity; Uint result = 0; +#if HALFWORD_HEAP + UWord wobj = 0; +#endif goto L_jump_start; outer_loop: - while (!ESTACK_ISEMPTY(s)) { - obj = ESTACK_POP(s); - + while (!WSTACK_ISEMPTY(s)) { +#if HALFWORD_HEAP + obj = (Eterm) (wobj = WSTACK_POP(s)); +#else + obj = WSTACK_POP(s); +#endif handle_popped_obj: - if (is_CP(obj)) { + if (is_CP(obj)) { /* Does not look for CP, looks for "no tag" */ +#if HALFWORD_HEAP + Eterm* ptr = (Eterm *) wobj; +#else Eterm* ptr = (Eterm *) obj; - +#endif /* * Pointer into a tuple. */ obj = *ptr--; if (!is_header(obj)) { - ESTACK_PUSH(s, (Eterm)ptr); + WSTACK_PUSH(s, (UWord)ptr); } else { /* Reached tuple header */ ASSERT(header_is_arityval(obj)); @@ -2611,7 +2651,7 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags) tl = CDR(cons); obj = CAR(cons); - ESTACK_PUSH(s, tl); + WSTACK_PUSH(s, tl); } else if (is_nil(obj)) { result++; goto outer_loop; @@ -2650,9 +2690,11 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags) else if (sizeof(Sint) == 4 || IS_SSMALL28(val)) result += 1 + 4; /* INTEGER_EXT */ else { - Eterm tmp_big[2]; + DeclareTmpHeapNoproc(tmp_big,2); + UseTmpHeapNoproc(2); i = big_bytes(small_to_big(val, tmp_big)); result += 1 + 1 + 1 + i; /* SMALL_BIG_EXT */ + UnUseTmpHeapNoproc(2); } } break; @@ -2698,7 +2740,11 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags) result += 1 + 4; } ptr += arity; +#if HALFWORD_HEAP + obj = (Eterm) (wobj = (UWord) ptr); +#else obj = (Eterm) ptr; +#endif goto handle_popped_obj; } break; @@ -2740,14 +2786,14 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags) if (is_not_list(obj)) { /* Push any non-list terms on the stack */ - ESTACK_PUSH(s, obj); + WSTACK_PUSH(s, obj); } else { /* Lists must be handled specially. */ if ((m = is_string(obj)) && (m < MAX_STRING_LEN)) { result += m + 2 + 1; } else { result += 5; - ESTACK_PUSH(s, obj); + WSTACK_PUSH(s, obj); } } } @@ -2760,8 +2806,12 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags) case EXPORT_DEF: { - Export* ep = (Export *) (export_val(obj))[1]; + Export* ep = *((Export **) (export_val(obj) + 1)); +#if HALFWORD_HEAP + result += 2; +#else result += 1; +#endif result += encode_size_struct2(acmp, ep->code[0], dflags); result += encode_size_struct2(acmp, ep->code[1], dflags); result += encode_size_struct2(acmp, make_small(ep->code[2]), dflags); @@ -2774,7 +2824,7 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags) } } - DESTROY_ESTACK(s); + DESTROY_WSTACK(s); return result; } @@ -2886,7 +2936,7 @@ decoded_size(byte *ep, byte* endp, int no_refc_bins) ep += 2; atom_extra_skip = 1 + 4*id_words; /* In case it is an external ref */ -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP heap_size += EXTERNAL_THING_HEAD_SIZE + id_words/2 + 1; #else heap_size += EXTERNAL_THING_HEAD_SIZE + id_words; @@ -2961,7 +3011,11 @@ decoded_size(byte *ep, byte* endp, int no_refc_bins) break; case EXPORT_EXT: terms += 3; +#if HALFWORD_HEAP + heap_size += 3; +#else heap_size += 2; +#endif break; case NEW_FUN_EXT: { diff --git a/erts/emulator/beam/external.h b/erts/emulator/beam/external.h index eada6d4f27..db86b4d796 100644 --- a/erts/emulator/beam/external.h +++ b/erts/emulator/beam/external.h @@ -212,7 +212,7 @@ erts_dist_ext_trailer(ErtsDistExternal *edep) { void *res = (void *) (edep->ext_endp + ERTS_WORD_ALIGN_PAD_SZ(edep->ext_endp)); - ASSERT((((Uint) res) % sizeof(Uint)) == 0); + ASSERT((((UWord) res) % sizeof(Uint)) == 0); return res; } diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index cab249a53f..cefdf80fb4 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -403,7 +403,7 @@ extern Eterm erts_ddll_monitor_driver(Process *p, /* Add fields in ERTS_INTERNAL_BINARY_FIELDS, otherwise the drivers crash */ #define ERTS_INTERNAL_BINARY_FIELDS \ - Uint flags; \ + UWord flags; \ erts_refc_t refc; \ ERTS_BINARY_STRUCT_ALIGNMENT @@ -723,6 +723,60 @@ do { \ #define ESTACK_POP(s) (*(--ESTK_CONCAT(s,_sp))) +void erl_grow_wstack(UWord** start, UWord** sp, UWord** end); +#define WSTK_CONCAT(a,b) a##b +#define WSTK_SUBSCRIPT(s,i) *((UWord *)((byte *)WSTK_CONCAT(s,_start) + (i))) +#define DEF_WSTACK_SIZE (16) + +#define DECLARE_WSTACK(s) \ + UWord WSTK_CONCAT(s,_default_stack)[DEF_WSTACK_SIZE]; \ + UWord* WSTK_CONCAT(s,_start) = WSTK_CONCAT(s,_default_stack); \ + UWord* WSTK_CONCAT(s,_sp) = WSTK_CONCAT(s,_start); \ + UWord* WSTK_CONCAT(s,_end) = WSTK_CONCAT(s,_start) + DEF_WSTACK_SIZE + +#define DESTROY_WSTACK(s) \ +do { \ + if (WSTK_CONCAT(s,_start) != WSTK_CONCAT(s,_default_stack)) { \ + erts_free(ERTS_ALC_T_ESTACK, WSTK_CONCAT(s,_start)); \ + } \ +} while(0) + +#define WSTACK_PUSH(s, x) \ +do { \ + if (WSTK_CONCAT(s,_sp) == WSTK_CONCAT(s,_end)) { \ + erl_grow_wstack(&WSTK_CONCAT(s,_start), &WSTK_CONCAT(s,_sp), \ + &WSTK_CONCAT(s,_end)); \ + } \ + *WSTK_CONCAT(s,_sp)++ = (x); \ +} while(0) + +#define WSTACK_PUSH2(s, x, y) \ +do { \ + if (WSTK_CONCAT(s,_sp) > WSTK_CONCAT(s,_end) - 2) { \ + erl_grow_wstack(&WSTK_CONCAT(s,_start), &WSTK_CONCAT(s,_sp), \ + &WSTK_CONCAT(s,_end)); \ + } \ + *WSTK_CONCAT(s,_sp)++ = (x); \ + *WSTK_CONCAT(s,_sp)++ = (y); \ +} while(0) + +#define WSTACK_PUSH3(s, x, y, z) \ +do { \ + if (WSTK_CONCAT(s,_sp) > WSTK_CONCAT(s,_end) - 3) { \ + erl_grow_wstack(&WSTK_CONCAT(s,_start), &WSTK_CONCAT(s,_sp), \ + &WSTK_CONCAT(s,_end)); \ + } \ + *WSTK_CONCAT(s,_sp)++ = (x); \ + *WSTK_CONCAT(s,_sp)++ = (y); \ + *WSTK_CONCAT(s,_sp)++ = (z); \ +} while(0) + +#define WSTACK_COUNT(s) (WSTK_CONCAT(s,_sp) - WSTK_CONCAT(s,_start)) + +#define WSTACK_ISEMPTY(s) (WSTK_CONCAT(s,_sp) == WSTK_CONCAT(s,_start)) +#define WSTACK_POP(s) (*(--WSTK_CONCAT(s,_sp))) + + /* port status flags */ #define ERTS_PORT_SFLG_CONNECTED ((Uint32) (1 << 0)) @@ -802,7 +856,7 @@ void erts_system_profile_clear(Process *c_p); int erts_load_module(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm* mod, byte* code, int size); void init_load(void); -Eterm* find_function_from_pc(Eterm* pc); +BeamInstr* find_function_from_pc(BeamInstr* pc); Eterm erts_module_info_0(Process* p, Eterm module); Eterm erts_module_info_1(Process* p, Eterm module, Eterm what); Eterm erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info); @@ -1171,7 +1225,7 @@ erts_smp_port_unlock(Port *prt) ERTS_INVALID_PORT_OPT((PP), (ID), ERTS_PORT_SFLGS_INVALID_TRACER_LOOKUP) #define ERTS_PORT_SCHED_ID(P, ID) \ - ((Uint) erts_prtsd_set((P), ERTS_PSD_SCHED_ID, (void *) (ID))) + ((Uint) (UWord) erts_prtsd_set((P), ERTS_PSD_SCHED_ID, (void *) (UWord) (ID))) #ifdef ERTS_SMP Port *erts_de2port(DistEntry *, Process *, ErtsProcLocks); @@ -1463,6 +1517,7 @@ Uint32 make_hash(Eterm); Eterm erts_bld_atom(Uint **hpp, Uint *szp, char *str); Eterm erts_bld_uint(Uint **hpp, Uint *szp, Uint ui); +Eterm erts_bld_uword(Uint **hpp, Uint *szp, UWord uw); Eterm erts_bld_uint64(Uint **hpp, Uint *szp, Uint64 ui64); Eterm erts_bld_sint64(Uint **hpp, Uint *szp, Sint64 si64); Eterm erts_bld_cons(Uint **hpp, Uint *szp, Eterm car, Eterm cdr); @@ -1515,7 +1570,9 @@ Sint cmp(Eterm, Eterm); #define CMP_EQ(a,b) ((a) == (b) || cmp_eq((a),(b))) #define CMP_NE(a,b) ((a) != (b) && cmp_ne((a),(b))) +/* duplicates from big.h */ int term_to_Uint(Eterm term, Uint *up); +int term_to_UWord(Eterm, UWord*); #ifdef HAVE_ERTS_NOW_CPU extern int erts_cpu_timestamp; @@ -1554,12 +1611,12 @@ void erts_queue_error_logger_message(Eterm, Eterm, ErlHeapFragment *); void erts_send_sys_msg_proc(Eterm, Eterm, Eterm, ErlHeapFragment *); void trace_send(Process*, Eterm, Eterm); void trace_receive(Process*, Eterm); -Uint32 erts_call_trace(Process *p, Eterm mfa[], Binary *match_spec, Eterm* args, +Uint32 erts_call_trace(Process *p, BeamInstr mfa[], Binary *match_spec, Eterm* args, int local, Eterm *tracer_pid); -void erts_trace_return(Process* p, Eterm* fi, Eterm retval, Eterm *tracer_pid); -void erts_trace_exception(Process* p, Eterm mfa[], Eterm class, Eterm value, +void erts_trace_return(Process* p, BeamInstr* fi, Eterm retval, Eterm *tracer_pid); +void erts_trace_exception(Process* p, BeamInstr mfa[], Eterm class, Eterm value, Eterm *tracer); -void erts_trace_return_to(Process *p, Uint *pc); +void erts_trace_return_to(Process *p, BeamInstr *pc); void trace_sched(Process*, Eterm); void trace_proc(Process*, Process*, Eterm, Eterm); void trace_proc_spawn(Process*, Eterm pid, Eterm mod, Eterm func, Eterm args); @@ -1589,7 +1646,7 @@ Uint erts_trace_flag2bit(Eterm flag); int erts_trace_flags(Eterm List, Uint *pMask, Eterm *pTracer, int *pCpuTimestamp); Eterm erts_bif_trace(int bif_index, Process* p, - Eterm arg1, Eterm arg2, Eterm arg3, Uint *I); + Eterm arg1, Eterm arg2, Eterm arg3, BeamInstr *I); #ifdef ERTS_SMP void erts_send_pending_trace_msgs(ErtsSchedulerData *esdp); @@ -1606,7 +1663,7 @@ void bin_write(int, void*, byte*, int); int intlist_to_buf(Eterm, char*, int); /* most callers pass plain char*'s */ struct Sint_buf { -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP char s[22]; #else char s[12]; @@ -1839,4 +1896,61 @@ erts_alloc_message_heap(Uint size, #endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */ +#if !HEAP_ON_C_STACK +# if defined(DEBUG) +# define DeclareTmpHeap(VariableName,Size,Process) \ + Eterm *VariableName = erts_debug_allocate_tmp_heap(Size,Process) +# define DeclareTmpHeapNoproc(VariableName,Size) \ + Eterm *VariableName = erts_debug_allocate_tmp_heap(Size,NULL) +# define UseTmpHeap(Size,Proc) \ + do { \ + erts_debug_use_tmp_heap((Size),(Proc)); \ + } while (0) +# define UnUseTmpHeap(Size,Proc) \ + do { \ + erts_debug_unuse_tmp_heap((Size),(Proc)); \ + } while (0) +# define UseTmpHeapNoproc(Size) \ + do { \ + erts_debug_use_tmp_heap(Size,NULL); \ + } while (0) +# define UnUseTmpHeapNoproc(Size) \ + do { \ + erts_debug_unuse_tmp_heap(Size,NULL); \ + } while (0) +# else +# define DeclareTmpHeap(VariableName,Size,Process) \ + Eterm *VariableName = (ERTS_PROC_GET_SCHDATA(Process)->tmp_heap)+(ERTS_PROC_GET_SCHDATA(Process)->num_tmp_heap_used) +# define DeclareTmpHeapNoproc(VariableName,Size) \ + Eterm *VariableName = (erts_get_scheduler_data()->tmp_heap)+(erts_get_scheduler_data()->num_tmp_heap_used) +# define UseTmpHeap(Size,Proc) \ + do { \ + ERTS_PROC_GET_SCHDATA(Proc)->num_tmp_heap_used += (Size); \ + } while (0) +# define UnUseTmpHeap(Size,Proc) \ + do { \ + ERTS_PROC_GET_SCHDATA(Proc)->num_tmp_heap_used -= (Size); \ + } while (0) +# define UseTmpHeapNoproc(Size) \ + do { \ + erts_get_scheduler_data()->num_tmp_heap_used += (Size); \ + } while (0) +# define UnUseTmpHeapNoproc(Size) \ + do { \ + erts_get_scheduler_data()->num_tmp_heap_used -= (Size); \ + } while (0) + + +# endif + +#else +# define DeclareTmpHeap(VariableName,Size,Process) \ + Eterm VariableName[Size] +# define DeclareTmpHeapNoproc(VariableName,Size) \ + Eterm VariableName[Size] +# define UseTmpHeap(Size,Proc) /* Nothing */ +# define UnUseTmpHeap(Size,Proc) /* Nothing */ +# define UseTmpHeapNoproc(Size) /* Nothing */ +# define UnUseTmpHeapNoproc(Size) /* Nothing */ +#endif #endif diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 3309b77086..10f1082039 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -72,6 +72,15 @@ erts_driver_t fd_driver; static int init_driver(erts_driver_t *, ErlDrvEntry *, DE_Handle *); static void terminate_port(Port *p); static void pdl_init(void); +#ifdef ERTS_SMP +static void driver_monitor_lock_pdl(Port *p); +static void driver_monitor_unlock_pdl(Port *p); +#define DRV_MONITOR_LOCK_PDL(Port) driver_monitor_lock_pdl(Port) +#define DRV_MONITOR_UNLOCK_PDL(Port) driver_monitor_unlock_pdl(Port) +#else +#define DRV_MONITOR_LOCK_PDL(Port) /* nothing */ +#define DRV_MONITOR_UNLOCK_PDL(Port) /* nothing */ +#endif static ERTS_INLINE ErlIOQueue* drvport2ioq(ErlDrvPort drvport) @@ -1998,12 +2007,13 @@ erts_do_exit_port(Port *p, Eterm from, Eterm reason) p->nlinks = NULL; erts_sweep_links(lnk, &sweep_one_link, &sc); } + DRV_MONITOR_LOCK_PDL(p); { ErtsMonitor *moni = p->monitors; p->monitors = NULL; erts_sweep_monitors(moni, &sweep_one_monitor, NULL); } - + DRV_MONITOR_UNLOCK_PDL(p); if ((p->status & ERTS_PORT_SFLG_DISTRIBUTION) && p->dist_entry) { erts_do_net_exits(p->dist_entry, rreason); @@ -3536,6 +3546,32 @@ static ERTS_INLINE void pdl_destroy(ErlDrvPDL pdl) erts_free(ERTS_ALC_T_PORT_DATA_LOCK, pdl); } +#ifdef ERTS_SMP + +static void driver_monitor_lock_pdl(Port *p) { + if (p->port_data_lock) { + driver_pdl_lock(p->port_data_lock); + } + /* Now we either have the port lock or the port_data_lock */ + ERTS_LC_ASSERT(!p->port_data_lock + || erts_lc_mtx_is_locked(&(p->port_data_lock->mtx))); + ERTS_SMP_LC_ASSERT(p->port_data_lock + || erts_lc_is_port_locked(p)); +} + +static void driver_monitor_unlock_pdl(Port *p) { + /* We should either have the port lock or the port_data_lock */ + ERTS_LC_ASSERT(!p->port_data_lock + || erts_lc_mtx_is_locked(&(p->port_data_lock->mtx))); + ERTS_SMP_LC_ASSERT(p->port_data_lock + || erts_lc_is_port_locked(p)); + if (p->port_data_lock) { + driver_pdl_unlock(p->port_data_lock); + } +} + +#endif + /* * exported driver_pdl_* functions ... */ @@ -3994,7 +4030,7 @@ drv_cancel_timer(Port *prt) erts_port_task_abort(prt->id, &prt->timeout_task); } -int driver_set_timer(ErlDrvPort ix, Uint t) +int driver_set_timer(ErlDrvPort ix, UWord t) { Port* prt = erts_drvport2port(ix); @@ -4053,12 +4089,16 @@ driver_read_timer(ErlDrvPort ix, unsigned long* t) int driver_get_now(ErlDrvNowData *now_data) { + Uint mega,secs,micro; ERTS_SMP_CHK_NO_PROC_LOCKS; if (now_data == NULL) { return -1; } - get_now(&(now_data->megasecs),&(now_data->secs),&(now_data->microsecs)); + get_now(&mega,&secs,µ); + now_data->megasecs = (unsigned long) mega; + now_data->secs = (unsigned long) secs; + now_data->microsecs = (unsigned long) micro; return 0; } @@ -4072,14 +4112,15 @@ static void ref_to_driver_monitor(Eterm ref, ErlDrvMonitor *mon) memcpy(mon,refp,sizeof(RefThing)); } -int driver_monitor_process(ErlDrvPort port, - ErlDrvTermData process, - ErlDrvMonitor *monitor) + +static int do_driver_monitor_process(Port *prt, + Eterm *buf, + ErlDrvTermData process, + ErlDrvMonitor *monitor) { - Port *prt = erts_drvport2port(port); Process *rp; Eterm ref; - Eterm buf[REF_THING_SIZE]; + if (prt->drv_ptr->process_exit == NULL) { return -1; } @@ -4089,22 +4130,76 @@ int driver_monitor_process(ErlDrvPort port, if (!rp) { return 1; } + ref = erts_make_ref_in_buffer(buf); erts_add_monitor(&(prt->monitors), MON_ORIGIN, ref, rp->id, NIL); erts_add_monitor(&(rp->monitors), MON_TARGET, ref, prt->id, NIL); - + erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_LINK); ref_to_driver_monitor(ref,monitor); return 0; } -int driver_demonitor_process(ErlDrvPort port, - const ErlDrvMonitor *monitor) +/* + * This can be called from a non scheduler thread iff a port_data_lock exists + */ +int driver_monitor_process(ErlDrvPort port, + ErlDrvTermData process, + ErlDrvMonitor *monitor) +{ + Port *prt; + int ret; + Uint32 status; + ErtsSchedulerData *sched = erts_get_scheduler_data(); + int ix = (int) port; + if (ix < 0 || erts_max_ports <= ix) { + return -1; + } + prt = &erts_port[ix]; + + DRV_MONITOR_LOCK_PDL(prt); + + if (sched) { + status = erts_port[ix].status; + } else { + erts_smp_port_state_lock(prt); + status = erts_port[ix].status; + erts_smp_port_state_unlock(prt); + } + + if (status & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) { + DRV_MONITOR_UNLOCK_PDL(prt); + return -1; + } + + /* Now (in SMP) we should have either the port lock (if we have a scheduler) or the port data lock + (if we're a driver thread) */ + ERTS_SMP_LC_ASSERT((sched != NULL || prt->port_data_lock)); + +#if !HEAP_ON_C_STACK + if (!sched) { + /* Need a separate allocation for the ref :( */ + Eterm *buf = erts_alloc(ERTS_ALC_T_TEMP_TERM, + sizeof(Eterm)*REF_THING_SIZE); + ret = do_driver_monitor_process(prt,buf,process,monitor); + erts_free(ERTS_ALC_T_TEMP_TERM,buf); + } else +#endif + { + DeclareTmpHeapNoproc(buf,REF_THING_SIZE); + UseTmpHeapNoproc(REF_THING_SIZE); + ret = do_driver_monitor_process(prt,buf,process,monitor); + UnUseTmpHeapNoproc(REF_THING_SIZE); + } + DRV_MONITOR_UNLOCK_PDL(prt); + return ret; +} + +static int do_driver_demonitor_process(Port *prt, Eterm *buf, + const ErlDrvMonitor *monitor) { - Port *prt = erts_drvport2port(port); Process *rp; Eterm ref; - Eterm buf[REF_THING_SIZE]; ErtsMonitor *mon; Eterm to; @@ -4137,12 +4232,60 @@ int driver_demonitor_process(ErlDrvPort port, return 0; } -ErlDrvTermData driver_get_monitored_process(ErlDrvPort port, +int driver_demonitor_process(ErlDrvPort port, + const ErlDrvMonitor *monitor) +{ + Port *prt; + int ret; + Uint32 status; + ErtsSchedulerData *sched = erts_get_scheduler_data(); + int ix = (int) port; + if (ix < 0 || erts_max_ports <= ix) { + return -1; + } + prt = &erts_port[ix]; + + DRV_MONITOR_LOCK_PDL(prt); + + if (sched) { + status = erts_port[ix].status; + } else { + erts_smp_port_state_lock(prt); + status = erts_port[ix].status; + erts_smp_port_state_unlock(prt); + } + + if (status & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) { + DRV_MONITOR_UNLOCK_PDL(prt); + return -1; + } + + /* Now we should have either the port lock (if we have a scheduler) or the port data lock + (if we're a driver thread) */ + ERTS_SMP_LC_ASSERT((sched != NULL || prt->port_data_lock)); +#if !HEAP_ON_C_STACK + if (!sched) { + /* Need a separate allocation for the ref :( */ + Eterm *buf = erts_alloc(ERTS_ALC_T_TEMP_TERM, + sizeof(Eterm)*REF_THING_SIZE); + ret = do_driver_demonitor_process(prt,buf,monitor); + erts_free(ERTS_ALC_T_TEMP_TERM,buf); + } else +#endif + { + DeclareTmpHeapNoproc(buf,REF_THING_SIZE); + UseTmpHeapNoproc(REF_THING_SIZE); + ret = do_driver_demonitor_process(prt,buf,monitor); + UnUseTmpHeapNoproc(REF_THING_SIZE); + } + DRV_MONITOR_UNLOCK_PDL(prt); + return ret; +} + +static ErlDrvTermData do_driver_get_monitored_process(Port *prt, Eterm *buf, const ErlDrvMonitor *monitor) { - Port *prt = erts_drvport2port(port); Eterm ref; - Eterm buf[REF_THING_SIZE]; ErtsMonitor *mon; Eterm to; @@ -4158,6 +4301,59 @@ ErlDrvTermData driver_get_monitored_process(ErlDrvPort port, return (ErlDrvTermData) to; } + +ErlDrvTermData driver_get_monitored_process(ErlDrvPort port, + const ErlDrvMonitor *monitor) +{ + Port *prt; + ErlDrvTermData ret; + Uint32 status; + ErtsSchedulerData *sched = erts_get_scheduler_data(); + int ix = (int) port; + if (ix < 0 || erts_max_ports <= ix) { + return driver_term_nil; + } + prt = &erts_port[ix]; + + DRV_MONITOR_LOCK_PDL(prt); + + if (sched) { + status = erts_port[ix].status; + } else { + erts_smp_port_state_lock(prt); + status = erts_port[ix].status; + erts_smp_port_state_unlock(prt); + } + + if (status & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) { + DRV_MONITOR_UNLOCK_PDL(prt); + return driver_term_nil; + } + + /* Now we should have either the port lock (if we have a scheduler) or the port data lock + (if we're a driver thread) */ + ERTS_SMP_LC_ASSERT((sched != NULL || prt->port_data_lock)); + +#if !HEAP_ON_C_STACK + if (!sched) { + /* Need a separate allocation for the ref :( */ + Eterm *buf = erts_alloc(ERTS_ALC_T_TEMP_TERM, + sizeof(Eterm)*REF_THING_SIZE); + ret = do_driver_get_monitored_process(prt,buf,monitor); + erts_free(ERTS_ALC_T_TEMP_TERM,buf); + } else +#endif + { + DeclareTmpHeapNoproc(buf,REF_THING_SIZE); + UseTmpHeapNoproc(REF_THING_SIZE); + ret = do_driver_get_monitored_process(prt,buf,monitor); + UnUseTmpHeapNoproc(REF_THING_SIZE); + } + DRV_MONITOR_UNLOCK_PDL(prt); + return ret; +} + + int driver_compare_monitors(const ErlDrvMonitor *monitor1, const ErlDrvMonitor *monitor2) { @@ -4173,18 +4369,22 @@ void erts_fire_port_monitor(Port *prt, Eterm ref) ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)); ASSERT(prt->drv_ptr != NULL); - + DRV_MONITOR_LOCK_PDL(prt); if (erts_lookup_monitor(prt->monitors,ref) == NULL) { + DRV_MONITOR_UNLOCK_PDL(prt); return; } callback = prt->drv_ptr->process_exit; ASSERT(callback != NULL); ref_to_driver_monitor(ref,&drv_monitor); + DRV_MONITOR_UNLOCK_PDL(prt); fpe_was_unmasked = erts_block_fpe(); (*callback)((ErlDrvData) (prt->drv_data), &drv_monitor); erts_unblock_fpe(fpe_was_unmasked); + DRV_MONITOR_LOCK_PDL(prt); /* remove monitor *after* callback */ rmon = erts_remove_monitor(&(prt->monitors),ref); + DRV_MONITOR_UNLOCK_PDL(prt); if (rmon) { erts_destroy_monitor(rmon); } diff --git a/erts/emulator/beam/module.h b/erts/emulator/beam/module.h index 87d13b3607..694e4ab72f 100644 --- a/erts/emulator/beam/module.h +++ b/erts/emulator/beam/module.h @@ -29,8 +29,8 @@ typedef struct erl_module { IndexSlot slot; /* Must be located at top of struct! */ int module; /* Atom index for module (not tagged). */ - Eterm* code; - Eterm* old_code; + BeamInstr* code; + BeamInstr* old_code; int code_length; /* Length of loaded code in bytes. */ int old_code_length; /* Length of old loaded code in bytes */ unsigned catches, old_catches; diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 4b949523fa..a86bcb80dd 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -1,25 +1,26 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ #ifndef __SYS_H__ #define __SYS_H__ + #if defined(VALGRIND) && !defined(NO_FPE_SIGNALS) # define NO_FPE_SIGNALS #endif @@ -230,9 +231,14 @@ EXTERN_FUNCTION(int, real_printf, (const char *fmt, ...)); ** Data types: ** ** Eterm: A tagged erlang term (possibly 64 bits) +** BeamInstr: A beam code instruction unit, possibly larger than Eterm, not smaller. ** UInt: An unsigned integer exactly as large as an Eterm. ** SInt: A signed integer exactly as large as an eterm and therefor large ** enough to hold the return value of the signed_val() macro. +** UWord: An unsigned integer at least as large as a void * and also as large +** or larger than an Eterm +** SWord: A signed integer at least as large as a void * and also as large +** or larger than an Eterm ** Uint32: An unsigned integer of 32 bits exactly ** Sint32: A signed integer of 32 bits exactly ** Uint16: An unsigned integer of 16 bits exactly @@ -253,11 +259,43 @@ EXTERN_FUNCTION(int, real_printf, (const char *fmt, ...)); #else #error Neither 32 nor 64 bit architecture #endif +#ifdef ARCH_64 +# ifdef HALFWORD_HEAP_EMULATOR +# define HALFWORD_HEAP 1 +# define HALFWORD_ASSERT 0 +# else +# define HALFWORD_HEAP 0 +# define HALFWORD_ASSERT 0 +# endif +#endif #if SIZEOF_VOID_P != SIZEOF_SIZE_T #error sizeof(void*) != sizeof(size_t) #endif +#if HALFWORD_HEAP + +#if SIZEOF_INT == 4 +typedef unsigned int Eterm; +typedef unsigned int Uint; +typedef int Sint; +#define ERTS_SIZEOF_ETERM SIZEOF_INT +#else +#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint' +#endif + +#if SIZEOF_VOID_P == SIZEOF_LONG +typedef unsigned long UWord; +typedef long SWord; +#elif SIZEOF_VOID_P == SIZEOF_INT +typedef unsigned int UWord; +typedef int SWord; +#else +#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint' +#endif + +#else /* !HALFWORD_HEAP */ + #if SIZEOF_VOID_P == SIZEOF_LONG typedef unsigned long Eterm; typedef unsigned long Uint; @@ -272,6 +310,13 @@ typedef int Sint; #error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint' #endif +typedef Uint UWord; +typedef Sint SWord; + +#endif /* HALFWORD_HEAP */ + +typedef UWord BeamInstr; + #ifndef HAVE_INT64 #if SIZEOF_LONG == 8 #define HAVE_INT64 1 diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 31efddc0f2..51c12a0b69 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -204,6 +204,25 @@ erl_grow_stack(Eterm** start, Eterm** sp, Eterm** end) *end = *start + new_size; *sp = *start + sp_offs; } +/* + * Helper function for the ESTACK macros defined in global.h. + */ +void +erl_grow_wstack(UWord** start, UWord** sp, UWord** end) +{ + Uint old_size = (*end - *start); + Uint new_size = old_size * 2; + Uint sp_offs = *sp - *start; + if (new_size > 2 * DEF_ESTACK_SIZE) { + *start = erts_realloc(ERTS_ALC_T_ESTACK, (void *) *start, new_size*sizeof(UWord)); + } else { + UWord* new_ptr = erts_alloc(ERTS_ALC_T_ESTACK, new_size*sizeof(UWord)); + sys_memcpy(new_ptr, *start, old_size*sizeof(UWord)); + *start = new_ptr; + } + *end = *start + new_size; + *sp = *start + sp_offs; +} /* CTYPE macros */ @@ -354,6 +373,31 @@ erts_bld_uint(Uint **hpp, Uint *szp, Uint ui) return res; } +/* + * Erts_bld_uword is more or less similar to erts_bld_uint, but a pointer + * can safely be passed. + */ + +Eterm +erts_bld_uword(Uint **hpp, Uint *szp, UWord uw) +{ + Eterm res = THE_NON_VALUE; + if (IS_USMALL(0, uw)) { + if (hpp) + res = make_small((Uint) uw); + } + else { + if (szp) + *szp += BIG_UWORD_HEAP_SIZE(uw); + if (hpp) { + res = uword_to_big(uw, *hpp); + *hpp += BIG_UWORD_HEAP_SIZE(uw); + } + } + return res; +} + + Eterm erts_bld_uint64(Uint **hpp, Uint *szp, Uint64 ui64) { @@ -711,7 +755,7 @@ hash_binary_bytes(Eterm bin, Uint sz, Uint32 hash) Uint32 make_hash(Eterm term_arg) { - DECLARE_ESTACK(stack); + DECLARE_WSTACK(stack); Eterm term = term_arg; Eterm hash = 0; unsigned op; @@ -770,7 +814,7 @@ tail_recur: Uint y2 = y1 < 0 ? -(Uint)y1 : y1; UINT32_HASH_STEP(y2, FUNNY_NUMBER2); -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP if (y2 >> 32) UINT32_HASH_STEP(y2 >> 32, FUNNY_NUMBER2); #endif @@ -787,7 +831,7 @@ tail_recur: } case EXPORT_DEF: { - Export* ep = (Export *) (export_val(term))[1]; + Export* ep = *((Export **) (export_val(term) + 1)); hash = hash * FUNNY_NUMBER11 + ep->code[2]; hash = hash*FUNNY_NUMBER1 + @@ -809,7 +853,7 @@ tail_recur: hash = hash*FUNNY_NUMBER2 + funp->fe->old_uniq; if (num_free > 0) { if (num_free > 1) { - ESTACK_PUSH3(stack, (Eterm) &funp->env[1], (num_free-1), MAKE_HASH_FUN_OP); + WSTACK_PUSH3(stack, (UWord) &funp->env[1], (num_free-1), MAKE_HASH_FUN_OP); } term = funp->env[0]; goto tail_recur; @@ -837,9 +881,9 @@ tail_recur: } case MAKE_HASH_CDR_PRE_OP: - term = ESTACK_POP(stack); + term = (Eterm) WSTACK_POP(stack); if (is_not_list(term)) { - ESTACK_PUSH(stack, MAKE_HASH_CDR_POST_OP); + WSTACK_PUSH(stack, (UWord) MAKE_HASH_CDR_POST_OP); goto tail_recur; } /* fall through */ @@ -854,13 +898,13 @@ tail_recur: hash = hash*FUNNY_NUMBER2 + unsigned_val(*list); if (is_not_list(CDR(list))) { - ESTACK_PUSH(stack, MAKE_HASH_CDR_POST_OP); + WSTACK_PUSH(stack, MAKE_HASH_CDR_POST_OP); term = CDR(list); goto tail_recur; } list = list_val(CDR(list)); } - ESTACK_PUSH2(stack, CDR(list), MAKE_HASH_CDR_PRE_OP); + WSTACK_PUSH2(stack, CDR(list), MAKE_HASH_CDR_PRE_OP); term = CAR(list); goto tail_recur; } @@ -888,7 +932,7 @@ tail_recur: } d = BIG_DIGIT(ptr, k); k = sizeof(ErtsDigit); -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP if (!(d >> 32)) k /= 2; #endif @@ -904,21 +948,21 @@ tail_recur: Eterm* ptr = tuple_val(term); Uint arity = arityval(*ptr); - ESTACK_PUSH3(stack, arity, (Eterm)(ptr+1), arity); + WSTACK_PUSH3(stack, (UWord) arity, (UWord)(ptr+1), (UWord) arity); op = MAKE_HASH_TUPLE_OP; }/*fall through*/ case MAKE_HASH_TUPLE_OP: case MAKE_HASH_FUN_OP: { - Uint i = ESTACK_POP(stack); - Eterm* ptr = (Eterm*) ESTACK_POP(stack); + Uint i = (Uint) WSTACK_POP(stack); + Eterm* ptr = (Eterm*) WSTACK_POP(stack); if (i != 0) { term = *ptr; - ESTACK_PUSH3(stack, (Eterm)(ptr+1), i-1, op); + WSTACK_PUSH3(stack, (UWord)(ptr+1), (UWord) i-1, (UWord) op); goto tail_recur; } if (op == MAKE_HASH_TUPLE_OP) { - Uint32 arity = ESTACK_POP(stack); + Uint32 arity = (Uint32) WSTACK_POP(stack); hash = hash*FUNNY_NUMBER9 + arity; } break; @@ -928,10 +972,10 @@ tail_recur: erl_exit(1, "Invalid tag in make_hash(0x%X,0x%X)\n", term, op); return 0; } - if (ESTACK_ISEMPTY(stack)) break; - op = ESTACK_POP(stack); + if (WSTACK_ISEMPTY(stack)) break; + op = WSTACK_POP(stack); } - DESTROY_ESTACK(stack); + DESTROY_WSTACK(stack); return hash; #undef UINT32_HASH_STEP @@ -1002,7 +1046,7 @@ Uint32 make_hash2(Eterm term) { Uint32 hash; - Eterm tmp_big[2]; + DeclareTmpHeapNoproc(tmp_big,2); /* (HCONST * {2, ..., 14}) mod 2^32 */ #define HCONST_2 0x3c6ef372UL @@ -1041,7 +1085,6 @@ make_hash2(Eterm term) } while(0) #define IS_SSMALL28(x) (((Uint) (((x) >> (28-1)) + 1)) < 2) - /* Optimization. Simple cases before declaration of estack. */ if (primary_tag(term) == TAG_PRIMARY_IMMED1) { switch (term & _TAG_IMMED1_MASK) { @@ -1070,6 +1113,7 @@ make_hash2(Eterm term) Eterm tmp; DECLARE_ESTACK(s); + UseTmpHeapNoproc(2); hash = 0; for (;;) { switch (primary_tag(term)) { @@ -1123,7 +1167,7 @@ make_hash2(Eterm term) break; case EXPORT_SUBTAG: { - Export* ep = (Export *) (export_val(term))[1]; + Export* ep = *((Export **) (export_val(term) + 1)); UINT32_HASH_2 (ep->code[2], @@ -1314,6 +1358,7 @@ make_hash2(Eterm term) hash2_common: if (ESTACK_ISEMPTY(s)) { DESTROY_ESTACK(s); + UnUseTmpHeapNoproc(2); return hash; } term = ESTACK_POP(s); @@ -1332,7 +1377,7 @@ make_hash2(Eterm term) Uint32 make_broken_hash(Eterm term) { Uint32 hash = 0; - DECLARE_ESTACK(stack); + DECLARE_WSTACK(stack); unsigned op; tail_recur: op = tag_val_def(term); @@ -1346,7 +1391,7 @@ tail_recur: (atom_tab(atom_val(term))->slot.bucket.hvalue); break; case SMALL_DEF: -#ifdef ARCH_64 +#if defined(ARCH_64) && !HALFWORD_HEAP { Sint y1 = signed_val(term); Uint y2 = y1 < 0 ? -(Uint)y1 : y1; @@ -1399,7 +1444,7 @@ tail_recur: case EXPORT_DEF: { - Export* ep = (Export *) (export_val(term))[1]; + Export* ep = *((Export **) (export_val(term) + 1)); hash = hash * FUNNY_NUMBER11 + ep->code[2]; hash = hash*FUNNY_NUMBER1 + @@ -1421,7 +1466,7 @@ tail_recur: hash = hash*FUNNY_NUMBER2 + funp->fe->old_uniq; if (num_free > 0) { if (num_free > 1) { - ESTACK_PUSH3(stack, (Eterm) &funp->env[1], (num_free-1), MAKE_HASH_FUN_OP); + WSTACK_PUSH3(stack, (UWord) &funp->env[1], (num_free-1), MAKE_HASH_FUN_OP); } term = funp->env[0]; goto tail_recur; @@ -1456,16 +1501,17 @@ tail_recur: break; case MAKE_HASH_CDR_PRE_OP: - term = ESTACK_POP(stack); + term = (Eterm) WSTACK_POP(stack); if (is_not_list(term)) { - ESTACK_PUSH(stack, MAKE_HASH_CDR_POST_OP); + WSTACK_PUSH(stack, (UWord) MAKE_HASH_CDR_POST_OP); goto tail_recur; } /*fall through*/ case LIST_DEF: { Eterm* list = list_val(term); - ESTACK_PUSH2(stack, CDR(list), MAKE_HASH_CDR_PRE_OP); + WSTACK_PUSH2(stack, (UWord) CDR(list), + (UWord) MAKE_HASH_CDR_PRE_OP); term = CAR(list); goto tail_recur; } @@ -1538,21 +1584,21 @@ tail_recur: Eterm* ptr = tuple_val(term); Uint arity = arityval(*ptr); - ESTACK_PUSH3(stack, arity, (Eterm)(ptr+1), arity); + WSTACK_PUSH3(stack, (UWord) arity, (UWord) (ptr+1), (UWord) arity); op = MAKE_HASH_TUPLE_OP; }/*fall through*/ case MAKE_HASH_TUPLE_OP: case MAKE_HASH_FUN_OP: { - Uint i = ESTACK_POP(stack); - Eterm* ptr = (Eterm*) ESTACK_POP(stack); + Uint i = (Uint) WSTACK_POP(stack); + Eterm* ptr = (Eterm*) WSTACK_POP(stack); if (i != 0) { term = *ptr; - ESTACK_PUSH3(stack, (Eterm)(ptr+1), i-1, op); + WSTACK_PUSH3(stack, (UWord)(ptr+1), (UWord) i-1, (UWord) op); goto tail_recur; } if (op == MAKE_HASH_TUPLE_OP) { - Uint32 arity = ESTACK_POP(stack); + Uint32 arity = (UWord) WSTACK_POP(stack); hash = hash*FUNNY_NUMBER9 + arity; } break; @@ -1562,11 +1608,11 @@ tail_recur: erl_exit(1, "Invalid tag in make_broken_hash\n"); return 0; } - if (ESTACK_ISEMPTY(stack)) break; - op = ESTACK_POP(stack); + if (WSTACK_ISEMPTY(stack)) break; + op = (Uint) WSTACK_POP(stack); } - DESTROY_ESTACK(stack); + DESTROY_WSTACK(stack); return hash; #undef MAKE_HASH_TUPLE_OP @@ -1869,7 +1915,7 @@ erts_destroy_tmp_dsbuf(erts_dsprintf_buf_t *dsbufp) int eq(Eterm a, Eterm b) { - DECLARE_ESTACK(stack); + DECLARE_WSTACK(stack); Sint sz; Eterm* aa; Eterm* bb; @@ -1887,7 +1933,7 @@ tailrecur_ne: Eterm atmp = CAR(aval); Eterm btmp = CAR(bval); if (atmp != btmp) { - ESTACK_PUSH2(stack,CDR(bval),CDR(aval)); + WSTACK_PUSH2(stack,(UWord) CDR(bval),(UWord) CDR(aval)); a = atmp; b = btmp; goto tailrecur_ne; @@ -1957,8 +2003,8 @@ tailrecur_ne: case EXPORT_SUBTAG: { if (is_export(b)) { - Export* a_exp = (Export *) (export_val(a))[1]; - Export* b_exp = (Export *) (export_val(b))[1]; + Export* a_exp = *((Export **) (export_val(a) + 1)); + Export* b_exp = *((Export **) (export_val(b) + 1)); if (a_exp == b_exp) goto pop_next; } break; /* not equal */ @@ -2130,32 +2176,32 @@ term_array: /* arrays in 'aa' and 'bb', length in 'sz' */ goto not_equal; } if (i > 1) { /* push the rest */ - ESTACK_PUSH3(stack, i-1, (Eterm)(bp+1), - ((Eterm)(ap+1)) | TAG_PRIMARY_HEADER); + WSTACK_PUSH3(stack, i-1, (UWord)(bp+1), + ((UWord)(ap+1)) | TAG_PRIMARY_HEADER); /* We (ab)use TAG_PRIMARY_HEADER to recognize a term_array */ } goto tailrecur_ne; } pop_next: - if (!ESTACK_ISEMPTY(stack)) { - Eterm something = ESTACK_POP(stack); - if (primary_tag(something) == TAG_PRIMARY_HEADER) { /* a term_array */ + if (!WSTACK_ISEMPTY(stack)) { + UWord something = WSTACK_POP(stack); + if (primary_tag((Eterm) something) == TAG_PRIMARY_HEADER) { /* a term_array */ aa = (Eterm*) something; - bb = (Eterm*) ESTACK_POP(stack); - sz = ESTACK_POP(stack); + bb = (Eterm*) WSTACK_POP(stack); + sz = WSTACK_POP(stack); goto term_array; } a = something; - b = ESTACK_POP(stack); + b = WSTACK_POP(stack); goto tailrecur; } - DESTROY_ESTACK(stack); + DESTROY_WSTACK(stack); return 1; not_equal: - DESTROY_ESTACK(stack); + DESTROY_WSTACK(stack); return 0; } @@ -2210,7 +2256,7 @@ static int cmp_atoms(Eterm a, Eterm b) Sint cmp(Eterm a, Eterm b) { - DECLARE_ESTACK(stack); + DECLARE_WSTACK(stack); Eterm* aa; Eterm* bb; int i; @@ -2327,7 +2373,7 @@ tailrecur_ne: Eterm atmp = CAR(aa); Eterm btmp = CAR(bb); if (atmp != btmp) { - ESTACK_PUSH2(stack,CDR(bb),CDR(aa)); + WSTACK_PUSH2(stack,(UWord) CDR(bb),(UWord) CDR(aa)); a = atmp; b = btmp; goto tailrecur_ne; @@ -2392,8 +2438,8 @@ tailrecur_ne: a_tag = EXPORT_DEF; goto mixed_types; } else { - Export* a_exp = (Export *) (export_val(a))[1]; - Export* b_exp = (Export *) (export_val(b))[1]; + Export* a_exp = *((Export **) (export_val(a) + 1)); + Export* b_exp = *((Export **) (export_val(b) + 1)); if ((j = cmp_atoms(a_exp->code[0], b_exp->code[0])) != 0) { RETURN_NEQ(j); @@ -2581,7 +2627,11 @@ tailrecur_ne: { FloatDef f1, f2; Eterm big; - Eterm big_buf[2]; +#if HEAP_ON_C_STACK + Eterm big_buf[2]; /* If HEAP_ON_C_STACK */ +#else + Eterm *big_buf = erts_get_scheduler_data()->cmp_tmp_heap; +#endif switch(_NUMBER_CODE(a_tag, b_tag)) { case SMALL_BIG: @@ -2644,7 +2694,7 @@ term_array: /* arrays in 'aa' and 'bb', length in 'i' */ } } else { /* (ab)Use TAG_PRIMARY_HEADER to recognize a term_array */ - ESTACK_PUSH3(stack, i, (Eterm)bb, (Eterm)aa | TAG_PRIMARY_HEADER); + WSTACK_PUSH3(stack, i, (UWord)bb, (UWord)aa | TAG_PRIMARY_HEADER); goto tailrecur_ne; } } @@ -2654,20 +2704,20 @@ term_array: /* arrays in 'aa' and 'bb', length in 'i' */ goto tailrecur; pop_next: - if (!ESTACK_ISEMPTY(stack)) { - Eterm something = ESTACK_POP(stack); - if (primary_tag(something) == TAG_PRIMARY_HEADER) { /* a term_array */ + if (!WSTACK_ISEMPTY(stack)) { + UWord something = WSTACK_POP(stack); + if (primary_tag((Eterm) something) == TAG_PRIMARY_HEADER) { /* a term_array */ aa = (Eterm*) something; - bb = (Eterm*) ESTACK_POP(stack); - i = ESTACK_POP(stack); + bb = (Eterm*) WSTACK_POP(stack); + i = WSTACK_POP(stack); goto term_array; } - a = something; - b = ESTACK_POP(stack); + a = (Eterm) something; + b = (Eterm) WSTACK_POP(stack); goto tailrecur; } - DESTROY_ESTACK(stack); + DESTROY_WSTACK(stack); return 0; not_equal: diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 95510a16b2..cc4421b49c 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ /* @@ -196,9 +196,9 @@ enum e_timer {timer_idle, timer_again, timer_write}; struct t_data; typedef struct { - Sint fd; + SWord fd; ErlDrvPort port; - unsigned key; /* Async queue key */ + unsigned long key; /* Async queue key */ unsigned flags; /* Original flags from FILE_OPEN. */ void (*invoke)(void *); struct t_data *d; @@ -306,7 +306,7 @@ struct t_data int result_ok; Efile_error errInfo; int flags; - Sint fd; + SWord fd; /**/ Efile_info info; EFILE_DIR_HANDLE dir_handle; /* Handle to open directory. */ @@ -605,7 +605,7 @@ file_start(ErlDrvPort port, char* command) } desc->fd = FILE_FD_INVALID; desc->port = port; - desc->key = (unsigned) (Uint) port; + desc->key = (unsigned long) (UWord) port; desc->flags = 0; desc->invoke = NULL; desc->d = NULL; @@ -630,7 +630,7 @@ static void free_data(void *data) EF_FREE(data); } -static void do_close(int flags, Sint fd) { +static void do_close(int flags, SWord fd) { if (flags & EFILE_COMPRESSED) { erts_gzclose((gzFile)(fd)); } else { @@ -709,7 +709,7 @@ static void reply_Uint_posix_error(file_descriptor *desc, Uint num, TRACE_C('N'); response[0] = FILE_RESP_NUMERR; -#if SIZEOF_VOID_P == 4 +#if SIZEOF_VOID_P == 4 || HALFWORD_HEAP put_int32(0, response+1); #else put_int32(num>>32, response+1); @@ -767,7 +767,7 @@ static int reply_Uint(file_descriptor *desc, Uint result) { TRACE_C('R'); tmp[0] = FILE_RESP_NUMBER; -#if SIZEOF_VOID_P == 4 +#if SIZEOF_VOID_P == 4 || HALFWORD_HEAP put_int32(0, tmp+1); #else put_int32(result>>32, tmp+1); @@ -1620,7 +1620,7 @@ static void invoke_open(void *data) status = efile_may_openfile(&d->errInfo, d->b); if (status || (d->errInfo.posix_errno != EISDIR)) { mode = (d->flags & EFILE_MODE_READ) ? "rb" : "wb"; - d->fd = (Sint) erts_gzopen(d->b, mode); + d->fd = (SWord) erts_gzopen(d->b, mode); if ((gzFile)d->fd) { status = 1; } else { diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c index 4cd54c073f..d782b044a9 100644 --- a/erts/emulator/drivers/unix/ttsl_drv.c +++ b/erts/emulator/drivers/unix/ttsl_drv.c @@ -314,7 +314,7 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf) sys_sigset(SIGCONT, cont); sys_sigset(SIGWINCH, winch); - driver_select(port, (ErlDrvEvent)(Uint)ttysl_fd, ERL_DRV_READ|ERL_DRV_USE, 1); + driver_select(port, (ErlDrvEvent)(UWord)ttysl_fd, ERL_DRV_READ|ERL_DRV_USE, 1); ttysl_port = port; /* we need to know this when we enter the break handler */ @@ -394,7 +394,7 @@ static void ttysl_stop(ErlDrvData ttysl_data) stop_lbuf(); stop_termcap(); tty_reset(ttysl_fd); - driver_select(ttysl_port, (ErlDrvEvent)(Uint)ttysl_fd, ERL_DRV_READ|ERL_DRV_USE, 0); + driver_select(ttysl_port, (ErlDrvEvent)(UWord)ttysl_fd, ERL_DRV_READ|ERL_DRV_USE, 0); sys_sigset(SIGCONT, SIG_DFL); sys_sigset(SIGWINCH, SIG_DFL); } @@ -685,7 +685,7 @@ static void ttysl_from_tty(ErlDrvData ttysl_data, ErlDrvEvent fd) utf8buf_size = 0; } - if ((i = read((int)(Sint)fd, (char *) p, left)) >= 0) { + if ((i = read((int)(SWord)fd, (char *) p, left)) >= 0) { if (p != b) { i += (p - b); } diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c index f4e21bc05f..4a9bfd5d08 100644 --- a/erts/emulator/sys/common/erl_mseg.c +++ b/erts/emulator/sys/common/erl_mseg.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2002-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -83,10 +83,20 @@ static int is_cache_check_scheduled; static int is_cache_check_requested; #endif +#if HALFWORD_HEAP +static int initialize_pmmap(void); +static void *pmmap(size_t size); +static int pmunmap(void *p, size_t size); +static void *pmremap(void *old_address, size_t old_size, + size_t new_size); +#endif + #if HAVE_MMAP /* Mmap ... */ #define MMAP_PROT (PROT_READ|PROT_WRITE) + + #ifdef MAP_ANON # define MMAP_FLAGS (MAP_ANON|MAP_PRIVATE) # define MMAP_FD (-1) @@ -102,7 +112,11 @@ static int mmap_fd; # define HAVE_MSEG_RECREATE 0 #endif +#if HALFWORD_HEAP +#define CAN_PARTLY_DESTROY 0 +#else #define CAN_PARTLY_DESTROY 1 +#endif #else /* #if HAVE_MMAP */ #define CAN_PARTLY_DESTROY 0 #error "Not supported" @@ -232,6 +246,7 @@ static void thread_safe_init(void) { erts_mtx_init(&init_atoms_mutex, "mseg_init_atoms"); erts_mtx_init(&mseg_mutex, "mseg"); + #ifdef ERTS_THREADS_NO_SMP main_tid = erts_thr_self(); #endif @@ -306,10 +321,20 @@ mseg_create(Uint size) #if defined(ERTS_MSEG_FAKE_SEGMENTS) seg = erts_sys_alloc(ERTS_ALC_N_INVALID, NULL, size); #elif HAVE_MMAP +#if HALFWORD_HEAP + seg = pmmap(size); +#else seg = (void *) mmap((void *) 0, (size_t) size, MMAP_PROT, MMAP_FLAGS, MMAP_FD, 0); if (seg == (void *) MAP_FAILED) seg = NULL; +#endif +#if HALFWORD_HEAP + if ((unsigned long) seg & CHECK_POINTER_MASK) { + erts_fprintf(stderr,"Pointer mask failure (0x%08lx)\n",(unsigned long) seg); + return NULL; + } +#endif #else #error "Missing mseg_create() implementation" #endif @@ -329,9 +354,11 @@ mseg_destroy(void *seg, Uint size) #ifdef DEBUG int res = #endif - +#if HALFWORD_HEAP + pmunmap((void *) seg, size); +#else munmap((void *) seg, size); - +#endif ASSERT(size % page_size == 0); ASSERT(res == 0); #else @@ -355,12 +382,18 @@ mseg_recreate(void *old_seg, Uint old_size, Uint new_size) #if defined(ERTS_MSEG_FAKE_SEGMENTS) new_seg = erts_sys_realloc(ERTS_ALC_N_INVALID, NULL, old_seg, new_size); #elif HAVE_MREMAP +#if HALFWORD_HEAP + new_seg = (void *) pmremap((void *) old_seg, + (size_t) old_size, + (size_t) new_size); +#else new_seg = (void *) mremap((void *) old_seg, (size_t) old_size, (size_t) new_size, MREMAP_MAYMOVE); if (new_seg == (void *) MAP_FAILED) new_seg = NULL; +#endif #else #error "Missing mseg_recreate() implementation" #endif @@ -1328,6 +1361,10 @@ erts_mseg_init(ErtsMsegInit_t *init) erl_exit(ERTS_ABORT_EXIT, "erts_mseg: unable to open /dev/zero\n"); #endif +#if HAVE_MMAP && HALFWORD_HEAP + initialize_pmmap(); +#endif + page_size = GET_PAGE_SIZE; page_shift = 1; @@ -1450,3 +1487,419 @@ erts_mseg_test(unsigned long op, } +#if HALFWORD_HEAP +/* + * Very simple page oriented mmap replacer. Works in the lower + * 32 bit address range of a 64bit program. + * Implements anonymous mmap mremap and munmap with address order first fit. + * The free list is expected to be very short... + * To be used for compressed pointers in Erlang halfword emulator + * implementation. The MacOS X version is more of a toy, it's not really + * for production as the halfword erlang VM relies on Linux specific memory + * mapping tricks. + */ + +/*#define HARDDEBUG 1*/ + +#ifdef __APPLE__ +#define MAP_ANONYMOUS MAP_ANON +#endif + +#define INIT_LOCK() do {erts_mtx_init(&pmmap_mutex, "pmmap");} while(0) + +#define TAKE_LOCK() do {erts_mtx_lock(&pmmap_mutex);} while(0) + +#define RELEASE_LOCK() do {erts_mtx_unlock(&pmmap_mutex);} while(0) + +static erts_mtx_t pmmap_mutex; /* Also needed when !USE_THREADS */ + +typedef struct _free_block { + unsigned long num; /*pages*/ + struct _free_block *next; +} FreeBlock; + +/* Assigned once and for all */ +static size_t pagsz; + +/* Protect with lock */ +static FreeBlock *first; + +static size_t round_up_to_pagesize(size_t size) +{ + size_t x = size / pagsz; + + if ((size % pagsz)) { + ++x; + } + + return pagsz * x; +} + +static size_t round_down_to_pagesize(size_t size) +{ + size_t x = size / pagsz; + + return pagsz * x; +} + +static void *do_map(void *ptr, size_t sz) +{ + void *res; + + if (round_up_to_pagesize(sz) != sz) { +#ifdef HARDDEBUG + fprintf(stderr,"Mapping of address %p with size %ld " + "does not map complete pages\r\n", + (void *) ptr, (unsigned long) sz); +#endif + return NULL; + } + + if (((unsigned long) ptr) % pagsz) { +#ifdef HARDDEBUG + fprintf(stderr,"Mapping of address %p with size %ld " + "is not page aligned\r\n", + (void *) ptr, (unsigned long) sz); +#endif + return NULL; + } + + + res = mmap(ptr, sz, + PROT_READ | PROT_WRITE, MAP_PRIVATE | + MAP_ANONYMOUS | MAP_FIXED, + -1 , 0); + + if (res == MAP_FAILED) { +#ifdef HARDDEBUG + fprintf(stderr,"Mapping of address %p with size %ld failed!\r\n", + (void *) ptr, (unsigned long) sz); +#endif + return NULL; + } + + return res; +} + +static int do_unmap(void *ptr, size_t sz) +{ + void *res; + + if (round_up_to_pagesize(sz) != sz) { +#ifdef HARDDEBUG + fprintf(stderr,"Mapping of address %p with size %ld " + "does not map complete pages\r\n", + (void *) ptr, (unsigned long) sz); +#endif + return 1; + } + + if (((unsigned long) ptr) % pagsz) { +#ifdef HARDDEBUG + fprintf(stderr,"Mapping of address %p with size %ld " + "is not page aligned\r\n", + (void *) ptr, (unsigned long) sz); +#endif + return 1; + } + + + res = mmap(ptr, sz, + PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE + | MAP_FIXED, + -1 , 0); + + if (res == MAP_FAILED) { +#ifdef HARDDEBUG + fprintf(stderr,"Mapping of address %p with size %ld failed!\r\n", + (void *) ptr, (unsigned long) sz); +#endif + return 1; + } + + return 0; +} + +#ifdef __APPLE__ +/* + * The first 4 gig's are protected on Macos X for 64bit processes :( + * The range 0x1000000000 - 0x10FFFFFFFF is selected as an arbitrary + * value of a normally unused range... Real MMAP's will avoid + * it and all 32bit compressed pointers can be in that range... + * More expensive than on Linux where expansion of compressed + * poiters involves no masking (as they are in the first 4 gig's). + * It's also very uncertain if the MAP_NORESERVE flag really has + * any effect in MacOS X. Swap space may always be allocated... + */ +#define SET_RANGE_MIN() /* nothing */ +#define RANGE_MIN 0x1000000000UL +#define RANGE_MAX 0x1100000000UL +#define RANGE_MASK (RANGE_MIN) +#define EXTRA_MAP_FLAGS (MAP_FIXED) +#else +static size_t range_min; +#define SET_RANGE_MIN() do { range_min = (size_t) sbrk(0); } while (0) +#define RANGE_MIN range_min +#define RANGE_MAX 0x100000000UL +#define RANGE_MASK 0UL +#define EXTRA_MAP_FLAGS (0) +#endif + +static int initialize_pmmap(void) +{ + char *p,*q,*rptr; + size_t rsz; + FreeBlock *initial; + + + pagsz = getpagesize(); + SET_RANGE_MIN(); + if (sizeof(void *) != 8) { + erl_exit(1,"Halfword emulator cannot be run in 32bit mode"); + } + + p = (char *) RANGE_MIN; + q = (char *) RANGE_MAX; + + rsz = round_down_to_pagesize(q - p); + + rptr = mmap((void *) p, rsz, + PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | + MAP_NORESERVE | EXTRA_MAP_FLAGS, + -1 , 0); +#ifdef HARDDEBUG + printf("rsz = %ld, pages = %ld, rptr = %p\r\n", + (unsigned long) rsz, (unsigned long) (rsz / pagsz), + (void *) rptr); +#endif + if (!do_map(rptr,pagsz)) { + erl_exit(1,"Could not actually mmap first page for halfword emulator...\n"); + } + initial = (FreeBlock *) rptr; + initial->num = (rsz / pagsz); + initial->next = NULL; + first = initial; + INIT_LOCK(); + return 0; +} + +#ifdef HARDDEBUG +static void dump_freelist(void) +{ + FreeBlock *p = first; + + while (p) { + printf("p = %p\r\np->num = %ld\r\np->next = %p\r\n\r\n", + (void *) p, (unsigned long) p->num, (void *) p->next); + p = p->next; + } +} +#endif + + +static void *pmmap(size_t size) +{ + size_t real_size = round_up_to_pagesize(size); + size_t num_pages = real_size / pagsz; + FreeBlock **block; + FreeBlock *tail; + FreeBlock *res; + TAKE_LOCK(); + for (block = &first; + *block != NULL && (*block)->num < num_pages; + block = &((*block)->next)) + ; + if (!(*block)) { + RELEASE_LOCK(); + return NULL; + } + if ((*block)->num == num_pages) { + /* nice, perfect fit */ + res = *block; + *block = (*block)->next; + } else { + tail = (FreeBlock *) (((char *) ((void *) (*block))) + real_size); + if (!do_map(tail,pagsz)) { +#ifdef HARDDEBUG + fprintf(stderr, "Could not actually allocate page at %p...\r\n", + (void *) tail); +#endif + RELEASE_LOCK(); + return NULL; + } + tail->num = (*block)->num - num_pages; + tail->next = (*block)->next; + res = *block; + *block = tail; + } + RELEASE_LOCK(); + if (!do_map(res,real_size)) { +#ifdef HARDDEBUG + fprintf(stderr, "Could not actually allocate %ld at %p...\r\n", + (unsigned long) real_size, (void *) res); +#endif + return NULL; + } + + return (void *) res; +} + +static int pmunmap(void *p, size_t size) +{ + size_t real_size = round_up_to_pagesize(size); + size_t num_pages = real_size / pagsz; + FreeBlock *block; + FreeBlock *last; + FreeBlock *nb = (FreeBlock *) p; + + if (real_size > pagsz) { + if (do_unmap(((char *) p) + pagsz,real_size - pagsz)) { + return 1; + } + } + + TAKE_LOCK(); + + last = NULL; + block = first; + while(block != NULL && ((void *) block) < p) { + last = block; + block = block->next; + } + + if (block != NULL && + ((void *) block) == ((void *) (((char *) p) + real_size))) { + /* Merge new free block with following */ + nb->num = block->num + num_pages; + nb->next = block->next; + if (do_unmap(block,pagsz)) { + RELEASE_LOCK(); + return 1; + } + } else { + /* just link in */ + nb->num = num_pages; + nb->next = block; + } + if (last != NULL) { + if (p == ((void *) (((char *) last) + (last->num * pagsz)))) { + /* Merge with previous */ + last->num += nb->num; + last->next = nb->next; + if (do_unmap(nb,pagsz)) { + RELEASE_LOCK(); + return 1; + } + } else { + last->next = nb; + } + } else { + first = nb; + } + RELEASE_LOCK(); + return 0; +} + +static void *pmremap(void *old_address, size_t old_size, + size_t new_size) +{ + size_t new_real_size = round_up_to_pagesize(new_size); + size_t new_num_pages = new_real_size / pagsz; + size_t old_real_size = round_up_to_pagesize(old_size); + size_t old_num_pages = old_real_size / pagsz; + if (new_num_pages == old_num_pages) { + return old_address; + } else if (new_num_pages < old_num_pages) { /* Shrink */ + size_t nfb_pages = old_num_pages - new_num_pages; + size_t nfb_real_size = old_real_size - new_real_size; + void *vnfb = (void *) (((char *)old_address) + new_real_size); + FreeBlock *nfb = (FreeBlock *) vnfb; + FreeBlock **block; + TAKE_LOCK(); + for (block = &first; + *block != NULL && (*block) < nfb; + block = &((*block)->next)) + ; + if (!(*block) || + (*block) > ((FreeBlock *)(((char *) vnfb) + nfb_real_size))) { + /* Normal link in */ + if (nfb_pages > 1) { + if (do_unmap((void *)(((char *) vnfb) + pagsz), + (nfb_pages - 1)*pagsz)) { + return NULL; + } + } + nfb->next = (*block); + nfb->num = nfb_pages; + (*block) = nfb; + } else { /* block merge */ + nfb->next = (*block)->next; + nfb->num = nfb_pages + (*block)->num; + /* unmap also the first page of the next freeblock */ + (*block) = nfb; + if (do_unmap((void *)(((char *) vnfb) + pagsz), + nfb_pages*pagsz)) { + return NULL; + } + } + RELEASE_LOCK(); + return old_address; + } else { /* Enlarge */ + FreeBlock **block; + void *old_end = (void *) (((char *)old_address) + old_real_size); + TAKE_LOCK(); + for (block = &first; + *block != NULL && (*block) < (FreeBlock *) old_address; + block = &((*block)->next)) + ; + if ((*block) == NULL || old_end > ((void *) RANGE_MAX) || + (*block) != old_end || + (*block)->num < (new_num_pages - old_num_pages)) { + /* cannot extend */ + void *result; + RELEASE_LOCK(); + result = pmmap(new_size); + if (result == NULL) { + return NULL; + } + memcpy(result,old_address,old_size); + if (pmunmap(old_address,old_size)) { + /* Oups... */ + pmunmap(result,new_size); + return NULL; + } + return result; + } else { /* extend */ + size_t remaining_pages = (*block)->num - + (new_num_pages - old_num_pages); + if (!remaining_pages) { + void *p = (void *) (((char *) (*block)) + pagsz); + void *n = (*block)->next; + size_t x = ((*block)->num - 1) * pagsz; + if (x > 0) { + if (do_map(p,x) == NULL) { + RELEASE_LOCK(); + return NULL; + } + } + (*block) = n; + } else { + FreeBlock *nfb = (FreeBlock *) ((void *) + (((char *) old_address) + + new_real_size)); + void *p = (void *) (((char *) (*block)) + pagsz); + if (do_map(p,new_real_size - old_real_size) == NULL) { + RELEASE_LOCK(); + return NULL; + } + nfb->num = remaining_pages; + nfb->next = (*block)->next; + (*block) = nfb; + } + RELEASE_LOCK(); + return old_address; + } + } +} + +#endif /* HALFWORD_HEAP */ diff --git a/erts/emulator/sys/common/erl_mseg.h b/erts/emulator/sys/common/erl_mseg.h index 1c5aa63e90..d8053eb0d9 100644 --- a/erts/emulator/sys/common/erl_mseg.h +++ b/erts/emulator/sys/common/erl_mseg.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2002-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -58,8 +58,8 @@ typedef struct { typedef struct { int cache; int preserv; - Uint abs_shrink_th; - Uint rel_shrink_th; + UWord abs_shrink_th; + UWord rel_shrink_th; } ErtsMsegOpt_t; #define ERTS_MSEG_DEFAULT_OPT_INITIALIZER \ diff --git a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c index f429a5b51e..2ac86b1ec2 100644 --- a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c +++ b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c @@ -127,7 +127,7 @@ static int control(ErlDrvData drv_data, char **rbuf, int rlen) { PeekNonXQDrvData *dp = (PeekNonXQDrvData *) drv_data; - unsigned int key = 0; + unsigned long key = 0; char *res_str = "ok"; ErlDrvSysInfo si; driver_system_info(&si, sizeof(ErlDrvSysInfo)); diff --git a/erts/emulator/test/obsolete_SUITE.erl b/erts/emulator/test/obsolete_SUITE.erl index 33c4726699..b191f84ee0 100644 --- a/erts/emulator/test/obsolete_SUITE.erl +++ b/erts/emulator/test/obsolete_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -32,9 +32,9 @@ all(doc) -> []; all(suite) -> - case catch erlang:system_info(wordsize) of + case catch erlang:system_info({wordsize,external}) of 4 -> [erl_threads]; - _ -> {skip, "Only expected to work on 32-bit architectures"} + _ -> {skip, "Only expected to work on true 32-bit architectures"} end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index e782d2f293..ba433d4e11 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -35,12 +35,12 @@ %-compile(export_all). -export([all/1, init_per_testcase/2, fin_per_testcase/2]). --export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1]). +-export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1, wordsize/1]). -define(DEFAULT_TIMEOUT, ?t:minutes(2)). all(doc) -> []; -all(suite) -> [process_count, system_version, misc_smoke_tests, heap_size]. +all(suite) -> [process_count, system_version, misc_smoke_tests, heap_size, wordsize]. init_per_testcase(_Case, Config) when is_list(Config) -> Dog = ?t:timetrap(?DEFAULT_TIMEOUT), @@ -145,3 +145,23 @@ heap_size(Config) when is_list(Config) -> ?line Hmin = proplists:get_value(min_heap_size, GCinf), ok. +wordsize(suite) -> + []; +wordsize(doc) -> + ["Tests the various wordsize variants"]; +wordsize(Config) when is_list(Config) -> + ?line A = erlang:system_info(wordsize), + ?line true = is_integer(A), + ?line A = erlang:system_info({wordsize,internal}), + ?line B = erlang:system_info({wordsize,external}), + ?line true = A =< B, + case {B,A} of + {4,4} -> + {comment, "True 32-bit emulator"}; + {8,8} -> + {comment, "True 64-bit emulator"}; + {8,4} -> + {comment, "Halfword 64-bit emulator"}; + Other -> + exit({unexpected_wordsizes,Other}) + end. diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops index 4a859c3094..de19a2e35b 100755 --- a/erts/emulator/utils/beam_makeops +++ b/erts/emulator/utils/beam_makeops @@ -1,20 +1,20 @@ #!/usr/bin/env perl # # %CopyrightBegin% -# -# Copyright Ericsson AB 1998-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 1998-2010. All Rights Reserved. +# # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in # compliance with the License. You should have received a copy of the # Erlang Public License along with this software. If not, it can be # retrieved online at http://www.erlang.org/. -# +# # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. -# +# # %CopyrightEnd% # use strict; @@ -499,7 +499,11 @@ sub emulator_output { print "\n"; print "#ifdef ARCH_64\n"; print "# define BEAM_LOOSE_MASK 0x1FFFUL\n"; + print "#if HALFWORD_HEAP\n"; + print "# define BEAM_TIGHT_MASK 0x1FFCUL\n"; + print "#else\n"; print "# define BEAM_TIGHT_MASK 0x1FF8UL\n"; + print "#endif\n"; print "# define BEAM_LOOSE_SHIFT 16\n"; print "# define BEAM_TIGHT_SHIFT 16\n"; print "#else\n"; @@ -813,7 +817,7 @@ sub basic_generator { # if ($flags =~ /-pack/ && $hot) { - ($prefix, $pack_spec, @args) = &do_pack(@args); + ($prefix, $pack_spec, @args) = &do_pack(@args); } # @@ -907,16 +911,16 @@ sub basic_generator { my($code); if (defined $macro{$name}) { my($macro_code) = "$prefix$macro(" . join(', ', @f) . ");"; - $var_decls .= "Uint tmp_packed1;" + $var_decls .= "BeamInstr tmp_packed1;" if $macro_code =~ /tmp_packed1/; - $var_decls .= "Uint tmp_packed2;" + $var_decls .= "BeamInstr tmp_packed2;" if $macro_code =~ /tmp_packed2/; if ($flags =~ /-nonext/) { $code = "$macro_code\n"; } else { $code = join("\n", "{ $var_decls", - "Eterm* next;", + "BeamInstr* next;", "PreFetch($size, next);", "$macro_code", "NextPF($size, next);", diff --git a/erts/emulator/utils/make_tables b/erts/emulator/utils/make_tables index b5391234cf..918ef62094 100755 --- a/erts/emulator/utils/make_tables +++ b/erts/emulator/utils/make_tables @@ -1,20 +1,20 @@ #!/usr/bin/env perl # # %CopyrightBegin% -# -# Copyright Ericsson AB 1999-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 1999-2010. All Rights Reserved. +# # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in # compliance with the License. You should have received a copy of the # Erlang Public License along with this software. If not, it can be # retrieved online at http://www.erlang.org/. -# +# # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. -# +# # %CopyrightEnd% # use strict; @@ -184,7 +184,7 @@ for ($i = 0; $i < @bif; $i++) { my $arity = $bif[$i]->[2]; my $args = join(', ', 'Process*', ('Eterm') x $arity); print "Eterm $bif[$i]->[3]($args);\n"; - print "Eterm wrap_$bif[$i]->[3]($args, Uint *I);\n"; + print "Eterm wrap_$bif[$i]->[3]($args, UWord *I);\n"; } print "#endif\n"; @@ -225,15 +225,15 @@ for ($i = 0; $i < @bif; $i++) { for ($arg = 1; $arg <= $arity; $arg++) { print ", Eterm arg$arg"; } - print ", Uint *I)\n"; + print ", UWord *I)\n"; print "{\n"; print " return erts_bif_trace($i, p"; for ($arg = 1; $arg <= 3; $arg++) { if ($arg <= $arity) { print ", arg$arg"; - } elsif ($arg == ($arity + 1)) { - # Place I in correct position - print ", (Eterm) I"; + #} elsif ($arg == ($arity + 1)) { + # # Place I in correct position + # print ", (Eterm) I"; } else { print ", 0"; } diff --git a/erts/include/erl_int_sizes_config.h.in b/erts/include/erl_int_sizes_config.h.in index ef49995732..4b8a8e1b98 100644 --- a/erts/include/erl_int_sizes_config.h.in +++ b/erts/include/erl_int_sizes_config.h.in @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2004-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2004-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -31,3 +31,6 @@ /* The number of bytes in a long long. */ #undef SIZEOF_LONG_LONG + +/* Define if building a halfword-heap 64bit emulator (needed for NIF's) */ +#undef HALFWORD_HEAP_EMULATOR diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl index 66ac0422eb..56283f4d3d 100644 --- a/lib/runtime_tools/src/dbg.erl +++ b/lib/runtime_tools/src/dbg.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(dbg). @@ -945,7 +945,7 @@ dhandler(end_of_trace, Out) -> dhandler(Trace, Out) when element(1, Trace) == trace, tuple_size(Trace) >= 3 -> dhandler1(Trace, tuple_size(Trace), Out); dhandler(Trace, Out) when element(1, Trace) == trace_ts, tuple_size(Trace) >= 4 -> - dhandler1(Trace, tuple_size(Trace)-1, Out); + dhandler1(Trace, tuple_size(Trace)-1, element(tuple_size(Trace),Trace), Out); dhandler(Trace, Out) when element(1, Trace) == drop, tuple_size(Trace) =:= 2 -> io:format(Out, "*** Dropped ~p messages.~n", [element(2,Trace)]), Out; @@ -978,24 +978,18 @@ dhandler(_Trace, Out) -> Out. dhandler1(Trace, Size, Out) -> -%%%! Self = self(), From = element(2, Trace), case element(3, Trace) of 'receive' -> case element(4, Trace) of {dbg,ok} -> ok; - Message -> io:format(Out, "(~p) << ~p~n", [From,Message]) + Message -> + io:format(Out, "(~p) << ~p~n", [From,Message]) end; 'send' -> Message = element(4, Trace), - case element(5, Trace) of -%%%! This causes messages to disappear when used by ttb (observer). Tests -%%%! so far show that there is no difference in results with dbg even if I -%%%! comment it out, so I hope this is only some old code which isn't -%%%! needed anymore... /siri -%%%! Self -> ok; - To -> io:format(Out, "(~p) ~p ! ~p~n", [From,To,Message]) - end; + To = element(5, Trace), + io:format(Out, "(~p) ~p ! ~p~n", [From,To,Message]); call -> case element(4, Trace) of MFA when Size == 5 -> @@ -1028,6 +1022,51 @@ dhandler1(Trace, Size, Out) -> end, Out. +dhandler1(Trace, Size, TS, Out) -> + From = element(2, Trace), + case element(3, Trace) of + 'receive' -> + case element(4, Trace) of + {dbg,ok} -> ok; + Message -> + io:format(Out, "(~p) << ~p (Timestamp: ~p)~n", [From,Message,TS]) + end; + 'send' -> + Message = element(4, Trace), + To = element(5, Trace), + io:format(Out, "(~p) ~p ! ~p (Timestamp: ~p)~n", [From,To,Message,TS]); + call -> + case element(4, Trace) of + MFA when Size == 5 -> + Message = element(5, Trace), + io:format(Out, "(~p) call ~s (~p) (Timestamp: ~p)~n", [From,ffunc(MFA),Message,TS]); + MFA -> + io:format(Out, "(~p) call ~s (Timestamp: ~p)~n", [From,ffunc(MFA),TS]) + end; + return -> %% To be deleted... + case element(4, Trace) of + MFA when Size == 5 -> + Ret = element(5, Trace), + io:format(Out, "(~p) old_ret ~s -> ~p (Timestamp: ~p)~n", [From,ffunc(MFA),Ret,TS]); + MFA -> + io:format(Out, "(~p) old_ret ~s (Timestamp: ~p)~n", [From,ffunc(MFA),TS]) + end; + return_from -> + MFA = element(4, Trace), + Ret = element(5, Trace), + io:format(Out, "(~p) returned from ~s -> ~p (Timestamp: ~p)~n", [From,ffunc(MFA),Ret,TS]); + return_to -> + MFA = element(4, Trace), + io:format(Out, "(~p) returning to ~s (Timestamp: ~p)~n", [From,ffunc(MFA),TS]); + spawn when Size == 5 -> + Pid = element(4, Trace), + MFA = element(5, Trace), + io:format(Out, "(~p) spawn ~p as ~s (Timestamp: ~p)~n", [From,Pid,ffunc(MFA),TS]); + Op -> + io:format(Out, "(~p) ~p ~s (Timestamp: ~p)~n", [From,Op,ftup(Trace,4,Size),TS]) + end, + Out. + %%% These f* functions returns non-flat strings diff --git a/lib/wx/c_src/wxe_driver.c b/lib/wx/c_src/wxe_driver.c index 3b951bec57..310325ea26 100644 --- a/lib/wx/c_src/wxe_driver.c +++ b/lib/wx/c_src/wxe_driver.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2008-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2008-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -113,6 +113,7 @@ wxe_driver_start(ErlDrvPort port, char *buff) data->driver_data = NULL; data->bin = NULL; data->port = port; + data->pdl = driver_pdl_create(port); if(WXE_DRV_PORT == 0) { for(; *buff != 32; buff++); buff++; @@ -124,7 +125,7 @@ wxe_driver_start(ErlDrvPort port, char *buff) if(!(start_native_gui(data) == 1)) return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */ } else { - meta_command(CREATE_PORT,data); + meta_command(CREATE_PORT,data); } return (ErlDrvData) data; } diff --git a/lib/wx/c_src/wxe_driver.h b/lib/wx/c_src/wxe_driver.h index 8437b4eb36..13a17e356f 100644 --- a/lib/wx/c_src/wxe_driver.h +++ b/lib/wx/c_src/wxe_driver.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2008-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2008-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -45,6 +45,7 @@ typedef struct wxe_data_def { WXEBinRef * bin; /* Argument binaries */ ErlDrvPort port; int is_cbport; + ErlDrvPDL pdl; } wxe_data; diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index 4486dff63b..528a08e654 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -101,7 +101,7 @@ int start_native_gui(wxe_data *sd) init_caller = driver_connected(sd->port); if((res = erl_drv_thread_create((char *)"wxwidgets", - &wxe_thread,wxe_main_loop,NULL,NULL)) == 0) { + &wxe_thread,wxe_main_loop,(void *) sd->pdl,NULL)) == 0) { erl_drv_mutex_lock(wxe_status_m); for(;wxe_status == WXE_NOT_INITIATED;) { erl_drv_cond_wait(wxe_status_c, wxe_status_m); @@ -179,12 +179,15 @@ void meta_command(int what, wxe_data *sd) { * wxWidgets Thread * ************************************************************/ -void *wxe_main_loop(void * not_used) +void *wxe_main_loop(void *vpdl) { int result; int argc = 1; char * temp = (char *) "Erlang\0"; char ** argv = &temp; + ErlDrvPDL pdl = (ErlDrvPDL) vpdl; + + driver_pdl_inc_refc(pdl); // ErlDrvSysInfo einfo; // driver_system_info(&einfo, sizeof(ErlDrvSysInfo)); @@ -199,6 +202,7 @@ void *wxe_main_loop(void * not_used) if(result >= 0 && wxe_status == WXE_INITIATED) { /* We are done try to make a clean exit */ wxe_status = WXE_EXITED; + driver_pdl_dec_refc(pdl); erl_drv_thread_exit(NULL); return NULL; } else { @@ -206,6 +210,7 @@ void *wxe_main_loop(void * not_used) wxe_status = WXE_ERROR; erl_drv_cond_signal(wxe_status_c); erl_drv_mutex_unlock(wxe_status_m); + driver_pdl_dec_refc(pdl); return NULL; } } @@ -401,11 +406,12 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process) node = batch->GetFirst()) { wxeCommand *event = (wxeCommand *)node->GetData(); + wxeMemEnv *memenv = getMemEnv(event->port); batch->Erase(node); if(event->caller == process || // Callbacks from CB process only event->op == WXE_CB_START || // Recursive event callback allow // Allow connect_cb during CB i.e. msg from wxe_server. - event->caller == driver_connected(event->port)) + event->caller == memenv->owner) { switch(event->op) { case WXE_BATCH_END: @@ -456,6 +462,9 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process) void WxeApp::newMemEnv(wxeMetaCommand& Ecmd) { wxeMemEnv * memenv = new wxeMemEnv(); + + driver_pdl_inc_refc(Ecmd.pdl); + for(int i = 0; i < global_me->next; i++) { memenv->ref2ptr[i] = global_me->ref2ptr[i]; } @@ -576,6 +585,7 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) { // } // fflush(stderr); delete memenv; + driver_pdl_dec_refc(Ecmd.pdl); refmap.erase((ErlDrvTermData) Ecmd.port); } diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h index 5e9d596633..39c02f8c1a 100644 --- a/lib/wx/c_src/wxe_impl.h +++ b/lib/wx/c_src/wxe_impl.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2008-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2008-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ @@ -34,15 +34,16 @@ class wxeMetaCommand : public wxEvent public: wxeMetaCommand(wxe_data *sd, int EvId) : wxEvent(EvId, wxeEVT_META_COMMAND) - { caller = driver_caller(sd->port); port = sd->port; } ; + { caller = driver_caller(sd->port); port = sd->port; pdl = sd->pdl; } ; wxeMetaCommand(const wxeMetaCommand& event) : wxEvent(event) - { caller = event.caller; port = event.port; }; + { caller = event.caller; port = event.port; pdl = event.pdl; }; virtual ~wxeMetaCommand() {}; virtual wxEvent *Clone() const { return new wxeMetaCommand(*this); } ErlDrvTermData caller; ErlDrvPort port; + ErlDrvPDL pdl; }; class wxeCommand : public wxObject |