Navigation Menu

Skip to content

Commit

Permalink
Eliminating FieldCacheCompiler for JRUBY-2807: Migrate inheritance-ba…
Browse files Browse the repository at this point in the history
…sed cache compiler to use arrays for more stuff

git-svn-id: http://svn.codehaus.org/jruby/trunk/jruby@7959 961051c9-f516-0410-bf72-c9f7e237a7b7
  • Loading branch information
headius committed Oct 30, 2008
1 parent 20361c6 commit 1ae4157
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 151 deletions.
149 changes: 0 additions & 149 deletions src/org/jruby/compiler/impl/FieldBasedCacheCompiler.java

This file was deleted.

127 changes: 125 additions & 2 deletions src/org/jruby/compiler/impl/InheritedCacheCompiler.java
Expand Up @@ -5,38 +5,50 @@

package org.jruby.compiler.impl;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jruby.Ruby;
import org.jruby.RubyFixnum;
import org.jruby.RubySymbol;
import org.jruby.ast.NodeType;
import org.jruby.compiler.ASTInspector;
import org.jruby.compiler.CacheCompiler;
import org.jruby.javasupport.util.RuntimeHelpers;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.BlockBody;
import org.jruby.runtime.CallSite;
import org.jruby.runtime.CallType;
import org.jruby.runtime.CompiledBlockCallback;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import static org.jruby.util.CodegenUtils.*;

