I noticed this evening we don't cache literal floats in either the
interpreter or the compiler, but I could not remember why. I've attached
a patch that fixes this, but does anyone remember if there's a reason
why we couldn't cache floats? Are they mutable or something?
- Charlie
>From c4a8d4b5c6625762f003d0debe54a659bb9a333e Mon Sep 17 00:00:00 2001
From: Charles Nutter <[email protected]>
Date: Sat, 21 Feb 2009 02:40:22 -0600
Subject: [PATCH] Add Float caching to compiler and interpreter. Passes all
tests, improves performance, but I feel like I didn't do it before on purpose...
---
src/org/jruby/ast/FloatNode.java | 8 +++++-
src/org/jruby/ast/executable/AbstractScript.java | 25 ++++++++++++++++++++
src/org/jruby/compiler/CacheCompiler.java | 2 +
src/org/jruby/compiler/impl/BaseBodyCompiler.java | 5 +---
.../compiler/impl/InheritedCacheCompiler.java | 25 ++++++++++++++++++++
5 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/src/org/jruby/ast/FloatNode.java b/src/org/jruby/ast/FloatNode.java
index ee8b914..7b8fc20 100644
--- a/src/org/jruby/ast/FloatNode.java
+++ b/src/org/jruby/ast/FloatNode.java
@@ -47,6 +47,7 @@ import org.jruby.runtime.builtin.IRubyObject;
*/
public class FloatNode extends Node implements ILiteralNode {
private double value;
+ private RubyFloat rubyFloat;
public FloatNode(ISourcePosition position, double value) {
super(position);
@@ -68,6 +69,11 @@ public class FloatNode extends Node implements ILiteralNode {
public double getValue() {
return value;
}
+
+ public RubyFloat getRubyFloat(Ruby runtime) {
+ if (rubyFloat == null) rubyFloat = RubyFloat.newFloat(runtime, value);
+ return rubyFloat;
+ }
/**
* Sets the value
@@ -83,6 +89,6 @@ public class FloatNode extends Node implements ILiteralNode {
@Override
public IRubyObject interpret(Ruby runtime, ThreadContext context,
IRubyObject self, Block aBlock) {
- return RubyFloat.newFloat(runtime, value);
+ return getRubyFloat(runtime);
}
}
diff --git a/src/org/jruby/ast/executable/AbstractScript.java
b/src/org/jruby/ast/executable/AbstractScript.java
index f73a21e..d0098db 100644
--- a/src/org/jruby/ast/executable/AbstractScript.java
+++ b/src/org/jruby/ast/executable/AbstractScript.java
@@ -9,6 +9,7 @@ import java.math.BigInteger;
import java.util.Arrays;
import org.jruby.Ruby;
import org.jruby.RubyFixnum;
+import org.jruby.RubyFloat;
import org.jruby.RubyModule;
import org.jruby.RubyRegexp;
import org.jruby.RubyString;
@@ -250,6 +251,25 @@ public abstract class AbstractScript implements Script {
return fixnum;
}
+ public static final double NUMBERED_FLOAT_COUNT = 10;
+
+ public final RubyFloat getFloat0(Ruby runtime, double value) {return
getFloat(runtime, 0, value);}
+ public final RubyFloat getFloat1(Ruby runtime, double value) {return
getFloat(runtime, 1, value);}
+ public final RubyFloat getFloat2(Ruby runtime, double value) {return
getFloat(runtime, 2, value);}
+ public final RubyFloat getFloat3(Ruby runtime, double value) {return
getFloat(runtime, 3, value);}
+ public final RubyFloat getFloat4(Ruby runtime, double value) {return
getFloat(runtime, 4, value);}
+ public final RubyFloat getFloat5(Ruby runtime, double value) {return
getFloat(runtime, 5, value);}
+ public final RubyFloat getFloat6(Ruby runtime, double value) {return
getFloat(runtime, 6, value);}
+ public final RubyFloat getFloat7(Ruby runtime, double value) {return
getFloat(runtime, 7, value);}
+ public final RubyFloat getFloat8(Ruby runtime, double value) {return
getFloat(runtime, 8, value);}
+ public final RubyFloat getFloat9(Ruby runtime, double value) {return
getFloat(runtime, 9, value);}
+
+ public final RubyFloat getFloat(Ruby runtime, int index, double value) {
+ RubyFloat flote = flotes[index];
+ if (flote == null) return flotes[index] = RubyFloat.newFloat(runtime,
value);
+ return flote;
+ }
+
public final RubyRegexp getRegexp(Ruby runtime, int index, String pattern,
int options) {
RubyRegexp regexp = regexps[index];
if (regexp == null) {
@@ -332,6 +352,10 @@ public abstract class AbstractScript implements Script {
fixnums = new RubyFixnum[size];
}
+ public final void initFloats(int size) {
+ flotes = new RubyFloat[size];
+ }
+
public final void initRegexps(int size) {
regexps = new RubyRegexp[size];
}
@@ -522,6 +546,7 @@ public abstract class AbstractScript implements Script {
public RubySymbol[] symbols;
public ByteList[] byteLists;
public RubyFixnum[] fixnums;
+ public RubyFloat[] flotes;
public RubyRegexp[] regexps;
public BigInteger[] bigIntegers;
public String filename;
diff --git a/src/org/jruby/compiler/CacheCompiler.java
b/src/org/jruby/compiler/CacheCompiler.java
index d10e1a8..4cbc01c 100644
--- a/src/org/jruby/compiler/CacheCompiler.java
+++ b/src/org/jruby/compiler/CacheCompiler.java
@@ -24,6 +24,8 @@ public interface CacheCompiler {
public void cacheSymbol(BaseBodyCompiler method, String symbol);
public void cacheFixnum(BaseBodyCompiler method, long value);
+
+ public void cacheFloat(BaseBodyCompiler method, double value);
public void cacheBigInteger(BaseBodyCompiler method, BigInteger bigint);
diff --git a/src/org/jruby/compiler/impl/BaseBodyCompiler.java
b/src/org/jruby/compiler/impl/BaseBodyCompiler.java
index befb8f6..6b37bc1 100644
--- a/src/org/jruby/compiler/impl/BaseBodyCompiler.java
+++ b/src/org/jruby/compiler/impl/BaseBodyCompiler.java
@@ -443,10 +443,7 @@ public abstract class BaseBodyCompiler implements
BodyCompiler {
}
public void createNewFloat(double value) {
- loadRuntime();
- method.ldc(new Double(value));
-
- invokeRuby("newFloat", sig(RubyFloat.class, params(Double.TYPE)));
+ script.getCacheCompiler().cacheFloat(this, value);
}
public void createNewFixnum(long value) {
diff --git a/src/org/jruby/compiler/impl/InheritedCacheCompiler.java
b/src/org/jruby/compiler/impl/InheritedCacheCompiler.java
index 043612a..7eb3faf 100644
--- a/src/org/jruby/compiler/impl/InheritedCacheCompiler.java
+++ b/src/org/jruby/compiler/impl/InheritedCacheCompiler.java
@@ -12,6 +12,7 @@ import java.util.List;
import java.util.Map;
import org.jruby.Ruby;
import org.jruby.RubyFixnum;
+import org.jruby.RubyFloat;
import org.jruby.RubyModule;
import org.jruby.RubyRegexp;
import org.jruby.RubyString;
@@ -47,11 +48,13 @@ public class InheritedCacheCompiler implements
CacheCompiler {
Map<BigInteger, String> bigIntegers = new HashMap<BigInteger, String>();
Map<String, Integer> symbolIndices = new HashMap<String, Integer>();
Map<Long, Integer> fixnumIndices = new HashMap<Long, Integer>();
+ Map<Double, Integer> floatIndices = new HashMap<Double, Integer>();
int inheritedSymbolCount = 0;
int inheritedStringCount = 0;
int inheritedRegexpCount = 0;
int inheritedBigIntegerCount = 0;
int inheritedFixnumCount = 0;
+ int inheritedFloatCount = 0;
int inheritedConstantCount = 0;
int inheritedBlockBodyCount = 0;
int inheritedBlockCallbackCount = 0;
@@ -213,6 +216,20 @@ public class InheritedCacheCompiler implements
CacheCompiler {
}
}
+ public void cacheFloat(BaseBodyCompiler method, double value) {
+ Integer index = floatIndices.get(value);
+ if (index == null) {
+ index = new Integer(inheritedFloatCount++);
+ floatIndices.put(value, index);
+ }
+
+ method.loadThis();
+ method.loadRuntime();
+ method.method.pushInt(index.intValue());
+ method.method.ldc(value);
+ method.method.invokevirtual(scriptCompiler.getClassname(), "getFloat",
sig(RubyFloat.class, Ruby.class, int.class, double.class));
+ }
+
public void cacheConstant(BaseBodyCompiler method, String constantName) {
method.loadThis();
method.loadThreadContext();
@@ -405,6 +422,14 @@ public class InheritedCacheCompiler implements
CacheCompiler {
initMethod.invokevirtual(scriptCompiler.getClassname(),
"initFixnums", sig(void.class, params(int.class)));
}
+ // generate fixnums initialization code
+ size = inheritedFloatCount;
+ if (size != 0) {
+ initMethod.aload(0);
+ initMethod.pushInt(size);
+ initMethod.invokevirtual(scriptCompiler.getClassname(),
"initFloats", sig(void.class, params(int.class)));
+ }
+
// generate constants initialization code
size = inheritedConstantCount;
if (size != 0) {
--
1.6.0.2
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email