mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 10:44:47 +01:00
implements reading from constant strings from memory
This commit is contained in:
parent
835cf45f61
commit
f61cebd285
@ -28,7 +28,21 @@ import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||
*/
|
||||
public abstract class ArraySyntheticFunctionName extends SyntheticFunctionName {
|
||||
|
||||
private final AnyType[] signature;
|
||||
private final AnyType[] signatureTypes;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param className
|
||||
* the Java class name
|
||||
* @param name
|
||||
* the function name
|
||||
* @param signatureTypes
|
||||
* the method signature, first the parameters, then null and the the return types
|
||||
*/
|
||||
public ArraySyntheticFunctionName( String className, String name, AnyType... signatureTypes ) {
|
||||
this( className, name, "()V", signatureTypes ); //TODO better signature name
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
@ -38,11 +52,13 @@ public abstract class ArraySyntheticFunctionName extends SyntheticFunctionName {
|
||||
* @param name
|
||||
* the function name
|
||||
* @param signature
|
||||
* the string signature
|
||||
* @param signatureTypes
|
||||
* the method signature, first the parameters, then null and the the return types
|
||||
*/
|
||||
public ArraySyntheticFunctionName( String className, String name, AnyType... signature ) {
|
||||
super( className, name, "()V" ); //TODO better signature name
|
||||
this.signature = signature;
|
||||
public ArraySyntheticFunctionName( String className, String name, String signature, AnyType... signatureTypes ) {
|
||||
super( className, name, signature );
|
||||
this.signatureTypes = signatureTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -50,6 +66,6 @@ public abstract class ArraySyntheticFunctionName extends SyntheticFunctionName {
|
||||
*/
|
||||
@Override
|
||||
public Iterator<AnyType> getSignature( TypeManager types ) {
|
||||
return Arrays.asList( signature ).iterator();
|
||||
return Arrays.asList( signatureTypes ).iterator();
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +95,7 @@ public class ModuleGenerator {
|
||||
this.libraries = new URLClassLoader( libraries.toArray( new URL[libraries.size()] ) );
|
||||
WasmOptions options = writer.options;
|
||||
types.init( options );
|
||||
strings.init( functions );
|
||||
javaCodeBuilder.init( types, functions, strings, options );
|
||||
((WasmCodeBuilder)watParser).init( types, functions, strings, options );
|
||||
scanLibraries( libraries );
|
||||
|
@ -24,6 +24,9 @@ import java.util.LinkedHashMap;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
|
||||
import de.inetsoftware.jwebassembly.api.annotation.WasmTextCode;
|
||||
import de.inetsoftware.jwebassembly.wasm.ValueType;
|
||||
|
||||
/**
|
||||
* Handle all the constant strings. The constant strings will be write into the data section.
|
||||
*
|
||||
@ -31,6 +34,12 @@ import javax.annotation.Nonnegative;
|
||||
*/
|
||||
class StringManager extends LinkedHashMap<String, Integer> {
|
||||
|
||||
private FunctionManager functions;
|
||||
|
||||
void init( FunctionManager functions ) {
|
||||
this.functions = functions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the prepare. Now no new strings should be added.
|
||||
*
|
||||
@ -41,7 +50,12 @@ class StringManager extends LinkedHashMap<String, Integer> {
|
||||
*/
|
||||
void prepareFinish( ModuleWriter writer ) throws IOException {
|
||||
// inform the writer of string count that it can allocate a table of type anyref for the constant strings
|
||||
writer.setStringCount( size() );
|
||||
int size = size();
|
||||
writer.setStringCount( size );
|
||||
if( size == 0 ) {
|
||||
// no strings, nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write the strings to the data sections.
|
||||
first there is a index table, then follows the strings
|
||||
@ -68,7 +82,10 @@ class StringManager extends LinkedHashMap<String, Integer> {
|
||||
ByteArrayOutputStream stringOut = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream dataStream = writer.dataStream;
|
||||
|
||||
int offset = dataStream.size() + size() * 4;
|
||||
int offset = dataStream.size();
|
||||
WatCodeSyntheticFunctionName stringMemoryOffset = new WatCodeSyntheticFunctionName( "de/inetsoftware/jwebassembly/module/StringManager", "stringsMemoryOffset", "()I", "i32.const " + offset, null, ValueType.i32 );
|
||||
// functions.markAsNeeded( stringMemoryOffset, true );
|
||||
offset += size * 4;
|
||||
|
||||
for( String str : this.keySet() ) {
|
||||
// write the position where the string starts in the data section
|
||||
@ -110,4 +127,98 @@ class StringManager extends LinkedHashMap<String, Integer> {
|
||||
out.write( b );
|
||||
} while( value != 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Signature of method stringConstant.
|
||||
* @see #stringConstant(int)
|
||||
*/
|
||||
static final String STRING_CONSTANT_SIGNATURE = "de/inetsoftware/jwebassembly/module/StringManager.stringConstant(I)Ljava/lang/String;";
|
||||
|
||||
/**
|
||||
* WASM code
|
||||
* Get a constant string from the table.
|
||||
*
|
||||
* @param strIdx the id/index of the string.
|
||||
* @return the string
|
||||
* @see #STRING_CONSTANT_SIGNATURE
|
||||
*/
|
||||
private static String stringConstant( int strIdx ) {
|
||||
String str = getStringFromTable( strIdx );
|
||||
if( str != null ) {
|
||||
return str;
|
||||
}
|
||||
|
||||
int offset = getIntFromMemory( strIdx * 4 + stringsMemoryOffset() );
|
||||
int length = 0;
|
||||
int b;
|
||||
do {
|
||||
b = getUnsignedByteFromMemory( offset++ );
|
||||
length = (length << 7) + (b & 0x7F);
|
||||
} while( b >= 0x80 );
|
||||
|
||||
byte[] bytes = new byte[length];
|
||||
for( int i = 0; i < length; i++ ) {
|
||||
bytes[i] = getUnsignedByteFromMemory( i + offset );
|
||||
}
|
||||
str = new String( bytes );
|
||||
setStringIntoTable( strIdx, str );
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* WASM code
|
||||
* Get a string from the string table. Should be inlined from the optimizer.
|
||||
*
|
||||
* @param strIdx
|
||||
* the id/index of the string.
|
||||
* @return the string or null if not already set.
|
||||
*/
|
||||
@WasmTextCode( "local.get 0 " + //
|
||||
"table.get 1 " + //
|
||||
"return" )
|
||||
private static native String getStringFromTable( int strIdx );
|
||||
|
||||
/**
|
||||
* WASM code
|
||||
* Set a string from the string table. Should be inlined from the optimizer.
|
||||
*
|
||||
* @param strIdx
|
||||
* the id/index of the string.
|
||||
* @param str
|
||||
* the string
|
||||
*/
|
||||
@WasmTextCode( "local.get 0 " + //
|
||||
"local.get 1 " + //
|
||||
"table.set 1 " + //
|
||||
"return" )
|
||||
private static native void setStringIntoTable( int strIdx, String str );
|
||||
|
||||
@WasmTextCode( "i32.const 0" )
|
||||
private static native int stringsMemoryOffset();
|
||||
|
||||
/**
|
||||
* WASM code
|
||||
* Load an i32 from memory. The offset must be aligned.
|
||||
*
|
||||
* @param pos
|
||||
* the memory position
|
||||
* @return the value from the memory
|
||||
*/
|
||||
@WasmTextCode( "local.get 0 " + //
|
||||
"i32.load offset=0 align=4 " + //
|
||||
"return" )
|
||||
private static native int getIntFromMemory( int pos );
|
||||
|
||||
/**
|
||||
* WASM code
|
||||
* Load a byte from the memory.
|
||||
*
|
||||
* @param pos
|
||||
* the memory position
|
||||
* @return the value from the memory
|
||||
*/
|
||||
@WasmTextCode( "local.get 0 " + //
|
||||
"i32.load8_u offset=0 " + //
|
||||
"return" )
|
||||
private static native byte getUnsignedByteFromMemory( int pos );
|
||||
}
|
||||
|
@ -357,20 +357,7 @@ public abstract class WasmCodeBuilder {
|
||||
if( id == null ) {
|
||||
strings.put( (String)value, id = strings.size() );
|
||||
}
|
||||
String wat = "local.get 0 " + //
|
||||
"table.get 1 " + // strings table
|
||||
"local.tee 1 " + //
|
||||
"ref.is_null " + //
|
||||
"if " + //
|
||||
"local.get 0 " + //
|
||||
"i32.const 4 " + //
|
||||
"i32.mul " + //
|
||||
"i32.load offset=0 " + //
|
||||
"drop " + //
|
||||
"end " + //
|
||||
"local.get 1 " + //
|
||||
"return";
|
||||
FunctionName name = new WatCodeSyntheticFunctionName( "stringConstant", wat, ValueType.i32, null, ValueType.anyref );
|
||||
FunctionName name = new FunctionName( StringManager.STRING_CONSTANT_SIGNATURE );
|
||||
instructions.add( new WasmConstInstruction( id, ValueType.i32, javaCodePos, lineNumber ) );
|
||||
addCallInstruction( name, javaCodePos, lineNumber );
|
||||
} else {
|
||||
|
@ -35,11 +35,30 @@ class WatCodeSyntheticFunctionName extends ArraySyntheticFunctionName {
|
||||
* the function name
|
||||
* @param code
|
||||
* the WAT code (WASM in text form)
|
||||
* @param signature
|
||||
* @param signatureTypes
|
||||
* the method signature, first the parameters, then null and the the return types
|
||||
*/
|
||||
public WatCodeSyntheticFunctionName( String name, String code, AnyType... signature ) {
|
||||
super( "", name, signature );
|
||||
public WatCodeSyntheticFunctionName( String name, String code, AnyType... signatureTypes ) {
|
||||
super( "", name, signatureTypes );
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param className
|
||||
* the Java class name
|
||||
* @param name
|
||||
* the function name
|
||||
* @param code
|
||||
* the WAT code (WASM in text form)
|
||||
* @param signature
|
||||
* the string signature
|
||||
* @param signatureTypes
|
||||
* the method signature, first the parameters, then null and the the return types
|
||||
*/
|
||||
public WatCodeSyntheticFunctionName( String className, String name, String signature, String code, AnyType... signatureTypes ) {
|
||||
super( className, name, signature, signatureTypes );
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user