/**
*
* @author headius
*/
public class InheritedCacheCompiler extends FieldBasedCacheCompiler {
public class InheritedCacheCompiler implements CacheCompiler {
protected StandardASMCompiler scriptCompiler;
int callSiteCount = 0;
List<String> callSiteList = new ArrayList<String>();
List<CallType> callTypeList = new ArrayList<CallType>();
Map<String, Integer> byteListIndices = new HashMap<String, Integer>();
Map<String, ByteList> byteListValues = new HashMap<String, ByteList>();
Map<BigInteger, String> bigIntegers = new HashMap<BigInteger, String>();
int inheritedSymbolCount = 0;
int inheritedFixnumCount = 0;
int inheritedConstantCount = 0;
int inheritedByteListCount = 0;

public InheritedCacheCompiler(StandardASMCompiler scriptCompiler) {
super(scriptCompiler);
this.scriptCompiler = scriptCompiler;
}

public void cacheCallSite(BaseBodyCompiler method, String name, CallType callType) {
Expand Down Expand Up @@ -210,4 +222,115 @@ public void cacheByteList(BaseBodyCompiler method, ByteList contents) {
method.method.ldc(index.intValue());
method.method.invokestatic(scriptCompiler.getClassname(), "getByteList", sig(ByteList.class, int.class));
}

public void cacheBigInteger(BaseBodyCompiler method, BigInteger bigint) {
String fieldName = bigIntegers.get(bigint);
if (fieldName == null) {
SkinnyMethodAdapter clinitMethod = scriptCompiler.getClassInitMethod();
fieldName = scriptCompiler.getNewStaticConstant(ci(BigInteger.class), "bigInt");
bigIntegers.put(bigint, fieldName);

clinitMethod.newobj(p(BigInteger.class));
clinitMethod.dup();
clinitMethod.ldc(bigint.toString());
clinitMethod.invokespecial(p(BigInteger.class), "<init>", sig(void.class, String.class));
clinitMethod.putstatic(scriptCompiler.getClassname(), fieldName, ci(BigInteger.class));
}

method.method.getstatic(scriptCompiler.getClassname(), fieldName, ci(BigInteger.class));
}

public void cacheClosure(BaseBodyCompiler method, String closureMethod, int arity, StaticScope scope, boolean hasMultipleArgsHead, NodeType argsNodeId, ASTInspector inspector) {
String closureFieldName = scriptCompiler.getNewConstant(ci(BlockBody.class), "closure");

String closureMethodName = "getClosure_" + closureFieldName;

ClassVisitor cv = scriptCompiler.getClassVisitor();

{
SkinnyMethodAdapter closureGetter = new SkinnyMethodAdapter(
cv.visitMethod(Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC, closureMethodName,
sig(BlockBody.class, ThreadContext.class), null, null));

closureGetter.aload(0);
closureGetter.getfield(scriptCompiler.getClassname(), closureFieldName, ci(BlockBody.class));
closureGetter.dup();
Label alreadyCreated = new Label();
closureGetter.ifnonnull(alreadyCreated);

// no callback, construct and cache it
closureGetter.pop();
closureGetter.aload(0); // [this]

// create callbackloadThreadContext();
closureGetter.aload(1);
closureGetter.aload(0);
closureGetter.ldc(closureMethod); // [this, runtime, this, str]
closureGetter.pushInt(arity);
StandardASMCompiler.buildStaticScopeNames(closureGetter, scope);
closureGetter.ldc(Boolean.valueOf(hasMultipleArgsHead));
closureGetter.pushInt(BlockBody.asArgumentType(argsNodeId));
// if there's a sub-closure or there's scope-aware methods, it can't be "light"
closureGetter.ldc(!(inspector.hasClosure() || inspector.hasScopeAwareMethods()));
closureGetter.invokestatic(p(RuntimeHelpers.class), "createCompiledBlockBody",
sig(BlockBody.class, ThreadContext.class, Object.class, String.class, int.class,
String[].class, boolean.class, int.class, boolean.class));

closureGetter.putfield(scriptCompiler.getClassname(), closureFieldName, ci(BlockBody.class)); // []
closureGetter.aload(0); // [this]
closureGetter.getfield(scriptCompiler.getClassname(), closureFieldName, ci(BlockBody.class)); // [callback]

closureGetter.label(alreadyCreated);
closureGetter.areturn();

closureGetter.end();
}

method.loadThis();
method.loadThreadContext();
method.method.invokevirtual(scriptCompiler.getClassname(), closureMethodName,
sig(BlockBody.class, ThreadContext.class));
}

public void cacheClosureOld(BaseBodyCompiler method, String closureMethod) {
String closureFieldName = scriptCompiler.getNewConstant(ci(CompiledBlockCallback.class), "closure");

String closureMethodName = "getClosure_" + closureFieldName;

ClassVisitor cv = scriptCompiler.getClassVisitor();

{
SkinnyMethodAdapter closureGetter = new SkinnyMethodAdapter(
cv.visitMethod(Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC, closureMethodName,
sig(CompiledBlockCallback.class, Ruby.class), null, null));

closureGetter.aload(0);
closureGetter.getfield(scriptCompiler.getClassname(), closureFieldName, ci(CompiledBlockCallback.class));
closureGetter.dup();
Label alreadyCreated = new Label();
closureGetter.ifnonnull(alreadyCreated);

// no callback, construct and cache it
closureGetter.pop();
closureGetter.aload(0); // [this]
closureGetter.aload(1); // [this, runtime]
closureGetter.aload(0); // [this, runtime, this]
closureGetter.ldc(closureMethod); // [this, runtime, this, str]
closureGetter.invokestatic(p(RuntimeHelpers.class), "createBlockCallback",
sig(CompiledBlockCallback.class, Ruby.class, Object.class, String.class)); // [this, callback]
closureGetter.putfield(scriptCompiler.getClassname(), closureFieldName, ci(CompiledBlockCallback.class)); // []
closureGetter.aload(0); // [this]
closureGetter.getfield(scriptCompiler.getClassname(), closureFieldName, ci(CompiledBlockCallback.class)); // [callback]

closureGetter.label(alreadyCreated);
closureGetter.areturn();

closureGetter.end();
}

method.loadThis();
method.loadRuntime();
method.method.invokevirtual(scriptCompiler.getClassname(), closureMethodName,
sig(CompiledBlockCallback.class, params(Ruby.class)));
}
}

0 comments on commit 1ae4157

Please sign in to comment.