From 5a8e6c4183a30f3b10de22fa5ba80950dfb2adea Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Mon, 7 Dec 2009 15:25:32 +0100 Subject: Fit all heap data into the 32-bit address range This is the first step in the implementation of the half-word emulator, a 64-bit emulator where all pointers to heap data will be stored in 32-bit words. Code specific for this emulator variant is conditionally compiled when the HALFWORD_HEAP define has a non-zero value. First force all pointers to heap data to fall into a single 32-bit range, but still store them in 64-bit words. Temporary term data stored on C stack is moved into scheduler specific storage (allocated as heaps) and macros are added to make this happen only in emulators where this is needed. For a vanilla VM the temporary terms are still stored on the C stack. --- erts/emulator/beam/global.h | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'erts/emulator/beam/global.h') diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index cab249a53f..03e97a0ce4 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1839,4 +1839,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 -- cgit v1.2.3 From fb94cd974dc03baf149264ca4f4d50c6d1f80f21 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Wed, 20 Jan 2010 16:26:14 +0100 Subject: Store pointers to heap data in 32-bit words Store Erlang terms in 32-bit entities on the heap, expanding the pointers to 64-bit when needed. This works because all terms are stored on addresses in the 32-bit address range (the 32 most significant bits of pointers to term data are always 0). Introduce a new datatype called UWord (along with its companion SWord), which is an integer having the exact same size as the machine word (a void *), but might be larger than Eterm/Uint. Store code as machine words, as the instructions are pointers to executable code which might reside outside the 32-bit address range. Continuation pointers are stored on the 32-bit stack and hence must point to addresses in the low range, which means that loaded beam code much be placed in the low 32-bit address range (but, as said earlier, the instructions themselves are full words). No Erlang term data can be stored on C stacks (enforced by an earlier commit). This version gives a prompt, but test cases still fail (and dump core). The loader (and emulator loop) has instruction packing disabled. The main issues has been in rewriting loader and actual virtual machine. Subsystems (like distribution) does not work yet. --- erts/emulator/beam/global.h | 73 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 9 deletions(-) (limited to 'erts/emulator/beam/global.h') diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 03e97a0ce4..2afb6775b5 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); +UWord* find_function_from_pc(UWord* 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); @@ -1554,12 +1609,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, UWord 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, UWord* fi, Eterm retval, Eterm *tracer_pid); +void erts_trace_exception(Process* p, UWord mfa[], Eterm class, Eterm value, Eterm *tracer); -void erts_trace_return_to(Process *p, Uint *pc); +void erts_trace_return_to(Process *p, UWord *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 +1644,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, UWord *I); #ifdef ERTS_SMP void erts_send_pending_trace_msgs(ErtsSchedulerData *esdp); @@ -1606,7 +1661,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]; -- cgit v1.2.3 From 0cbb78132f50be8ba38051963314b9722c1aba05 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Thu, 4 Feb 2010 12:15:29 +0100 Subject: Fix the BEAM dissambler for the half-word emulator --- erts/emulator/beam/global.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'erts/emulator/beam/global.h') diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 2afb6775b5..ebe7302373 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1570,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; -- cgit v1.2.3 From 20ba5ed3c281d3f0be587395fa66182873d229f0 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Thu, 4 Feb 2010 15:21:36 +0100 Subject: Add the BeamInstr data type for loaded BEAM code For cleanliness, use BeamInstr instead of the UWord data type to any machine-sized words that are used for BEAM instructions. Only use UWord for untyped words in general. --- erts/emulator/beam/global.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'erts/emulator/beam/global.h') diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index ebe7302373..cefdf80fb4 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -856,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); -UWord* find_function_from_pc(UWord* 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); @@ -1611,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, UWord 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, UWord* fi, Eterm retval, Eterm *tracer_pid); -void erts_trace_exception(Process* p, UWord 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, UWord *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); @@ -1646,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, UWord *I); + Eterm arg1, Eterm arg2, Eterm arg3, BeamInstr *I); #ifdef ERTS_SMP void erts_send_pending_trace_msgs(ErtsSchedulerData *esdp); -- cgit v1.2.3