Download - Goto devoxx

Transcript
Page 1: Goto devoxx

@MSkarsaune#GotoJava

goto java;- Java compilation under the hood

Martin [email protected]

Kantega – Norwegian software craftsmanship since 2003

高馬丁

Page 2: Goto devoxx
Page 3: Goto devoxx

GOTO Statements in Java!

Page 4: Goto devoxx

@MSkarsaune#GotoJava

GOTO Statement –Objective

• Syntax goto identifier;• Runtime• Program control moves to target statement

• Other Semantics • Target (statement label) must be defined in

same scope, compilation error if not• Potential circular gotos should give

compilation warning.

Page 5: Goto devoxx

@MSkarsaune#GotoJava

GOTO Statement –Means

• OpenJDK• Open source Java implementation• Javac is implemented in plain Java

• Modify compiler to support GOTO

Page 6: Goto devoxx

@MSkarsaune#GotoJava

public class GotoSuccess {

public static void main(String[] args) {one: System.out.print("goto ");two: System.out.print(”DEV");goto four;three: System.out.print(”UK");goto five;four: System.out.print(”OXX ");goto three;five: System.out.print("!");

}}

Success Case

Page 7: Goto devoxx

@MSkarsaune#GotoJava

GOTOAHEAD

Dijkstra 1968:

Page 8: Goto devoxx

@MSkarsaune#GotoJava

What is a Compiler?

Compiler

Page 9: Goto devoxx

@MSkarsaune#GotoJava

What is a Compiler?

frontend

backend

Page 10: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 11: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 12: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Syntax: goto identifier;• First convert character stream to token

stream (Scanner.java)

GOTO IDENTIFIER SEMI

[g][o][t][o][ ][f][o][u][r][;]

Page 13: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• goto is already a reserved word in Java!• Lucky for us, goto is therefore defined as a

TokenKind. • Tokens.java:141: GOTO("goto")• The scanner therefore works out of the box!

Page 14: Goto devoxx

@MSkarsaune#GotoJava

final Scanner scanner=factory.newScanner(”goto identifier;”, false);

Parse Enter Process Attribute Flow Desuga

rGenerat

e

...import com.sun.tools.javac.parser.Scanner;...

Page 15: Goto devoxx

@MSkarsaune#GotoJava

final Scanner scanner=factory.newScanner(”goto identifier;”, false);

scanner.nextToken();

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Page 16: Goto devoxx

@MSkarsaune#GotoJava

final Scanner scanner=factory.newScanner(”goto identifier;”, false);

scanner.nextToken();assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Page 17: Goto devoxx

@MSkarsaune#GotoJava

final Scanner scanner=factory.newScanner(”goto identifier;”, false);

scanner.nextToken();assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));

scanner.nextToken();

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Page 18: Goto devoxx

@MSkarsaune#GotoJava

final Scanner scanner=factory.newScanner(”goto identifier;”, false);

scanner.nextToken();assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));

scanner.nextToken();assertThat("Second token is IDENTIFIER", scanner.token().kind,

is(IDENTIFIER));

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Page 19: Goto devoxx

@MSkarsaune#GotoJava

final Scanner scanner=factory.newScanner(”goto identifier;”, false);

scanner.nextToken();assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));

scanner.nextToken();assertThat("Second token is IDENTIFIER", scanner.token().kind,

is(IDENTIFIER));

scanner.nextToken();

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Page 20: Goto devoxx

@MSkarsaune#GotoJava

final Scanner scanner=factory.newScanner(”goto identifier;”, false);

scanner.nextToken();assertThat(”First token is GOTO”, scanner.token().kind, is(GOTO));

scanner.nextToken();assertThat("Second token is IDENTIFIER", scanner.token().kind,

is(IDENTIFIER));

scanner.nextToken(); assertThat("Third token is SEMI", scanner.token().kind, is(SEMI));

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Page 21: Goto devoxx

@MSkarsaune#GotoJava

CompilationUnit

ClassDefinition

FieldDefintion

MethodDefinition

Signature

