javazone 2014 - goto java;

Post on 16-Dec-2014

224 Views

Category:

Software

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

Martin SkarsauneJava Developer and Co-Owner

A peek into the OpenJDK compiler : goto java;

高馬丁

GOTO statements in

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.

GOTO Statement – Means

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

2. Modify compiler source to support goto statements

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("!");}

}

GOTOAHEAD

Dijkstra 1968:

What is a Compiler?

Compiler

What is a Compiler?

front back

Parse Enter Process Attribute Flow Desugar Generat

e

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

Parse Enter Process Attribute Flow Desugar Generat

e

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

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][;]

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!

Parse Enter Process Attribute Flow Desugar Generat

e

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

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

Parse Enter Process Attribute Flow Desugar Generat

e

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

scanner.nextToken();

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

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

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

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

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

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

Parse Enter Process Attribute Flow Desugar Generat

e

Class Interface

Parse Enter Process Attribute Flow Desugar Generat

e

• Interface based visitors

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}

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

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

Parse Enter Process Attribute Flow Desugar Generat

e

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

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

Parse Enter Process Attribute Flow Desugar Generat

e

public class SimpleClass {

}

• Default constructor

Parse Enter Process Attribute Flow Desugar Generat

e

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

• Default constructor

Parse Enter Process Attribute Flow Desugar Generat

e

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

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)

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

Parse Enter Process Attribute Flow Desugar Generat

e

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

Parse Enter Process Attribute Flow Desugar Generat

e

• Semantic checks– Types– References

• Corrections– Add required calls to super constructor

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("!");}

}

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

Parse Enter Process Attribute Flow Desugar Generat

e

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

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

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

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

Parse Enter Process Attribute Flow Desugar Generat

e

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

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Erase generic types

public class Bridge implements Comparator {

}

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> {

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> {

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> {

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;

}}

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

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

};}

}

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

};}

}

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

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

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

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

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

}

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

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

}

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

}

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

}

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

}

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

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

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

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

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

}

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

}

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

}

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

}

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Enumspublic enum Status {

YES, NO, MAYBE}

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

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

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

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

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

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

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 {

}

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

}

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]

}

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

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

Parse Enter Process Attribute Flow Desugar Generat

e

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

Parse Enter Process Attribute Flow Desugar Generat

e

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

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

}

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

}

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

}

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

}

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

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

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

Parse Enter Process Attribute Flow Desugar Generat

e

• String concatenation

”string” + value

Source code “Generated code”

Parse Enter Process Attribute Flow Desugar Generat

e

”string” + value new StringBuilder()

Source code “Generated code”

Parse Enter Process Attribute Flow Desugar Generat

e

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

Source code “Generated code”

Parse Enter Process Attribute Flow Desugar Generat

e

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

Source code “Generated code”

Parse Enter Process Attribute Flow Desugar Generat

e

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

Source code “Generated code”

Goto Generation

• Lucky for us there is a byte code for goto

• goto <addr>

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

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

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

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

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

Mission Accompli

shed!

λambd

a

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

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

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)

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

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• Runtime class generation

LambdaMetaFactory• metaFactory(…)• altMetaFactory(…)

InnerClassLambdaMetafactory

ASM

Lambda Class

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

• SerializationLambda Instance

Serialize

SerializedLambda

Deserialize

LambdaMeta

Factory

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

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

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

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

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

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

Parse Enter Process Attribute Flow Desugar Generat

e

TransTypes

Unlambda Lower

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

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

• 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

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

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

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

λambd

a

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

Questions or Comments?

Martin SkarsauneJava Developer and Co-Owner

Thank You for Your Time!

Martin SkarsauneJava Developer and Co-Owner

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

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

top related