From 07257e7a4ce4503d13e1baaad0c0d6b13101f2cd Mon Sep 17 00:00:00 2001 From: "Nicholas D. Matsakis" Date: Tue, 9 Jul 2013 15:29:39 -0400 Subject: [PATCH] Bug 829896 - Make typed array element accesses return undefined if the element is out of bounds, rather than accessing the prototype chain r=jandem --- js/src/ion/CodeGenerator.cpp | 60 +++---------------- js/src/ion/CodeGenerator.h | 1 - js/src/ion/IonBuilder.cpp | 2 +- js/src/ion/MIR.h | 4 +- .../tests/basic/testTypedArrayOutOfBounds.js | 7 +-- .../basic/typed-array-getprop-out-of-range.js | 2 +- js/src/jit-test/tests/ion/typed-arrays-2.js | 4 +- .../jit-test/tests/parallelarray/bug890465.js | 4 ++ js/src/vm/Interpreter.cpp | 11 ---- js/src/vm/Interpreter.h | 3 - js/src/vm/TypedArrayObject.cpp | 9 +-- 11 files changed, 20 insertions(+), 87 deletions(-) create mode 100644 js/src/jit-test/tests/parallelarray/bug890465.js diff --git a/js/src/ion/CodeGenerator.cpp b/js/src/ion/CodeGenerator.cpp index 09ea6fe3c85..9a6be755efe 100644 --- a/js/src/ion/CodeGenerator.cpp +++ b/js/src/ion/CodeGenerator.cpp @@ -6363,43 +6363,25 @@ CodeGenerator::visitLoadTypedArrayElement(LLoadTypedArrayElement *lir) return true; } -class OutOfLineLoadTypedArray : public OutOfLineCodeBase -{ - LLoadTypedArrayElementHole *ins_; - - public: - OutOfLineLoadTypedArray(LLoadTypedArrayElementHole *ins) - : ins_(ins) - { } - - bool accept(CodeGenerator *codegen) { - return codegen->visitOutOfLineLoadTypedArray(this); - } - - LLoadTypedArrayElementHole *ins() const { - return ins_; - } -}; - bool CodeGenerator::visitLoadTypedArrayElementHole(LLoadTypedArrayElementHole *lir) { Register object = ToRegister(lir->object()); const ValueOperand out = ToOutValue(lir); - OutOfLineLoadTypedArray *ool = new OutOfLineLoadTypedArray(lir); - if (!addOutOfLineCode(ool)) - return false; - // Load the length. Register scratch = out.scratchReg(); Int32Key key = ToInt32Key(lir->index()); masm.unboxInt32(Address(object, TypedArrayObject::lengthOffset()), scratch); - // OOL path if index >= length. - masm.branchKey(Assembler::BelowOrEqual, scratch, key, ool->entry()); + // Load undefined unless length > key. + Label inbounds, done; + masm.branchKey(Assembler::Above, scratch, key, &inbounds); + masm.moveValue(UndefinedValue(), out); + masm.jump(&done); // Load the elements vector. + masm.bind(&inbounds); masm.loadPtr(Address(object, TypedArrayObject::dataOffset()), scratch); int arrayType = lir->mir()->arrayType(); @@ -6419,35 +6401,7 @@ CodeGenerator::visitLoadTypedArrayElementHole(LLoadTypedArrayElementHole *lir) if (fail.used() && !bailoutFrom(&fail, lir->snapshot())) return false; - masm.bind(ool->rejoin()); - return true; -} - -typedef bool (*GetElementMonitoredFn)(JSContext *, MutableHandleValue, HandleValue, MutableHandleValue); -static const VMFunction GetElementMonitoredInfo = - FunctionInfo(js::GetElementMonitored); - -bool -CodeGenerator::visitOutOfLineLoadTypedArray(OutOfLineLoadTypedArray *ool) -{ - LLoadTypedArrayElementHole *ins = ool->ins(); - saveLive(ins); - - Register object = ToRegister(ins->object()); - ValueOperand out = ToOutValue(ins); - - if (ins->index()->isConstant()) - pushArg(*ins->index()->toConstant()); - else - pushArg(TypedOrValueRegister(MIRType_Int32, ToAnyRegister(ins->index()))); - pushArg(TypedOrValueRegister(MIRType_Object, AnyRegister(object))); - if (!callVM(GetElementMonitoredInfo, ins)) - return false; - - masm.storeCallResultValue(out); - restoreLive(ins); - - masm.jump(ool->rejoin()); + masm.bind(&done); return true; } diff --git a/js/src/ion/CodeGenerator.h b/js/src/ion/CodeGenerator.h index aa0720ec3ed..58cff0443bf 100644 --- a/js/src/ion/CodeGenerator.h +++ b/js/src/ion/CodeGenerator.h @@ -212,7 +212,6 @@ class CodeGenerator : public CodeGeneratorSpecific bool visitClampIToUint8(LClampIToUint8 *lir); bool visitClampDToUint8(LClampDToUint8 *lir); bool visitClampVToUint8(LClampVToUint8 *lir); - bool visitOutOfLineLoadTypedArray(OutOfLineLoadTypedArray *ool); bool visitCallIteratorStart(LCallIteratorStart *lir); bool visitIteratorStart(LIteratorStart *lir); bool visitIteratorNext(LIteratorNext *lir); diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index a902ac24024..e5bb7588e89 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -6666,7 +6666,7 @@ IonBuilder::jsop_getelem_typed(int arrayType) current->add(load); current->push(load); - return resumeAfter(load) && pushTypeBarrier(load, types, needsBarrier); + return pushTypeBarrier(load, types, needsBarrier); } } diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h index b2fa01fd0fe..d3f8b1a7205 100644 --- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -5001,9 +5001,7 @@ class MLoadTypedArrayElementHole return getOperand(1); } AliasSet getAliasSet() const { - // Out-of-bounds accesses are handled using a VM call, this may - // invoke getters on the prototype chain. - return AliasSet::Store(AliasSet::Any); + return AliasSet::Load(AliasSet::TypedArrayElement); } }; diff --git a/js/src/jit-test/tests/basic/testTypedArrayOutOfBounds.js b/js/src/jit-test/tests/basic/testTypedArrayOutOfBounds.js index e02a127c53e..8c2d85441c1 100644 --- a/js/src/jit-test/tests/basic/testTypedArrayOutOfBounds.js +++ b/js/src/jit-test/tests/basic/testTypedArrayOutOfBounds.js @@ -14,6 +14,9 @@ function f1() { f1(); function f2() { + // Test that values on the prototype are ignored, + // even for OOB accesses. This behavior is new + // with ECMA 6 (see bug 829896). Object.prototype[50] = 4.4; Object.prototype[55] = Math; @@ -22,10 +25,6 @@ function f2() { var x = a[i]; if (i < a.length) assertEq(x, 0); - else if (i === 50) - assertEq(x, 4.4); - else if (i === 55) - assertEq(x, Math); else assertEq(x, undefined); } diff --git a/js/src/jit-test/tests/basic/typed-array-getprop-out-of-range.js b/js/src/jit-test/tests/basic/typed-array-getprop-out-of-range.js index de7754dcb2e..601d9f3c55f 100644 --- a/js/src/jit-test/tests/basic/typed-array-getprop-out-of-range.js +++ b/js/src/jit-test/tests/basic/typed-array-getprop-out-of-range.js @@ -5,7 +5,7 @@ function test() for (var i = 0, sz = 9; i < sz; i++) { var ta = new Int8Array(); - assertEq(ta[0], r); + assertEq(ta[0], undefined); } } test(); diff --git a/js/src/jit-test/tests/ion/typed-arrays-2.js b/js/src/jit-test/tests/ion/typed-arrays-2.js index fcf3483dcab..1f88cb65df6 100644 --- a/js/src/jit-test/tests/ion/typed-arrays-2.js +++ b/js/src/jit-test/tests/ion/typed-arrays-2.js @@ -11,10 +11,8 @@ function test1() { assertEq(res, 0xffffee00); else if (i == 84) assertEq(res, 444); - else if (i == 105) - assertEq(res, true); else if (i >= 100) assertEq(res, undefined); } } -test1(); \ No newline at end of file +test1(); diff --git a/js/src/jit-test/tests/parallelarray/bug890465.js b/js/src/jit-test/tests/parallelarray/bug890465.js new file mode 100644 index 00000000000..20aa711c581 --- /dev/null +++ b/js/src/jit-test/tests/parallelarray/bug890465.js @@ -0,0 +1,4 @@ +x = Uint8ClampedArray() +ParallelArray([320], function() { + return x[8] +}) \ No newline at end of file diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 9e01dc62bb6..533aa5771e5 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -3706,17 +3706,6 @@ js::GetElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, Mutable return GetElementOperation(cx, JSOP_GETELEM, lref, rref, vp); } -bool -js::GetElementMonitored(JSContext *cx, MutableHandleValue lref, HandleValue rref, - MutableHandleValue vp) -{ - if (!GetElement(cx, lref, rref, vp)) - return false; - - TypeScript::Monitor(cx, vp); - return true; -} - bool js::CallElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res) { diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h index e8625108053..0b30fa91974 100644 --- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -415,9 +415,6 @@ Lambda(JSContext *cx, HandleFunction fun, HandleObject parent); bool GetElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res); -bool -GetElementMonitored(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res); - bool CallElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res); diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 63309a9f4d6..df1dfbc14ec 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -1442,13 +1442,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject return true; } - RootedObject proto(cx, tarray->getProto()); - if (!proto) { - vp.setUndefined(); - return true; - } - - return JSObject::getElement(cx, proto, receiver, index, vp); + vp.setUndefined(); + return true; } static JSBool