Body

IfStatement

Goto

Parse Enter Process Attribute Flow Desuga

rGenerat

e

visitClassDef(..)

visitMethodDef(..)

visitIf(..)

Abstract Syntax Tree

[g][o][t][o][ ][f][o][u][r][;]

GOTO IDENTIFIER SEMIWikipedia: “the visitor design pattern is a way of separating an algorithm from an

object structure on which it operates”

Page 22: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

ClassInterface

Page 23: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Interface based visitors

Page 24: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Class based visitors

public void visitGoto(JCGoto tree) { try {

print("goto " + tree.label + ";"); } catch (IOException e) {

throw new UncheckedIOException(e); }

}

public void visitGoto(JCGoto tree) { //TODO implement

}

Page 25: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

public static class JCLabeledStatement extends JCStatement implements LabeledStatementTree {…public GotoResolver handler;…}

public class GotoResolver { Map<GotoTree, Name> gotos; Map<Name, LabeledStatementTree> targets; List<StatementTree> statementsInSequence; ...}

Helper object

Page 26: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

JavacParser.parseStatement()

case GOTO: { nextToken(); Name label = ident(); JCGoto t = to(F.at(pos).Goto(label, getGotoResolver())); accept(SEMI); return t; }

TreeMaker.java:

public JCGoto Goto(Name label, GotoResolver resolver) { JCGoto tree = new JCGoto(label, resolver); tree.pos = pos; return tree;}

Page 27: Goto devoxx

@YourTwitterHandle@MSkarsaune#GotoJava

Dem

o

Page 28: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 29: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 30: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Basic sanity testing of compilation unit

• File name and folder location

• Duplicate class names• Corrections• Add default constructor if

no constructors are declared

Page 31: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Default Constructorpublic class SimpleClass {

}

Page 32: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Default Constructorpublic class SimpleClass { public SimpleClass() { super(); }}

Page 33: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 34: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 35: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Process Annitations• Annotation processing API• Part of ordinary javac process since Java 1.6

• Plugin API (see javac documentation)

Page 36: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Output controlled by command line switches

@

- proc:only – only process annotations, do not compile

- proc:none – do not process annotations

Page 37: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Annotation processor Example• ensure that all fields with @Config

annotation are primitive or strings

@Configprivate String sender;//ok @Configprivate int retries;//ok @Configprivate String[] receivers;//not ok

Page 38: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

META-INF/services/javax.annotation.processing.Processor:

org.kantega.reststop.apt.ConfigFieldProcessor

Page 39: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

ConfigFieldProcessor.java :

@SupportedAnnotationTypes("org.kantega.reststop.api.Config")@SupportedSourceVersion(SourceVersion.RELEASE_7)public class ConfigFieldProcessor extends AbstractProcessor { //... public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

//... if(! isPrimitive(type) && ! isString(type) ) {

processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@Config annotated field must primitive, boxed or String”, element)

Page 40: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Simply add to compilation path:

<dependency> <groupId>org.kantega.reststop</groupId> <artifactId>reststop-annotation-processor</artifactId> <version>${reststop.version}</version> <scope>compile</scope></dependency>

Page 41: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Devoxx BE 2014 : “Plugging into the Java Compiler” , •https://www.parleys.com/tutorial/plugging-java-compiler-1

•Google the session title for additional resources.

Page 42: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 43: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 44: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Attribution• Semantic checks

–Types–References

• Corrections–Add required calls to super constructor

