Skip to content

Commit 45ff592

Browse files
committed
Don't serialize IC opcodes
Translate IC opcodes to their non-IC variants before writing them out. Before this commit they were not byte-swapped properly, breaking the ability to load serialized bytecode containing ICs on systems with different endianness.
1 parent f02ed18 commit 45ff592

7 files changed

+32
-11
lines changed

gen/function_source.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
const uint32_t qjsc_function_source_size = 393;
66

77
const uint8_t qjsc_function_source[393] = {
8-
0x08, 0x06, 0x0c, 0x61, 0x63, 0x74, 0x75, 0x61,
8+
0x09, 0x06, 0x0c, 0x61, 0x63, 0x74, 0x75, 0x61,
99
0x6c, 0x02, 0x66, 0x0c, 0x65, 0x78, 0x70, 0x65,
1010
0x63, 0x74, 0x14, 0x75, 0x73, 0x65, 0x20, 0x73,
1111
0x74, 0x72, 0x69, 0x63, 0x74, 0x34, 0x66, 0x75,

gen/hello.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
const uint32_t qjsc_hello_size = 95;
66

77
const uint8_t qjsc_hello[95] = {
8-
0x08, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f,
8+
0x09, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f,
99
0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67, 0x16, 0x48,
1010
0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72,
1111
0x6c, 0x64, 0x22, 0x65, 0x78, 0x61, 0x6d, 0x70,

gen/hello_module.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
const uint32_t qjsc_fib_module_size = 318;
66

77
const uint8_t qjsc_fib_module[318] = {
8-
0x08, 0x03, 0x2c, 0x65, 0x78, 0x61, 0x6d, 0x70,
8+
0x09, 0x03, 0x2c, 0x65, 0x78, 0x61, 0x6d, 0x70,
99
0x6c, 0x65, 0x73, 0x2f, 0x66, 0x69, 0x62, 0x5f,
1010
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x6a,
1111
0x73, 0x06, 0x66, 0x69, 0x62, 0x02, 0x6e, 0x0d,
@@ -50,7 +50,7 @@ const uint8_t qjsc_fib_module[318] = {
5050
const uint32_t qjsc_hello_module_size = 183;
5151

5252
const uint8_t qjsc_hello_module[183] = {
53-
0x08, 0x07, 0x30, 0x65, 0x78, 0x61, 0x6d, 0x70,
53+
0x09, 0x07, 0x30, 0x65, 0x78, 0x61, 0x6d, 0x70,
5454
0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, 0x6c,
5555
0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
5656
0x2e, 0x6a, 0x73, 0x1e, 0x2e, 0x2f, 0x66, 0x69,

gen/repl.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
const uint32_t qjsc_repl_size = 103010;
66

77
const uint8_t qjsc_repl[103010] = {
8-
0x08, 0x99, 0x03, 0x0e, 0x72, 0x65, 0x70, 0x6c,
8+
0x09, 0x99, 0x03, 0x0e, 0x72, 0x65, 0x70, 0x6c,
99
0x2e, 0x6a, 0x73, 0x06, 0x73, 0x74, 0x64, 0x04,
1010
0x6f, 0x73, 0x02, 0x67, 0x10, 0x69, 0x73, 0x46,
1111
0x69, 0x6e, 0x69, 0x74, 0x65, 0x0c, 0x63, 0x6f,

gen/test_fib.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
const uint32_t qjsc_test_fib_size = 172;
66

77
const uint8_t qjsc_test_fib[172] = {
8-
0x08, 0x07, 0x28, 0x65, 0x78, 0x61, 0x6d, 0x70,
8+
0x09, 0x07, 0x28, 0x65, 0x78, 0x61, 0x6d, 0x70,
99
0x6c, 0x65, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74,
1010
0x5f, 0x66, 0x69, 0x62, 0x2e, 0x6a, 0x73, 0x10,
1111
0x2e, 0x2f, 0x66, 0x69, 0x62, 0x2e, 0x73, 0x6f,

quickjs-opcode.h

+4
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,12 @@ DEF( put_ref_value, 1, 3, 0, none)
136136
DEF( define_var, 6, 0, 0, atom_u8)
137137
DEF(check_define_var, 6, 0, 0, atom_u8)
138138
DEF( define_func, 6, 1, 0, atom_u8)
139+
140+
// order matters, see IC counterparts
139141
DEF( get_field, 5, 1, 1, atom)
140142
DEF( get_field2, 5, 1, 2, atom)
141143
DEF( put_field, 5, 2, 0, atom)
144+
142145
DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */
143146
DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */
144147
DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */
@@ -358,6 +361,7 @@ DEF( is_null, 1, 1, 1, none)
358361
DEF(typeof_is_undefined, 1, 1, 1, none)
359362
DEF( typeof_is_function, 1, 1, 1, none)
360363

364+
// order matters, see non-IC counterparts
361365
DEF( get_field_ic, 5, 1, 1, none)
362366
DEF( get_field2_ic, 5, 1, 2, none)
363367
DEF( put_field_ic, 5, 2, 0, none)

quickjs.c

+22-5
Original file line numberDiff line numberDiff line change
@@ -32518,7 +32518,7 @@ typedef enum BCTagEnum {
3251832518
BC_TAG_OBJECT_REFERENCE,
3251932519
} BCTagEnum;
3252032520

32521-
#define BC_VERSION 8
32521+
#define BC_VERSION 9
3252232522

3252332523
typedef struct BCWriterState {
3252432524
JSContext *ctx;
@@ -32722,18 +32722,24 @@ static void bc_byte_swap(uint8_t *bc_buf, int bc_len)
3272232722
}
3272332723
}
3272432724

32725+
static BOOL is_ic_op(uint8_t op)
32726+
{
32727+
return op >= OP_get_field_ic && op <= OP_put_field_ic;
32728+
}
32729+
3272532730
static int JS_WriteFunctionBytecode(BCWriterState *s,
32726-
const uint8_t *bc_buf1, int bc_len)
32731+
const JSFunctionBytecode *b)
3272732732
{
32728-
int pos, len, op;
32733+
int pos, len, bc_len, op;
3272932734
JSAtom atom;
3273032735
uint8_t *bc_buf;
3273132736
uint32_t val;
3273232737

32738+
bc_len = b->byte_code_len;
3273332739
bc_buf = js_malloc(s->ctx, bc_len);
3273432740
if (!bc_buf)
3273532741
return -1;
32736-
memcpy(bc_buf, bc_buf1, bc_len);
32742+
memcpy(bc_buf, b->byte_code_buf, bc_len);
3273732743

3273832744
pos = 0;
3273932745
while (pos < bc_len) {
@@ -32751,6 +32757,16 @@ static int JS_WriteFunctionBytecode(BCWriterState *s,
3275132757
put_u32(bc_buf + pos + 1, val);
3275232758
break;
3275332759
default:
32760+
// IC (inline cache) opcodes should not end up in the serialized
32761+
// bytecode; translate them to their non-IC counterparts here
32762+
if (is_ic_op(op)) {
32763+
val = get_u32(bc_buf + pos + 1);
32764+
atom = get_ic_atom(b->ic, val);
32765+
if (bc_atom_to_idx(s, &val, atom))
32766+
goto fail;
32767+
put_u32(bc_buf + pos + 1, val);
32768+
bc_buf[pos] -= (OP_get_field_ic - OP_get_field);
32769+
}
3275432770
break;
3275532771
}
3275632772
pos += len;
@@ -32918,7 +32934,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValue obj)
3291832934
bc_put_u8(s, flags);
3291932935
}
3292032936

32921-
if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len))
32937+
if (JS_WriteFunctionBytecode(s, b))
3292232938
goto fail;
3292332939

3292432940
bc_put_atom(s, b->filename);
@@ -33643,6 +33659,7 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,
3364333659
#endif
3364433660
break;
3364533661
default:
33662+
assert(!is_ic_op(op)); // should not end up in serialized bytecode
3364633663
break;
3364733664
}
3364833665
pos += len;

0 commit comments

Comments
 (0)