-
-
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.
[Truffle] Optimize dispatch for singleton objects.
* Since they are singleton, checking against the object itself is the same as checking against its metaclass. Compared to checking the Shape, it is actually a wider check as the Shape could change.
- 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
- 9.0.5.0
- 9.0.4.0
- 9.0.3.0
- 9.0.1.0
Showing
2 changed files
with
166 additions
and
1 deletion.
There are no files selected for viewing
161 changes: 161 additions & 0 deletions
161
truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedSingletonDispatchNode.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,161 @@ | ||
/* | ||
* Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved. This | ||
* code is released under a tri EPL/GPL/LGPL license. You can use it, | ||
* redistribute it and/or modify it under the terms of the: | ||
* | ||
* Eclipse Public License version 1.0 | ||
* GNU General Public License version 2 | ||
* GNU Lesser General Public License version 2.1 | ||
*/ | ||
package org.jruby.truffle.nodes.dispatch; | ||
|
||
import com.oracle.truffle.api.Assumption; | ||
import com.oracle.truffle.api.Truffle; | ||
import com.oracle.truffle.api.frame.VirtualFrame; | ||
import com.oracle.truffle.api.nodes.DirectCallNode; | ||
import com.oracle.truffle.api.nodes.IndirectCallNode; | ||
import com.oracle.truffle.api.nodes.InvalidAssumptionException; | ||
import com.oracle.truffle.api.object.DynamicObject; | ||
|
||
import org.jruby.truffle.nodes.RubyGuards; | ||
import org.jruby.truffle.runtime.RubyArguments; | ||
import org.jruby.truffle.runtime.RubyContext; | ||
import org.jruby.truffle.runtime.layouts.Layouts; | ||
import org.jruby.truffle.runtime.methods.InternalMethod; | ||
|
||
/** | ||
* Like {@link CachedBoxedDispatchNode}, but on singleton objects. | ||
* Checking identity of the DynamicObject is therefore faster than reading the Shape and checking the Shape identity. | ||
*/ | ||
public class CachedSingletonDispatchNode extends CachedDispatchNode { | ||
|
||
private final DynamicObject expectedReceiver; | ||
private final Assumption unmodifiedAssumption; | ||
|
||
private final InternalMethod method; | ||
@Child private DirectCallNode callNode; | ||
@Child private IndirectCallNode indirectCallNode; | ||
|
||
public CachedSingletonDispatchNode( | ||
RubyContext context, | ||
Object cachedName, | ||
DispatchNode next, | ||
DynamicObject expectedReceiver, | ||
DynamicObject expectedClass, | ||
InternalMethod method, | ||
boolean indirect, | ||
DispatchAction dispatchAction) { | ||
super(context, cachedName, next, indirect, dispatchAction); | ||
|
||
assert RubyGuards.isRubyClass(expectedClass); | ||
|
||
this.expectedReceiver = expectedReceiver; | ||
this.unmodifiedAssumption = Layouts.MODULE.getFields(expectedClass).getUnmodifiedAssumption(); | ||
this.next = next; | ||
this.method = method; | ||
|
||
if (method != null) { | ||
if (indirect) { | ||
indirectCallNode = Truffle.getRuntime().createIndirectCallNode(); | ||
} else { | ||
callNode = Truffle.getRuntime().createDirectCallNode(method.getCallTarget()); | ||
|
||
if ((callNode.isCallTargetCloningAllowed() && method.getSharedMethodInfo().shouldAlwaysSplit()) | ||
|| (method.getDeclaringModule() != null | ||
&& Layouts.MODULE.getFields(method.getDeclaringModule()).getName().equals("TruffleInterop"))) { | ||
insert(callNode); | ||
callNode.cloneCallTarget(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public boolean guard(Object methodName, Object receiver) { | ||
return guardName(methodName) && | ||
receiver == expectedReceiver; | ||
} | ||
|
||
@Override | ||
public Object executeDispatch( | ||
VirtualFrame frame, | ||
Object receiverObject, | ||
Object methodName, | ||
Object blockObject, | ||
Object argumentsObjects) { | ||
if (!guard(methodName, receiverObject)) { | ||
return next.executeDispatch( | ||
frame, | ||
receiverObject, | ||
methodName, | ||
blockObject, | ||
argumentsObjects); | ||
} | ||
|
||
// Check the class has not been modified | ||
|
||
try { | ||
unmodifiedAssumption.check(); | ||
} catch (InvalidAssumptionException e) { | ||
return resetAndDispatch( | ||
frame, | ||
receiverObject, | ||
methodName, | ||
(DynamicObject) blockObject, | ||
argumentsObjects, | ||
"class modified"); | ||
} | ||
|
||
switch (getDispatchAction()) { | ||
case CALL_METHOD: { | ||
if (isIndirect()) { | ||
return indirectCallNode.call( | ||
frame, | ||
method.getCallTarget(), | ||
RubyArguments.pack( | ||
method, | ||
method.getDeclarationFrame(), | ||
expectedReceiver, | ||
(DynamicObject) blockObject, | ||
(Object[]) argumentsObjects)); | ||
} else { | ||
return callNode.call( | ||
frame, | ||
RubyArguments.pack( | ||
method, | ||
method.getDeclarationFrame(), | ||
expectedReceiver, | ||
(DynamicObject) blockObject, | ||
(Object[]) argumentsObjects)); | ||
} | ||
} | ||
|
||
case RESPOND_TO_METHOD: | ||
return true; | ||
|
||
default: | ||
throw new UnsupportedOperationException(); | ||
} | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return String.format("CachedBoxedDispatchNode(:%s, %s@%x, %s)", | ||
getCachedNameAsSymbol().toString(), | ||
expectedReceiver, expectedReceiver.hashCode(), | ||
method == null ? "null" : method.toString()); | ||
} | ||
|
||
public boolean couldOptimizeKeywordArguments() { | ||
// TODO CS 18-Apr-15 doesn't seem to work with Truffle? | ||
return false; //method.getSharedMethodInfo().getArity().getKeywordArguments() != null && next instanceof UnresolvedDispatchNode; | ||
} | ||
|
||
public InternalMethod getMethod() { | ||
return method; | ||
} | ||
|
||
public Assumption getUnmodifiedAssumption() { | ||
return unmodifiedAssumption; | ||
} | ||
} |
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