1 / 25

Compiling Java for Low-End Embedded Systems

Compiling Java for Low-End Embedded Systems. Based on joint work with:. 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 ++

afya
Télécharger la présentation

Compiling Java for Low-End Embedded Systems

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Compiling Java for Low-End Embedded Systems Based on joint work with:

  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 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! 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? CASSIS'04

  5. Relevance of a Java compiler Standard approach Alternative approach (this talk) (c.f. Jean-Jacques Vandewalle, #3) Runtime system (also in Java!) JavaCard software (1) compile statically (1) download bytecode (2) produce cheap cards Binary executable image +JAVA (2) run on JVM (3) execute directly on card CASSIS'04

  6. Outline • Low-end embedded systems vs. Java • Our solution: JEPES • Non-intrusive configuration (IDC) • Stack size analysis • Experiments • Conclusion & future work 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 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, ...) 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 CASSIS'04

  10. InterruptEHandler.java interface InterruptEHandler {} InterruptEHandler.jid Handler.java InterruptEHandler { methods { static void handlerE() { vector = 0x0E; } } } class Handler implements InterruptEHandler { … static void handlerE() { … } } 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 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 • … CASSIS'04

  12. interface StackedIterator extends Iterator, StackAlloc {} class SetIterator implements StackedIterator { … } Iterator i = new SetIterator(…); printAll(i); jepes/lang/StackAlloc.jid StackAlloc { class { stack-allocate; } } Memory management • Heap allocation (not relevant here: ½K RAM) • Static allocation • Stack allocation • can be forced using IDC, forced when no GC • intuition: type checking static final queue = new Queue(…); 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 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); } CASSIS'04

  15. Simple stack size analysis (1) • Use IDC to declaratively control interrupts • Simple static analysis propagates interrupt enable/disable at method granularity public class InputProcessor implements DisableINT0 { void criticalOperation(byte[] data) { … } } process() { } criticalOperation() {INT0 disable} handle_INT7() {global disable} INT7 handle_INT0() {global disable} INT0 storeData() {INT7 disable} CASSIS'04

  16. Simple stack size analysis (1) • Use IDC to declaratively control interrupts • Simple static analysis propagates interrupt enable/disable at method granularity public class InputProcessor implements DisableINT0 { void criticalOperation(byte[] data) { … } } none disabled INT0 disabled process() { } criticalOperation() {INT0 disable} handle_INT7() {global disable} INT7 all disabled handle_INT0() {global disable} INT0 storeData() {INT7 disable} all disabled CASSIS'04 INT0,INT7 disabled

  17. Simple stack size analysis (2) • Construct interrupt-aware call graph which includes potential interrupt handler calls • Compute stack depth on interrupt-aware call graph (cycle means unbounded) none disabled INT0 disabled process() { } criticalOperation() {INT0 disable} handle_INT7() {global disable} INT7 all disabled handle_INT0() {global disable} INT0 storeData() {INT7 disable} all disabled CASSIS'04 INT0,INT7 disabled

  18. Simple stack size analysis (2) • Construct interrupt-aware call graph which includes potential interrupt handler calls • Compute stack depth on interrupt-aware call graph (cycle means unbounded) none disabled INT0 disabled process() { } criticalOperation() {INT0 disable} handle_INT7() {global disable} INT7 all disabled handle_INT0() {global disable} INT0 storeData() {INT7 disable} all disabled CASSIS'04 INT0,INT7 disabled

  19. Simple stack size analysis (2) • Construct interrupt-aware call graph which includes potential interrupt handler calls • Compute stack depth on interrupt-aware call graph (cycle means unbounded) none disabled INT0 disabled process() { } criticalOperation() {INT0 disable} handle_INT7() {global disable} INT7 all disabled handle_INT0() {global disable} INT0 storeData() {INT7 disable} all disabled CASSIS'04 INT0,INT7 disabled

  20. Experiments KVM demo (avg. size: 68K) average: 32.6% JEPES demo (avg. size: 8K) native average: 18.9% footprint: 1511B ROM, 50B RAM 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 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] 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? Method granularity (declarative) Statement level System.disableInterrupts(); … // critical code System.enableInterrupts(); public class IP implements DisableINT7 { void process(byte[] data) { … } } 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) { … } } CASSIS'04

  25. jepes/io/bus/SerialImp.java class SerialImp implements jepes.io.ISerialImp { byte readByte() { return 0; } void writeByte(byte b) { ; } } jepes/io/bus/ISerialImp/AVR/readByte__B.asm Receive: SBI UCR,RXEN SBIS USR,RXC RJMP Receive ; Wait until ready IN <@R>,UDR ; Write data to return register CBI UCR,RXEN ; Clear receive flag on UART Interface-directed configuration: assembly macros Assembly macros • High-performance, complement native methods, simulation code easy to implement CASSIS'04

More Related