Skip to content

Commit

Permalink
Move remaining logical chunks out of Bootstrap
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Oct 26, 2023
1 parent f21f7d5 commit 842327c
Show file tree
Hide file tree
Showing 16 changed files with 425 additions and 326 deletions.
4 changes: 4 additions & 0 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -5108,6 +5108,10 @@ private RaiseException cannotRemoveError(String id) {
return getRuntime().newNameError(str(runtime, "cannot remove ", ids(runtime, id), " for ", types(runtime, this)), id);
}

public static boolean testModuleMatch(ThreadContext context, IRubyObject arg0, int id) {
return arg0 instanceof RubyModule && ((RubyModule) arg0).id == id;
}


//
////////////////// INTERNAL MODULE VARIABLE API METHODS ////////////////
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@
import org.jruby.ir.representations.BasicBlock;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.ir.targets.IRBytecodeAdapter.BlockPassType;
import org.jruby.ir.targets.indy.Bootstrap;
import org.jruby.ir.targets.indy.CallTraceSite;
import org.jruby.ir.targets.indy.CoverageSite;
import org.jruby.ir.targets.indy.MetaClassBootstrap;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.ArgumentDescriptor;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallType;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.Frame;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.RubyEvent;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
Expand Down Expand Up @@ -1515,7 +1515,7 @@ public void DefineMetaClassInstr(DefineMetaClassInstr definemetaclassinstr) {
jvmAdapter().invokedynamic(
"openMetaClass",
sig(DynamicMethod.class, ThreadContext.class, IRubyObject.class, String.class, StaticScope.class),
Bootstrap.OPEN_META_CLASS,
MetaClassBootstrap.OPEN_META_CLASS,
bodyHandle,
scopeHandle,
setScopeHandle,
Expand Down Expand Up @@ -1738,7 +1738,7 @@ public void LineNumberInstr(LineNumberInstr linenumberinstr) {
jvmAdapter().invokedynamic(
"coverLine",
sig(void.class, ThreadContext.class),
Bootstrap.coverLineHandle(),
CoverageSite.COVER_LINE_BOOTSTRAP,
jvm.methodData().scope.getFile(),
linenumberinstr.getLineNumber(),
linenumberinstr.oneshot ? 1 : 0);
Expand Down
315 changes: 4 additions & 311 deletions core/src/main/java/org/jruby/ir/targets/indy/Bootstrap.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.jruby.ir.targets.indy;

import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.runtime.ThreadContext;
import org.objectweb.asm.Handle;

import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

import static java.lang.invoke.MethodHandles.insertArguments;
import static java.lang.invoke.MethodType.methodType;

public class CallInfoBootstrap {
public static final Handle CALL_INFO_BOOTSTRAP = Bootstrap.getBootstrapHandle("callInfoBootstrap", Bootstrap.BOOTSTRAP_INT_SIG);

public static CallSite callInfoBootstrap(MethodHandles.Lookup lookup, String name, MethodType type, int callInfo) throws Throwable {
MethodHandle handle;
if (callInfo == 0) {
handle = lookup.findVirtual(ThreadContext.class, "clearCallInfo", methodType(void.class));
} else {
handle = lookup.findStatic(IRRuntimeHelpers.class, "setCallInfo", methodType(void.class, ThreadContext.class, int.class));
handle = insertArguments(handle, 1, callInfo);
}

return new ConstantCallSite(handle);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.jruby.ir.targets.indy;

import org.jruby.runtime.CallType;
import org.jruby.runtime.callsite.CachingCallSite;
import org.jruby.runtime.callsite.FunctionalCachingCallSite;
import org.jruby.runtime.callsite.MonomorphicCallSite;
import org.jruby.runtime.callsite.VariableCachingCallSite;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;

import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

import static java.lang.invoke.MethodHandles.constant;
import static org.jruby.util.CodegenUtils.p;
import static org.jruby.util.CodegenUtils.sig;

public class CallSiteCacheBootstrap {
public static final Handle CALLSITE = new Handle(
Opcodes.H_INVOKESTATIC,
p(Bootstrap.class),
"callSite",
sig(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, String.class, int.class),
false);

public static CallSite callSite(MethodHandles.Lookup lookup, String name, MethodType type, String id, int callType) {
return new ConstantCallSite(constant(CachingCallSite.class, callSite(id, callType)));
}

private static CachingCallSite callSite(String id, int callType) {
switch (CallType.fromOrdinal(callType)) {
case NORMAL:
return new MonomorphicCallSite(id);
case FUNCTIONAL:
return new FunctionalCachingCallSite(id);
case VARIABLE:
return new VariableCachingCallSite(id);
default:
throw new RuntimeException("BUG: Unexpected call type " + callType + " in JVM6 invoke logic");
}
}
}
53 changes: 53 additions & 0 deletions core/src/main/java/org/jruby/ir/targets/indy/CheckpointSite.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.jruby.ir.targets.indy;

import com.headius.invokebinder.Binder;
import org.jruby.Ruby;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.opto.Invalidator;
import org.objectweb.asm.Handle;

import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;
import java.lang.invoke.SwitchPoint;

import static java.lang.invoke.MethodHandles.lookup;
import static java.lang.invoke.MethodType.methodType;

public class CheckpointSite extends MutableCallSite {
public static final Handle CHECKPOINT_BOOTSTRAP = Bootstrap.getBootstrapHandle("checkpointBootstrap", Bootstrap.BOOTSTRAP_BARE_SIG);

public CheckpointSite(MethodType type) {
super(type);
}

public static CallSite checkpointBootstrap(MethodHandles.Lookup lookup, String name, MethodType type) throws Throwable {
CheckpointSite site = new CheckpointSite(type);
MethodHandle handle = lookup.findVirtual(CheckpointSite.class, "checkpointFallback", methodType(void.class, ThreadContext.class));

handle = handle.bindTo(site);
site.setTarget(handle);

return site;
}

public void checkpointFallback(ThreadContext context) throws Throwable {
Ruby runtime = context.runtime;
Invalidator invalidator = runtime.getCheckpointInvalidator();

MethodHandle target = Binder
.from(void.class, ThreadContext.class)
.nop();
MethodHandle fallback = lookup().findStatic(Bootstrap.class, "checkpointFallback", methodType(void.class, MutableCallSite.class, ThreadContext.class));
fallback = fallback.bindTo(this);

target = ((SwitchPoint)invalidator.getData()).guardWithTest(target, fallback);

this.setTarget(target);

// poll for events once since we've ended up back in fallback
context.pollThreadEvents();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package org.jruby.ir.targets.indy;

import com.headius.invokebinder.Binder;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Binding;
import org.jruby.runtime.Block;
import org.jruby.runtime.CompiledIRBlockBody;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.Frame;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;

import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

import static org.jruby.util.CodegenUtils.p;
import static org.jruby.util.CodegenUtils.sig;

public class ConstructBlockBootstrap {
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private static final Binder BINDING_MAKER_BINDER = Binder.from(Binding.class, ThreadContext.class, IRubyObject.class, DynamicScope.class);
private static final MethodHandle SELF_BINDING = BINDING_MAKER_BINDER.invokeStaticQuiet(LOOKUP, Bootstrap.class, "selfBinding");
private static final MethodHandle SCOPE_BINDING = BINDING_MAKER_BINDER.invokeStaticQuiet(LOOKUP, Bootstrap.class, "scopeBinding");
private static final MethodHandle FRAME_BINDING = BINDING_MAKER_BINDER.invokeStaticQuiet(LOOKUP, Bootstrap.class, "frameBinding");
private static final MethodHandle FRAME_SCOPE_BINDING = BINDING_MAKER_BINDER.invokeStaticQuiet(LOOKUP, IRRuntimeHelpers.class, "newFrameScopeBinding");
private static final MethodHandle CONSTRUCT_BLOCK = Binder.from(Block.class, Binding.class, CompiledIRBlockBody.class).invokeStaticQuiet(LOOKUP, Bootstrap.class, "constructBlock");

public static Handle prepareBlock() {
return new Handle(
Opcodes.H_INVOKESTATIC,
p(Bootstrap.class),
"prepareBlock",
sig(CallSite.class, MethodHandles.Lookup.class, String.class,
MethodType.class, MethodHandle.class, MethodHandle.class, MethodHandle.class, MethodHandle.class, String.class, long.class,
String.class, int.class, String.class),
false);
}

public static CallSite prepareBlock(MethodHandles.Lookup lookup, String name, MethodType type,
MethodHandle bodyHandle, MethodHandle scopeHandle, MethodHandle setScopeHandle, MethodHandle parentHandle, String scopeDescriptor, long encodedSignature,
String file, int line, String encodedArgumentDescriptors
) throws Throwable {
StaticScope staticScope = (StaticScope) scopeHandle.invokeExact();

if (staticScope == null) {
staticScope = Helpers.restoreScope(scopeDescriptor, (StaticScope) parentHandle.invokeExact());
setScopeHandle.invokeExact(staticScope);
}

CompiledIRBlockBody body = new CompiledIRBlockBody(bodyHandle, staticScope, file, line, encodedArgumentDescriptors, encodedSignature);

Binder binder = Binder.from(type);

binder = binder.fold(FRAME_SCOPE_BINDING);

// This optimization can't happen until we can see into the method we're calling to know if it reifies the block
if (false) {
/*
if (needsBinding) {
if (needsFrame) {
FullInterpreterContext fic = scope.getExecutionContext();
if (fic.needsBinding()) {
if (fic.needsFrame()) {
binder = binder.fold(FRAME_SCOPE_BINDING);
} else {
binder = binder.fold(SCOPE_BINDING);
}
} else {
if (needsFrame) {
binder = binder.fold(FRAME_BINDING);
} else {
binder = binder.fold(SELF_BINDING);
}
}*/
}

MethodHandle blockMaker = binder.drop(1, 3)
.append(body)
.invoke(CONSTRUCT_BLOCK);

return new ConstantCallSite(blockMaker);
}

public static Binding frameBinding(ThreadContext context, IRubyObject self, DynamicScope scope) {
Frame frame = context.getCurrentFrame().capture();
return new Binding(self, frame, frame.getVisibility());
}

public static Binding scopeBinding(ThreadContext context, IRubyObject self, DynamicScope scope) {
return new Binding(self, scope);
}

public static Binding selfBinding(ThreadContext context, IRubyObject self, DynamicScope scope) {
return new Binding(self);
}

public static Block constructBlock(Binding binding, CompiledIRBlockBody body) throws Throwable {
return new Block(body, binding);
}
}
37 changes: 37 additions & 0 deletions core/src/main/java/org/jruby/ir/targets/indy/CoverageSite.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.jruby.ir.targets.indy;

import com.headius.invokebinder.Binder;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.runtime.ThreadContext;
import org.objectweb.asm.Handle;

import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;

import static java.lang.invoke.MethodHandles.insertArguments;
import static java.lang.invoke.MethodType.methodType;
import static org.jruby.util.CodegenUtils.sig;

public class CoverageSite {
public static final Handle COVER_LINE_BOOTSTRAP = Bootstrap.getBootstrapHandle("coverLineBootstrap", sig(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, String.class, int.class, int.class));

public static CallSite coverLineBootstrap(MethodHandles.Lookup lookup, String name, MethodType type, String filename, int line, int oneshot) throws Throwable {
MutableCallSite site = new MutableCallSite(type);
MethodHandle handle = lookup.findStatic(Bootstrap.class, "coverLineFallback", methodType(void.class, MutableCallSite.class, ThreadContext.class, String.class, int.class, boolean.class));

handle = handle.bindTo(site);
handle = insertArguments(handle, 1, filename, line, oneshot != 0);
site.setTarget(handle);

return site;
}

public static void coverLineFallback(MutableCallSite site, ThreadContext context, String filename, int line, boolean oneshot) throws Throwable {
IRRuntimeHelpers.updateCoverage(context, filename, line);

if (oneshot) site.setTarget(Binder.from(void.class, ThreadContext.class).dropAll().nop());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.jruby.ir.targets.indy;

import com.headius.invokebinder.Binder;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.scope.DynamicScopeGenerator;
import org.objectweb.asm.Handle;

import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

import static java.lang.invoke.MethodType.methodType;
import static org.jruby.runtime.Helpers.arrayOf;

public class HeapVariableBootstrap {
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
public static final Handle GET_HEAP_LOCAL_OR_NIL_BOOTSTRAP = Bootstrap.getBootstrapHandle("getHeapLocalOrNilBootstrap", Bootstrap.BOOTSTRAP_INT_INT_SIG);
public static final Handle GET_HEAP_LOCAL_BOOTSTRAP = Bootstrap.getBootstrapHandle("getHeapLocalBootstrap", Bootstrap.BOOTSTRAP_INT_INT_SIG);

public static CallSite getHeapLocalBootstrap(MethodHandles.Lookup lookup, String name, MethodType type, int depth, int location) throws Throwable {
// no null checking needed for method bodies
MethodHandle getter;
Binder binder = Binder
.from(type);

if (depth == 0) {
if (location < DynamicScopeGenerator.SPECIALIZED_GETS.size()) {
getter = binder.invokeVirtualQuiet(LOOKUP, DynamicScopeGenerator.SPECIALIZED_GETS.get(location));
} else {
getter = binder
.insert(1, location)
.invokeVirtualQuiet(LOOKUP, "getValueDepthZero");
}
} else {
getter = binder
.insert(1, arrayOf(int.class, int.class), location, depth)
.invokeVirtualQuiet(LOOKUP, "getValue");
}

ConstantCallSite site = new ConstantCallSite(getter);

return site;
}

public static CallSite getHeapLocalOrNilBootstrap(MethodHandles.Lookup lookup, String name, MethodType type, int depth, int location) throws Throwable {
MethodHandle getter;
Binder binder = Binder
.from(type)
.filter(1, LiteralValueBootstrap.contextValue(lookup, "nil", methodType(IRubyObject.class, ThreadContext.class)).dynamicInvoker());

if (depth == 0) {
if (location < DynamicScopeGenerator.SPECIALIZED_GETS_OR_NIL.size()) {
getter = binder.invokeVirtualQuiet(LOOKUP, DynamicScopeGenerator.SPECIALIZED_GETS_OR_NIL.get(location));
} else {
getter = binder
.insert(1, location)
.invokeVirtualQuiet(LOOKUP, "getValueDepthZeroOrNil");
}
} else {
getter = binder
.insert(1, arrayOf(int.class, int.class), location, depth)
.invokeVirtualQuiet(LOOKUP, "getValueOrNil");
}

ConstantCallSite site = new ConstantCallSite(getter);

return site;
}
}
Loading

0 comments on commit 842327c

Please sign in to comment.