Skip to content

Commit

Permalink
Enable byte code generation in birk
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed May 17, 2016
1 parent 5746262 commit 0070d7b
Show file tree
Hide file tree
Showing 21 changed files with 624 additions and 133 deletions.
Expand Up @@ -179,6 +179,7 @@ public CodeBlock ifStatement( Expression test )
return new CodeBlock( this ); return new CodeBlock( this );
} }



public TryBlock tryBlock( Class<?> resourceType, String resourceName, Expression resource ) public TryBlock tryBlock( Class<?> resourceType, String resourceName, Expression resource )
{ {
return tryBlock( withResource( resourceType, resourceName, resource ) ); return tryBlock( withResource( resourceType, resourceName, resource ) );
Expand Down
Expand Up @@ -21,6 +21,7 @@


import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;


/** /**
Expand All @@ -44,7 +45,12 @@ public LocalVariable createNew( TypeReference type, String name )


public LocalVariable get( String name ) public LocalVariable get( String name )
{ {
return localVariables.get( name ); LocalVariable localVariable = localVariables.get( name );
if (localVariable == null)
{
throw new NoSuchElementException( "No variable " + name + " in scope" );
}
return localVariable;
} }


public static LocalVariables copy( LocalVariables original ) public static LocalVariables copy( LocalVariables original )
Expand Down
161 changes: 106 additions & 55 deletions community/codegen/src/main/java/org/neo4j/codegen/TryBlock.java
Expand Up @@ -20,6 +20,7 @@
package org.neo4j.codegen; package org.neo4j.codegen;


import java.util.Collections; import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
Expand All @@ -34,21 +35,25 @@
public class TryBlock extends CodeBlock public class TryBlock extends CodeBlock
{ {
private final Resource[] resources; private final Resource[] resources;
private final State tryState = newState( null ); private final State tryState = State.empty();
private final List<CatchState> catchStates = new LinkedList<>(); private final List<CatchState> catchStates = new LinkedList<>();
private State finallyState = null; private State finallyState = null;

private State currentState = tryState; private State currentState = tryState;


TryBlock( CodeBlock parent, Resource... resources ) TryBlock( CodeBlock parent, Resource... resources )
{ {
super( parent ); super( parent );
for ( Resource resource : resources )
{
localVariables.createNew( resource.type(), resource.name() );
}
this.resources = resources; this.resources = resources;
} }


public CodeBlock catchBlock(Parameter exception) public CodeBlock catchBlock(Parameter exception)
{ {
CatchState catchState = new CatchState( exception, currentState ); CatchState catchState = new CatchState( exception, currentState );
localVariables.createNew( exception.type(), exception.name() );
this.currentState = catchState; this.currentState = catchState;
catchStates.add( catchState ); catchStates.add( catchState );
return this; return this;
Expand All @@ -60,7 +65,7 @@ public CodeBlock finallyBlock()
{ {
throw new IllegalStateException( "Cannot have more than one finally block" ); throw new IllegalStateException( "Cannot have more than one finally block" );
} }
finallyState = newState( currentState ); finallyState = new State(currentState);
currentState = finallyState; currentState = finallyState;
return this; return this;
} }
Expand All @@ -74,110 +79,156 @@ protected void emit( Consumer<MethodEmitter> emitFunction )
@Override @Override
public void close() public void close()
{ {
currentState.close();
State nextState = currentState.nextState(); State nextState = currentState.nextState();
if ( nextState == null ) if ( nextState == null )
{ {
super.emit( ( e ) -> e.tryCatchBlock( tryActions(), catchClauses(), finallyActions(), localVariables, resources ) ); createTryCatchFinallyBlock();
super.close(); super.close();
} }
currentState = nextState; currentState = nextState;
}


protected void createTryCatchFinallyBlock()
{
super.emit( ( e ) -> e.tryCatchBlock( tryActions(), catchClauses(), finallyActions(),
localVariables, resources ) );
} }


@Override @Override
protected void endBlock() public CodeBlock ifStatement( Expression test )
{ {
//do nothing emit( e -> e.beginIf( test ) );
currentState.innerBlock( () -> emit( MethodEmitter::endBlock ) );
return this;
} }


private List<Consumer<MethodEmitter>> tryActions() @Override
public CodeBlock whileLoop( Expression test )
{ {
return tryState.actions(); emit( e -> e.beginWhile( test ) );
currentState.innerBlock( () -> emit( MethodEmitter::endBlock ) );
return this;
} }


private List<CatchClause> catchClauses() @Override
public TryBlock tryBlock( Resource... resources )
{ {
return catchStates.stream().map( c -> new CatchClause( c.exception, c.actions) ) return new NestedTryBlock( this, resources );
.collect( Collectors.toList() );
} }


private List<Consumer<MethodEmitter>> finallyActions() @Override
protected void endBlock()
{ {
return finallyState == null ? Collections.emptyList() : finallyState.actions(); //do nothing
} }


/** protected List<Consumer<MethodEmitter>> tryActions()
* A Try block can be in different states depending on if we're in try, catch or finally.
* When nextState returns <tt>null</tt> it means we have no more blocks left and should close
* the underlying code block.
*/
private interface State
{ {
return tryState.actions();
}


void addAction( Consumer<MethodEmitter> action ); protected List<CatchClause> catchClauses()

{
List<Consumer<MethodEmitter>> actions(); return catchStates.stream().map( c -> new CatchClause( c.exception, c.actions()) )
.collect( Collectors.toList() );
}


State nextState(); protected List<Consumer<MethodEmitter>> finallyActions()
{
return finallyState == null ? Collections.emptyList() : finallyState.actions();
} }


/** private static class State
* Catch states are special states that stores what kind of exception we are catching.
*/
private static class CatchState implements State
{ {
private final Deque<State> stack = new LinkedList<>();
private final Deque<Runnable> closeActions = new LinkedList<>();
static State empty()
{
return new State(null);
}


private final List<Consumer<MethodEmitter>> actions = new LinkedList<>(); static State from(State parent)
private final Parameter exception; {
private final State parent; return new State(parent);
}


CatchState( Parameter exception, State parent ) private State( State parent )
{ {
this.exception = exception; if ( parent != null )
this.parent = parent; {
stack.push( parent );
}
} }


@Override private final List<Consumer<MethodEmitter>> actions = new LinkedList<>();

public void addAction( Consumer<MethodEmitter> action ) public void addAction( Consumer<MethodEmitter> action )
{ {
actions.add( action ); actions.add( action );
} }


@Override
public List<Consumer<MethodEmitter>> actions() public List<Consumer<MethodEmitter>> actions()
{ {
return actions; return actions;
} }


@Override
public State nextState() public State nextState()
{ {
return parent; return stack.isEmpty() ? null : stack.pop();
} }
}
private State newState( State parent )
{
return new State()
{
private final List<Consumer<MethodEmitter>> actions = new LinkedList<>();


@Override public void innerBlock( Runnable... onCloseActions)
public void addAction( Consumer<MethodEmitter> action ) {
stack.push( this );
for ( Runnable action : onCloseActions )
{ {
actions.add( action ); closeActions.push(action);
} }
}


@Override public void close()
public List<Consumer<MethodEmitter>> actions() {
if ( !closeActions.isEmpty() )
{ {
return actions; closeActions.pop().run();
} }
}
}


@Override /**
public State nextState() * Catch states are special states that stores what kind of exception we are catching.
{ */
return parent; private static class CatchState extends State
} {
};
private final Parameter exception;

CatchState( Parameter exception, State parent )
{
super(parent);
this.exception = exception;
}
}

private class NestedTryBlock extends TryBlock {

NestedTryBlock( CodeBlock parent, Resource... resources )
{
super( parent, resources );
}

// @Override
// protected void emit( Consumer<MethodEmitter> emitFunction )
// {
// currentState.addAction( emitFunction );
// }

@Override
protected void createTryCatchFinallyBlock()
{
currentState.addAction( ( e ) -> e.tryCatchBlock( tryActions(), catchClauses(), finallyActions(),
localVariables, resources ) );
}
} }
} }
Expand Up @@ -123,7 +123,54 @@ public void getField( Expression target, FieldReference field )
@Override @Override
public void constant( Object value ) public void constant( Object value )
{ {
methodVisitor.visitLdcInsn( value ); if ( value == null )
{
methodVisitor.visitInsn( ACONST_NULL );
}
else if ( value instanceof Integer )
{
pushInteger( (Integer) value );
// methodVisitor
// .visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
}
else if ( value instanceof Byte )
{
pushInteger( (Byte) value );
// methodVisitor
// .visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false );
}
else if ( value instanceof Short )
{
pushInteger( (Short) value );
//methodVisitor
// .visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false );
}
else if ( value instanceof Long )
{
methodVisitor.visitLdcInsn( value );
//methodVisitor.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false );
}
else if ( value instanceof Double )
{
methodVisitor.visitLdcInsn( value );
// methodVisitor
// .visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false );
}
else if ( value instanceof Float )
{
methodVisitor.visitLdcInsn( value );
// methodVisitor.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false );
}
else if ( value instanceof Boolean )
{
boolean b = (boolean) value;
methodVisitor.visitInsn( b ? ICONST_1 : ICONST_0 );
// methodVisitor.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false );
}
else
{
methodVisitor.visitLdcInsn( value );
}
} }


