aoqi@0: /* aoqi@0: * Copyright (c) 1999, 2014, 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: #include "precompiled.hpp" aoqi@0: #include "ci/ciObject.hpp" aoqi@0: #include "ci/ciUtilities.hpp" aoqi@0: #include "gc_interface/collectedHeap.inline.hpp" aoqi@0: #include "oops/oop.inline2.hpp" aoqi@0: aoqi@0: // ciObject aoqi@0: // aoqi@0: // This class represents an oop in the HotSpot virtual machine. aoqi@0: // Its subclasses are structured in a hierarchy which mirrors aoqi@0: // an aggregate of the VM's oop and klass hierarchies (see aoqi@0: // oopHierarchy.hpp). Each instance of ciObject holds a handle aoqi@0: // to a corresponding oop on the VM side and provides routines aoqi@0: // for accessing the information in its oop. By using the ciObject aoqi@0: // hierarchy for accessing oops in the VM, the compiler ensures aoqi@0: // that it is safe with respect to garbage collection; that is, aoqi@0: // GC and compilation can proceed independently without aoqi@0: // interference. aoqi@0: // aoqi@0: // Within the VM, the oop and klass hierarchies are separate. aoqi@0: // The compiler interface does not preserve this separation -- aoqi@0: // the distinction between `Klass*' and `Klass' are not aoqi@0: // reflected in the interface and instead the Klass hierarchy aoqi@0: // is directly modeled as the subclasses of ciKlass. aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::ciObject aoqi@0: ciObject::ciObject(oop o) { aoqi@0: ASSERT_IN_VM; aoqi@0: if (ciObjectFactory::is_initialized()) { aoqi@0: _handle = JNIHandles::make_local(o); aoqi@0: } else { aoqi@0: _handle = JNIHandles::make_global(o); aoqi@0: } aoqi@0: _klass = NULL; aoqi@0: init_flags_from(o); aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::ciObject aoqi@0: // aoqi@0: ciObject::ciObject(Handle h) { aoqi@0: ASSERT_IN_VM; aoqi@0: if (ciObjectFactory::is_initialized()) { aoqi@0: _handle = JNIHandles::make_local(h()); aoqi@0: } else { aoqi@0: _handle = JNIHandles::make_global(h); aoqi@0: } aoqi@0: _klass = NULL; aoqi@0: init_flags_from(h()); aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::ciObject aoqi@0: // aoqi@0: // Unloaded klass/method variant. `klass' is the klass of the unloaded aoqi@0: // klass/method, if that makes sense. aoqi@0: ciObject::ciObject(ciKlass* klass) { aoqi@0: ASSERT_IN_VM; aoqi@0: assert(klass != NULL, "must supply klass"); aoqi@0: _handle = NULL; aoqi@0: _klass = klass; aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::ciObject aoqi@0: // aoqi@0: // NULL variant. Used only by ciNullObject. aoqi@0: ciObject::ciObject() { aoqi@0: ASSERT_IN_VM; aoqi@0: _handle = NULL; aoqi@0: _klass = NULL; aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::klass aoqi@0: // aoqi@0: // Get the ciKlass of this ciObject. aoqi@0: ciKlass* ciObject::klass() { aoqi@0: if (_klass == NULL) { aoqi@0: if (_handle == NULL) { aoqi@0: // When both _klass and _handle are NULL, we are dealing aoqi@0: // with the distinguished instance of ciNullObject. aoqi@0: // No one should ask it for its klass. aoqi@0: assert(is_null_object(), "must be null object"); aoqi@0: ShouldNotReachHere(); aoqi@0: return NULL; aoqi@0: } aoqi@0: aoqi@0: GUARDED_VM_ENTRY( aoqi@0: oop o = get_oop(); aoqi@0: _klass = CURRENT_ENV->get_klass(o->klass()); aoqi@0: ); aoqi@0: } aoqi@0: return _klass; aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::equals aoqi@0: // aoqi@0: // Are two ciObjects equal? aoqi@0: bool ciObject::equals(ciObject* obj) { aoqi@0: return (this == obj); aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::hash aoqi@0: // aoqi@0: // A hash value for the convenience of compilers. aoqi@0: // aoqi@0: // Implementation note: we use the address of the ciObject as the aoqi@0: // basis for the hash. Use the _ident field, which is well-behaved. aoqi@0: int ciObject::hash() { aoqi@0: return ident() * 31; aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::constant_encoding aoqi@0: // aoqi@0: // The address which the compiler should embed into the aoqi@0: // generated code to represent this oop. This address aoqi@0: // is not the true address of the oop -- it will get patched aoqi@0: // during nmethod creation. aoqi@0: // aoqi@0: // aoqi@0: // aoqi@0: // Implementation note: we use the handle as the encoding. The aoqi@0: // nmethod constructor resolves the handle and patches in the oop. aoqi@0: // aoqi@0: // This method should be changed to return an generified address aoqi@0: // to discourage use of the JNI handle. aoqi@0: jobject ciObject::constant_encoding() { aoqi@0: assert(is_null_object() || handle() != NULL, "cannot embed null pointer"); aoqi@0: assert(can_be_constant(), "oop must be NULL or perm"); aoqi@0: return handle(); aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::can_be_constant aoqi@0: bool ciObject::can_be_constant() { aoqi@0: if (ScavengeRootsInCode >= 1) return true; // now everybody can encode as a constant aoqi@0: return handle() == NULL; aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::should_be_constant() aoqi@0: bool ciObject::should_be_constant() { aoqi@0: if (ScavengeRootsInCode >= 2) return true; // force everybody to be a constant aoqi@0: if (is_null_object()) return true; aoqi@0: aoqi@0: ciEnv* env = CURRENT_ENV; aoqi@0: aoqi@0: // We want Strings and Classes to be embeddable by default since aoqi@0: // they used to be in the perm world. Not all Strings used to be aoqi@0: // embeddable but there's no easy way to distinguish the interned aoqi@0: // from the regulars ones so just treat them all that way. aoqi@0: if (klass() == env->String_klass() || klass() == env->Class_klass()) { aoqi@0: return true; aoqi@0: } aoqi@0: if (EnableInvokeDynamic && aoqi@0: (klass()->is_subclass_of(env->MethodHandle_klass()) || aoqi@0: klass()->is_subclass_of(env->CallSite_klass()))) { aoqi@0: assert(ScavengeRootsInCode >= 1, "must be"); aoqi@0: // We want to treat these aggressively. aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: return handle() == NULL; aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::should_be_constant() aoqi@0: void ciObject::init_flags_from(oop x) { aoqi@0: int flags = 0; aoqi@0: if (x != NULL) { aoqi@0: assert(Universe::heap()->is_in_reserved(x), "must be"); aoqi@0: if (x->is_scavengable()) aoqi@0: flags |= SCAVENGABLE_FLAG; aoqi@0: } aoqi@0: _ident |= flags; aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::print aoqi@0: // aoqi@0: // Print debugging output about this ciObject. aoqi@0: // aoqi@0: // Implementation note: dispatch to the virtual print_impl behavior aoqi@0: // for this ciObject. aoqi@0: void ciObject::print(outputStream* st) { aoqi@0: st->print("<%s", type_string()); aoqi@0: GUARDED_VM_ENTRY(print_impl(st);) aoqi@0: st->print(" ident=%d %s address=" INTPTR_FORMAT ">", ident(), aoqi@0: is_scavengable() ? "SCAVENGABLE" : "", aoqi@0: p2i((address)this)); aoqi@0: } aoqi@0: aoqi@0: // ------------------------------------------------------------------ aoqi@0: // ciObject::print_oop aoqi@0: // aoqi@0: // Print debugging output about the oop this ciObject represents. aoqi@0: void ciObject::print_oop(outputStream* st) { aoqi@0: if (is_null_object()) { aoqi@0: st->print_cr("NULL"); aoqi@0: } else if (!is_loaded()) { aoqi@0: st->print_cr("UNLOADED"); aoqi@0: } else { aoqi@0: GUARDED_VM_ENTRY(get_oop()->print_on(st);) aoqi@0: } aoqi@0: }