35
Mixing Source and Bytecode A Case for Compilation by Normalization OOPSLA'08, Nashville, Tennessee Lennart Kats, TU Delft Martin Bravenboer, UMass Eelco Visser, TU Delft Software Engineering Research Group October 21, 2008

Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

Embed Size (px)

DESCRIPTION

Language extensions increase programmer productivity by providing concise, often domain-specific syntax, and support for static verification of correctness, security, and style constraints. Language extensions can often be realized through translation to the base language, supported by preprocessors and extensible compilers. However, various kinds of extensions require further adaptation of a base compiler's internal stages and components, for example to support separate compilation or to make use of low-level primitives of the platform (e.g., jump instructions or unbalanced synchronization). To allow for a more loosely coupled approach, we propose an open compiler model based on normalization steps from a high-level language to a subset of it, the core language. We developed such a compiler for a mixed Java and (core) bytecode language, and evaluate its effectiveness for composition mechanisms such as traits, as well as statement-level and expression-level language extensions.

Citation preview

Page 1: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

Mixing Source and Bytecode

A Case for Compilation by Normalization

OOPSLA'08, Nashville, Tennessee

Lennart Kats, TU DelftMartin Bravenboer, UMassEelco Visser, TU Delft

Software Engineering Research Group

October 21, 2008

Page 2: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

2

LanguageExtensions

Page 3: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

3

DSLs and Language Extensions

Domain-specific• Database queries• Regular expressions• XML processing• Matrices• Complex numbers• ...

void browse() { List<Book> books =

<| SELECT *

FROM books

WHERE price < 100.00

|>;

for (int i = 0; i < books.size(); i++)

books.get(i).title =~ s/^The //;

}

Page 4: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

4

DSLs and Language Extensions

Domain-specific• Database queries• Regular expressions• XML processing• Matrices• Complex numbers• ...

General-purpose• AOP• Traits• Enums• Iterators• Case classes• Properties/accessors• ...

Page 5: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

5

Program C: Foo.class

(bytecode)

Program B: Foo.java

public class Foo { void bar(BarList list) { Iterator it = list.iterator(); while (it.hasNext()) { Bar b = it.next(); b.print(); } }}

Program A: Foo.mylang

public class Foo { void bar(BarList list) { foreach (Bar b in list) { b.print(); } }}

javac

Code generator

Example: The Foreach Statement

Page 6: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

6

The Preprocessor

+ loosely coupled+ small, modular extension+ no need to know compiler

internalsHost language

Preprocessor

Bytecode

Extendedlanguage

CompilerINTERFACE

– no parser– semantic analysis, errors?

Page 7: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

7

The Front-end Extensible Compiler

Extension

Host language

Front-end

Extendedlanguage

+ front-end reuse

Polyglot

ableJ

MetaBorg

INTERFACE

OJ

– tied to the front-end internals

Bytecode

Compiler

Page 8: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

8

public class Shape { void draw() { … } Vertices getVertices() { … }}

Traits: Composable Units of Behavior[Schärli, Ducasse, Nierstrasz, Black 2003]

Traits

public trait TDrawing { void draw() { … } require Vertices getVertices();}

public class Shape with TDrawing { … Vertices getVertices() { … }}

Page 9: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

9

• Simple idea

• Most libraries are distributed as compiled code

→ Why not do this for traits?

Foo.java TBar.java

FooBar.java

FooBar.class

Traits

javac

Traits

Not extensible

Page 10: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

10

TheFullyExtensible Compiler?

Page 11: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

11

TheFullyExtensible Compiler?

+ reuse everything+ access to back-end–– tied to all compiler internals– complexity– performance trade-offs

Bytecode

Parsing

Extendedlanguage

Parsing

ParsingName

analysis

ParsingType

analysis

ParsingCode

generation

Optimize

Parsing

ParsingEmit

Frontend

Backend

Page 12: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

12

–– tied to all compiler internals– complexity– performance trade-offs

TheWhiteBoxModel?

Page 13: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

13

The Normalizing Compiler

Extensionprocessor

Normalizing compiler

Extendedlanguage

Bytecodecore language

Source+bytecode

INTERFACE

+ simple interface+ access to back-end++ not tied to compiler internals

Page 14: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

14

Foo.java TBar.class

FooBar.classTraits, Revisited

FooBar.javaT

raits

Page 15: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

15

class FooBar {

void hello1() {

System.out.println(“Hello Java world”);

}

`hello2 (void) [

getstatic java.lang.System.out : java.io.PrintStream;

ldc “Hello bytecode world”;

invokevirtual java.io.PrintStream.println(java.lang.String : void);

]

}

Java (Foo.java)

Bytecode (TBar.class)

Java, and Bytecode, and Backticks,Oh, My!

Page 16: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

16

class FooBar {

void hello3() {

System.out.println(`ldc "Hello mixed world");

}

`hello4 (void) [

getstatic System.out : java.io.PrintStream;

push `"Hello ” + “Java".concat("bytecode world");

invokevirtual java.io.PrintStream.println (java.lang.String : void);

]

}

PP

S

Java, and Bytecode, and Backticks:Fine-grained Mixing

