Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/ir/instructions/CallBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ public boolean computeScopeFlags(IRScope scope, EnumSet<IRFlags> flags) {
modifiedScope |= setIRFlagsFromFrameFields(flags, frameReads);
modifiedScope |= setIRFlagsFromFrameFields(flags, frameWrites);

if (getId().equals("block_given?") && argsCount == 0) {
// remove frame read from flags for optimizable methods
flags.remove(REQUIRES_BLOCK);
}

// literal closures can be used to capture surrounding binding
if (hasLiteralClosure()) {
modifiedScope = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,11 @@ public static RubyModule findInstanceMethodContainer(ThreadContext context, Dyna
public static RubyBoolean isBlockGiven(ThreadContext context, Object blk) {
if (blk instanceof RubyProc) blk = ((RubyProc) blk).getBlock();
if (blk instanceof RubyNil) blk = Block.NULL_BLOCK;
return RubyBoolean.newBoolean(context, ((Block) blk).isGiven() );
return isBlockGiven(context, (Block) blk);
}

public static RubyBoolean isBlockGiven(ThreadContext context, Block blk) {
return RubyBoolean.newBoolean(context, blk != null && blk.isGiven() );
}

@JIT @Interp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ public void invokeSelf(String file, String scopeFieldName, CallBase call, int ar

int flags = call.getFlags();

if (id.equals("block_given?") && arity == 0) {
// specialized call site for block_given? that passes given block through
compiler.loadBlock();
compiler.adapter.invokedynamic("callFunctional:" + JavaNameMangler.mangleMethodName(id), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, Block.class)), SelfInvokeSite.BOOTSTRAP, false, flags, file, compiler.getLastLine());
return;
}

String action = call.getCallType() == CallType.FUNCTIONAL ? "callFunctional" : "callVariable";
IRBytecodeAdapter.BlockPassType blockPassType = IRBytecodeAdapter.BlockPassType.fromIR(call);
if (blockPassType != IRBytecodeAdapter.BlockPassType.NONE) {
Expand Down
29 changes: 29 additions & 0 deletions core/src/main/java/org/jruby/ir/targets/indy/InvokeSite.java
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,15 @@ private IRubyObject performIndirectCall(ThreadContext context, IRubyObject self,
RubyModule sourceModule = entry.sourceModule;
DynamicMethod method = entry.method;

if (methodName.equals("block_given?") && arity == 0) {
if (method.isBuiltin()) {
return RubyBoolean.newBoolean(context, block != null && block.isGiven());
}

// omit block if it's not builtin, dispatch normally
return method.call(context, self, sourceModule, methodName, args);
}

IRRuntimeHelpers.setCallInfo(context, flags);

if (literalClosure) {
Expand Down Expand Up @@ -522,6 +531,7 @@ protected MethodHandle getHandle(IRubyObject self, CacheEntry entry) throws Thro
boolean blockGiven = signature.lastArgType() == Block.class;

MethodHandle mh = buildNewInstanceHandle(entry, self);
if (mh == null) mh = buildBlockGivenHandle(entry, self);
if (mh == null) mh = buildNotEqualHandle(entry, self);
if (mh == null) mh = Bootstrap.buildNativeHandle(this, entry, blockGiven);
if (mh == null) mh = buildJavaFieldHandle(this, entry, self);
Expand Down Expand Up @@ -647,6 +657,25 @@ MethodHandle buildNewInstanceHandle(CacheEntry entry, IRubyObject self) {
return mh;
}

MethodHandle buildBlockGivenHandle(CacheEntry entry, IRubyObject self) {
MethodHandle mh = null;
DynamicMethod method = entry.method;

if ("block_given?".equals(method.getName()) && method.isBuiltin()) {
mh = Binder.from(type())
.drop(1, 1)
.printType()
.cast(RubyBoolean.class, ThreadContext.class, Block.class)
.invokeStaticQuiet(LOOKUP, IRRuntimeHelpers.class, "isBlockGiven");

if (Options.INVOKEDYNAMIC_LOG_BINDING.load()) {
LOG.info(name() + "\tbound as fast block given check " + Bootstrap.logMethod(method));
}
}

return mh;
}

MethodHandle buildNotEqualHandle(CacheEntry entry, IRubyObject self) {
MethodHandle mh = null;
DynamicMethod method = entry.method;
Expand Down