Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9d52bae649d6
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 046ed6e17dfe
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Jul 9, 2018

  1. Verified

    This commit was signed with the committer’s verified signature.
    headius Charles Oliver Nutter
    Copy the full SHA
    7d9b0ef View commit details
  2. Verified

    This commit was signed with the committer’s verified signature.
    headius Charles Oliver Nutter
    Copy the full SHA
    046ed6e View commit details
8 changes: 3 additions & 5 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -1253,16 +1253,15 @@ public IRubyObject op_not(ThreadContext context) {
}

/**
* The != method implemented for BasicObject. Note that this version is currently
* replaced by a Ruby version in basicobject.rb for better caching characteristics.
* The != method implemented for BasicObject.
*
* @param context thread context
* @param other other object
* @return false if this == other, true otherwise
*/
@JRubyMethod(name = "!=", required = 1)
public IRubyObject op_not_equal(ThreadContext context, IRubyObject other) {
return context.runtime.newBoolean(!invokedynamic(context, this, OP_EQUAL, other).isTrue());
return context.runtime.newBoolean(!sites(context).op_equal.call(context, this, this, other).isTrue());
}

/**
@@ -2802,8 +2801,7 @@ public IRubyObject op_match19(ThreadContext context, IRubyObject arg) {
}

/**
* Invert the match operator. Note that this version is currently
* replaced by a Ruby version in basicobject.rb for better caching characteristics.
* Invert the match operator.
*
* @param context
* @param arg
54 changes: 47 additions & 7 deletions core/src/main/java/org/jruby/ir/targets/InvokeSite.java
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

import static java.lang.invoke.MethodHandles.insertArguments;
import static java.lang.invoke.MethodHandles.lookup;

/**
@@ -175,7 +176,8 @@ public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject
return method.call(context, self, selfClass, methodName, args, block);
}

private static final MethodHandle ESCAPE_BLOCK = Binder.from(void.class, Block.class).invokeVirtualQuiet(lookup(), "escape");
private static final MethodHandles.Lookup LOOKUP = lookup();
private static final MethodHandle ESCAPE_BLOCK = Binder.from(void.class, Block.class).invokeVirtualQuiet(LOOKUP, "escape");
private static final Map<Signature, MethodHandle> BLOCK_ESCAPES = Collections.synchronizedMap(new HashMap<Signature, MethodHandle>());

private static MethodHandle getBlockEscape(Signature signature) {
@@ -326,6 +328,7 @@ MethodHandle getHandle(IRubyObject self, RubyClass dispatchClass, DynamicMethod
boolean blockGiven = signature.lastArgType() == Block.class;

MethodHandle mh = buildNewInstanceHandle(method, self);
if (mh == null) mh = buildNotEqualHandle(method, self);
if (mh == null) mh = Bootstrap.buildNativeHandle(this, method, blockGiven);
if (mh == null) mh = Bootstrap.buildIndyHandle(this, method, method.getImplementationClass());
if (mh == null) mh = Bootstrap.buildJittedHandle(this, method, blockGiven);
@@ -345,15 +348,15 @@ MethodHandle buildNewInstanceHandle(DynamicMethod method, IRubyObject self) {
RubyClass recvClass = (RubyClass) self;

// Bind a second site as a dynamic invoker to guard against changes in new object's type
CallSite initSite = SelfInvokeSite.bootstrap(lookup(), "callFunctional:initialize", type(), literalClosure ? 1 : 0, file, line);
CallSite initSite = SelfInvokeSite.bootstrap(LOOKUP, "callFunctional:initialize", type(), literalClosure ? 1 : 0, file, line);
MethodHandle initHandle = initSite.dynamicInvoker();

MethodHandle allocFilter = Binder.from(IRubyObject.class, IRubyObject.class)
.cast(IRubyObject.class, RubyClass.class)
.insert(0, new Class[] {ObjectAllocator.class, Ruby.class}, recvClass.getAllocator(), self.getRuntime())
.invokeVirtualQuiet(lookup(), "allocate");
.invokeVirtualQuiet(LOOKUP, "allocate");

mh = SmartBinder.from(lookup(), signature)
mh = SmartBinder.from(LOOKUP, signature)
.filter("self", allocFilter)
.fold("dummy", initHandle)
.permute("self")
@@ -368,6 +371,43 @@ MethodHandle buildNewInstanceHandle(DynamicMethod method, IRubyObject self) {
return mh;
}

MethodHandle buildNotEqualHandle(DynamicMethod method, IRubyObject self) {
MethodHandle mh = null;

Ruby runtime = self.getRuntime();

if (method.isBuiltin()) {

CallSite equalSite = null;

if (method.getImplementationClass() == runtime.getBasicObject() && name().equals("!=")) {
equalSite = SelfInvokeSite.bootstrap(LOOKUP, "callFunctional:==", type(), literalClosure ? 1 : 0, file, line);
} else if (method.getImplementationClass() == runtime.getKernel() && name().equals("!~")) {
equalSite = SelfInvokeSite.bootstrap(LOOKUP, "callFunctional:=~", type(), literalClosure ? 1 : 0, file, line);
}

if (equalSite != null) {
// Bind a second site as a dynamic invoker to guard against changes in new object's type
MethodHandle equalHandle = equalSite.dynamicInvoker();

MethodHandle filter = insertArguments(NEGATE, 1, runtime.getNil(), runtime.getTrue(), runtime.getFalse());
mh = MethodHandles.filterReturnValue(equalHandle, filter);

if (Options.INVOKEDYNAMIC_LOG_BINDING.load()) {
LOG.info(name() + "\tbound as new instance creation " + Bootstrap.logMethod(method));
}
}
}

return mh;
}

public static final MethodHandle NEGATE = Binder.from(IRubyObject.class, IRubyObject.class, RubyNil.class, RubyBoolean.True.class, RubyBoolean.False.class).invokeStaticQuiet(LOOKUP, InvokeSite.class, "negate");

public static IRubyObject negate(IRubyObject object, RubyNil nil, RubyBoolean.True tru, RubyBoolean.False fals) {
return object == nil || object == fals ? tru : fals;
}

MethodHandle buildAliasHandle(DynamicMethod method, IRubyObject self, RubyClass dispatchClass) throws Throwable {
MethodHandle mh = null;

@@ -377,7 +417,7 @@ MethodHandle buildAliasHandle(DynamicMethod method, IRubyObject self, RubyClass
String name = alias.getName();

// Use a second site to mimic invocation from AliasMethod
InvokeSite innerSite = (InvokeSite) SelfInvokeSite.bootstrap(lookup(), "callFunctional:" + name, type(), literalClosure ? 1 : 0, file, line);
InvokeSite innerSite = (InvokeSite) SelfInvokeSite.bootstrap(LOOKUP, "callFunctional:" + name, type(), literalClosure ? 1 : 0, file, line);
mh = innerSite.getHandle(self, dispatchClass, innerMethod);

alias.setHandle(mh);
@@ -488,7 +528,7 @@ private void logFail() {

private MethodHandle bindToFail() {
MethodHandle target;
setTarget(target = prepareBinder(false).invokeVirtualQuiet(lookup(), "fail"));
setTarget(target = prepareBinder(false).invokeVirtualQuiet(LOOKUP, "fail"));
return target;
}

@@ -582,5 +622,5 @@ public String toString() {

private static final MethodHandle TEST_CLASS = Binder
.from(boolean.class, Object.class, Class.class)
.invokeStaticQuiet(lookup(), InvokeSite.class, "testClass");
.invokeStaticQuiet(LOOKUP, InvokeSite.class, "testClass");
}
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/runtime/JavaSites.java
Original file line number Diff line number Diff line change
@@ -8,6 +8,8 @@
import org.jruby.runtime.callsite.FunctionalCachingCallSite;
import org.jruby.runtime.callsite.RespondToCallSite;

import java.lang.invoke.MutableCallSite;

import static org.jruby.runtime.invokedynamic.MethodNames.OP_CMP;

/**
@@ -64,6 +66,7 @@ public static class BasicObjectSites {
public final CallSite inspect = new FunctionalCachingCallSite("inspect");
public final CallSite match = new FunctionalCachingCallSite("=~");
public final CallSite call = new FunctionalCachingCallSite("call");
public final CallSite op_equal = new FunctionalCachingCallSite("==");
}

public static class ObjectSites {
1 change: 0 additions & 1 deletion core/src/main/ruby/jruby/kernel.rb
Original file line number Diff line number Diff line change
@@ -29,7 +29,6 @@ module JRuby
load 'jruby/kernel/gc.rb'
load 'jruby/kernel/range.rb'
load 'jruby/kernel/file.rb'
load 'jruby/kernel/basicobject.rb'
load 'jruby/kernel/hash.rb'
load 'jruby/kernel/string.rb'

10 changes: 0 additions & 10 deletions core/src/main/ruby/jruby/kernel/basicobject.rb

This file was deleted.