Page 45: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Ensure target label exists in current scopepublic class GotoMissingLabel {

public static void main(String[] args) {one: System.out.print("goto ");two: System.out.print(”DEV");goto six;three: System.out.print(”UK");goto five;four: System.out.print(”OXX ");goto three;five: System.out.print("!");

}}

Page 46: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Attr.java: @Override public void visitGoto(JCGoto that) {

that.findTarget();if(that.target==null)

log.error(that.pos(), "undef.label", that.label);result = null;

}

class JCGoto: …public void findTarget() { this.target = (JCLabeledStatement)this.handler.findTarget(this);}

Page 47: Goto devoxx

@YourTwitterHandle@MSkarsaune#GotoJava

Dem

o

Page 48: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 49: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 50: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Flow analysis• Detect unreachable code• Verify assignments• Ensure proper method return• Verify (effectively) final• Check exception flow

Page 51: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Detect circular gotospublic class GotoCircularWarning {

public static void main(String[] args) { one: System.out.print("goto "); two: System.out.print(”DEV"); goto four; three: System.out.print(”UK"); goto five; four: System.out.print(”OXX "); goto three; five: System.out.println("!"); goto one;//forms infinite loop }}

Page 52: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Flow.FlowAnalyzer class:

compiler.properties:

@Override public void visitGoto(JCGoto tree) { if (tree.handler.detectCircularGotoPosition(tree))

log.warning(tree.pos, "circular.goto"); }

...compiler.warn.circular.goto=circular goto...

Page 53: Goto devoxx

@YourTwitterHandle@MSkarsaune#GotoJava

Dem

o

Page 54: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 55: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 56: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerErase generic types

public class Bridge implements Comparator {

}

public interface Comparator<T> {tint compare(T o1, T o2);

}or<T> {

Page 57: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerErase generic types

public class Bridge implements Comparator<Integer> {

public int compare(Integer first, Integer second) {return first - second;

}

}

public interface Comparator<T> {tint compare(T o1, T o2);

}or<T> {

Page 58: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerErasure - Runtime

public class Bridge implements Comparator {

public int compare(Integer first, Integer second) {return first - second;

}

}

Page 59: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerErasure - Bridge

public class Bridge implements Comparator {

public int compare(Integer first, Integer second) {return first - second;

} /*synthetic*/ public int compare(Object first, Object second) { return this.compare((Integer)first, (Integer)second); }

}

Page 60: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerExtract inner class

public class Outer {private void foo() { }

public Runnable fooRunner() {return new Runnable() {

public void run() {foo();

}};

}}

Page 61: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerExtract inner class

public class Outer {private void foo() { }

public Runnable fooRunner() {return new Runnable() {

public void run() {foo();

}};

}}

Page 62: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerExtract inner class

public class Outer {private void foo() { }

public Runnable fooRunner() {return new Outer$1(this);

}}

class Outer$1 implements Runnable {final Outer this$0;

Outer$1(final Outer this$0) { this.this$0 = this$0; super(); } public void run() {

this$0.foo(); }}

Page 63: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerExtract inner class

public class Outer {private void foo() { }

public Runnable fooRunner() {return new Outer$1(this);

}}

class Outer$1 implements Runnable {final Outer this$0;

Outer$1(final Outer this$0) { this.this$0 = this$0; super(); } public void run() {

this$0.foo(); }}

Page 64: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerExtract inner class

public class Outer {private void foo() { }

public Runnable fooRunner() {return new Outer$1(this);

}/*synthetic*/static void access$000(

Outer x0) { x0.foo(); }

}

class Outer$1 implements Runnable {final Outer this$0;

Outer$1(final Outer this$0) { this.this$0 = this$0; super(); } public void run() {

Outer.access$000(this$0); }}

Page 65: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerBoxing

List<Integer> list = Arrays.asList(1, 2);

for (Integer i : list) {System.out.println("Double: " + i * 2);

}

Page 66: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerBoxing

List<Integer> list = Arrays.asList(1, 2);

for (Integer i : list) {System.out.println("Double: " + i * 2);

}

public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }

Page 67: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerBoxing

List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));

for (Integer i : list) {System.out.println("Double: " + i * 2);

}

Page 68: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerUnboxing

List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));

for (Integer i : list) {System.out.println("Double: " + i * 2);

}

Page 69: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerUnboxing

List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));

for (Integer i : list) {System.out.println("Double: " + i.intValue() * 2);

}

Page 70: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerVarargs

List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));

for (Integer i : list) {System.out.println("Double: " + i.intValue() * 2);

}

public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }

Page 71: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerVarargs

List<Integer> list = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2));

