Backed out changeset 213b09228bdf (bug 1141865)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 03 Jun 2015 12:41:25 +0200
changeset 269639 05411d0a95ad05108ec468fbc12bb84ddaee7d4b
parent 269638 3cbe1f9d3557576631ee67de686e57ea6d581403
child 269640 b003dbf1e2536d38220b85961422c95a3860faed
push id2540
push userwcosta@mozilla.com
push dateWed, 03 Jun 2015 20:55:41 +0000
bugs1141865
milestone41.0a1
backs out213b09228bdfc38905dcd6dbd5ecea040d3bb675
Backed out changeset 213b09228bdf (bug 1141865)
js/src/frontend/SharedContext.h
js/src/jit/BaselineCompiler.cpp
js/src/tests/ecma_6/Class/newTargetGenerators.js
js/src/tests/js1_8_5/reflect-parse/newTarget.js
js/src/vm/GeneratorObject.cpp
js/src/vm/GeneratorObject.h
js/src/vm/Interpreter.cpp
js/src/vm/Stack-inl.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -238,18 +238,18 @@ class SharedContext
 
   protected:
     static bool FunctionAllowsSyntax(JSFunction* func, AllowedSyntax allowed)
     {
         MOZ_ASSERT(!func->isArrow());
 
         switch (allowed) {
           case AllowedSyntax::NewTarget:
-            // Any function supports new.target
-            return true;
+            // For now, disallow new.target inside generators
+            return !func->isGenerator();
           case AllowedSyntax::SuperProperty:
             return func->allowSuperProperty();
           default:;
         }
         MOZ_CRASH("Unknown AllowedSyntax query");
     }
 };
 
@@ -368,16 +368,21 @@ class FunctionBox : public ObjectBox, pu
         return bindings.hasAnyAliasedBindings() ||
                hasExtensibleScope() ||
                needsDeclEnvObject() ||
                needsHomeObject()    ||
                isGenerator();
     }
 
     bool allowSyntax(AllowedSyntax allowed) const {
+        // For now (!) we don't allow new.target in generators, and can't
+        // check that for functions we haven't finished parsing, as they
+        // don't have initialized scripts. Check from our stashed bits instead.
+        if (allowed == AllowedSyntax::NewTarget)
+            return !isGenerator();
         return FunctionAllowsSyntax(function(), allowed);
     }
 };
 
 inline FunctionBox*
 SharedContext::asFunctionBox()
 {
     MOZ_ASSERT(isFunctionBox());
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -3673,29 +3673,16 @@ BaselineCompiler::emit_JSOP_RESUME()
     Register scratch1 = regs.takeAny();
     masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), scratch1);
 
     // Load the BaselineScript or call a stub if we don't have one.
     Label interpret;
     masm.loadPtr(Address(scratch1, JSScript::offsetOfBaselineScript()), scratch1);
     masm.branchPtr(Assembler::BelowOrEqual, scratch1, ImmPtr(BASELINE_DISABLED_SCRIPT), &interpret);
 
-    Register constructing = regs.takeAny();
-    ValueOperand newTarget = regs.takeAnyValue();
-    masm.loadValue(Address(genObj, GeneratorObject::offsetOfNewTargetSlot()), newTarget);
-    masm.move32(Imm32(0), constructing);
-    {
-        Label notConstructing;
-        masm.branchTestObject(Assembler::NotEqual, newTarget, &notConstructing);
-        masm.pushValue(newTarget);
-        masm.move32(Imm32(CalleeToken_FunctionConstructing), constructing);
-        masm.bind(&notConstructing);
-    }
-    regs.add(newTarget);
-
     // Push |undefined| for all formals.
     Register scratch2 = regs.takeAny();
     Label loop, loopDone;
     masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), scratch2);
     masm.bind(&loop);
     masm.branchTest32(Assembler::Zero, scratch2, scratch2, &loopDone);
     {
         masm.pushValue(UndefinedValue());
@@ -3710,24 +3697,20 @@ BaselineCompiler::emit_JSOP_RESUME()
     // Update BaselineFrame frameSize field and create the frame descriptor.
     masm.computeEffectiveAddress(Address(BaselineFrameReg, BaselineFrame::FramePointerOffset),
                                  scratch2);
     masm.subPtr(BaselineStackReg, scratch2);
     masm.store32(scratch2, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
     masm.makeFrameDescriptor(scratch2, JitFrame_BaselineJS);
 
     masm.Push(Imm32(0)); // actual argc
-
-    // Duplicate PushCalleeToken with a variable instead.
-    masm.orPtr(constructing, callee);
-    masm.Push(callee);
+    masm.PushCalleeToken(callee, false);
     masm.Push(scratch2); // frame descriptor
 
     regs.add(callee);
-    regs.add(constructing);
 
     // Load the return value.
     ValueOperand retVal = regs.takeAnyValue();
     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), retVal);
 
     // Push a fake return address on the stack. We will resume here when the
     // generator returns.
     Label genStart, returnTarget;
