From 56b5c02366235e7e95edb16ff978b8d25f0a3cdd Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 20 Apr 2011 09:34:44 -0500 Subject: [PATCH] Cache a Float instance for literals, like other impls do. --- src/org/jruby/ast/FloatNode.java | 14 ++++++++++++- .../jruby/ast/executable/AbstractScript.java | 15 +++++++++++++ .../jruby/ast/executable/RuntimeCache.java | 20 +++++++++++++++++- src/org/jruby/compiler/CacheCompiler.java | 2 ++ .../jruby/compiler/impl/BaseBodyCompiler.java | 5 +---- .../compiler/impl/InheritedCacheCompiler.java | 21 +++++++++++++++++++ 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/org/jruby/ast/FloatNode.java b/src/org/jruby/ast/FloatNode.java index ee8b914b86e..2b4679a692d 100644 --- a/src/org/jruby/ast/FloatNode.java +++ b/src/org/jruby/ast/FloatNode.java @@ -47,6 +47,7 @@ */ public class FloatNode extends Node implements ILiteralNode { private double value; + private RubyFloat flote; public FloatNode(ISourcePosition position, double value) { super(position); @@ -74,15 +75,26 @@ public double getValue() { * @param value to set */ public void setValue(double value) { + // This should never happen past parse, but just bulletproof this just in case + if (flote != null) { + flote = null; + } this.value = value; } + public RubyFloat getFloat(Ruby runtime) { + if (flote == null) { + return flote = RubyFloat.newFloat(runtime, value); + } + return flote; + } + public List childNodes() { return EMPTY_LIST; } @Override public IRubyObject interpret(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) { - return RubyFloat.newFloat(runtime, value); + return getFloat(runtime); } } diff --git a/src/org/jruby/ast/executable/AbstractScript.java b/src/org/jruby/ast/executable/AbstractScript.java index 7b1d20d117a..42e2a8add02 100644 --- a/src/org/jruby/ast/executable/AbstractScript.java +++ b/src/org/jruby/ast/executable/AbstractScript.java @@ -10,6 +10,7 @@ import org.jcodings.EncodingDB; import org.jruby.Ruby; import org.jruby.RubyFixnum; +import org.jruby.RubyFloat; import org.jruby.RubyModule; import org.jruby.RubyRegexp; import org.jruby.RubyString; @@ -196,6 +197,20 @@ public IRubyObject run(ThreadContext context, IRubyObject self, IRubyObject[] ar public final RubyFixnum getFixnum8(Ruby runtime, int value) {return runtimeCache.getFixnum(runtime, 8, value);} public final RubyFixnum getFixnum9(Ruby runtime, int value) {return runtimeCache.getFixnum(runtime, 9, value);} + public static final int NUMBERED_FLOAT_COUNT = 10; + + public final RubyFloat getFloat(Ruby runtime, int i, double value) {return runtimeCache.getFloat(runtime, i, value);} + public final RubyFloat getFloat0(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 0, value);} + public final RubyFloat getFloat1(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 1, value);} + public final RubyFloat getFloat2(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 2, value);} + public final RubyFloat getFloat3(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 3, value);} + public final RubyFloat getFloat4(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 4, value);} + public final RubyFloat getFloat5(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 5, value);} + public final RubyFloat getFloat6(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 6, value);} + public final RubyFloat getFloat7(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 7, value);} + public final RubyFloat getFloat8(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 8, value);} + public final RubyFloat getFloat9(Ruby runtime, double value) {return runtimeCache.getFloat(runtime, 9, value);} + public static final int NUMBERED_REGEXP_COUNT = 10; public final RubyRegexp getRegexp(Ruby runtime, int i, ByteList pattern, int options) {return runtimeCache.getRegexp(runtime, i, pattern, options);} diff --git a/src/org/jruby/ast/executable/RuntimeCache.java b/src/org/jruby/ast/executable/RuntimeCache.java index be8e26ffd04..2abc0253935 100644 --- a/src/org/jruby/ast/executable/RuntimeCache.java +++ b/src/org/jruby/ast/executable/RuntimeCache.java @@ -7,6 +7,7 @@ import org.jruby.RubyClass; import org.jruby.RubyClass.VariableAccessor; import org.jruby.RubyFixnum; +import org.jruby.RubyFloat; import org.jruby.RubyModule; import org.jruby.RubyRegexp; import org.jruby.RubyString; @@ -130,6 +131,14 @@ public final RubyFixnum getFixnum(Ruby runtime, int index, long value) { return fixnum; } + public final RubyFloat getFloat(Ruby runtime, int index, double value) { + RubyFloat flote = floats[index]; + if (flote == null) { + return floats[index] = RubyFloat.newFloat(runtime, value); + } + return flote; + } + public final RubyRegexp getRegexp(Ruby runtime, int index, ByteList pattern, int options) { RubyRegexp regexp = regexps[index]; if (regexp == null || runtime.getKCode() != regexp.getKCode()) { @@ -246,7 +255,8 @@ public final void initFromDescriptor(String descriptor) { private static final int SCOPE = 0; private static final int SYMBOL = SCOPE + 1; private static final int FIXNUM = SYMBOL + 1; - private static final int CONSTANT = FIXNUM + 1; + private static final int FLOAT = FIXNUM + 1; + private static final int CONSTANT = FLOAT + 1; private static final int REGEXP = CONSTANT + 1; private static final int BIGINTEGER = REGEXP + 1; private static final int VARIABLEREADER = BIGINTEGER + 1; @@ -285,6 +295,8 @@ public final void initOthers(String descriptor) { if (symbolCount > 0) initSymbols(symbolCount); int fixnumCount = getDescriptorValue(descriptor, FIXNUM); if (fixnumCount > 0) initFixnums(fixnumCount); + int floatCount = getDescriptorValue(descriptor, FLOAT); + if (floatCount > 0) initFloats(floatCount); int constantCount = getDescriptorValue(descriptor, CONSTANT); if (constantCount > 0) initConstants(constantCount); int regexpCount = getDescriptorValue(descriptor, REGEXP); @@ -335,6 +347,10 @@ public final void initFixnums(int size) { fixnums = new RubyFixnum[size]; } + public final void initFloats(int size) { + floats = new RubyFloat[size]; + } + public final void initRegexps(int size) { regexps = new RubyRegexp[size]; } @@ -626,6 +642,8 @@ private CacheEntry getCacheEntry(int index) { public Encoding[] encodings = EMPTY_ENCODINGS; private static final RubyFixnum[] EMPTY_FIXNUMS = {}; public RubyFixnum[] fixnums = EMPTY_FIXNUMS; + private static final RubyFloat[] EMPTY_FLOATS = {}; + public RubyFloat[] floats = EMPTY_FLOATS; private static final RubyRegexp[] EMPTY_RUBYREGEXPS = {}; public RubyRegexp[] regexps = EMPTY_RUBYREGEXPS; private static final BigInteger[] EMPTY_BIGINTEGERS = {}; diff --git a/src/org/jruby/compiler/CacheCompiler.java b/src/org/jruby/compiler/CacheCompiler.java index 512f2ef0acb..91c578e42c1 100644 --- a/src/org/jruby/compiler/CacheCompiler.java +++ b/src/org/jruby/compiler/CacheCompiler.java @@ -28,6 +28,8 @@ public interface CacheCompiler { public void cacheFixnum(BaseBodyCompiler method, long value); + public void cacheFloat(BaseBodyCompiler method, double value); + public void cacheBigInteger(BaseBodyCompiler method, BigInteger bigint); public void cachedGetVariable(BaseBodyCompiler method, String name); diff --git a/src/org/jruby/compiler/impl/BaseBodyCompiler.java b/src/org/jruby/compiler/impl/BaseBodyCompiler.java index d9993667eeb..baada686d02 100644 --- a/src/org/jruby/compiler/impl/BaseBodyCompiler.java +++ b/src/org/jruby/compiler/impl/BaseBodyCompiler.java @@ -434,10 +434,7 @@ public void declareClassVariable(String name, CompilerCallback value) { } 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 03f9e62989f..6e41164e2af 100644 --- a/src/org/jruby/compiler/impl/InheritedCacheCompiler.java +++ b/src/org/jruby/compiler/impl/InheritedCacheCompiler.java @@ -14,6 +14,7 @@ import org.jruby.Ruby; import org.jruby.RubyEncoding; import org.jruby.RubyFixnum; +import org.jruby.RubyFloat; import org.jruby.RubyModule; import org.jruby.RubyRegexp; import org.jruby.RubyString; @@ -53,6 +54,7 @@ public class InheritedCacheCompiler implements CacheCompiler { Map stringEncodings = new HashMap(); Map symbolIndices = new HashMap(); Map fixnumIndices = new HashMap(); + Map floatIndices = new HashMap(); int inheritedSymbolCount = 0; int inheritedStringCount = 0; int inheritedEncodingCount = 0; @@ -61,6 +63,7 @@ public class InheritedCacheCompiler implements CacheCompiler { int inheritedVariableReaderCount = 0; int inheritedVariableWriterCount = 0; int inheritedFixnumCount = 0; + int inheritedFloatCount = 0; int inheritedConstantCount = 0; int inheritedBlockBodyCount = 0; int inheritedBlockCallbackCount = 0; @@ -220,6 +223,22 @@ public void cacheFixnum(BaseBodyCompiler method, long value) { } } } + + public void cacheFloat(BaseBodyCompiler method, double value) { + Integer index = Integer.valueOf(inheritedFloatCount++); + floatIndices.put(value, index); + + method.loadThis(); + method.loadRuntime(); + if (index < AbstractScript.NUMBERED_FLOAT_COUNT) { + method.method.ldc(value); + method.method.invokevirtual(scriptCompiler.getClassname(), "getFloat" + index, sig(RubyFloat.class, Ruby.class, double.class)); + } else { + 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(); @@ -486,6 +505,7 @@ public void finish() { int otherCount = scopeCount + inheritedSymbolCount + inheritedFixnumCount + + inheritedFloatCount + inheritedConstantCount + inheritedRegexpCount + inheritedBigIntegerCount @@ -523,6 +543,7 @@ public void finish() { descriptor.append((char)scopeCount); descriptor.append((char)inheritedSymbolCount); descriptor.append((char)inheritedFixnumCount); + descriptor.append((char)inheritedFloatCount); descriptor.append((char)inheritedConstantCount); descriptor.append((char)inheritedRegexpCount); descriptor.append((char)inheritedBigIntegerCount);