diff --git a/js/src/jit-test/tests/ion/bug1317943.js b/js/src/jit-test/tests/ion/bug1317943.js new file mode 100644 index 000000000000..10b36d3681df --- /dev/null +++ b/js/src/jit-test/tests/ion/bug1317943.js @@ -0,0 +1,14 @@ +"use strict"; +function test() { + for (var i=0; i<10; i++) { + try { + var arr = []; + arr[0] = 1; + Object.freeze(arr); + arr[0] = 2; + } catch (e) { + assertEq(e.toString().includes("TypeError: 0 is read-only"), true); + } + } +} +test(); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index e65b64dc7b4b..a6e1f16938c4 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -8306,7 +8306,7 @@ CodeGenerator::visitStoreElementHoleV(LStoreElementHoleV* lir) emitStoreElementHoleV(lir); } -typedef bool (*ThrowReadOnlyFn)(JSContext*, HandleObject); +typedef bool (*ThrowReadOnlyFn)(JSContext*, int32_t); static const VMFunction ThrowReadOnlyInfo = FunctionInfo(ThrowReadOnlyError, "ThrowReadOnlyError"); @@ -8321,9 +8321,12 @@ CodeGenerator::visitFallibleStoreElementT(LFallibleStoreElementT* lir) if (!lir->mir()->strict()) { masm.branchTest32(Assembler::NonZero, flags, Imm32(ObjectElements::FROZEN), &isFrozen); } else { - Register object = ToRegister(lir->object()); - OutOfLineCode* ool = oolCallVM(ThrowReadOnlyInfo, lir, - ArgList(object), StoreNothing()); + const LAllocation* index = lir->index(); + OutOfLineCode* ool; + if (index->isConstant()) + ool = oolCallVM(ThrowReadOnlyInfo, lir, ArgList(Imm32(ToInt32(index))), StoreNothing()); + else + ool = oolCallVM(ThrowReadOnlyInfo, lir, ArgList(ToRegister(index)), StoreNothing()); masm.branchTest32(Assembler::NonZero, flags, Imm32(ObjectElements::FROZEN), ool->entry()); // This OOL code should have thrown an exception, so will never return. // So, do not bind ool->rejoin() anywhere, so that it implicitly (and without the cost @@ -8346,9 +8349,12 @@ CodeGenerator::visitFallibleStoreElementV(LFallibleStoreElementV* lir) if (!lir->mir()->strict()) { masm.branchTest32(Assembler::NonZero, flags, Imm32(ObjectElements::FROZEN), &isFrozen); } else { - Register object = ToRegister(lir->object()); - OutOfLineCode* ool = oolCallVM(ThrowReadOnlyInfo, lir, - ArgList(object), StoreNothing()); + const LAllocation* index = lir->index(); + OutOfLineCode* ool; + if (index->isConstant()) + ool = oolCallVM(ThrowReadOnlyInfo, lir, ArgList(Imm32(ToInt32(index))), StoreNothing()); + else + ool = oolCallVM(ThrowReadOnlyInfo, lir, ArgList(ToRegister(index)), StoreNothing()); masm.branchTest32(Assembler::NonZero, flags, Imm32(ObjectElements::FROZEN), ool->entry()); // This OOL code should have thrown an exception, so will never return. // So, do not bind ool->rejoin() anywhere, so that it implicitly (and without the cost diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 427099bbfd91..bbbb4fc767de 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -1316,10 +1316,9 @@ ThrowRuntimeLexicalError(JSContext* cx, unsigned errorNumber) } bool -ThrowReadOnlyError(JSContext* cx, HandleObject handle) +ThrowReadOnlyError(JSContext* cx, int32_t index) { - HandleNativeObject obj = handle.as(); - RootedValue val(cx, ObjectValue(*obj)); + RootedValue val(cx, Int32Value(index)); ReportValueError(cx, JSMSG_READ_ONLY, JSDVG_IGNORE_STACK, val, nullptr); return false; } diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h index 7e0d03c67125..f754d58c71b1 100644 --- a/js/src/jit/VMFunctions.h +++ b/js/src/jit/VMFunctions.h @@ -786,10 +786,13 @@ bool ObjectIsConstructor(JSObject* obj); MOZ_MUST_USE bool ThrowRuntimeLexicalError(JSContext* cx, unsigned errorNumber); + MOZ_MUST_USE bool -ThrowReadOnlyError(JSContext* cx, HandleObject obj); +ThrowReadOnlyError(JSContext* cx, int32_t index); + MOZ_MUST_USE bool BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame); + MOZ_MUST_USE bool ThrowBadDerivedReturn(JSContext* cx, HandleValue v);