Mercurial > hg > graal-compiler
view graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyClass.java @ 13514:0fbee3eb71f0
Ruby: import project.
author | Chris Seaton <chris.seaton@oracle.com> |
---|---|
date | Mon, 06 Jan 2014 17:12:09 +0000 |
parents | |
children | 50c11b9a7fdf |
line wrap: on
line source
/* * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This * code is released under a tri EPL/GPL/LGPL license. You can use it, * redistribute it and/or modify it under the terms of the: * * Eclipse Public License version 1.0 * GNU General Public License version 2 * GNU Lesser General Public License version 2.1 */ package com.oracle.truffle.ruby.runtime.core; import java.util.*; import com.oracle.truffle.api.CompilerDirectives.*; import com.oracle.truffle.ruby.runtime.*; import com.oracle.truffle.ruby.runtime.lookup.*; import com.oracle.truffle.ruby.runtime.objects.*; /** * Represents the Ruby {@code Class} class. Note that most of the functionality you might associate * with {@code Class} is actually in {@code Module}, implemented by {@link RubyModule}. */ public class RubyClass extends RubyModule { /** * The class from which we create the object that is {@code Class}. A subclass of * {@link RubyClass} so that we can override {@link #newInstance} and allocate a * {@link RubyClass} rather than a normal {@link RubyBasicObject}. */ public static class RubyClassClass extends RubyClass { public RubyClassClass(RubyContext context) { super(context, null, null, null, "Class"); } @Override public RubyBasicObject newInstance() { return new RubyClass(null, getContext().getCoreLibrary().getObjectClass(), "(unnamed class)"); } } @CompilationFinal private RubyClass superclass; // We maintain a list of subclasses so we can notify them when they need to update their layout. private final Set<RubyClass> subClasses = Collections.newSetFromMap(new WeakHashMap<RubyClass, Boolean>()); /* * The layout to use for instances of this class - do not confuse with objectLayout, which is * the layout for this object - the class. */ private ObjectLayout objectLayoutForInstances = null; public RubyClass(RubyModule parentModule, RubyClass rubySuperclass, String name) { this(parentModule, rubySuperclass, name, false); } public RubyClass(RubyModule parentModule, RubyClass rubySuperclass, String name, boolean isSingleton) { this(rubySuperclass.getContext(), rubySuperclass.getContext().getCoreLibrary().getClassClass(), parentModule, rubySuperclass, name); if (!isSingleton) { getSingletonClass(); } } /** * This constructor supports initialization and solves boot-order problems and should not * normally be used from outside this class. */ public RubyClass(RubyContext context, RubyClass classClass, RubyModule parentModule, RubyClass superclass, String name) { super(context, classClass, parentModule, name); if (superclass == null) { objectLayoutForInstances = ObjectLayout.EMPTY; } else { unsafeSetSuperclass(superclass); } } public RubyClass getSuperclass() { assert superclass != null; return superclass; } @Override public RubyClass getSingletonClass() { if (rubySingletonClass == null) { RubyClass singletonSuperclass; if (superclass == null) { singletonSuperclass = getRubyClass(); } else { singletonSuperclass = superclass.getSingletonClass(); } rubySingletonClass = new RubyClass(getParentModule(), singletonSuperclass, String.format("#<Class:%s>", getName()), true); lookupNode = new LookupFork(rubySingletonClass, lookupNode); } return rubySingletonClass; } /** * This method supports initialization and solves boot-order problems and should not normally be * used. */ public void unsafeSetSuperclass(RubyClass newSuperclass) { assert superclass == null; superclass = newSuperclass; superclass.addDependent(this); superclass.subClasses.add(this); include(superclass); objectLayoutForInstances = new ObjectLayout(getName(), getContext(), superclass.objectLayoutForInstances); } public RubyBasicObject newInstance() { return new RubyObject(this); } /** * Is an instance of this class assignable to some location expecting some other class? */ public boolean assignableTo(RubyClass otherClass) { if (this == otherClass) { return true; } if (superclass == null) { return false; } return superclass.assignableTo(otherClass); } /** * Returns the object layout that objects of this class should use. Do not confuse with * {@link #getObjectLayout}, which for {@link RubyClass} will return the layout of the class * object itself. */ public ObjectLayout getObjectLayoutForInstances() { return objectLayoutForInstances; } /** * Change the layout to be used for instances of this object. */ public void setObjectLayoutForInstances(ObjectLayout newObjectLayoutForInstances) { objectLayoutForInstances = newObjectLayoutForInstances; for (RubyClass subClass : subClasses) { subClass.renewObjectLayoutForInstances(); } } private void renewObjectLayoutForInstances() { objectLayoutForInstances = objectLayoutForInstances.renew(getContext(), superclass.objectLayoutForInstances); for (RubyClass subClass : subClasses) { subClass.renewObjectLayoutForInstances(); } } }