fix stone crash
This commit is contained in:
@@ -1369,7 +1369,7 @@ JSValue gc_copy_value (JSContext *ctx, JSValue v, uint8_t *from_base, uint8_t *f
|
||||
|
||||
/* Frame shortening: returned frames (caller == JS_NULL) only need
|
||||
[this][args][closure_locals] — shrink during copy. */
|
||||
if (type == OBJ_FRAME) {
|
||||
if (0 && type == OBJ_FRAME) {
|
||||
JSFrame *f = (JSFrame *)hdr_ptr;
|
||||
if (JS_IsNull (f->caller) && JS_IsPtr (f->function)) {
|
||||
/* fn may be forwarded, but kind (offset 18) and u.cell.code (offset 24)
|
||||
|
||||
@@ -1308,25 +1308,18 @@ var streamline = function(ir, log) {
|
||||
var insert_stone_text = function(func, log) {
|
||||
var instructions = func.instructions
|
||||
var nr_slots = func.nr_slots
|
||||
var dpc = func.disruption_pc
|
||||
var events = null
|
||||
var slot_types = null
|
||||
var result = null
|
||||
var i = 0
|
||||
var j = 0
|
||||
var s = 0
|
||||
var n = 0
|
||||
var instr = null
|
||||
var op = null
|
||||
var esc = null
|
||||
var slot = 0
|
||||
var nc = 0
|
||||
var limit = 0
|
||||
var first_ref = null
|
||||
var last_ref = null
|
||||
var label_map = null
|
||||
var changed = false
|
||||
var target = null
|
||||
var tpos = 0
|
||||
var shift = 0
|
||||
|
||||
if (instructions == null || length(instructions) == 0) {
|
||||
return null
|
||||
@@ -1336,72 +1329,10 @@ var streamline = function(ir, log) {
|
||||
events = log.events
|
||||
}
|
||||
|
||||
// Build first_ref / last_ref for liveness (needed for move)
|
||||
first_ref = array(nr_slots, -1)
|
||||
last_ref = array(nr_slots, -1)
|
||||
n = length(instructions)
|
||||
i = 0
|
||||
while (i < n) {
|
||||
instr = instructions[i]
|
||||
if (is_array(instr)) {
|
||||
j = 1
|
||||
limit = length(instr) - 2
|
||||
while (j < limit) {
|
||||
if (is_number(instr[j]) && instr[j] >= 0 && instr[j] < nr_slots) {
|
||||
if (first_ref[instr[j]] < 0) first_ref[instr[j]] = i
|
||||
last_ref[instr[j]] = i
|
||||
}
|
||||
j = j + 1
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
// Extend for backward jumps (loops)
|
||||
label_map = {}
|
||||
i = 0
|
||||
while (i < n) {
|
||||
instr = instructions[i]
|
||||
if (is_text(instr) && !starts_with(instr, "_nop_")) {
|
||||
label_map[instr] = i
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
changed = true
|
||||
while (changed) {
|
||||
changed = false
|
||||
i = 0
|
||||
while (i < n) {
|
||||
instr = instructions[i]
|
||||
if (is_array(instr)) {
|
||||
target = null
|
||||
op = instr[0]
|
||||
if (op == "jump") {
|
||||
target = instr[1]
|
||||
} else if (op == "jump_true" || op == "jump_false" || op == "jump_not_null") {
|
||||
target = instr[2]
|
||||
}
|
||||
if (target != null && is_text(target)) {
|
||||
tpos = label_map[target]
|
||||
if (tpos != null && tpos < i) {
|
||||
s = 0
|
||||
while (s < nr_slots) {
|
||||
if (first_ref[s] >= 0 && first_ref[s] < tpos && last_ref[s] >= tpos && last_ref[s] < i) {
|
||||
last_ref[s] = i
|
||||
changed = true
|
||||
}
|
||||
s = s + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
// Walk instructions, tracking types, inserting stone_text
|
||||
slot_types = array(nr_slots, T_UNKNOWN)
|
||||
result = []
|
||||
n = length(instructions)
|
||||
i = 0
|
||||
while (i < n) {
|
||||
instr = instructions[i]
|
||||
@@ -1413,6 +1344,7 @@ var streamline = function(ir, log) {
|
||||
if (is_number(slot) && slot_is(slot_types, slot, T_TEXT)) {
|
||||
result[] = ["stone_text", slot]
|
||||
nc = nc + 1
|
||||
if (is_number(dpc) && i < dpc) shift = shift + 1
|
||||
if (events != null) {
|
||||
events[] = {
|
||||
event: "insert", pass: "insert_stone_text",
|
||||
@@ -1421,12 +1353,12 @@ var streamline = function(ir, log) {
|
||||
}
|
||||
}
|
||||
} else if (op == "move") {
|
||||
// Stone source before move only if source is provably text
|
||||
// AND source slot is still live after this instruction
|
||||
// Conservatively stone source before move if provably text
|
||||
slot = instr[2]
|
||||
if (is_number(slot) && slot_is(slot_types, slot, T_TEXT) && last_ref[slot] > i) {
|
||||
if (is_number(slot) && slot_is(slot_types, slot, T_TEXT)) {
|
||||
result[] = ["stone_text", slot]
|
||||
nc = nc + 1
|
||||
if (is_number(dpc) && i < dpc) shift = shift + 1
|
||||
if (events != null) {
|
||||
events[] = {
|
||||
event: "insert", pass: "insert_stone_text",
|
||||
@@ -1443,6 +1375,9 @@ var streamline = function(ir, log) {
|
||||
|
||||
if (nc > 0) {
|
||||
func.instructions = result
|
||||
if (is_number(dpc) && shift > 0) {
|
||||
func.disruption_pc = dpc + shift
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -2538,12 +2473,6 @@ var streamline = function(ir, log) {
|
||||
})
|
||||
if (verify_fn) verify_fn(func, "after " + name)
|
||||
|
||||
name = "insert_stone_text" + suffix
|
||||
run_pass(func, name, function() {
|
||||
return insert_stone_text(func, log)
|
||||
})
|
||||
if (verify_fn) verify_fn(func, "after " + name)
|
||||
|
||||
name = "eliminate_unreachable" + suffix
|
||||
run_pass(func, name, function() {
|
||||
return eliminate_unreachable(func)
|
||||
@@ -2590,6 +2519,7 @@ var streamline = function(ir, log) {
|
||||
// Process main function
|
||||
if (ir.main != null) {
|
||||
optimize_function(ir.main, log)
|
||||
insert_stone_text(ir.main, log)
|
||||
}
|
||||
|
||||
// Process all sub-functions (resolve closure types from parent first)
|
||||
@@ -2599,6 +2529,7 @@ var streamline = function(ir, log) {
|
||||
while (fi < length(ir.functions)) {
|
||||
resolve_closure_types(ir.functions[fi], fi, ir)
|
||||
optimize_function(ir.functions[fi], log)
|
||||
insert_stone_text(ir.functions[fi], log)
|
||||
fi = fi + 1
|
||||
}
|
||||
}
|
||||
|
||||
23
vm_suite.ce
23
vm_suite.ce
@@ -103,6 +103,29 @@ run("string concatenation empty", function() {
|
||||
if ("" + "world" != "world") fail("empty + string failed")
|
||||
})
|
||||
|
||||
run("string concat does not mutate alias", function() {
|
||||
var a = "hello world"
|
||||
var b = a
|
||||
a = a + " appended"
|
||||
if (a != "hello world appended") fail("a wrong, got " + a)
|
||||
if (b != "hello world") fail("b should still be hello world, got " + b)
|
||||
})
|
||||
|
||||
run("string concat in loop preserves aliases", function() {
|
||||
var a = "starting value"
|
||||
var copies = [a]
|
||||
var i = 0
|
||||
while (i < 5) {
|
||||
a = a + " more"
|
||||
copies[] = a
|
||||
i = i + 1
|
||||
}
|
||||
if (copies[0] != "starting value") fail("copies[0] wrong, got " + copies[0])
|
||||
if (copies[1] != "starting value more") fail("copies[1] wrong, got " + copies[1])
|
||||
if (copies[5] != "starting value more more more more more") fail("copies[5] wrong, got " + copies[5])
|
||||
if (a != "starting value more more more more more") fail("a wrong, got " + a)
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// TYPE MIXING SHOULD DISRUPT
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user