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
|
/* Frame shortening: returned frames (caller == JS_NULL) only need
|
||||||
[this][args][closure_locals] — shrink during copy. */
|
[this][args][closure_locals] — shrink during copy. */
|
||||||
if (type == OBJ_FRAME) {
|
if (0 && type == OBJ_FRAME) {
|
||||||
JSFrame *f = (JSFrame *)hdr_ptr;
|
JSFrame *f = (JSFrame *)hdr_ptr;
|
||||||
if (JS_IsNull (f->caller) && JS_IsPtr (f->function)) {
|
if (JS_IsNull (f->caller) && JS_IsPtr (f->function)) {
|
||||||
/* fn may be forwarded, but kind (offset 18) and u.cell.code (offset 24)
|
/* 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 insert_stone_text = function(func, log) {
|
||||||
var instructions = func.instructions
|
var instructions = func.instructions
|
||||||
var nr_slots = func.nr_slots
|
var nr_slots = func.nr_slots
|
||||||
|
var dpc = func.disruption_pc
|
||||||
var events = null
|
var events = null
|
||||||
var slot_types = null
|
var slot_types = null
|
||||||
var result = null
|
var result = null
|
||||||
var i = 0
|
var i = 0
|
||||||
var j = 0
|
|
||||||
var s = 0
|
|
||||||
var n = 0
|
var n = 0
|
||||||
var instr = null
|
var instr = null
|
||||||
var op = null
|
var op = null
|
||||||
var esc = null
|
var esc = null
|
||||||
var slot = 0
|
var slot = 0
|
||||||
var nc = 0
|
var nc = 0
|
||||||
var limit = 0
|
var shift = 0
|
||||||
var first_ref = null
|
|
||||||
var last_ref = null
|
|
||||||
var label_map = null
|
|
||||||
var changed = false
|
|
||||||
var target = null
|
|
||||||
var tpos = 0
|
|
||||||
|
|
||||||
if (instructions == null || length(instructions) == 0) {
|
if (instructions == null || length(instructions) == 0) {
|
||||||
return null
|
return null
|
||||||
@@ -1336,72 +1329,10 @@ var streamline = function(ir, log) {
|
|||||||
events = log.events
|
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
|
// Walk instructions, tracking types, inserting stone_text
|
||||||
slot_types = array(nr_slots, T_UNKNOWN)
|
slot_types = array(nr_slots, T_UNKNOWN)
|
||||||
result = []
|
result = []
|
||||||
|
n = length(instructions)
|
||||||
i = 0
|
i = 0
|
||||||
while (i < n) {
|
while (i < n) {
|
||||||
instr = instructions[i]
|
instr = instructions[i]
|
||||||
@@ -1413,6 +1344,7 @@ var streamline = function(ir, log) {
|
|||||||
if (is_number(slot) && slot_is(slot_types, slot, T_TEXT)) {
|
if (is_number(slot) && slot_is(slot_types, slot, T_TEXT)) {
|
||||||
result[] = ["stone_text", slot]
|
result[] = ["stone_text", slot]
|
||||||
nc = nc + 1
|
nc = nc + 1
|
||||||
|
if (is_number(dpc) && i < dpc) shift = shift + 1
|
||||||
if (events != null) {
|
if (events != null) {
|
||||||
events[] = {
|
events[] = {
|
||||||
event: "insert", pass: "insert_stone_text",
|
event: "insert", pass: "insert_stone_text",
|
||||||
@@ -1421,12 +1353,12 @@ var streamline = function(ir, log) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (op == "move") {
|
} else if (op == "move") {
|
||||||
// Stone source before move only if source is provably text
|
// Conservatively stone source before move if provably text
|
||||||
// AND source slot is still live after this instruction
|
|
||||||
slot = instr[2]
|
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]
|
result[] = ["stone_text", slot]
|
||||||
nc = nc + 1
|
nc = nc + 1
|
||||||
|
if (is_number(dpc) && i < dpc) shift = shift + 1
|
||||||
if (events != null) {
|
if (events != null) {
|
||||||
events[] = {
|
events[] = {
|
||||||
event: "insert", pass: "insert_stone_text",
|
event: "insert", pass: "insert_stone_text",
|
||||||
@@ -1443,6 +1375,9 @@ var streamline = function(ir, log) {
|
|||||||
|
|
||||||
if (nc > 0) {
|
if (nc > 0) {
|
||||||
func.instructions = result
|
func.instructions = result
|
||||||
|
if (is_number(dpc) && shift > 0) {
|
||||||
|
func.disruption_pc = dpc + shift
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -2538,12 +2473,6 @@ var streamline = function(ir, log) {
|
|||||||
})
|
})
|
||||||
if (verify_fn) verify_fn(func, "after " + name)
|
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
|
name = "eliminate_unreachable" + suffix
|
||||||
run_pass(func, name, function() {
|
run_pass(func, name, function() {
|
||||||
return eliminate_unreachable(func)
|
return eliminate_unreachable(func)
|
||||||
@@ -2590,6 +2519,7 @@ var streamline = function(ir, log) {
|
|||||||
// Process main function
|
// Process main function
|
||||||
if (ir.main != null) {
|
if (ir.main != null) {
|
||||||
optimize_function(ir.main, log)
|
optimize_function(ir.main, log)
|
||||||
|
insert_stone_text(ir.main, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process all sub-functions (resolve closure types from parent first)
|
// Process all sub-functions (resolve closure types from parent first)
|
||||||
@@ -2599,6 +2529,7 @@ var streamline = function(ir, log) {
|
|||||||
while (fi < length(ir.functions)) {
|
while (fi < length(ir.functions)) {
|
||||||
resolve_closure_types(ir.functions[fi], fi, ir)
|
resolve_closure_types(ir.functions[fi], fi, ir)
|
||||||
optimize_function(ir.functions[fi], log)
|
optimize_function(ir.functions[fi], log)
|
||||||
|
insert_stone_text(ir.functions[fi], log)
|
||||||
fi = fi + 1
|
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")
|
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
|
// TYPE MIXING SHOULD DISRUPT
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user