deleted file mode 100644
--- a/js/src/tests/ecma_6/Class/newTargetGenerators.js
+++ /dev/null
@@ -1,24 +0,0 @@
-function *generatorNewTarget(expected) {
-    assertEq(new.target, expected);
-    assertEq(eval('new.target'), expected);
-    assertEq((() => new.target)(), expected);
-    yield (() => new.target);
-}
-
-const ITERATIONS = 25;
-
-for (let i = 0; i < ITERATIONS; i++)
-    assertEq(generatorNewTarget(undefined).next().value(), undefined);
-
-for (let i = 0; i < ITERATIONS; i++)
-    assertEq(new generatorNewTarget(generatorNewTarget).next().value(),
-             generatorNewTarget);
-
-// also check to make sure it's useful in yield inside generators.
-// Plus, this code is so ugly, how could it not be a test? ;)
-// Thanks to anba for supplying this ludicrous expression.
-assertDeepEq([...new function*(i) { yield i; if(i > 0) yield* new new.target(i-1) }(10)],
-             [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ]);
-
-if (typeof reportCompare === 'function')
-    reportCompare(0,0,"OK");
--- a/js/src/tests/js1_8_5/reflect-parse/newTarget.js
+++ b/js/src/tests/js1_8_5/reflect-parse/newTarget.js
@@ -10,19 +10,18 @@ function testNewTarget() {
 
     // invalid in top-level scripts
     assertError("new.target", SyntaxError);
 
     // valid in arrow functions inside functions
     assertInFunctionExpr("()=>new.target", arrowExpr([], newTarget()));
     assertError("(() => new.target))", SyntaxError);
 
-    // valid in generators, too!
-    assertStmt("function *foo() { new.target; }", genFunDecl(ident("foo"), [],
-               blockStmt([exprStmt(newTarget())])));
+    // invalid (for now!) in generators
+    assertError("function *foo() { new.target; }", SyntaxError);
 
     // new.target is a member expression. You should be able to call, invoke, or
     // access properties of it.
     assertInFunctionExpr("new.target.foo", dotExpr(newTarget(), ident("foo")));
     assertInFunctionExpr("new.target[\"foo\"]", memExpr(newTarget(), literal("foo")));
 
     assertInFunctionExpr("new.target()", callExpr(newTarget(), []));
     assertInFunctionExpr("new new.target()", newExpr(newTarget(), []));
--- a/js/src/vm/GeneratorObject.cpp
+++ b/js/src/vm/GeneratorObject.cpp
@@ -44,17 +44,16 @@ GeneratorObject::create(JSContext* cx, A
         obj = NewNativeObjectWithGivenProto(cx, &LegacyGeneratorObject::class_, proto);
     }
     if (!obj)
         return nullptr;
 
     GeneratorObject* genObj = &obj->as<GeneratorObject>();
     genObj->setCallee(*frame.callee());
     genObj->setThisValue(frame.thisValue());
-    genObj->setNewTarget(frame.newTarget());
     genObj->setScopeChain(*frame.scopeChain());
     if (frame.script()->needsArgsObj())
         genObj->setArgsObj(frame.argsObj());
     genObj->clearExpressionStack();
 
     return obj;
 }
 
