Bug 532689: guard that index is in range for arguments[k] on trace, r=bz
authorDavid Mandelin <dmandelin@mozilla.com>
Thu, 14 Jan 2010 18:48:17 -0800
changeset 37693 5c06d8cc50b00fd0420b5c9172ebe90d6722ec4b
parent 37692 a39e0b5578645dd64e11a4939a9de3ca9ff8b08b
child 37694 910ee7db07dee0d99855db1718567902eee54cf0
push idunknown
push userunknown
push dateunknown
reviewersbz
bugs532689
milestone1.9.3a1pre
Bug 532689: guard that index is in range for arguments[k] on trace, r=bz
js/src/jstracer.cpp
js/src/trace-test/tests/arguments/args-range-2.js
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -11911,16 +11911,25 @@ TraceRecorder::record_JSOP_GETELEM()
                 else
                     v_ins = INS_VOID();
             } else {
                 // If the index is not a constant expression, we generate LIR to load the value from
                 // the native stack area. The guard on js_ArgumentClass above ensures the up-to-date
                 // value has been written back to the native stack area.
                 idx_ins = makeNumberInt32(idx_ins);
                 if (int_idx >= 0 && int_idx < afp->argc) {
+                    guard(true,
+                          addName(lir->ins2(LIR_ge, idx_ins, INS_CONST(0)),
+                                  "guard(upvar index >= 0)"),
+                          BRANCH_EXIT);
+                    guard(true,
+                          addName(lir->ins2(LIR_lt, idx_ins, INS_CONST(afp->argc)),
+                                  "guard(upvar index in range)"),
+                          BRANCH_EXIT);
+
                     JSTraceType type = getCoercedType(*vp);
 
                     // Guard that the argument has the same type on trace as during recording.
                     LIns* typemap_ins;
                     if (callDepth == depth) {
                         // In this case, we are in the same frame where the arguments object was created.
                         // The entry type map is not necessarily up-to-date, so we capture a new type map
                         // for this point in the code.
@@ -11931,17 +11940,17 @@ TraceRecorder::record_JSOP_GETELEM()
                         typemap_ins = INS_CONSTPTR(typemap + 2 /* callee, this */);
                     } else {
                         // In this case, we are in a deeper frame from where the arguments object was
                         // created. The type map at the point of the call out from the creation frame
                         // is accurate.
                         // Note: this relies on the assumption that we abort on setting an element of
                         // an arguments object in any deeper frame.
                         LIns* fip_ins = lir->insLoad(LIR_ldp, lirbuf->rp, (callDepth-depth)*sizeof(FrameInfo*));
-                        typemap_ins = lir->ins2(LIR_add, fip_ins, INS_CONST(sizeof(FrameInfo) + 2/*callee,this*/ * sizeof(JSTraceType)));
+                        typemap_ins = lir->ins2(LIR_piadd, fip_ins, INS_CONSTWORD(sizeof(FrameInfo) + 2/*callee,this*/ * sizeof(JSTraceType)));
                     }
 
                     LIns* typep_ins = lir->ins2(LIR_piadd, typemap_ins,
                                                 lir->ins_u2p(lir->ins2(LIR_mul,
                                                                        idx_ins,
                                                                        INS_CONST(sizeof(JSTraceType)))));
                     LIns* type_ins = lir->insLoad(LIR_ldcb, typep_ins, 0);
                     guard(true,
new file mode 100644
--- /dev/null
+++ b/js/src/trace-test/tests/arguments/args-range-2.js
@@ -0,0 +1,37 @@
+actual = '';
+expected = "undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,"; 
+
+var index;
+
+function h() {
+  for (var i = 0; i < 5; ++i) {
+    var a = arguments;
+    appendToActual(a[index]);
+  }
+}
+
+index = 0;
+h();
+index = -1;
+h();
+index = 1;
+h();
+
+index = -9999999;
+h(1, 2, 3);
+index = -1;
+h(1, 2, 3);
+index = 0;
+h(1, 2, 3);
+index = 1;
+h(1, 2, 3);
+index = 2;
+h(1, 2, 3);
+index = 3;
+h(1, 2, 3);
+index = 4;
+h(1, 2, 3);
+index = 9999999;
+h(1, 2, 3);
+
+assertEq(actual, expected)