From 6965c9bb7124d967c2b9b53b1c5a3e0f88a16ef2 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Wed, 28 Jul 2010 14:53:39 +0000 Subject: [PATCH] String concatenation optimization. --- src/core/org/luaj/vm2/Buffer.java | 12 ++++++++---- src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/core/org/luaj/vm2/Buffer.java b/src/core/org/luaj/vm2/Buffer.java index 8f5d2bd9..dc789c9a 100644 --- a/src/core/org/luaj/vm2/Buffer.java +++ b/src/core/org/luaj/vm2/Buffer.java @@ -45,30 +45,34 @@ public final class Buffer { return LuaString.valueOf(bytes, 0, length).tojstring(); } - public final void append( byte b ) { + public final Buffer append( byte b ) { ensureCapacity( length + 1 ); bytes[ length++ ] = b; + return this; } - public final void append( LuaValue val ) { + public final Buffer append( LuaValue val ) { if ( ! val.isstring() ) val.error("attempt to concatenate a '"+val.typename()+"' value"); append( val.strvalue() ); + return this; } - public final void append( LuaString str ) { + public final Buffer append( LuaString str ) { final int alen = str.length(); ensureCapacity( length + alen ); str.copyInto( 0, bytes, length, alen ); length += alen; + return this; } - public final void append( String str ) { + public final Buffer append( String str ) { char[] chars = str.toCharArray(); final int alen = LuaString.lengthAsUtf8( chars ); ensureCapacity( length + alen ); LuaString.encodeToUtf8( chars, bytes, length ); length += alen; + return this; } public final void setLength( int length ) { diff --git a/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java b/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java index d29cc278..a3c130e0 100644 --- a/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java +++ b/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java @@ -533,11 +533,25 @@ public class JavaCodeGen { case Lua.OP_LE: out(evalLuaValue(exp.lhs)+".lteq("+evalNumber(exp.rhs)+")"); return; case Lua.OP_EQ: out(evalLuaValue(exp.lhs)+".eq("+evalLuaValue(exp.rhs)+")"); return; case Lua.OP_NEQ: out(evalLuaValue(exp.lhs)+".neq("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_CONCAT: out(evalLuaValue(exp.lhs)+".concat("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_CONCAT: + if ( isConcatExp(exp.rhs) ) { + out( "new Buffer().append("+evalLuaValue(exp.lhs)+")" ); + Exp e = exp.rhs; + for ( ; isConcatExp(e); e=((BinopExp)e).rhs ) + out( ".append("+evalLuaValue(((BinopExp)e).lhs)+")" ); + out( ".append("+evalLuaValue(e)+")" ); + out( ".tostring()" ); + } else + out(evalLuaValue(exp.lhs)+".concat("+evalLuaValue(exp.rhs)+")"); + return; default: throw new IllegalStateException("unknown bin op:"+exp.op); } } + private boolean isConcatExp(Exp e) { + return (e instanceof BinopExp) && (((BinopExp)e).op == Lua.OP_CONCAT); + } + public void visit(UnopExp exp) { exp.rhs.accept(this); switch ( exp.op ) {