Skip to content

Commit

Permalink
Showing 4 changed files with 35 additions and 26 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/core/class/allocate_tags.txt

This file was deleted.

8 changes: 6 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -308,6 +308,7 @@ public CoreLibrary(RubyContext context) {
// Close the cycles
Layouts.MODULE.getFields(classClass).parentModule = Layouts.MODULE.getFields(moduleClass).start;
Layouts.MODULE.getFields(moduleClass).addDependent(classClass);
Layouts.CLASS.setSuperclass(classClass, moduleClass);
Layouts.MODULE.getFields(classClass).newVersion();

Layouts.MODULE.getFields(classClass).getAdoptedByLexicalParent(context, objectClass, "Class", node);
@@ -547,6 +548,9 @@ public CoreLibrary(RubyContext context) {

digestClass = defineClass(truffleModule, basicObjectClass, "Digest");
Layouts.CLASS.setInstanceFactoryUnsafe(digestClass, DigestLayoutImpl.INSTANCE.createDigestShape(digestClass, digestClass));

Layouts.CLASS.setSuperclass(basicObjectClass, nilObject);
Layouts.MODULE.getFields(basicObjectClass).newVersion();

This comment has been minimized.

Copy link
@eregon

eregon Mar 3, 2016

Member

Why the newVersion()?

This comment has been minimized.

Copy link
@pitr-ch

pitr-ch Mar 4, 2016

Author Member

Because the superclass is changing, but that's flawed since it's null before which is never cached. Good catch.

}

private static DynamicObjectFactory alwaysFrozen(DynamicObjectFactory factory) {
@@ -733,13 +737,13 @@ private DynamicObject defineClass(String name) {

private DynamicObject defineClass(DynamicObject superclass, String name) {
assert RubyGuards.isRubyClass(superclass);
return ClassNodes.createRubyClass(context, objectClass, superclass, name);
return ClassNodes.createInitializedRubyClass(context, objectClass, superclass, name);
}

private DynamicObject defineClass(DynamicObject lexicalParent, DynamicObject superclass, String name) {
assert RubyGuards.isRubyModule(lexicalParent);
assert RubyGuards.isRubyClass(superclass);
return ClassNodes.createRubyClass(context, lexicalParent, superclass, name);
return ClassNodes.createInitializedRubyClass(context, lexicalParent, superclass, name);
}

private DynamicObject defineModule(String name) {
50 changes: 28 additions & 22 deletions truffle/src/main/java/org/jruby/truffle/core/klass/ClassNodes.java
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@
import org.jruby.truffle.language.NotProvided;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;

@@ -96,6 +97,7 @@ public static DynamicObject createBootClass(RubyContext context, DynamicObject c

fields.parentModule = Layouts.MODULE.getFields(superclass).start;
Layouts.MODULE.getFields(superclass).addDependent(rubyClass);
Layouts.CLASS.setSuperclass(rubyClass, superclass);

fields.newVersion();
}
@@ -110,21 +112,36 @@ 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));
return ensureSingletonConsistency(context, createRubyClass(context, Layouts.BASIC_OBJECT.getLogicalClass(superclass), null, superclass, name, true, attached, true));
}

@TruffleBoundary
public static DynamicObject createRubyClass(RubyContext context, DynamicObject lexicalParent, DynamicObject superclass, String name) {
final DynamicObject rubyClass = createRubyClass(context, Layouts.BASIC_OBJECT.getLogicalClass(superclass), lexicalParent, superclass, name, false, null);
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);
return rubyClass;
}

@TruffleBoundary
public static DynamicObject createRubyClass(RubyContext context, DynamicObject classClass, DynamicObject lexicalParent, DynamicObject superclass, String name, boolean isSingleton, DynamicObject attached) {
public static DynamicObject createRubyClass(RubyContext context,
DynamicObject classClass,
DynamicObject lexicalParent,
DynamicObject superclass,
String name,
boolean isSingleton,
DynamicObject attached,
boolean initialized) {
assert superclass == null || RubyGuards.isRubyClass(superclass);

final ModuleFields model = new ModuleFields(context, lexicalParent, name);

final DynamicObject rubyClass = Layouts.CLASS.createClass(Layouts.CLASS.getInstanceFactory(classClass), model, isSingleton, attached, null, null);
final DynamicObject rubyClass = Layouts.CLASS.createClass(
Layouts.CLASS.getInstanceFactory(classClass),
model,
isSingleton,
attached,
null,
initialized ? superclass : null);
assert RubyGuards.isRubyClass(rubyClass) : classClass.getShape().getObjectType().getClass();
assert RubyGuards.isRubyModule(rubyClass) : classClass.getShape().getObjectType().getClass();

@@ -138,8 +155,6 @@ public static DynamicObject createRubyClass(RubyContext context, DynamicObject c
}

if (superclass != null) {
assert RubyGuards.isRubyClass(superclass);

fields.parentModule = Layouts.MODULE.getFields(superclass).start;
Layouts.MODULE.getFields(superclass).addDependent(rubyClass);

@@ -199,7 +214,7 @@ public static DynamicObject createOneSingletonClass(RubyContext context, Dynamic
}

String name = String.format("#<Class:%s>", Layouts.MODULE.getFields(rubyClass).getName());
Layouts.BASIC_OBJECT.setMetaClass(rubyClass, ClassNodes.createRubyClass(context, Layouts.BASIC_OBJECT.getLogicalClass(rubyClass), null, singletonSuperclass, name, true, rubyClass));
Layouts.BASIC_OBJECT.setMetaClass(rubyClass, ClassNodes.createRubyClass(context, Layouts.BASIC_OBJECT.getLogicalClass(rubyClass), null, singletonSuperclass, name, true, rubyClass, true));

return Layouts.BASIC_OBJECT.getMetaClass(rubyClass);
}
@@ -342,30 +357,21 @@ public Object getSuperClass(DynamicObject rubyClass,
return cachedSuperclass;
}

@Specialization
DynamicObject getGetSuperClass(DynamicObject rubyClass) {
@Specialization(contains = "getSuperClass")
DynamicObject getSuperClassUncached(DynamicObject rubyClass) {
final DynamicObject superclass = fastLookUp(rubyClass);
if (superclass != null) {
return superclass;
} else {
return slowLookUp(rubyClass);
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeError("uninitialized class", this));
}
}

protected DynamicObject fastLookUp(DynamicObject rubyClass) {
return Layouts.CLASS.getSuperclass(rubyClass);
}

@TruffleBoundary
private DynamicObject slowLookUp(DynamicObject rubyClass) {
final DynamicObject superclass = ClassNodes.getSuperClass(rubyClass);
if (superclass == null) {
return nil();
} else {
return superclass;
}
}

protected int getCacheLimit() {
return getContext().getOptions().CLASS_CACHE;
}
@@ -380,7 +386,7 @@ public AllocateConstructorNode(RubyContext context, SourceSection sourceSection)

@Specialization
public DynamicObject allocate(DynamicObject rubyClass) {
return createRubyClass(getContext(), coreLibrary().getClassClass(), null, coreLibrary().getObjectClass(), null, false, null);
return createRubyClass(getContext(), coreLibrary().getClassClass(), null, coreLibrary().getObjectClass(), null, false, null, false);
}

}
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ public Object execute(VirtualFrame frame) {
}

if (needToDefineProfile.profile(constant == null)) {
definingClass = ClassNodes.createRubyClass(getContext(), lexicalParentModule, superClassModule, name);
definingClass = ClassNodes.createInitializedRubyClass(getContext(), lexicalParentModule, superClassModule, name);

if (inheritedNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();

0 comments on commit 566807e

Please sign in to comment.