Bug 1308346 - Return new.target separately from readFrameArgsAndLocals. r=shu,efaust
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 21 Oct 2016 17:03:36 +0200
changeset 318839 3428128df1170d4f9a0148aabe2a6f717bf43908
parent 318838 d3de60b2f63081c33db27c86c56ee7de2b6bec08
child 318840 c827628cdf72242ffa592854d06e1257d2f28d80
push id83034
push userjandemooij@gmail.com
push dateFri, 21 Oct 2016 15:04:05 +0000
treeherdermozilla-inbound@3428128df117 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu, efaust
bugs1308346
milestone52.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 1308346 - Return new.target separately from readFrameArgsAndLocals. r=shu,efaust
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** envChain, bool* hasInitialEnv,
-                                Value* rval, ArgumentsObject** argsObj, Value* thisv,
+                                Value* rval, ArgumentsObject** argsObj,
+                                Value* thisv, Value* newTarget,
                                 ReadFrameArgsBehavior behavior,
                                 MaybeReadFallback& fallback) const
     {
         SnapshotIterator s(si_);
 
         // Read the env chain.
         if (envChain) {
             Value envChainValue = 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(); // env 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, &envChain_, &hasInitialEnv_, &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;
 
@@ -142,18 +142,18 @@ RematerializedFrame::trace(JSTracer* trc
     TraceRoot(trc, &script_, "remat ion frame script");
     TraceRoot(trc, &envChain_, "remat ion frame env 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
@@ -56,16 +56,17 @@ class RematerializedFrame
 
     JSScript* script_;
     JSObject* envChain_;
     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);
@@ -200,17 +201,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());
@@ -224,19 +225,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_;