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: 675a56d4341d
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b4f5a169d6c7
Choose a head ref
  • 10 commits
  • 9 files changed
  • 1 contributor

Commits on Jun 7, 2016

  1. Copy the full SHA
    ad270e1 View commit details
  2. Copy the full SHA
    be0ff0f View commit details
  3. Copy the full SHA
    82c767c View commit details
  4. Copy the full SHA
    17b23d1 View commit details
  5. [Truffle] better var name

    pitr-ch committed Jun 7, 2016
    Copy the full SHA
    0615569 View commit details
  6. Copy the full SHA
    680ef48 View commit details
  7. [Truffle] remove broken specialization

    it was caching singleton classes against wrong shape
    pitr-ch committed Jun 7, 2016
    Copy the full SHA
    ed88ff2 View commit details
  8. Copy the full SHA
    fd0deee View commit details
  9. Copy the full SHA
    657debd View commit details
  10. Copy the full SHA
    b4f5a16 View commit details
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/class/dup_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/class/new_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
fails:Class.new with a block given runs the inherited hook after yielding the block
fails:Class.new raises a TypeError if passed a metaclass
fails:Class#new passes the block to #initialize
1 change: 0 additions & 1 deletion spec/truffle/tags/core/class/superclass_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/module/new_tags.txt

This file was deleted.

65 changes: 55 additions & 10 deletions truffle/src/main/java/org/jruby/truffle/core/klass/ClassNodes.java
Original file line number Diff line number Diff line change
@@ -26,6 +26,8 @@
import org.jruby.truffle.builtins.CoreClass;
import org.jruby.truffle.builtins.CoreMethod;
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode;
import org.jruby.truffle.core.kernel.KernelNodes;
import org.jruby.truffle.core.kernel.KernelNodesFactory;
import org.jruby.truffle.core.module.ModuleFields;
import org.jruby.truffle.core.module.ModuleNodes;
import org.jruby.truffle.core.module.ModuleNodesFactory;
@@ -34,6 +36,8 @@
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.language.objects.SingletonClassNode;
import org.jruby.truffle.language.objects.SingletonClassNodeGen;

