summaryrefslogtreecommitdiffstats
path: root/byterun/intern.c
diff options
context:
space:
mode:
Diffstat (limited to 'byterun/intern.c')
-rw-r--r--byterun/intern.c126
1 files changed, 92 insertions, 34 deletions
diff --git a/byterun/intern.c b/byterun/intern.c
index b58dd43a4..15064ce81 100644
--- a/byterun/intern.c
+++ b/byterun/intern.c
@@ -81,9 +81,10 @@ static void intern_rec(dest)
unsigned int code;
tag_t tag;
mlsize_t size, len, ofs_ind;
- value v;
+ value v, clos;
asize_t ofs;
header_t header;
+ char cksum[16];
tailcall:
code = read8u();
@@ -98,7 +99,7 @@ static void intern_rec(dest)
} else {
v = Val_hp(intern_dest);
*dest = v;
- intern_obj_table[obj_counter++] = v;
+ if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v;
dest = (value *) (intern_dest + 1);
*intern_dest = Make_header(size, tag, intern_color);
intern_dest += 1 + size;
@@ -117,7 +118,7 @@ static void intern_rec(dest)
read_string:
size = (len + sizeof(value)) / sizeof(value);
v = Val_hp(intern_dest);
- intern_obj_table[obj_counter++] = v;
+ if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v;
*intern_dest = Make_header(size, String_tag, intern_color);
intern_dest += 1 + size;
Field(v, size - 1) = 0;
@@ -147,7 +148,7 @@ static void intern_rec(dest)
case CODE_SHARED8:
ofs = read8u();
read_shared:
- Assert(ofs > 0 && ofs <= obj_counter);
+ Assert(ofs > 0 && ofs <= obj_counter && intern_obj_table != NULL);
v = intern_obj_table[obj_counter - ofs];
break;
case CODE_SHARED16:
@@ -174,7 +175,7 @@ static void intern_rec(dest)
invalid_argument("input_value: non-standard floats");
}
v = Val_hp(intern_dest);
- intern_obj_table[obj_counter++] = v;
+ if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v;
*intern_dest = Make_header(Double_wosize, Double_tag, intern_color);
intern_dest += 1 + Double_wosize;
readblock((char *) v, 8);
@@ -191,7 +192,7 @@ static void intern_rec(dest)
}
size = len * Double_wosize;
v = Val_hp(intern_dest);
- intern_obj_table[obj_counter++] = v;
+ if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v;
*intern_dest = Make_header(size, Double_array_tag, intern_color);
intern_dest += 1 + size;
readblock((char *) v, len * 8);
@@ -209,8 +210,23 @@ static void intern_rec(dest)
case CODE_DOUBLE_ARRAY32_BIG:
len = read32u();
goto read_double_array;
+ case CODE_CODEPOINTER:
+ ofs = read32u();
+ readblock(cksum, 16);
+ if (memcmp(cksum, code_checksum(), 16) != 0) {
+ intern_cleanup();
+ failwith("input_value: code mismatch");
+ }
+ v = (value) (code_area_start + ofs);
+ break;
+ case CODE_INFIXPOINTER:
+ ofs = read32u();
+ intern_rec(&clos);
+ v = clos + ofs;
+ break;
default:
- fatal_error("intern_rec");
+ intern_cleanup();
+ failwith("input_value: ill-formed message");
}
}
}
@@ -237,7 +253,10 @@ static void intern_alloc(whsize, num_objects)
Assert (intern_color == White || intern_color == Black);
intern_dest = (header_t *) Hp_val(intern_block);
obj_counter = 0;
- intern_obj_table = (value *) stat_alloc(num_objects * sizeof(value));
+ if (num_objects > 0)
+ intern_obj_table = (value *) stat_alloc(num_objects * sizeof(value));
+ else
+ intern_obj_table = NULL;
}
}
@@ -280,36 +299,75 @@ value input_value(chan) /* ML */
value input_value_from_string(str, ofs) /* ML */
value str, ofs;
{
- uint32 magic;
- mlsize_t block_len, num_objects, size_32, size_64, whsize;
- value res;
- value obj = Val_unit;
+ mlsize_t num_objects, size_32, size_64, whsize;
+ value obj;
- Begin_roots2(str, obj);
- intern_src = &Byte_u(str, Long_val(ofs));
- intern_input_malloced = 0;
- magic = read32u();
- if (magic != Intext_magic_number) failwith("input_value: bad object");
- block_len = read32u();
- num_objects = read32u();
- size_32 = read32u();
- size_64 = read32u();
- /* Allocate result */
+ intern_src = &Byte_u(str, Long_val(ofs) + 2*4);
+ intern_input_malloced = 0;
+ num_objects = read32u();
+ size_32 = read32u();
+ size_64 = read32u();
+ /* Allocate result */
#ifdef ARCH_SIXTYFOUR
- whsize = size_64;
+ whsize = size_64;
#else
- whsize = size_32;
+ whsize = size_32;
#endif
+ Begin_root(str);
intern_alloc(whsize, num_objects);
- intern_src = &Byte_u(str, Long_val(ofs) + 5*4); /* If a GC occurred */
- /* Fill it in */
- intern_rec(&obj);
- /* Free everything */
- if (intern_obj_table != NULL) stat_free((char *) intern_obj_table);
- /* Build result */
- res = alloc_tuple(2);
- Field(res, 0) = obj;
- Field(res, 1) = Val_long(Long_val(ofs) + 5*4 + block_len);
End_roots();
- return res;
+ intern_src = &Byte_u(str, Long_val(ofs) + 5*4); /* If a GC occurred */
+ /* Fill it in */
+ intern_rec(&obj);
+ /* Free everything */
+ if (intern_obj_table != NULL) stat_free((char *) intern_obj_table);
+ return obj;
}
+
+value marshal_data_size(buff, ofs) /* ML */
+ value buff, ofs;
+{
+ uint32 magic;
+ mlsize_t block_len;
+
+ intern_src = &Byte_u(buff, Long_val(ofs));
+ intern_input_malloced = 0;
+ magic = read32u();
+ if (magic != Intext_magic_number) failwith("Marshal.data_size: bad object");
+ block_len = read32u();
+ return Val_long(block_len);
+}
+
+/* Return an MD5 checksum of the code area */
+
+#ifdef NATIVE_CODE
+
+#include "md5.h"
+
+char * code_checksum()
+{
+ static char checksum[16];
+ static int checksum_computed = 0;
+
+ if (! checksum_computed) {
+ struct MD5Context ctx;
+ MD5Init(&ctx);
+ MD5Update(&ctx,
+ (unsigned char *) code_area_start,
+ code_area_end - code_area_start);
+ MD5Final(checksum, &ctx);
+ checksum_computed = 1;
+ }
+ return checksum;
+}
+
+#else
+
+#include "fix_code.h"
+
+char * code_checksum()
+{
+ return code_md5;
+}
+
+#endif