mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 23:47:51 +01:00
optimize the DUP instruction, only use a temp local variable if needed.
This commit is contained in:
parent
3d8f49c79a
commit
a4040a8d3b
@ -723,7 +723,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
|
|||||||
byteCode.skip( 4 - padding );
|
byteCode.skip( 4 - padding );
|
||||||
}
|
}
|
||||||
startPosition--;
|
startPosition--;
|
||||||
int switchValuestartPosition = findPushInstructionCodePosition( 1 );
|
int switchValuestartPosition = findBlockStartCodePosition( 1 );
|
||||||
|
|
||||||
int defaultPosition = startPosition + byteCode.readInt();
|
int defaultPosition = startPosition + byteCode.readInt();
|
||||||
int[] keys;
|
int[] keys;
|
||||||
|
@ -18,6 +18,7 @@ package de.inetsoftware.jwebassembly.module;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import javax.annotation.Nonnegative;
|
import javax.annotation.Nonnegative;
|
||||||
@ -112,8 +113,8 @@ public abstract class WasmCodeBuilder {
|
|||||||
* the count of values on the stack back. 1 means the last value. 2 means the penultimate value.
|
* the count of values on the stack back. 1 means the last value. 2 means the penultimate value.
|
||||||
* @return the code position that push the last instruction
|
* @return the code position that push the last instruction
|
||||||
*/
|
*/
|
||||||
int findPushInstructionCodePosition( int count ) {
|
int findBlockStartCodePosition( int count ) {
|
||||||
return findPushInstruction( count, true );
|
return findBlockStart( count, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,7 +127,7 @@ public abstract class WasmCodeBuilder {
|
|||||||
* true, get the code position; false, get the index in the instructions
|
* true, get the code position; false, get the index in the instructions
|
||||||
* @return the code position that push the last instruction
|
* @return the code position that push the last instruction
|
||||||
*/
|
*/
|
||||||
private int findPushInstruction( int count, boolean codePosition ) {
|
private int findBlockStart( int count, boolean codePosition ) {
|
||||||
int valueCount = 0;
|
int valueCount = 0;
|
||||||
List<WasmInstruction> instructions = this.instructions;
|
List<WasmInstruction> instructions = this.instructions;
|
||||||
for( int i = instructions.size() - 1; i >= 0; i-- ) {
|
for( int i = instructions.size() - 1; i >= 0; i-- ) {
|
||||||
@ -152,6 +153,32 @@ public abstract class WasmCodeBuilder {
|
|||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
AnyType findValueTypeFromStack( int count ) {
|
AnyType findValueTypeFromStack( int count ) {
|
||||||
|
return findInstructionThatPushValue( count, (idx,instr ) -> instr.getPushValueType() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the instruction that push the x-th value to the stack.
|
||||||
|
*
|
||||||
|
* @param count
|
||||||
|
* the count of values on the stack back. 1 means the last value. 2 means the penultimate value.
|
||||||
|
* @return the instruction
|
||||||
|
*/
|
||||||
|
private WasmInstruction findInstructionThatPushValue( int count ) {
|
||||||
|
return findInstructionThatPushValue( count, (index,instruction) -> instruction );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the instruction that push the x-th value to the stack.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* the return type
|
||||||
|
* @param count
|
||||||
|
* the count of values on the stack back. 1 means the last value. 2 means the penultimate value.
|
||||||
|
* @param funct
|
||||||
|
* the return value from the instruction
|
||||||
|
* @return the function value
|
||||||
|
*/
|
||||||
|
<T> T findInstructionThatPushValue( int count, BiFunction<Integer, WasmInstruction, T> funct ) {
|
||||||
int valueCount = 0;
|
int valueCount = 0;
|
||||||
List<WasmInstruction> instructions = this.instructions;
|
List<WasmInstruction> instructions = this.instructions;
|
||||||
for( int i = instructions.size() - 1; i >= 0; i-- ) {
|
for( int i = instructions.size() - 1; i >= 0; i-- ) {
|
||||||
@ -159,12 +186,12 @@ public abstract class WasmCodeBuilder {
|
|||||||
AnyType valueType = instr.getPushValueType();
|
AnyType valueType = instr.getPushValueType();
|
||||||
if( valueType != null ) {
|
if( valueType != null ) {
|
||||||
if( ++valueCount == count ) {
|
if( ++valueCount == count ) {
|
||||||
return valueType;
|
return funct.apply( i, instr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
valueCount -= instr.getPopCount();
|
valueCount -= instr.getPopCount();
|
||||||
}
|
}
|
||||||
throw new WasmException( "Push Value not found", -1 ); // should never occur
|
throw new WasmException( "Push instruction not found", -1 ); // should never occur
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -271,7 +298,7 @@ public abstract class WasmCodeBuilder {
|
|||||||
AnyType valueType = findValueTypeFromStack( 1 );
|
AnyType valueType = findValueTypeFromStack( 1 );
|
||||||
localVariables.useIndex( valueType, wasmIdx );
|
localVariables.useIndex( valueType, wasmIdx );
|
||||||
}
|
}
|
||||||
instructions.add( new WasmLocalInstruction( op, wasmIdx, javaCodePos, lineNumber ) );
|
instructions.add( new WasmLocalInstruction( op, wasmIdx, localVariables, javaCodePos, lineNumber ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -283,11 +310,25 @@ public abstract class WasmCodeBuilder {
|
|||||||
* the line number in the Java source code
|
* the line number in the Java source code
|
||||||
*/
|
*/
|
||||||
protected void addDupInstruction( int javaCodePos, int lineNumber ) {
|
protected void addDupInstruction( int javaCodePos, int lineNumber ) {
|
||||||
AnyType type = findValueTypeFromStack( 1 );
|
WasmInstruction instr = findInstructionThatPushValue( 1 );
|
||||||
int idx = getTempVariable( type, javaCodePos, javaCodePos + 1 );
|
AnyType type = instr.getPushValueType();
|
||||||
instructions.add( new WasmDupInstruction( idx, type, localVariables, javaCodePos, lineNumber ) );
|
int varIndex = -1;
|
||||||
|
// if it is a GET to a local variable then we can use it
|
||||||
|
if( instr.getType() == Type.Local ) {
|
||||||
|
WasmLocalInstruction local1 = (WasmLocalInstruction)instr;
|
||||||
|
if( local1.getOperator() == VariableOperator.get ) {
|
||||||
|
varIndex = local1.getIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//alternate we need to create a new locale variable
|
||||||
|
if( varIndex < 0 ) {
|
||||||
|
varIndex = getTempVariable( type, javaCodePos, javaCodePos + 1 );
|
||||||
|
instructions.add( new WasmDupInstruction( varIndex, type, localVariables, javaCodePos, lineNumber ) );
|
||||||
// an alternative solution can be a function call with multiple return values but this seems to be slower
|
// an alternative solution can be a function call with multiple return values but this seems to be slower
|
||||||
// new SyntheticFunctionName( "dup" + storeType, "local.get 0 local.get 0 return", storeType, null, storeType, storeType ), codePos, lineNumber )
|
// new SyntheticFunctionName( "dup" + storeType, "local.get 0 local.get 0 return", storeType, null, storeType, storeType ), codePos, lineNumber )
|
||||||
|
} else {
|
||||||
|
instructions.add( new WasmLocalInstruction( VariableOperator.get, varIndex, localVariables, javaCodePos, lineNumber ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -473,8 +514,7 @@ public abstract class WasmCodeBuilder {
|
|||||||
|
|
||||||
// find the instruction that this push on stack
|
// find the instruction that this push on stack
|
||||||
int count = indirectCall.getPopCount();
|
int count = indirectCall.getPopCount();
|
||||||
int idx = findPushInstruction( count, false );
|
WasmInstruction instr = findInstructionThatPushValue( count );
|
||||||
WasmInstruction instr = instructions.get( idx );
|
|
||||||
int varIndex = -1;
|
int varIndex = -1;
|
||||||
// if it is a GET to a local variable then we can use it
|
// if it is a GET to a local variable then we can use it
|
||||||
if( instr.getType() == Type.Local ) {
|
if( instr.getType() == Type.Local ) {
|
||||||
@ -487,7 +527,7 @@ public abstract class WasmCodeBuilder {
|
|||||||
if( varIndex < 0 ) {
|
if( varIndex < 0 ) {
|
||||||
int javaCodePos = indirectCall.getCodePosition();
|
int javaCodePos = indirectCall.getCodePosition();
|
||||||
varIndex = getTempVariable( indirectCall.getThisType(), instr.getCodePosition(), javaCodePos + 1 );
|
varIndex = getTempVariable( indirectCall.getThisType(), instr.getCodePosition(), javaCodePos + 1 );
|
||||||
idx = count == 1 ? instructions.size() : findPushInstruction( count - 1, false );
|
int idx = count == 1 ? instructions.size() : findBlockStart( count - 1, false );
|
||||||
instructions.add( idx, new DupThis( indirectCall, varIndex, javaCodePos ) );
|
instructions.add( idx, new DupThis( indirectCall, varIndex, javaCodePos ) );
|
||||||
}
|
}
|
||||||
indirectCall.setVariableIndexOfThis( varIndex );
|
indirectCall.setVariableIndexOfThis( varIndex );
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2018 - 2019 Volker Berlin (i-net software)
|
Copyright 2018 - 2020 Volker Berlin (i-net software)
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -31,8 +31,6 @@ import de.inetsoftware.jwebassembly.wasm.AnyType;
|
|||||||
*/
|
*/
|
||||||
class WasmLoadStoreInstruction extends WasmLocalInstruction {
|
class WasmLoadStoreInstruction extends WasmLocalInstruction {
|
||||||
|
|
||||||
private LocaleVariableManager localVariables;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of a load/store instruction
|
* Create an instance of a load/store instruction
|
||||||
*
|
*
|
||||||
@ -48,8 +46,7 @@ class WasmLoadStoreInstruction extends WasmLocalInstruction {
|
|||||||
* the line number in the Java source code
|
* the line number in the Java source code
|
||||||
*/
|
*/
|
||||||
WasmLoadStoreInstruction( boolean load, @Nonnegative int idx, LocaleVariableManager localVariables, int javaCodePos, int lineNumber ) {
|
WasmLoadStoreInstruction( boolean load, @Nonnegative int idx, LocaleVariableManager localVariables, int javaCodePos, int lineNumber ) {
|
||||||
super( load ? get : set, idx, javaCodePos, lineNumber );
|
super( load ? get : set, idx, localVariables, javaCodePos, lineNumber );
|
||||||
this.localVariables = localVariables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,11 +56,4 @@ class WasmLoadStoreInstruction extends WasmLocalInstruction {
|
|||||||
int getIndex() {
|
int getIndex() {
|
||||||
return localVariables.get( super.getIndex(), getCodePosition() ); // translate slot index to position index
|
return localVariables.get( super.getIndex(), getCodePosition() ); // translate slot index to position index
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
AnyType getPushValueType() {
|
|
||||||
return getPopCount() == 0 ? localVariables.getValueType( getIndex() ) : null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2018 - 2019 Volker Berlin (i-net software)
|
Copyright 2018 - 2020 Volker Berlin (i-net software)
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -38,6 +38,8 @@ class WasmLocalInstruction extends WasmInstruction {
|
|||||||
|
|
||||||
private int idx;
|
private int idx;
|
||||||
|
|
||||||
|
final LocaleVariableManager localVariables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of a load/store instruction for a local variable.
|
* Create an instance of a load/store instruction for a local variable.
|
||||||
*
|
*
|
||||||
@ -45,15 +47,18 @@ class WasmLocalInstruction extends WasmInstruction {
|
|||||||
* the operation
|
* the operation
|
||||||
* @param idx
|
* @param idx
|
||||||
* the memory/slot idx of the variable
|
* the memory/slot idx of the variable
|
||||||
|
* @param localVariables
|
||||||
|
* the manager for local variables
|
||||||
* @param javaCodePos
|
* @param javaCodePos
|
||||||
* the code position/offset in the Java method
|
* the code position/offset in the Java method
|
||||||
* @param lineNumber
|
* @param lineNumber
|
||||||
* the line number in the Java source code
|
* the line number in the Java source code
|
||||||
*/
|
*/
|
||||||
WasmLocalInstruction( VariableOperator op, @Nonnegative int idx, int javaCodePos, int lineNumber ) {
|
WasmLocalInstruction( VariableOperator op, @Nonnegative int idx, LocaleVariableManager localVariables, int javaCodePos, int lineNumber ) {
|
||||||
super( javaCodePos, lineNumber );
|
super( javaCodePos, lineNumber );
|
||||||
this.op = op;
|
this.op = op;
|
||||||
this.idx = idx;
|
this.idx = idx;
|
||||||
|
this.localVariables = localVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,7 +91,7 @@ class WasmLocalInstruction extends WasmInstruction {
|
|||||||
/**
|
/**
|
||||||
* Get the number of the locals
|
* Get the number of the locals
|
||||||
*
|
*
|
||||||
* @return the index
|
* @return the index, mostly the Wasm Index
|
||||||
*/
|
*/
|
||||||
@Nonnegative
|
@Nonnegative
|
||||||
int getIndex() {
|
int getIndex() {
|
||||||
@ -107,7 +112,7 @@ class WasmLocalInstruction extends WasmInstruction {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
AnyType getPushValueType() {
|
AnyType getPushValueType() {
|
||||||
return null;
|
return op == get ? localVariables.getValueType( getIndex() ) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user