Skip to content

Commit

Permalink
Showing 2 changed files with 27 additions and 7 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/core/class/inherited_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fails:Class.inherited is invoked with the child Class when self is subclassed
windows:Class.inherited is invoked only once per subclass
33 changes: 27 additions & 6 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ClassNodes.java
Original file line number Diff line number Diff line change
@@ -80,11 +80,20 @@ private Object doNewInstance(VirtualFrame frame, RubyClass rubyClass, Object[] a
public abstract static class InitializeNode extends CoreMethodArrayArgumentsNode {

@Child private ModuleNodes.InitializeNode moduleInitializeNode;
@Child private CallDispatchHeadNode inheritedNode;

public InitializeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

void triggerInheritedHook(VirtualFrame frame, RubyClass subClass, RubyClass superClass) {
if (inheritedNode == null) {
CompilerDirectives.transferToInterpreter();
inheritedNode = insert(DispatchHeadNodeFactory.createMethodCallOnSelf(getContext()));
}

This comment has been minimized.

Copy link
@eregon

eregon Jun 26, 2015

Member

A nice way to write this is with @Cached:

void triggerInheritedHook(VirtualFrame frame, RubyClass subClass, RubyClass superClass,
    @Cached("create(getContext())") CallDispatchHeadNode inheritedNode) {

But we need:

  • CallDispatchHeadNode.create(RubyContext), should be easy.
  • It must be in a @specialization of course, so here they should be unified by having two CreateCast, one coercing the block to null if not provided, and one for superclass to default to Object.
inheritedNode.call(frame, superClass, "inherited", null, subClass);
}

void moduleInitialize(VirtualFrame frame, RubyClass rubyClass, RubyProc block) {
if (moduleInitializeNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -94,25 +103,37 @@ void moduleInitialize(VirtualFrame frame, RubyClass rubyClass, RubyProc block) {
}

@Specialization
public RubyClass initialize(RubyClass rubyClass, NotProvided superclass, NotProvided block) {
return initialize(rubyClass, getContext().getCoreLibrary().getObjectClass(), block);
public RubyClass initialize(VirtualFrame frame, RubyClass rubyClass, NotProvided superclass, NotProvided block) {
return initializeGeneralWithoutBlock(frame, rubyClass, getContext().getCoreLibrary().getObjectClass(), null);
}

@Specialization
public RubyClass initialize(RubyClass rubyClass, RubyClass superclass, NotProvided block) {
rubyClass.initialize(superclass);
return rubyClass;
public RubyClass initialize(VirtualFrame frame, RubyClass rubyClass, RubyClass superclass, NotProvided block) {
return initializeGeneralWithoutBlock(frame, rubyClass, superclass, null);
}

@Specialization
public RubyClass initialize(VirtualFrame frame, RubyClass rubyClass, NotProvided superclass, RubyProc block) {
return initialize(frame, rubyClass, getContext().getCoreLibrary().getObjectClass(), block);
return initializeGeneralWithBlock(frame, rubyClass, getContext().getCoreLibrary().getObjectClass(), block);
}

@Specialization
public RubyClass initialize(VirtualFrame frame, RubyClass rubyClass, RubyClass superclass, RubyProc block) {
return initializeGeneralWithBlock(frame, rubyClass, superclass, block);
}

private RubyClass initializeGeneralWithoutBlock(VirtualFrame frame, RubyClass rubyClass, RubyClass superclass, RubyProc block) {
rubyClass.initialize(superclass);
triggerInheritedHook(frame, rubyClass, superclass);

return rubyClass;
}

private RubyClass initializeGeneralWithBlock(VirtualFrame frame, RubyClass rubyClass, RubyClass superclass, RubyProc block) {
rubyClass.initialize(superclass);
triggerInheritedHook(frame, rubyClass, superclass);
moduleInitialize(frame, rubyClass, block);

return rubyClass;
}

0 comments on commit fd3a43e

Please sign in to comment.