for (Integer i : list) {System.out.println("Double: " + i.intValue() * 2);

}

public static <T> List<T> asList(T... a) { return new ArrayList<>(a);}

Page 72: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerVarargs - runtime

List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});

for (Integer i : list) {System.out.println("Double: " + i.intValue() * 2);

}

Page 73: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerFor each loop

List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});

for (Integer i : list) {System.out.println("Double: " + i.intValue() * 2);

}

Page 74: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerFor each loop

List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});

for (Integer i : list) {System.out.println("Double: " + i.intValue() * 2);

}

public interface Iterable<T> { Iterator<T> iterator();}

Page 75: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerFor each loop

List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});

for (;;) {Integer i System.out.println("Double: " + i.intValue() * 2);

}

Page 76: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerFor each loop

List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});

for (Iterator i$ = list.iterator();;) {Integer i System.out.println("Double: " + i.intValue() * 2);

}

Page 77: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerFor each loop

List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});

for (Iterator i$ = list.iterator(); i$.hasNext();) {Integer i System.out.println("Double: " + i.intValue() * 2);

}

Page 78: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerFor each loop

List<Integer> list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});

for (Iterator i$ = list.iterator(); i$.hasNext();) {Integer i = (Integer)i$.next(); System.out.println("Double: " + i.intValue() * 2);

}

Page 79: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnums

public enum Status {YES, NO, MAYBE

}

Page 80: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnums - constructor

public enum Status {YES, NO, MAYBEprivate Status(String $enum$name, int $enum$ordinal) {

super($enum$name, $enum$ordinal); }}

public static final Status TRUE = new Status("TRUE", 0);public static final Status FALSE = new Status("FALSE", 1);public static final Status MAYBE = new Status("MAYBE", 2);

Page 81: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnums - valueOf

public enum Status {YES, NO, MAYBEprivate Status(String $enum$name, int $enum$ordinal) {

super($enum$name, $enum$ordinal); } public static Status valueOf(String name) { return (Status)Enum.valueOf(Status.class, name); }}

Page 82: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnums - values

public enum Status {YES, NO, MAYBEprivate Status(String $enum$name, int $enum$ordinal) {

super($enum$name, $enum$ordinal); } public static Status valueOf(String name) { return (Status)Enum.valueOf(Status.class, name); } private static final Status[] $VALUES = new Status[]{ Status.YES, Status.NO, Status.MAYBE};

public static Status[] values() { return (Status[])$VALUES.clone(); }}

Page 83: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnum switch statement

public class SwitchStatus {

void switchStatus(Status status) {

switch (status) { case MAYBE: return;

default: break; } }}

Page 84: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnum switch statement

public class SwitchStatus {

void switchStatus(Status status) {

switch (status) { case MAYBE: return;

default: break; } }}

Page 85: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnum switch statement

public class SwitchStatus {

void switchStatus(Status status) {

switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) { case 1: return;

default: break; } }}

class SwitchStatus$1 {

}

Page 86: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnum switch statement

public class SwitchStatus {

void switchStatus(Status status) {

switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) { case 1: return;

default: break; } }}

class SwitchStatus$1 {static final int[] $SwitchMap$Status = new

int[Status.values().length];

}

Page 87: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnum switch statement

public class SwitchStatus {

void switchStatus(Status status) {

switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) { case 1: return;

default: break; } }}

class SwitchStatus$1 {static final int[] $SwitchMap$Status = new

int[Status.values().length]; [0][0][0]

}

Page 88: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerEnum switch statement

public class SwitchStatus {

void switchStatus(Status status) {

switch (SwitchStatus$1.$SwitchMap$Status[(status).ordinal()]) { case 1: return;

default: break; } }}

class SwitchStatus$1 {static final int[] $SwitchMap$Status = new

int[Status.values().length]; [0][0][1]static { try { SwitchStatus$1.$SwitchMap$Status[Status.MAYBE.ordinal()] = 1; } catch (NoSuchFieldError ex) { } }}

Page 89: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 90: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

