Bug 1360220 - Replace emitRequireObjectCoercible with JSOP_CHECKOBJCOERCIBLE. r=shu
authorAndré Bargull <andre.bargull@gmail.com>
Thu, 27 Apr 2017 09:24:08 -0700
changeset 356551 ed8623eefe6ca566ebee4ae3070fba6f1e05f200
parent 356550 f9abb9c834521e7c5019bde82a1a893fa26a1d2b
child 356552 e059178907999f07218e8d26f18a919b3ac9435a
push id89933
push userryanvm@gmail.com
push dateThu, 04 May 2017 22:18:10 +0000
treeherdermozilla-inbound@e05917890799 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1360220
milestone55.0a1
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 1360220 - Replace emitRequireObjectCoercible with JSOP_CHECKOBJCOERCIBLE. r=shu
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/jit-test/tests/basic/expression-autopsy.js
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5883,17 +5883,17 @@ BytecodeEmitter::emitComputedPropertyNam
 bool
 BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav)
 {
     MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
     MOZ_ASSERT(pattern->isArity(PN_LIST));
 
     MOZ_ASSERT(this->stackDepth > 0);                             // ... RHS
 
-    if (!emitRequireObjectCoercible())                            // ... RHS
+    if (!emit1(JSOP_CHECKOBJCOERCIBLE))                           // ... RHS
         return false;
 
     bool needsRestPropertyExcludedSet = pattern->pn_count > 1 &&
                                         pattern->last()->isKind(PNK_SPREAD);
     if (needsRestPropertyExcludedSet) {
         if (!emitDestructuringObjRestExclusionSet(pattern))       // ... RHS SET
             return false;
 
@@ -6924,52 +6924,16 @@ BytecodeEmitter::emitWith(ParseNode* pn)
 
     if (!emitTree(pn->pn_right))
         return false;
 
     return emitterScope.leave(this);
 }
 
 bool
-BytecodeEmitter::emitRequireObjectCoercible()
-{
-    // For simplicity, handle this in self-hosted code, at cost of 13 bytes of
-    // bytecode versus 1 byte for a dedicated opcode.  As more places need this
-    // behavior, we may want to reconsider this tradeoff.
-
-#ifdef DEBUG
-    auto depth = this->stackDepth;
-#endif
-    MOZ_ASSERT(depth > 0);                 // VAL
-    if (!emit1(JSOP_DUP))                  // VAL VAL
-        return false;
-
-    // Note that "intrinsic" is a misnomer: we're calling a *self-hosted*
-    // function that's not an intrinsic!  But it nonetheless works as desired.
-    if (!emitAtomOp(cx->names().RequireObjectCoercible,
-                    JSOP_GETINTRINSIC))    // VAL VAL REQUIREOBJECTCOERCIBLE
-    {
-        return false;
-    }
-    if (!emit1(JSOP_UNDEFINED))            // VAL VAL REQUIREOBJECTCOERCIBLE UNDEFINED
-        return false;
-    if (!emit2(JSOP_PICK, 2))              // VAL REQUIREOBJECTCOERCIBLE UNDEFINED VAL
-        return false;
-    if (!emitCall(JSOP_CALL_IGNORES_RV, 1))// VAL IGNORED
-        return false;
-    checkTypeSet(JSOP_CALL_IGNORES_RV);
-
-    if (!emit1(JSOP_POP))                  // VAL
-        return false;
-
-    MOZ_ASSERT(depth == this->stackDepth);
-    return true;
-}
-
-bool
 BytecodeEmitter::emitCopyDataProperties(CopyOption option)
 {
     DebugOnly<int32_t> depth = this->stackDepth;
 
     uint32_t argc;
     if (option == CopyOption::Filtered) {
         MOZ_ASSERT(depth > 2);                 // TARGET SOURCE SET
         argc = 3;
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -703,20 +703,16 @@ struct MOZ_STACK_CLASS BytecodeEmitter
     MOZ_MUST_USE bool emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav);
 
     typedef bool
     (*DestructuringDeclEmitter)(BytecodeEmitter* bce, ParseNode* pn);
 
     template <typename NameEmitter>
     MOZ_MUST_USE bool emitDestructuringDeclsWithEmitter(ParseNode* pattern, NameEmitter emitName);
 
-    // Throw a TypeError if the value atop the stack isn't convertible to an
-    // object, with no overall effect on the stack.
-    MOZ_MUST_USE bool emitRequireObjectCoercible();
-
     enum class CopyOption {
         Filtered, Unfiltered
     };
 
     // Calls either the |CopyDataProperties| or the
     // |CopyDataPropertiesUnfiltered| intrinsic function, consumes three (or
     // two in the latter case) elements from the stack.
     MOZ_MUST_USE bool emitCopyDataProperties(CopyOption option);
--- a/js/src/jit-test/tests/basic/expression-autopsy.js
+++ b/js/src/jit-test/tests/basic/expression-autopsy.js
@@ -178,32 +178,20 @@ check_one("(new foo.x(...))",
 
 check_one("[...].foo",
           function() { [undefined].foo(); },
           " is not a function");
 check_one("[...].foo",
           function() { [undefined, ...[]].foo(); },
           " is not a function");
 
-// Manual testing for this case: the only way to trigger an error is *not* on
-// an attempted property access during destructuring, and the error message
-// invoking ToObject(null) is different: "can't convert {0} to object".
-try
-{
-  (function() {
-    var [{x}] = [null, {}];
-   })();
-  throw new Error("didn't throw");
-}
-catch (e)
-{
-  assertEq(e instanceof TypeError, true,
-           "expected TypeError, got " + e);
-  assertEq(e.message, "can't convert null to object");
-}
+check_one("[...][Symbol.iterator](...).next(...).value",
+          function () { var [{x}] = [null, {}]; }, " is null");
+check_one("[...][Symbol.iterator](...).next(...).value",
+          function () { var [{x}] = [void 0, {}]; }, " is undefined");
 
 try {
   (function() {
     "use strict";
     var o = [];
     Object.freeze(o);
     o[0] = "foo";
   }());