Chromium Code Reviews| Index: src/wasm/encoder.cc |
| diff --git a/src/wasm/encoder.cc b/src/wasm/encoder.cc |
| index 05eb0d513b07a86b8c23656ed9336a2a855ed973..50db2fd88ddbced5f9502cfb6af1ca15282ffd25 100644 |
| --- a/src/wasm/encoder.cc |
| +++ b/src/wasm/encoder.cc |
| @@ -30,15 +30,11 @@ namespace v8 { |
| namespace internal { |
| namespace wasm { |
| -// Emit a section name and the size as a padded varint that can be patched |
| +// Emit a section code and the size as a padded varint that can be patched |
| // later. |
| -size_t EmitSection(WasmSection::Code code, ZoneBuffer& buffer) { |
| - // Emit the section name. |
| - const char* name = WasmSection::getName(code); |
| - TRACE("emit section: %s\n", name); |
| - size_t length = WasmSection::getNameLength(code); |
| - buffer.write_size(length); // Section name string size. |
| - buffer.write(reinterpret_cast<const byte*>(name), length); |
| +size_t EmitSection(WasmSectionCode code, ZoneBuffer& buffer) { |
|
Mircea Trofin
2016/09/19 16:16:25
const ZoneBuffer&, or ZoneBuffer*
titzer
2016/09/21 08:58:44
You're right that this should be a pointer instead
|
| + // Emit the section code. |
| + buffer.write_u8(code); |
| // Emit a placeholder for the length. |
| return buffer.reserve_u32v(); |
| @@ -55,6 +51,8 @@ WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder) |
| locals_(builder->zone()), |
| signature_index_(0), |
| exported_(0), |
| + func_index_(static_cast<uint32_t>(builder->imports_.size() + |
| + builder->functions_.size())), |
| body_(builder->zone()), |
| name_(builder->zone()), |
| i32_temps_(builder->zone()), |
| @@ -90,6 +88,10 @@ void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) { |
| EmitWithVarInt(kExprSetLocal, local_index); |
| } |
| +void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) { |
| + EmitWithVarInt(kExprTeeLocal, local_index); |
| +} |
| + |
| void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) { |
| for (size_t i = 0; i < code_size; ++i) { |
| body_.push_back(code[i]); |
| @@ -143,14 +145,14 @@ void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const { |
| buffer.write_u32v(signature_index_); |
| } |
| -void WasmFunctionBuilder::WriteExport(ZoneBuffer& buffer, |
| - uint32_t func_index) const { |
| +void WasmFunctionBuilder::WriteExport(ZoneBuffer& buffer) const { |
|
Mircea Trofin
2016/09/19 16:16:25
const ZoneBuffer&, or ZoneBuffer*
|
| if (exported_) { |
| - buffer.write_u32v(func_index); |
| buffer.write_size(name_.size()); |
| if (name_.size() > 0) { |
| buffer.write(reinterpret_cast<const byte*>(&name_[0]), name_.size()); |
| } |
| + buffer.write_u8(kExternalFunction); |
| + buffer.write_u32v(func_index_); |
| } |
| } |
| @@ -175,7 +177,10 @@ WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data, |
| } |
| void WasmDataSegmentEncoder::Write(ZoneBuffer& buffer) const { |
|
Mircea Trofin
2016/09/19 16:16:25
const ZoneBuffer&, or ZoneBuffer*
|
| + buffer.write_u8(0); // linear memory zero |
| + buffer.write_u8(kExprI32Const); |
| buffer.write_u32v(dest_); |
| + buffer.write_u8(kExprEnd); |
| buffer.write_u32v(static_cast<uint32_t>(data_.size())); |
| buffer.write(&data_[0], data_.size()); |
| } |
| @@ -191,17 +196,11 @@ WasmModuleBuilder::WasmModuleBuilder(Zone* zone) |
| signature_map_(zone), |
| start_function_index_(-1) {} |
| -uint32_t WasmModuleBuilder::AddFunction() { |
| +WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) { |
| functions_.push_back(new (zone_) WasmFunctionBuilder(this)); |
| - return static_cast<uint32_t>(functions_.size() - 1); |
| -} |
| - |
| -WasmFunctionBuilder* WasmModuleBuilder::FunctionAt(size_t index) { |
| - if (functions_.size() > index) { |
| - return functions_.at(index); |
| - } else { |
| - return nullptr; |
| - } |
| + // Add the signature if one was provided here. |
| + if (sig) functions_.back()->SetSignature(sig); |
| + return functions_.back(); |
| } |
| void WasmModuleBuilder::AddDataSegment(WasmDataSegmentEncoder* data) { |
| @@ -243,16 +242,18 @@ void WasmModuleBuilder::AddIndirectFunction(uint32_t index) { |
| uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, |
| FunctionSig* sig) { |
| + DCHECK_EQ(0, functions_.size()); // imports must be added before functions! |
| imports_.push_back({AddSignature(sig), name, name_length}); |
| return static_cast<uint32_t>(imports_.size() - 1); |
| } |
| -void WasmModuleBuilder::MarkStartFunction(uint32_t index) { |
| - start_function_index_ = index; |
| +void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) { |
| + start_function_index_ = function->func_index(); |
| } |
| -uint32_t WasmModuleBuilder::AddGlobal(LocalType type, bool exported) { |
| - globals_.push_back(std::make_pair(type, exported)); |
| +uint32_t WasmModuleBuilder::AddGlobal(LocalType type, bool exported, |
| + bool mutability) { |
| + globals_.push_back(std::make_tuple(type, exported, mutability)); |
| return static_cast<uint32_t>(globals_.size() - 1); |
| } |
| @@ -266,7 +267,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
| // == Emit signatures ======================================================== |
| if (signatures_.size() > 0) { |
| - size_t start = EmitSection(WasmSection::Code::Signatures, buffer); |
| + size_t start = EmitSection(kTypeSectionCode, buffer); |
| buffer.write_size(signatures_.size()); |
| for (FunctionSig* sig : signatures_) { |
| @@ -283,86 +284,130 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
| FixupSection(buffer, start); |
| } |
| - // == Emit globals =========================================================== |
| - if (globals_.size() > 0) { |
| - size_t start = EmitSection(WasmSection::Code::Globals, buffer); |
| - buffer.write_size(globals_.size()); |
| - |
| - for (auto global : globals_) { |
| - buffer.write_u32v(0); // Length of the global name. |
| - buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(global.first)); |
| - buffer.write_u8(global.second); |
| - } |
| - FixupSection(buffer, start); |
| - } |
| - |
| // == Emit imports =========================================================== |
| if (imports_.size() > 0) { |
| - size_t start = EmitSection(WasmSection::Code::ImportTable, buffer); |
| + size_t start = EmitSection(kImportSectionCode, buffer); |
| buffer.write_size(imports_.size()); |
| for (auto import : imports_) { |
| - buffer.write_u32v(import.sig_index); |
| - buffer.write_u32v(import.name_length); |
| - buffer.write(reinterpret_cast<const byte*>(import.name), |
| + buffer.write_u32v(import.name_length); // module name length |
| + buffer.write(reinterpret_cast<const byte*>(import.name), // module name |
| import.name_length); |
| - buffer.write_u32v(0); |
| + buffer.write_u32v(0); // field name length |
| + buffer.write_u8(kExternalFunction); |
| + buffer.write_u32v(import.sig_index); |
| } |
| FixupSection(buffer, start); |
| } |
| // == Emit function signatures =============================================== |
| + bool has_names = false; |
| if (functions_.size() > 0) { |
| - size_t start = EmitSection(WasmSection::Code::FunctionSignatures, buffer); |
| + size_t start = EmitSection(kFunctionSectionCode, buffer); |
| buffer.write_size(functions_.size()); |
| for (auto function : functions_) { |
| function->WriteSignature(buffer); |
| if (function->exported()) exports++; |
| + if (function->name_.size() > 0) has_names = true; |
| } |
| FixupSection(buffer, start); |
| } |
| // == emit function table ==================================================== |
| if (indirect_functions_.size() > 0) { |
| - size_t start = EmitSection(WasmSection::Code::FunctionTable, buffer); |
| + size_t start = EmitSection(kTableSectionCode, buffer); |
| + buffer.write_u8(1); // table count |
| + buffer.write_u8(kWasmAnyFunctionTypeForm); |
| + buffer.write_u8(kResizableMaximumFlag); |
| + buffer.write_size(indirect_functions_.size()); |
| buffer.write_size(indirect_functions_.size()); |
| - |
| - for (auto index : indirect_functions_) { |
| - buffer.write_u32v(index); |
| - } |
| FixupSection(buffer, start); |
| } |
| // == emit memory declaration ================================================ |
| { |
| - size_t start = EmitSection(WasmSection::Code::Memory, buffer); |
| + size_t start = EmitSection(kMemorySectionCode, buffer); |
| + buffer.write_u8(1); // memory count |
| + buffer.write_u32v(kResizableMaximumFlag); |
| buffer.write_u32v(16); // min memory size |
| buffer.write_u32v(16); // max memory size |
| - buffer.write_u8(0); // memory export |
| - static_assert(kDeclMemorySize == 3, "memory size must match emit above"); |
| + FixupSection(buffer, start); |
| + } |
| + |
| + // == Emit globals =========================================================== |
| + if (globals_.size() > 0) { |
| + size_t start = EmitSection(kGlobalSectionCode, buffer); |
| + buffer.write_size(globals_.size()); |
| + |
| + for (auto global : globals_) { |
|
Mircea Trofin
2016/09/19 16:16:25
If we're not using global as an iterator, it'd be
|
| + static const int kLocalTypeIndex = 0; |
| + static const int kMutabilityIndex = 2; |
| + buffer.write_u8( |
| + WasmOpcodes::LocalTypeCodeFor(std::get<kLocalTypeIndex>(global))); |
| + buffer.write_u8(std::get<kMutabilityIndex>(global)); |
| + switch (std::get<kLocalTypeIndex>(global)) { |
| + case kAstI32: { |
| + static const byte code[] = {WASM_I32V_1(0)}; |
| + buffer.write(code, sizeof(code)); |
| + break; |
| + } |
| + case kAstF32: { |
| + static const byte code[] = {WASM_F32(0)}; |
| + buffer.write(code, sizeof(code)); |
| + break; |
| + } |
| + case kAstI64: { |
| + static const byte code[] = {WASM_I64V_1(0)}; |
| + buffer.write(code, sizeof(code)); |
| + break; |
| + } |
| + case kAstF64: { |
| + static const byte code[] = {WASM_F64(0.0)}; |
| + buffer.write(code, sizeof(code)); |
| + break; |
| + } |
| + default: |
| + UNREACHABLE(); |
| + } |
| + buffer.write_u8(kExprEnd); |
| + } |
| FixupSection(buffer, start); |
| } |
| // == emit exports =========================================================== |
| if (exports > 0) { |
| - size_t start = EmitSection(WasmSection::Code::ExportTable, buffer); |
| + size_t start = EmitSection(kExportSectionCode, buffer); |
| buffer.write_u32v(exports); |
| - uint32_t index = 0; |
| - for (auto function : functions_) { |
| - function->WriteExport(buffer, index++); |
| - } |
| + for (auto function : functions_) function->WriteExport(buffer); |
|
Mircea Trofin
2016/09/19 16:16:25
same comment about auto
titzer
2016/09/21 08:58:44
Should be clear from context, IMHO. Iterating over
Mircea Trofin
2016/09/21 16:38:23
I don't know from local context what type function
|
| FixupSection(buffer, start); |
| } |
| // == emit start function index ============================================== |
| if (start_function_index_ >= 0) { |
| - size_t start = EmitSection(WasmSection::Code::StartFunction, buffer); |
| + size_t start = EmitSection(kStartSectionCode, buffer); |
| buffer.write_u32v(start_function_index_); |
| FixupSection(buffer, start); |
| } |
| + // == emit function table elements =========================================== |
| + if (indirect_functions_.size() > 0) { |
|
Mircea Trofin
2016/09/19 16:16:25
if !indirect_functions.empty()
titzer
2016/09/21 08:58:44
We should probably fix all the others above. No ne
|
| + size_t start = EmitSection(kElementSectionCode, buffer); |
| + buffer.write_u8(1); // count of entries |
| + buffer.write_u8(0); // table index |
| + buffer.write_u8(kExprI32Const); // offset |
| + buffer.write_u32v(0); |
| + buffer.write_u8(kExprEnd); |
| + buffer.write_size(indirect_functions_.size()); // element count |
| + |
| + for (auto index : indirect_functions_) { |
| + buffer.write_u32v(index); |
| + } |
| + |
| + FixupSection(buffer, start); |
| + } |
| + |
| // == emit code ============================================================== |
| if (functions_.size() > 0) { |
| - size_t start = EmitSection(WasmSection::Code::FunctionBodies, buffer); |
| + size_t start = EmitSection(kCodeSectionCode, buffer); |
| buffer.write_size(functions_.size()); |
| for (auto function : functions_) { |
| function->WriteBody(buffer); |
| @@ -372,7 +417,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
| // == emit data segments ===================================================== |
| if (data_segments_.size() > 0) { |
| - size_t start = EmitSection(WasmSection::Code::DataSegments, buffer); |
| + size_t start = EmitSection(kDataSectionCode, buffer); |
| buffer.write_size(data_segments_.size()); |
| for (auto segment : data_segments_) { |
| @@ -380,6 +425,28 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
| } |
| FixupSection(buffer, start); |
| } |
| + |
| + // == Emit names ============================================================= |
| + if (has_names) { |
| + // Emit the section code. |
| + buffer.write_u8(kUnknownSectionCode); |
| + // Emit the section string. |
| + buffer.write_size(4); |
| + buffer.write(reinterpret_cast<const byte*>("name"), 4); |
| + // Emit a placeholder for the length. |
| + size_t start = buffer.reserve_u32v(); |
| + // Emit the names. |
| + buffer.write_size(functions_.size()); |
| + for (auto function : functions_) { |
| + buffer.write_size(function->name_.size()); |
| + if (function->name_.size() > 0) { |
| + buffer.write(reinterpret_cast<const byte*>(&function->name_[0]), |
| + function->name_.size()); |
| + } |
| + buffer.write_u8(0); |
| + } |
| + FixupSection(buffer, start); |
| + } |
| } |
| } // namespace wasm |
| } // namespace internal |