Bug 620029 - Add a check for negative lengths in |new Array(l)| (r=njn)
authorBill McCloskey <wmccloskey@mozilla.com>
Tue, 21 Dec 2010 16:47:13 -0800
changeset 59913 a4f9580c9b72328c944220e08a3bb4e0232c6e98
parent 59912 e852f9426d25059502162ac18d445f229ac23636
child 59914 89ec0c0b48e2b24e1822ee16261c8d2c80114f1e
push id17820
push usercleary@mozilla.com
push dateTue, 04 Jan 2011 21:40:57 +0000
treeherdermozilla-central@969691cfe40e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs620029
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 620029 - Add a check for negative lengths in |new Array(l)| (r=njn)
js/src/jit-test/tests/basic/testNegativeArrayLength.js
js/src/jstracer.cpp
js/src/jstracer.h
--- a/js/src/jit-test/tests/basic/testNegativeArrayLength.js
+++ b/js/src/jit-test/tests/basic/testNegativeArrayLength.js
@@ -1,10 +1,10 @@
 function f() {
     try {
-	for ( var i = 1; i > -2; i-- )
+	for ( var i = HOTLOOP-1; i > -2; i-- )
 	    new Array(i).join('*');
     } catch (e) {
 	return e instanceof RangeError;
     }
     return false;
 }
 assertEq(f(), true);
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -8469,16 +8469,33 @@ TraceRecorder::makeNumberInt32(LIns* d, 
     // This means "convert double to int if it's integral, otherwise
     // exit".  We first convert the double to an int, then convert it back
     // and exit if the two doubles don't match.  If 'f' is a non-integral
     // immediate we'll end up aborting.
     *out = d2i(d, /* resultCanBeImpreciseIfFractional = */true);
     return guard(true, w.eqd(d, w.i2d(*out)), MISMATCH_EXIT, /* abortIfAlwaysExits = */true);
 }
 
+JS_REQUIRES_STACK RecordingStatus
+TraceRecorder::makeNumberUint32(LIns* d, LIns** out)
+{
+    JS_ASSERT(d->isD());
+    if (IsPromoteUint(d)) {
+        *out = w.demote(d);
+        return RECORD_CONTINUE;
+    }
+
+    // This means "convert double to uint if it's integral, otherwise
+    // exit".  We first convert the double to an unsigned int, then
+    // convert it back and exit if the two doubles don't match.  If
+    // 'f' is a non-integral immediate we'll end up aborting.
+    *out = d2u(d);
+    return guard(true, w.eqd(d, w.ui2d(*out)), MISMATCH_EXIT, /* abortIfAlwaysExits = */true);
+}
+
 JS_REQUIRES_STACK LIns*
 TraceRecorder::stringify(const Value& v)
 {
     LIns* v_ins = get(&v);
     if (v.isString())
         return v_ins;
 
     LIns* args[] = { v_ins, cx_ins };
@@ -10960,17 +10977,19 @@ TraceRecorder::newArray(JSObject* ctor, 
     LIns *arr_ins;
     if (argc == 0) {
         LIns *args[] = { proto_ins, cx_ins };
         arr_ins = w.call(&js::NewDenseEmptyArray_ci, args);
         guard(false, w.eqp0(arr_ins), OOM_EXIT);
 
     } else if (argc == 1 && argv[0].isNumber()) {
         /* Abort on RangeError if the double doesn't fit in a uint. */
-        LIns *args[] = { proto_ins, d2i(get(argv)), cx_ins };
+        LIns *len_ins;
+        CHECK_STATUS(makeNumberUint32(get(argv), &len_ins));
+        LIns *args[] = { proto_ins, len_ins, cx_ins };
         arr_ins = w.call(&js::NewDenseUnallocatedArray_ci, args);
         guard(false, w.eqp0(arr_ins), OOM_EXIT);
 
     } else {
         LIns *args[] = { proto_ins, w.nameImmi(argc), cx_ins };
         arr_ins = w.call(&js::NewDenseAllocatedArray_ci, args);
         guard(false, w.eqp0(arr_ins), OOM_EXIT);
 
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -1273,16 +1273,17 @@ class TraceRecorder
 
     JS_REQUIRES_STACK void guardNonNeg(nanojit::LIns* d0, nanojit::LIns* d1, VMSideExit* exit);
     JS_REQUIRES_STACK nanojit::LIns* alu(nanojit::LOpcode op, jsdouble v0, jsdouble v1,
                                          nanojit::LIns* s0, nanojit::LIns* s1);
 
     nanojit::LIns* d2i(nanojit::LIns* f, bool resultCanBeImpreciseIfFractional = false);
     nanojit::LIns* d2u(nanojit::LIns* d);
     JS_REQUIRES_STACK RecordingStatus makeNumberInt32(nanojit::LIns* d, nanojit::LIns** num_ins);
+    JS_REQUIRES_STACK RecordingStatus makeNumberUint32(nanojit::LIns* d, nanojit::LIns** num_ins);
     JS_REQUIRES_STACK nanojit::LIns* stringify(const Value& v);
 
     JS_REQUIRES_STACK nanojit::LIns* newArguments(nanojit::LIns* callee_ins, bool strict);
 
     JS_REQUIRES_STACK bool canCallImacro() const;
     JS_REQUIRES_STACK RecordingStatus callImacro(jsbytecode* imacro);
     JS_REQUIRES_STACK RecordingStatus callImacroInfallibly(jsbytecode* imacro);