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: 14f00d78df3e
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f691f6999a55
Choose a head ref
  • 2 commits
  • 15 files changed
  • 1 contributor

Commits on Jun 30, 2018

  1. Delete some unused code.

    headius committed Jun 30, 2018
    Copy the full SHA
    7cba748 View commit details
  2. Expand reification to arbitrary object size.

    This commit allows reification of instance variables to handle
    arbitrarily-sized objects, with no upper limit at present.
    
    It fixes the following problems:
    
    * Object with instance variable counts over 10 fall back on using
      an array.
    * Objects reified with the same shape as a previous class do not
      properly use the reified fields.
    
    There's additional work to do, however:
    
    * The allocator is no longer generated; it is currently a single
      subclass that uses a method handle to construct the object. This
      will not optimize the way we want, and will not properly inline
      into `new` call sites.
    * The accessors are now just FieldVariableAccessor instances with
      two handles for getter and setter. Indy variable/attr call sites
      will use these handles and ideally optimize well, but non-indy
      sites will have the overhead of calling handles every time. This
      may be justification for enabling indy by default now, or
      disabling reification without indy.
    headius committed Jun 30, 2018
    Copy the full SHA
    f691f69 View commit details
14 changes: 6 additions & 8 deletions core/src/main/java/org/jruby/ir/targets/Bootstrap.java
Original file line number Diff line number Diff line change
@@ -451,12 +451,12 @@ private static MethodHandle createAttrReaderHandle(InvokeSite site, IRubyObject
MethodHandle getValue;

if (accessor instanceof FieldVariableAccessor) {
int offset = ((FieldVariableAccessor)accessor).getOffset();
MethodHandle getter = ((FieldVariableAccessor)accessor).getGetter();
getValue = Binder.from(site.type())
.drop(0, 2)
.filterReturn(filter)
.cast(methodType(Object.class, self.getClass()))
.getFieldQuiet(LOOKUP, "var" + offset);
.invoke(getter);
} else {
getValue = Binder.from(site.type())
.drop(0, 2)
@@ -486,12 +486,12 @@ private static MethodHandle createAttrWriterHandle(InvokeSite site, IRubyObject
MethodHandle setValue;

if (accessor instanceof FieldVariableAccessor) {
int offset = ((FieldVariableAccessor)accessor).getOffset();
MethodHandle setter = ((FieldVariableAccessor)accessor).getSetter();
setValue = Binder.from(site.type())
.drop(0, 2)
.filterReturn(filter)
.cast(methodType(void.class, self.getClass(), Object.class))
.invokeVirtualQuiet(LOOKUP, "setVariable" + offset);
.invoke(setter);
} else {
setValue = Binder.from(site.type())
.drop(0, 2)
@@ -708,8 +708,7 @@ public static IRubyObject ivarGet(VariableSite site, IRubyObject self) throws Th

if (accessor instanceof FieldVariableAccessor) {
direct = true;
int offset = ((FieldVariableAccessor)accessor).getOffset();
getValue = lookup().findGetter(self.getClass(), "var" + offset, Object.class);
getValue = ((FieldVariableAccessor) accessor).getGetter();
getValue = explicitCastArguments(getValue, methodType(Object.class, IRubyObject.class));
} else {
getValue = findStatic(VariableAccessor.class, "getVariable", methodType(Object.class, RubyBasicObject.class, int.class));
@@ -765,8 +764,7 @@ public static void ivarSet(VariableSite site, IRubyObject self, IRubyObject valu

if (accessor instanceof FieldVariableAccessor) {
direct = true;
int offset = ((FieldVariableAccessor)accessor).getOffset();
setValue = findVirtual(self.getClass(), "setVariable" + offset, methodType(void.class, Object.class));
setValue = ((FieldVariableAccessor)accessor).getSetter();
setValue = explicitCastArguments(setValue, methodType(void.class, IRubyObject.class, IRubyObject.class));
} else {
setValue = findStatic(accessor.getClass(), "setVariableChecked", methodType(void.class, RubyBasicObject.class, RubyClass.class, int.class, Object.class));
Original file line number Diff line number Diff line change
@@ -27,14 +27,21 @@

package org.jruby.runtime.ivars;

import com.headius.invokebinder.Binder;
import org.jruby.RubyBasicObject;
import org.jruby.RubyClass;
import org.jruby.runtime.Helpers;
import org.jruby.specialized.RubyObjectSpecializer;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;

/**
* A variable accessor that accesses a field directly;
*/
public abstract class FieldVariableAccessor extends VariableAccessor {
/** The offset of the field for this accessor */
private final int offset;
public class FieldVariableAccessor extends VariableAccessor {
private final MethodHandle getter;
private final MethodHandle setter;

/**
* Construct a new FieldVariableAccessor for the given "real" class,
@@ -44,18 +51,61 @@ public abstract class FieldVariableAccessor extends VariableAccessor {
* @param name the variable's name
* @param index the variable's index
* @param classId the class's ID
* @param getter the getter handle for the field
* @param setter the setter handle for the field
*/
public FieldVariableAccessor(RubyClass realClass, String name, int index, int classId, int offset) {
public FieldVariableAccessor(RubyClass realClass, String name, int index, int classId, MethodHandle getter, MethodHandle setter) {
super(realClass, name, index, classId);
this.offset = offset;

this.getter = getter;

// mix frozen check into setter
setter = MethodHandles.foldArguments(setter, ENSURE_SETTABLE.asType(setter.type()));

this.setter = setter;
}


public MethodHandle getGetter() {
return getter;
}

public MethodHandle getSetter() {
return setter;
}

/**
* Get the field offset for this accessor.
*
* @return offset of the field
* Retrieve the variable's value from the given object.
*
* @param object the object from which to retrieve this variable
* @return the variable's value
*/
public int getOffset() {
return offset;
public Object get(Object object) {
try {
return getter.invoke(object);
} catch (Throwable t) {
Helpers.throwException(t);
return null;
}
}

/**
* Set this variable into the given object using Unsafe to ensure
* safe updating of the variable table.
*
* @param object the object into which to set this variable
* @param value the variable's value
*/
public void set(Object object, Object value) {
try {
setter.invoke(object, value);
} catch (Throwable t) {
Helpers.throwException(t);
}
}

private static final MethodHandle ENSURE_SETTABLE = Binder
.from(Object.class, Object.class, Object.class)
.dropLast()
.cast(void.class, RubyBasicObject.class)
.invokeVirtualQuiet(RubyObjectSpecializer.LOOKUP, "ensureInstanceVariablesSettable");
}
100 changes: 0 additions & 100 deletions core/src/main/java/org/jruby/runtime/ivars/VariableAccessorVar0.java

This file was deleted.

100 changes: 0 additions & 100 deletions core/src/main/java/org/jruby/runtime/ivars/VariableAccessorVar1.java

This file was deleted.

Loading