Mon, 12 Dec 2016 12:53:38 +0100
8157181: Compilers accept modification of final fields outside initializer methods
Summary: Track initialized final field updates; disable constant folding if an update is detected.
Reviewed-by: vlivanov, dnsimon, forax, never, kvn, coleenp
duke@435 | 1 | /* |
drchase@5732 | 2 | * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
stefank@2314 | 25 | #ifndef SHARE_VM_CI_CIFIELD_HPP |
stefank@2314 | 26 | #define SHARE_VM_CI_CIFIELD_HPP |
stefank@2314 | 27 | |
stefank@2314 | 28 | #include "ci/ciClassList.hpp" |
stefank@2314 | 29 | #include "ci/ciConstant.hpp" |
stefank@2314 | 30 | #include "ci/ciFlags.hpp" |
stefank@2314 | 31 | #include "ci/ciInstance.hpp" |
stefank@2314 | 32 | |
duke@435 | 33 | // ciField |
duke@435 | 34 | // |
duke@435 | 35 | // This class represents the result of a field lookup in the VM. |
duke@435 | 36 | // The lookup may not succeed, in which case the information in |
duke@435 | 37 | // the ciField will be incomplete. |
duke@435 | 38 | class ciField : public ResourceObj { |
duke@435 | 39 | CI_PACKAGE_ACCESS |
duke@435 | 40 | friend class ciEnv; |
duke@435 | 41 | friend class ciInstanceKlass; |
duke@435 | 42 | friend class NonStaticFieldFiller; |
duke@435 | 43 | |
duke@435 | 44 | private: |
duke@435 | 45 | ciFlags _flags; |
duke@435 | 46 | ciInstanceKlass* _holder; |
duke@435 | 47 | ciSymbol* _name; |
duke@435 | 48 | ciSymbol* _signature; |
duke@435 | 49 | ciType* _type; |
duke@435 | 50 | int _offset; |
duke@435 | 51 | bool _is_constant; |
never@3854 | 52 | ciInstanceKlass* _known_to_link_with_put; |
never@3854 | 53 | ciInstanceKlass* _known_to_link_with_get; |
duke@435 | 54 | ciConstant _constant_value; |
duke@435 | 55 | |
duke@435 | 56 | ciType* compute_type(); |
duke@435 | 57 | ciType* compute_type_impl(); |
duke@435 | 58 | |
duke@435 | 59 | ciField(ciInstanceKlass* klass, int index); |
duke@435 | 60 | ciField(fieldDescriptor* fd); |
duke@435 | 61 | |
duke@435 | 62 | // shared constructor code |
duke@435 | 63 | void initialize_from(fieldDescriptor* fd); |
duke@435 | 64 | |
duke@435 | 65 | public: |
duke@435 | 66 | ciFlags flags() { return _flags; } |
duke@435 | 67 | |
duke@435 | 68 | // Of which klass is this field a member? |
duke@435 | 69 | // |
duke@435 | 70 | // Usage note: the declared holder of a field is the class |
duke@435 | 71 | // referenced by name in the bytecodes. The canonical holder |
duke@435 | 72 | // is the most general class which holds the field. This |
duke@435 | 73 | // method returns the canonical holder. The declared holder |
duke@435 | 74 | // can be accessed via a method in ciBytecodeStream. |
duke@435 | 75 | // |
duke@435 | 76 | // Ex. |
duke@435 | 77 | // class A { |
duke@435 | 78 | // public int f = 7; |
duke@435 | 79 | // } |
duke@435 | 80 | // class B extends A { |
duke@435 | 81 | // public void test() { |
duke@435 | 82 | // System.out.println(f); |
duke@435 | 83 | // } |
duke@435 | 84 | // } |
duke@435 | 85 | // |
duke@435 | 86 | // A java compiler is permitted to compile the access to |
duke@435 | 87 | // field f as: |
duke@435 | 88 | // |
duke@435 | 89 | // getfield B.f |
duke@435 | 90 | // |
duke@435 | 91 | // In that case the declared holder of f would be B and |
duke@435 | 92 | // the canonical holder of f would be A. |
duke@435 | 93 | ciInstanceKlass* holder() { return _holder; } |
duke@435 | 94 | |
duke@435 | 95 | // Name of this field? |
duke@435 | 96 | ciSymbol* name() { return _name; } |
duke@435 | 97 | |
duke@435 | 98 | // Signature of this field? |
duke@435 | 99 | ciSymbol* signature() { return _signature; } |
duke@435 | 100 | |
duke@435 | 101 | // Of what type is this field? |
duke@435 | 102 | ciType* type() { return (_type == NULL) ? compute_type() : _type; } |
duke@435 | 103 | |
duke@435 | 104 | // How is this field actually stored in memory? |
duke@435 | 105 | BasicType layout_type() { return type2field[(_type == NULL) ? T_OBJECT : _type->basic_type()]; } |
duke@435 | 106 | |
duke@435 | 107 | // How big is this field in memory? |
kvn@464 | 108 | int size_in_bytes() { return type2aelembytes(layout_type()); } |
duke@435 | 109 | |
duke@435 | 110 | // What is the offset of this field? |
duke@435 | 111 | int offset() { |
duke@435 | 112 | assert(_offset >= 1, "illegal call to offset()"); |
duke@435 | 113 | return _offset; |
duke@435 | 114 | } |
duke@435 | 115 | |
duke@435 | 116 | // Same question, explicit units. (Fields are aligned to the byte level.) |
duke@435 | 117 | int offset_in_bytes() { |
duke@435 | 118 | return offset(); |
duke@435 | 119 | } |
duke@435 | 120 | |
duke@435 | 121 | // Is this field shared? |
duke@435 | 122 | bool is_shared() { |
duke@435 | 123 | // non-static fields of shared holders are cached |
duke@435 | 124 | return _holder->is_shared() && !is_static(); |
duke@435 | 125 | } |
duke@435 | 126 | |
zmajo@8664 | 127 | // Is this field a constant? See ciField::initialize_from() for details |
zmajo@8664 | 128 | // about how a field is determined to be constant. |
duke@435 | 129 | bool is_constant() { return _is_constant; } |
duke@435 | 130 | |
duke@435 | 131 | // Get the constant value of this field. |
duke@435 | 132 | ciConstant constant_value() { |
twisti@1573 | 133 | assert(is_static() && is_constant(), "illegal call to constant_value()"); |
duke@435 | 134 | return _constant_value; |
duke@435 | 135 | } |
duke@435 | 136 | |
twisti@1573 | 137 | // Get the constant value of non-static final field in the given |
twisti@1573 | 138 | // object. |
twisti@1573 | 139 | ciConstant constant_value_of(ciObject* object) { |
twisti@1573 | 140 | assert(!is_static() && is_constant(), "only if field is non-static constant"); |
twisti@1573 | 141 | assert(object->is_instance(), "must be instance"); |
twisti@1573 | 142 | return object->as_instance()->field_value(this); |
twisti@1573 | 143 | } |
twisti@1573 | 144 | |
duke@435 | 145 | // Check for link time errors. Accessing a field from a |
duke@435 | 146 | // certain class via a certain bytecode may or may not be legal. |
duke@435 | 147 | // This call checks to see if an exception may be raised by |
duke@435 | 148 | // an access of this field. |
duke@435 | 149 | // |
duke@435 | 150 | // Usage note: if the same field is accessed multiple times |
duke@435 | 151 | // in the same compilation, will_link will need to be checked |
duke@435 | 152 | // at each point of access. |
duke@435 | 153 | bool will_link(ciInstanceKlass* accessing_klass, |
duke@435 | 154 | Bytecodes::Code bc); |
duke@435 | 155 | |
duke@435 | 156 | // Java access flags |
duke@435 | 157 | bool is_public () { return flags().is_public(); } |
duke@435 | 158 | bool is_private () { return flags().is_private(); } |
duke@435 | 159 | bool is_protected () { return flags().is_protected(); } |
duke@435 | 160 | bool is_static () { return flags().is_static(); } |
duke@435 | 161 | bool is_final () { return flags().is_final(); } |
vlivanov@5658 | 162 | bool is_stable () { return flags().is_stable(); } |
duke@435 | 163 | bool is_volatile () { return flags().is_volatile(); } |
duke@435 | 164 | bool is_transient () { return flags().is_transient(); } |
zmajo@8664 | 165 | // The field is modified outside of instance initializer methods |
zmajo@8664 | 166 | // (or class/initializer methods if the field is static). |
zmajo@8664 | 167 | bool has_initialized_final_update() { return flags().has_initialized_final_update(); } |
duke@435 | 168 | |
twisti@3101 | 169 | bool is_call_site_target() { |
kvn@3107 | 170 | ciInstanceKlass* callsite_klass = CURRENT_ENV->CallSite_klass(); |
kvn@3107 | 171 | if (callsite_klass == NULL) |
kvn@3107 | 172 | return false; |
kvn@3107 | 173 | return (holder()->is_subclass_of(callsite_klass) && (name() == ciSymbol::target_name())); |
twisti@3101 | 174 | } |
twisti@3050 | 175 | |
duke@435 | 176 | // Debugging output |
duke@435 | 177 | void print(); |
duke@435 | 178 | void print_name_on(outputStream* st); |
duke@435 | 179 | }; |
stefank@2314 | 180 | |
stefank@2314 | 181 | #endif // SHARE_VM_CI_CIFIELD_HPP |