processAnnotations(enterTrees(… parseFiles(…))),…)

…generate(desugar(flow(attribute(…))))

Page 91: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Organize initializers• String concatenation• Generate bytecodes

Page 92: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Organize <init> (Constructor)public class InstanceInitialization { String key="key"; String value; public InstanceInitialization(String value) { this.value = value; }

}

Page 93: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Organize <init> (Constructor)public class InstanceInitialization { String key="key"; String value; public InstanceInitialization(String value) {

super(); this.value = value; }

}

Page 94: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Organize <init> (Constructor)public class InstanceInitialization { String key; String value; public InstanceInitialization(String value) {

super(); key = ”key”; this.value = value; }

}

Page 95: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Organize <init> (Constructor)public class InstanceInitialization { String key; String value; public void <init> () {

super(); key = ”key”; this.value = value; }

}

Page 96: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Organize <clinit> (static initialization)public class StaticInitialization { static String key="key"; static { init(); }}

Page 97: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Organize <clinit> (static initialization)public class StaticInitialization { static String key; static { key="key"; init(); }}

Page 98: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Organize <clinit> (static initialization)public class StaticInitialization { static String key; static void clinit() { key="key"; init(); }}

Page 99: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

String concatenationSource code “Generated code”

”string” + value

Page 100: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

String concatenationSource code “Generated code”

”string” + value new StringBuilder()

Page 101: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

String concatenationSource code “Generated code”

”string” + value new StringBuilder() .append(”string”)

Page 102: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

String concatenationSource code “Generated code”

”string” + value new StringBuilder() .append(”string”) .append(value)

Page 103: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

String concatenationSource code “Generated code”

”string” + value new StringBuilder() .append(”string”) .append(value) .toString()

Page 104: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Goto generation–Luckily for us there is a GOTO byte code–goto <addr>

Page 105: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

if (<test>) { <ifblock>} else { <elseblock>}<codeafter>

Source code Byte codeCI

9 ifeq<elseblock>

goto<stackmap>

22 <ifblock>

22

<stackmap>

29 <codeafter>

29

Java >= 1.6:Stack map frames must be embedded at target of jump instruction

Code generator (Code.java) marked as not alive.Goto instruction added to list of pending jumps (Chain.java)

Pending jumps processed

Normal GOTO usage

Page 106: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Source code Byte codeCI

…label: <somecode>…goto label;

20

… goto 20

<stackmap>

<somecode>

Used by goto?Must emit stackmap

Emit goto to label and turn code generation on again

GOTO scenario 1 : jump back

Page 107: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

Source code Byte codeCI

GOTO scenario 2 : jump forward

…goto label; …label: <somecode>

……

29 <somecode>

goto

<stackmap>

Label position not yet known?• emit goto• add to list of pending gotos• turn generation on again

29Label used? • emit stack frame • patch pending

gotos

Page 108: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Goto generation–Gen.java , visitor for code generation–Modify for LabelledStatement–Add implementation for Goto

Page 109: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Gen.java – Labelled Statement

