Bug 1808927 - Use a single vector for module export entries r=arai

This uses a single vector for all export entries and stores the start positions
for indirect and star export entries separately. The export entries are
returned as spans, and other vectors changed to be returned as spans too to
ease the shell integration.

Differential Revision: https://phabricator.services.mozilla.com/D166187
This commit is contained in:
Jon Coppeard 2023-01-10 09:44:07 +00:00
parent 4037735ebb
commit 9513c27cf4
5 changed files with 91 additions and 50 deletions

View File

@ -10,6 +10,7 @@
#include "mozilla/Assertions.h" // MOZ_ASSERT
#include "mozilla/Attributes.h" // MOZ_STACK_CLASS
#include "mozilla/MemoryReporting.h" // MallocSizeOf
#include "mozilla/Span.h"
#include "mozilla/Vector.h"
#include <stddef.h> // size_t
@ -72,6 +73,9 @@ class GCVector {
T& back() { return vector.back(); }
const T& back() const { return vector.back(); }
operator mozilla::Span<T>() { return vector; }
operator mozilla::Span<const T>() const { return vector; }
bool initCapacity(size_t cap) { return vector.initCapacity(cap); }
[[nodiscard]] bool reserve(size_t req) { return vector.reserve(req); }
void shrinkBy(size_t amount) { return vector.shrinkBy(amount); }

View File

@ -40,6 +40,7 @@ using namespace js;
using mozilla::Maybe;
using mozilla::Nothing;
using mozilla::Some;
using mozilla::Span;
static_assert(ModuleStatus::Unlinked < ModuleStatus::Linking &&
ModuleStatus::Linking < ModuleStatus::Linked &&
@ -641,15 +642,17 @@ class js::CyclicModuleFields {
uint32_t asyncEvaluatingPostOrder = 0;
uint32_t pendingAsyncDependencies = 0;
// Fields describing the layout of exportEntries.
uint32_t indirectExportEntriesStart = 0;
uint32_t starExportEntriesStart = 0;
public:
HeapPtr<Value> evaluationError;
HeapPtr<JSObject*> metaObject;
HeapPtr<ScriptSourceObject*> scriptSourceObject;
RequestedModuleVector requestedModules;
ImportEntryVector importEntries;
ExportEntryVector localExportEntries;
ExportEntryVector indirectExportEntries;
ExportEntryVector starExportEntries;
ExportEntryVector exportEntries;
IndirectBindingMap importBindings;
UniquePtr<FunctionDeclarationVector> functionDeclarations;
HeapPtr<PromiseObject*> topLevelCapability;
@ -661,6 +664,14 @@ class js::CyclicModuleFields {
void trace(JSTracer* trc);
void initExportEntries(MutableHandle<ExportEntryVector> allEntries,
uint32_t localExportCount,
uint32_t indirectExportCount,
uint32_t starExportCount);
Span<const ExportEntry> localExportEntries() const;
Span<const ExportEntry> indirectExportEntries() const;
Span<const ExportEntry> starExportEntries() const;
void setDfsIndex(uint32_t index);
Maybe<uint32_t> maybeDfsIndex() const;
void setDfsAncestorIndex(uint32_t index);
@ -690,9 +701,7 @@ void CyclicModuleFields::trace(JSTracer* trc) {
"CyclicModuleFields::scriptSourceObject");
requestedModules.trace(trc);
importEntries.trace(trc);
localExportEntries.trace(trc);
indirectExportEntries.trace(trc);
starExportEntries.trace(trc);
exportEntries.trace(trc);
importBindings.trace(trc);
TraceNullableEdge(trc, &topLevelCapability,
"CyclicModuleFields::topLevelCapability");
@ -701,6 +710,36 @@ void CyclicModuleFields::trace(JSTracer* trc) {
TraceNullableEdge(trc, &cycleRoot, "CyclicModuleFields::cycleRoot");
}
void CyclicModuleFields::initExportEntries(
MutableHandle<ExportEntryVector> allEntries, uint32_t localExportCount,
uint32_t indirectExportCount, uint32_t starExportCount) {
MOZ_ASSERT(allEntries.length() ==
localExportCount + indirectExportCount + starExportCount);
exportEntries = std::move(allEntries.get());
indirectExportEntriesStart = localExportCount;
starExportEntriesStart = indirectExportEntriesStart + indirectExportCount;
}
Span<const ExportEntry> CyclicModuleFields::localExportEntries() const {
MOZ_ASSERT(indirectExportEntriesStart <= exportEntries.length());
return Span(exportEntries.begin(),
exportEntries.begin() + indirectExportEntriesStart);
}
Span<const ExportEntry> CyclicModuleFields::indirectExportEntries() const {
MOZ_ASSERT(indirectExportEntriesStart <= starExportEntriesStart);
MOZ_ASSERT(starExportEntriesStart <= exportEntries.length());
return Span(exportEntries.begin() + indirectExportEntriesStart,
exportEntries.begin() + starExportEntriesStart);
}
Span<const ExportEntry> CyclicModuleFields::starExportEntries() const {
MOZ_ASSERT(starExportEntriesStart <= exportEntries.length());
return Span(exportEntries.begin() + starExportEntriesStart,
exportEntries.end());
}
void CyclicModuleFields::setDfsIndex(uint32_t index) {
dfsIndex = index;
hasDfsIndex = true;
@ -799,24 +838,24 @@ const CyclicModuleFields* ModuleObject::cyclicModuleFields() const {
return const_cast<ModuleObject*>(this)->cyclicModuleFields();
}
const RequestedModuleVector& ModuleObject::requestedModules() const {
Span<const RequestedModule> ModuleObject::requestedModules() const {
return cyclicModuleFields()->requestedModules;
}
const ImportEntryVector& ModuleObject::importEntries() const {
Span<const ImportEntry> ModuleObject::importEntries() const {
return cyclicModuleFields()->importEntries;
}
const ExportEntryVector& ModuleObject::localExportEntries() const {
return cyclicModuleFields()->localExportEntries;
Span<const ExportEntry> ModuleObject::localExportEntries() const {
return cyclicModuleFields()->localExportEntries();
}
const ExportEntryVector& ModuleObject::indirectExportEntries() const {
return cyclicModuleFields()->indirectExportEntries;
Span<const ExportEntry> ModuleObject::indirectExportEntries() const {
return cyclicModuleFields()->indirectExportEntries();
}
const ExportEntryVector& ModuleObject::starExportEntries() const {
return cyclicModuleFields()->starExportEntries;
Span<const ExportEntry> ModuleObject::starExportEntries() const {
return cyclicModuleFields()->starExportEntries();
}
void ModuleObject::initFunctionDeclarations(
@ -934,16 +973,12 @@ void ModuleObject::setInitialEnvironment(
void ModuleObject::initImportExportData(
MutableHandle<RequestedModuleVector> requestedModules,
MutableHandle<ImportEntryVector> importEntries,
MutableHandle<ExportEntryVector> localExportEntries,
MutableHandle<ExportEntryVector> indirectExportEntries,
MutableHandle<ExportEntryVector> starExportEntries) {
MutableHandle<ExportEntryVector> exportEntries, uint32_t localExportCount,
uint32_t indirectExportCount, uint32_t starExportCount) {
cyclicModuleFields()->requestedModules = std::move(requestedModules.get());
cyclicModuleFields()->importEntries = std::move(importEntries.get());
cyclicModuleFields()->localExportEntries =
std::move(localExportEntries.get());
cyclicModuleFields()->indirectExportEntries =
std::move(indirectExportEntries.get());
cyclicModuleFields()->starExportEntries = std::move(starExportEntries.get());
cyclicModuleFields()->initExportEntries(exportEntries, localExportCount,
indirectExportCount, starExportCount);
}
/* static */
@ -1492,7 +1527,7 @@ bool frontend::StencilModuleMetadata::createExportEntries(
Handle<ModuleRequestVector> moduleRequests,
const frontend::StencilModuleMetadata::EntryVector& input,
MutableHandle<ExportEntryVector> output) const {
if (!output.reserve(input.length())) {
if (!output.reserve(output.length() + input.length())) {
ReportOutOfMemory(cx);
return false;
}
@ -1575,22 +1610,21 @@ bool frontend::StencilModuleMetadata::initModule(
return false;
}
Rooted<ExportEntryVector> localExportEntriesVector(cx);
Rooted<ExportEntryVector> exportEntriesVector(cx);
if (!createExportEntries(cx, atomCache, moduleRequestsVector,
localExportEntries, &localExportEntriesVector)) {
localExportEntries, &exportEntriesVector)) {
return false;
}
Rooted<ExportEntryVector> indirectExportEntriesVector(cx);
if (!createExportEntries(cx, atomCache, moduleRequestsVector,
indirectExportEntries,
&indirectExportEntriesVector)) {
indirectExportEntries, &exportEntriesVector)) {
return false;
}
Rooted<ExportEntryVector> starExportEntriesVector(cx);
if (!createExportEntries(cx, atomCache, moduleRequestsVector,
starExportEntries, &starExportEntriesVector)) {
starExportEntries, &exportEntriesVector)) {
return false;
}
@ -1610,8 +1644,9 @@ bool frontend::StencilModuleMetadata::initModule(
module->initAsyncSlots(cx, isAsync, asyncParentModulesList);
module->initImportExportData(
&requestedModulesVector, &importEntriesVector, &localExportEntriesVector,
&indirectExportEntriesVector, &starExportEntriesVector);
&requestedModulesVector, &importEntriesVector, &exportEntriesVector,
localExportEntries.length(), indirectExportEntries.length(),
starExportEntries.length());
return true;
}

View File

@ -9,6 +9,7 @@
#include "mozilla/HashTable.h" // mozilla::{HashMap, DefaultHasher}
#include "mozilla/Maybe.h" // mozilla::Maybe
#include "mozilla/Span.h"
#include <stddef.h> // size_t
#include <stdint.h> // int32_t, uint32_t
@ -325,9 +326,8 @@ class ModuleObject : public NativeObject {
void initImportExportData(
MutableHandle<RequestedModuleVector> requestedModules,
MutableHandle<ImportEntryVector> importEntries,
MutableHandle<ExportEntryVector> localExportEntries,
MutableHandle<ExportEntryVector> indirectExportEntries,
MutableHandle<ExportEntryVector> starExportEntries);
MutableHandle<ExportEntryVector> exportEntries, uint32_t localExportCount,
uint32_t indirectExportCount, uint32_t starExportCount);
static bool Freeze(JSContext* cx, Handle<ModuleObject*> self);
#ifdef DEBUG
static bool AssertFrozen(JSContext* cx, Handle<ModuleObject*> self);
@ -348,11 +348,11 @@ class ModuleObject : public NativeObject {
Value evaluationError() const;
JSObject* metaObject() const;
ScriptSourceObject* scriptSourceObject() const;
const RequestedModuleVector& requestedModules() const;
const ImportEntryVector& importEntries() const;
const ExportEntryVector& localExportEntries() const;
const ExportEntryVector& indirectExportEntries() const;
const ExportEntryVector& starExportEntries() const;
mozilla::Span<const RequestedModule> requestedModules() const;
mozilla::Span<const ImportEntry> importEntries() const;
mozilla::Span<const ExportEntry> localExportEntries() const;
mozilla::Span<const ExportEntry> indirectExportEntries() const;
mozilla::Span<const ExportEntry> starExportEntries() const;
IndirectBindingMap& importBindings();
void setStatus(ModuleStatus newStatus);

View File

@ -7,6 +7,7 @@
#include "shell/ShellModuleObjectWrapper.h"
#include "mozilla/Maybe.h"
#include "mozilla/Span.h"
#include "jsapi.h" // JS_GetProperty, JS::Call, JS_NewPlainObject, JS_DefineProperty
@ -33,6 +34,8 @@
using namespace js;
using namespace js::shell;
using mozilla::Span;
#define DEFINE_CLASS_IMPL(CLASS) \
CLASS* Shell##CLASS##Wrapper::get() { \
return &getReservedSlot(TargetSlot).toObject().as<CLASS>(); \
@ -247,11 +250,10 @@ bool ShellModuleWrapperGetter(JSContext* cx, const JS::CallArgs& args,
}
template <class T>
bool VectorToArrayFilter(
JSContext* cx, JS::Handle<JSObject*> owner,
const GCVector<typename T::Target, 0, SystemAllocPolicy>& from,
JS::MutableHandle<JS::Value> to) {
size_t length = from.length();
bool SpanToArrayFilter(JSContext* cx, JS::Handle<JSObject*> owner,
Span<const typename T::Target> from,
JS::MutableHandle<JS::Value> to) {
size_t length = from.Length();
JS::Rooted<ArrayObject*> toArray(cx, NewDenseFullyAllocatedArray(cx, length));
if (!toArray) {
return false;
@ -288,7 +290,7 @@ bool ShellModuleNativeWrapperGetter(JSContext* cx, const JS::CallArgs& args,
}
#define DEFINE_NATIVE_GETTER_FUNCTIONS(CLASS, PROP, FILTER) \
static const auto& Shell##CLASS##Wrapper_##PROP##Getter_raw(CLASS* obj) { \
static auto Shell##CLASS##Wrapper_##PROP##Getter_raw(CLASS* obj) { \
return obj->PROP(); \
} \
static bool Shell##CLASS##Wrapper_##PROP##Getter_impl( \
@ -362,15 +364,15 @@ DEFINE_GETTER_FUNCTIONS(ModuleObject, namespace_, ObjectOrNullValue,
DEFINE_GETTER_FUNCTIONS(ModuleObject, status, StatusValue, IdentFilter)
DEFINE_GETTER_FUNCTIONS(ModuleObject, maybeEvaluationError, Value, IdentFilter)
DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, requestedModules,
VectorToArrayFilter<ShellRequestedModuleWrapper>)
SpanToArrayFilter<ShellRequestedModuleWrapper>)
DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, importEntries,
VectorToArrayFilter<ShellImportEntryWrapper>)
SpanToArrayFilter<ShellImportEntryWrapper>)
DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, localExportEntries,
VectorToArrayFilter<ShellExportEntryWrapper>)
SpanToArrayFilter<ShellExportEntryWrapper>)
DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, indirectExportEntries,
VectorToArrayFilter<ShellExportEntryWrapper>)
SpanToArrayFilter<ShellExportEntryWrapper>)
DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, starExportEntries,
VectorToArrayFilter<ShellExportEntryWrapper>)
SpanToArrayFilter<ShellExportEntryWrapper>)
DEFINE_GETTER_FUNCTIONS(ModuleObject, maybeDfsIndex, Uint32OrUndefinedValue,
IdentFilter)
DEFINE_GETTER_FUNCTIONS(ModuleObject, maybeDfsAncestorIndex,

View File

@ -180,7 +180,7 @@ JS::GetRequestedModulesCount(JSContext* cx, Handle<JSObject*> moduleRecord) {
CHECK_THREAD(cx);
cx->check(moduleRecord);
return moduleRecord->as<ModuleObject>().requestedModules().length();
return moduleRecord->as<ModuleObject>().requestedModules().Length();
}
JS_PUBLIC_API JSString* JS::GetRequestedModuleSpecifier(