From 07c18a52b17725d5e9fa7cc35a7d68943c7f73be Mon Sep 17 00:00:00 2001 From: Fedor Date: Thu, 5 Sep 2019 20:05:17 +0300 Subject: [PATCH] 1320403 - Move JSFunction::EXPR_BODY to JSScript, LazyScript, and FunctionBox. --- js/src/builtin/ReflectParse.cpp | 7 +------ js/src/frontend/Parser.cpp | 18 +++++++++++++----- js/src/frontend/SharedContext.h | 8 ++++++++ js/src/jsfun.cpp | 2 -- js/src/jsfun.h | 10 +--------- js/src/jsscript.cpp | 9 +++++++++ js/src/jsscript.h | 22 +++++++++++++++++++++- js/src/shell/js.cpp | 2 +- js/src/wasm/AsmJS.cpp | 3 +-- 9 files changed, 55 insertions(+), 26 deletions(-) diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index beff58e13..2a0a08a5d 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -3407,12 +3407,7 @@ ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst) : GeneratorStyle::None; bool isAsync = pn->pn_funbox->isAsync(); - bool isExpression = -#if JS_HAS_EXPR_CLOSURES - func->isExprBody(); -#else - false; -#endif + bool isExpression = pn->pn_funbox->isExprBody(); RootedValue id(cx); RootedAtom funcAtom(cx, func->explicitName()); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index c86d9ca7b..2a80afbf1 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -474,6 +474,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* trac usesThis(false), usesReturn(false), hasRest_(false), + isExprBody_(false), funCxFlags() { // Functions created at parse time may be set singleton after parsing and @@ -2264,6 +2265,8 @@ Parser::finishFunction(bool isStandaloneFunction /* = false lazy->setAsyncKind(funbox->asyncKind()); if (funbox->hasRest()) lazy->setHasRest(); + if (funbox->isExprBody()) + lazy->setIsExprBody(); if (funbox->isLikelyConstructorWrapper()) lazy->setLikelyConstructorWrapper(); if (funbox->isDerivedClassConstructor()) @@ -3030,6 +3033,8 @@ Parser::skipLazyInnerFunction(ParseNode* pn, uint32_t preludeS LazyScript* lazy = fun->lazyScript(); if (lazy->needsHomeObject()) funbox->setNeedsHomeObject(); + if (lazy->isExprBody()) + funbox->setIsExprBody(); PropagateTransitiveParseFlags(lazy, pc->sc()); @@ -3042,10 +3047,15 @@ Parser::skipLazyInnerFunction(ParseNode* pn, uint32_t preludeS if (!tokenStream.advance(fun->lazyScript()->end() - userbufBase)) return false; - if (kind == Statement && fun->isExprBody()) { +#if JS_HAS_EXPR_CLOSURES + // Only expression closure can be Statement kind. + // If we remove expression closure, we can remove isExprBody flag from + // LazyScript and JSScript. + if (kind == Statement && funbox->isExprBody()) { if (!matchOrInsertSemicolonAfterExpression()) return false; } +#endif return true; } @@ -3490,9 +3500,7 @@ Parser::functionFormalParametersAndBody(InHandling inHandling, tokenStream.ungetToken(); bodyType = ExpressionBody; -#if JS_HAS_EXPR_CLOSURES - fun->setIsExprBody(); -#endif + funbox->setIsExprBody(); } // Arrow function parameters inherit yieldHandling from the enclosing @@ -6130,7 +6138,7 @@ Parser::yieldExpression(InHandling inHandling) if (pc->funHasReturnExpr #if JS_HAS_EXPR_CLOSURES - || pc->functionBox()->function()->isExprBody() + || pc->functionBox()->isExprBody() #endif ) { diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index b20417d5d..f5a74e18c 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -473,6 +473,9 @@ class FunctionBox : public ObjectBox, public SharedContext bool usesThis:1; /* contains 'this' */ bool usesReturn:1; /* contains a 'return' statement */ bool hasRest_:1; /* has rest parameter */ + bool isExprBody_:1; /* arrow function with expression + * body or expression closure: + * function(x) x*x */ FunctionContextFlags funCxFlags; @@ -546,6 +549,11 @@ class FunctionBox : public ObjectBox, public SharedContext hasRest_ = true; } + bool isExprBody() const { return isExprBody_; } + 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 diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 3cba3434d..304700da2 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -980,8 +980,6 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint) return nullptr; } } else { - MOZ_ASSERT(!fun->isExprBody()); - bool derived = fun->infallibleIsDefaultClassConstructor(cx); if (derived && fun->isDerivedClassConstructor()) { if (!AppendPrelude() || diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 62b285806..b91c69d33 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -58,8 +58,6 @@ class JSFunction : public js::NativeObject CONSTRUCTOR = 0x0002, /* function that can be called as a constructor */ EXTENDED = 0x0004, /* structure is FunctionExtended */ BOUND_FUN = 0x0008, /* function was created with Function.prototype.bind. */ - EXPR_BODY = 0x0010, /* arrow function with expression body or - * expression closure: function(x) x*x */ HAS_GUESSED_ATOM = 0x0020, /* function had no explicit name, but a name was guessed for it anyway */ LAMBDA = 0x0040, /* function comes from a FunctionExpression, ArrowFunction, or @@ -102,7 +100,7 @@ class JSFunction : public js::NativeObject INTERPRETED_GENERATOR = INTERPRETED, NO_XDR_FLAGS = RESOLVED_LENGTH | RESOLVED_NAME, - STABLE_ACROSS_CLONES = CONSTRUCTOR | EXPR_BODY | HAS_GUESSED_ATOM | LAMBDA | + STABLE_ACROSS_CLONES = CONSTRUCTOR | HAS_GUESSED_ATOM | LAMBDA | SELF_HOSTED | HAS_COMPILE_TIME_NAME | FUNCTION_KIND_MASK }; @@ -187,7 +185,6 @@ class JSFunction : public js::NativeObject bool isAsmJSNative() const { return kind() == AsmJS; } /* Possible attributes of an interpreted function: */ - bool isExprBody() const { return flags() & EXPR_BODY; } bool hasCompileTimeName() const { return flags() & HAS_COMPILE_TIME_NAME; } bool hasGuessedAtom() const { return flags() & HAS_GUESSED_ATOM; } bool isLambda() const { return flags() & LAMBDA; } @@ -290,11 +287,6 @@ class JSFunction : public js::NativeObject flags_ |= SELF_HOSTED; } - // Can be called multiple times by the parser. - void setIsExprBody() { - flags_ |= EXPR_BODY; - } - void setArrow() { setKind(Arrow); } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 33ae56d6f..899820a0d 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -319,6 +319,7 @@ js::XDRScript(XDRState* xdr, HandleScope scriptEnclosingScope, HandleScrip IsStarGenerator, IsAsync, HasRest, + IsExprBody, OwnSource, ExplicitUseStrict, SelfHosted, @@ -436,6 +437,8 @@ js::XDRScript(XDRState* xdr, HandleScope scriptEnclosingScope, HandleScrip scriptBits |= (1 << IsAsync); if (script->hasRest()) scriptBits |= (1 << HasRest); + if (script->isExprBody()) + scriptBits |= (1 << IsExprBody); if (script->hasSingletons()) scriptBits |= (1 << HasSingleton); if (script->treatAsRunOnce()) @@ -589,6 +592,8 @@ js::XDRScript(XDRState* xdr, HandleScope scriptEnclosingScope, HandleScrip script->setAsyncKind(AsyncFunction); if (scriptBits & (1 << HasRest)) script->setHasRest(); + if (scriptBits & (1 << IsExprBody)) + script->setIsExprBody(); } JS_STATIC_ASSERT(sizeof(jsbytecode) == 1); @@ -2660,6 +2665,8 @@ JSScript::initFromFunctionBox(ExclusiveContext* cx, HandleScript script, script->setAsyncKind(funbox->asyncKind()); if (funbox->hasRest()) script->setHasRest(); + if (funbox->isExprBody()) + script->setIsExprBody(); PositionalFormalParameterIter fi(script); while (fi && !fi.closedOver()) @@ -3320,6 +3327,7 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst, dst->isDefaultClassConstructor_ = src->isDefaultClassConstructor(); dst->isAsync_ = src->asyncKind() == AsyncFunction; dst->hasRest_ = src->hasRest_; + dst->isExprBody_ = src->isExprBody_; if (nconsts != 0) { GCPtrValue* vector = Rebase(dst, src, src->consts()->vector); @@ -4059,6 +4067,7 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun, p.hasThisBinding = false; p.isAsync = false; p.hasRest = false; + p.isExprBody = false; p.numClosedOverBindings = closedOverBindings.length(); p.numInnerFunctions = innerFunctions.length(); p.generatorKindBits = GeneratorKindAsBits(NotGenerator); diff --git a/js/src/jsscript.h b/js/src/jsscript.h index bb8635581..c3298a884 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -1021,6 +1021,7 @@ class JSScript : public js::gc::TenuredCell bool isAsync_:1; bool hasRest_:1; + bool isExprBody_:1; // Add padding so JSScript is gc::Cell aligned. Make padding protected // instead of private to suppress -Wunused-private-field compiler warnings. @@ -1329,6 +1330,13 @@ class JSScript : public js::gc::TenuredCell hasRest_ = true; } + bool isExprBody() const { + return isExprBody_; + } + void setIsExprBody() { + isExprBody_ = true; + } + void setNeedsHomeObject() { needsHomeObject_ = true; } @@ -1936,7 +1944,7 @@ class LazyScript : public gc::TenuredCell #endif private: - static const uint32_t NumClosedOverBindingsBits = 21; + static const uint32_t NumClosedOverBindingsBits = 20; static const uint32_t NumInnerFunctionsBits = 20; struct PackedView { @@ -1946,7 +1954,12 @@ class LazyScript : public gc::TenuredCell uint32_t shouldDeclareArguments : 1; uint32_t hasThisBinding : 1; uint32_t isAsync : 1; + uint32_t isExprBody : 1; + uint32_t numClosedOverBindings : NumClosedOverBindingsBits; + + // -- 32bit boundary -- + uint32_t numInnerFunctions : NumInnerFunctionsBits; uint32_t generatorKindBits : 2; @@ -2104,6 +2117,13 @@ class LazyScript : public gc::TenuredCell p_.hasRest = true; } + bool isExprBody() const { + return p_.isExprBody; + } + void setIsExprBody() { + p_.isExprBody = true; + } + bool strict() const { return p_.strict; } diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 617b5e902..f6a13623c 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -2689,7 +2689,7 @@ DisassembleScript(JSContext* cx, HandleScript script, HandleFunction fun, if (sp->put(" CONSTRUCTOR") < 0) return false; } - if (fun->isExprBody()) { + if (script->isExprBody()) { if (sp->put(" EXPRESSION_CLOSURE") < 0) return false; } diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index a318d67a9..6483d6ec3 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -3250,10 +3250,9 @@ CheckModuleLevelName(ModuleValidator& m, ParseNode* usepn, PropertyName* name) static bool CheckFunctionHead(ModuleValidator& m, ParseNode* fn) { - JSFunction* fun = FunctionObject(fn); if (fn->pn_funbox->hasRest()) return m.fail(fn, "rest args not allowed"); - if (fun->isExprBody()) + if (fn->pn_funbox->isExprBody()) return m.fail(fn, "expression closures not allowed"); if (fn->pn_funbox->hasDestructuringArgs) return m.fail(fn, "destructuring args not allowed");