From df7cb74bccc9a9f1f22ab1ffc1fabf7985d871af Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Sun, 7 Oct 2018 21:20:14 +0200 Subject: [PATCH] Refactor the writing of sections more object oriented. --- .../binary/BinaryModuleWriter.java | 136 +++--------------- .../jwebassembly/binary/Function.java | 11 +- .../jwebassembly/binary/FunctionType.java | 21 ++- .../jwebassembly/binary/Global.java | 15 +- .../jwebassembly/binary/ImportFunction.java | 18 +++ .../jwebassembly/binary/WasmOutputStream.java | 35 +++++ 6 files changed, 113 insertions(+), 123 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java index 41a9a72..a9a6e59 100644 --- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -88,10 +89,10 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod wasm.write( WASM_BINARY_MAGIC ); wasm.writeInt32( WASM_BINARY_VERSION ); - writeTypeSection(); - writeImportSection(); - writeFunctionSection(); - writeGlobalSection(); + writeSection( SectionType.Type, functionTypes ); + writeSection( SectionType.Import, imports.values() ); + writeSection( SectionType.Function, functions.values() ); + writeSection( SectionType.Global, globals.values() ); writeExportSection(); writeCodeSection(); @@ -99,94 +100,24 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod } /** - * Write the type section to the output. This section contains the signatures of the functions. + * Write a section with list format to the output. * + * @param type + * the type of the section + * @param entries + * the entries of the section * @throws IOException * if any I/O error occur */ - private void writeTypeSection() throws IOException { - int count = functionTypes.size(); + private void writeSection( SectionType type, Collection entries ) throws IOException { + int count = entries.size(); if( count > 0 ) { WasmOutputStream stream = new WasmOutputStream(); stream.writeVaruint32( count ); - for( FunctionType type : functionTypes ) { - stream.write( ValueType.func.getCode() ); - stream.writeVaruint32( type.params.size() ); - for( ValueType valueType : type.params ) { - stream.write( valueType.getCode() ); - } - if( type.result == null ) { - stream.writeVaruint32( 0 ); - } else { - stream.writeVaruint32( 1 ); - stream.write( type.result.getCode() ); - } + for( SectionEntry entry : entries ) { + entry.writeSectionEntry( stream ); } - wasm.writeSection( SectionType.Type, stream, null ); - } - } - - /** - * Write the import section to the output. This section declare all imports. - * - * @throws IOException - * if any I/O error occur - */ - private void writeImportSection() throws IOException { - int count = imports.size(); - if( count > 0 ) { - WasmOutputStream stream = new WasmOutputStream(); - stream.writeVaruint32( count ); - for( ImportFunction importFunction : imports.values() ) { - byte[] bytes = importFunction.module.getBytes( StandardCharsets.UTF_8 ); - stream.writeVaruint32( bytes.length ); - stream.write( bytes ); - bytes = importFunction.name.getBytes( StandardCharsets.UTF_8 ); - stream.writeVaruint32( bytes.length ); - stream.write( bytes ); - stream.writeVaruint32( ExternalKind.Function.ordinal() ); - stream.writeVaruint32( importFunction.typeId ); - } - wasm.writeSection( SectionType.Import, stream, null ); - } - } - - /** - * Write the function section to the output. This section contains a mapping from the function index to the type signature index. - * - * @throws IOException - * if any I/O error occur - */ - private void writeFunctionSection() throws IOException { - int count = functions.size(); - if( count > 0 ) { - WasmOutputStream stream = new WasmOutputStream(); - stream.writeVaruint32( count ); - for( Function func : functions.values() ) { - stream.writeVaruint32( func.typeId ); - } - wasm.writeSection( SectionType.Function, stream, null ); - } - } - - /** - * Write the global section to the output. This section contains a declaring of global (static) variables. - * - * @throws IOException - * if any I/O error occur - */ - private void writeGlobalSection() throws IOException { - int count = globals.size(); - if( count > 0 ) { - WasmOutputStream stream = new WasmOutputStream(); - stream.writeVaruint32( count ); - for( Global var : globals.values() ) { - stream.write( var.type.getCode() ); - stream.write( var.mutability ? 1 : 0 ); - writeConst( stream, 0, var.type ); - stream.writeOpCode( END ); - } - wasm.writeSection( SectionType.Global, stream, null ); + wasm.writeSection( type, stream, null ); } } @@ -335,42 +266,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod */ @Override protected void writeConst( Number value, ValueType valueType ) throws IOException { - writeConst( codeStream, value, valueType ); - } - - /** - * Write a constant number value - * - * @param codeStream - * the target stream - * @param value - * the value - * @param valueType - * the data type of the number - * @throws IOException - * if any I/O error occur - */ - private static void writeConst( WasmOutputStream codeStream, Number value, ValueType valueType ) throws IOException { - switch( valueType ) { - case i32: - codeStream.writeOpCode( I32_CONST ); - codeStream.writeVarint( value.intValue() ); - break; - case i64: - codeStream.writeOpCode( I64_CONST ); - codeStream.writeVarint( value.longValue() ); - break; - case f32: - codeStream.writeOpCode( F32_CONST ); - codeStream.writeFloat( value.floatValue() ); - break; - case f64: - codeStream.writeOpCode( F64_CONST ); - codeStream.writeDouble( value.doubleValue() ); - break; - default: - throw new Error( valueType + " " + value ); - } + codeStream.writeConst( value, valueType ); } /** diff --git a/src/de/inetsoftware/jwebassembly/binary/Function.java b/src/de/inetsoftware/jwebassembly/binary/Function.java index e280012..7282a7a 100644 --- a/src/de/inetsoftware/jwebassembly/binary/Function.java +++ b/src/de/inetsoftware/jwebassembly/binary/Function.java @@ -15,15 +15,24 @@ */ package de.inetsoftware.jwebassembly.binary; +import java.io.IOException; + /** * An entry in the function section of the WebAssembly. * * @author Volker Berlin */ -class Function { +class Function extends SectionEntry { int id; int typeId; + /** + * {@inheritDoc} + */ + @Override + void writeSectionEntry( WasmOutputStream stream ) throws IOException { + stream.writeVaruint32( this.typeId ); + } } diff --git a/src/de/inetsoftware/jwebassembly/binary/FunctionType.java b/src/de/inetsoftware/jwebassembly/binary/FunctionType.java index 33bb3b4..0b52494 100644 --- a/src/de/inetsoftware/jwebassembly/binary/FunctionType.java +++ b/src/de/inetsoftware/jwebassembly/binary/FunctionType.java @@ -15,6 +15,7 @@ */ package de.inetsoftware.jwebassembly.binary; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -26,12 +27,30 @@ import de.inetsoftware.jwebassembly.module.ValueType; * * @author Volker Berlin */ -class FunctionType { +class FunctionType extends SectionEntry { final List params = new ArrayList<>(); ValueType result; // Java has only one return parameter + /** + * {@inheritDoc} + */ + @Override + void writeSectionEntry( WasmOutputStream stream ) throws IOException { + stream.write( ValueType.func.getCode() ); + stream.writeVaruint32( this.params.size() ); + for( ValueType valueType : this.params ) { + stream.write( valueType.getCode() ); + } + if( this.result == null ) { + stream.writeVaruint32( 0 ); + } else { + stream.writeVaruint32( 1 ); + stream.write( this.result.getCode() ); + } + } + /** * {@inheritDoc} */ diff --git a/src/de/inetsoftware/jwebassembly/binary/Global.java b/src/de/inetsoftware/jwebassembly/binary/Global.java index acd42da..263e7ad 100644 --- a/src/de/inetsoftware/jwebassembly/binary/Global.java +++ b/src/de/inetsoftware/jwebassembly/binary/Global.java @@ -15,6 +15,8 @@ */ package de.inetsoftware.jwebassembly.binary; +import java.io.IOException; + import de.inetsoftware.jwebassembly.module.ValueType; /** @@ -22,11 +24,22 @@ import de.inetsoftware.jwebassembly.module.ValueType; * * @author Volker Berlin */ -class Global { +class Global extends SectionEntry { int id; ValueType type; boolean mutability; + + /** + * {@inheritDoc} + */ + @Override + void writeSectionEntry( WasmOutputStream stream ) throws IOException { + stream.write( this.type.getCode() ); + stream.write( this.mutability ? 1 : 0 ); + stream.writeConst( 0, this.type ); + stream.writeOpCode( InstructionOpcodes.END ); + } } diff --git a/src/de/inetsoftware/jwebassembly/binary/ImportFunction.java b/src/de/inetsoftware/jwebassembly/binary/ImportFunction.java index d33a4ad..0904e83 100644 --- a/src/de/inetsoftware/jwebassembly/binary/ImportFunction.java +++ b/src/de/inetsoftware/jwebassembly/binary/ImportFunction.java @@ -15,6 +15,9 @@ */ package de.inetsoftware.jwebassembly.binary; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + /** * An entry in the import section of the WebAssembly. * @@ -30,4 +33,19 @@ class ImportFunction extends Function { this.module = module; this.name = name; } + + /** + * {@inheritDoc} + */ + @Override + void writeSectionEntry( WasmOutputStream stream ) throws IOException { + byte[] bytes = this.module.getBytes( StandardCharsets.UTF_8 ); + stream.writeVaruint32( bytes.length ); + stream.write( bytes ); + bytes = this.name.getBytes( StandardCharsets.UTF_8 ); + stream.writeVaruint32( bytes.length ); + stream.write( bytes ); + stream.writeVaruint32( ExternalKind.Function.ordinal() ); + stream.writeVaruint32( this.typeId ); + } } diff --git a/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java b/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java index 15a9518..d110e32 100644 --- a/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java +++ b/src/de/inetsoftware/jwebassembly/binary/WasmOutputStream.java @@ -23,6 +23,8 @@ import java.nio.charset.StandardCharsets; import javax.annotation.Nonnegative; +import de.inetsoftware.jwebassembly.module.ValueType; + /** * @author Volker Berlin */ @@ -147,6 +149,39 @@ class WasmOutputStream extends FilterOutputStream { writeInt32( (int)(l >>> 32) ); } + /** + * Write a constant number value + * + * @param value + * the value + * @param valueType + * the data type of the number + * @throws IOException + * if any I/O error occur + */ + void writeConst( Number value, ValueType valueType ) throws IOException { + switch( valueType ) { + case i32: + this.writeOpCode( InstructionOpcodes.I32_CONST ); + this.writeVarint( value.intValue() ); + break; + case i64: + this.writeOpCode( InstructionOpcodes.I64_CONST ); + this.writeVarint( value.longValue() ); + break; + case f32: + this.writeOpCode( InstructionOpcodes.F32_CONST ); + this.writeFloat( value.floatValue() ); + break; + case f64: + this.writeOpCode( InstructionOpcodes.F64_CONST ); + this.writeDouble( value.doubleValue() ); + break; + default: + throw new Error( valueType + " " + value ); + } + } + /** * Write a section with header and data. *