Last active
March 15, 2019 15:40
-
-
Save corwin-of-amber/9806eb4cb64b53d563e0f97ef98fea61 to your computer and use it in GitHub Desktop.
Override js_of_ocaml's Marshal functionality with 32-bit truncation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is a hack to circumvent a discrepancy arising when Coq is compiled | |
* as a 64-bit library and then passed through js_of_ocaml, resulting in | |
* 32-bit JavaScript code. | |
* As a whole, the Coq codebase makes little use of integer arithmetic and | |
* does not create huge arrays of more than 2^31-1 elements. An exception | |
* to this is hash values calculated for storing various Coq types in maps | |
* and hash tables and to speed up comparisons. | |
* Though the values themselves are meaningless, they are unfortunately | |
* stored in .vo files through use of the Marshal module, and lead to files | |
* that cannot be read back via 32-bit code. | |
* | |
* As 32-bit support is declining (e.g. the following issue relating to | |
* macOS builds of OCaml: https://github.com/ocaml/ocaml/issues/6900), | |
* there may be no escape from building 64-bit Coq, both core and libraries. | |
* This requires a patch to jsoo's Marshal primitive that will not throw | |
* when encountering a 64-bit integer. The version below truncates such | |
* values. It may be extremely fragile, but so far, seems to work. | |
*/ | |
//Provides: caml_input_value_from_reader mutable | |
//Requires: caml_failwith | |
//Requires: caml_float_of_bytes, caml_int64_of_bytes | |
/*** !!! This overrides the implementation from js_of_ocaml !!! ***/ | |
function caml_input_value_from_reader(reader, ofs) { | |
var _magic = reader.read32u () | |
var _block_len = reader.read32u (); | |
var num_objects = reader.read32u (); | |
var _size_32 = reader.read32u (); | |
var _size_64 = reader.read32u (); | |
var stack = []; | |
var intern_obj_table = (num_objects > 0)?[]:null; | |
var obj_counter = 0; | |
function intern_rec () { | |
var code = reader.read8u (); | |
if (code >= 0x40 /*cst.PREFIX_SMALL_INT*/) { | |
if (code >= 0x80 /*cst.PREFIX_SMALL_BLOCK*/) { | |
var tag = code & 0xF; | |
var size = (code >> 4) & 0x7; | |
var v = [tag]; | |
if (size == 0) return v; | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
stack.push(v, size); | |
return v; | |
} else | |
return (code & 0x3F); | |
} else { | |
if (code >= 0x20/*cst.PREFIX_SMALL_STRING */) { | |
var len = code & 0x1F; | |
var v = reader.readstr (len); | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
return v; | |
} else { | |
switch(code) { | |
case 0x00: //cst.CODE_INT8: | |
return reader.read8s (); | |
case 0x01: //cst.CODE_INT16: | |
return reader.read16s (); | |
case 0x02: //cst.CODE_INT32: | |
return reader.read32s (); | |
case 0x03: //cst.CODE_INT64: | |
reader.read32s (); return reader.read32s (); // <------------ HERE | |
//caml_failwith("input_value: integer too large"); // (ouch) | |
break; | |
case 0x04: //cst.CODE_SHARED8: | |
var offset = reader.read8u (); | |
return intern_obj_table[obj_counter - offset]; | |
case 0x05: //cst.CODE_SHARED16: | |
var offset = reader.read16u (); | |
return intern_obj_table[obj_counter - offset]; | |
case 0x06: //cst.CODE_SHARED32: | |
var offset = reader.read32u (); | |
return intern_obj_table[obj_counter - offset]; | |
case 0x08: //cst.CODE_BLOCK32: | |
var header = reader.read32u (); | |
var tag = header & 0xFF; | |
var size = header >> 10; | |
var v = [tag]; | |
if (size == 0) return v; | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
stack.push(v, size); | |
return v; | |
case 0x13: //cst.CODE_BLOCK64: | |
caml_failwith ("input_value: data block too large"); | |
break; | |
case 0x09: //cst.CODE_STRING8: | |
var len = reader.read8u(); | |
var v = reader.readstr (len); | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
return v; | |
case 0x0A: //cst.CODE_STRING32: | |
var len = reader.read32u(); | |
var v = reader.readstr (len); | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
return v; | |
case 0x0C: //cst.CODE_DOUBLE_LITTLE: | |
var t = new Array(8);; | |
for (var i = 0;i < 8;i++) t[7 - i] = reader.read8u (); | |
var v = caml_float_of_bytes (t); | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
return v; | |
case 0x0B: //cst.CODE_DOUBLE_BIG: | |
var t = new Array(8);; | |
for (var i = 0;i < 8;i++) t[i] = reader.read8u (); | |
var v = caml_float_of_bytes (t); | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
return v; | |
case 0x0E: //cst.CODE_DOUBLE_ARRAY8_LITTLE: | |
var len = reader.read8u(); | |
var v = new Array(len+1); | |
v[0] = 254; | |
var t = new Array(8);; | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
for (var i = 1;i <= len;i++) { | |
for (var j = 0;j < 8;j++) t[7 - j] = reader.read8u(); | |
v[i] = caml_float_of_bytes (t); | |
} | |
return v; | |
case 0x0D: //cst.CODE_DOUBLE_ARRAY8_BIG: | |
var len = reader.read8u(); | |
var v = new Array(len+1); | |
v[0] = 254; | |
var t = new Array(8);; | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
for (var i = 1;i <= len;i++) { | |
for (var j = 0;j < 8;j++) t[j] = reader.read8u(); | |
v [i] = caml_float_of_bytes (t); | |
} | |
return v; | |
case 0x07: //cst.CODE_DOUBLE_ARRAY32_LITTLE: | |
var len = reader.read32u(); | |
var v = new Array(len+1); | |
v[0] = 254; | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
var t = new Array(8);; | |
for (var i = 1;i <= len;i++) { | |
for (var j = 0;j < 8;j++) t[7 - j] = reader.read8u(); | |
v[i] = caml_float_of_bytes (t); | |
} | |
return v; | |
case 0x0F: //cst.CODE_DOUBLE_ARRAY32_BIG: | |
var len = reader.read32u(); | |
var v = new Array(len+1); | |
v[0] = 254; | |
var t = new Array(8);; | |
for (var i = 1;i <= len;i++) { | |
for (var j = 0;j < 8;j++) t[j] = reader.read8u(); | |
v [i] = caml_float_of_bytes (t); | |
} | |
return v; | |
case 0x10: //cst.CODE_CODEPOINTER: | |
case 0x11: //cst.CODE_INFIXPOINTER: | |
caml_failwith ("input_value: code pointer"); | |
break; | |
case 0x12: //cst.CODE_CUSTOM: | |
var c, s = ""; | |
while ((c = reader.read8u ()) != 0) s += String.fromCharCode (c); | |
switch(s) { | |
case "_j": | |
// Int64 | |
var t = new Array(8);; | |
for (var j = 0;j < 8;j++) t[j] = reader.read8u(); | |
var v = caml_int64_of_bytes (t); | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
return v; | |
case "_i": | |
// Int32 | |
var v = reader.read32s (); | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
return v; | |
case "_n": | |
// Nativeint | |
switch (reader.read8u ()) { | |
case 1: | |
var v = reader.read32s (); | |
if (intern_obj_table) intern_obj_table[obj_counter++] = v; | |
return v; | |
case 2: | |
caml_failwith("input_value: native integer value too large"); | |
default: | |
caml_failwith("input_value: ill-formed native integer"); | |
} | |
default: | |
caml_failwith("input_value: unknown custom block identifier"); | |
} | |
default: | |
caml_failwith ("input_value: ill-formed message"); | |
} | |
} | |
} | |
} | |
var res = intern_rec (); | |
while (stack.length > 0) { | |
var size = stack.pop(); | |
var v = stack.pop(); | |
var d = v.length; | |
if (d < size) stack.push(v, size); | |
v[d] = intern_rec (); | |
} | |
if (typeof ofs!="number") ofs[0] = reader.i; | |
return res; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment