compiling java for low-end embedded systems ulrik p. schultz isis/daimi university of aarhus kim...

25
Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming G. Christensen Jørgen L. Knudsen Mjølner Informatics A/S Based on joint work with:

Post on 19-Dec-2015

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Compiling Java for Low-End Embedded Systems

Ulrik P. SchultzISIS/DAIMI

University of Aarhus

Kim BurgaardSystematic Software

Engineering A/S

Flemming G. Christensen

Jørgen L. KnudsenMjølner Informatics

A/S

Based on joint work with:

Page 2: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

2

Motivation Scenario: baggage control system

Family of tiny embedded systems (e.g., ½K RAM, 4K ROM)

Opportunities for software reuse… across hardware platforms across device types

Immediate solution: use C++ Large minimal memory footprint when using

virtuals Unneeded library/framework code included

Page 3: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

3

Motivation Scenario: baggage control system

Family of tiny embedded systems (e.g., ½K RAM, 4K ROM)

Opportunities for software reuse… across hardware platforms across device types

Immediate solution: use C++ Large minimal memory footprint when using

virtuals Unneeded library/framework code included

This talk: use compiled “Java” instead!

Page 4: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

4

Motivation Scenario: baggage control system

Family of tiny embedded systems (e.g., ½K RAM, 4K ROM)

Opportunities for software reuse… across hardware platforms across device types

Immediate solution: use C++ Large minimal memory footprint when using

virtuals Unneeded library/framework code included

Relevance to JavaCard?

Page 5: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

5

Relevance of a Java compiler

JavaCardsoftware

(1) downloadbytecode

Runtime system

(also in Java!)(1) compilestatically

Binaryexecutable

image

Standard approach Alternative approach (this talk)

(2) run on JVM

+JAVA

(2) producecheap cards

(3) executedirectly on card

(c.f. Jean-Jacques Vandewalle, #3)

Page 6: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

6

Outline

1. Low-end embedded systems vs. Java

2. Our solution: JEPES3. Non-intrusive configuration (IDC)4. Stack size analysis5. Experiments6. Conclusion & future work

Page 7: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

7

Low-end embedded systems vs. Java Pervasive computing 8/16 bit devices vs. 32-bit devices:

cheaper, more robust, lower power consumption, more predictable

resource constrained (RAM, ROM, CPU) This talk: 8-bit devices with very little

memory Java pros and cons:

object-oriented, simple, platform independent automatic memory management inefficient execution

Page 8: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

8

Our solution: JEPES Scalable Java execution platform for low-end

embedded systems Language: larger than JavaCard, smaller than

J2ME (different API, no dynamic class loading, static/stack allocation [more], …)

Compiler: ahead-of-time compiler outputs Atmel AVR, Hitachi H8, x86, or Java bytecode; bare-bones execution; space-saving optimizations driven by global analyses [more]; stack size analysis [more]

Hardware-close programming: interface-directed configuration [more]; API with hardware access (streams, interrupts, ...)

Page 9: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

9

Compiler optimizations No pointers => easy to optimize Interprocedural CHA, inlining, stack

allocation, tree shaking, etc. Ghost allocation:

…Stream getStream() { Serial port=new Serial(); port.setBaudRate(9600); port.setHandShake(Serial.HS_HW); return port;}

…Stream s=io.getStream();s.writeByte(b);

• Constant propagation and method inlining allows serial port object to be completely eliminated

Page 10: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

10

Interface-directed configuration: basic idea

Problem: need for extra configuration information (e.g., interrupt handlers need alternate call semantics)

Solution: use Java interfaces to attach semantic properties to classes (Java example: java.io.Serializable)

JEPES example: interrupt handler for vector 0x0E

interface InterruptEHandler {}

InterruptEHandler.java

InterruptEHandler { methods { static void handlerE() { vector = 0x0E; } }}

InterruptEHandler.jid

class Handler implements InterruptEHandler { … static void handlerE() { … }}

Handler.java

Page 11: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

11

Interface-directed configuration Non-intrusive

no special syntax needed specific information declared elsewhere

No “magic” names Used in JEPES for

interrupt handlers and interrupt control [more] assembly macros for direct hardware access forcing ghost allocation and stack allocation

[more] external access …

Page 12: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

12

Memory management1. Heap allocation (not relevant here: ½K RAM)2. Static allocation

3. Stack allocation can be forced using IDC, forced when no GC intuition: type checking

interface StackedIterator extends Iterator, StackAlloc {}

StackAlloc { class { stack-allocate; }}

jepes/lang/StackAlloc.jid

Iterator i = new SetIterator(…);printAll(i);

class SetIterator implementsStackedIterator { … }

static final queue = new Queue(…);

Page 13: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

13

Stack size analysis: what Each stack frame has fixed size (including

stack-allocated objects) Memory consumed at run-time bounded by:

statically allocated objects, plus highest sum of stack frame sizes in

approximated call graph (assuming fixed-size arrays)

But: interrupts are part of the call graph!void process() { Iterator i = …; while(i.hasNext()) { Record c = (Record)i.next(); c.update(…);}

static void handle_INT0() { Context c = …; …}

INT0

Page 14: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

14

Stack size analysis: how

Solution: interrupt-aware analysis [Brylow, Damgaard, Palsberg: ICSE’01]

Caveats: interrupt control is low-level

analysis is complex (although efficient)

void criticalOperation(byte[] data) { int old_mask = System.getInterruptMask(); System.setInterruptMaskXOR(Atmel.INT0); … System.setInterruptMask(old_mask);}

Page 15: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

15

Simple stack size analysis (1)

1. Use IDC to declaratively control interrupts

2. Simple static analysis propagates interrupt enable/disable at method granularity

public class InputProcessor implements DisableINT0 { void criticalOperation(byte[] data) { … }}

process(){ }

criticalOperation(){INT0 disable}

handle_INT0(){global disable}

handle_INT7(){global disable}

INT0

INT7

storeData(){INT7 disable}

Page 16: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

16

Simple stack size analysis (1)

1. Use IDC to declaratively control interrupts

2. Simple static analysis propagates interrupt enable/disable at method granularity

public class InputProcessor implements DisableINT0 { void criticalOperation(byte[] data) { … }}

process(){ }

criticalOperation(){INT0 disable}

handle_INT0(){global disable}

handle_INT7(){global disable}

INT0

INT7

storeData(){INT7 disable}

none disabled

all disabled

INT0 disabled

INT0,INT7 disabled

all disabled

Page 17: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

17

Simple stack size analysis (2)

3. Construct interrupt-aware call graph which includes potential interrupt handler calls

4. Compute stack depth on interrupt-aware call graph (cycle means unbounded)

process(){ }

criticalOperation(){INT0 disable}

handle_INT0(){global disable}

handle_INT7(){global disable}

INT0

INT7

storeData(){INT7 disable}

none disabled

all disabled

INT0 disabled

INT0,INT7 disabled

all disabled

Page 18: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

18

Simple stack size analysis (2)

3. Construct interrupt-aware call graph which includes potential interrupt handler calls

4. Compute stack depth on interrupt-aware call graph (cycle means unbounded)

process(){ }

criticalOperation(){INT0 disable}

handle_INT0(){global disable}

handle_INT7(){global disable}

INT0

INT7

storeData(){INT7 disable}

none disabled

all disabled

INT0 disabled

INT0,INT7 disabled

all disabled

Page 19: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

19

Simple stack size analysis (2)

3. Construct interrupt-aware call graph which includes potential interrupt handler calls

4. Compute stack depth on interrupt-aware call graph (cycle means unbounded)

process(){ }

criticalOperation(){INT0 disable}

handle_INT0(){global disable}

handle_INT7(){global disable}

INT0

INT7

storeData(){INT7 disable}

none disabled

all disabled

INT0 disabled

INT0,INT7 disabled

all disabled

Page 20: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

20

Experiments

0 0,2 0,4 0,6 0,8 1

Lego lift

Valve controller

Bridge (object)

Bridge (static)

EightQueens

Dragon

KvmHttpTest

Native size

Java size

KVM demo(avg. size: 68K)

average: 32.6%

JEPES demo(avg. size: 8K)

native average: 18.9%

footprint: 1511B

ROM, 50B RAM

Page 21: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

21

Future work

Compilation of JavaCard programs Real experiments:

large, realistic programs instantiated from frameworks (Bang & Olufsen A/V infrastructure?)

smart dust More aggressive program

configuration using partial evaluation techniques

Page 22: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

22

Summary JEPES allows ”Java” to be used on a ½K RAM

4K ROM embedded system Interface-directed configuration:

non-intrusive, Java-style assembly macro, interrupt handler, force stack

allocation, … Static memory (stack) size analysis Initial experiments:

CHA essential stack allocation discipline acceptable stack size analysis would benefit from context

sensitivity[Availability: commercial product from Mjølner, GPL version pending]

Page 23: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

23

JEPES concurrency model

Interrupts: event-driven concurrency

Threads: interface to underlying OS (example: LegOS)

Standard thread API for embedded devices? Interaction between threads and interrupts?

System.disableInterrupts();… // critical codeSystem.enableInterrupts();

Statement level Method granularity (declarative)public class IP implements DisableINT7 { void process(byte[] data) { … }}

Page 24: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

24

JDK 1.5 Annotation Types JDK 1.5 supports source-level program

annotations (compiled into class file attributes)

Usable in JEPES for interrupt handlers, interrupts masking

assembly macros, external access, …

public class InputHandler { @DisableInterrupt({Atmel.INT0,Atmel.INT7}) void handle(byte b) { … }}

Page 25: Compiling Java for Low-End Embedded Systems Ulrik P. Schultz ISIS/DAIMI University of Aarhus Kim Burgaard Systematic Software Engineering A/S Flemming

Schultz, ISIS/DAIMI, University of Aarhus CASSIS'04

25

Interface-directed configuration: assembly macros

Assembly macros

High-performance, complement native methods, simulation code easy to implement

class SerialImp implements jepes.io.ISerialImp { byte readByte() { return 0; } void writeByte(byte b) { ; }}

jepes/io/bus/SerialImp.java

Receive: SBI UCR,RXENSBIS USR,RXCRJMP Receive ; Wait until readyIN <@R>,UDR ; Write data to return registerCBI UCR,RXEN ; Clear receive flag on UART

jepes/io/bus/ISerialImp/AVR/readByte__B.asm