add all used functions to the vtable (also abstract methods)

This commit is contained in:
Volker Berlin 2020-03-21 10:40:22 +01:00
parent be29e7c456
commit 7bf1a26a37
2 changed files with 35 additions and 18 deletions

View File

@ -55,7 +55,7 @@ class FunctionManager {
* @return the state * @return the state
*/ */
@Nonnull @Nonnull
private FunctionState getOrCreate( FunctionName name ) { private FunctionState getOrCreate( @Nonnull FunctionName name ) {
FunctionState state = states.get( name ); FunctionState state = states.get( name );
if( state == null ) { if( state == null ) {
states.put( name, state = new FunctionState() ); states.put( name, state = new FunctionState() );
@ -79,7 +79,7 @@ class FunctionManager {
* the function name * the function name
* @return true, if known * @return true, if known
*/ */
boolean isKnown( FunctionName name ) { boolean isKnown( @Nonnull FunctionName name ) {
return states.get( name ) != null; return states.get( name ) != null;
} }
@ -92,7 +92,7 @@ class FunctionManager {
* @param importAnannotation * @param importAnannotation
* the annotation of the import * the annotation of the import
*/ */
void markAsImport( FunctionName name, Map<String,Object> importAnannotation ) { void markAsImport( @Nonnull FunctionName name, Map<String,Object> importAnannotation ) {
markAsImport( name, (key) -> importAnannotation.get( key ) ); markAsImport( name, (key) -> importAnannotation.get( key ) );
} }
@ -105,7 +105,7 @@ class FunctionManager {
* @param importAnannotation * @param importAnannotation
* the annotation of the import * the annotation of the import
*/ */
void markAsImport( FunctionName name, Function<String,Object> importAnannotation ) { void markAsImport( @Nonnull FunctionName name, Function<String,Object> importAnannotation ) {
getOrCreate( name ).importAnannotation = importAnannotation; getOrCreate( name ).importAnannotation = importAnannotation;
} }
@ -117,7 +117,7 @@ class FunctionManager {
* @param needThisParameter * @param needThisParameter
* if this function need additional to the parameter of the signature an extra "this" parameter * if this function need additional to the parameter of the signature an extra "this" parameter
*/ */
void markAsScanned( FunctionName name, boolean needThisParameter ) { void markAsScanned( @Nonnull FunctionName name, boolean needThisParameter ) {
FunctionState state = getOrCreate( name ); FunctionState state = getOrCreate( name );
switch( state.state ) { switch( state.state ) {
case None: case None:
@ -134,7 +134,7 @@ class FunctionManager {
* @param name * @param name
* the function name * the function name
*/ */
void markAsWritten( FunctionName name ) { void markAsWritten( @Nonnull FunctionName name ) {
getOrCreate( name ).state = State.Written; getOrCreate( name ).state = State.Written;
} }
@ -144,7 +144,7 @@ class FunctionManager {
* @param name * @param name
* the function name * the function name
*/ */
void markAsAbstract( FunctionName name ) { void markAsAbstract( @Nonnull FunctionName name ) {
getOrCreate( name ).state = State.Abstract; getOrCreate( name ).state = State.Abstract;
} }
@ -154,7 +154,7 @@ class FunctionManager {
* @param name * @param name
* the function name * the function name
*/ */
void markAsNeededAndReplaceIfExists( SyntheticFunctionName name ) { void markAsNeededAndReplaceIfExists( @Nonnull SyntheticFunctionName name ) {
FunctionState state = states.get( name ); FunctionState state = states.get( name );
if( state != null ) { if( state != null ) {
states.remove( name ); states.remove( name );
@ -170,7 +170,7 @@ class FunctionManager {
* the function name * the function name
* @return the real function name * @return the real function name
*/ */
FunctionName markAsNeeded( FunctionName name ) { FunctionName markAsNeeded( @Nonnull FunctionName name ) {
FunctionState state = getOrCreate( name ); FunctionState state = getOrCreate( name );
if( state.state == State.None ) { if( state.state == State.None ) {
if( isFinish ) { if( isFinish ) {
@ -276,7 +276,7 @@ class FunctionManager {
* the function name * the function name
* @return true, if the function on the to do list * @return true, if the function on the to do list
*/ */
boolean needToScan( FunctionName name ) { boolean needToScan( @Nonnull FunctionName name ) {
switch( getOrCreate( name ).state ) { switch( getOrCreate( name ).state ) {
case Needed: case Needed:
return true; return true;
@ -292,7 +292,7 @@ class FunctionManager {
* the function name * the function name
* @return true, if the function on the to do list * @return true, if the function on the to do list
*/ */
boolean needToWrite( FunctionName name ) { boolean needToWrite( @Nonnull FunctionName name ) {
switch( getOrCreate( name ).state ) { switch( getOrCreate( name ).state ) {
case Needed: case Needed:
case Scanned: case Scanned:
@ -302,6 +302,22 @@ class FunctionManager {
} }
} }
/**
* Test if the function is called anywhere.
*
* @param name
* the function name
* @return true, if used
*/
boolean isUsed( @Nonnull FunctionName name ) {
switch( getOrCreate( name ).state ) {
case None:
return false;
default:
return true;
}
}
/** /**
* If this function need additional to the parameter of the signature an extra "this" parameter. * If this function need additional to the parameter of the signature an extra "this" parameter.
* *
@ -309,7 +325,7 @@ class FunctionManager {
* the function name * the function name
* @return true, if the function is static * @return true, if the function is static
*/ */
boolean needThisParameter( FunctionName name ) { boolean needThisParameter( @Nonnull FunctionName name ) {
return getOrCreate( name ).needThisParameter; return getOrCreate( name ).needThisParameter;
} }
@ -321,7 +337,7 @@ class FunctionManager {
* @param method * @param method
* the new implementation * the new implementation
*/ */
void addReplacement( FunctionName name, MethodInfo method ) { void addReplacement( @Nonnull FunctionName name, MethodInfo method ) {
FunctionState state = getOrCreate( name ); FunctionState state = getOrCreate( name );
if( state.method == null ) { // ignore redefinition replacements and use the first instance in the library path if( state.method == null ) { // ignore redefinition replacements and use the first instance in the library path
state.method = method; state.method = method;
@ -337,7 +353,7 @@ class FunctionManager {
* @param alias * @param alias
* the new name. * the new name.
*/ */
void setAlias( FunctionName name, FunctionName alias ) { void setAlias( @Nonnull FunctionName name, FunctionName alias ) {
FunctionState state = getOrCreate( name ); FunctionState state = getOrCreate( name );
state.alias = alias; state.alias = alias;
state.state = State.Written; state.state = State.Written;
@ -353,7 +369,7 @@ class FunctionManager {
* @return the method that should be write * @return the method that should be write
*/ */
@Nonnull @Nonnull
MethodInfo replace( FunctionName name, MethodInfo method ) { MethodInfo replace( @Nonnull FunctionName name, MethodInfo method ) {
MethodInfo newMethod = getOrCreate( name ).method; MethodInfo newMethod = getOrCreate( name ).method;
return newMethod != null ? newMethod : method; return newMethod != null ? newMethod : method;
} }
@ -366,7 +382,7 @@ class FunctionManager {
* @param functionIdx * @param functionIdx
* the index * the index
*/ */
void setFunctionIndex( FunctionName name, int functionIdx ) { void setFunctionIndex( @Nonnull FunctionName name, int functionIdx ) {
getOrCreate( name ).functionIdx = functionIdx; getOrCreate( name ).functionIdx = functionIdx;
} }
@ -377,7 +393,7 @@ class FunctionManager {
* the name * the name
* @return the index * @return the index
*/ */
int getFunctionIndex( FunctionName name ) { int getFunctionIndex( @Nonnull FunctionName name ) {
return getOrCreate( name ).functionIdx; return getOrCreate( name ).functionIdx;
} }

View File

@ -448,6 +448,7 @@ public class TypeManager {
fields.add( new NamedStorageType( className, field, types ) ); fields.add( new NamedStorageType( className, field, types ) );
} }
// calculate the vtable (the function indexes of the virtual methods)
for( MethodInfo method : classFile.getMethods() ) { for( MethodInfo method : classFile.getMethods() ) {
if( method.isStatic() || "<init>".equals( method.getName() ) ) { if( method.isStatic() || "<init>".equals( method.getName() ) ) {
continue; continue;
@ -464,7 +465,7 @@ public class TypeManager {
break; break;
} }
} }
if( idx == methods.size() && functions.needToWrite( funcName ) ) { if( idx == methods.size() && functions.isUsed( funcName ) ) {
// if a new needed method then add it // if a new needed method then add it
methods.add( funcName ); methods.add( funcName );
} }