@CoreClass("Class")
public abstract class ClassNodes {
@@ -112,13 +116,13 @@ public static DynamicObject createSingletonClassOfObject(RubyContext context, Dy
// Allocator is null here, we cannot create instances of singleton classes.
assert RubyGuards.isRubyClass(superclass);
assert attached != null;
return ensureSingletonConsistency(context, createRubyClass(context, Layouts.BASIC_OBJECT.getLogicalClass(superclass), null, superclass, name, true, attached, true));
return ensureItHasSingletonClassCreated(context, createRubyClass(context, Layouts.BASIC_OBJECT.getLogicalClass(superclass), null, superclass, name, true, attached, true));
}

@TruffleBoundary
public static DynamicObject createInitializedRubyClass(RubyContext context, DynamicObject lexicalParent, DynamicObject superclass, String name) {
final DynamicObject rubyClass = createRubyClass(context, Layouts.BASIC_OBJECT.getLogicalClass(superclass), lexicalParent, superclass, name, false, null, true);
ensureSingletonConsistency(context, rubyClass);
ensureItHasSingletonClassCreated(context, rubyClass);
return rubyClass;
}

@@ -177,7 +181,7 @@ public static void initialize(RubyContext context, DynamicObject rubyClass, Dyna
Layouts.MODULE.getFields(superclass).addDependent(rubyClass);

Layouts.MODULE.getFields(rubyClass).newVersion();
ensureSingletonConsistency(context, rubyClass);
ensureItHasSingletonClassCreated(context, rubyClass);

DynamicObjectFactory factory = Layouts.CLASS.getInstanceFactory(superclass);
factory = Layouts.BASIC_OBJECT.setLogicalClass(factory, rubyClass);
@@ -187,30 +191,40 @@ public static void initialize(RubyContext context, DynamicObject rubyClass, Dyna
Layouts.CLASS.setSuperclass(rubyClass, superclass);
}

public static DynamicObject ensureSingletonConsistency(RubyContext context, DynamicObject rubyClass) {
createOneSingletonClass(context, rubyClass);
private static DynamicObject ensureItHasSingletonClassCreated(RubyContext context, DynamicObject rubyClass) {
getLazyCreatedSingletonClass(context, rubyClass);
return rubyClass;
}

@TruffleBoundary
public static DynamicObject getSingletonClass(RubyContext context, DynamicObject rubyClass) {
// We also need to create the singleton class of a singleton class for proper lookup and consistency.
// See rb_singleton_class() documentation in MRI.
return ensureSingletonConsistency(context, createOneSingletonClass(context, rubyClass));
return ensureItHasSingletonClassCreated(context, getLazyCreatedSingletonClass(context, rubyClass));
}

public static DynamicObject createOneSingletonClass(RubyContext context, DynamicObject rubyClass) {
CompilerAsserts.neverPartOfCompilation();
public static DynamicObject getSingletonClassOrNull(RubyContext context, DynamicObject rubyClass) {
if (Layouts.CLASS.getIsSingleton(Layouts.BASIC_OBJECT.getMetaClass(rubyClass))) {
return ensureItHasSingletonClassCreated(context, Layouts.BASIC_OBJECT.getMetaClass(rubyClass));
} else {
return null;
}
}

private static DynamicObject getLazyCreatedSingletonClass(RubyContext context, DynamicObject rubyClass) {
if (Layouts.CLASS.getIsSingleton(Layouts.BASIC_OBJECT.getMetaClass(rubyClass))) {
return Layouts.BASIC_OBJECT.getMetaClass(rubyClass);
}

return createSingletonClass(context, rubyClass);
}

@TruffleBoundary
private static DynamicObject createSingletonClass(RubyContext context, DynamicObject rubyClass) {
final DynamicObject singletonSuperclass;
if (getSuperClass(rubyClass) == null) {
singletonSuperclass = Layouts.BASIC_OBJECT.getLogicalClass(rubyClass);
} else {
singletonSuperclass = createOneSingletonClass(context, getSuperClass(rubyClass));
singletonSuperclass = getLazyCreatedSingletonClass(context, getSuperClass(rubyClass));
}

String name = String.format("#<Class:%s>", Layouts.MODULE.getFields(rubyClass).getName());
@@ -260,6 +274,37 @@ private Object doNewInstance(VirtualFrame frame, DynamicObject rubyClass, Object
}
}

@CoreMethod(names = "dup", taintFromSelf = true)
public abstract static class DupNode extends CoreMethodArrayArgumentsNode {

@Child private KernelNodes.CopyNode copyNode;
@Child private CallDispatchHeadNode initializeDupNode;
@Child private SingletonClassNode singletonClassNode;

public DupNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
copyNode = KernelNodesFactory.CopyNodeFactory.create(context, sourceSection, null);
initializeDupNode = DispatchHeadNodeFactory.createMethodCallOnSelf(context);
singletonClassNode = SingletonClassNodeGen.create(context, sourceSection, null);
}

@Specialization
public DynamicObject dup(VirtualFrame frame, DynamicObject self) {
final DynamicObject newObject = copyNode.executeCopy(frame, self);
final DynamicObject newObjectMetaClass = singletonClassNode.executeSingletonClass(newObject);
final DynamicObject selfMetaClass = Layouts.BASIC_OBJECT.getMetaClass(self);

assert Layouts.CLASS.getIsSingleton(selfMetaClass);
assert Layouts.CLASS.getIsSingleton(Layouts.BASIC_OBJECT.getMetaClass(newObject));

Layouts.MODULE.getFields(newObjectMetaClass).initCopy(selfMetaClass); // copies class methods
initializeDupNode.call(frame, newObject, "initialize_dup", null, self);

return newObject;
}

}

@CoreMethod(names = "initialize", optional = 1, needsBlock = true)
public abstract static class InitializeNode extends CoreMethodArrayArgumentsNode {

Original file line number Diff line number Diff line change
@@ -150,18 +150,18 @@ public void initCopy(DynamicObject from) {
assert RubyGuards.isRubyModule(from);

// Do not copy name, the copy is an anonymous module
final ModuleFields fields = Layouts.MODULE.getFields(from);
this.methods.putAll(fields.methods);
this.constants.putAll(fields.constants);
this.classVariables.putAll(fields.classVariables);
final ModuleFields fromFields = Layouts.MODULE.getFields(from);
this.methods.putAll(fromFields.methods);
this.constants.putAll(fromFields.constants);
this.classVariables.putAll(fromFields.classVariables);

if (fields.start.getParentModule() != fields) {
this.parentModule = fields.start.getParentModule();
if (fromFields.start.getParentModule() != fromFields) {
this.parentModule = fromFields.start.getParentModule();
} else {
this.parentModule = fields.parentModule;
this.parentModule = fromFields.parentModule;
}

for (DynamicObject ancestor : fields.ancestors()) {
for (DynamicObject ancestor : fromFields.parentAncestors()) {
Layouts.MODULE.getFields(ancestor).addDependent(rubyModuleObject);
}
}
Original file line number Diff line number Diff line change
@@ -1133,7 +1133,7 @@ void classEval(VirtualFrame frame, DynamicObject module, DynamicObject block) {
CompilerDirectives.transferToInterpreter();
classExecNode = insert(ModuleNodesFactory.ClassExecNodeFactory.create(getContext(), getSourceSection(), null));
}
classExecNode.executeClassExec(frame, module, new Object[]{}, block);
classExecNode.executeClassExec(frame, module, new Object[]{module}, block);
}

@Specialization
Original file line number Diff line number Diff line change
@@ -78,14 +78,16 @@ protected DynamicObject singletonClassSymbol(DynamicObject value) {
@Specialization(
guards = {
"isRubyClass(rubyClass)",
"rubyClass.getShape() == cachedShape"
"rubyClass.getShape() == cachedShape",
"cachedSingletonClass != null"
},
limit = "getCacheLimit()"
)
protected DynamicObject singletonClassClassCached(
DynamicObject rubyClass,
@Cached("rubyClass.getShape()") Shape cachedShape,
@Cached("getSingletonClassForClass(rubyClass)") DynamicObject cachedSingletonClass) {
@Cached("getSingletonClassOrNull(rubyClass)") DynamicObject cachedSingletonClass) {

return cachedSingletonClass;
}

@@ -94,7 +96,7 @@ protected DynamicObject singletonClassClassCached(
contains = "singletonClassClassCached"
)
protected DynamicObject singletonClassClassUncached(DynamicObject rubyClass) {
return getSingletonClassForClass(rubyClass);
return ClassNodes.getSingletonClass(getContext(), rubyClass);
}

@Specialization(
@@ -132,9 +134,8 @@ private DynamicObject noSingletonClass() {
throw new RaiseException(coreExceptions().typeErrorCantDefineSingleton(this));
}

@TruffleBoundary
protected DynamicObject getSingletonClassForClass(DynamicObject rubyClass) {
return ClassNodes.getSingletonClass(getContext(), rubyClass);
protected DynamicObject getSingletonClassOrNull(DynamicObject object) {
return ClassNodes.getSingletonClassOrNull(getContext(), object);
}

@TruffleBoundary
5 changes: 1 addition & 4 deletions truffle/src/main/ruby/core/post.rb
Original file line number Diff line number Diff line change
@@ -86,13 +86,10 @@ def include(*modules)

Truffle.privately do
mod.append_features self
end

Truffle.privately do
mod.included self
end
end
self
end

end
end