/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.unsafe; import com.sun.max.annotate.*; import com.sun.max.vm.object.*; /** * Why we never directly use any arrays of any subtype of 'Word': * * The byte codes aaload and aastore have no clue whether the array reference on the stack refers to a Word array or an * Object array. As long as we are unable to or unsure whether we can discern the difference STATICALLY, we must not * allow aaload and aastore to deal with either case dynamically. * * Compare this to the situation between byte arrays and boolean arrays addressed by baload and bastore! In those cases, * we CAN differentiate between the respective array types DYNAMICALLY and cause no harm to the GC, because both types * are primitive types. * * In case of Object and Word, one calls for a stack map entry and the other does not. Therefore, a dynamic distinction * would require support for dynamic stack map changes. So far we are not willing to afford the price for that * (runtime, implementation effort, complexity). * * Instead, always use WordArray.set() and WordArray.get() instead of [] when addressing word array elements. */ public final class WordArray { private WordArray() { } /** * Replaces all {@code null} entries in a given word array with the appropriately typed boxed zero value. */ @HOSTED_ONLY private static void replaceNullWithZero(Word[] array) { final Word zero = Word.zero(); for (int i = 0; i != array.length; ++i) { if (array[i] == null) { array[i] = zero; } } } public static void fill(Word[] array, Word value) { for (int i = 0; i < array.length; i++) { uncheckedSet(array, i, value); } } // Substituted by uncheckedGet_() public static Word uncheckedGet(Word[] array, int index) { if (array[index] == null) { replaceNullWithZero(array); } return array[index]; } @LOCAL_SUBSTITUTION @INLINE private static Word uncheckedGet_(Word[] array, int index) { return ArrayAccess.getWord(array, index); } // Substituted by get_() public static Word get(Word[] array, int index) { if (array[index] == null) { replaceNullWithZero(array); } return array[index]; } @LOCAL_SUBSTITUTION @INLINE private static Word get_(Word[] array, int index) { ArrayAccess.checkIndex(array, index); return ArrayAccess.getWord(array, index); } // Substituted by uncheckedSet_() public static void uncheckedSet(Word[] array, int index, Word value) { array[index] = value; } @LOCAL_SUBSTITUTION @INLINE private static void uncheckedSet_(Word[] array, int index, Word value) { ArrayAccess.setWord(array, index, value); } // Substituted by set_() public static void set(Word[] array, int index, Word value) { array[index] = value; } @LOCAL_SUBSTITUTION @INLINE private static void set_(Word[] array, int index, Word value) { ArrayAccess.checkIndex(array, index); ArrayAccess.setWord(array, index, value); } public static void copyAll(Word[] fromArray, Word[] toArray) { if (fromArray.length > toArray.length) { throw new ArrayIndexOutOfBoundsException(); } for (int i = 0; i < fromArray.length; i++) { uncheckedSet(toArray, i, uncheckedGet(fromArray, i)); } } }