SlideShare a Scribd company logo
1 of 65
Building Languages
    for the JVM
    Charles Oliver Nutter
Me

• Charles Oliver Nutter
• JRuby and JVM guy
• “headius” on most services
• headius@headius.com
Who Was I?

• Java EE architect
 • Successfully!
• Never wrote a parser
• Never wrote a compiler
• But I wanted to learn how...
You

• Java?
• Ruby?
• Python?
• C#?
• Other?
Why Create Languages?

• Nothing is perfect
• New problems need new solutions
• Language design can be fun
• Fame and fortune?
 • Not really.
Why Impl a Language?
• To learn it?
 • Sort of...
• To learn the target platform
 • Definitely!
• Fame and fortune?
 • Well...getting there...
Challenges

• Community
• Platform
• Specifications
• Resources
Community

• Investment in status quo
• Afraid to stand out
• Known quantities
• Everything else sucks
• Gotta get paid!
Platform
• Matching language semantics
 • JVM designed around Java
 • JVM hides underlying platform
• Challenging to use
 • Not bad...C/++ would be way worse
• Community may hate it ;-)
Specifications
•   Incomplete
    •   Ruby had none for years
    •   ...and no complete test suites
•   Difficult to implement
    •   Low level features
    •   Single-implementation quirks
•   Hard or impossible to optimize
Resources

• You gotta eat
• Not much money in language work
• Some parts are hard
• OSS is a necessity
Why JVM?

• Because I am lazy
• Because VMs are *hard*
• Because I can’t be awesome at everything
Ok, Why Really?
• Cross-platform
• Libraries
• Languages
• Memory management
• Tools
• OSS
Cross-platform

• OpenJDK: Linux, Windows, Solaris, OS X,
  xBSD
• J9: Linux, zLinux, AS/400, ...
• HP: OpenVMS, HP/UX, ...
• Dalvik (Android): Linux on ARM, x86
Libraries

• For any need, a dozen libraries
 • And a couple of them are good!
• Cross-platform
• Leading edge
Selection of languages
• Java
• Scala
• Clojure
• JRuby
• Mirah
• Jython, Groovy, Fantom, Kotlin, Ceylon, ...
Memory management

• Best GCs in the world
• Fastest object allocation
• Safe escape hatches like NIO
Tools

• Debugging
• Profiling
• Monitoring
• JVM internals
Open source?

• FOSS reference impl (OpenJDK)
• Mostly OSS libraries
• Heavy OSS culture
• Strong OSS influence in OpenJDK core
Case Study: JRuby
Ruby on the JVM

• All of Ruby’s power and beauty
• Solid VM underneath
• “Just another JVM language”
JVM Language
•   Full interop with Java
    •   Tricky to do...
    •   Very rewarding for 99% case
•   VM concerns solved
    •   No need to write a GC
    •   No need to write a JIT
    •   ...oh, but wait...
More than a JVM
        language
• Use native code where JDK fails us
• Paper over ugly bits like CLASSPATH
• Matching Ruby semantics exactly*
• Push JVM forward too!
Playing with JRuby

• Simple IRB demo
• JRuby on Rails - see Jano’s talk tomorrow
• JRuby performance
• PotC (???)
How did we do it?
JRuby Architecture

• Parser
• Abstract Syntax Tree (AST)
• Intermediate Representation (IR)
• Core classes
• Compiler
Parser

• Port of MRI’s Bison grammar
• “Jay” parser generator for Java
• Hand-written lexer
• Nearly as fast as the C version
 • ...once it gets going
system ~/projects/jruby $ jruby -y -e "1 + 1"
push	 state 0	 value null
reduce	 tate 0	 uncover 0	
       s                  rule (1) $$1 :
goto	 from state 0 to 2
push	 state 2	 value null
lex	 tate 2	 reading tIDENTIFIER	 value Token { Value=load,
   s
Position=file:/Users/headius/projects/jruby/lib/jruby.jar!/
jruby/kernel.rb:6}
shift	from state 2 to 33
push	 state 33	 value Token { Value=load, Position=file:/Users/
headius/projects/jruby/lib/jruby.jar!/jruby/kernel.rb:6}
lex	 tate 33	 reading tSTRING_BEG	 value Token { Value=',
   s
Position=file:/Users/headius/projects/jruby/lib/jruby.jar!/
jruby/kernel.rb:6}
reduce	 tate 33	 uncover 2	
       s                  rule (487) operation : tIDENTIFIER
goto	 from state 2 to 62
push	 state 62	 value Token { Value=load, Position=file:/Users/
headius/projects/jruby/lib/jruby.jar!/jruby/kernel.rb:6}
reduce	 tate 62	 uncover 62	 rule (252) $$6 :
       s
system ~/projects/jruby $ jruby -y -e "1 + 1"
push	 state 0	 value null
reduce	 tate 0	 uncover 0	
       s                  rule (1) $$1 :
goto	 from state 0 to 2
push	 state 2	 value null
lex	 tate 2	 reading tIDENTIFIER	 value Token { Value=load,
   s
Position=file:/Users/headius/projects/jruby/lib/jruby.jar!/
jruby/kernel.rb:6}
shift	from state 2 to 33

         You will never need this.
push	 state 33	 value Token { Value=load, Position=file:/Users/
headius/projects/jruby/lib/jruby.jar!/jruby/kernel.rb:6}
lex	 tate 33	 reading tSTRING_BEG	 value Token { Value=',
   s
Position=file:/Users/headius/projects/jruby/lib/jruby.jar!/
jruby/kernel.rb:6}
reduce	 tate 33	 uncover 2	
       s                  rule (487) operation : tIDENTIFIER
goto	 from state 2 to 62
push	 state 62	 value Token { Value=load, Position=file:/Users/
headius/projects/jruby/lib/jruby.jar!/jruby/kernel.rb:6}
reduce	 tate 62	 uncover 62	 rule (252) $$6 :
       s
public class RubyYaccLexer {
    public static final Encoding UTF8_ENCODING = UTF8Encoding.INSTANCE;
    public static final Encoding USASCII_ENCODING = USASCIIEncoding.INSTANCE;
    public static final Encoding ASCII8BIT_ENCODING = ASCIIEncoding.INSTANCE;
    
    private static ByteList END_MARKER = new ByteList(new byte[] {'_', 'E', 'N', 'D', '_', '_'});
    private static ByteList BEGIN_DOC_MARKER = new ByteList(new byte[] {'b', 'e', 'g', 'i', 'n'});
    private static ByteList END_DOC_MARKER = new ByteList(new byte[] {'e', 'n', 'd'});
    private static final HashMap<String, Keyword> map;

    static {
        map = new HashMap<String, Keyword>();

        map.put("end", Keyword.END);
        map.put("else", Keyword.ELSE);
        map.put("case", Keyword.CASE);
        map.put("ensure", Keyword.ENSURE);
        map.put("module", Keyword.MODULE);
        map.put("elsif", Keyword.ELSIF);
        map.put("def", Keyword.DEF);
        map.put("rescue", Keyword.RESCUE);
        map.put("not", Keyword.NOT);
        map.put("then", Keyword.THEN);
        map.put("yield", Keyword.YIELD);
        map.put("for", Keyword.FOR);
        map.put("self", Keyword.SELF);
        map.put("false", Keyword.FALSE);
    public enum Keyword {
        END ("end", Tokens.kEND, Tokens.kEND, LexState.EXPR_END),
        ELSE ("else", Tokens.kELSE, Tokens.kELSE, LexState.EXPR_BEG),
        CASE ("case", Tokens.kCASE, Tokens.kCASE, LexState.EXPR_BEG),
        ENSURE ("ensure", Tokens.kENSURE, Tokens.kENSURE, LexState.EXPR_BEG),
        MODULE ("module", Tokens.kMODULE, Tokens.kMODULE, LexState.EXPR_BEG),
        ELSIF ("elsif", Tokens.kELSIF, Tokens.kELSIF, LexState.EXPR_BEG),
        DEF ("def", Tokens.kDEF, Tokens.kDEF, LexState.EXPR_FNAME),
        RESCUE ("rescue", Tokens.kRESCUE, Tokens.kRESCUE_MOD, LexState.EXPR_MID),
        NOT ("not", Tokens.kNOT, Tokens.kNOT, LexState.EXPR_BEG),
        THEN ("then", Tokens.kTHEN, Tokens.kTHEN, LexState.EXPR_BEG),
        YIELD ("yield", Tokens.kYIELD, Tokens.kYIELD, LexState.EXPR_ARG),
        FOR ("for", Tokens.kFOR, Tokens.kFOR, LexState.EXPR_BEG),
        SELF ("self", Tokens.kSELF, Tokens.kSELF, LexState.EXPR_END),
        FALSE ("false", Tokens.kFALSE, Tokens.kFALSE, LexState.EXPR_END),
        RETRY ("retry", Tokens.kRETRY, Tokens.kRETRY, LexState.EXPR_END),
        RETURN ("return", Tokens.kRETURN, Tokens.kRETURN, LexState.EXPR_MID),
        TRUE ("true", Tokens.kTRUE, Tokens.kTRUE, LexState.EXPR_END),
        IF ("if", Tokens.kIF, Tokens.kIF_MOD, LexState.EXPR_BEG),
        DEFINED_P ("defined?", Tokens.kDEFINED, Tokens.kDEFINED, LexState.EXPR_ARG),
    private int yylex() throws IOException {
        int c;
        boolean spaceSeen = false;
        boolean commandState;
        
        if (lex_strterm != null) {
            int tok = lex_strterm.parseString(this, src);
            if (tok == Tokens.tSTRING_END || tok == Tokens.tREGEXP_END) {
                lex_strterm = null;
                setState(LexState.EXPR_END);
            }

            return tok;
        }

        commandState = commandStart;
        commandStart = false;

        loop: for(;;) {
            c = src.read();
            switch(c) {
            case '<':
                return   lessThan(spaceSeen);
            case '>':
                return   greaterThan();
            case '"':
                return   doubleQuote();
            case '`':
                return   backtick(commandState);
            case ''':
                return   singleQuote();
            case '?':
                return   questionMark();
            case '&':
                return   ampersand(spaceSeen);
            case '|':
                return   pipe();
            case '+':
                return   plus(spaceSeen);
    private int lessThan(boolean spaceSeen) throws IOException {
        int c = src.read();
        if (c == '<' && lex_state != LexState.EXPR_DOT && lex_state !=
LexState.EXPR_CLASS &&
                !isEND() && (!isARG() || spaceSeen)) {
            int tok = hereDocumentIdentifier();
            
            if (tok != 0) return tok;
        }
        
        determineExpressionState();
        
        switch (c) {
        case '=':
            if ((c = src.read()) == '>') {
                yaccValue = new Token("<=>", getPosition());
                return Tokens.tCMP;
%%
program       : {
                  lexer.setState(LexState.EXPR_BEG);
                  support.initTopLocalVariables();
              } top_compstmt {
  // ENEBO: Removed !compile_for_eval which probably is to reduce
warnings
                  if ($2 != null) {
                      /* last expression should not be void */
                      if ($2 instanceof BlockNode) {
                          support.checkUselessStatement($<BlockNod
e>2.getLast());
                      } else {
                          support.checkUselessStatement($2);
                      }
                  }
                  support.getResult().setAST(support.addRootNode($
2, support.getPosition($2)));
              }
stmt            : kALIAS fitem {
                    lexer.setState(LexState.EXPR_FNAME);
                } fitem {
                    $$ = support.newAlias($1.getPosition(), $2, $4);
                }
                | kALIAS tGVAR tGVAR {
                    $$ = new VAliasNode($1.getPosition(), (String)
$2.getValue(), (String) $3.getValue());
                }
                | kALIAS tGVAR tBACK_REF {
                    $$ = new VAliasNode($1.getPosition(), (String)
$2.getValue(), "$" + $<BackRefNode>3.getType());
                }
                | kALIAS tGVAR tNTH_REF {
                    support.yyerror("can't make alias for the number
variables");
                }
                | kUNDEF undef_list {
                    $$ = $2;
                }
                | stmt kIF_MOD expr_value {
                    $$ = new IfNode(support.getPosition($1),
support.getConditionNode($3), $1, null);
                }
  public Object yyparse (RubyYaccLexer yyLex) throws java.io.IOException {
    if (yyMax <= 0) yyMax = 256;"" " // initial size
    int yyState = 0, yyStates[] = new int[yyMax];" // state stack
    Object yyVal = null, yyVals[] = new Object[yyMax];" // value stack
    int yyToken = -1;" " " " " // current input
    int yyErrorFlag = 0;" " " " // #tokens to shift

    yyLoop: for (int yyTop = 0;; ++ yyTop) {
      if (yyTop >= yyStates.length) {" " " // dynamically increase
        int[] i = new int[yyStates.length+yyMax];
        System.arraycopy(yyStates, 0, i, 0, yyStates.length);
        yyStates = i;
        Object[] o = new Object[yyVals.length+yyMax];
        System.arraycopy(yyVals, 0, o, 0, yyVals.length);
        yyVals = o;
      }
      yyStates[yyTop] = yyState;
      yyVals[yyTop] = yyVal;
      if (yydebug != null) yydebug.push(yyState, yyVal);
        if (state == null) {
            yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]);
        } else {
            yyVal = state.execute(support, lexer, yyVal, yyVals, yyTop);
        }
states[23] = new ParserState() {
  public Object execute(ParserSupport support, RubyYaccLexer lexer, Object
yyVal, Object[] yyVals, int yyTop) {
                    yyVal = new
IfNode(support.getPosition(((Node)yyVals[-2+yyTop])),
support.getConditionNode(((Node)yyVals[0+yyTop])), ((Node)yyVals[-2+yyTop]),
null);
    return yyVal;
  }
};
                  Never look at this.
states[24] = new ParserState() {
  public Object execute(ParserSupport support, RubyYaccLexer lexer, Object
yyVal, Object[] yyVals, int yyTop) {
                    yyVal = new
IfNode(support.getPosition(((Node)yyVals[-2+yyTop])),
support.getConditionNode(((Node)yyVals[0+yyTop])), null,
((Node)yyVals[-2+yyTop]));
    return yyVal;
  }
};
AST

• Interpreted directly
• Specialized in places
• Large and rich
$ ast -e "a = true; if a; 2; else; 3; end"
AST:
RootNode 0
  BlockNode 0
     NewlineNode 0
       LocalAsgnNode:a 0
         TrueNode:true 0
     NewlineNode 0
       IfNode 0
         LocalVarNode:a 0
         NewlineNode 0
           FixnumNode 0
         NewlineNode 0
           FixnumNode 0
public class IfNode extends Node {
    private final Node condition;
    private final Node thenBody;
    private final Node elseBody;

    public IfNode(ISourcePosition position, Node   condition, Node thenBody,
Node elseBody) {
        super(position);
        
        assert condition != null : "condition is   not null";
//        assert thenBody != null : "thenBody is   not null";
//        assert elseBody != null : "elseBody is   not null";
        
        this.condition = condition;
        this.thenBody = thenBody;
        this.elseBody = elseBody;
    }
    @Override
    public IRubyObject interpret(Ruby runtime, ThreadContext context,
IRubyObject self, Block aBlock) {
        ISourcePosition position = getPosition();

        context.setFile(position.getFile());
        context.setLine(position.getStartLine());

        IRubyObject result =
             condition.interpret(runtime, context, self, aBlock);
        
        if (result.isTrue()) {
            return thenBody == null ?
                 runtime.getNil() :
                 thenBody.interpret(runtime, context, self, aBlock);
        } else {
            return elseBody == null ?
                 runtime.getNil() :
                 elseBody.interpret(runtime, context, self, aBlock);
        }
    }
IR (future work)

• Control flow graph
• Ruby-specific instruction set
• Optimizing compiler
• Ruby-level optimizations
jruby -e “1 + 1”
2011-11-04T05:23:09.375-03:00: IR_Printer:
  instrs:
  0	 %self = recv_self
  1	 %block(0:0) = recv_closure
  2	 file_name(-e)
  3	 line_num(0)
  4	 %v_0 = call(+, 1:fixnum, [1:fixnum])
  5	 return(%v_0)
2011-11-04T05:23:09.375-03:00: IR_Printer:
  live variables:
    %v_0: 4-5
a = 1; while a < 10; puts a; a += 1; end
2011-11-04T05:25:23.517-03:00: IR_Printer:
  instrs:
  0	%self = recv_self
  1	%block(0:0) = recv_closure
  2	file_name(-e)
  3	line_num(0)
  4	a(0:1) = 1:fixnum
  5	_LOOP_BEGIN_0:
  6	%v_1 = call(<, a(0:1), [10:fixnum])
  7	beq(%v_1, true, _ITER_BEGIN_0)
  8	%v_0 = nil
  9	jump _LOOP_END_0
  10	   _ITER_BEGIN_0:
  11	   %v_2 = call(puts, %self, [a(0:1)])
  12	   %v_3 = call(+, a(0:1), [1:fixnum])
  13	   a(0:1) = copy(%v_3)
  14	   %v_0 = copy(%v_3)
  15	   thread_poll
  16	   _ITER_END_0:
  17	   jump _LOOP_BEGIN_0
  18	   _LOOP_END_0:
  19	   return(%v_0)
2011-11-04T05:25:23.517-03:00: IR_Printer:
  live variables:
    %v_0: 8-19
    %v_1: 6-7
    %v_3: 12-14
2011-11-04T05:25:23.518-03:00: IRScope: ################## After
CFG Linearize##################
2011-11-04T05:25:23.518-03:00: IR_Printer:
----------------------------------------
2011-11-04T05:25:23.518-03:00: IR_Printer: Method [root]:
[script]:-e
2011-11-04T05:25:23.518-03:00: IR_Printer:
Graph:
BB [4:LBL_3]:>[7], <[3]
BB [1:LBL_1]:>[8,2]
BB [2:LBL_2]:>[3], <[1]
BB [7:_LOOP_END_0]:>[8], <[4]
BB [8:LBL_4]:<[1,7]
BB [3:_LOOP_BEGIN_0]:>[5,4], <[6,2]
BB [6:_ITER_END_0]:>[3], <[5]
BB [5:_ITER_BEGIN_0]:>[6], <[3]
2011-11-04T05:25:23.517-03:00: IR_Printer:
  instrs:
  0	%self = recv_self
  1	%block(0:0) = recv_closure
  2	file_name(-e)
  3	line_num(0)
  4	a(0:1) = 1:fixnum
  5	_LOOP_BEGIN_0:
  6	%v_1 = call(<, a(0:1), [10:fixnum])
  7	beq(%v_1, true, _ITER_BEGIN_0)
  8	%v_0 = nil
  9	jump _LOOP_END_0
  10	   _ITER_BEGIN_0:
  11	   %v_2 = call(puts, %self, [a(0:1)])
  12	   %v_3 = call(+, a(0:1), [1:fixnum])
  13	   a(0:1) = copy(%v_3)
  14	   %v_0 = copy(%v_3)
  15	   thread_poll
  16	   _ITER_END_0:
  17	   jump _LOOP_BEGIN_0
  18	   _LOOP_END_0:
  19	   return(%v_0)
2011-11-04T05:25:23.517-03:00: IR_Printer:
  live variables:
    %v_0: 8-19
    %v_1: 6-7
    %v_3: 12-14
2011-11-04T05:25:23.518-03:00: IR_Printer:
Instructions:
BB [4:LBL_3]
	 %v_0 = nil
BB [1:LBL_1]
BB [2:LBL_2]
	 %self = recv_self
	 %block(0:0) = recv_closure
	 file_name(-e)
	 line_num(0)
	 a(0:1) = 1:fixnum
BB [7:_LOOP_END_0]
	 return(%v_0)
BB [8:LBL_4]
	 return(nil)
Core classes

• Mostly Java-based
• Leverage JDK where possible
• Work around JDK where necessary
• Use Ruby when possible
@JRubyClass(name="Fixnum", parent="Integer", include="Precision")
public class RubyFixnum extends RubyInteger {
    
    public static RubyClass createFixnumClass(Ruby runtime) {
        RubyClass fixnum = runtime.defineClass("Fixnum", runtime.getInteger(),
                ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
    @JRubyMethod(name = "+")
    public IRubyObject op_plus(ThreadContext context, IRubyObject other) {
        if (other instanceof RubyFixnum) {
            return addFixnum(context, (RubyFixnum)other);
        }
        return addOther(context, other);
    }
    private IRubyObject addFixnum(ThreadContext context, RubyFixnum other) {
        long otherValue = other.value;
        long result = value + otherValue;
        if (additionOverflowed(value, otherValue, result)) {
            return addAsBignum(context, other);
        }
        return newFixnum(context.getRuntime(), result);
    }
Compiler

• AST-walking
• ASM bytecode library
• Minimal optimizations
• Invokedynamic really helps
• IR offers new opportunities
jruby --bytecode -e “1 + 1”
ALOAD 0
INVOKEVIRTUAL ruby/__dash_e__.getCallSite0
ALOAD 1
ALOAD 2
ALOAD 1
GETFIELD org/jruby/runtime/ThreadContext.runtime
INVOKESTATIC org/jruby/RubyFixnum.one
LDC 1
INVOKEVIRTUAL org/jruby/runtime/CallSite.call
ARETURN
public class ASTCompiler {
    private boolean isAtRoot = true;

    public void compileBody(Node node, BodyCompiler context, boolean expr) {
        Node oldBodyNode = currentBodyNode;
        currentBodyNode = node;
        compile(node, context, expr);
        currentBodyNode = oldBodyNode;
    }
    
    public void compile(Node node, BodyCompiler context, boolean expr) {
        if (node == null) {
            if (expr) context.loadNil();
            return;
        }
        switch (node.getNodeType()) {
            case ALIASNODE:
                compileAlias((AliasNode) node, context, expr);
                break;
            case ANDNODE:
                compileAnd(node, context, expr);
                break;
    public void compileIf(Node node, BodyCompiler context, final boolean expr) {
        final IfNode ifNode = (IfNode) node;

        // optimizations if we know ahead of time it will always be true or false
        Node actualCondition = ifNode.getCondition();
        while (actualCondition instanceof NewlineNode) {
            actualCondition = ((NewlineNode)actualCondition).getNextNode();
        }

        if (actualCondition.getNodeType().alwaysTrue()) {
            // compile condition as non-expr and just compile "then" body
            compile(actualCondition, context, false);
            compile(ifNode.getThenBody(), context, expr);
        } else if (actualCondition.getNodeType().alwaysFalse()) {
            // always false or nil
            compile(ifNode.getElseBody(), context, expr);
        } else {
            BranchCallback trueCallback = new BranchCallback() {
                public void branch(BodyCompiler context) {
                    if (ifNode.getThenBody() != null) {
                        compile(ifNode.getThenBody(), context, expr);
                    } else {
                        if (expr) context.loadNil();
                    }
                }
            };

            BranchCallback falseCallback = new BranchCallback() {
                public void branch(BodyCompiler context) {
                    if (ifNode.getElseBody() != null) {
                        compile(ifNode.getElseBody(), context, expr);
                    } else {
                        if (expr) context.loadNil();
                    }
                }
            };
            
            // normal
            compile(actualCondition, context, true);
            context.performBooleanBranch(trueCallback, falseCallback);
        }
public abstract class BaseBodyCompiler implements BodyCompiler {
    protected SkinnyMethodAdapter method;
    protected VariableCompiler variableCompiler;
    protected InvocationCompiler invocationCompiler;
    protected int argParamCount;
    protected Label[] currentLoopLabels;
    protected Label scopeStart = new Label();
    protected Label scopeEnd = new Label();
    protected Label redoJump;
    protected boolean inNestedMethod = false;
    private int lastLine = -1;
    private int lastPositionLine = -1;
    protected StaticScope scope;
    protected ASTInspector inspector;
    protected String methodName;
    protected String rubyName;
    protected StandardASMCompiler script;
    public void performBooleanBranch(BranchCallback trueBranch,
                                      BranchCallback falseBranch) {
        Label afterJmp = new Label();
        Label falseJmp = new Label();

        // call isTrue on the result
        isTrue();

        method.ifeq(falseJmp); // EQ == 0 (i.e. false)
        trueBranch.branch(this);
        method.go_to(afterJmp);

        // FIXME: optimize for cases where we have no false branch
        method.label(falseJmp);
        falseBranch.branch(this);

        method.label(afterJmp);
    }
More Demos!
• JRuby + JVM flags
• JRuby concurrency
• Invokedynamic (Java 7)
• Redcar Editor
• Ruboto (Android)
• VisualVM
Gracias!

• Charles Oliver Nutter
• “headius” on most services
• headius@headius.com

More Related Content

What's hot

JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015Charles Nutter
 
Fast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaFast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaCharles Nutter
 
Type Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signaturesType Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signaturesmametter
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesCharles Nutter
 
TRICK2015 results
TRICK2015 resultsTRICK2015 results
TRICK2015 resultsmametter
 
Over 9000: JRuby in 2015
Over 9000: JRuby in 2015Over 9000: JRuby in 2015
Over 9000: JRuby in 2015Charles Nutter
 
JRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMJRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMCharles Nutter
 
Slot Composition
Slot CompositionSlot Composition
Slot CompositionESUG
 
A Taste of Clojure
A Taste of ClojureA Taste of Clojure
A Taste of ClojureDavid Leung
 
JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015Charles Nutter
 
Ahead-Of-Time Compilation of Java Applications
Ahead-Of-Time Compilation of Java ApplicationsAhead-Of-Time Compilation of Java Applications
Ahead-Of-Time Compilation of Java ApplicationsNikita Lipsky
 
Java 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevJava 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevMattias Karlsson
 
The State of Managed Runtimes 2013, by Attila Szegedi
The State of Managed Runtimes 2013, by Attila SzegediThe State of Managed Runtimes 2013, by Attila Szegedi
The State of Managed Runtimes 2013, by Attila SzegediZeroTurnaround
 
Using Java from Ruby with JRuby IRB
Using Java from Ruby with JRuby IRBUsing Java from Ruby with JRuby IRB
Using Java from Ruby with JRuby IRBHiro Asari
 
Dockersh and a brief intro to the docker internals
Dockersh and a brief intro to the docker internalsDockersh and a brief intro to the docker internals
Dockersh and a brief intro to the docker internalsTomas Doran
 
Hybrid concurrency patterns
Hybrid concurrency patternsHybrid concurrency patterns
Hybrid concurrency patternsKyle Drake
 

What's hot (20)

JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015
 
Guild Prototype
Guild PrototypeGuild Prototype
Guild Prototype
 
Fast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaFast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible Java
 
Type Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signaturesType Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signatures
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for Dummies
 
PHP7
PHP7PHP7
PHP7
 
JRuby: The Hard Parts
JRuby: The Hard PartsJRuby: The Hard Parts
JRuby: The Hard Parts
 
TRICK2015 results
TRICK2015 resultsTRICK2015 results
TRICK2015 results
 
Over 9000: JRuby in 2015
Over 9000: JRuby in 2015Over 9000: JRuby in 2015
Over 9000: JRuby in 2015
 
JRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMJRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVM
 
Slot Composition
Slot CompositionSlot Composition
Slot Composition
 
Slot Composition
Slot CompositionSlot Composition
Slot Composition
 
A Taste of Clojure
A Taste of ClojureA Taste of Clojure
A Taste of Clojure
 
JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015
 
Ahead-Of-Time Compilation of Java Applications
Ahead-Of-Time Compilation of Java ApplicationsAhead-Of-Time Compilation of Java Applications
Ahead-Of-Time Compilation of Java Applications
 
Java 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevJava 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from Oredev
 
The State of Managed Runtimes 2013, by Attila Szegedi
The State of Managed Runtimes 2013, by Attila SzegediThe State of Managed Runtimes 2013, by Attila Szegedi
The State of Managed Runtimes 2013, by Attila Szegedi
 
Using Java from Ruby with JRuby IRB
Using Java from Ruby with JRuby IRBUsing Java from Ruby with JRuby IRB
Using Java from Ruby with JRuby IRB
 
Dockersh and a brief intro to the docker internals
Dockersh and a brief intro to the docker internalsDockersh and a brief intro to the docker internals
Dockersh and a brief intro to the docker internals
 
Hybrid concurrency patterns
Hybrid concurrency patternsHybrid concurrency patterns
Hybrid concurrency patterns
 

Similar to Charles nutter star techconf 2011 - jvm languages

Real-world polyglot programming on the JVM - Ben Summers (ONEIS)
Real-world polyglot programming on the JVM  - Ben Summers (ONEIS)Real-world polyglot programming on the JVM  - Ben Summers (ONEIS)
Real-world polyglot programming on the JVM - Ben Summers (ONEIS)jaxLondonConference
 
GOTO Night with Charles Nutter Slides
GOTO Night with Charles Nutter SlidesGOTO Night with Charles Nutter Slides
GOTO Night with Charles Nutter SlidesAlexandra Masterson
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Mario Camou Riveroll
 
Практики применения JRuby
Практики применения JRubyПрактики применения JRuby
Практики применения JRuby.toster
 
Concurrency and Multithreading Demistified - Reversim Summit 2014
Concurrency and Multithreading Demistified - Reversim Summit 2014Concurrency and Multithreading Demistified - Reversim Summit 2014
Concurrency and Multithreading Demistified - Reversim Summit 2014Haim Yadid
 
The Enterprise Strikes Back
The Enterprise Strikes BackThe Enterprise Strikes Back
The Enterprise Strikes BackBurke Libbey
 
Clojure - An Introduction for Lisp Programmers
Clojure - An Introduction for Lisp ProgrammersClojure - An Introduction for Lisp Programmers
Clojure - An Introduction for Lisp Programmerselliando dias
 
JRuby - The Best of Java and Ruby
JRuby - The Best of Java and RubyJRuby - The Best of Java and Ruby
JRuby - The Best of Java and RubyEvgeny Rahman
 
Introduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platformIntroduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platformEastBanc Tachnologies
 
Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013Charles Nutter
 
Introduction to JRuby
Introduction to JRubyIntroduction to JRuby
Introduction to JRubyajuckel
 
Tampering with JavaScript
Tampering with JavaScriptTampering with JavaScript
Tampering with JavaScriptBoy Baukema
 
RubyStack: the easiest way to deploy Ruby on Rails
RubyStack: the easiest way to deploy Ruby on RailsRubyStack: the easiest way to deploy Ruby on Rails
RubyStack: the easiest way to deploy Ruby on Railselliando dias
 
The Future of Node - @rvagg - NodeConf Christchurch 2015
The Future of Node - @rvagg - NodeConf Christchurch 2015The Future of Node - @rvagg - NodeConf Christchurch 2015
The Future of Node - @rvagg - NodeConf Christchurch 2015rvagg
 
Ruby Midwest 2010 jRuby by Charles Nutter
Ruby Midwest 2010 jRuby by Charles NutterRuby Midwest 2010 jRuby by Charles Nutter
Ruby Midwest 2010 jRuby by Charles NutterSteven Chau
 

Similar to Charles nutter star techconf 2011 - jvm languages (20)

Real-world polyglot programming on the JVM - Ben Summers (ONEIS)
Real-world polyglot programming on the JVM  - Ben Summers (ONEIS)Real-world polyglot programming on the JVM  - Ben Summers (ONEIS)
Real-world polyglot programming on the JVM - Ben Summers (ONEIS)
 
GOTO Night with Charles Nutter Slides
GOTO Night with Charles Nutter SlidesGOTO Night with Charles Nutter Slides
GOTO Night with Charles Nutter Slides
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?
 
Children of Ruby
Children of RubyChildren of Ruby
Children of Ruby
 
Практики применения JRuby
Практики применения JRubyПрактики применения JRuby
Практики применения JRuby
 
Concurrency and Multithreading Demistified - Reversim Summit 2014
Concurrency and Multithreading Demistified - Reversim Summit 2014Concurrency and Multithreading Demistified - Reversim Summit 2014
Concurrency and Multithreading Demistified - Reversim Summit 2014
 
Scala Introduction
Scala IntroductionScala Introduction
Scala Introduction
 
The Enterprise Strikes Back
The Enterprise Strikes BackThe Enterprise Strikes Back
The Enterprise Strikes Back
 
Clojure - An Introduction for Lisp Programmers
Clojure - An Introduction for Lisp ProgrammersClojure - An Introduction for Lisp Programmers
Clojure - An Introduction for Lisp Programmers
 
JRuby - The Best of Java and Ruby
JRuby - The Best of Java and RubyJRuby - The Best of Java and Ruby
JRuby - The Best of Java and Ruby
 
Introduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platformIntroduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platform
 
Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013
 
Introduction to JRuby
Introduction to JRubyIntroduction to JRuby
Introduction to JRuby
 
Tampering with JavaScript
Tampering with JavaScriptTampering with JavaScript
Tampering with JavaScript
 
Ruby on the JVM
Ruby on the JVMRuby on the JVM
Ruby on the JVM
 
RubyStack: the easiest way to deploy Ruby on Rails
RubyStack: the easiest way to deploy Ruby on RailsRubyStack: the easiest way to deploy Ruby on Rails
RubyStack: the easiest way to deploy Ruby on Rails
 
IJTC%202009%20JRuby
IJTC%202009%20JRubyIJTC%202009%20JRuby
IJTC%202009%20JRuby
 
IJTC%202009%20JRuby
IJTC%202009%20JRubyIJTC%202009%20JRuby
IJTC%202009%20JRuby
 
The Future of Node - @rvagg - NodeConf Christchurch 2015
The Future of Node - @rvagg - NodeConf Christchurch 2015The Future of Node - @rvagg - NodeConf Christchurch 2015
The Future of Node - @rvagg - NodeConf Christchurch 2015
 
Ruby Midwest 2010 jRuby by Charles Nutter
Ruby Midwest 2010 jRuby by Charles NutterRuby Midwest 2010 jRuby by Charles Nutter
Ruby Midwest 2010 jRuby by Charles Nutter
 

More from StarTech Conference

Mike hostetler - jQuery knowledge append to you
Mike hostetler - jQuery knowledge append to youMike hostetler - jQuery knowledge append to you
Mike hostetler - jQuery knowledge append to youStarTech Conference
 
Stephen Anderson - Como construimos e hicimos crecer una empresa de consultor...
Stephen Anderson - Como construimos e hicimos crecer una empresa de consultor...Stephen Anderson - Como construimos e hicimos crecer una empresa de consultor...
Stephen Anderson - Como construimos e hicimos crecer una empresa de consultor...StarTech Conference
 
Scott Chacon - Cuento de tres árboles
Scott Chacon - Cuento de tres árbolesScott Chacon - Cuento de tres árboles
Scott Chacon - Cuento de tres árbolesStarTech Conference
 
Robert Nyman - HTML5 apis where no man has gone before startechconf
Robert Nyman - HTML5 apis where no man has gone before startechconfRobert Nyman - HTML5 apis where no man has gone before startechconf
Robert Nyman - HTML5 apis where no man has gone before startechconfStarTech Conference
 
Markos calderon lecciones aprendidas del desarrollo de un sistema de web co...
Markos calderon   lecciones aprendidas del desarrollo de un sistema de web co...Markos calderon   lecciones aprendidas del desarrollo de un sistema de web co...
Markos calderon lecciones aprendidas del desarrollo de un sistema de web co...StarTech Conference
 
Ravi Mynampaty - developing findability standards
Ravi Mynampaty - developing findability standardsRavi Mynampaty - developing findability standards
Ravi Mynampaty - developing findability standardsStarTech Conference
 
Abraham Barrera - dev-cross-mobile
Abraham Barrera - dev-cross-mobileAbraham Barrera - dev-cross-mobile
Abraham Barrera - dev-cross-mobileStarTech Conference
 
Eduardo Silva - monkey http-server everywhere
Eduardo Silva - monkey http-server everywhereEduardo Silva - monkey http-server everywhere
Eduardo Silva - monkey http-server everywhereStarTech Conference
 
Rey Bango - HTML5: polyfills and shims
Rey Bango -  HTML5: polyfills and shimsRey Bango -  HTML5: polyfills and shims
Rey Bango - HTML5: polyfills and shimsStarTech Conference
 
Tom Preston Werner - Optimize for happiness
Tom Preston Werner -  Optimize for happinessTom Preston Werner -  Optimize for happiness
Tom Preston Werner - Optimize for happinessStarTech Conference
 
Mark ramm To relate or not to relate
Mark ramm   To relate or not to relateMark ramm   To relate or not to relate
Mark ramm To relate or not to relateStarTech Conference
 

More from StarTech Conference (19)

Mike hostetler - jQuery knowledge append to you
Mike hostetler - jQuery knowledge append to youMike hostetler - jQuery knowledge append to you
Mike hostetler - jQuery knowledge append to you
 
Luis Meijueiro - Open Data
Luis Meijueiro - Open DataLuis Meijueiro - Open Data
Luis Meijueiro - Open Data
 
Stephen Anderson - Como construimos e hicimos crecer una empresa de consultor...
Stephen Anderson - Como construimos e hicimos crecer una empresa de consultor...Stephen Anderson - Como construimos e hicimos crecer una empresa de consultor...
Stephen Anderson - Como construimos e hicimos crecer una empresa de consultor...
 
Jonathan snook - fake-it
Jonathan snook - fake-itJonathan snook - fake-it
Jonathan snook - fake-it
 
Scott Chacon - Cuento de tres árboles
Scott Chacon - Cuento de tres árbolesScott Chacon - Cuento de tres árboles
Scott Chacon - Cuento de tres árboles
 
T.Pollak y C.Yaconi - Prey
T.Pollak y C.Yaconi - PreyT.Pollak y C.Yaconi - Prey
T.Pollak y C.Yaconi - Prey
 
Jano Gonzalez - jruby
Jano Gonzalez - jrubyJano Gonzalez - jruby
Jano Gonzalez - jruby
 
Pedro Fuentes - star techconf
Pedro Fuentes - star techconfPedro Fuentes - star techconf
Pedro Fuentes - star techconf
 
Robert Nyman - HTML5 apis where no man has gone before startechconf
Robert Nyman - HTML5 apis where no man has gone before startechconfRobert Nyman - HTML5 apis where no man has gone before startechconf
Robert Nyman - HTML5 apis where no man has gone before startechconf
 
Markos calderon lecciones aprendidas del desarrollo de un sistema de web co...
Markos calderon   lecciones aprendidas del desarrollo de un sistema de web co...Markos calderon   lecciones aprendidas del desarrollo de un sistema de web co...
Markos calderon lecciones aprendidas del desarrollo de un sistema de web co...
 
Ravi Mynampaty - developing findability standards
Ravi Mynampaty - developing findability standardsRavi Mynampaty - developing findability standards
Ravi Mynampaty - developing findability standards
 
Caridy patino - node-js
Caridy patino - node-jsCaridy patino - node-js
Caridy patino - node-js
 
Abraham Barrera - dev-cross-mobile
Abraham Barrera - dev-cross-mobileAbraham Barrera - dev-cross-mobile
Abraham Barrera - dev-cross-mobile
 
Eduardo Silva - monkey http-server everywhere
Eduardo Silva - monkey http-server everywhereEduardo Silva - monkey http-server everywhere
Eduardo Silva - monkey http-server everywhere
 
Stephanie Rewis - css-startech
Stephanie Rewis -  css-startechStephanie Rewis -  css-startech
Stephanie Rewis - css-startech
 
Rey Bango - HTML5: polyfills and shims
Rey Bango -  HTML5: polyfills and shimsRey Bango -  HTML5: polyfills and shims
Rey Bango - HTML5: polyfills and shims
 
Tom Preston Werner - Optimize for happiness
Tom Preston Werner -  Optimize for happinessTom Preston Werner -  Optimize for happiness
Tom Preston Werner - Optimize for happiness
 
Mark ramm To relate or not to relate
Mark ramm   To relate or not to relateMark ramm   To relate or not to relate
Mark ramm To relate or not to relate
 
Greg rewis move-itsession
Greg rewis move-itsessionGreg rewis move-itsession
Greg rewis move-itsession
 

Recently uploaded

Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 

Recently uploaded (20)

Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 

Charles nutter star techconf 2011 - jvm languages

  • 1. Building Languages for the JVM Charles Oliver Nutter
  • 2. Me • Charles Oliver Nutter • JRuby and JVM guy • “headius” on most services • headius@headius.com
  • 3. Who Was I? • Java EE architect • Successfully! • Never wrote a parser • Never wrote a compiler • But I wanted to learn how...
  • 4. You • Java? • Ruby? • Python? • C#? • Other?
  • 5. Why Create Languages? • Nothing is perfect • New problems need new solutions • Language design can be fun • Fame and fortune? • Not really.
  • 6. Why Impl a Language? • To learn it? • Sort of... • To learn the target platform • Definitely! • Fame and fortune? • Well...getting there...
  • 7. Challenges • Community • Platform • Specifications • Resources
  • 8. Community • Investment in status quo • Afraid to stand out • Known quantities • Everything else sucks • Gotta get paid!
  • 9. Platform • Matching language semantics • JVM designed around Java • JVM hides underlying platform • Challenging to use • Not bad...C/++ would be way worse • Community may hate it ;-)
  • 10. Specifications • Incomplete • Ruby had none for years • ...and no complete test suites • Difficult to implement • Low level features • Single-implementation quirks • Hard or impossible to optimize
  • 11. Resources • You gotta eat • Not much money in language work • Some parts are hard • OSS is a necessity
  • 12. Why JVM? • Because I am lazy • Because VMs are *hard* • Because I can’t be awesome at everything
  • 13. Ok, Why Really? • Cross-platform • Libraries • Languages • Memory management • Tools • OSS
  • 14. Cross-platform • OpenJDK: Linux, Windows, Solaris, OS X, xBSD • J9: Linux, zLinux, AS/400, ... • HP: OpenVMS, HP/UX, ... • Dalvik (Android): Linux on ARM, x86
  • 15. Libraries • For any need, a dozen libraries • And a couple of them are good! • Cross-platform • Leading edge
  • 16. Selection of languages • Java • Scala • Clojure • JRuby • Mirah • Jython, Groovy, Fantom, Kotlin, Ceylon, ...
  • 17. Memory management • Best GCs in the world • Fastest object allocation • Safe escape hatches like NIO
  • 18. Tools • Debugging • Profiling • Monitoring • JVM internals
  • 19. Open source? • FOSS reference impl (OpenJDK) • Mostly OSS libraries • Heavy OSS culture • Strong OSS influence in OpenJDK core
  • 21. Ruby on the JVM • All of Ruby’s power and beauty • Solid VM underneath • “Just another JVM language”
  • 22. JVM Language • Full interop with Java • Tricky to do... • Very rewarding for 99% case • VM concerns solved • No need to write a GC • No need to write a JIT • ...oh, but wait...
  • 23. More than a JVM language • Use native code where JDK fails us • Paper over ugly bits like CLASSPATH • Matching Ruby semantics exactly* • Push JVM forward too!
  • 24. Playing with JRuby • Simple IRB demo • JRuby on Rails - see Jano’s talk tomorrow • JRuby performance • PotC (???)
  • 25. How did we do it?
  • 26. JRuby Architecture • Parser • Abstract Syntax Tree (AST) • Intermediate Representation (IR) • Core classes • Compiler
  • 27. Parser • Port of MRI’s Bison grammar • “Jay” parser generator for Java • Hand-written lexer • Nearly as fast as the C version • ...once it gets going
  • 28. system ~/projects/jruby $ jruby -y -e "1 + 1" push state 0 value null reduce tate 0 uncover 0 s rule (1) $$1 : goto from state 0 to 2 push state 2 value null lex tate 2 reading tIDENTIFIER value Token { Value=load, s Position=file:/Users/headius/projects/jruby/lib/jruby.jar!/ jruby/kernel.rb:6} shift from state 2 to 33 push state 33 value Token { Value=load, Position=file:/Users/ headius/projects/jruby/lib/jruby.jar!/jruby/kernel.rb:6} lex tate 33 reading tSTRING_BEG value Token { Value=', s Position=file:/Users/headius/projects/jruby/lib/jruby.jar!/ jruby/kernel.rb:6} reduce tate 33 uncover 2 s rule (487) operation : tIDENTIFIER goto from state 2 to 62 push state 62 value Token { Value=load, Position=file:/Users/ headius/projects/jruby/lib/jruby.jar!/jruby/kernel.rb:6} reduce tate 62 uncover 62 rule (252) $$6 : s
  • 29. system ~/projects/jruby $ jruby -y -e "1 + 1" push state 0 value null reduce tate 0 uncover 0 s rule (1) $$1 : goto from state 0 to 2 push state 2 value null lex tate 2 reading tIDENTIFIER value Token { Value=load, s Position=file:/Users/headius/projects/jruby/lib/jruby.jar!/ jruby/kernel.rb:6} shift from state 2 to 33 You will never need this. push state 33 value Token { Value=load, Position=file:/Users/ headius/projects/jruby/lib/jruby.jar!/jruby/kernel.rb:6} lex tate 33 reading tSTRING_BEG value Token { Value=', s Position=file:/Users/headius/projects/jruby/lib/jruby.jar!/ jruby/kernel.rb:6} reduce tate 33 uncover 2 s rule (487) operation : tIDENTIFIER goto from state 2 to 62 push state 62 value Token { Value=load, Position=file:/Users/ headius/projects/jruby/lib/jruby.jar!/jruby/kernel.rb:6} reduce tate 62 uncover 62 rule (252) $$6 : s
  • 30. public class RubyYaccLexer {     public static final Encoding UTF8_ENCODING = UTF8Encoding.INSTANCE;     public static final Encoding USASCII_ENCODING = USASCIIEncoding.INSTANCE;     public static final Encoding ASCII8BIT_ENCODING = ASCIIEncoding.INSTANCE;          private static ByteList END_MARKER = new ByteList(new byte[] {'_', 'E', 'N', 'D', '_', '_'});     private static ByteList BEGIN_DOC_MARKER = new ByteList(new byte[] {'b', 'e', 'g', 'i', 'n'});     private static ByteList END_DOC_MARKER = new ByteList(new byte[] {'e', 'n', 'd'});     private static final HashMap<String, Keyword> map;     static {         map = new HashMap<String, Keyword>();         map.put("end", Keyword.END);         map.put("else", Keyword.ELSE);         map.put("case", Keyword.CASE);         map.put("ensure", Keyword.ENSURE);         map.put("module", Keyword.MODULE);         map.put("elsif", Keyword.ELSIF);         map.put("def", Keyword.DEF);         map.put("rescue", Keyword.RESCUE);         map.put("not", Keyword.NOT);         map.put("then", Keyword.THEN);         map.put("yield", Keyword.YIELD);         map.put("for", Keyword.FOR);         map.put("self", Keyword.SELF);         map.put("false", Keyword.FALSE);
  • 31.     public enum Keyword {         END ("end", Tokens.kEND, Tokens.kEND, LexState.EXPR_END),         ELSE ("else", Tokens.kELSE, Tokens.kELSE, LexState.EXPR_BEG),         CASE ("case", Tokens.kCASE, Tokens.kCASE, LexState.EXPR_BEG),         ENSURE ("ensure", Tokens.kENSURE, Tokens.kENSURE, LexState.EXPR_BEG),         MODULE ("module", Tokens.kMODULE, Tokens.kMODULE, LexState.EXPR_BEG),         ELSIF ("elsif", Tokens.kELSIF, Tokens.kELSIF, LexState.EXPR_BEG),         DEF ("def", Tokens.kDEF, Tokens.kDEF, LexState.EXPR_FNAME),         RESCUE ("rescue", Tokens.kRESCUE, Tokens.kRESCUE_MOD, LexState.EXPR_MID),         NOT ("not", Tokens.kNOT, Tokens.kNOT, LexState.EXPR_BEG),         THEN ("then", Tokens.kTHEN, Tokens.kTHEN, LexState.EXPR_BEG),         YIELD ("yield", Tokens.kYIELD, Tokens.kYIELD, LexState.EXPR_ARG),         FOR ("for", Tokens.kFOR, Tokens.kFOR, LexState.EXPR_BEG),         SELF ("self", Tokens.kSELF, Tokens.kSELF, LexState.EXPR_END),         FALSE ("false", Tokens.kFALSE, Tokens.kFALSE, LexState.EXPR_END),         RETRY ("retry", Tokens.kRETRY, Tokens.kRETRY, LexState.EXPR_END),         RETURN ("return", Tokens.kRETURN, Tokens.kRETURN, LexState.EXPR_MID),         TRUE ("true", Tokens.kTRUE, Tokens.kTRUE, LexState.EXPR_END),         IF ("if", Tokens.kIF, Tokens.kIF_MOD, LexState.EXPR_BEG),         DEFINED_P ("defined?", Tokens.kDEFINED, Tokens.kDEFINED, LexState.EXPR_ARG),
  • 32.     private int yylex() throws IOException {         int c;         boolean spaceSeen = false;         boolean commandState;                  if (lex_strterm != null) {             int tok = lex_strterm.parseString(this, src);             if (tok == Tokens.tSTRING_END || tok == Tokens.tREGEXP_END) {                 lex_strterm = null;                 setState(LexState.EXPR_END);             }             return tok;         }         commandState = commandStart;         commandStart = false;         loop: for(;;) {             c = src.read();             switch(c) {
  • 33.             case '<':                 return lessThan(spaceSeen);             case '>':                 return greaterThan();             case '"':                 return doubleQuote();             case '`':                 return backtick(commandState);             case ''':                 return singleQuote();             case '?':                 return questionMark();             case '&':                 return ampersand(spaceSeen);             case '|':                 return pipe();             case '+':                 return plus(spaceSeen);
  • 34.     private int lessThan(boolean spaceSeen) throws IOException {         int c = src.read();         if (c == '<' && lex_state != LexState.EXPR_DOT && lex_state != LexState.EXPR_CLASS &&                 !isEND() && (!isARG() || spaceSeen)) {             int tok = hereDocumentIdentifier();                          if (tok != 0) return tok;         }                  determineExpressionState();                  switch (c) {         case '=':             if ((c = src.read()) == '>') {                 yaccValue = new Token("<=>", getPosition());                 return Tokens.tCMP;
  • 35. %% program : {                   lexer.setState(LexState.EXPR_BEG);                   support.initTopLocalVariables();               } top_compstmt {   // ENEBO: Removed !compile_for_eval which probably is to reduce warnings                   if ($2 != null) {                       /* last expression should not be void */                       if ($2 instanceof BlockNode) {                           support.checkUselessStatement($<BlockNod e>2.getLast());                       } else {                           support.checkUselessStatement($2);                       }                   }                   support.getResult().setAST(support.addRootNode($ 2, support.getPosition($2)));               }
  • 36. stmt : kALIAS fitem {                     lexer.setState(LexState.EXPR_FNAME);                 } fitem {                     $$ = support.newAlias($1.getPosition(), $2, $4);                 }                 | kALIAS tGVAR tGVAR {                     $$ = new VAliasNode($1.getPosition(), (String) $2.getValue(), (String) $3.getValue());                 }                 | kALIAS tGVAR tBACK_REF {                     $$ = new VAliasNode($1.getPosition(), (String) $2.getValue(), "$" + $<BackRefNode>3.getType());                 }                 | kALIAS tGVAR tNTH_REF {                     support.yyerror("can't make alias for the number variables");                 }                 | kUNDEF undef_list {                     $$ = $2;                 }                 | stmt kIF_MOD expr_value {                     $$ = new IfNode(support.getPosition($1), support.getConditionNode($3), $1, null);                 }
  • 37.   public Object yyparse (RubyYaccLexer yyLex) throws java.io.IOException {     if (yyMax <= 0) yyMax = 256;"" " // initial size     int yyState = 0, yyStates[] = new int[yyMax];" // state stack     Object yyVal = null, yyVals[] = new Object[yyMax];" // value stack     int yyToken = -1;" " " " " // current input     int yyErrorFlag = 0;" " " " // #tokens to shift     yyLoop: for (int yyTop = 0;; ++ yyTop) {       if (yyTop >= yyStates.length) {" " " // dynamically increase         int[] i = new int[yyStates.length+yyMax];         System.arraycopy(yyStates, 0, i, 0, yyStates.length);         yyStates = i;         Object[] o = new Object[yyVals.length+yyMax];         System.arraycopy(yyVals, 0, o, 0, yyVals.length);         yyVals = o;       }       yyStates[yyTop] = yyState;       yyVals[yyTop] = yyVal;       if (yydebug != null) yydebug.push(yyState, yyVal);
  • 38.         if (state == null) {             yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]);         } else {             yyVal = state.execute(support, lexer, yyVal, yyVals, yyTop);         }
  • 39. states[23] = new ParserState() {   public Object execute(ParserSupport support, RubyYaccLexer lexer, Object yyVal, Object[] yyVals, int yyTop) {                     yyVal = new IfNode(support.getPosition(((Node)yyVals[-2+yyTop])), support.getConditionNode(((Node)yyVals[0+yyTop])), ((Node)yyVals[-2+yyTop]), null);     return yyVal;   } }; Never look at this. states[24] = new ParserState() {   public Object execute(ParserSupport support, RubyYaccLexer lexer, Object yyVal, Object[] yyVals, int yyTop) {                     yyVal = new IfNode(support.getPosition(((Node)yyVals[-2+yyTop])), support.getConditionNode(((Node)yyVals[0+yyTop])), null, ((Node)yyVals[-2+yyTop]));     return yyVal;   } };
  • 40. AST • Interpreted directly • Specialized in places • Large and rich
  • 41. $ ast -e "a = true; if a; 2; else; 3; end" AST: RootNode 0 BlockNode 0 NewlineNode 0 LocalAsgnNode:a 0 TrueNode:true 0 NewlineNode 0 IfNode 0 LocalVarNode:a 0 NewlineNode 0 FixnumNode 0 NewlineNode 0 FixnumNode 0
  • 42. public class IfNode extends Node {     private final Node condition;     private final Node thenBody;     private final Node elseBody;     public IfNode(ISourcePosition position, Node condition, Node thenBody, Node elseBody) {         super(position);                  assert condition != null : "condition is not null"; // assert thenBody != null : "thenBody is not null"; // assert elseBody != null : "elseBody is not null";                  this.condition = condition;         this.thenBody = thenBody;         this.elseBody = elseBody;     }
  • 43.     @Override     public IRubyObject interpret(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {         ISourcePosition position = getPosition();         context.setFile(position.getFile());         context.setLine(position.getStartLine());         IRubyObject result = condition.interpret(runtime, context, self, aBlock);                  if (result.isTrue()) {             return thenBody == null ? runtime.getNil() : thenBody.interpret(runtime, context, self, aBlock);         } else {             return elseBody == null ? runtime.getNil() : elseBody.interpret(runtime, context, self, aBlock);         }     }
  • 44. IR (future work) • Control flow graph • Ruby-specific instruction set • Optimizing compiler • Ruby-level optimizations
  • 45. jruby -e “1 + 1”
  • 46. 2011-11-04T05:23:09.375-03:00: IR_Printer: instrs: 0 %self = recv_self 1 %block(0:0) = recv_closure 2 file_name(-e) 3 line_num(0) 4 %v_0 = call(+, 1:fixnum, [1:fixnum]) 5 return(%v_0) 2011-11-04T05:23:09.375-03:00: IR_Printer: live variables: %v_0: 4-5
  • 47. a = 1; while a < 10; puts a; a += 1; end
  • 48. 2011-11-04T05:25:23.517-03:00: IR_Printer: instrs: 0 %self = recv_self 1 %block(0:0) = recv_closure 2 file_name(-e) 3 line_num(0) 4 a(0:1) = 1:fixnum 5 _LOOP_BEGIN_0: 6 %v_1 = call(<, a(0:1), [10:fixnum]) 7 beq(%v_1, true, _ITER_BEGIN_0) 8 %v_0 = nil 9 jump _LOOP_END_0 10 _ITER_BEGIN_0: 11 %v_2 = call(puts, %self, [a(0:1)]) 12 %v_3 = call(+, a(0:1), [1:fixnum]) 13 a(0:1) = copy(%v_3) 14 %v_0 = copy(%v_3) 15 thread_poll 16 _ITER_END_0: 17 jump _LOOP_BEGIN_0 18 _LOOP_END_0: 19 return(%v_0) 2011-11-04T05:25:23.517-03:00: IR_Printer: live variables: %v_0: 8-19 %v_1: 6-7 %v_3: 12-14
  • 49. 2011-11-04T05:25:23.518-03:00: IRScope: ################## After CFG Linearize################## 2011-11-04T05:25:23.518-03:00: IR_Printer: ---------------------------------------- 2011-11-04T05:25:23.518-03:00: IR_Printer: Method [root]: [script]:-e 2011-11-04T05:25:23.518-03:00: IR_Printer: Graph: BB [4:LBL_3]:>[7], <[3] BB [1:LBL_1]:>[8,2] BB [2:LBL_2]:>[3], <[1] BB [7:_LOOP_END_0]:>[8], <[4] BB [8:LBL_4]:<[1,7] BB [3:_LOOP_BEGIN_0]:>[5,4], <[6,2] BB [6:_ITER_END_0]:>[3], <[5] BB [5:_ITER_BEGIN_0]:>[6], <[3]
  • 50. 2011-11-04T05:25:23.517-03:00: IR_Printer: instrs: 0 %self = recv_self 1 %block(0:0) = recv_closure 2 file_name(-e) 3 line_num(0) 4 a(0:1) = 1:fixnum 5 _LOOP_BEGIN_0: 6 %v_1 = call(<, a(0:1), [10:fixnum]) 7 beq(%v_1, true, _ITER_BEGIN_0) 8 %v_0 = nil 9 jump _LOOP_END_0 10 _ITER_BEGIN_0: 11 %v_2 = call(puts, %self, [a(0:1)]) 12 %v_3 = call(+, a(0:1), [1:fixnum]) 13 a(0:1) = copy(%v_3) 14 %v_0 = copy(%v_3) 15 thread_poll 16 _ITER_END_0: 17 jump _LOOP_BEGIN_0 18 _LOOP_END_0: 19 return(%v_0) 2011-11-04T05:25:23.517-03:00: IR_Printer: live variables: %v_0: 8-19 %v_1: 6-7 %v_3: 12-14
  • 51. 2011-11-04T05:25:23.518-03:00: IR_Printer: Instructions: BB [4:LBL_3] %v_0 = nil BB [1:LBL_1] BB [2:LBL_2] %self = recv_self %block(0:0) = recv_closure file_name(-e) line_num(0) a(0:1) = 1:fixnum BB [7:_LOOP_END_0] return(%v_0) BB [8:LBL_4] return(nil)
  • 52. Core classes • Mostly Java-based • Leverage JDK where possible • Work around JDK where necessary • Use Ruby when possible
  • 53. @JRubyClass(name="Fixnum", parent="Integer", include="Precision") public class RubyFixnum extends RubyInteger {          public static RubyClass createFixnumClass(Ruby runtime) {         RubyClass fixnum = runtime.defineClass("Fixnum", runtime.getInteger(),                 ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
  • 54.     @JRubyMethod(name = "+")     public IRubyObject op_plus(ThreadContext context, IRubyObject other) {         if (other instanceof RubyFixnum) {             return addFixnum(context, (RubyFixnum)other);         }         return addOther(context, other);     }
  • 55.     private IRubyObject addFixnum(ThreadContext context, RubyFixnum other) {         long otherValue = other.value;         long result = value + otherValue;         if (additionOverflowed(value, otherValue, result)) {             return addAsBignum(context, other);         }         return newFixnum(context.getRuntime(), result);     }
  • 56. Compiler • AST-walking • ASM bytecode library • Minimal optimizations • Invokedynamic really helps • IR offers new opportunities
  • 57. jruby --bytecode -e “1 + 1”
  • 58. ALOAD 0 INVOKEVIRTUAL ruby/__dash_e__.getCallSite0 ALOAD 1 ALOAD 2 ALOAD 1 GETFIELD org/jruby/runtime/ThreadContext.runtime INVOKESTATIC org/jruby/RubyFixnum.one LDC 1 INVOKEVIRTUAL org/jruby/runtime/CallSite.call ARETURN
  • 59. public class ASTCompiler {     private boolean isAtRoot = true;     public void compileBody(Node node, BodyCompiler context, boolean expr) {         Node oldBodyNode = currentBodyNode;         currentBodyNode = node;         compile(node, context, expr);         currentBodyNode = oldBodyNode;     }          public void compile(Node node, BodyCompiler context, boolean expr) {         if (node == null) {             if (expr) context.loadNil();             return;         }         switch (node.getNodeType()) {             case ALIASNODE:                 compileAlias((AliasNode) node, context, expr);                 break;             case ANDNODE:                 compileAnd(node, context, expr);                 break;
  • 60.     public void compileIf(Node node, BodyCompiler context, final boolean expr) {         final IfNode ifNode = (IfNode) node;         // optimizations if we know ahead of time it will always be true or false         Node actualCondition = ifNode.getCondition();         while (actualCondition instanceof NewlineNode) {             actualCondition = ((NewlineNode)actualCondition).getNextNode();         }         if (actualCondition.getNodeType().alwaysTrue()) {             // compile condition as non-expr and just compile "then" body             compile(actualCondition, context, false);             compile(ifNode.getThenBody(), context, expr);         } else if (actualCondition.getNodeType().alwaysFalse()) {             // always false or nil             compile(ifNode.getElseBody(), context, expr);         } else {
  • 61.             BranchCallback trueCallback = new BranchCallback() {                 public void branch(BodyCompiler context) {                     if (ifNode.getThenBody() != null) {                         compile(ifNode.getThenBody(), context, expr);                     } else {                         if (expr) context.loadNil();                     }                 }             };             BranchCallback falseCallback = new BranchCallback() {                 public void branch(BodyCompiler context) {                     if (ifNode.getElseBody() != null) {                         compile(ifNode.getElseBody(), context, expr);                     } else {                         if (expr) context.loadNil();                     }                 }             };                          // normal             compile(actualCondition, context, true);             context.performBooleanBranch(trueCallback, falseCallback);         }
  • 62. public abstract class BaseBodyCompiler implements BodyCompiler {     protected SkinnyMethodAdapter method;     protected VariableCompiler variableCompiler;     protected InvocationCompiler invocationCompiler;     protected int argParamCount;     protected Label[] currentLoopLabels;     protected Label scopeStart = new Label();     protected Label scopeEnd = new Label();     protected Label redoJump;     protected boolean inNestedMethod = false;     private int lastLine = -1;     private int lastPositionLine = -1;     protected StaticScope scope;     protected ASTInspector inspector;     protected String methodName;     protected String rubyName;     protected StandardASMCompiler script;
  • 63.     public void performBooleanBranch(BranchCallback trueBranch, BranchCallback falseBranch) {         Label afterJmp = new Label();         Label falseJmp = new Label();         // call isTrue on the result         isTrue();         method.ifeq(falseJmp); // EQ == 0 (i.e. false)         trueBranch.branch(this);         method.go_to(afterJmp);         // FIXME: optimize for cases where we have no false branch         method.label(falseJmp);         falseBranch.branch(this);         method.label(afterJmp);     }
  • 64. More Demos! • JRuby + JVM flags • JRuby concurrency • Invokedynamic (Java 7) • Redcar Editor • Ruboto (Android) • VisualVM
  • 65. Gracias! • Charles Oliver Nutter • “headius” on most services • headius@headius.com

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n