From 86b79103ebafa70996f5e1d53e3feadc0f227ae3 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Mon, 10 Sep 2018 15:09:32 +0200 Subject: [PATCH] Bug 1471500 - Complete initial implementation of the bulk-memory proposal. Part 5 of 10. r=bbouvier. At run time, the implementation of {memory,table}.init needs to know the actual bytes to be copied to complete the required initialisations, for passive initialisers. It seems simplest to compute them exactly at instantiation time, and have the computed data owned by the instance. This also means it is possible for that data to be released by {memory,table}.drop, independently of all other instances. This patch adds new types DataSegmentInit, ElemSegmentInit, DataSegmentInitVector, and ElemSegmentInitVector to hold this data. They are explained in detail in a comment in WasmTypes.h. For a data segment, the initialising values for a memory are merely bytes, but for a table it is more complex -- a pair of (entry point, instance pointer). This patch also adds a type WasmCallee to encapsulate that. --HG-- extra : rebase_source : adaee69ee3662432bd2fc6e9924b8ce8093a7a46 --- js/src/wasm/WasmInstance.h | 4 ++++ js/src/wasm/WasmModule.cpp | 14 ++++++------ js/src/wasm/WasmTypes.h | 45 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/js/src/wasm/WasmInstance.h b/js/src/wasm/WasmInstance.h index 701d6bd391dd..3d2abd4bd251 100644 --- a/js/src/wasm/WasmInstance.h +++ b/js/src/wasm/WasmInstance.h @@ -55,6 +55,8 @@ class Instance const UniqueTlsData tlsData_; GCPtrWasmMemoryObject memory_; SharedTableVector tables_; + DataSegmentInitVector dataSegInitVec_; + ElemSegmentInitVector elemSegInitVec_; bool enterFrameTrapsEnabled_; // Internal helpers: @@ -97,6 +99,8 @@ class Instance const Metadata& metadata() const { return code_->metadata(); } bool isAsmJS() const { return metadata().isAsmJS(); } const SharedTableVector& tables() const { return tables_; } + DataSegmentInitVector& dataSegInitVec() { return dataSegInitVec_; } + ElemSegmentInitVector& elemSegInitVec() { return elemSegInitVec_; } SharedMem memoryBase() const; WasmMemoryObject* memory() const; size_t memoryMappedSize() const; diff --git a/js/src/wasm/WasmModule.cpp b/js/src/wasm/WasmModule.cpp index cae549504f9b..40828a98d509 100644 --- a/js/src/wasm/WasmModule.cpp +++ b/js/src/wasm/WasmModule.cpp @@ -950,26 +950,26 @@ Module::instantiate(JSContext* cx, return false; ElemSegmentVector elemSegments; - for (const ElemSegment& eseg : code_->elemSegments()) { + for (const ElemSegment& seg : code_->elemSegments()) { // This (debugging) code path is called only for tier 1. - MOZ_ASSERT(eseg.elemCodeRangeIndices2_.empty()); + MOZ_ASSERT(seg.elemCodeRangeIndices2_.empty()); // ElemSegment doesn't have a (fallible) copy constructor, // so we have to clone it "by hand". ElemSegment clone; - clone.tableIndex = eseg.tableIndex; - clone.offset = eseg.offset; + clone.tableIndex = seg.tableIndex; + clone.offset = seg.offset; MOZ_ASSERT(clone.elemFuncIndices.empty()); - if (!clone.elemFuncIndices.appendAll(eseg.elemFuncIndices)) + if (!clone.elemFuncIndices.appendAll(seg.elemFuncIndices)) return false; MOZ_ASSERT(clone.elemCodeRangeIndices1_.empty()); - if (!clone.elemCodeRangeIndices1_.appendAll(eseg.elemCodeRangeIndices1_)) + if (!clone.elemCodeRangeIndices1_.appendAll(seg.elemCodeRangeIndices1_)) return false; MOZ_ASSERT(clone.elemCodeRangeIndices2_.empty()); - if (!clone.elemCodeRangeIndices2_.appendAll(eseg.elemCodeRangeIndices2_)) + if (!clone.elemCodeRangeIndices2_.appendAll(seg.elemCodeRangeIndices2_)) return false; if (!elemSegments.append(std::move(clone))) diff --git a/js/src/wasm/WasmTypes.h b/js/src/wasm/WasmTypes.h index df05531c2781..c6ef9e600095 100644 --- a/js/src/wasm/WasmTypes.h +++ b/js/src/wasm/WasmTypes.h @@ -1122,6 +1122,51 @@ struct DataSegment typedef Vector DataSegmentVector; +// A pairing of entry point and instance pointer, used for lazy table +// initialisation. + +struct WasmCallee +{ + WasmCallee() : instance(nullptr), entry(nullptr) {} + WasmCallee(const Instance* instance, void* entry) + : instance(instance), + entry(entry) + {} + // The instance associated with the code address. + const Instance* instance; + // The table entry code address. + void* entry; +}; + +// Support for passive data and element segments -- lazy initialisation. +// +// At instantiation time, we prepare the required initialising data for each +// passive segment, copying it into new memory. This is done separately for +// data segments and elem segments. We also create a vector of pointers to +// this copied data, with nullptr for entries corresponding to active +// segments. This vector has the same length as the vector of data/elem +// segments respectively in the originating module. +// +// The vector of pointers and the prepared data are owned by the instance +// that is constructed. We have to do this so that the initialising data is +// available at run time in the instance, in particular to +// Instance::{mem,table}{Init,Drop}. +// +// The final structures have type DataSegmentInitVector and +// ElemSegmentInitVector respectively. + +typedef Vector DataSegmentInit; +typedef Vector ElemSegmentInit; + +// We store (unique) pointers rather than references to the initialising +// vectors in order that they can be incrementally freed as we execute +// {memory,table}.drop instructions. + +typedef Vector, 0, SystemAllocPolicy> + DataSegmentInitVector; +typedef Vector, 0, SystemAllocPolicy> + ElemSegmentInitVector; + // FuncTypeIdDesc describes a function type that can be used by call_indirect // and table-entry prologues to structurally compare whether the caller and // callee's signatures *structurally* match. To handle the general case, a