mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +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 {
|
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.
|
* Create a new instance.
|
||||||
@ -38,11 +52,13 @@ public abstract class ArraySyntheticFunctionName extends SyntheticFunctionName {
|
|||||||
* @param name
|
* @param name
|
||||||
* the function name
|
* the function name
|
||||||
* @param signature
|
* @param signature
|
||||||
|
* the string signature
|
||||||
|
* @param signatureTypes
|
||||||
* the method signature, first the parameters, then null and the the return types
|
* the method signature, first the parameters, then null and the the return types
|
||||||
*/
|
*/
|
||||||
public ArraySyntheticFunctionName( String className, String name, AnyType... signature ) {
|
public ArraySyntheticFunctionName( String className, String name, String signature, AnyType... signatureTypes ) {
|
||||||
super( className, name, "()V" ); //TODO better signature name
|
super( className, name, signature );
|
||||||
this.signature = signature;
|
this.signatureTypes = signatureTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,6 +66,6 @@ public abstract class ArraySyntheticFunctionName extends SyntheticFunctionName {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Iterator<AnyType> getSignature( TypeManager types ) {
|
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()] ) );
|
this.libraries = new URLClassLoader( libraries.toArray( new URL[libraries.size()] ) );
|
||||||
WasmOptions options = writer.options;
|
WasmOptions options = writer.options;
|
||||||
types.init( options );
|
types.init( options );
|
||||||
|
strings.init( functions );
|
||||||
javaCodeBuilder.init( types, functions, strings, options );
|
javaCodeBuilder.init( types, functions, strings, options );
|
||||||
((WasmCodeBuilder)watParser).init( types, functions, strings, options );
|
((WasmCodeBuilder)watParser).init( types, functions, strings, options );
|
||||||
scanLibraries( libraries );
|
scanLibraries( libraries );
|
||||||
|
@ -24,6 +24,9 @@ import java.util.LinkedHashMap;
|
|||||||
|
|
||||||
import javax.annotation.Nonnegative;
|
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.
|
* 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> {
|
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.
|
* 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 {
|
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
|
// 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.
|
/* Write the strings to the data sections.
|
||||||
first there is a index table, then follows the strings
|
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 stringOut = new ByteArrayOutputStream();
|
||||||
ByteArrayOutputStream dataStream = writer.dataStream;
|
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() ) {
|
for( String str : this.keySet() ) {
|
||||||
// write the position where the string starts in the data section
|
// write the position where the string starts in the data section
|
||||||
@ -110,4 +127,98 @@ class StringManager extends LinkedHashMap<String, Integer> {
|
|||||||
out.write( b );
|
out.write( b );
|
||||||
} while( value != 0 );
|
} 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 ) {
|
if( id == null ) {
|
||||||
strings.put( (String)value, id = strings.size() );
|
strings.put( (String)value, id = strings.size() );
|
||||||
}
|
}
|
||||||
String wat = "local.get 0 " + //
|
FunctionName name = new FunctionName( StringManager.STRING_CONSTANT_SIGNATURE );
|
||||||
"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 );
|
|
||||||
instructions.add( new WasmConstInstruction( id, ValueType.i32, javaCodePos, lineNumber ) );
|
instructions.add( new WasmConstInstruction( id, ValueType.i32, javaCodePos, lineNumber ) );
|
||||||
addCallInstruction( name, javaCodePos, lineNumber );
|
addCallInstruction( name, javaCodePos, lineNumber );
|
||||||
} else {
|
} else {
|
||||||
|
@ -35,11 +35,30 @@ class WatCodeSyntheticFunctionName extends ArraySyntheticFunctionName {
|
|||||||
* the function name
|
* the function name
|
||||||
* @param code
|
* @param code
|
||||||
* the WAT code (WASM in text form)
|
* the WAT code (WASM in text form)
|
||||||
* @param signature
|
* @param signatureTypes
|
||||||
* the method signature, first the parameters, then null and the the return types
|
* the method signature, first the parameters, then null and the the return types
|
||||||
*/
|
*/
|
||||||
public WatCodeSyntheticFunctionName( String name, String code, AnyType... signature ) {
|
public WatCodeSyntheticFunctionName( String name, String code, AnyType... signatureTypes ) {
|
||||||
super( "", name, signature );
|
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;
|
this.code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user