Bug 1677426 - Part 3: Include JSFunction.h from Scope.h. r=nbp

Moved BindingKind and BindingLocation out of Scope.h,
added Scope.h -> JSFunction.h dependency,
and removed JSScript.h -> Scope.h dependency.

Differential Revision: https://phabricator.services.mozilla.com/D97662
This commit is contained in:
Tooru Fujisawa 2020-12-08 01:01:01 +00:00
Родитель 487f0ea0e6
Коммит 3882f3a5d2
9 изменённых файлов: 256 добавлений и 188 удалений

Просмотреть файл

@ -7,11 +7,18 @@
#ifndef frontend_NameAnalysisTypes_h
#define frontend_NameAnalysisTypes_h
#include "mozilla/Assertions.h" // MOZ_ASSERT, MOZ_CRASH
#include "mozilla/Casting.h" // mozilla::AssertedCast
#include <stdint.h> // uint8_t, uint16_t, uint32_t
#include <type_traits>
#include "frontend/ParserAtom.h"
#include "vm/BytecodeUtil.h"
#include "vm/Scope.h"
#include "frontend/ParserAtom.h" // ParserAtom
#include "js/AllocPolicy.h" // SystemAllocPolicy
#include "js/Vector.h" // Vector
#include "vm/BindingKind.h" // BindingKind, BindingLocation
#include "vm/BytecodeFormatFlags.h" // JOF_ENVCOORD
#include "vm/BytecodeUtil.h" // ENVCOORD_HOPS_BITS, ENVCOORD_SLOT_BITS, GET_ENVCOORD_HOPS, GET_ENVCOORD_SLOT, ENVCOORD_HOPS_LEN, JOF_OPTYPE, JSOp, LOCALNO_LIMIT
namespace js {

Просмотреть файл

@ -7,18 +7,35 @@
#ifndef jit_CompileInfo_h
#define jit_CompileInfo_h
#include "mozilla/Maybe.h"
#include "mozilla/Assertions.h" // MOZ_ASSERT
#include "mozilla/Maybe.h" // mozilla::Maybe, mozilla::Some
#include <algorithm>
#include <algorithm> // std::max
#include <stdint.h> // uint32_t
#include "jit/CompileWrappers.h"
#include "jit/JitAllocPolicy.h"
#include "jit/JitFrames.h"
#include "jit/Registers.h"
#include "vm/JSAtomState.h"
#include "vm/JSFunction.h"
#include "jit/CompileWrappers.h" // CompileRuntime
#include "jit/JitFrames.h" // MinJITStackSize
#include "js/TypeDecls.h" // jsbytecode
#include "vm/BindingKind.h" // BindingLocation
#include "vm/BytecodeUtil.h" // JSOp
#include "vm/JSAtomState.h" // JSAtomState
#include "vm/JSFunction.h" // JSFunction
#include "vm/JSScript.h" // JSScript, PCToLineNumber
#include "vm/Scope.h" // BindingIter
class JSAtom;
class JSObject;
namespace JS {
class BigInt;
} // namespace JS
namespace js {
class ModuleObject;
class PropertyName;
class RegExpObject;
namespace jit {
class InlineScriptTree;

102
js/src/vm/BindingKind.h Normal file
Просмотреть файл

@ -0,0 +1,102 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef vm_BindingKind_h
#define vm_BindingKind_h
#include "mozilla/Assertions.h" // MOZ_ASSERT, MOZ_ASSERT_IF
#include "mozilla/Casting.h" // mozilla::AssertedCast
#include <stdint.h> // uint16_t, uint32_t
#include "vm/BytecodeUtil.h" // LOCALNO_LIMIT, ENVCOORD_SLOT_LIMIT
namespace js {
enum class BindingKind : uint8_t {
Import,
FormalParameter,
Var,
Let,
Const,
// So you think named lambda callee names are consts? Nope! They don't
// throw when being assigned to in sloppy mode.
NamedLambdaCallee
};
static inline bool BindingKindIsLexical(BindingKind kind) {
return kind == BindingKind::Let || kind == BindingKind::Const;
}
class BindingLocation {
public:
enum class Kind {
Global,
Argument,
Frame,
Environment,
Import,
NamedLambdaCallee
};
private:
Kind kind_;
uint32_t slot_;
BindingLocation(Kind kind, uint32_t slot) : kind_(kind), slot_(slot) {}
public:
static BindingLocation Global() {
return BindingLocation(Kind::Global, UINT32_MAX);
}
static BindingLocation Argument(uint16_t slot) {
return BindingLocation(Kind::Argument, slot);
}
static BindingLocation Frame(uint32_t slot) {
MOZ_ASSERT(slot < LOCALNO_LIMIT);
return BindingLocation(Kind::Frame, slot);
}
static BindingLocation Environment(uint32_t slot) {
MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
return BindingLocation(Kind::Environment, slot);
}
static BindingLocation Import() {
return BindingLocation(Kind::Import, UINT32_MAX);
}
static BindingLocation NamedLambdaCallee() {
return BindingLocation(Kind::NamedLambdaCallee, UINT32_MAX);
}
bool operator==(const BindingLocation& other) const {
return kind_ == other.kind_ && slot_ == other.slot_;
}
bool operator!=(const BindingLocation& other) const {
return !operator==(other);
}
Kind kind() const { return kind_; }
uint32_t slot() const {
MOZ_ASSERT(kind_ == Kind::Frame || kind_ == Kind::Environment);
return slot_;
}
uint16_t argumentSlot() const {
MOZ_ASSERT(kind_ == Kind::Argument);
return mozilla::AssertedCast<uint16_t>(slot_);
}
};
} // namespace js
#endif // vm_BindingKind_h

Просмотреть файл

@ -20,6 +20,7 @@
namespace js {
class WithScope;
class EnvironmentIter;
class PlainObject;

Просмотреть файл

@ -1990,6 +1990,22 @@ bool JSFunction::needsNamedLambdaEnvironment() const {
return scope->hasEnvironment();
}
bool JSFunction::needsCallObject() const {
if (isNative()) {
return false;
}
MOZ_ASSERT(hasBytecode());
// Note: this should be kept in sync with
// FunctionBox::needsCallObjectRegardlessOfBindings().
MOZ_ASSERT_IF(
baseScript()->funHasExtensibleScope() || isGenerator() || isAsync(),
nonLazyScript()->bodyScope()->hasEnvironment());
return nonLazyScript()->bodyScope()->hasEnvironment();
}
JSFunction* js::NewScriptedFunction(
JSContext* cx, unsigned nargs, FunctionFlags flags, HandleAtom atom,
HandleObject proto /* = nullptr */,

Просмотреть файл

@ -134,21 +134,7 @@ class JSFunction : public js::NativeObject {
js::HandleShape shape, js::HandleObjectGroup group);
/* Call objects must be created for each invocation of this function. */
bool needsCallObject() const {
if (isNative()) {
return false;
}
MOZ_ASSERT(hasBytecode());
// Note: this should be kept in sync with
// FunctionBox::needsCallObjectRegardlessOfBindings().
MOZ_ASSERT_IF(
baseScript()->funHasExtensibleScope() || isGenerator() || isAsync(),
nonLazyScript()->bodyScope()->hasEnvironment());
return nonLazyScript()->bodyScope()->hasEnvironment();
}
bool needsCallObject() const;
bool needsExtraBodyVarEnvironment() const;
bool needsNamedLambdaEnvironment() const;

Просмотреть файл

@ -690,6 +690,92 @@ void js::BaseScript::swapData(UniquePtr<PrivateScriptData>& other) {
other.reset(tmp);
}
js::Scope* js::BaseScript::enclosingScope() const {
MOZ_ASSERT(!warmUpData_.isEnclosingScript(),
"Enclosing scope is not computed yet");
if (warmUpData_.isEnclosingScope()) {
return warmUpData_.toEnclosingScope();
}
MOZ_ASSERT(data_, "Script doesn't seem to be compiled");
return gcthings()[js::GCThingIndex::outermostScopeIndex()]
.as<Scope>()
.enclosing();
}
size_t JSScript::numAlwaysLiveFixedSlots() const {
if (bodyScope()->is<js::FunctionScope>()) {
return bodyScope()->as<js::FunctionScope>().nextFrameSlot();
}
if (bodyScope()->is<js::ModuleScope>()) {
return bodyScope()->as<js::ModuleScope>().nextFrameSlot();
}
return 0;
}
unsigned JSScript::numArgs() const {
if (bodyScope()->is<js::FunctionScope>()) {
return bodyScope()->as<js::FunctionScope>().numPositionalFormalParameters();
}
return 0;
}
bool JSScript::functionHasParameterExprs() const {
// Only functions have parameters.
js::Scope* scope = bodyScope();
if (!scope->is<js::FunctionScope>()) {
return false;
}
return scope->as<js::FunctionScope>().hasParameterExprs();
}
js::ModuleObject* JSScript::module() const {
if (bodyScope()->is<js::ModuleScope>()) {
return bodyScope()->as<js::ModuleScope>().module();
}
return nullptr;
}
bool JSScript::isGlobalCode() const {
return bodyScope()->is<js::GlobalScope>();
}
js::VarScope* JSScript::functionExtraBodyVarScope() const {
MOZ_ASSERT(functionHasExtraBodyVarScope());
for (JS::GCCellPtr gcThing : gcthings()) {
if (!gcThing.is<js::Scope>()) {
continue;
}
js::Scope* scope = &gcThing.as<js::Scope>();
if (scope->kind() == js::ScopeKind::FunctionBodyVar) {
return &scope->as<js::VarScope>();
}
}
MOZ_CRASH("Function extra body var scope not found");
}
bool JSScript::needsBodyEnvironment() const {
for (JS::GCCellPtr gcThing : gcthings()) {
if (!gcThing.is<js::Scope>()) {
continue;
}
js::Scope* scope = &gcThing.as<js::Scope>();
if (ScopeKindIsInBody(scope->kind()) && scope->hasEnvironment()) {
return true;
}
}
return false;
}
bool JSScript::isDirectEvalInFunction() const {
if (!isForEval()) {
return false;
}
return bodyScope()->hasOnChain(js::ScopeKind::Function);
}
template <XDRMode mode>
/* static */
XDRResult js::PrivateScriptData::XDR(XDRState<mode>* xdr, HandleScript script,

Просмотреть файл

@ -42,7 +42,7 @@
#include "vm/GeneratorAndAsyncKind.h" // GeneratorKind, FunctionAsyncKind
#include "vm/JSAtom.h"
#include "vm/NativeObject.h"
#include "vm/Scope.h"
#include "vm/ScopeKind.h" // ScopeKind
#include "vm/Shape.h"
#include "vm/SharedImmutableStringsCache.h"
#include "vm/SharedStencil.h" // js::GCThingIndex, js::SourceExtent, js::SharedImmutableScriptData, MemberInitializers
@ -56,6 +56,9 @@ class SourceText;
namespace js {
class VarScope;
class LexicalScope;
namespace coverage {
class LCovSource;
} // namespace coverage
@ -1725,20 +1728,7 @@ class BaseScript : public gc::TenuredCellWithNonGCPointer<uint8_t> {
return warmUpData_.isEnclosingScope();
}
Scope* enclosingScope() const {
MOZ_ASSERT(!warmUpData_.isEnclosingScript(),
"Enclosing scope is not computed yet");
if (warmUpData_.isEnclosingScope()) {
return warmUpData_.toEnclosingScope();
}
MOZ_ASSERT(data_, "Script doesn't seem to be compiled");
return gcthings()[js::GCThingIndex::outermostScopeIndex()]
.as<Scope>()
.enclosing();
}
Scope* enclosingScope() const;
void setEnclosingScope(Scope* enclosingScope);
Scope* releaseEnclosingScope();
@ -2023,40 +2013,18 @@ class JSScript : public js::BaseScript {
// Number of fixed slots reserved for slots that are always live. Only
// nonzero for function or module code.
size_t numAlwaysLiveFixedSlots() const {
if (bodyScope()->is<js::FunctionScope>()) {
return bodyScope()->as<js::FunctionScope>().nextFrameSlot();
}
if (bodyScope()->is<js::ModuleScope>()) {
return bodyScope()->as<js::ModuleScope>().nextFrameSlot();
}
return 0;
}
size_t numAlwaysLiveFixedSlots() const;
// Calculate the number of fixed slots that are live at a particular bytecode.
size_t calculateLiveFixed(jsbytecode* pc);
size_t nslots() const { return immutableScriptData()->nslots; }
unsigned numArgs() const {
if (bodyScope()->is<js::FunctionScope>()) {
return bodyScope()
->as<js::FunctionScope>()
.numPositionalFormalParameters();
}
return 0;
}
unsigned numArgs() const;
inline js::Shape* initialEnvironmentShape() const;
bool functionHasParameterExprs() const {
// Only functions have parameters.
js::Scope* scope = bodyScope();
if (!scope->is<js::FunctionScope>()) {
return false;
}
return scope->as<js::FunctionScope>().hasParameterExprs();
}
bool functionHasParameterExprs() const;
bool functionAllowsParameterRedeclaration() const {
// Parameter redeclaration is only allowed for non-strict functions with
@ -2123,14 +2091,9 @@ class JSScript : public js::BaseScript {
bool isRelazifiable() const { return isRelazifiableImpl(); }
js::ModuleObject* module() const {
if (bodyScope()->is<js::ModuleScope>()) {
return bodyScope()->as<js::ModuleScope>().module();
}
return nullptr;
}
js::ModuleObject* module() const;
bool isGlobalCode() const { return bodyScope()->is<js::GlobalScope>(); }
bool isGlobalCode() const;
// Returns true if the script may read formal arguments on the stack
// directly, via lazy arguments or a rest parameter.
@ -2146,12 +2109,7 @@ class JSScript : public js::BaseScript {
public:
/* Return whether this is a 'direct eval' script in a function scope. */
bool isDirectEvalInFunction() const {
if (!isForEval()) {
return false;
}
return bodyScope()->hasOnChain(js::ScopeKind::Function);
}
bool isDirectEvalInFunction() const;
/*
* Return whether this script is a top-level script.
@ -2204,32 +2162,9 @@ class JSScript : public js::BaseScript {
return res;
}
js::VarScope* functionExtraBodyVarScope() const {
MOZ_ASSERT(functionHasExtraBodyVarScope());
for (JS::GCCellPtr gcThing : gcthings()) {
if (!gcThing.is<js::Scope>()) {
continue;
}
js::Scope* scope = &gcThing.as<js::Scope>();
if (scope->kind() == js::ScopeKind::FunctionBodyVar) {
return &scope->as<js::VarScope>();
}
}
MOZ_CRASH("Function extra body var scope not found");
}
js::VarScope* functionExtraBodyVarScope() const;
bool needsBodyEnvironment() const {
for (JS::GCCellPtr gcThing : gcthings()) {
if (!gcThing.is<js::Scope>()) {
continue;
}
js::Scope* scope = &gcThing.as<js::Scope>();
if (ScopeKindIsInBody(scope->kind()) && scope->hasEnvironment()) {
return true;
}
}
return false;
}
bool needsBodyEnvironment() const;
inline js::LexicalScope* maybeNamedLambdaScope() const;

Просмотреть файл

@ -32,13 +32,14 @@
#include "js/UniquePtr.h" // UniquePtr
#include "util/Poison.h" // AlwaysPoison, JS_SCOPE_DATA_TRAILING_NAMES_PATTERN, MemCheckKind
#include "vm/BytecodeUtil.h" // LOCALNO_LIMIT, ENVCOORD_SLOT_LIMIT
#include "vm/JSFunction.h" // JSFunction
#include "vm/ScopeKind.h" // ScopeKind
#include "vm/Shape.h" // Shape
#include "vm/Xdr.h" // XDRResult, XDRState
class JSAtom;
class JSFreeOp;
class JSFunction; // FIXME: include JSFunction.h
class JSFunction;
class JSScript;
class JSTracer;
struct JSContext;
@ -71,22 +72,6 @@ using BindingIter = AbstractBindingIter<JSAtom>;
class AbstractScopePtr;
enum class BindingKind : uint8_t {
Import,
FormalParameter,
Var,
Let,
Const,
// So you think named lambda callee names are consts? Nope! They don't
// throw when being assigned to in sloppy mode.
NamedLambdaCallee
};
static inline bool BindingKindIsLexical(BindingKind kind) {
return kind == BindingKind::Let || kind == BindingKind::Const;
}
static inline bool ScopeKindIsCatch(ScopeKind kind) {
return kind == ScopeKind::SimpleCatch || kind == ScopeKind::Catch;
}
@ -235,73 +220,6 @@ class AbstractTrailingNamesArray {
BindingNameT& operator[](size_t i) { return get(i); }
};
// typedef AbstractTrailingNamesArray<JSAtom> TrailingNamesArray;
class BindingLocation {
public:
enum class Kind {
Global,
Argument,
Frame,
Environment,
Import,
NamedLambdaCallee
};
private:
Kind kind_;
uint32_t slot_;
BindingLocation(Kind kind, uint32_t slot) : kind_(kind), slot_(slot) {}
public:
static BindingLocation Global() {
return BindingLocation(Kind::Global, UINT32_MAX);
}
static BindingLocation Argument(uint16_t slot) {
return BindingLocation(Kind::Argument, slot);
}
static BindingLocation Frame(uint32_t slot) {
MOZ_ASSERT(slot < LOCALNO_LIMIT);
return BindingLocation(Kind::Frame, slot);
}
static BindingLocation Environment(uint32_t slot) {
MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
return BindingLocation(Kind::Environment, slot);
}
static BindingLocation Import() {
return BindingLocation(Kind::Import, UINT32_MAX);
}
static BindingLocation NamedLambdaCallee() {
return BindingLocation(Kind::NamedLambdaCallee, UINT32_MAX);
}
bool operator==(const BindingLocation& other) const {
return kind_ == other.kind_ && slot_ == other.slot_;
}
bool operator!=(const BindingLocation& other) const {
return !operator==(other);
}
Kind kind() const { return kind_; }
uint32_t slot() const {
MOZ_ASSERT(kind_ == Kind::Frame || kind_ == Kind::Environment);
return slot_;
}
uint16_t argumentSlot() const {
MOZ_ASSERT(kind_ == Kind::Argument);
return mozilla::AssertedCast<uint16_t>(slot_);
}
};
//
// Allow using is<T> and as<T> on Rooted<Scope*> and Handle<Scope*>.
//