Bug 1308346 - Return new.target separately from readFrameArgsAndLocals. r=shu,efaust a=ritu
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 21 Oct 2016 17:03:36 +0200
changeset 350784 1796b06d333cd97b7aec26d41dca1d5d2b348f78
parent 350783 565744df41736b4f662f9ddcd767bf4fe711a938
child 350785 b63199973fca016285756d6d2c7c283f2ba8a2ed
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu, efaust, ritu
bugs1308346
milestone50.0
Bug 1308346 - Return new.target separately from readFrameArgsAndLocals. r=shu,efaust a=ritu
js/src/jit/JitFrameIterator.h
js/src/jit/RematerializedFrame.cpp
js/src/jit/RematerializedFrame.h
--- a/js/src/jit/JitFrameIterator.h
+++ b/js/src/jit/JitFrameIterator.h
@@ -690,17 +690,18 @@ class InlineFrameIterator
             return numActualArgs_;
 
         return frame_->numActualArgs();
     }
 
     template <class ArgOp, class LocalOp>
     void readFrameArgsAndLocals(JSContext* cx, ArgOp& argOp, LocalOp& localOp,
                                 JSObject** scopeChain, bool* hasCallObj,
-                                Value* rval, ArgumentsObject** argsObj, Value* thisv,
+                                Value* rval, ArgumentsObject** argsObj,
+                                Value* thisv, Value* newTarget,
                                 ReadFrameArgsBehavior behavior,
                                 MaybeReadFallback& fallback) const
     {
         SnapshotIterator s(si_);
 
         // Read the scope chain.
         if (scopeChain) {
             Value scopeChainValue = s.maybeRead(fallback);
@@ -710,16 +711,23 @@ class InlineFrameIterator
         }
 
         // Read return value.
         if (rval)
             *rval = s.maybeRead(fallback);
         else
             s.skip();
 
+        if (newTarget) {
+            // For now, only support reading new.target when we are reading
+            // overflown arguments.
+            MOZ_ASSERT(behavior != ReadFrame_Formals);
+            newTarget->setUndefined();
+        }
+
         // Read arguments, which only function frames have.
         if (isFunctionFrame()) {
             unsigned nactual = numActualArgs();
             unsigned nformal = calleeTemplate()->nargs();
 
             // Get the non overflown arguments, which are taken from the inlined
             // frame, because it will have the updated value when JSOP_SETARG is
             // done.
@@ -750,41 +758,45 @@ class InlineFrameIterator
                     for (unsigned j = 0; j < skip; j++)
                         parent_s.skip();
 
                     // Get the overflown arguments
                     MaybeReadFallback unusedFallback;
                     parent_s.skip(); // scope chain
                     parent_s.skip(); // return value
                     parent_s.readFunctionFrameArgs(argOp, nullptr, nullptr,
-                                                   nformal, nactual + isConstructing(), it.script(),
+                                                   nformal, nactual, it.script(),
                                                    fallback);
+                    if (newTarget && isConstructing())
+                        *newTarget = parent_s.maybeRead(fallback);
                 } else {
                     // There is no parent frame to this inlined frame, we can read
                     // from the frame's Value vector directly.
                     Value* argv = frame_->actualArgs();
-                    for (unsigned i = nformal; i < nactual + isConstructing(); i++)
+                    for (unsigned i = nformal; i < nactual; i++)
                         argOp(argv[i]);
+                    if (newTarget && isConstructing())
+                        *newTarget = argv[nactual];
                 }
             }
         }
 
         // At this point we've read all the formals in s, and can read the
         // locals.
         for (unsigned i = 0; i < script()->nfixed(); i++)
             localOp(s.maybeRead(fallback));
     }
 
     template <class Op>
     void unaliasedForEachActual(JSContext* cx, Op op,
                                 ReadFrameArgsBehavior behavior,
                                 MaybeReadFallback& fallback) const
     {
         Nop nop;
-        readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr,
+        readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr, nullptr,
                                nullptr, nullptr, behavior, fallback);
     }
 
     JSScript* script() const {
         return script_;
     }
     jsbytecode* pc() const {
         return pc_;
--- a/js/src/jit/RematerializedFrame.cpp
+++ b/js/src/jit/RematerializedFrame.cpp
@@ -46,26 +46,26 @@ RematerializedFrame::RematerializedFrame
 {
     if (iter.isFunctionFrame())
         callee_ = iter.callee(fallback);
     else
         callee_ = nullptr;
 
     CopyValueToRematerializedFrame op(slots_);
     iter.readFrameArgsAndLocals(cx, op, op, &scopeChain_, &hasCallObj_, &returnValue_,
-                                &argsObj_, &thisArgument_, ReadFrame_Actuals,
+                                &argsObj_, &thisArgument_, &newTarget_, ReadFrame_Actuals,
                                 fallback);
 }
 
 /* static */ RematerializedFrame*
 RematerializedFrame::New(JSContext* cx, uint8_t* top, InlineFrameIterator& iter,
                          MaybeReadFallback& fallback)
 {
     unsigned numFormals = iter.isFunctionFrame() ? iter.calleeTemplate()->nargs() : 0;
-    unsigned argSlots = Max(numFormals, iter.numActualArgs()) + iter.isConstructing();
+    unsigned argSlots = Max(numFormals, iter.numActualArgs());
     size_t numBytes = sizeof(RematerializedFrame) +
         (argSlots + iter.script()->nfixed()) * sizeof(Value) -
         sizeof(Value); // 1 Value included in sizeof(RematerializedFrame)
 
     void* buf = cx->pod_calloc<uint8_t>(numBytes);
     if (!buf)
         return nullptr;
 
@@ -160,18 +160,18 @@ RematerializedFrame::mark(JSTracer* trc)
     TraceRoot(trc, &script_, "remat ion frame script");
     TraceRoot(trc, &scopeChain_, "remat ion frame scope chain");
     if (callee_)
         TraceRoot(trc, &callee_, "remat ion frame callee");
     if (argsObj_)
         TraceRoot(trc, &argsObj_, "remat ion frame argsobj");
     TraceRoot(trc, &returnValue_, "remat ion frame return value");
     TraceRoot(trc, &thisArgument_, "remat ion frame this");
-    TraceRootRange(trc, numArgSlots() + isConstructing_ + script_->nfixed(),
-                   slots_, "remat ion frame stack");
+    TraceRoot(trc, &newTarget_, "remat ion frame newTarget");
+    TraceRootRange(trc, numArgSlots() + script_->nfixed(), slots_, "remat ion frame stack");
 }
 
 void
 RematerializedFrame::dump()
 {
     fprintf(stderr, " Rematerialized Ion Frame%s\n", inlined() ? " (inlined)" : "");
     if (isFunctionFrame()) {
         fprintf(stderr, "  callee fun: ");
--- a/js/src/jit/RematerializedFrame.h
+++ b/js/src/jit/RematerializedFrame.h
@@ -53,16 +53,17 @@ class RematerializedFrame
 
     JSScript* script_;
     JSObject* scopeChain_;
     JSFunction* callee_;
     ArgumentsObject* argsObj_;
 
     Value returnValue_;
     Value thisArgument_;
+    Value newTarget_;
     Value slots_[1];
 
     RematerializedFrame(JSContext* cx, uint8_t* top, unsigned numActualArgs,
                         InlineFrameIterator& iter, MaybeReadFallback& fallback);
 
   public:
     static RematerializedFrame* New(JSContext* cx, uint8_t* top, InlineFrameIterator& iter,
                                     MaybeReadFallback& fallback);
@@ -185,17 +186,17 @@ class RematerializedFrame
     unsigned numArgSlots() const {
         return (std::max)(numFormalArgs(), numActualArgs());
     }
 
     Value* argv() {
         return slots_;
     }
     Value* locals() {
-        return slots_ + numArgSlots() + isConstructing_;
+        return slots_ + numArgSlots();
     }
 
     Value& unaliasedLocal(unsigned i) {
         MOZ_ASSERT(i < script()->nfixed());
         return locals()[i];
     }
     Value& unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) {
         MOZ_ASSERT(i < numFormalArgs());
@@ -209,19 +210,18 @@ class RematerializedFrame
         MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
         return argv()[i];
     }
 
     Value newTarget() {
         MOZ_ASSERT(isFunctionFrame());
         if (callee()->isArrow())
             return callee()->getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
-        if (isConstructing())
-            return argv()[numActualArgs()];
-        return UndefinedValue();
+        MOZ_ASSERT_IF(!isConstructing(), newTarget_.isUndefined());
+        return newTarget_;
     }
 
     void setReturnValue(const Value& value) {
         returnValue_ = value;
     }
 
     Value& returnValue() {
         return returnValue_;