aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/external.c
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2010-03-22 14:51:35 +0000
committerErlang/OTP <[email protected]>2010-03-22 15:56:43 +0100
commita4b4d36cdbbd692123443a1d3f19f1c452963201 (patch)
tree218002c4a2b38f69eb67d6388c8034820812fd47 /erts/emulator/beam/external.c
parent835dba95f810cc925ac856171014b9dbea8c90be (diff)
parent24095d93fb28bdd60abe771a426e39c6ff0f72c7 (diff)
downloadotp-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
Diffstat (limited to 'erts/emulator/beam/external.c')
-rw-r--r--erts/emulator/beam/external.c162
1 files changed, 108 insertions, 54 deletions
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:
{