Permalink
Browse files

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.
  • Loading branch information...
1 parent 775191a commit fb94cd974dc03baf149264ca4f4d50c6d1f80f21 @bufflig bufflig committed with bjorng Jan 20, 2010
Showing with 1,492 additions and 1,049 deletions.
  1. +4 −0 configure.in
  2. +27 −0 erts/configure.in
  3. +19 −19 erts/emulator/beam/beam_bif_load.c
  4. +3 −3 erts/emulator/beam/beam_bp.c
  5. +8 −8 erts/emulator/beam/beam_bp.h
  6. +4 −4 erts/emulator/beam/beam_catches.c
  7. +3 −3 erts/emulator/beam/beam_catches.h
  8. +1 −1 erts/emulator/beam/beam_debug.c
  9. +254 −225 erts/emulator/beam/beam_emu.c
  10. +224 −147 erts/emulator/beam/beam_load.c
  11. +6 −6 erts/emulator/beam/beam_load.h
  12. +9 −4 erts/emulator/beam/bif.c
  13. +12 −9 erts/emulator/beam/bif.h
  14. +24 −0 erts/emulator/beam/big.c
  15. +9 −2 erts/emulator/beam/big.h
  16. +1 −1 erts/emulator/beam/break.c
  17. +4 −4 erts/emulator/beam/dist.c
  18. +55 −17 erts/emulator/beam/erl_alloc.c
  19. +1 −1 erts/emulator/beam/erl_alloc.h
  20. +1 −0 erts/emulator/beam/erl_alloc.types
  21. +69 −68 erts/emulator/beam/erl_alloc_util.c
  22. +26 −26 erts/emulator/beam/erl_alloc_util.h
  23. +1 −1 erts/emulator/beam/erl_async.c
  24. +2 −2 erts/emulator/beam/erl_bif_chksum.c
  25. +6 −6 erts/emulator/beam/erl_bif_info.c
  26. +1 −1 erts/emulator/beam/erl_bif_op.c
  27. +4 −4 erts/emulator/beam/erl_bif_re.c
  28. +3 −3 erts/emulator/beam/erl_bif_timer.c
  29. +12 −12 erts/emulator/beam/erl_bif_trace.c
  30. +1 −1 erts/emulator/beam/erl_binary.h
  31. +2 −2 erts/emulator/beam/erl_bits.c
  32. +24 −18 erts/emulator/beam/erl_db.c
  33. +2 −2 erts/emulator/beam/erl_db_tree.c
  34. +69 −67 erts/emulator/beam/erl_db_util.c
  35. +3 −3 erts/emulator/beam/erl_db_util.h
  36. +2 −2 erts/emulator/beam/erl_debug.c
  37. +1 −1 erts/emulator/beam/erl_driver.h
  38. +4 −4 erts/emulator/beam/erl_fun.c
  39. +4 −4 erts/emulator/beam/erl_fun.h
  40. +3 −3 erts/emulator/beam/erl_gc.c
  41. +24 −24 erts/emulator/beam/erl_goodfit_alloc.c
  42. +10 −10 erts/emulator/beam/erl_goodfit_alloc.h
  43. +37 −37 erts/emulator/beam/erl_instrument.c
  44. +1 −1 erts/emulator/beam/erl_message.h
  45. +13 −13 erts/emulator/beam/erl_mtrace.c
  46. +35 −27 erts/emulator/beam/erl_nif.c
  47. +1 −1 erts/emulator/beam/erl_node_container_utils.h
  48. +14 −0 erts/emulator/beam/erl_node_tables.c
  49. +1 −1 erts/emulator/beam/erl_node_tables.h
  50. +3 −3 erts/emulator/beam/erl_printf_term.c
  51. +23 −19 erts/emulator/beam/erl_process.c
  52. +15 −11 erts/emulator/beam/erl_process.h
  53. +11 −11 erts/emulator/beam/erl_process_dump.c
  54. +3 −3 erts/emulator/beam/erl_term.c
  55. +23 −22 erts/emulator/beam/erl_term.h
  56. +16 −24 erts/emulator/beam/erl_trace.c
  57. +10 −10 erts/emulator/beam/erl_unicode.c
  58. +4 −0 erts/emulator/beam/erl_vm.h
  59. +3 −3 erts/emulator/beam/error.h
  60. +5 −5 erts/emulator/beam/export.c
  61. +5 −1 erts/emulator/beam/export.h
  62. +84 −43 erts/emulator/beam/external.c
  63. +1 −1 erts/emulator/beam/external.h
  64. +64 −9 erts/emulator/beam/global.h
  65. +6 −2 erts/emulator/beam/io.c
  66. +2 −2 erts/emulator/beam/module.h
  67. +42 −0 erts/emulator/beam/sys.h
  68. +105 −60 erts/emulator/beam/utils.c
  69. +8 −8 erts/emulator/drivers/common/efile_drv.c
  70. +3 −3 erts/emulator/drivers/unix/ttsl_drv.c
  71. +2 −2 erts/emulator/sys/common/erl_mseg.h
  72. +5 −4 erts/emulator/utils/beam_makeops
  73. +5 −5 erts/emulator/utils/make_tables
