123
Martin Skarsaune Java Developer and Co-Owner A peek into the OpenJDK compiler : goto java;

JavaZone 2014 - goto java;

Embed Size (px)

DESCRIPTION

Slide pack for goto java; presentation at JavaZone 2014. The talk looks into the Java compiler and adds support for goto statements.

Citation preview

Page 1: JavaZone 2014 - goto java;

Martin SkarsauneJava Developer and Co-Owner

A peek into the OpenJDK compiler : goto java;

高馬丁

Page 2: JavaZone 2014 - goto java;
Page 3: JavaZone 2014 - goto java;

GOTO statements in

Java!

Page 4: JavaZone 2014 - goto java;

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: JavaZone 2014 - goto java;

GOTO Statement – Means

1. OpenJDK– Open source Java implementation – Compiler implemented in Java

2. Modify compiler source to support goto statements

Page 6: JavaZone 2014 - goto java;

Success case

public class GotoSuccess {

public static void main(String[] args) {one: System.out.print("goto ");two: System.out.print("Java");goto four;three: System.out.print("2014");goto five;four: System.out.print("Zone ");goto three;five: System.out.print("!");}

}

Page 7: JavaZone 2014 - goto java;

GOTOAHEAD

Dijkstra 1968:

Page 8: JavaZone 2014 - goto java;

What is a Compiler?

Compiler

Page 9: JavaZone 2014 - goto java;

What is a Compiler?

front back

Page 10: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

processAnnotations(enterTrees(… parseFiles(…))),…)…generate(desugar(flow(attribute(…))))

Page 11: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

processAnnotations(enterTrees(… parseFiles(…))),…)…generate(desugar(flow(attribute(…))))

Page 12: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

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: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

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: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

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

Page 15: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

scanner.nextToken();

Page 16: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

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

Page 17: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

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

scanner.nextToken();

Page 18: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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));

Page 19: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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();

Page 20: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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));

Page 21: JavaZone 2014 - goto java;

CompilationUnit

ClassDefinition

FieldDefintion

MethodDefinition

Signature

Body

IfStatement

Goto

Wikipedia: “the visitor design pattern is a way of separating an algorithm from an object structure on which it operates”

visitClassDef(..)

visitMethodDef(..)

visitIf(..)

Parse Enter Process Attribute Flow Desugar Generat

eAbstract Syntax Tree

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

GOTO IDENTIFIER SEMI

Page 22: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

Class Interface

Page 23: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Interface based visitors

Page 24: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

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: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

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; ...}

Page 26: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

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: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

processAnnotations(enterTrees(… parseFiles(…))),…)…generate(desugar(flow(attribute(…))))

Page 28: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

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 29: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

public class SimpleClass {

}

• Default constructor

Page 30: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

• Default constructor

Page 31: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

processAnnotations(enterTrees(… parseFiles(…))),…)…generate(desugar(flow(attribute(…))))

Page 32: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Annotation processing API• Part of ordinary javac process since

Java 1.6• Plugin API (see javac documentation)

Page 33: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

@

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

- proc:none – do not process annotations

• Output controlled by command line switches

Page 34: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

processAnnotations(enterTrees(… parseFiles(…))),…)…generate(desugar(flow(attribute(…))))

Page 35: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Semantic checks– Types– References

• Corrections– Add required calls to super constructor

Page 36: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• We want to verify that goto target exists in current scope

public class GotoMissingLabel {

public static void main(String[] args) {one: System.out.print("goto ");two: System.out.print("Java");goto six;three: System.out.print("2014");goto five;four: System.out.print("Zone ");goto three;five: System.out.print("!");}

}

Page 37: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

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 38: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

processAnnotations(enterTrees(… parseFiles(…))),…)…generate(desugar(flow(attribute(…))))

Page 39: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

Page 40: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

We want to detect circular gotos:

