Skip to content

Commit

Permalink
Performance improvements for defined? logic.
Browse files Browse the repository at this point in the history
* Return a cached, frozen string rather than recreating each time.
* Cache variable accessors for ivar defined? checks.
  • Loading branch information
headius committed Sep 17, 2012
1 parent 8a309ad commit b03d0bc
Show file tree
Hide file tree
Showing 50 changed files with 364 additions and 159 deletions.
32 changes: 19 additions & 13 deletions src/org/jruby/Ruby.java
Expand Up @@ -118,6 +118,7 @@
import org.jruby.runtime.scope.ManyVarsDynamicScope;
import org.jruby.threading.DaemonThreadFactory;
import org.jruby.util.ByteList;
import org.jruby.util.DefinedMessage;
import org.jruby.util.IOInputStream;
import org.jruby.util.IOOutputStream;
import org.jruby.util.JRubyClassLoader;
Expand All @@ -143,19 +144,7 @@
import java.net.BindException;
import java.nio.channels.ClosedChannelException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Stack;
import java.util.Vector;
import java.util.WeakHashMap;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
Expand Down Expand Up @@ -1112,6 +1101,9 @@ private void init() {

// Initialize all the core classes
bootstrap();

// set up defined messages
initDefinedMessages();

irManager = new IRManager();

Expand Down Expand Up @@ -1162,6 +1154,14 @@ private void bootstrap() {
initExceptions();
}

private void initDefinedMessages() {
for (DefinedMessage definedMessage : DefinedMessage.values()) {
RubyString str = RubyString.newString(this, ByteList.create(definedMessage.getText()));
str.setFrozen(true);
definedMessages.put(definedMessage, str);
}
}

private void initRoot() {
boolean oneNine = is1_9();
// Bootstrap the top of the hierarchy
Expand Down Expand Up @@ -4219,6 +4219,10 @@ public void setFFI(FFI ffi) {
this.ffi = ffi;
}

public RubyString getDefinedMessage(DefinedMessage definedMessage) {
return definedMessages.get(definedMessage);
}

@Deprecated
public int getSafeLevel() {
return 0;
Expand Down Expand Up @@ -4475,4 +4479,6 @@ public void secure(int level) {
private FFI ffi;

private JavaProxyClassFactory javaProxyClassFactory;

private EnumMap<DefinedMessage, RubyString> definedMessages = new EnumMap<DefinedMessage, RubyString>(DefinedMessage.class);
}
6 changes: 4 additions & 2 deletions src/org/jruby/ast/AndNode.java
Expand Up @@ -34,12 +34,14 @@
import java.util.List;

import org.jruby.Ruby;
import org.jruby.RubyString;
import org.jruby.ast.visitor.NodeVisitor;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.DefinedMessage;

/**
* Represents a && (and) operator.
Expand Down Expand Up @@ -96,11 +98,11 @@ public IRubyObject interpret(Ruby runtime, ThreadContext context, IRubyObject se
}

@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
if (!context.runtime.is1_9()) {
return super.definition(runtime, context, self, aBlock);
} else {
return EXPRESSION_BYTELIST;
return runtime.getDefinedMessage(DefinedMessage.EXPRESSION);
}
}
}
6 changes: 4 additions & 2 deletions src/org/jruby/ast/AssignableNode.java
Expand Up @@ -31,13 +31,15 @@
package org.jruby.ast;

import org.jruby.Ruby;
import org.jruby.RubyString;
import org.jruby.ast.types.IArityNode;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.DefinedMessage;

/**
* Base class of any node which can be assigned to.
Expand Down Expand Up @@ -81,7 +83,7 @@ public Arity getArity() {
}

@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
return ASSIGNMENT_BYTELIST;
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
return runtime.getDefinedMessage(DefinedMessage.ASSIGNMENT);
}
}
6 changes: 4 additions & 2 deletions src/org/jruby/ast/AttrAssignNode.java
Expand Up @@ -33,6 +33,7 @@
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyString;
import org.jruby.ast.types.INameNode;
import org.jruby.ast.visitor.NodeVisitor;
import org.jruby.evaluator.ASTInterpreter;
Expand All @@ -48,6 +49,7 @@
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.DefinedMessage;

/**
* Node that represents an assignment of either an array element or attribute.
Expand Down Expand Up @@ -256,7 +258,7 @@ private IRubyObject otherAssign(Ruby runtime, ThreadContext context, IRubyObject
}

@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
if (receiverNode.definition(runtime, context, self, aBlock) != null) {
try {
IRubyObject receiver = receiverNode.interpret(runtime, context, self, aBlock);
Expand All @@ -267,7 +269,7 @@ public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self
if (visibility != Visibility.PRIVATE &&
(visibility != Visibility.PROTECTED || metaClass.getRealClass().isInstance(self))) {
if (metaClass.isMethodBound(name, false)) {
return ASTInterpreter.getArgumentDefinition(runtime, context, argsNode, ASSIGNMENT_BYTELIST, self, aBlock);
return ASTInterpreter.getArgumentDefinition(runtime, context, argsNode, runtime.getDefinedMessage(DefinedMessage.ASSIGNMENT), self, aBlock);
}
}
} catch (JumpException e) {
Expand Down
10 changes: 6 additions & 4 deletions src/org/jruby/ast/BackRefNode.java
Expand Up @@ -36,12 +36,14 @@
import org.jruby.Ruby;
import org.jruby.RubyMatchData;
import org.jruby.RubyRegexp;
import org.jruby.RubyString;
import org.jruby.ast.visitor.NodeVisitor;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.DefinedMessage;

/**
* Regexp back reference:
Expand All @@ -57,12 +59,12 @@ public class BackRefNode extends Node {
private final char type;

/** ByteList for the name of this backref global */
private final ByteList nameByteList;
private final DefinedMessage definedMessage;

public BackRefNode(ISourcePosition position, int type) {
super(position);
this.type = (char) type;
this.nameByteList = ByteList.create("$" + (char)type);
this.definedMessage = DefinedMessage.byText("$" + (char)type);
}

public NodeType getNodeType() {
Expand Down Expand Up @@ -110,11 +112,11 @@ public IRubyObject interpret(Ruby runtime, ThreadContext context, IRubyObject se
}

@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
IRubyObject backref = context.getCurrentScope().getBackRef(runtime);

if (backref instanceof RubyMatchData) {
return context.runtime.is1_9() ? GLOBAL_VARIABLE_BYTELIST : nameByteList;
return runtime.getDefinedMessage(runtime.is1_9() ? DefinedMessage.GLOBAL_VARIABLE : definedMessage);
}
return null;
}
Expand Down
6 changes: 3 additions & 3 deletions src/org/jruby/ast/CallNoArgNode.java
Expand Up @@ -34,6 +34,7 @@

import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyString;
import org.jruby.exceptions.JumpException;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.javasupport.util.RuntimeHelpers;
Expand Down Expand Up @@ -69,8 +70,7 @@ public Node setIterNode(Node iterNode) {
}

@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
ByteList definition = null;
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
if (getReceiverNode().definition(runtime, context, self, aBlock) != null) {
try {
IRubyObject receiver = getReceiverNode().interpret(runtime, context, self, aBlock);
Expand All @@ -79,6 +79,6 @@ public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self
}
}

return definition;
return null;
}
}
6 changes: 4 additions & 2 deletions src/org/jruby/ast/CallNode.java
Expand Up @@ -37,6 +37,7 @@
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyString;
import org.jruby.ast.types.INameNode;
import org.jruby.ast.visitor.NodeVisitor;
import org.jruby.evaluator.ASTInterpreter;
Expand All @@ -52,6 +53,7 @@
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.DefinedMessage;

/**
* A method or operator call.
Expand Down Expand Up @@ -171,7 +173,7 @@ public IRubyObject assign(Ruby runtime, ThreadContext context, IRubyObject self,
}

@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
if (receiverNode.definition(runtime, context, self, aBlock) != null) {
try {
IRubyObject receiver = receiverNode.interpret(runtime, context, self, aBlock);
Expand All @@ -182,7 +184,7 @@ public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self
if (visibility != Visibility.PRIVATE &&
(visibility != Visibility.PROTECTED || metaClass.getRealClass().isInstance(self))) {
if (!method.isUndefined()) {
return ASTInterpreter.getArgumentDefinition(runtime, context, getArgsNode(), METHOD_BYTELIST, self, aBlock);
return ASTInterpreter.getArgumentDefinition(runtime, context, getArgsNode(), context.runtime.getDefinedMessage(DefinedMessage.METHOD), self, aBlock);
}
}
} catch (JumpException excptn) {
Expand Down
11 changes: 6 additions & 5 deletions src/org/jruby/ast/ClassVarNode.java
Expand Up @@ -36,6 +36,7 @@
import org.jruby.MetaClass;
import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.RubyString;
import org.jruby.ast.types.INameNode;
import org.jruby.ast.visitor.NodeVisitor;
import org.jruby.evaluator.ASTInterpreter;
Expand All @@ -44,6 +45,7 @@
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.DefinedMessage;

/**
* Access to a class variable.
Expand Down Expand Up @@ -94,20 +96,19 @@ public IRubyObject interpret(Ruby runtime, ThreadContext context, IRubyObject se
}

@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
//RubyModule module = context.getRubyClass();
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
RubyModule module = context.getCurrentScope().getStaticScope().getModule();

if (module == null && self.getMetaClass().isClassVarDefined(name)) {
return CLASS_VARIABLE_BYTELIST;
return runtime.getDefinedMessage(DefinedMessage.CLASS_VARIABLE);
} else if (module.isClassVarDefined(name)) {
return CLASS_VARIABLE_BYTELIST;
return runtime.getDefinedMessage(DefinedMessage.CLASS_VARIABLE);
}

IRubyObject attached = module.isSingleton() ? ((MetaClass)module).getAttached() : null;

if (attached instanceof RubyModule && ((RubyModule) attached).isClassVarDefined(name)) {
return CLASS_VARIABLE_BYTELIST;
return runtime.getDefinedMessage(DefinedMessage.CLASS_VARIABLE);
}

return null;
Expand Down
9 changes: 7 additions & 2 deletions src/org/jruby/ast/Colon2ConstNode.java
Expand Up @@ -7,13 +7,15 @@

import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.RubyString;
import org.jruby.exceptions.JumpException;
import org.jruby.javasupport.util.RuntimeHelpers;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.DefinedMessage;

/**
*
Expand All @@ -39,10 +41,13 @@ public IRubyObject interpret(Ruby runtime, ThreadContext context, IRubyObject se
}

@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
IRubyObject lastError = context.getErrorInfo();
try {
if (RuntimeHelpers.isModuleAndHasConstant(leftNode.interpret(runtime, context, self, aBlock), name)) return CONSTANT_BYTELIST;
if (RuntimeHelpers.isModuleAndHasConstant(
leftNode.interpret(runtime, context, self, aBlock), name)) {
return runtime.getDefinedMessage(DefinedMessage.CONSTANT);
}
} catch (JumpException e) {
// replace lastError
context.setErrorInfo(lastError);
Expand Down
3 changes: 2 additions & 1 deletion src/org/jruby/ast/Colon2ImplicitNode.java
Expand Up @@ -30,6 +30,7 @@

import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.RubyString;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
Expand Down Expand Up @@ -69,7 +70,7 @@ public IRubyObject interpret(Ruby runtime, ThreadContext context, IRubyObject se
* appear to be a ConstNode.
*/
@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
assert false: "definition should not ever happen for Colon2ImplicitNode";
return null;
}
Expand Down
8 changes: 6 additions & 2 deletions src/org/jruby/ast/Colon2MethodNode.java
Expand Up @@ -6,13 +6,15 @@
package org.jruby.ast;

import org.jruby.Ruby;
import org.jruby.RubyString;
import org.jruby.exceptions.JumpException;
import org.jruby.javasupport.util.RuntimeHelpers;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.DefinedMessage;

/**
* Represents a constant path which ends in a method (e.g. Foo::bar). Note: methods with
Expand All @@ -31,9 +33,11 @@ public IRubyObject interpret(Ruby runtime, ThreadContext context, IRubyObject se
}

@Override
public ByteList definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
public RubyString definition(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
try {
if (hasMethod(leftNode.interpret(runtime, context, self, aBlock))) return METHOD_BYTELIST;
if (hasMethod(leftNode.interpret(runtime, context, self, aBlock))) {
return runtime.getDefinedMessage(DefinedMessage.METHOD);
}
} catch (JumpException e) {
}

Expand Down

0 comments on commit b03d0bc

Please sign in to comment.