public void visitLabelled(JCLabeledStatement tree) { // if the label is used from gotos, have to emit stack map if (tree.handler.isUsed(tree)) code.emitStackMap(); … }

Page 110: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

• Gen.java – Goto

public void visitGoto(JCGoto tree) { tree.handler.addBranch(new Chain(code.emitJump(goto_), null, code.state.dup()), tree.target); //normally goto marks code as not alive, turn generation on code.entryPoint();}

Target position known?• Yes – patch immediately• No – add to list of pending

gotos

Page 111: Goto devoxx

@YourTwitterHandle@MSkarsaune#GotoJava

Dem

o

Page 112: Goto devoxx

@YourTwitterHandle@MSkarsaune#GotoJava

Page 113: Goto devoxx

@YourTwitterHandle@MSkarsaune#GotoJava

ambdaλ

Page 114: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda Lower

• Lambda implementation in Java 8–Language change–Compilation–Runtime support

• Many interesting design considerations

Page 115: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerSimple Example

public Comparator<String> lambdaExample() { return (String a, String b) -> a.compareTo(b);}

Page 116: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerLambdaToMethod.java

public Comparator<String> lambdaExample() { return (String a, String b) -> a.compareTo(b);}

/*synthetic*/ private static int lambda$lambdaExample$0( , ) { return ;}

final String afinal String b

a.compareTo(b)

Page 117: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerRuntime

public Comparator<String> lambdaExample() { return <invokedynamic>LambdaMetafactory.metafactory(}

/*synthetic*/ private static int lambda$lambdaExample$0( final String a, final String b) { return a.compareTo(b);}

public interface Comparator {/*erased*/ int compare(Object o1, Object o2);}

Lookup(LambdaExample), /*caller*/ "compare", ()Comparator, /*MethodType*/ (Object,Object)int, /*MethodType*/ lambda$lambdaExample$0, /*MethodHandle*/ (String,String)int); /*MethodType*/

final class LambdaExample$$Lambda$1/1834188994 implements Comparator { private LambdaExample$$Lambda$1/1834188994() public int compare(Object,Object)}

Page 118: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda Lower

Runtime implementation

LambdaMetaFactory• metaFactory(…)• altMetaFactory(…)

InnerClassLambdaMetafactory

ASM

Lambda Class

Page 119: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda Lower

SerializationLambda Instance

Serialize

SerializedLambda

Deserialize

LambdaMeta

Factory

Page 120: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda Lower

• Possible to back port ?–Capture generated class ?–Compile time generation of inner class!

Page 121: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerStep 1: Source.java

public boolean allowLambda() { return compareTo( ) >= 0;}

JDK1_8JDK1_5

Page 122: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerStep 2: Special handling

boolean mustBackportLambda() { return this.target.compareTo(Target.JDK1_8) < 0;}

Page 123: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerStep 3: Call backport

if(!this.attr.mustBackportLambda()) { result = makeMetafactoryIndyCall(...);}else{ result = new LambdaBackPorter(...).implementLambdaClass(...);}

Page 124: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerExample implementation

private static final class Lambda$$2 implements Comparator<String> {

Lambda$$2 { super(); } public int compare(String arg0, String arg1) { return LambdaExample.lambda$lambdaExample$0(arg0, arg1); } public int compare(Object o1, Object o2) { return this.compare((String)o1, (String)o2); }}

Page 125: Goto devoxx

@MSkarsaune#GotoJava

Parse Enter Process Attribute Flow Desuga

rGenerat

e

TransTypes Unlambda LowerExample invoking

public Comparator<String> lambdaExample() { }

return LambdaMetafactory.metafactory(...);return new Lambda$$289();

Page 126: Goto devoxx

@YourTwitterHandle@MSkarsaune#GotoJava

ambdaλ

Page 127: Goto devoxx

@YourTwitterHandle#DVXFR14{session hashtag} @MSkarsaune#GotoJava

Sum

mar

y

Page 128: Goto devoxx

@MSkarsaune#GotoJava

Wrap Up

• The Java compiler is written in Java• Compilation is done in phases• Programming language advances (syntactic

sugar) require good compiler support• Lambdas are compiled in a forward compatible

manner

Page 129: Goto devoxx

@MSkarsaune#GotoJava

Resources• OpenJDK

• Source: http://hg.openjdk.java.net/• Compiler hacking tutorial

• http://www.ahristov.com/tutorial/java-compiler.html• Lambda design discussion

• http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html

• Sample code:• https://github.com/skarsaune/goto

• Slide pack:• http://www.slideshare.net/MartinSkarsaune

Page 130: Goto devoxx

@YourTwitterHandle#DVXFR14{session hashtag} @MSkarsaune#GotoJava

Q &

A

https://wall-simple.sli.do/#/event/cmnxxfl0/section/18316/questions

Page 131: Goto devoxx

@YourTwitterHandle#DVXFR14{session hashtag} @MSkarsaune#GotoJava

Than

k yo

u

for yo

ur

time!

http://lanyrd.com/profile/martinskarsaune/