public class GotoCircularWarning {public static void main(String[] args) {

one: System.out.print("goto "); two: System.out.print("Java"); goto four; three: System.out.print("2014"); goto five; four: System.out.print("Zone "); goto three; five: System.out.println("!"); goto one;//forms infinite loop }}

Page 41: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

Flow.FlowAnalyzer class:

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

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

compiler.properties:

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

Page 42: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

processAnnotations(enterTrees(… parseFiles(…))),…)…generate(desugar(flow(attribute(…))))

Page 43: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Erase generic types

public class Bridge implements Comparator {

}

Page 44: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Erase generic types

public class Bridge implements Comparator {

}

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

}or<T> {

Page 45: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Erase generic types

public class Bridge implements Comparator<Integer> {

}

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

}or<T> {

Page 46: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Erase 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 47: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Erase generic types

public class Bridge implements Comparator {

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

}}

Page 48: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Erase generic types

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 49: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Extract Inner Class

public class Outer {private void foo() { }

public Runnable fooRunner() {

return new Runnable() {

public void run() {

foo();}

};}

}

Page 50: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Extract Inner Class

public class Outer {private void foo() { }

public Runnable fooRunner() {

return new Runnable() {

public void run() {

foo();}

};}

}

Page 51: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Extract 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;

public void run() {

this$0.foo(); }}

Page 52: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Extract 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 53: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Extract 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 54: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Extract Inner Class

public class Outer {private void foo() { }

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

}

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 55: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Boxing

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

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

}

Page 56: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Boxing

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); }

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

Page 57: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Boxing

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

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

}

Page 58: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Unboxing

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

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

}

Page 59: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Unboxing

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

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

}

Page 60: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Varargs

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

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

}

Page 61: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Varargs

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); }

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

Page 62: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Varargs

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 63: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• For 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 64: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• For 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 static <T> List<T> asList(T... a) { return new ArrayList<>(a); }

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

Page 65: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• For 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 66: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• For 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 67: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• For 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 68: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• For 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 69: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enumspublic enum Status {

YES, NO, MAYBE}

Page 70: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enumspublic enum Status {

YES, NO, MAYBE private Status(String $enum$name, int $enum$ordinal) { super($enum$name, $enum$ordinal); }}

Page 71: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enumspublic enum Status {

YES, NO, MAYBE private 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 72: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enumspublic enum Status {

YES, NO, MAYBE private 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 73: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enum based switch statements

public class SwitchStatus {

void switchStatus(Status status) {

switch (status) { case MAYBE: return;

default: break; } }}

Page 74: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enum based switch statements

public class SwitchStatus {

void switchStatus(Status status) {

switch (status) { case MAYBE: return;

default: break; } }}

Page 75: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enum based switch statements

public class SwitchStatus {

void switchStatus(Status status) {

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

default: break; } }}

Page 76: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enum based switch statements

public class SwitchStatus {

void switchStatus(Status status) {

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

default: break; } }}

class SwitchStatus$1 {

}

Page 77: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enum based switch statements

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 78: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enum based switch statements

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 79: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enum based switch statements

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 80: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enum based switch statements

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 81: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

processAnnotations(enterTrees(… parseFiles(…))),…)…generate(desugar(flow(attribute(…))))

Page 82: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Generate bytecodes• Organize initializers• String concatenation• Some optimizations

Page 83: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Organize <init> (Constructor)

public class InstanceInitialization { String key="key"; String value; public InstanceInitialization(String value) { this.value = value; }

}

Page 84: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Organize <init> (Constructor)

public class InstanceInitialization { String key="key"; String value; public InstanceInitialization(String value) { super(); this.value = value; }

}

Page 85: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Organize <init> (Constructor)

public class InstanceInitialization { String key; String value; public InstanceInitialization(String value) { super(); key = ”key”; this.value = value; }

}

Page 86: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Organize <init> (Constructor)

public class InstanceInitialization { String key; String value; public <init>(String value) { super(); key = ”key”; this.value = value; }

}

Page 87: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Organize <clinit> (Static initialization)

public class StaticInitialization { static String key="key"; static String value; static { value = value; }}

Page 88: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Organize <clinit> (Static initialization)