@@ -158,19 +157,18 @@ bool
 GeneratorObject::resume(JSContext* cx, InterpreterActivation& activation,
                         HandleObject obj, HandleValue arg, GeneratorObject::ResumeKind resumeKind)
 {
     Rooted<GeneratorObject*> genObj(cx, &obj->as<GeneratorObject>());
     MOZ_ASSERT(genObj->isSuspended());
 
     RootedFunction callee(cx, &genObj->callee());
     RootedValue thisv(cx, genObj->thisValue());
-    RootedValue newTarget(cx, genObj->newTarget());
     RootedObject scopeChain(cx, &genObj->scopeChain());
-    if (!activation.resumeGeneratorFrame(callee, thisv, newTarget, scopeChain))
+    if (!activation.resumeGeneratorFrame(callee, thisv, scopeChain))
         return false;
 
     if (genObj->hasArgsObj())
         activation.regs().fp()->initArgsObj(genObj->argsObj());
 
     if (genObj->hasExpressionStack()) {
         uint32_t len = genObj->expressionStack().length();
         MOZ_ASSERT(activation.regs().spForStackDepth(len));
--- a/js/src/vm/GeneratorObject.h
+++ b/js/src/vm/GeneratorObject.h
@@ -26,17 +26,16 @@ class GeneratorObject : public NativeObj
 
     enum {
         CALLEE_SLOT = 0,
         THIS_SLOT,
         SCOPE_CHAIN_SLOT,
         ARGS_OBJ_SLOT,
         EXPRESSION_STACK_SLOT,
         YIELD_INDEX_SLOT,
-        NEWTARGET_SLOT,
         RESERVED_SLOTS
     };
 
     enum ResumeKind { NEXT, THROW, CLOSE };
 
   private:
     static bool suspend(JSContext* cx, HandleObject obj, AbstractFramePtr frame, jsbytecode* pc,
                         Value* vp, unsigned nvalues);
@@ -113,27 +112,16 @@ class GeneratorObject : public NativeObj
     }
     void setExpressionStack(ArrayObject& expressionStack) {
         setFixedSlot(EXPRESSION_STACK_SLOT, ObjectValue(expressionStack));
     }
     void clearExpressionStack() {
         setFixedSlot(EXPRESSION_STACK_SLOT, NullValue());
     }
 
-    bool isConstructing() const {
-        return getFixedSlot(NEWTARGET_SLOT).isObject();
-    }
-    const Value& newTarget() const {
-        return getFixedSlot(NEWTARGET_SLOT);
-    }
-    void setNewTarget(Value newTarget) {
-        setFixedSlot(NEWTARGET_SLOT, newTarget);
-    }
-
-
     // The yield index slot is abused for a few purposes.  It's undefined if
     // it hasn't been set yet (before the initial yield), and null if the
     // generator is closed. If the generator is running, the yield index is
     // YIELD_INDEX_RUNNING. If the generator is in that bizarre "closing"
     // state, the yield index is YIELD_INDEX_CLOSING.
     //
     // If the generator is suspended, it's the yield index (stored as
     // JSOP_INITIALYIELD/JSOP_YIELD operand) of the yield instruction that
@@ -179,17 +167,16 @@ class GeneratorObject : public NativeObj
     }
     void setClosed() {
         setFixedSlot(CALLEE_SLOT, NullValue());
         setFixedSlot(THIS_SLOT, NullValue());
         setFixedSlot(SCOPE_CHAIN_SLOT, NullValue());
         setFixedSlot(ARGS_OBJ_SLOT, NullValue());
         setFixedSlot(EXPRESSION_STACK_SLOT, NullValue());
         setFixedSlot(YIELD_INDEX_SLOT, NullValue());
-        setFixedSlot(NEWTARGET_SLOT, NullValue());
     }
 
     static size_t offsetOfCalleeSlot() {
         return getFixedSlotOffset(CALLEE_SLOT);
     }
     static size_t offsetOfThisSlot() {
         return getFixedSlotOffset(THIS_SLOT);
     }
@@ -200,19 +187,16 @@ class GeneratorObject : public NativeObj
         return getFixedSlotOffset(ARGS_OBJ_SLOT);
     }
     static size_t offsetOfYieldIndexSlot() {
         return getFixedSlotOffset(YIELD_INDEX_SLOT);
     }
     static size_t offsetOfExpressionStackSlot() {
         return getFixedSlotOffset(EXPRESSION_STACK_SLOT);
     }
-    static size_t offsetOfNewTargetSlot() {
-        return getFixedSlotOffset(NEWTARGET_SLOT);
-    }
 };
 
 class LegacyGeneratorObject : public GeneratorObject
 {
   public:
     static const Class class_;
 
     static bool close(JSContext* cx, HandleObject obj);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -3807,20 +3807,16 @@ CASE(JSOP_YIELD)
 CASE(JSOP_RESUME)
 {
     {
         ReservedRooted<JSObject*> gen(&rootObject0, &REGS.sp[-2].toObject());
         ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]);
         // popInlineFrame expects there to be an additional value on the stack
         // to pop off, so leave "gen" on the stack.
 
-        // Again, lie to popInlineFrame. Add a "new.target" to pop later.
-        if (gen->as<GeneratorObject>().isConstructing())
-            PUSH_UNDEFINED();
-
         GeneratorObject::ResumeKind resumeKind = GeneratorObject::getResumeKind(REGS.pc);
         bool ok = GeneratorObject::resume(cx, activation, gen, val, resumeKind);
         SET_SCRIPT(REGS.fp()->script());
         if (!ok)
             goto error;
     }
     ADVANCE_AND_DISPATCH(0);
 }
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -343,49 +343,44 @@ InterpreterStack::pushInlineFrame(JSCont
 
     regs.prepareToRun(*fp, script);
     return true;
 }
 
 MOZ_ALWAYS_INLINE bool
 InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
                                            HandleFunction callee, HandleValue thisv,
