-
-
Notifications
You must be signed in to change notification settings - Fork 925
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement optimized a["b"] with pre-frozen hash key and lazy dup.
This is the last missing optimization using frozen strings; see
- 9.4.12.0
- 9.4.11.0
- 9.4.10.0
- 9.4.9.0
- 9.4.8.0
- 9.4.7.0
- 9.4.6.0
- 9.4.5.0
- 9.4.4.0
- 9.4.3.0
- 9.4.2.0
- 9.4.1.0
- 9.4.0.0
- 9.3.15.0
- 9.3.14.0
- 9.3.13.0
- 9.3.12.0
- 9.3.11.0
- 9.3.10.0
- 9.3.9.0
- 9.3.8.0
- 9.3.7.0
- 9.3.6.0
- 9.3.5.0
- 9.3.4.0
- 9.3.3.0
- 9.3.2.0
- 9.3.1.0
- 9.3.0.0
- 9.2.21.0
- 9.2.20.1
- 9.2.20.0
- 9.2.19.0
- 9.2.18.0
- 9.2.17.0
- 9.2.16.0
- 9.2.15.0
- 9.2.14.0
- 9.2.13.0
- 9.2.12.0
- 9.2.11.1
- 9.2.11.0
- 9.2.10.0
- 9.2.9.0
- 9.2.8.0
- 9.2.7.0
- 9.2.6.0
- 9.2.5.0
- 9.2.4.1
- 9.2.4.0
- 9.2.3.0
- 9.2.2.0
- 9.2.1.0
- 9.2.0.0
- 9.1.17.0
- 9.1.16.0
- 9.1.15.0
- 9.1.14.0
- 9.1.13.0
- 9.1.12.0
- 9.1.11.0
- 9.1.10.0
- 9.1.9.0
- 9.1.8.0
- 9.1.7.0
- 9.1.6.0
- 9.1.5.0
- 9.1.4.0
- 9.1.3.0
- 9.1.2.0
- 9.1.1.0
- 9.1.0.0
Showing
14 changed files
with
313 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
core/src/main/java/org/jruby/ir/instructions/ArrayDerefInstr.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package org.jruby.ir.instructions; | ||
|
||
import org.jruby.RubyInstanceConfig; | ||
import org.jruby.RubyString; | ||
import org.jruby.ir.IRScope; | ||
import org.jruby.ir.IRVisitor; | ||
import org.jruby.ir.Operation; | ||
import org.jruby.ir.instructions.specialized.OneOperandArgNoBlockCallInstr; | ||
import org.jruby.ir.operands.FrozenString; | ||
import org.jruby.ir.operands.Operand; | ||
import org.jruby.ir.operands.Variable; | ||
import org.jruby.ir.persistence.IRReaderDecoder; | ||
import org.jruby.ir.persistence.IRWriterEncoder; | ||
import org.jruby.ir.runtime.IRRuntimeHelpers; | ||
import org.jruby.ir.transformations.inlining.CloneInfo; | ||
import org.jruby.parser.StaticScope; | ||
import org.jruby.runtime.CallType; | ||
import org.jruby.runtime.DynamicScope; | ||
import org.jruby.runtime.ThreadContext; | ||
import org.jruby.runtime.builtin.IRubyObject; | ||
|
||
import static org.jruby.ir.IRFlags.REQUIRES_FRAME; | ||
|
||
/** | ||
* Instruction representing Ruby code of the form: "a['str']" | ||
* which is equivalent to: a.[]('str'). Because a Hash receiver | ||
* would immediately freeze the string, we can freeze and dedup | ||
* the string ahead of time and call [] directly. | ||
*/ | ||
public class ArrayDerefInstr extends OneOperandArgNoBlockCallInstr { | ||
private final FrozenString key; | ||
|
||
public static ArrayDerefInstr create(Variable result, Operand obj, FrozenString arg0) { | ||
return new ArrayDerefInstr(result, obj, arg0); | ||
} | ||
|
||
public ArrayDerefInstr(Variable result, Operand obj, FrozenString arg0) { | ||
super(Operation.ARRAY_DEREF, CallType.FUNCTIONAL, result, "[]", obj, new Operand[] {arg0}, false); | ||
|
||
key = arg0; | ||
} | ||
|
||
@Override | ||
public boolean computeScopeFlags(IRScope scope) { | ||
// CON: No native [] impls require backref/lastline for a literal String arg, | ||
// so we don't have to deopt frame here. | ||
super.computeScopeFlags(scope); | ||
return true; | ||
} | ||
|
||
@Override | ||
public Instr clone(CloneInfo ii) { | ||
return new ArrayDerefInstr((Variable) getResult().cloneForInlining(ii), getReceiver().cloneForInlining(ii), key); | ||
} | ||
|
||
@Override | ||
public void encode(IRWriterEncoder e) { | ||
if (RubyInstanceConfig.IR_WRITING_DEBUG) System.out.println("Instr(" + getOperation() + "): " + this); | ||
e.encode(getOperation()); | ||
e.encode(getResult()); | ||
e.encode(getReceiver()); | ||
e.encode(getArg1()); | ||
} | ||
|
||
public static ArrayDerefInstr decode(IRReaderDecoder d) { | ||
return create(d.decodeVariable(), d.decodeOperand(), (FrozenString) d.decodeOperand()); | ||
} | ||
|
||
@Override | ||
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope dynamicScope, IRubyObject self, Object[] temp) { | ||
IRubyObject object = (IRubyObject) getReceiver().retrieve(context, self, currScope, dynamicScope, temp); | ||
RubyString keyStr = (RubyString) key.retrieve(context, self, currScope, dynamicScope, temp); | ||
|
||
return IRRuntimeHelpers.callOptimizedAref(context, self, object, keyStr, getCallSite()); | ||
} | ||
|
||
@Override | ||
public void visit(IRVisitor visitor) { | ||
visitor.ArrayDerefInstr(this); | ||
} | ||
|
||
public FrozenString getKey() { | ||
return key; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 116 additions & 0 deletions
116
core/src/main/java/org/jruby/ir/targets/ArrayDerefInvokeSite.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package org.jruby.ir.targets; | ||
|
||
import com.headius.invokebinder.Binder; | ||
import com.headius.invokebinder.SmartBinder; | ||
import org.jruby.RubyClass; | ||
import org.jruby.RubyHash; | ||
import org.jruby.RubyString; | ||
import org.jruby.internal.runtime.methods.DynamicMethod; | ||
import org.jruby.ir.runtime.IRRuntimeHelpers; | ||
import org.jruby.runtime.Block; | ||
import org.jruby.runtime.CallType; | ||
import org.jruby.runtime.ThreadContext; | ||
import org.jruby.runtime.builtin.IRubyObject; | ||
import org.jruby.runtime.callsite.CacheEntry; | ||
import org.jruby.runtime.callsite.FunctionalCachingCallSite; | ||
import org.jruby.util.JavaNameMangler; | ||
import org.objectweb.asm.Handle; | ||
import org.objectweb.asm.Opcodes; | ||
|
||
import java.lang.invoke.CallSite; | ||
import java.lang.invoke.MethodHandle; | ||
import java.lang.invoke.MethodHandles; | ||
import java.lang.invoke.MethodType; | ||
import java.lang.invoke.SwitchPoint; | ||
|
||
import static org.jruby.util.CodegenUtils.p; | ||
import static org.jruby.util.CodegenUtils.sig; | ||
|
||
/** | ||
* Created by headius on 10/23/14. | ||
*/ | ||
public class ArrayDerefInvokeSite extends NormalInvokeSite { | ||
public ArrayDerefInvokeSite(MethodType type) { | ||
super(type, "[]"); | ||
} | ||
|
||
public static final Handle BOOTSTRAP = new Handle(Opcodes.H_INVOKESTATIC, p(ArrayDerefInvokeSite.class), "bootstrap", sig(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class)); | ||
|
||
public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) { | ||
InvokeSite site = new ArrayDerefInvokeSite(type); | ||
|
||
return InvokeSite.bootstrap(site, lookup); | ||
} | ||
|
||
public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject[] args, Block block) throws Throwable { | ||
RubyClass selfClass = pollAndGetClass(context, self); | ||
|
||
MethodHandle mh; | ||
|
||
CacheEntry entry = selfClass.searchWithCache(methodName); | ||
DynamicMethod method = entry.method; | ||
|
||
if (method.isBuiltin() && selfClass == context.runtime.getHash()) { | ||
// fast path since we know we're working with a normal hash and have a pre-frozen string | ||
mh = SmartBinder.from(signature) | ||
.permute("self", "context", "arg0") | ||
.cast(IRubyObject.class, RubyHash.class, ThreadContext.class, IRubyObject.class) | ||
.invokeVirtual(MethodHandles.publicLookup(), "op_aref") | ||
.handle(); | ||
|
||
SwitchPoint switchPoint = (SwitchPoint) selfClass.getInvalidator().getData(); | ||
|
||
updateInvocationTarget(mh, self, selfClass, method, switchPoint); | ||
|
||
return ((RubyHash) self).fastARef(args[0]); | ||
} else { | ||
// slow path follows normal invoke logic with a strDup for the key | ||
SwitchPoint switchPoint = (SwitchPoint) selfClass.getInvalidator().getData(); | ||
|
||
// strdup for this call | ||
args[0] = ((RubyString) args[0]).strDup(context.runtime); | ||
|
||
if (methodMissing(entry, caller)) { | ||
return callMethodMissing(entry, callType, context, self, methodName, args, block); | ||
} | ||
|
||
mh = getHandle(self, selfClass, method); | ||
// strdup for future calls | ||
mh = MethodHandles.filterArguments(mh, 3, STRDUP_FILTER); | ||
|
||
updateInvocationTarget(mh, self, selfClass, entry.method, switchPoint); | ||
|
||
return method.call(context, self, selfClass, methodName, args, block); | ||
} | ||
} | ||
|
||
/** | ||
* Failover version uses a monomorphic cache and DynamicMethod.call, as in non-indy. | ||
*/ | ||
public IRubyObject fail(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject[] args, Block block) throws Throwable { | ||
RubyClass selfClass = pollAndGetClass(context, self); | ||
String name = methodName; | ||
CacheEntry entry = cache; | ||
|
||
// strdup for all calls | ||
args[0] = ((RubyString) args[0]).strDup(context.runtime); | ||
|
||
if (entry.typeOk(selfClass)) { | ||
return entry.method.call(context, self, selfClass, name, args, block); | ||
} | ||
|
||
entry = selfClass.searchWithCache(name); | ||
|
||
if (methodMissing(entry, caller)) { | ||
return callMethodMissing(entry, callType, context, self, name, args, block); | ||
} | ||
|
||
cache = entry; | ||
|
||
return entry.method.call(context, self, selfClass, name, args, block); | ||
} | ||
|
||
private static final MethodHandle STRDUP_FILTER = Binder.from(IRubyObject.class, IRubyObject.class) | ||
.cast(RubyString.class, RubyString.class) | ||
.invokeVirtualQuiet(MethodHandles.publicLookup(), "strDup"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters