001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.objectmodel; 014 015import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_LONG; 016 017import org.jikesrvm.VM; 018import org.jikesrvm.classloader.RVMClass; 019import org.jikesrvm.runtime.Memory; 020 021/** 022 * Layout fields in an object, packed like sardines in a crushed tin box. 023 */ 024public class FieldLayoutPacked extends FieldLayout { 025 026 /** 027 * Lay out an object, maintaining offsets of free slots of size 1,2,4 and 8 028 * bytes. 029 */ 030 private static class LayoutContext extends FieldLayoutContext { 031 private static final int LOG_MAX_SLOT_SIZE = LOG_BYTES_IN_LONG; 032 private static final int MAX_SLOT_SIZE = (1 << LOG_MAX_SLOT_SIZE); 033 034 private short slot0; 035 private short slot1; 036 private short slot2; 037 038 private short get(int logSize) { 039 switch (logSize) { 040 case 0: return slot0; 041 case 1: return slot1; 042 case 2: return slot2; 043 case 3: return (short)Memory.alignUp(getObjectSize(), MAX_SLOT_SIZE); 044 default: VM.sysFail("Invalid slot"); return -1; 045 } 046 } 047 048 private void set(int logSize, int value) { 049 if (VM.VerifyAssertions) VM._assert(value >= 0 && value < Short.MAX_VALUE); 050 short shortValue = (short)value; 051 switch (logSize) { 052 case 0: slot0 = shortValue; break; 053 case 1: slot1 = shortValue; break; 054 case 2: slot2 = shortValue; break; 055 case 3: if (VM.VerifyAssertions) VM._assert(shortValue == 0); 056 } 057 } 058 059 /** 060 * Create a layout for an object, initializing offsets from its 061 * superclass. 062 * 063 * @param alignment Current alignment of first field. 064 * @param superLayout Superclass layout context 065 */ 066 LayoutContext(byte alignment, LayoutContext superLayout) { 067 super(alignment, superLayout); 068 if (superLayout != null) { 069 for (int i = 0; i < LOG_MAX_SLOT_SIZE; i++) { 070 set(i, superLayout.get(i)); 071 } 072 } 073 } 074 075 /** 076 * Return the next available offset for a given size 077 * 078 * @param size Size of the field to be laid out. Must be 079 * a power of 2. 080 */ 081 @Override 082 int nextOffset(int size, boolean isReference) { 083 if (VM.VerifyAssertions) VM._assert((size & (size - 1)) == 0); // Ensure =2^n 084 adjustAlignment(size); 085 086 /* Calculate the log of the size of the field */ 087 int logSize = log2(size); 088 int result = 0; 089 090 /* Find a free slot */ 091 for (int i = logSize; i <= LOG_MAX_SLOT_SIZE; i++) { 092 int slot = get(i); 093 if (slot != 0 || i == LOG_MAX_SLOT_SIZE) { 094 result = slot; 095 set(i, 0); 096 /* Set any holes we have created */ 097 for (i = i - 1; i >= logSize; i--) { 098 if (VM.VerifyAssertions) VM._assert(get(i) == 0); 099 set(i, result + (1 << i)); 100 } 101 break; 102 } 103 } 104 105 /* Make sure the field fits */ 106 ensureObjectSize(result + size); 107 108 if (DEBUG) { 109 VM.sysWrite(" field: & offset ", result, " New object size = ", getObjectSize()); 110 VM.sysWrite(" slots: "); 111 for (int i = 0; i < LOG_MAX_SLOT_SIZE; i++) { 112 VM.sysWrite(get(i), i == LOG_MAX_SLOT_SIZE - 1 ? "" : ", "); 113 } 114 VM.sysWriteln(); 115 } 116 117 /* Bounds check - scalar objects this size are impossible, surely ?? */ 118 if (result >= Short.MAX_VALUE) { 119 VM.sysFail("Scalar class size exceeds offset width"); 120 } 121 122 return result; 123 } 124 } 125 126 public FieldLayoutPacked(boolean largeFieldsFirst, boolean clusterReferenceFields) { 127 super(largeFieldsFirst, clusterReferenceFields); 128 } 129 130 /** 131 * @param klass the class to layout 132 * @return The layout context 133 * @see FieldLayout#getLayoutContext(RVMClass) 134 */ 135 @Override 136 protected FieldLayoutContext getLayoutContext(RVMClass klass) { 137 return new LayoutContext((byte) klass.getAlignment(), (LayoutContext) klass.getFieldLayoutContext()); 138 } 139}