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