View
@@ -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])
View
@@ -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
@@ -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(UWord* 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(UWord* 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;
+ UWord* code;
+ UWord* 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 = (UWord *)((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;
+ UWord* start;
char* mod_start;
Uint mod_size;
- Eterm* end;
+ UWord* 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 = (UWord *)((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;
+ UWord* fun_code;
fun_code = funp->fe->address;
- if (INSIDE((Eterm *) funp->fe->address)) {
+ if (INSIDE((UWord *) 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;
+ UWord* code;
+ UWord* 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 = (UWord *)((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(UWord* 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] == (UWord) em_apply_bif)) {
continue;
}
ep->address = ep->code+3;
- ep->code[3] = (Uint) em_call_error_handler;
+ ep->code[3] = (UWord) 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(UWord* code)
{
return ((Eterm *)code[MI_FUNCTIONS])[1] != 0;
}
@@ -262,7 +262,7 @@ 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,
+erts_trace_break(Process *p, UWord *pc, Eterm *args,
Uint32 *ret_flags, Eterm *tracer_pid) {
Eterm tpid1, tpid2;
BpDataTrace *bdt = (BpDataTrace *) pc[-4];
@@ -296,7 +296,7 @@ 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, UWord *pc, Eterm *args, int local,
Eterm *tracer_pid) {
BpDataTrace *bdt = (BpDataTrace *) pc[-4];
@@ -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(UWord *pc, Binary **match_spec_ret, Eterm *tracer_pid_ret) {
BpDataTrace *bdt = (BpDataTrace *) pc[-4];
if (bdt) {
@@ -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] == (UWord) BeamOp(op_i_func_info_IaaI)); \
ASSERT(bdc); \
bdc = (BpDataCount *) bdc->next; \
ASSERT(bdc); \
- (pc)[-4] = (Uint) bdc; \
+ (pc)[-4] = (UWord) 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] == (UWord) BeamOp(op_i_func_info_IaaI)); \
ASSERT(bd); \
bd = bd->next; \
ASSERT(bd); \
- (pc)[-4] = (Uint) bd; \
+ (pc)[-4] = (UWord) bd; \
*(instr_result) = bd->orig_instr; \
} while (0)
@@ -146,16 +146,16 @@ 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);
-Uint erts_trace_break(Process *p, Uint *pc, Eterm *args,
+Uint erts_trace_break(Process *p, UWord *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, UWord *pc, Eterm *args,
int local, Eterm *tracer_pid);
-int erts_is_trace_break(Uint *pc, Binary **match_spec_ret,
+int 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_rte);
-int erts_is_mtrace_bif(Uint *pc, Binary **match_spec_ret,
+int erts_is_mtrace_bif(UWord *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);
@@ -26,7 +26,7 @@
/* XXX: should use dynamic reallocation */
#define TABSIZ (16*1024)
static struct {
- Eterm *cp;
+ UWord *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(UWord *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)
+UWord *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, UWord *code, unsigned code_bytes)
{
unsigned i, cdr;
@@ -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(UWord* cp, unsigned cdr);
+UWord *beam_catches_car(unsigned i);
+void beam_catches_delmod(unsigned head, UWord* code, unsigned code_bytes);
#define catch_pc(x) beam_catches_car(catch_val((x)))
@@ -38,7 +38,7 @@
#include "beam_bp.h"
#include "erl_binary.h"
-#ifdef ARCH_64
+#ifdef ARCH_64 /* XXX:PaN Halfword? */
# define HEXF "%016bpX"
#else
# define HEXF "%08bpX"
Oops, something went wrong.

0 comments on commit fb94cd9

Please sign in to comment.