aoqi@0: /* aoqi@0: * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_RUNTIME_JFIELDIDWORKAROUND_HPP aoqi@0: #define SHARE_VM_RUNTIME_JFIELDIDWORKAROUND_HPP aoqi@0: aoqi@0: class jfieldIDWorkaround: AllStatic { aoqi@0: // This workaround is because JVMTI doesn't have distinct entry points aoqi@0: // for methods that use static jfieldIDs and instance jfieldIDs. aoqi@0: // The workaround is to steal a low-order bit: aoqi@0: // a 1 means the jfieldID is an instance jfieldID, aoqi@0: // and the rest of the word is the offset of the field. aoqi@0: // a 0 means the jfieldID is a static jfieldID, aoqi@0: // and the rest of the word is the JNIid*. aoqi@0: // aoqi@0: // Another low-order bit is used to mark if an instance field aoqi@0: // is accompanied by an indication of which class it applies to. aoqi@0: // aoqi@0: // Bit-format of a jfieldID (most significant first): aoqi@0: // address:30 instance=0:1 checked=0:1 aoqi@0: // offset:30 instance=1:1 checked=0:1 aoqi@0: // klass:23 offset:7 instance=1:1 checked=1:1 aoqi@0: // aoqi@0: // If the offset does not fit in 7 bits, or if the fieldID is aoqi@0: // not checked, then the checked bit is zero and the rest of aoqi@0: // the word (30 bits) contains only the offset. aoqi@0: // aoqi@0: private: aoqi@0: enum { aoqi@0: checked_bits = 1, aoqi@0: instance_bits = 1, aoqi@0: address_bits = BitsPerWord - checked_bits - instance_bits, aoqi@0: aoqi@0: large_offset_bits = address_bits, // unioned with address aoqi@0: small_offset_bits = 7, aoqi@0: klass_bits = address_bits - small_offset_bits, aoqi@0: aoqi@0: checked_shift = 0, aoqi@0: instance_shift = checked_shift + checked_bits, aoqi@0: address_shift = instance_shift + instance_bits, aoqi@0: aoqi@0: offset_shift = address_shift, // unioned with address aoqi@0: klass_shift = offset_shift + small_offset_bits, aoqi@0: aoqi@0: checked_mask_in_place = right_n_bits(checked_bits) << checked_shift, aoqi@0: instance_mask_in_place = right_n_bits(instance_bits) << instance_shift, aoqi@0: #ifndef _WIN64 aoqi@0: large_offset_mask = right_n_bits(large_offset_bits), aoqi@0: small_offset_mask = right_n_bits(small_offset_bits), aoqi@0: klass_mask = right_n_bits(klass_bits) aoqi@0: #endif aoqi@0: }; aoqi@0: aoqi@0: #ifdef _WIN64 aoqi@0: // These values are too big for Win64 aoqi@0: const static uintptr_t large_offset_mask = right_n_bits(large_offset_bits); aoqi@0: const static uintptr_t small_offset_mask = right_n_bits(small_offset_bits); aoqi@0: const static uintptr_t klass_mask = right_n_bits(klass_bits); aoqi@0: #endif aoqi@0: aoqi@0: // helper routines: aoqi@0: static bool is_checked_jfieldID(jfieldID id) { aoqi@0: uintptr_t as_uint = (uintptr_t) id; aoqi@0: return ((as_uint & checked_mask_in_place) != 0); aoqi@0: } aoqi@0: static intptr_t raw_instance_offset(jfieldID id) { aoqi@0: uintptr_t result = (uintptr_t) id >> address_shift; aoqi@0: if (VerifyJNIFields && is_checked_jfieldID(id)) { aoqi@0: result &= small_offset_mask; // cut off the hash bits aoqi@0: } aoqi@0: return (intptr_t)result; aoqi@0: } aoqi@0: static intptr_t encode_klass_hash(Klass* k, intptr_t offset); aoqi@0: static bool klass_hash_ok(Klass* k, jfieldID id); aoqi@0: static void verify_instance_jfieldID(Klass* k, jfieldID id); aoqi@0: aoqi@0: public: aoqi@0: static bool is_valid_jfieldID(Klass* k, jfieldID id); aoqi@0: aoqi@0: static bool is_instance_jfieldID(Klass* k, jfieldID id) { aoqi@0: uintptr_t as_uint = (uintptr_t) id; aoqi@0: return ((as_uint & instance_mask_in_place) != 0); aoqi@0: } aoqi@0: static bool is_static_jfieldID(jfieldID id) { aoqi@0: uintptr_t as_uint = (uintptr_t) id; aoqi@0: return ((as_uint & instance_mask_in_place) == 0); aoqi@0: } aoqi@0: aoqi@0: static jfieldID to_instance_jfieldID(Klass* k, int offset) { aoqi@0: intptr_t as_uint = ((offset & large_offset_mask) << offset_shift) | instance_mask_in_place; aoqi@0: if (VerifyJNIFields) { aoqi@0: as_uint |= encode_klass_hash(k, offset); aoqi@0: } aoqi@0: jfieldID result = (jfieldID) as_uint; aoqi@0: #ifndef ASSERT aoqi@0: // always verify in debug mode; switchable in anything else aoqi@0: if (VerifyJNIFields) aoqi@0: #endif // ASSERT aoqi@0: { aoqi@0: verify_instance_jfieldID(k, result); aoqi@0: } aoqi@0: assert(raw_instance_offset(result) == (offset & large_offset_mask), "extract right offset"); aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: static intptr_t from_instance_jfieldID(Klass* k, jfieldID id) { aoqi@0: #ifndef ASSERT aoqi@0: // always verify in debug mode; switchable in anything else aoqi@0: if (VerifyJNIFields) aoqi@0: #endif // ASSERT aoqi@0: { aoqi@0: verify_instance_jfieldID(k, id); aoqi@0: } aoqi@0: return raw_instance_offset(id); aoqi@0: } aoqi@0: aoqi@0: static jfieldID to_static_jfieldID(JNIid* id) { aoqi@0: assert(id->is_static_field_id(), "from_JNIid, but not static field id"); aoqi@0: jfieldID result = (jfieldID) id; aoqi@0: assert(from_static_jfieldID(result) == id, "must produce the same static id"); aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: static JNIid* from_static_jfieldID(jfieldID id) { aoqi@0: assert(jfieldIDWorkaround::is_static_jfieldID(id), aoqi@0: "to_JNIid, but not static jfieldID"); aoqi@0: JNIid* result = (JNIid*) id; aoqi@0: assert(result->is_static_field_id(), "to_JNIid, but not static field id"); aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: static jfieldID to_jfieldID(instanceKlassHandle k, int offset, bool is_static) { aoqi@0: if (is_static) { aoqi@0: JNIid *id = k->jni_id_for(offset); aoqi@0: debug_only(id->set_is_static_field_id()); aoqi@0: return jfieldIDWorkaround::to_static_jfieldID(id); aoqi@0: } else { aoqi@0: return jfieldIDWorkaround::to_instance_jfieldID(k(), offset); aoqi@0: } aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: #endif // SHARE_VM_RUNTIME_JFIELDIDWORKAROUND_HPP