@CompilerDirectives.TruffleBoundary public void prepend(Node currentNode, DynamicObject module) { assert RubyGuards.isRubyModule(module); checkFrozen(currentNode); // If the module we want to prepend already includes us, it is cyclic if (ModuleOperations.includesModule(module, rubyModuleObject)) { throw new RaiseException( getContext().getCoreLibrary().argumentError("cyclic prepend detected", currentNode)); } ModuleChain mod = Layouts.MODULE.getFields(module).start; ModuleChain cur = start; while (mod != null && !(RubyGuards.isRubyModule(mod) && RubyGuards.isRubyClass(((ModuleFields) mod).rubyModuleObject))) { if (!(mod instanceof PrependMarker)) { if (!ModuleOperations.includesModule(rubyModuleObject, mod.getActualModule())) { cur.insertAfter(mod.getActualModule()); Layouts.MODULE.getFields(mod.getActualModule()).addDependent(rubyModuleObject); cur = cur.getParentModule(); } } mod = mod.getParentModule(); } newVersion(); }
public void getAdoptedByLexicalParent( DynamicObject lexicalParent, String name, Node currentNode) { assert RubyGuards.isRubyModule(lexicalParent); Layouts.MODULE .getFields(lexicalParent) .setConstantInternal(currentNode, name, rubyModuleObject, false); Layouts.MODULE.getFields(lexicalParent).addLexicalDependent(rubyModuleObject); if (this.name == null) { // Tricky, we need to compare with the Object class, but we only have a Class at hand. final DynamicObject classClass = Layouts.BASIC_OBJECT.getLogicalClass(getLogicalClass()); final DynamicObject objectClass = ClassNodes.getSuperClass(ClassNodes.getSuperClass(classClass)); if (lexicalParent == objectClass) { this.name = name; updateAnonymousChildrenModules(); } else if (Layouts.MODULE.getFields(lexicalParent).hasName()) { this.name = Layouts.MODULE.getFields(lexicalParent).getName() + "::" + name; updateAnonymousChildrenModules(); } // else: Our lexicalParent is also an anonymous module // and will name us when it gets named via updateAnonymousChildrenModules() } }
public static DynamicObject createOneSingletonClass(DynamicObject rubyClass) { CompilerAsserts.neverPartOfCompilation(); if (Layouts.CLASS.getIsSingleton(Layouts.BASIC_OBJECT.getMetaClass(rubyClass))) { return Layouts.BASIC_OBJECT.getMetaClass(rubyClass); } final DynamicObject singletonSuperclass; if (getSuperClass(rubyClass) == null) { singletonSuperclass = Layouts.BASIC_OBJECT.getLogicalClass(rubyClass); } else { singletonSuperclass = createOneSingletonClass(getSuperClass(rubyClass)); } String name = String.format("#<Class:%s>", Layouts.MODULE.getFields(rubyClass).getName()); Layouts.BASIC_OBJECT.setMetaClass( rubyClass, ClassNodes.createRubyClass( Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(rubyClass)).getContext(), Layouts.BASIC_OBJECT.getLogicalClass(rubyClass), null, singletonSuperclass, name, true, rubyClass)); return Layouts.BASIC_OBJECT.getMetaClass(rubyClass); }
@Override public DynamicObject execute(VirtualFrame frame) { CompilerDirectives.transferToInterpreter(); final Object receiverObject = receiver.execute(frame); final InternalMethod methodObject = (InternalMethod) methodNode.execute(frame); final DynamicObject module = (DynamicObject) receiverObject; assert RubyGuards.isRubyModule(module); final Visibility visibility = getVisibility(frame, methodObject.getName()); final InternalMethod method = methodObject.withDeclaringModule(module).withVisibility(visibility); if (method.getVisibility() == Visibility.MODULE_FUNCTION) { Layouts.MODULE.getFields(module).addMethod(this, method.withVisibility(Visibility.PRIVATE)); Layouts.MODULE .getFields(singletonClassNode.executeSingletonClass(module)) .addMethod(this, method.withVisibility(Visibility.PUBLIC)); } else { Layouts.MODULE.getFields(module).addMethod(this, method); } return getSymbol(method.getName()); }
public void updateAnonymousChildrenModules() { for (Map.Entry<String, RubyConstant> entry : constants.entrySet()) { RubyConstant constant = entry.getValue(); if (RubyGuards.isRubyModule(constant.getValue())) { DynamicObject module = (DynamicObject) constant.getValue(); if (!Layouts.MODULE.getFields(module).hasName()) { Layouts.MODULE .getFields(module) .getAdoptedByLexicalParent(rubyModuleObject, entry.getKey(), null); } } } }
public static void debugModuleChain(DynamicObject module) { assert RubyGuards.isRubyModule(module); ModuleChain chain = Layouts.MODULE.getFields(module); while (chain != null) { System.err.print(chain.getClass()); if (!(chain instanceof PrependMarker)) { DynamicObject real = chain.getActualModule(); System.err.print(" " + Layouts.MODULE.getFields(real).getName()); } System.err.println(); chain = chain.getParentModule(); } }
public static void initialize(DynamicObject rubyClass, DynamicObject superclass) { assert RubyGuards.isRubyClass(superclass); Layouts.MODULE.getFields(rubyClass).parentModule = Layouts.MODULE.getFields(superclass).start; Layouts.MODULE.getFields(superclass).addDependent(rubyClass); Layouts.MODULE.getFields(rubyClass).newVersion(); ensureSingletonConsistency(rubyClass); DynamicObjectFactory factory = Layouts.CLASS.getInstanceFactory(superclass); factory = Layouts.BASIC_OBJECT.setLogicalClass(factory, rubyClass); factory = Layouts.BASIC_OBJECT.setMetaClass(factory, rubyClass); Layouts.CLASS.setInstanceFactoryUnsafe(rubyClass, factory); }
public DynamicObject getNormalObjectSingletonClass(DynamicObject object) { CompilerAsserts.neverPartOfCompilation(); if (RubyGuards.isRubyClass(object)) { // For the direct caller return ClassNodes.getSingletonClass(object); } if (Layouts.CLASS.getIsSingleton(Layouts.BASIC_OBJECT.getMetaClass(object))) { return Layouts.BASIC_OBJECT.getMetaClass(object); } CompilerDirectives.transferToInterpreter(); final DynamicObject logicalClass = BasicObjectNodes.getLogicalClass(object); DynamicObject attached = null; if (RubyGuards.isRubyModule(object)) { attached = object; } final String name = String.format( "#<Class:#<%s:0x%x>>", Layouts.MODULE.getFields(logicalClass).getName(), BasicObjectNodes.verySlowGetObjectID(object)); final DynamicObject singletonClass = ClassNodes.createSingletonClassOfObject(getContext(), logicalClass, attached, name); propagateFrozen(object, singletonClass); Layouts.BASIC_OBJECT.setMetaClass(object, singletonClass); return singletonClass; }
public void performIncludes(ModuleChain inclusionPoint, Deque<DynamicObject> moduleAncestors) { while (!moduleAncestors.isEmpty()) { DynamicObject mod = moduleAncestors.pop(); assert RubyGuards.isRubyModule(mod); inclusionPoint.insertAfter(mod); Layouts.MODULE.getFields(mod).addDependent(rubyModuleObject); } }
// TODO (eregon, 12 May 2015): ideally all callers would be nodes and check themselves. public void checkFrozen(Node currentNode) { if (getContext().getCoreLibrary() != null && verySlowIsFrozen(getContext(), rubyModuleObject)) { CompilerDirectives.transferToInterpreter(); throw new RaiseException( getContext() .getCoreLibrary() .frozenError(Layouts.MODULE.getFields(getLogicalClass()).getName(), currentNode)); } }
public void newVersion(Set<DynamicObject> alreadyInvalidated, boolean considerLexicalDependents) { if (alreadyInvalidated.contains(rubyModuleObject)) return; unmodifiedAssumption.invalidate(); alreadyInvalidated.add(rubyModuleObject); // Make dependents new versions for (DynamicObject dependent : dependents) { Layouts.MODULE.getFields(dependent).newVersion(alreadyInvalidated, considerLexicalDependents); } if (considerLexicalDependents) { for (DynamicObject dependent : lexicalDependents) { Layouts.MODULE .getFields(dependent) .newVersion(alreadyInvalidated, considerLexicalDependents); } } }
public String getName() { if (name != null) { return name; } else { CompilerDirectives.transferToInterpreter(); if (givenBaseName != null) { return Layouts.MODULE.getFields(lexicalParent).getName() + "::" + givenBaseName; } else if (getLogicalClass() == rubyModuleObject) { // For the case of class Class during initialization return "#<cyclic>"; } else { return "#<" + Layouts.MODULE.getFields(getLogicalClass()).getName() + ":0x" + Long.toHexString(ObjectIDOperations.verySlowGetObjectID(rubyModuleObject)) + ">"; } } }
public static DynamicObject getSuperClass(DynamicObject rubyClass) { CompilerAsserts.neverPartOfCompilation(); for (DynamicObject ancestor : Layouts.MODULE.getFields(rubyClass).parentAncestors()) { if (RubyGuards.isRubyClass(ancestor)) { return ancestor; } } return null; }
public static DynamicObject createRubyClass( RubyContext context, DynamicObject classClass, DynamicObject lexicalParent, DynamicObject superclass, String name, boolean isSingleton, DynamicObject attached) { final ModuleFields model = new ModuleFields(context, lexicalParent, name); final DynamicObject rubyClass = Layouts.CLASS.createClass( Layouts.CLASS.getInstanceFactory(classClass), model, isSingleton, attached, null); assert RubyGuards.isRubyClass(rubyClass) : classClass.getShape().getObjectType().getClass(); assert RubyGuards.isRubyModule(rubyClass) : classClass.getShape().getObjectType().getClass(); model.rubyModuleObject = rubyClass; if (model.lexicalParent == null) { // bootstrap or anonymous module Layouts.MODULE.getFields(rubyClass).name = Layouts.MODULE.getFields(rubyClass).givenBaseName; } else { Layouts.MODULE .getFields(rubyClass) .getAdoptedByLexicalParent(model.lexicalParent, model.givenBaseName, null); } if (superclass != null) { assert RubyGuards.isRubyClass(superclass); assert RubyGuards.isRubyClass(Layouts.MODULE.getFields(rubyClass).rubyModuleObject); Layouts.MODULE.getFields(rubyClass).parentModule = Layouts.MODULE.getFields(superclass).start; Layouts.MODULE .getFields(superclass) .addDependent(Layouts.MODULE.getFields(rubyClass).rubyModuleObject); Layouts.MODULE.getFields(rubyClass).newVersion(); } DynamicObjectFactory factory = Layouts.CLASS.getInstanceFactory(superclass); factory = Layouts.BASIC_OBJECT.setLogicalClass(factory, rubyClass); factory = Layouts.BASIC_OBJECT.setMetaClass(factory, rubyClass); Layouts.CLASS.setInstanceFactoryUnsafe(rubyClass, factory); return rubyClass; }
/** * This constructor supports initialization and solves boot-order problems and should not normally * be used from outside this class. */ public static DynamicObject createBootClass( DynamicObject classClass, DynamicObject superclass, String name) { assert RubyGuards.isRubyClass(classClass); assert superclass == null || RubyGuards.isRubyClass(superclass); final ModuleFields model = new ModuleFields( Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(classClass)).getContext(), null, name); final DynamicObject rubyClass = Layouts.CLASS.createClass( Layouts.CLASS.getInstanceFactory(classClass), model, false, null, null); assert RubyGuards.isRubyClass(rubyClass) : classClass.getShape().getObjectType().getClass(); assert RubyGuards.isRubyModule(rubyClass) : classClass.getShape().getObjectType().getClass(); model.rubyModuleObject = rubyClass; if (model.lexicalParent == null) { // bootstrap or anonymous module Layouts.MODULE.getFields(rubyClass).name = Layouts.MODULE.getFields(rubyClass).givenBaseName; } else { Layouts.MODULE .getFields(rubyClass) .getAdoptedByLexicalParent(model.lexicalParent, model.givenBaseName, null); } if (superclass != null) { assert RubyGuards.isRubyClass(superclass); assert RubyGuards.isRubyClass(Layouts.MODULE.getFields(rubyClass).rubyModuleObject); Layouts.MODULE.getFields(rubyClass).parentModule = Layouts.MODULE.getFields(superclass).start; Layouts.MODULE .getFields(superclass) .addDependent(Layouts.MODULE.getFields(rubyClass).rubyModuleObject); Layouts.MODULE.getFields(rubyClass).newVersion(); } return rubyClass; }
public CachedBoxedReturnMissingDispatchNode( RubyContext context, Object cachedName, DispatchNode next, Shape expectedShape, DynamicObject expectedClass, DispatchAction dispatchAction) { super(context, cachedName, next, dispatchAction); this.expectedShape = expectedShape; this.unmodifiedAssumption = Layouts.MODULE.getFields(expectedClass).getUnmodifiedAssumption(); this.next = next; }
@CompilerDirectives.TruffleBoundary public void initCopy(DynamicObject from) { assert RubyGuards.isRubyModule(from); // Do not copy name, the copy is an anonymous module this.methods.putAll(Layouts.MODULE.getFields(from).methods); this.constants.putAll(Layouts.MODULE.getFields(from).constants); this.classVariables.putAll(Layouts.MODULE.getFields(from).classVariables); if (Layouts.MODULE.getFields(from).start.getParentModule() != Layouts.MODULE.getFields(from)) { this.parentModule = Layouts.MODULE.getFields(from).start.getParentModule(); } else { this.parentModule = Layouts.MODULE.getFields(from).parentModule; } for (DynamicObject ancestor : Layouts.MODULE.getFields(from).ancestors()) { Layouts.MODULE.getFields(ancestor).addDependent(rubyModuleObject); } }
public CachedSingletonDispatchNode( RubyContext context, Object cachedName, DispatchNode next, DynamicObject expectedReceiver, DynamicObject expectedClass, InternalMethod method, DispatchAction dispatchAction) { super(context, cachedName, next, dispatchAction); this.expectedReceiver = expectedReceiver; this.unmodifiedAssumption = Layouts.MODULE.getFields(expectedClass).getUnmodifiedAssumption(); this.next = next; this.method = method; this.callNode = Truffle.getRuntime().createDirectCallNode(method.getCallTarget()); applySplittingInliningStrategy(callNode, method); }
@Override public Object execute(VirtualFrame frame) { CompilerDirectives.transferToInterpreter(); // TODO(CS): cast final DynamicObject module = (DynamicObject) definingModule.execute(frame); lexicalScope.setLiveModule(module); Layouts.MODULE.getFields(lexicalScope.getParent().getLiveModule()).addLexicalDependent(module); final InternalMethod definition = definitionMethod.executeMethod(frame).withDeclaringModule(module); return callModuleDefinitionNode.call( frame, definition.getCallTarget(), RubyArguments.pack( definition, null, null, module, null, DeclarationContext.MODULE, new Object[] {})); }
/** Set the value of a constant, possibly redefining it. */ @CompilerDirectives.TruffleBoundary public void setConstant(Node currentNode, String name, Object value) { if (getContext().getCoreLibrary().isLoadingRubyCore()) { final RubyConstant currentConstant = constants.get(name); if (currentConstant != null) { return; } } if (RubyGuards.isRubyModule(value)) { Layouts.MODULE .getFields(((DynamicObject) value)) .getAdoptedByLexicalParent(rubyModuleObject, name, currentNode); } else { setConstantInternal(currentNode, name, value, false); } }
@CompilerDirectives.TruffleBoundary public void include(Node currentNode, DynamicObject module) { assert RubyGuards.isRubyModule(module); checkFrozen(currentNode); // If the module we want to include already includes us, it is cyclic if (ModuleOperations.includesModule(module, rubyModuleObject)) { throw new RaiseException( getContext().getCoreLibrary().argumentError("cyclic include detected", currentNode)); } // We need to include the module ancestors in reverse order for a given inclusionPoint ModuleChain inclusionPoint = this; Deque<DynamicObject> modulesToInclude = new ArrayDeque<>(); for (DynamicObject ancestor : Layouts.MODULE.getFields(module).ancestors()) { if (ModuleOperations.includesModule(rubyModuleObject, ancestor)) { if (isIncludedModuleBeforeSuperClass(ancestor)) { // Include the modules at the appropriate inclusionPoint performIncludes(inclusionPoint, modulesToInclude); assert modulesToInclude.isEmpty(); // We need to include the others after that module inclusionPoint = parentModule; while (inclusionPoint.getActualModule() != ancestor) { inclusionPoint = inclusionPoint.getParentModule(); } } else { // Just ignore this module, as it is included above the superclass } } else { modulesToInclude.push(ancestor); } } performIncludes(inclusionPoint, modulesToInclude); newVersion(); }
/** Special constructor for class Class */ public static DynamicObject createClassClass(RubyContext context) { final ModuleFields model = new ModuleFields(context, null, "Class"); final DynamicObject rubyClass = LAYOUT.newInstance(LAYOUT.createShape(new ObjectType())); final DynamicObjectFactory factory = Layouts.CLASS.createClassShape(rubyClass, rubyClass); rubyClass.setShapeAndGrow(rubyClass.getShape(), factory.getShape()); assert RubyGuards.isRubyModule(rubyClass); assert RubyGuards.isRubyClass(rubyClass); model.rubyModuleObject = rubyClass; Layouts.CLASS.setInstanceFactoryUnsafe(rubyClass, factory); Layouts.MODULE.setFields(rubyClass, model); model.name = model.givenBaseName; assert RubyGuards.isRubyModule(rubyClass); assert RubyGuards.isRubyClass(rubyClass); assert Layouts.MODULE.getFields(rubyClass) == model; assert Layouts.BASIC_OBJECT.getLogicalClass(rubyClass) == rubyClass; return rubyClass; }
private DynamicObject translate(UnsupportedSpecializationException exception) { if (getContext().getOptions().EXCEPTIONS_PRINT_JAVA) { exception.printStackTrace(); } final StringBuilder builder = new StringBuilder(); builder.append("Truffle doesn't have a case for the "); builder.append(exception.getNode().getClass().getName()); builder.append(" node with values of type "); for (Object value : exception.getSuppliedValues()) { builder.append(" "); if (value == null) { builder.append("null"); } else if (value instanceof DynamicObject) { builder.append( Layouts.MODULE .getFields(Layouts.BASIC_OBJECT.getLogicalClass(((DynamicObject) value))) .getName()); builder.append("("); builder.append(value.getClass().getName()); builder.append(")"); if (RubyGuards.isRubyArray(value)) { final DynamicObject array = (DynamicObject) value; builder.append("["); if (Layouts.ARRAY.getStore(array) == null) { builder.append("null"); } else { builder.append(Layouts.ARRAY.getStore(array).getClass().getName()); } builder.append(","); builder.append(Layouts.ARRAY.getSize(array)); builder.append("]"); } else if (RubyGuards.isRubyHash(value)) { final Object store = Layouts.HASH.getStore((DynamicObject) value); if (store == null) { builder.append("[null]"); } else { builder.append("["); builder.append(store.getClass().getName()); builder.append("]"); } } } else { builder.append(value.getClass().getName()); } if (value instanceof Number || value instanceof Boolean) { builder.append("="); builder.append(value.toString()); } } switch (unsupportedOperationBehavior) { case TYPE_ERROR: return getContext().getCoreLibrary().typeError(builder.toString(), this); case ARGUMENT_ERROR: return getContext().getCoreLibrary().argumentError(builder.toString(), this); default: throw new UnsupportedOperationException(); } }
public Assumption getUnmodifiedAssumption(DynamicObject module) { return Layouts.MODULE.getFields(module).getUnmodifiedAssumption(); }