[wasm] Refactor the module decoder to work with section bytes

This CL refactors the module decoder so that it can process a list of
section buffers instead of one module buffer. This change is needed for
streaming compilation. Streaming compilation may require additional
changes.

This CL introduces the following interface to the module decoder:
StartDecoding -- starts the decoding
DecodeModuleHeader -- decodes the module header
DecodeSection -- decodes the section
FinishDecoding -- finishes the decoding and returns the WasmModule

Aside from the different interface the biggest change to the module
decoder is the introduction of a buffer_offset, which is the offset
of the current section buffer of the module decoder in the module bytes.
This buffer_offset is used to translate from section offsets to module
offsets and back.

Another nice change is that the module decoder does not have a zone
anymore. Instead the zone is stored directly in the WasmModule where
it belongs. Zone ownership is also more obvious now.

R=mtrofin@chromium.org, clemensh@chromium.org

Change-Id: I815d777ec380f4c617c39e828ea0c9746c0bae20
Reviewed-on: https://chromium-review.googlesource.com/505490
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45374}
This commit is contained in:
Andreas Haas 2017-05-17 14:02:49 +02:00 committed by Commit Bot
parent 4bbe21671b
commit a8424d592f
5 changed files with 618 additions and 517 deletions

View File

@ -37,10 +37,11 @@ namespace wasm {
// a buffer of bytes.
class Decoder {
public:
Decoder(const byte* start, const byte* end)
: start_(start), pc_(start), end_(end), error_offset_(0) {}
Decoder(const byte* start, const byte* pc, const byte* end)
: start_(start), pc_(pc), end_(end), error_offset_(0) {}
Decoder(const byte* start, const byte* end, uint32_t buffer_offset = 0)
: start_(start), pc_(start), end_(end), buffer_offset_(buffer_offset) {}
Decoder(const byte* start, const byte* pc, const byte* end,
uint32_t buffer_offset = 0)
: start_(start), pc_(pc), end_(end), buffer_offset_(buffer_offset) {}
virtual ~Decoder() {}
@ -183,7 +184,7 @@ class Decoder {
va_end(arguments);
error_msg_.assign(buffer.start(), len);
DCHECK_GE(pc, start_);
error_offset_ = static_cast<uint32_t>(pc - start_);
error_offset_ = static_cast<uint32_t>(pc - start_) + buffer_offset_;
onFirstError();
}
@ -214,28 +215,44 @@ class Decoder {
}
// Resets the boundaries of this decoder.
void Reset(const byte* start, const byte* end) {
void Reset(const byte* start, const byte* end, uint32_t buffer_offset = 0) {
start_ = start;
pc_ = start;
end_ = end;
buffer_offset_ = buffer_offset;
error_offset_ = 0;
error_msg_.clear();
}
void Reset(Vector<const uint8_t> bytes, uint32_t buffer_offset = 0) {
Reset(bytes.begin(), bytes.end(), buffer_offset);
}
bool ok() const { return error_msg_.empty(); }
bool failed() const { return !ok(); }
bool more() const { return pc_ < end_; }
const byte* start() const { return start_; }
const byte* pc() const { return pc_; }
uint32_t pc_offset() const { return static_cast<uint32_t>(pc_ - start_); }
uint32_t pc_offset() const {
return static_cast<uint32_t>(pc_ - start_) + buffer_offset_;
}
uint32_t buffer_offset() const { return buffer_offset_; }
// Takes an offset relative to the module start and returns an offset relative
// to the current buffer of the decoder.
uint32_t GetBufferRelativeOffset(uint32_t offset) const {
DCHECK_LE(buffer_offset_, offset);
return offset - buffer_offset_;
}
const byte* end() const { return end_; }
protected:
const byte* start_;
const byte* pc_;
const byte* end_;
uint32_t error_offset_;
// The offset of the current buffer in the module. Needed for streaming.
uint32_t buffer_offset_;
uint32_t error_offset_ = 0;
std::string error_msg_;
private:

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ const uint8_t kWasmFunctionTypeForm = 0x60;
const uint8_t kWasmAnyFunctionTypeForm = 0x70;
const uint8_t kResizableMaximumFlag = 1;
enum SectionCode {
enum SectionCode : int8_t {
kUnknownSectionCode = 0, // code for unknown sections
kTypeSectionCode = 1, // Function signature declarations
kImportSectionCode = 2, // Import declarations
@ -34,6 +34,9 @@ enum SectionCode {
kCodeSectionCode = 10, // Function code
kDataSectionCode = 11, // Data segments
kNameSectionCode = 12, // Name section (encoded as a string)
// Helper values
kFirstSectionInModule = kTypeSectionCode,
};
enum NameSectionType : uint8_t { kFunction = 1, kLocal = 2 };

View File

@ -960,8 +960,8 @@ WasmInstanceObject* wasm::GetOwningWasmInstance(Code* code) {
return WasmInstanceObject::cast(cell->value());
}
WasmModule::WasmModule(Zone* owned)
: owned_zone(owned), pending_tasks(new base::Semaphore(0)) {}
WasmModule::WasmModule(std::unique_ptr<Zone> owned)
: signature_zone(std::move(owned)), pending_tasks(new base::Semaphore(0)) {}
namespace {

View File

@ -152,7 +152,7 @@ struct V8_EXPORT_PRIVATE WasmModule {
static const uint32_t kPageSize = 0x10000; // Page size, 64kb.
static const uint32_t kMinMemPages = 1; // Minimum memory size = 64kb
Zone* owned_zone;
std::unique_ptr<Zone> signature_zone;
uint32_t min_mem_pages = 0; // minimum size of the memory in 64k pages
uint32_t max_mem_pages = 0; // maximum size of the memory in 64k pages
bool has_max_mem = false; // try if a maximum memory size exists
@ -185,10 +185,7 @@ struct V8_EXPORT_PRIVATE WasmModule {
std::unique_ptr<base::Semaphore> pending_tasks;
WasmModule() : WasmModule(nullptr) {}
WasmModule(Zone* owned_zone);
~WasmModule() {
if (owned_zone) delete owned_zone;
}
WasmModule(std::unique_ptr<Zone> owned);
ModuleOrigin get_origin() const { return origin_; }
void set_origin(ModuleOrigin new_value) { origin_ = new_value; }