Typechecker

Page 17: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

17

Traits X

Partial/open classes X

Iterator generators X

Finite State Automata X

Expression-based Xextensions

Class-method / Statement / Expression level

Typical Applications

Page 18: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

18

States and transitions

Grammar

Code

Example: Finite State Automata (DFAs)

Page 19: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

19

while (true) { switch (state) { case INSIDE_QUOTE: switch (nextToken()) { case '"': consume(); state = OUTSIDE_QUOTE; // end quote found! break; … case EOF: return; default: consume(); } break; case OUTSIDE_QUOTE: switch (c) { … } break; }}

+ simple Java code– performance trade-off

Finite State Automata: Generated Java code

Page 20: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

20

InsideQuote: switch (nextToken()) { case '"': consume(); `goto OutsideQuote; case EOF: return; default: consume(); `goto InsideQuote; } }OutsideQuote: switch (c) { … }

+ performance+ low-level when necessary+ minimal changes+ maintainable

Finite State Automata: Inline Bytecode

Page 21: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

21

Method-body Extensions

• Operators: x as T, x ?? y, ...

• Embedded (external) DSLs: Database queries, XML, ...

• Closures Normalize

Lower-levelcode

Page 22: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

22

Stratego Normalization Rules

desugar-foreach: |[ foreach (t x in e) stm ]|

|[ Iterator x_iterator = e.iterator(); while (x_iterator.hasNext()) { t x = x_iterator.next(); stm; } ]| with x_iterator := <newname> “iterator”

Page 23: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

23

Normalizing ??

String property = readProperty(“x”) ?? “default”;System.out.println(property);

// In basic Java:

String temp = readProperty(“x”);if (temp == null) temp = “default”;String property = temp;System.out.println(property);

Context-sensitivetransformation

Page 24: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

24

Normalizing ??

“But placing statements in front of the assimilated expressions is easy, isn’t it?”

Requires syntactic knowledge:• for, while, return, throw, …• other expressions• other extensions

Page 25: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

25

Normalizing ??

“But placing statements in front of the assimilated expressions is easy, isn’t it? … Right?”

Also requires semantic knowledge:

Iterator<String> it = ...;

for (String e = e0; it.hasNext(); e = it.next() ?? “default”) {

...

}

Page 26: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

26

Normalizing ??

“But placing statements in front of the assimilated expressions is easy, isn’t it? … Right?”

Also requires semantic knowledge:

Iterator<String> it = ...;

Integer temp = ...;

for (String e = e0; it.hasNext(); e = temp) {

...

}

Page 27: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

27

Normalizing '??' !!

String property = readProperty(“x”) ?? “default”;System.out.println(property);

Page 28: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

28

Normalizing '??' !! - with Inline Bytecode

String property = `[ push `readProperty(“x”); dup; store temp; ifnull else; push `e2; goto end; else: load temp; end: ];System.out.println(property);

S

Page 29: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

29

Normalizing '??' !! - with Inline Bytecode

String property = `[ `String temp = readProperty(“x”); `if (temp == null) temp = “default”; push `temp];System.out.println(property);

S

Page 30: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

30

Normalizing '??' !! - with an EBlock

String property = {| String temp = readProperty(“x”); if (temp == null) temp = “default”;| temp|};System.out.println(property);

Page 31: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

31

{| String x_temp = e1; if (x_temp == null) x_temp = e2;| x_temp|}

desugar-coalescing:

'??' in a Normalization Rule

|[ e1 ?? e2 ]| |[

]|with x_temp := <newname> “temp”

Page 32: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

32

{| String x_temp = e1; if (x_temp == null) x_temp = e2;| x_temp|}

|[ e1 ?? e2 ]| |[

]|with x_temp := <newname> “temp”

desugar-coalescing:

Position Information InGenerated Code

Run-time:Exception in thread "main" java.lang.NullPointerException … at Generated.getVertices(Generated.java:10)

Page 33: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

33

trace (e1 ?? e2 @ <File>:<Line>:<Column>) {{| String x_temp = e1; if (x_temp == null) x_temp = e2;| x_temp|}}

|[ e1 ?? e2 ]| |[

]|with x_temp := <newname> “temp”

desugar-coalescing:

Maintaining Position Information With Source Tracing

Run-time:Exception in thread "main" java.lang.NullPointerException … at Shape.getVertices(Shape.java:10)

Page 34: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

34

Traits X

Partial/open classes X

Iterator generators X

Finite State Automata X

Expression-based Xextensions

Class-method / Statement / Expression level

Reflection

Aspect weaving X X X

Page 35: Mixing Source and Bytecode: A Case for Compilation By Normalization (OOPSLA 2008)

• Extension effort must be proportional to the benefits• Black Boxes vs. White Boxes• Don't throw away your primitives• Normalization rules

Mixing Source and Bytecode. A Case for Compilation by Normalization.Lennart C. L. Kats, Martin Bravenboer, and Eelco Visser. In OOPSLA'08.

http://www.program­transformation.org/Stratego/TheDryadCompilerhttp://www.strategoxt.org

Concluding Remarks