diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index a4555dbe513f..164267aeb574 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -6270,6 +6270,13 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, HandleId id, types::StackTypeS return true; } + // Don't call the getter with a primitive value. + if (unaryTypes.inTypes->getKnownTypeTag() != JSVAL_TYPE_OBJECT) { + MGuardObject *guardObj = MGuardObject::New(obj); + current->add(guardObj); + obj = guardObj; + } + // Spoof stack to expected state for call. pushConstant(ObjectValue(*commonGetter)); @@ -6423,6 +6430,13 @@ IonBuilder::jsop_setprop(HandlePropertyName name) return resumeAfter(set); } + // Don't call the setter with a primitive value. + if (types->getKnownTypeTag() != JSVAL_TYPE_OBJECT) { + MGuardObject *guardObj = MGuardObject::New(obj); + current->add(guardObj); + obj = guardObj; + } + // Dummy up the stack, as in getprop pushConstant(ObjectValue(*setter)); diff --git a/js/src/jit-test/tests/ion/bug827659-1.js b/js/src/jit-test/tests/ion/bug827659-1.js new file mode 100644 index 000000000000..f56ef46e3cc5 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug827659-1.js @@ -0,0 +1,11 @@ +function f() { + return y.byteOffset; +} +var y; +for (var j = 0; j < 1; ++j) { + y = new Float32Array(); +} +f(); +y = 0; +assertEq(f(), undefined); +assertEq(f(), undefined); diff --git a/js/src/jit-test/tests/ion/bug827659-2.js b/js/src/jit-test/tests/ion/bug827659-2.js new file mode 100644 index 000000000000..f223a6a6d5c3 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug827659-2.js @@ -0,0 +1,15 @@ +function f(x) { + return x["__proto__"] +} +var res = 0; +for each(a in [{}, null]) { + try { + f(a); + res += 20; + } catch (e) { + assertEq(e instanceof TypeError, true); + assertEq(e.message.indexOf("is null") > 0, true); + res += 50; + } +} +assertEq(res, 70);