@Override @Override
Expand Down
Expand Up @@ -78,7 +78,7 @@ public MethodEmitter method( MethodDeclaration signature )
public void field( FieldReference field, Expression value ) public void field( FieldReference field, Expression value )
{ {
//keep track of all static field->value, and initiate in <clinit> in done //keep track of all static field->value, and initiate in <clinit> in done
if ( Modifier.isStatic( field.modifiers() ) ) if ( Modifier.isStatic( field.modifiers() ) && value != null )
{ {
staticFields.put( field, value ); staticFields.put( field, value );
} }
Expand All @@ -99,7 +99,8 @@ public void done()
for ( Map.Entry<FieldReference,Expression> entry : staticFields.entrySet() ) for ( Map.Entry<FieldReference,Expression> entry : staticFields.entrySet() )
{ {
FieldReference field = entry.getKey(); FieldReference field = entry.getKey();
entry.getValue().accept( expressionVisitor ); Expression value = entry.getValue();
value.accept( expressionVisitor );
methodVisitor.visitFieldInsn( PUTSTATIC, byteCodeName( field.owner() ), methodVisitor.visitFieldInsn( PUTSTATIC, byteCodeName( field.owner() ),
field.name(), typeName( field.type() ) ); field.name(), typeName( field.type() ) );
} }
Expand Down
Expand Up @@ -240,14 +240,15 @@ public void tryCatchBlock( List<Consumer<MethodEmitter>> body, List<CatchClause>
Expression.invoke( Expression.load( variable ), close ) ) ); Expression.invoke( Expression.load( variable ), close ) ) );
} }


if ( !catchClauses.isEmpty() ) tryCatchFinally( body, catchClauses, updatedFinalClauses, localVariables );
{ // if ( !catchClauses.isEmpty() )
tryCatchFinally( body, catchClauses, updatedFinalClauses, localVariables ); // {
} // tryCatchFinally( body, catchClauses, updatedFinalClauses, localVariables );
else // }
{ // else
tryFinally( body, updatedFinalClauses, localVariables ); // {
} // tryFinally( body, updatedFinalClauses, localVariables );
// }
} }


/* /*
Expand Down
Expand Up @@ -41,6 +41,5 @@ public void endBlock()
{ {
methodVisitor.visitJumpInsn( GOTO, l0 ); methodVisitor.visitJumpInsn( GOTO, l0 );
methodVisitor.visitLabel( l1 ); methodVisitor.visitLabel( l1 );
methodVisitor.visitFrame( F_SAME, 0, null, 0, null );
} }
} }

0 comments on commit 0070d7b

Please sign in to comment.