Bug 1317943 - Fix ThrowReadOnlyError to pass the index instead of the object to the error reporter. r=nbp, a=gchang
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 19 Nov 2016 11:14:13 +0100
changeset 358911 877a0309d8de7bbbaf58be83b8102e008b80062f
parent 358910 99d833f2f864d14c5ad4bf0c5ca568493f436e1b
child 358912 37a277bc59867c25bfa6750a96c8cc06c6512458
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp, gchang
bugs1317943
milestone51.0
Bug 1317943 - Fix ThrowReadOnlyError to pass the index instead of the object to the error reporter. r=nbp, a=gchang
js/src/jit-test/tests/ion/bug1317943.js
js/src/jit/CodeGenerator.cpp
js/src/jit/VMFunctions.cpp
js/src/jit/VMFunctions.h
new file mode 100644
--- /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();
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8190,34 +8190,37 @@ CodeGenerator::emitStoreElementHoleV(T* 
 }
 
 void
 CodeGenerator::visitStoreElementHoleV(LStoreElementHoleV* lir)
 {
     emitStoreElementHoleV(lir);
 }
 
-typedef bool (*ThrowReadOnlyFn)(JSContext*, HandleObject);
+typedef bool (*ThrowReadOnlyFn)(JSContext*, int32_t);
 static const VMFunction ThrowReadOnlyInfo =
     FunctionInfo<ThrowReadOnlyFn>(ThrowReadOnlyError, "ThrowReadOnlyError");
 
 void
 CodeGenerator::visitFallibleStoreElementT(LFallibleStoreElementT* lir)
 {
     Register elements = ToRegister(lir->elements());
 
     // Handle frozen objects
     Label isFrozen;
     Address flags(elements, ObjectElements::offsetOfFlags());
     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
         // of a jump) does a masm.assumeUnreachable().
     }
 
     emitStoreElementHoleT(lir);
 
@@ -8230,19 +8233,22 @@ CodeGenerator::visitFallibleStoreElement
     Register elements = ToRegister(lir->elements());
 
     // Handle frozen objects
     Label isFrozen;
     Address flags(elements, ObjectElements::offsetOfFlags());
     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
         // of a jump) does a masm.assumeUnreachable().
     }
 
     emitStoreElementHoleV(lir);
 
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -1299,20 +1299,19 @@ ThrowRuntimeLexicalError(JSContext* cx, 
 {
     ScriptFrameIter iter(cx);
     RootedScript script(cx, iter.script());
     ReportRuntimeLexicalError(cx, errorNumber, script, iter.pc());
     return false;
 }
 
 bool
-ThrowReadOnlyError(JSContext* cx, HandleObject handle)
+ThrowReadOnlyError(JSContext* cx, int32_t index)
 {
-    HandleNativeObject obj = handle.as<NativeObject>();
-    RootedValue val(cx, ObjectValue(*obj));
+    RootedValue val(cx, Int32Value(index));
     ReportValueError(cx, JSMSG_READ_ONLY, JSDVG_IGNORE_STACK, val, nullptr);
     return false;
 }
 
 bool
 ThrowBadDerivedReturn(JSContext* cx, HandleValue v)
 {
     ReportValueError(cx, JSMSG_BAD_DERIVED_RETURN, JSDVG_IGNORE_STACK, v, nullptr);
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -780,20 +780,23 @@ IonMarkFunction(MIRType type)
     }
 }
 
 bool ObjectIsCallable(JSObject* obj);
 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);
 
 MOZ_MUST_USE bool
 ThrowObjectCoercible(JSContext* cx, HandleValue v);
 
 MOZ_MUST_USE bool
 BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res);