Bug 1343481 - Part 1: Remove {JSFunction,JSScript,LazyScript}.isGenerator() method. r=shu
authorTooru Fujisawa <arai_a@mac.com>
Wed, 01 Mar 2017 20:40:04 +0900
changeset 374317 3f9cb5adce0e76c382b910b52e602d552b3dc1b9
parent 374316 c594a1353f5dca6f24b45cfc5fd979d3bae837bd
child 374318 5ce3e1a949a61ab7a5caf942e8ca318621babc68
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1343481
milestone54.0a1
Bug 1343481 - Part 1: Remove {JSFunction,JSScript,LazyScript}.isGenerator() method. r=shu
js/src/builtin/ReflectParse.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/frontend/SharedContext.h
js/src/jit/Ion.cpp
js/src/jit/IonAnalysis.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsscript.cpp
js/src/jsscript.h
js/src/tests/js1_8_5/reflect-parse/PatternBuilders.js
js/src/vm/Debugger.cpp
js/src/vm/EnvironmentObject.cpp
js/src/vm/GeneratorObject.cpp
js/src/vm/ObjectGroup.cpp
js/src/vm/Probes-inl.h
js/src/vm/SelfHosting.cpp
js/src/vm/Stack-inl.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/src/wasm/AsmJS.cpp
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -3411,20 +3411,20 @@ ASTSerializer::identifier(ParseNode* pn,
 }
 
 bool
 ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst)
 {
     RootedFunction func(cx, pn->pn_funbox->function());
 
     GeneratorStyle generatorStyle =
-        pn->pn_funbox->isGenerator()
-        ? (pn->pn_funbox->isLegacyGenerator()
-           ? GeneratorStyle::Legacy
-           : GeneratorStyle::ES6)
+        pn->pn_funbox->isStarGenerator()
+        ? GeneratorStyle::ES6
+        : pn->pn_funbox->isLegacyGenerator()
+        ? GeneratorStyle::Legacy
         : GeneratorStyle::None;
 
     bool isAsync = pn->pn_funbox->isAsync();
     bool isExpression = pn->pn_funbox->isExprBody();
 
     RootedValue id(cx);
     RootedAtom funcAtom(cx, func->explicitName());
     if (!optIdentifier(funcAtom, nullptr, &id))
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -384,17 +384,20 @@ class BytecodeEmitter::EmitterScope : pu
         environmentChainLength_ = mozilla::AssertedCast<uint8_t>(hops + 1);
         return true;
     }
 
     void updateFrameFixedSlots(BytecodeEmitter* bce, const BindingIter& bi) {
         nextFrameSlot_ = bi.nextFrameSlot();
         if (nextFrameSlot_ > bce->maxFixedSlots)
             bce->maxFixedSlots = nextFrameSlot_;
-        MOZ_ASSERT_IF(bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->isGenerator(),
+        MOZ_ASSERT_IF(bce->sc->isFunctionBox() &&
+                      (bce->sc->asFunctionBox()->isStarGenerator() ||
+                       bce->sc->asFunctionBox()->isLegacyGenerator() ||
+                       bce->sc->asFunctionBox()->isAsync()),
                       bce->maxFixedSlots == 0);
     }
 
     MOZ_MUST_USE bool putNameInCache(BytecodeEmitter* bce, JSAtom* name, NameLocation loc) {
         NameLocationMap& cache = *nameCache_;
         NameLocationMap::AddPtr p = cache.lookupForAdd(name);
         MOZ_ASSERT(!p);
         if (!cache.add(p, name, loc)) {
@@ -4786,17 +4789,19 @@ BytecodeEmitter::isRunOnceLambda()
     if (!(parent && parent->emittingRunOnceLambda) &&
         (emitterMode != LazyFunction || !lazyScript->treatAsRunOnce()))
     {
         return false;
     }
 
     FunctionBox* funbox = sc->asFunctionBox();
     return !funbox->argumentsHasLocalBinding() &&
-           !funbox->isGenerator() &&
+           !funbox->isStarGenerator() &&
+           !funbox->isLegacyGenerator() &&
+           !funbox->isAsync() &&
            !funbox->function()->explicitName();
 }
 
 bool
 BytecodeEmitter::emitYieldOp(JSOp op)
 {
     if (op == JSOP_FINALYIELDRVAL)
         return emit1(JSOP_FINALYIELDRVAL);
@@ -8276,36 +8281,36 @@ BytecodeEmitter::emitReturn(ParseNode* p
      * with the correct stack pointer (i.e., after popping any with,
      * for/in, etc., slots nested inside the finally's try).
      *
      * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
      * extra JSOP_RETRVAL after the fixups.
      */
     ptrdiff_t top = offset();
 
-    bool isGenerator = sc->isFunctionBox() && sc->asFunctionBox()->isGenerator();
+    bool needsFinalYield = sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
     bool isDerivedClassConstructor =
         sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
 
-    if (!emit1((isGenerator || isDerivedClassConstructor) ? JSOP_SETRVAL : JSOP_RETURN))
+    if (!emit1((needsFinalYield || isDerivedClassConstructor) ? JSOP_SETRVAL : JSOP_RETURN))
         return false;
 
     // Make sure that we emit this before popping the blocks in prepareForNonLocalJump,
     // to ensure that the error is thrown while the scope-chain is still intact.
     if (isDerivedClassConstructor) {
         if (!emitCheckDerivedClassConstructorReturn())
             return false;
     }
 
     NonLocalExitControl nle(this, NonLocalExitControl::Return);
 
     if (!nle.prepareForNonLocalJumpToOutermost())
         return false;
 
-    if (isGenerator) {
+    if (needsFinalYield) {
         // We know that .generator is on the function scope, as we just exited
         // all nested scopes.
         NameLocation loc =
             *locationOfNameBoundInFunctionScope(cx->names().dotGenerator, varEmitterScope);
         if (!emitGetNameAtLocation(cx->names().dotGenerator, loc))
             return false;
         if (!emitYieldOp(JSOP_FINALYIELDRVAL))
             return false;
@@ -10085,25 +10090,25 @@ BytecodeEmitter::emitInitializeFunctionS
 bool
 BytecodeEmitter::emitFunctionBody(ParseNode* funBody)
 {
     FunctionBox* funbox = sc->asFunctionBox();
 
     if (!emitTree(funBody))
         return false;
 
-    if (funbox->isGenerator()) {
+    if (funbox->needsFinalYield()) {
         // If we fall off the end of a generator, do a final yield.
         if (funbox->isStarGenerator() && !emitPrepareIteratorResult())
             return false;
 
         if (!emit1(JSOP_UNDEFINED))
             return false;
 
-        if (sc->asFunctionBox()->isStarGenerator() && !emitFinishIteratorResult(true))
+        if (funbox->isStarGenerator() && !emitFinishIteratorResult(true))
             return false;
 
         if (!emit1(JSOP_SETRVAL))
             return false;
 
         NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator);
         if (!emitGetNameAtLocation(cx->names().dotGenerator, loc))
             return false;
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2635,17 +2635,17 @@ Parser<ParseHandler>::functionBody(InHan
         break;
 
       case StarGenerator:
         MOZ_ASSERT_IF(!pc->isAsync(), kind != Arrow);
         MOZ_ASSERT_IF(!pc->isAsync(), type == StatementListBody);
         break;
     }
 
-    if (pc->isGenerator()) {
+    if (pc->needsDotGeneratorName()) {
         MOZ_ASSERT_IF(!pc->isAsync(), type == StatementListBody);
         if (!declareDotGeneratorName())
             return null();
         Node generator = newDotGeneratorName();
         if (!generator)
             return null();
         if (!handler.prependInitialYield(pn, generator))
             return null();
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -496,32 +496,32 @@ class ParseContext : public Nestable<Par
 
     // Most functions start off being parsed as non-generators.
     // Non-generators transition to LegacyGenerator on parsing "yield" in JS 1.7.
     // An ES6 generator is marked as a "star generator" before its body is parsed.
     GeneratorKind generatorKind() const {
         return sc_->isFunctionBox() ? sc_->asFunctionBox()->generatorKind() : NotGenerator;
     }
 
-    bool isGenerator() const {
-        return generatorKind() != NotGenerator;
-    }
-
     bool isLegacyGenerator() const {
         return generatorKind() == LegacyGenerator;
     }
 
     bool isStarGenerator() const {
         return generatorKind() == StarGenerator;
     }
 
     bool isAsync() const {
         return sc_->isFunctionBox() && sc_->asFunctionBox()->isAsync();
     }
 
+    bool needsDotGeneratorName() const {
+        return isStarGenerator() || isLegacyGenerator() || isAsync();
+    }
+
     FunctionAsyncKind asyncKind() const {
         return isAsync() ? AsyncFunction : SyncFunction;
     }
 
     bool isArrowFunction() const {
         return sc_->isFunctionBox() && sc_->asFunctionBox()->function()->isArrow();
     }
 
@@ -811,17 +811,19 @@ class ParserBase : public StrictModeGett
     const char* getFilename() const { return tokenStream.getFilename(); }
     JSVersion versionNumber() const { return tokenStream.versionNumber(); }
     TokenPos pos() const { return tokenStream.currentToken().pos; }
 
     // Determine whether |yield| is a valid name in the current context, or
     // whether it's prohibited due to strictness, JS version, or occurrence
     // inside a star generator.
     bool yieldExpressionsSupported() {
-        return (versionNumber() >= JSVERSION_1_7 || pc->isGenerator()) && !pc->isAsync();
+        return (versionNumber() >= JSVERSION_1_7 && !pc->isAsync()) ||
+               pc->isStarGenerator() ||
+               pc->isLegacyGenerator();
     }
 
     virtual bool strictMode() { return pc->sc()->strict(); }
     bool setLocalStrictMode(bool strict) {
         MOZ_ASSERT(tokenStream.debugHasNoLookahead());
         return pc->sc()->setLocalStrictMode(strict);
     }
 
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -512,39 +512,48 @@ class FunctionBox : public ObjectBox, pu
                       enclosingScope_ == function()->lazyScript()->enclosingScope());
         return enclosingScope_;
     }
 
     bool needsCallObjectRegardlessOfBindings() const {
         return hasExtensibleScope() ||
                needsHomeObject() ||
                isDerivedClassConstructor() ||
-               isGenerator();
+               isStarGenerator() ||
+               isLegacyGenerator() ||
+               isAsync();
     }
 
     bool hasExtraBodyVarScope() const {
         return hasParameterExprs &&
                (extraVarScopeBindings_ ||
                 needsExtraBodyVarEnvironmentRegardlessOfBindings());
     }
 
     bool needsExtraBodyVarEnvironmentRegardlessOfBindings() const {
         MOZ_ASSERT(hasParameterExprs);
-        return hasExtensibleScope() || isGenerator();
+        return hasExtensibleScope() || needsDotGeneratorName();
     }
 
     bool isLikelyConstructorWrapper() const {
         return usesArguments && usesApply && usesThis && !usesReturn;
     }
 
     GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
-    bool isGenerator() const { return generatorKind() != NotGenerator; }
     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
     FunctionAsyncKind asyncKind() const { return AsyncKindFromBits(asyncKindBits_); }
+
+    bool needsFinalYield() const {
+        return isStarGenerator() || isLegacyGenerator() || isAsync();
+    }
+    bool needsDotGeneratorName() const {
+        return isStarGenerator() || isLegacyGenerator() || isAsync();
+    }
+
     bool isAsync() const { return asyncKind() == AsyncFunction; }
     bool isArrow() const { return function()->isArrow(); }
 
     bool hasRest() const { return hasRest_; }
     void setHasRest() {
         hasRest_ = true;
     }
 
@@ -552,17 +561,17 @@ class FunctionBox : public ObjectBox, pu
     void setIsExprBody() {
         isExprBody_ = true;
     }
 
     void setGeneratorKind(GeneratorKind kind) {
         // A generator kind can be set at initialization, or when "yield" is
         // first seen.  In both cases the transition can only happen from
         // NotGenerator.
-        MOZ_ASSERT(!isGenerator());
+        MOZ_ASSERT(!isStarGenerator() && !isLegacyGenerator());
         generatorKindBits_ = GeneratorKindAsBits(kind);
     }
 
     bool hasExtensibleScope()        const { return funCxFlags.hasExtensibleScope; }
     bool hasThisBinding()            const { return funCxFlags.hasThisBinding; }
     bool argumentsHasLocalBinding()  const { return funCxFlags.argumentsHasLocalBinding; }
     bool definitelyNeedsArgsObj()    const { return funCxFlags.definitelyNeedsArgsObj; }
     bool needsHomeObject()           const { return funCxFlags.needsHomeObject; }
@@ -639,15 +648,19 @@ SharedContext::asModuleContext()
 // the heap.  This way there is less information to copy off the stack when
 // suspending, and back on when resuming.  It also avoids the need to create
 // and invalidate DebugScope proxies for unaliased locals in a generator
 // frame, as the generator frame will be copied out to the heap and released
 // only by GC.
 inline bool
 SharedContext::allBindingsClosedOver()
 {
-    return bindingsAccessedDynamically() || (isFunctionBox() && asFunctionBox()->isGenerator());
+    return bindingsAccessedDynamically() ||
+           (isFunctionBox() &&
+            (asFunctionBox()->isStarGenerator() ||
+             asFunctionBox()->isLegacyGenerator() ||
+             asFunctionBox()->isAsync()));
 }
 
 } // namespace frontend
 } // namespace js
 
 #endif /* frontend_SharedContext_h */
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -2354,17 +2354,19 @@ IonCompile(JSContext* cx, JSScript* scri
     if (cx->isExceptionPending())
         return AbortReason::Error;
     return AbortReason::Disable;
 }
 
 static bool
 CheckFrame(JSContext* cx, BaselineFrame* frame)
 {
-    MOZ_ASSERT(!frame->script()->isGenerator());
+    MOZ_ASSERT(!frame->script()->isStarGenerator());
+    MOZ_ASSERT(!frame->script()->isLegacyGenerator());
+    MOZ_ASSERT(!frame->script()->isAsync());
     MOZ_ASSERT(!frame->isDebuggerEvalFrame());
     MOZ_ASSERT(!frame->isEvalFrame());
 
     // This check is to not overrun the stack.
     if (frame->isFunctionFrame()) {
         if (TooManyActualArguments(frame->numActualArgs())) {
             TrackAndSpewIonAbort(cx, frame->script(), "too many actual arguments");
             return false;
@@ -2385,20 +2387,24 @@ CheckScript(JSContext* cx, JSScript* scr
     if (script->isForEval()) {
         // Eval frames are not yet supported. Supporting this will require new
         // logic in pushBailoutFrame to deal with linking prev.
         // Additionally, JSOP_DEFVAR support will require baking in isEvalFrame().
         TrackAndSpewIonAbort(cx, script, "eval script");
         return false;
     }
 
-    if (script->isGenerator()) {
+    if (script->isStarGenerator() || script->isLegacyGenerator()) {
         TrackAndSpewIonAbort(cx, script, "generator script");
         return false;
     }
+    if (script->isAsync()) {
+        TrackAndSpewIonAbort(cx, script, "async script");
+        return false;
+    }
 
     if (script->hasNonSyntacticScope() && !script->functionNonDelazifying()) {
         // Support functions with a non-syntactic global scope but not other
         // scripts. For global scripts, IonBuilder currently uses the global
         // object as scope chain, this is not valid when the script has a
         // non-syntactic global scope.
         TrackAndSpewIonAbort(cx, script, "has non-syntactic global scope");
         return false;
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -4401,18 +4401,24 @@ jit::AnalyzeArgumentsUsage(JSContext* cx
     // and also simplifies handling of early returns.
     script->setNeedsArgsObj(true);
 
     // Always construct arguments objects when in debug mode, for generator
     // scripts (generators can be suspended when speculation fails) or when
     // direct eval is present.
     //
     // FIXME: Don't build arguments for ES6 generator expressions.
-    if (scriptArg->isDebuggee() || script->isGenerator() || script->bindingsAccessedDynamically())
+    if (scriptArg->isDebuggee() ||
+        script->isStarGenerator() ||
+        script->isLegacyGenerator() ||
+        script->isAsync() ||
+        script->bindingsAccessedDynamically())
+    {
         return true;
+    }
 
     if (!jit::IsIonEnabled(cx))
         return true;
 
     static const uint32_t MAX_SCRIPT_SIZE = 10000;
     if (script->length() > MAX_SCRIPT_SIZE)
         return true;
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -126,17 +126,21 @@ IsFunctionInStrictMode(JSFunction* fun)
         return true;
 
     // Only asm.js functions can also be strict.
     return IsAsmJSStrictModeModuleOrFunction(fun);
 }
 
 static bool
 IsNewerTypeFunction(JSFunction* fun) {
-    return fun->isArrow() || fun->isGenerator() || fun->isAsync() || fun->isMethod();
+    return fun->isArrow() ||
+           fun->isStarGenerator() ||
+           fun->isLegacyGenerator() ||
+           fun->isAsync() ||
+           fun->isMethod();
 }
 
 // Beware: this function can be invoked on *any* function! That includes
 // natives, strict mode functions, bound functions, arrow functions,
 // self-hosted functions and constructors, asm.js functions, functions with
 // destructuring arguments and/or a rest argument, and probably a few more I
 // forgot. Turn back and save yourself while you still can. It's too late for
 // me.
@@ -475,18 +479,22 @@ fun_resolve(JSContext* cx, HandleObject 
          * Generators are not constructors, but they have a .prototype property anyway,
          * according to errata to ES6. See bug 1191486.
          *
          * Thus all of the following don't get a .prototype property:
          * - Methods (that are not class-constructors or generators)
          * - Arrow functions
          * - Function.prototype
          */
-        if (fun->isBuiltin() || (!fun->isConstructor() && !fun->isGenerator()))
+        if (fun->isBuiltin())
             return true;
+        if (!fun->isConstructor()) {
+            if (!fun->isStarGenerator() && !fun->isLegacyGenerator() && !fun->isAsync())
+                return true;
+        }
 
         if (!ResolveInterpretedFunctionPrototype(cx, fun, id))
             return false;
 
         *resolvedp = true;
         return true;
     }
 
@@ -1564,17 +1572,17 @@ fun_isGenerator(JSContext* cx, unsigned 
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JSFunction* fun;
     if (!IsFunctionObject(args.thisv(), &fun)) {
         args.rval().setBoolean(false);
         return true;
     }
 
-    args.rval().setBoolean(fun->isGenerator());
+    args.rval().setBoolean(fun->isStarGenerator() || fun->isLegacyGenerator());
     return true;
 }
 
 const JSFunctionSpec js::function_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,   fun_toSource,   0,0),
 #endif
     JS_FN(js_toString_str,   fun_toString,   0,0),
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -141,17 +141,19 @@ class JSFunction : public js::NativeObje
         if (isNative())
             return false;
 
         // Note: this should be kept in sync with
         // FunctionBox::needsCallObjectRegardlessOfBindings().
         MOZ_ASSERT_IF(nonLazyScript()->funHasExtensibleScope() ||
                       nonLazyScript()->needsHomeObject()       ||
                       nonLazyScript()->isDerivedClassConstructor() ||
-                      isGenerator(),
+                      isStarGenerator() ||
+                      isLegacyGenerator() ||
+                      isAsync(),
                       nonLazyScript()->bodyScope()->hasEnvironment());
 
         return nonLazyScript()->bodyScope()->hasEnvironment();
     }
 
     bool needsExtraBodyVarEnvironment() const;
     bool needsNamedLambdaEnvironment() const;
 
@@ -483,31 +485,29 @@ class JSFunction : public js::NativeObje
         if (hasScript())
             return nonLazyScript()->generatorKind();
         if (js::LazyScript* lazy = lazyScriptOrNull())
             return lazy->generatorKind();
         MOZ_ASSERT(isSelfHostedBuiltin());
         return js::NotGenerator;
     }
 
-    bool isGenerator() const { return generatorKind() != js::NotGenerator; }
-
     bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; }
 
     bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
 
     js::FunctionAsyncKind asyncKind() const {
         return isInterpretedLazy() ? lazyScript()->asyncKind() : nonLazyScript()->asyncKind();
     }
 
     bool isAsync() const {
         if (isInterpretedLazy())
-            return lazyScript()->asyncKind() == js::AsyncFunction;
+            return lazyScript()->isAsync();
         if (hasScript())
-            return nonLazyScript()->asyncKind() == js::AsyncFunction;
+            return nonLazyScript()->isAsync();
         return false;
     }
 
     void setScript(JSScript* script_) {
         mutableScript() = script_;
     }
 
     void initScript(JSScript* script_) {
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -3952,17 +3952,19 @@ JSScript::argumentsOptimizationFailed(JS
      * everything has been fixed up, but there was an outstanding magic value
      * on the stack that has just now flowed into an apply. In this case, there
      * is nothing to do; GuardFunApplySpeculation will patch in the real
      * argsobj.
      */
     if (script->needsArgsObj())
         return true;
 
-    MOZ_ASSERT(!script->isGenerator());
+    MOZ_ASSERT(!script->isStarGenerator());
+    MOZ_ASSERT(!script->isLegacyGenerator());
+    MOZ_ASSERT(!script->isAsync());
 
     script->needsArgsObj_ = true;
 
     /*
      * Since we can't invalidate baseline scripts, set a flag that's checked from
      * JIT code to indicate the arguments optimization failed and JSOP_ARGUMENTS
      * should create an arguments object next time.
      */
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1330,29 +1330,31 @@ class JSScript : public js::gc::TenuredC
     void setArgumentsHasVarBinding();
     bool argumentsAliasesFormals() const {
         return argumentsHasVarBinding() && hasMappedArgsObj();
     }
 
     js::GeneratorKind generatorKind() const {
         return js::GeneratorKindFromBits(generatorKindBits_);
     }
-    bool isGenerator() const { return generatorKind() != js::NotGenerator; }
     bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; }
     bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
     void setGeneratorKind(js::GeneratorKind kind) {
         // A script only gets its generator kind set as part of initialization,
         // so it can only transition from not being a generator.
-        MOZ_ASSERT(!isGenerator());
+        MOZ_ASSERT(!isStarGenerator() && !isLegacyGenerator());
         generatorKindBits_ = GeneratorKindAsBits(kind);
     }
 
     js::FunctionAsyncKind asyncKind() const {
         return isAsync_ ? js::AsyncFunction : js::SyncFunction;
     }
+    bool isAsync() const {
+        return isAsync_;
+    }
 
     void setAsyncKind(js::FunctionAsyncKind kind) {
         isAsync_ = kind == js::AsyncFunction;
     }
 
     bool hasRest() const {
         return hasRest_;
     }
@@ -1496,17 +1498,18 @@ class JSScript : public js::gc::TenuredC
         return baselineOrIonRaw;
     }
     static size_t offsetOfBaselineOrIonSkipArgCheck() {
         return offsetof(JSScript, baselineOrIonSkipArgCheck);
     }
 
     bool isRelazifiable() const {
         return (selfHosted() || lazyScript) && !hasInnerFunctions_ && !types_ &&
-               !isGenerator() && !hasBaselineScript() && !hasAnyIonScript() &&
+               !isStarGenerator() && !isLegacyGenerator() && !isAsync() &&
+               !hasBaselineScript() && !hasAnyIonScript() &&
                !doNotRelazify_;
     }
     void setLazyScript(js::LazyScript* lazy) {
         lazyScript = lazy;
     }
     js::LazyScript* maybeLazyScript() {
         return lazyScript;
     }
@@ -1698,17 +1701,17 @@ class JSScript : public js::gc::TenuredC
     }
     void setHasArray(ArrayKind kind) { hasArrayBits |= (1 << kind); }
     void cloneHasArray(JSScript* script) { hasArrayBits = script->hasArrayBits; }
 
     bool hasConsts() const       { return hasArray(CONSTS); }
     bool hasObjects() const      { return hasArray(OBJECTS); }
     bool hasTrynotes() const     { return hasArray(TRYNOTES); }
     bool hasScopeNotes() const   { return hasArray(SCOPENOTES); }
-    bool hasYieldOffsets() const { return isGenerator(); }
+    bool hasYieldOffsets() const { return isStarGenerator() || isLegacyGenerator() || isAsync(); }
 
 #define OFF(fooOff, hasFoo, t)   (fooOff() + (hasFoo() ? sizeof(t) : 0))
 
     size_t scopesOffset() const       { return 0; }
     size_t constsOffset() const       { return scopesOffset() + sizeof(js::ScopeArray); }
     size_t objectsOffset() const      { return OFF(constsOffset,     hasConsts,     js::ConstArray); }
     size_t trynotesOffset() const     { return OFF(objectsOffset,    hasObjects,    js::ObjectArray); }
     size_t scopeNotesOffset() const   { return OFF(trynotesOffset,   hasTrynotes,   js::TryNoteArray); }
@@ -2109,34 +2112,35 @@ class LazyScript : public gc::TenuredCel
         return p_.numInnerFunctions;
     }
     GCPtrFunction* innerFunctions() {
         return (GCPtrFunction*)&closedOverBindings()[numClosedOverBindings()];
     }
 
     GeneratorKind generatorKind() const { return GeneratorKindFromBits(p_.generatorKindBits); }
 
-    bool isGenerator() const { return generatorKind() != NotGenerator; }
-
     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
 
     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
 
     void setGeneratorKind(GeneratorKind kind) {
         // A script only gets its generator kind set as part of initialization,
         // so it can only transition from NotGenerator.
-        MOZ_ASSERT(!isGenerator());
+        MOZ_ASSERT(!isStarGenerator() && !isLegacyGenerator());
         // Legacy generators cannot currently be lazy.
         MOZ_ASSERT(kind != LegacyGenerator);
         p_.generatorKindBits = GeneratorKindAsBits(kind);
     }
 
     FunctionAsyncKind asyncKind() const {
         return p_.isAsync ? AsyncFunction : SyncFunction;
     }
+    bool isAsync() const {
+        return p_.isAsync;
+    }
 
     void setAsyncKind(FunctionAsyncKind kind) {
         p_.isAsync = kind == AsyncFunction;
     }
 
     bool hasRest() const {
         return p_.hasRest;
     }
--- a/js/src/tests/js1_8_5/reflect-parse/PatternBuilders.js
+++ b/js/src/tests/js1_8_5/reflect-parse/PatternBuilders.js
@@ -48,19 +48,18 @@ function genFunDecl(style, id, params, b
                      style: style });
 }
 function asyncFunDecl(id, params, body) {
     return Pattern({ type: "FunctionDeclaration",
                      id: id,
                      params: params,
                      defaults: [],
                      body: body,
-                     generator: true,
-                     async: true,
-                     style: "es6" });
+                     generator: false,
+                     async: true });
 }
 function varDecl(decls) {
     return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "var" });
 }
 function letDecl(decls) {
     return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "let" });
 }
 function constDecl(decls) {
@@ -176,33 +175,31 @@ function genFunExpr(style, id, args, bod
                      generator: true,
                      style: style });
 }
 function asyncFunExpr(id, args, body) {
     return Pattern({ type: "FunctionExpression",
                      id: id,
                      params: args,
                      body: body,
-                     generator: true,
-                     async: true,
-                     style: "es6" });
+                     generator: false,
+                     async: true });
 }
 function arrowExpr(args, body) {
     return Pattern({ type: "ArrowFunctionExpression",
                      params: args,
                      body: body });
 }
 function asyncArrowExpr(isExpression, args, body) {
     return Pattern({ type: "ArrowFunctionExpression",
                      params: args,
                      body: body,
-                     generator: true,
+                     generator: false,
                      async: true,
-                     expression: isExpression,
-                     style: "es6" });
+                     expression: isExpression });
 }
 
 function metaProperty(meta, property) {
     return Pattern({ type: "MetaProperty",
                      meta: meta,
                      property: property });
 }
 function newTarget() {
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -7786,17 +7786,19 @@ DebuggerFrame::getEnvironment(JSContext*
 
     return dbg->wrapEnvironment(cx, env, result);
 }
 
 /* static */ bool
 DebuggerFrame::getIsGenerator(HandleDebuggerFrame frame)
 {
     AbstractFramePtr referent = DebuggerFrame::getReferent(frame);
-    return referent.hasScript() && referent.script()->isGenerator();
+    return referent.hasScript() &&
+           (referent.script()->isStarGenerator() ||
+            referent.script()->isLegacyGenerator());
 }
 
 /* static */ bool
 DebuggerFrame::getOffset(JSContext* cx, HandleDebuggerFrame frame, size_t& result)
 {
     MOZ_ASSERT(frame->isLive());
 
     Maybe<FrameIter> maybeIter;
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -2491,17 +2491,19 @@ DebugEnvironments::hasDebugEnvironment(J
 /* static */ bool
 DebugEnvironments::addDebugEnvironment(JSContext* cx, const EnvironmentIter& ei,
                                        Handle<DebugEnvironmentProxy*> debugEnv)
 {
     MOZ_ASSERT(!ei.hasSyntacticEnvironment());
     MOZ_ASSERT(cx->compartment() == debugEnv->compartment());
     // Generators should always have environments.
     MOZ_ASSERT_IF(ei.scope().is<FunctionScope>(),
-                  !ei.scope().as<FunctionScope>().canonicalFunction()->isGenerator());
+                  !ei.scope().as<FunctionScope>().canonicalFunction()->isStarGenerator() &&
+                  !ei.scope().as<FunctionScope>().canonicalFunction()->isLegacyGenerator() &&
+                  !ei.scope().as<FunctionScope>().canonicalFunction()->isAsync());
 
     if (!CanUseDebugEnvironmentMaps(cx))
         return true;
 
     DebugEnvironments* envs = ensureCompartmentData(cx);
     if (!envs)
         return false;
 
@@ -2637,18 +2639,21 @@ DebugEnvironments::onPopCall(JSContext* 
 
         /*
          * The frame may be observed before the prologue has created the
          * CallObject. See EnvironmentIter::settle.
          */
         if (!frame.environmentChain()->is<CallObject>())
             return;
 
-        if (frame.callee()->isGenerator())
+        if (frame.callee()->isStarGenerator() || frame.callee()->isLegacyGenerator() ||
+            frame.callee()->isAsync())
+        {
             return;
+        }
 
         CallObject& callobj = frame.environmentChain()->as<CallObject>();
         envs->liveEnvs.remove(&callobj);
         if (JSObject* obj = envs->proxiedEnvs.lookup(&callobj))
             debugEnv = &obj->as<DebugEnvironmentProxy>();
     } else {
         MissingEnvironmentKey key(frame, funScope);
         if (MissingEnvironmentMap::Ptr p = envs->missingEnvs.lookup(key)) {
@@ -2770,18 +2775,23 @@ DebugEnvironments::updateLiveEnvironment
     for (AllFramesIter i(cx); !i.done(); ++i) {
         if (!i.hasUsableAbstractFramePtr())
             continue;
 
         AbstractFramePtr frame = i.abstractFramePtr();
         if (frame.environmentChain()->compartment() != cx->compartment())
             continue;
 
-        if (frame.isFunctionFrame() && frame.callee()->isGenerator())
-            continue;
+        if (frame.isFunctionFrame()) {
+            if (frame.callee()->isStarGenerator() || frame.callee()->isLegacyGenerator() ||
+                frame.callee()->isAsync())
+            {
+                continue;
+            }
+        }
 
         if (!frame.isDebuggee())
             continue;
 
         RootedObject env(cx);
         RootedScope scope(cx);
         if (!GetFrameEnvironmentAndScope(cx, frame, i.pc(), &env, &scope))
             return false;
@@ -2932,17 +2942,18 @@ GetDebugEnvironmentForMissing(JSContext*
      * Note: to preserve envChain depth invariants, these lazily-reified
      * envs must not be put on the frame's environment chain; instead, they are
      * maintained via DebugEnvironments hooks.
      */
     Rooted<DebugEnvironmentProxy*> debugEnv(cx);
     if (ei.scope().is<FunctionScope>()) {
         RootedFunction callee(cx, ei.scope().as<FunctionScope>().canonicalFunction());
         // Generators should always reify their scopes.
-        MOZ_ASSERT(!callee->isGenerator());
+        MOZ_ASSERT(!callee->isStarGenerator() && !callee->isLegacyGenerator() &&
+                   !callee->isAsync());
 
         JS::ExposeObjectToActiveJS(callee);
         Rooted<CallObject*> callobj(cx, CallObject::createHollowForDebug(cx, callee));
         if (!callobj)
             return nullptr;
 
         debugEnv = DebugEnvironmentProxy::create(cx, *callobj, enclosingDebug);
     } else if (ei.scope().is<LexicalScope>()) {
--- a/js/src/vm/GeneratorObject.cpp
+++ b/js/src/vm/GeneratorObject.cpp
@@ -14,17 +14,18 @@
 #include "vm/NativeObject-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
 
 JSObject*
 GeneratorObject::create(JSContext* cx, AbstractFramePtr frame)
 {
-    MOZ_ASSERT(frame.script()->isGenerator());
+    MOZ_ASSERT(frame.script()->isStarGenerator() || frame.script()->isLegacyGenerator() ||
+               frame.script()->isAsync());
     MOZ_ASSERT(frame.script()->nfixed() == 0);
 
     Rooted<GlobalObject*> global(cx, cx->global());
     RootedNativeObject obj(cx);
     if (frame.script()->isStarGenerator()) {
         RootedValue pval(cx);
         RootedObject fun(cx, frame.callee());
         // FIXME: This would be faster if we could avoid doing a lookup to get
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -184,17 +184,17 @@ ObjectGroup::useSingletonForNewObject(JS
      *
      * Sub1.prototype = new Super();
      * Sub2.prototype = new Super();
      *
      * Using distinct groups for the particular prototypes of Sub1 and
      * Sub2 lets us continue to distinguish the two subclasses and any extra
      * properties added to those prototype objects.
      */
-    if (script->isGenerator())
+    if (script->isStarGenerator() || script->isLegacyGenerator() || script->isAsync())
         return false;
     if (JSOp(*pc) != JSOP_NEW)
         return false;
     pc += JSOP_NEW_LENGTH;
     if (JSOp(*pc) == JSOP_SETPROP) {
         if (script->getName(pc) == cx->names().prototype)
             return true;
     }
--- a/js/src/vm/Probes-inl.h
+++ b/js/src/vm/Probes-inl.h
@@ -38,17 +38,20 @@ probes::EnterScript(JSContext* cx, JSScr
     if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
         DTraceEnterJSFun(cx, maybeFun, script);
 #endif
 
     JSRuntime* rt = cx->runtime();
     if (rt->geckoProfiler().enabled()) {
         if (!rt->geckoProfiler().enter(cx, script, maybeFun))
             return false;
-        MOZ_ASSERT_IF(!fp->script()->isGenerator(), !fp->hasPushedGeckoProfilerFrame());
+        MOZ_ASSERT_IF(!fp->script()->isStarGenerator() &&
+                      !fp->script()->isLegacyGenerator() &&
+                      !fp->script()->isAsync(),
+                      !fp->hasPushedGeckoProfilerFrame());
         fp->setPushedGeckoProfilerFrame();
     }
 
     return true;
 }
 
 inline void
 probes::ExitScript(JSContext* cx, JSScript* script, JSFunction* maybeFun, bool popProfilerFrame)
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -3202,17 +3202,18 @@ bool
 JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name,
                                          HandleFunction targetFun)
 {
     RootedFunction sourceFun(cx, getUnclonedSelfHostedFunction(cx, name));
     if (!sourceFun)
         return false;
     // JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there
     // aren't any.
-    MOZ_ASSERT(!sourceFun->isGenerator());
+    MOZ_ASSERT(!sourceFun->isStarGenerator() && !sourceFun->isLegacyGenerator() &&
+               !sourceFun->isAsync());
     MOZ_ASSERT(targetFun->isExtended());
     MOZ_ASSERT(targetFun->isInterpretedLazy());
     MOZ_ASSERT(targetFun->isSelfHostedBuiltin());
 
     RootedScript sourceScript(cx, JSFunction::getOrCreateScript(cx, sourceFun));
     if (!sourceScript)
         return false;
 
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -332,17 +332,17 @@ InterpreterStack::pushInlineFrame(JSCont
     return true;
 }
 
 MOZ_ALWAYS_INLINE bool
 InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
                                            HandleFunction callee, HandleValue newTarget,
                                            HandleObject envChain)
 {
-    MOZ_ASSERT(callee->isGenerator());
+    MOZ_ASSERT(callee->isStarGenerator() || callee->isLegacyGenerator() || callee->isAsync());
     RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee));
     InterpreterFrame* prev = regs.fp();
     jsbytecode* prevpc = regs.pc;
     Value* prevsp = regs.sp;
     MOZ_ASSERT(prev);
 
     script->ensureNonLazyCanonicalFunction();
 
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -271,17 +271,19 @@ InterpreterFrame::epilogue(JSContext* cx
     // Check that the scope matches the environment at the point of leaving
     // the frame.
     AssertScopeMatchesEnvironment(this, pc);
 
     EnvironmentIter ei(cx, this, pc);
     UnwindAllEnvironmentsInFrame(cx, ei);
 
     if (isFunctionFrame()) {
-        if (!callee().isGenerator() &&
+        if (!callee().isStarGenerator() &&
+            !callee().isLegacyGenerator() &&
+            !callee().isAsync() &&
             isConstructing() &&
             thisArgument().isObject() &&
             returnValue().isPrimitive())
         {
             setReturnValue(thisArgument());
         }
 
         return;
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -700,17 +700,18 @@ class InterpreterFrame
     }
 
     void clearReturnValue() {
         rval_.setUndefined();
         markReturnValue();
     }
 
     void resumeGeneratorFrame(JSObject* envChain) {
-        MOZ_ASSERT(script()->isGenerator());
+        MOZ_ASSERT(script()->isStarGenerator() || script()->isLegacyGenerator() ||
+                   script()->isAsync());
         MOZ_ASSERT(isFunctionFrame());
         flags_ |= HAS_INITIAL_ENV;
         envChain_ = envChain;
     }
 
     /*
      * Other flags
      */
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -8586,19 +8586,22 @@ EstablishPreconditions(JSContext* cx, As
       case AsmJSOption::Disabled:
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by 'asmjs' runtime option");
       case AsmJSOption::DisabledByDebugger:
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by debugger");
       case AsmJSOption::Enabled:
         break;
     }
 
-    if (parser.pc->isGenerator())
+    if (parser.pc->isStarGenerator() || parser.pc->isLegacyGenerator())
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by generator context");
 
+    if (parser.pc->isAsync())
+        return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by async context");
+
     if (parser.pc->isArrowFunction())
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by arrow function context");
 
     // Class constructors are also methods
     if (parser.pc->isMethod())
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by class constructor or method context");
 
     return true;