diff --git a/js/src/jit-test/tests/gc/bug-1055034.js b/js/src/jit-test/tests/gc/bug-1055034.js new file mode 100644 index 00000000000..2b2220ba104 --- /dev/null +++ b/js/src/jit-test/tests/gc/bug-1055034.js @@ -0,0 +1,13 @@ +function range(n, m) { + var result = []; + for (var i = n; i < m; i++) + result.push(i); + return result; +} +function run(arr, func) { + var expected = arr["map"].apply(arr, [func]); + function f(m) { return arr["mapPar"].apply(arr, [func, m]); } + f({mode:"compile"}); + f({mode:"seq"}); + } +run(range(0, 1024), function (i) { var a = []; a.length = i; }); diff --git a/js/src/jit/arm/Assembler-arm.cpp b/js/src/jit/arm/Assembler-arm.cpp index b519dacf3b9..bb69f42c327 100644 --- a/js/src/jit/arm/Assembler-arm.cpp +++ b/js/src/jit/arm/Assembler-arm.cpp @@ -808,8 +808,14 @@ TraceOneDataRelocation(JSTracer *trc, Iter *iter, MacroAssemblerARM *masm) // No barrier needed since these are constants. gc::MarkGCThingUnbarriered(trc, &ptr, "ion-masm-ptr"); - if (ptr != prior) + if (ptr != prior) { masm->ma_movPatchable(Imm32(int32_t(ptr)), dest, Assembler::Always, rs, ins); + // L_LDR won't cause any instructions to be updated. + if (rs != Assembler::L_LDR) { + AutoFlushICache::flush(uintptr_t(ins), 4); + AutoFlushICache::flush(uintptr_t(ins->next()), 4); + } + } } static void diff --git a/js/src/jit/mips/Assembler-mips.cpp b/js/src/jit/mips/Assembler-mips.cpp index 6203fb2f0bf..da9045d5e0f 100644 --- a/js/src/jit/mips/Assembler-mips.cpp +++ b/js/src/jit/mips/Assembler-mips.cpp @@ -280,17 +280,27 @@ Assembler::TraceJumpRelocations(JSTracer *trc, JitCode *code, CompactBufferReade } } +static void +TraceOneDataRelocation(JSTracer *trc, Instruction *inst) +{ + void *ptr = (void *)Assembler::ExtractLuiOriValue(inst, inst->next()); + void *prior = ptr; + + // No barrier needed since these are constants. + gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); + if (ptr != prior) { + Assembler::UpdateLuiOriValue(inst, inst->next(), uint32_t(ptr)); + AutoFlushICache::flush(uintptr_t(inst), 8); + } +} + static void TraceDataRelocations(JSTracer *trc, uint8_t *buffer, CompactBufferReader &reader) { while (reader.more()) { size_t offset = reader.readUnsigned(); Instruction *inst = (Instruction*)(buffer + offset); - void *ptr = (void *)Assembler::ExtractLuiOriValue(inst, inst->next()); - - // No barrier needed since these are constants. - gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); - Assembler::UpdateLuiOriValue(inst, inst->next(), uint32_t(ptr)); + TraceOneDataRelocation(trc, inst); } } @@ -300,12 +310,7 @@ TraceDataRelocations(JSTracer *trc, MIPSBuffer *buffer, CompactBufferReader &rea while (reader.more()) { BufferOffset bo (reader.readUnsigned()); MIPSBuffer::AssemblerBufferInstIterator iter(bo, buffer); - - void *ptr = (void *)Assembler::ExtractLuiOriValue(iter.cur(), iter.next()); - - // No barrier needed since these are constants. - gc::MarkGCThingUnbarriered(trc, reinterpret_cast(&ptr), "ion-masm-ptr"); - Assembler::UpdateLuiOriValue(iter.cur(), iter.next(), uint32_t(ptr)); + TraceOneDataRelocation(trc, iter.cur()); } }