public class StaticInitialization { static String key; static String value; static { key="key”; value = value; }}

Page 89: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• Organize <clinit> (Static initialization)

public class StaticInitialization { static String key; static String value; static void <clinit>{ key="key”; value = value; }}

Page 90: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

• String concatenation

”string” + value

Source code “Generated code”

Page 91: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

”string” + value new StringBuilder()

Source code “Generated code”

Page 92: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

Source code “Generated code”

Page 93: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

Source code “Generated code”

Page 94: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

Source code “Generated code”

Page 95: JavaZone 2014 - goto java;

Goto Generation

• Lucky for us there is a byte code for goto

• goto <addr>

Page 96: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

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

Source code Byte codePC… …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

Page 97: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

…label: <somecode>…goto label;

Source code Byte codePC…20

… goto 20

<stackmap>

<somecode>

Used by goto?Must emit stackmap

• Scenario 1: go back

Emit goto to label and turn code generation on

again

Page 98: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

…goto label; …label: <somecode>

Source code Byte codePC……

29 <somecode>

goto

<stackmap>

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

• Scenario 2: go forward

Label used? • emit stack frame • patch pending gotos

29

Page 99: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

Gen.java - Labelled

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 100: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

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 101: JavaZone 2014 - goto java;

Mission Accompli

shed!

Page 102: JavaZone 2014 - goto java;

λambd

a

Page 103: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

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

• Many interesting design considerations

Page 104: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Simple example

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

Page 105: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• LambdaToMethod.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 106: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Runtime

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 107: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Runtime class generation

LambdaMetaFactory• metaFactory(…)• altMetaFactory(…)

InnerClassLambdaMetafactory

ASM

Lambda Class

Page 108: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• SerializationLambda Instance

Serialize

SerializedLambda

Deserialize

LambdaMeta

Factory

Page 109: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Example with instance and local capture

private int c = 3; public Comparator<String> withInstanceAndLocalCapture() { int a = 1, b = 2; return (String d, String e) -> d.compareTo(e) + a + b - c;}

Page 110: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Example with instance and local capture

private int c = 3; public Comparator<String> withInstanceAndLocalCapture() { int a = 1, b = 2; return (String d, String e) -> d.compareTo(e) + a + b - c;}/*synthetic*/ private int lambda$withInstanceAndLocalCapture$1(final int cap$0, final int cap$1, final String d, final String e) { return d.compareTo(e) + cap$0 + cap$1 - c;}

Page 111: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Example with instance and local capture

private int c = 3; public Comparator<String> withInstanceAndLocalCapture() { int a = 1, b = 2; return <invokedynamic>LambdaMetafactory.metafactory(this,a,b); }/*synthetic*/ private int lambda$withInstanceAndLocalCapture$1(final int cap$0, final int cap$1, final String d, final String e) { return d.compareTo(e) + cap$0 + cap$1 - c;}

Page 112: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Example with instance and local capture

final class LambdaExample$$Lambda$2/2117255219 extends Object implements Comparator { public int compare(Object, Object) private final LambdaExample arg$1; private final int arg$2; private final int arg$3; private LambdaExample$$Lambda$2/2117255219(LambdaExample,int,int) private static Comparator get$Lambda(LambdaExample,int,int)}

.lambda$withInstanceAndLocalCapture$1(arg$2, arg$3,(String)d,(String)e) arg$1

Page 113: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

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

Page 114: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

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

Page 115: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Step 1: Enable lambda : Source.java

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

JDK1_8JDK1_5

Page 116: JavaZone 2014 - goto java;

• Step 2: Enable special handling

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

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

Page 117: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Step 3: Implement and call lambda method

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

result = makeMetafactoryIndyCall(...);

Page 118: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Step 3: Example

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 119: JavaZone 2014 - goto java;

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Step 3: Example

public Comparator<String> lambdaExample() { }

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

Page 120: JavaZone 2014 - goto java;

λambd

a

Page 121: JavaZone 2014 - goto java;

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 122: JavaZone 2014 - goto java;

Questions or Comments?

Martin SkarsauneJava Developer and Co-Owner

Page 123: JavaZone 2014 - goto java;

Thank You for Your Time!

Martin SkarsauneJava Developer and Co-Owner

if(you.want(nineBot))goto Kantega;

Kantega: eat(bbq); test(java.skills);