diff options
Diffstat (limited to 'js/src/vm/JSScript-inl.h')
-rw-r--r-- | js/src/vm/JSScript-inl.h | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/js/src/vm/JSScript-inl.h b/js/src/vm/JSScript-inl.h new file mode 100644 index 0000000000..e423bdbe4f --- /dev/null +++ b/js/src/vm/JSScript-inl.h @@ -0,0 +1,255 @@ +/* -*- 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_JSScript_inl_h +#define vm_JSScript_inl_h + +#include "vm/JSScript.h" + +#include <utility> + +#include "jit/IonScript.h" +#include "jit/JitScript.h" +#include "vm/RegExpObject.h" +#include "wasm/AsmJS.h" + +namespace js { + +ScriptCounts::ScriptCounts() : ionCounts_(nullptr) {} + +ScriptCounts::ScriptCounts(PCCountsVector&& jumpTargets) + : pcCounts_(std::move(jumpTargets)), ionCounts_(nullptr) {} + +ScriptCounts::ScriptCounts(ScriptCounts&& src) + : pcCounts_(std::move(src.pcCounts_)), + throwCounts_(std::move(src.throwCounts_)), + ionCounts_(std::move(src.ionCounts_)) { + src.ionCounts_ = nullptr; +} + +ScriptCounts& ScriptCounts::operator=(ScriptCounts&& src) { + pcCounts_ = std::move(src.pcCounts_); + throwCounts_ = std::move(src.throwCounts_); + ionCounts_ = std::move(src.ionCounts_); + src.ionCounts_ = nullptr; + return *this; +} + +ScriptCounts::~ScriptCounts() { js_delete(ionCounts_); } + +ScriptAndCounts::ScriptAndCounts(JSScript* script) : script(script) { + script->releaseScriptCounts(&scriptCounts); +} + +ScriptAndCounts::ScriptAndCounts(ScriptAndCounts&& sac) + : script(std::move(sac.script)), + scriptCounts(std::move(sac.scriptCounts)) {} + +void SetFrameArgumentsObject(JSContext* cx, AbstractFramePtr frame, + HandleScript script, JSObject* argsobj); + +inline void ScriptWarmUpData::initEnclosingScript(BaseScript* enclosingScript) { + MOZ_ASSERT(data_ == ResetState()); + setTaggedPtr<EnclosingScriptTag>(enclosingScript); + static_assert(std::is_base_of_v<gc::TenuredCell, BaseScript>, + "BaseScript must be TenuredCell to avoid post-barriers"); +} +inline void ScriptWarmUpData::clearEnclosingScript() { + gc::PreWriteBarrier(toEnclosingScript()); + data_ = ResetState(); +} + +inline void ScriptWarmUpData::initEnclosingScope(Scope* enclosingScope) { + MOZ_ASSERT(data_ == ResetState()); + setTaggedPtr<EnclosingScopeTag>(enclosingScope); + static_assert(std::is_base_of_v<gc::TenuredCell, Scope>, + "Scope must be TenuredCell to avoid post-barriers"); +} +inline void ScriptWarmUpData::clearEnclosingScope() { + gc::PreWriteBarrier(toEnclosingScope()); + data_ = ResetState(); +} + +inline JSPrincipals* BaseScript::principals() const { + return realm()->principals(); +} + +inline JSScript* BaseScript::asJSScript() { + MOZ_ASSERT(hasBytecode()); + return static_cast<JSScript*>(this); +} + +} // namespace js + +inline JSFunction* JSScript::getFunction(js::GCThingIndex index) const { + JSObject* obj = getObject(index); + MOZ_RELEASE_ASSERT(obj->is<JSFunction>(), "Script object is not JSFunction"); + JSFunction* fun = &obj->as<JSFunction>(); + MOZ_ASSERT_IF(fun->isNativeFun(), IsAsmJSModuleNative(fun->native())); + return fun; +} + +inline JSFunction* JSScript::getFunction(jsbytecode* pc) const { + return getFunction(GET_GCTHING_INDEX(pc)); +} + +inline js::RegExpObject* JSScript::getRegExp(js::GCThingIndex index) const { + JSObject* obj = getObject(index); + MOZ_RELEASE_ASSERT(obj->is<js::RegExpObject>(), + "Script object is not RegExpObject"); + return &obj->as<js::RegExpObject>(); +} + +inline js::RegExpObject* JSScript::getRegExp(jsbytecode* pc) const { + JSObject* obj = getObject(pc); + MOZ_RELEASE_ASSERT(obj->is<js::RegExpObject>(), + "Script object is not RegExpObject"); + return &obj->as<js::RegExpObject>(); +} + +inline js::GlobalObject& JSScript::global() const { + /* + * A JSScript always marks its realm's global so we can assert it's non-null + * here. We don't need a read barrier here for the same reason + * JSObject::nonCCWGlobal doesn't need one. + */ + return *realm()->unsafeUnbarrieredMaybeGlobal(); +} + +inline bool JSScript::hasGlobal(const js::GlobalObject* global) const { + return global == realm()->unsafeUnbarrieredMaybeGlobal(); +} + +inline js::LexicalScope* JSScript::maybeNamedLambdaScope() const { + // Dynamically created Functions via the 'new Function' are considered + // named lambdas but they do not have the named lambda scope of + // textually-created named lambdas. + js::Scope* scope = outermostScope(); + if (scope->kind() == js::ScopeKind::NamedLambda || + scope->kind() == js::ScopeKind::StrictNamedLambda) { + MOZ_ASSERT_IF(!strict(), scope->kind() == js::ScopeKind::NamedLambda); + MOZ_ASSERT_IF(strict(), scope->kind() == js::ScopeKind::StrictNamedLambda); + return &scope->as<js::LexicalScope>(); + } + return nullptr; +} + +inline js::Shape* JSScript::initialEnvironmentShape() const { + js::Scope* scope = bodyScope(); + if (scope->is<js::FunctionScope>()) { + if (js::Shape* envShape = scope->environmentShape()) { + return envShape; + } + if (js::Scope* namedLambdaScope = maybeNamedLambdaScope()) { + return namedLambdaScope->environmentShape(); + } + } else if (scope->is<js::EvalScope>()) { + return scope->environmentShape(); + } + return nullptr; +} + +inline bool JSScript::isDebuggee() const { + return realm()->debuggerObservesAllExecution() || hasDebugScript(); +} + +inline bool js::BaseScript::hasBaselineScript() const { + return hasJitScript() && jitScript()->hasBaselineScript(); +} + +inline bool js::BaseScript::hasIonScript() const { + return hasJitScript() && jitScript()->hasIonScript(); +} + +inline bool JSScript::isIonCompilingOffThread() const { + return hasJitScript() && jitScript()->isIonCompilingOffThread(); +} + +inline bool JSScript::canBaselineCompile() const { + bool disabled = baselineDisabled(); +#ifdef DEBUG + if (hasJitScript()) { + bool jitScriptDisabled = + jitScript()->baselineScript_ == js::jit::BaselineDisabledScriptPtr; + MOZ_ASSERT(disabled == jitScriptDisabled); + } +#endif + return !disabled; +} + +inline bool JSScript::canIonCompile() const { + bool disabled = ionDisabled(); +#ifdef DEBUG + if (hasJitScript()) { + bool jitScriptDisabled = + jitScript()->ionScript_ == js::jit::IonDisabledScriptPtr; + MOZ_ASSERT(disabled == jitScriptDisabled); + } +#endif + return !disabled; +} + +inline void JSScript::disableBaselineCompile() { + MOZ_ASSERT(!hasBaselineScript()); + setFlag(MutableFlags::BaselineDisabled); + if (hasJitScript()) { + jitScript()->setBaselineScriptImpl(this, + js::jit::BaselineDisabledScriptPtr); + } +} + +inline void JSScript::disableIon() { + setFlag(MutableFlags::IonDisabled); + if (hasJitScript()) { + jitScript()->setIonScriptImpl(this, js::jit::IonDisabledScriptPtr); + } +} + +inline js::jit::BaselineScript* JSScript::baselineScript() const { + return jitScript()->baselineScript(); +} + +inline js::jit::IonScript* JSScript::ionScript() const { + return jitScript()->ionScript(); +} + +inline uint32_t JSScript::getWarmUpCount() const { + if (warmUpData_.isWarmUpCount()) { + return warmUpData_.toWarmUpCount(); + } + return warmUpData_.toJitScript()->warmUpCount(); +} + +inline void JSScript::updateLastICStubCounter() { + if (!hasJitScript()) { + return; + } + jitScript()->updateLastICStubCounter(); +} + +inline uint32_t JSScript::warmUpCountAtLastICStub() const { + MOZ_ASSERT(hasJitScript()); + return jitScript()->warmUpCountAtLastICStub(); +} + +inline void JSScript::incWarmUpCounter() { + if (warmUpData_.isWarmUpCount()) { + warmUpData_.incWarmUpCount(); + } else { + warmUpData_.toJitScript()->incWarmUpCount(); + } +} + +inline void JSScript::resetWarmUpCounterForGC() { + incWarmUpResetCounter(); + if (warmUpData_.isWarmUpCount()) { + warmUpData_.resetWarmUpCount(0); + } else { + warmUpData_.toJitScript()->resetWarmUpCount(0); + } +} + +#endif /* vm_JSScript_inl_h */ |