Mercurial > hg > graal-compiler
view graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/runtime/ObjectLayoutTests.java @ 13514:0fbee3eb71f0
Ruby: import project.
author | Chris Seaton <chris.seaton@oracle.com> |
---|---|
date | Mon, 06 Jan 2014 17:12:09 +0000 |
parents | |
children |
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.test.runtime; import org.junit.*; import com.oracle.truffle.ruby.runtime.*; import com.oracle.truffle.ruby.runtime.core.*; import com.oracle.truffle.ruby.runtime.objects.*; import static org.junit.Assert.*; /** * Test the object layout classes. */ public class ObjectLayoutTests { @Test public void testNewInstanceVariable() { final RubyContext context = new RubyContext(null); // Create a class and an instance final RubyClass classA = new RubyClass(context, null, null, null, "A"); final ObjectLayout layoutClassA = classA.getObjectLayoutForInstances(); final RubyBasicObject objectA = new RubyBasicObject(classA); final ObjectLayout layoutObjectA = objectA.getObjectLayout(); // Add an instance variable to the instance objectA.setInstanceVariable("foo", 14); // That should have changed the layout of the class assertNotSame(layoutClassA, classA.getObjectLayoutForInstances()); // If we notify the object, it should also change the layout of that objectA.updateLayout(); assertNotSame(layoutObjectA, objectA.getObjectLayout()); // We should be able to find that instance variable as a storage location in the class assertNotNull(classA.getObjectLayoutForInstances().findStorageLocation("foo")); // We should be able to read that value back out assertEquals(14, objectA.getInstanceVariable("foo")); } @Test public void testOverflowPrimitives() { final RubyContext context = new RubyContext(null); // Create a class and an instance final RubyClass classA = new RubyClass(context, null, null, null, "A"); final RubyBasicObject objectA = new RubyBasicObject(classA); // Add many more Fixnums that we have space for primitives final int count = 100; for (int n = 0; n < count; n++) { objectA.setInstanceVariable("foo" + n, n); } // We should be able to read them back out for (int n = 0; n < count; n++) { assertEquals(n, objectA.getInstanceVariable("foo" + n)); } } @Test public void testGeneralisation() { final RubyContext context = new RubyContext(null); // Create a class and two instances final RubyClass classA = new RubyClass(context, null, null, null, "A"); final RubyBasicObject object1 = new RubyBasicObject(classA); final RubyBasicObject object2 = new RubyBasicObject(classA); // Set an instance variable to be a Fixnum in object 1 object1.setInstanceVariable("foo", 14); // We should be able to read that instance variable back, and it should still be a Fixnum assertEquals(14, object1.getInstanceVariable("foo")); assertSame(Integer.class, object1.getInstanceVariable("foo").getClass()); // The underlying instance store should be Fixnum assertSame(FixnumStorageLocation.class, object1.getObjectLayout().findStorageLocation("foo").getClass()); /* * The same instance variable in object 2 should be Nil. Note that this requires that we * realise that even though the instance variable is known about in the layout of object 2, * and we are using a primitive int to hold it, that it hasn't been set and is actually Nil. * We don't want it to appear as 0. */ assertSame(NilPlaceholder.INSTANCE, object2.getInstanceVariable("foo")); /* * We should be able to set the same instance variable in object 2 to also be a Fixnum * without changing the layout. */ final ObjectLayout objectLayout2 = object2.getObjectLayout(); object2.setInstanceVariable("foo", 2); assertEquals(2, object2.getInstanceVariable("foo")); assertSame(Integer.class, object2.getInstanceVariable("foo").getClass()); assertSame(objectLayout2, object2.getObjectLayout()); // Set the instance variable in object 2 to be a Float object2.setInstanceVariable("foo", 2.25); // We should be able to read that instance variable back, and it should still be a Fixnum assertEquals(2.25, object2.getInstanceVariable("foo")); assertSame(Double.class, object2.getInstanceVariable("foo").getClass()); // Object 1 should give still think the instance variable is a Fixnum assertEquals(14, object1.getInstanceVariable("foo")); assertSame(Integer.class, object1.getInstanceVariable("foo").getClass()); // The underlying instance store in both objects should now be Object assertSame(ObjectStorageLocation.class, object1.getObjectLayout().findStorageLocation("foo").getClass()); assertSame(ObjectStorageLocation.class, object2.getObjectLayout().findStorageLocation("foo").getClass()); } @Test public void testSubclasses() { final RubyContext context = new RubyContext(null); // Create two classes, A, and a subclass, B, and an instance of each final RubyClass classA = new RubyClass(context, null, null, null, "A"); final RubyClass classB = new RubyClass(context, null, null, classA, "B"); ObjectLayout layoutClassA = classA.getObjectLayoutForInstances(); ObjectLayout layoutClassB = classA.getObjectLayoutForInstances(); final RubyBasicObject objectA = new RubyBasicObject(classA); final RubyBasicObject objectB = new RubyBasicObject(classB); ObjectLayout layoutObjectA = objectA.getObjectLayout(); ObjectLayout layoutObjectB = objectB.getObjectLayout(); // Add an instance variable to the instance of A objectA.setInstanceVariable("foo", 14); // That should have changed the layout of both classes assertNotSame(layoutClassA, classA.getObjectLayoutForInstances()); assertNotSame(layoutClassB, classB.getObjectLayoutForInstances()); layoutClassA = classA.getObjectLayoutForInstances(); layoutClassB = classA.getObjectLayoutForInstances(); // If we notify the objects, both of them should have changed layouts objectA.updateLayout(); objectB.updateLayout(); assertNotSame(layoutObjectA, objectA.getObjectLayout()); assertNotSame(layoutObjectB, objectB.getObjectLayout()); layoutObjectA = objectA.getObjectLayout(); layoutObjectB = objectB.getObjectLayout(); // We should be able to find that instance variable as a storage location in both classes assertNotNull(classA.getObjectLayoutForInstances().findStorageLocation("foo")); assertNotNull(classB.getObjectLayoutForInstances().findStorageLocation("foo")); // We should be able to read that value back out assertEquals(14, objectA.getInstanceVariable("foo")); // Add an instance variable to the instance of B objectB.setInstanceVariable("bar", 2); // This should not have changed the layout of A or the instance of A assertSame(layoutClassA, classA.getObjectLayoutForInstances()); assertSame(layoutObjectA, objectA.getObjectLayout()); // But the layout of B and the instance of B should have changed assertNotSame(layoutClassB, classB.getObjectLayoutForInstances()); objectB.updateLayout(); assertNotSame(layoutObjectB, objectB.getObjectLayout()); // We should be able to find the new instance variable in the instance of B but not A assertNull(classA.getObjectLayoutForInstances().findStorageLocation("bar")); assertNotNull(classB.getObjectLayoutForInstances().findStorageLocation("bar")); // We should be able to read that value back out assertEquals(2, objectB.getInstanceVariable("bar")); } @Test public void testPerObjectInstanceVariables() { final RubyContext context = new RubyContext(null); // Create a class and an instance final RubyClass classA = new RubyClass(context, context.getCoreLibrary().getClassClass(), null, null, "A"); final RubyBasicObject objectA = new RubyBasicObject(classA); ObjectLayout layoutClassA = classA.getObjectLayoutForInstances(); ObjectLayout layoutObjectA = objectA.getObjectLayout(); // Add an instance variable to the instance of A objectA.setInstanceVariable("foo", 2); // That should have changed the layout of the class and the object assertNotSame(layoutClassA, classA.getObjectLayoutForInstances()); assertNotSame(layoutObjectA, objectA.getObjectLayout()); layoutClassA = classA.getObjectLayoutForInstances(); layoutObjectA = classA.getObjectLayout(); // We should be able to read the value back out assertEquals(2, objectA.getInstanceVariable("foo")); /* * Switch object A to having a private object layout, as would be done by calls such as * instance_variable_set. */ objectA.switchToPrivateLayout(); // Set an instance variable on object A objectA.setInstanceVariable("bar", 14); // The layout of object A, however, should have changed // CS: it hasn't changed because it's still null // assertNotSame(layoutObjectA, objectA.getObjectLayout()); // We should be able to read the value back out assertEquals(14, objectA.getInstanceVariable("bar")); /* * We should also be able to read the first variable back out, even though we've switched to * private layout since then. */ assertEquals(2, objectA.getInstanceVariable("foo")); } }