-                                           HandleValue newTarget, HandleObject scopeChain)
+                                           HandleObject scopeChain)
 {
     MOZ_ASSERT(callee->isGenerator());
     RootedScript script(cx, callee->getOrCreateScript(cx));
     InterpreterFrame* prev = regs.fp();
     jsbytecode* prevpc = regs.pc;
     Value* prevsp = regs.sp;
     MOZ_ASSERT(prev);
 
     script->ensureNonLazyCanonicalFunction(cx);
 
     LifoAlloc::Mark mark = allocator_.mark();
 
-    bool constructing = newTarget.isObject();
-
-    // Include callee, |this|, and maybe |new.target|
+    // Include callee, |this|.
     unsigned nformal = callee->nargs();
-    unsigned nvals = 2 + constructing + nformal + script->nslots();
+    unsigned nvals = 2 + nformal + script->nslots();
 
     uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
     if (!buffer)
         return false;
 
     Value* argv = reinterpret_cast<Value*>(buffer) + 2;
     argv[-2] = ObjectValue(*callee);
     argv[-1] = thisv;
     SetValueRangeToUndefined(argv, nformal);
-    if (constructing)
-        argv[nformal] = newTarget;
 
-    InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(argv + nformal + constructing);
-    InterpreterFrame::Flags flags = constructing ? ToFrameFlags(INITIAL_CONSTRUCT)
-                                                 : ToFrameFlags(INITIAL_NONE);
+    InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(argv + nformal);
+    InterpreterFrame::Flags flags = ToFrameFlags(INITIAL_NONE);
     fp->mark_ = mark;
     fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, 0, flags);
     fp->resumeGeneratorFrame(scopeChain);
 
     regs.prepareToRun(*fp, script);
     return true;
 }
 
@@ -965,20 +960,20 @@ InterpreterActivation::popInlineFrame(In
     MOZ_ASSERT(regs_.fp() == frame);
     MOZ_ASSERT(regs_.fp() != entryFrame_);
 
     cx_->asJSContext()->runtime()->interpreterStack().popInlineFrame(regs_);
 }
 
 inline bool
 InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleValue thisv,
-                                            HandleValue newTarget, HandleObject scopeChain)
+                                            HandleObject scopeChain)
 {
     InterpreterStack& stack = cx_->asJSContext()->runtime()->interpreterStack();
-    if (!stack.resumeGeneratorCallFrame(cx_->asJSContext(), regs_, callee, thisv, newTarget, scopeChain))
+    if (!stack.resumeGeneratorCallFrame(cx_->asJSContext(), regs_, callee, thisv, scopeChain))
         return false;
 
     MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_);
     return true;
 }
 
 inline JSContext*
 AsmJSActivation::cx()
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -280,17 +280,17 @@ InterpreterFrame::epilogue(JSContext* cx
                       scopeChain()->as<CallObject>().callee().nonLazyScript() == script);
     } else {
         AssertDynamicScopeMatchesStaticScope(cx, script, scopeChain());
     }
 
     if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
         DebugScopes::onPopCall(this, cx);
 
-    if (!fun()->isGenerator() && isConstructing() && thisValue().isObject() && returnValue().isPrimitive())
+    if (isConstructing() && thisValue().isObject() && returnValue().isPrimitive())
         setReturnValue(ObjectValue(constructorThis()));
 }
 
 bool
 InterpreterFrame::pushBlock(JSContext* cx, StaticBlockObject& block)
 {
     MOZ_ASSERT(block.needsClone());
 
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1036,17 +1036,17 @@ class InterpreterStack
     // new InterpreterActivation or recursively calling Interpret.
     bool pushInlineFrame(JSContext* cx, InterpreterRegs& regs, const CallArgs& args,
                          HandleScript script, InitialFrameFlags initial);
 
     void popInlineFrame(InterpreterRegs& regs);
 
     bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
                                   HandleFunction callee, HandleValue thisv,
-                                  HandleValue newTarget, HandleObject scopeChain);
+                                  HandleObject scopeChain);
 
     inline void purge(JSRuntime* rt);
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
         return allocator_.sizeOfExcludingThis(mallocSizeOf);
     }
 };
 
@@ -1244,17 +1244,17 @@ class InterpreterActivation : public Act
     inline InterpreterActivation(RunState& state, JSContext* cx, InterpreterFrame* entryFrame);
     inline ~InterpreterActivation();
 
     inline bool pushInlineFrame(const CallArgs& args, HandleScript script,
                                 InitialFrameFlags initial);
     inline void popInlineFrame(InterpreterFrame* frame);
 
     inline bool resumeGeneratorFrame(HandleFunction callee, HandleValue thisv,
-                                     HandleValue newTarget, HandleObject scopeChain);
+                                     HandleObject scopeChain);
 
     InterpreterFrame* current() const {
         return regs_.fp();
     }
     InterpreterRegs& regs() {
         return regs_;
     }
     InterpreterFrame* entryFrame() const {